SimpleOCF.java
// SimpleOCF
// Demo for using the OCF 1.2 with PC/SC to transmit data to and from a Smart Card.
// File: SimpleOCF.java
//
// This program uses the PassThruCardService from OCF opencard.opt.util package.
// Additional informations and reference implementation see www.opencard.org.
// Testet with Towitoko Chipdrive micro on USB port and the appropriate PC/SC drivers
// from Towitoko on Windows 98. Testet with Omnikey CardMan Dongle 6020 on USB port
// and the appropriate PC/SC drivers from Omnikey on Windows 2000.
// Made with JBuilder 6 and JDK 1.3.1.
//
// Uses OCFPCSC1.DLL, OCFPCSC1.DLL, pcsc-wrapper-2.0.jar, base-core.jar, base-opt.jar
// from OCF 1.2
// The content of the file "opencard.properties" must be changed to:
// OpenCard.terminals = com.ibm.opencard.terminal.pcsc10.Pcsc10CardTerminalFactory
//
// This demo works with an ISO/IEC 7816-4 smart card with an > 10 byte transparent EF
// with FID=0001 and no access conditions direct under the MF. This demo works also with
// a simple SIM/USIM smart card, but this will throw some error mesages from the smart card.
//
// This source code is under GNU general public license (see www.opensource.org for details).
// Please send corrections and ideas for extensions to Wolfgang Rankl (www.wrankl.de)
// Copyright 2003-2004 by Wolfgang Rankl, Munich
//
// 10. July  2004 - V11, rw: some simplifications, migrate to PC/SC wrapper 2.0,
//                           6th published version
// 10. March 2004 - V10, rw: minor clarifications, 5th published version
// 15. Dez.  2003 - V 9, rw: minor clarifications, add GPL statement
//                       4th published version
// 23. Jan.  2003 - V 8, rw: simplifications byte to int conversion, test with new
//                       card reader, review of the source code, 3rd published version
// 30. Sept. 2002 - V 7, rw: documentation clarifications, 2nd published version
// 27. Sept. 2002 - V 6, rw: extended documentation, 1st published version
// 25. Sept. 2002 - V 5, rw: simplifying source, bug fix for ATR receiving
// 18. Sept. 2002 - V 4, rw: show content of ATR
// 17. Sept. 2002 - V 3, rw: usage of different commands, simplifying the code
// 16. Sept. 2002 - V 2, rw: improvement of the documentation, minor changes
// 12. Sept. 2002 - V 1, rw: initial runnable version
//---------------------------------------------------------------------------------------

import java.util.*;
import opencard.core.service.*;
import opencard.core.terminal.*;
import opencard.opt.util.*;

public class SimpleOCF {
  private static final int IFD_TIMEOUT = 10;     // unit: seconds
  private static final int MAX_APDU_SIZE = 100;  // unit: byte

  // command ISO/IEC 7816-4 SELECT FILE (select the MF, with no response data = '0C')
  // CLA || INS || P1 || P2 || Lc || DATA 1 (= FID high) || DATA 2 (= FID low)
  final byte[] CMD_SELECT_MF = {(byte)0x00, (byte)0xA4,
                                (byte)0x00, (byte)0x0C, (byte)0x02,
                                (byte)0x3F, (byte)0x00 };

  // command ISO/IEC 7816-4 SELECT FILE (select the EF with FID = 0001
  // and no response data = '0C')
  // CLA || INS || P1 || P2 || Lc || DATA 1 (= FID high) || DATA 2 (= FID low)
  final byte[] CMD_SELECT_EF0001 ={(byte)0x00, (byte)0xA4,
                                   (byte)0x00, (byte)0x0C, (byte)0x02,
                                   (byte)0x00, (byte)0x01 };

  // command ISO/IEC 7816-4 READ BINARY (read 16 byte with no offset from
  // a selected file with transparent structure)
  // CLA || INS || P1 || P2 || Le (= length of expected data)
  final byte[] CMD_READ_BINARY ={(byte)0x00, (byte)0xB0,
                                 (byte)0x00, (byte)0x00, (byte)0x10 };

  private int n, x;
  private byte[] i;

  public SimpleOCF() {
    // create system properties object
    Properties sysProps = System.getProperties();
    // set system properties for OCF, PC/SC and PassThruCardServce
    sysProps.put ("OpenCard.terminals", "com.ibm.opencard.terminal.pcsc10.Pcsc10CardTerminalFactory");
    sysProps.put ("OpenCard.services", "opencard.opt.util.PassThruCardServiceFactory");
  } // SimpleOCF

  public void runExample() {
    try {
      System.out.println("activate Smart Card");
      SmartCard.start();  // activate smart card
      CardRequest cr = new CardRequest(CardRequest.ANYCARD, null, PassThruCardService.class);
      cr.setTimeout(IFD_TIMEOUT);  // set timeout for IFD
      // wait  for a smart card inserted into the terminal
      System.out.println("wait for smart card - insert smart card in terminal");
      SmartCard sc = SmartCard.waitForCard(cr);

      if (sc != null) {  // no error occur and a smart card is in the terminal
        PassThruCardService ptcs = (PassThruCardService) sc.getCardService(PassThruCardService.class, true);

        System.out.print("ATR:           ");
        CardID cardID = sc.getCardID ();
        i = cardID.getATR();
        String s = new String();
        for (n = 0; n < i.length; n++) {
          x = (int) (0x000000FF & i[n]);  // byte to int conversion
          s = Integer.toHexString(x).toUpperCase();
          if (s.length() == 1) s = "0" + s;
          System.out.print(s + " ");
        } // for
        System.out.println("");

        // set APDU buffer size
        CommandAPDU command = new CommandAPDU(MAX_APDU_SIZE); // create APDU buffer and set size

        //----- prepare command APDU - SELECT FILE
        command.append(CMD_SELECT_MF);
        // send command and receive response
        ResponseAPDU response = ptcs.sendCommandAPDU(command);
        // show command apdu
        System.out.print("Command-APDU:  ");
        for (n = 0; n<command.getLength(); n++) {
          s = Integer.toHexString(command.getByte(n)).toUpperCase();
          if (s.length() == 1) s = "0" + s;
          System.out.print(s + " ");
        } // for
        System.out.println("");
        // show response apdu
        System.out.print("Response-APDU: ");
        for (n = 0; n < response.getLength(); n++) {
          s = Integer.toHexString(response.getByte(n)).toUpperCase();
          if (s.length() == 1) s = "0" + s;
          System.out.print(s + " ");
        } // for
        System.out.println("");

        //----- prepare command APDU - SELECT FILE
        command.setLength(0);
        command.append(CMD_SELECT_EF0001);
        // send command and receive response
        response = ptcs.sendCommandAPDU(command);
        // show command apdu
        System.out.print("Command-APDU:  ");
        for (n = 0; n < command.getLength(); n++) {
          s = Integer.toHexString(command.getByte(n)).toUpperCase();
          if (s.length() == 1) s = "0" + s;
          System.out.print(s + " ");
        } // for
        System.out.println("");
        // show int response apdu
        System.out.print("Response-APDU: ");
        for (n=0; n<response.getLength(); n++) {
          s = Integer.toHexString(response.getByte(n)).toUpperCase();
          if (s.length() == 1) s = "0" + s;
          System.out.print(s + " ");
        } // for
        System.out.println("");

        //----- prepare command APDU - READ BINARY
        command.setLength(0);
        command.append(CMD_READ_BINARY);
        // send command and receive response
        response = ptcs.sendCommandAPDU(command);
        // show command apdu
        System.out.print("Command-APDU:  ");
        for (n = 0; n < command.getLength(); n++) {
          s = Integer.toHexString(command.getByte(n)).toUpperCase();
          if (s.length() == 1) s = "0" + s;
          System.out.print(s + " ");
        } // for
        System.out.println("");
        // show response apdu
        System.out.print("Response-APDU: ");
        for (n = 0; n < response.getLength(); n++) {
          s = Integer.toHexString(response.getByte(n)).toUpperCase();
          if (s.length() == 1) s = "0" + s;
          System.out.print(s + " ");
        } // for
        System.out.println("\ndeactivate Smart Card");
        SmartCard.shutdown();
      } // if
      else System.out.println("could not create smart card object (e.g. no ICC in IFD)");
    } // try

    catch (Exception e) {
     System.err.println("Caught exception '" + e.getClass() + "' - " + e.getMessage() );
    } // catch

    finally {
      System.exit(0);
    } // finally
  } // run example

  public static void main( String [] args ){
    System.out.println("---------------\nStart SimpleOCF\n");
    SimpleOCF OCFTest = new SimpleOCF();
    OCFTest.runExample();
  } // main
} // class


SimpleOCF.java