ICC.java
//---------------------------------------------------------------------------------------
// Useful tools for high level commands to the smart card
// file:    ICC.java
// used by: EEPROMTest.java
// For comments see header of EEPROMTest.java.
//---------------------------------------------------------------------------------------

package eeppack;

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

public class ICC {
  static final int IFD_TIMEOUT = 0;      // unit: seconds
  static final int MAX_ATR_LEN = 32;     // maximum length of the ATR
  static final int MAX_APDU_SIZE = 250;  // unit: byte
  static final int CAPDU_P1 = 2;         // index of P1 within a command APDU
  static final int CAPDU_P2 = 3;         // index of P2 within a command APDU
  static final int CAPDU_D1 = 4 + 1;     // index of data byte 1 Le within a command APDU
  static final int RAPDU_SW1 = 0;        // index of SW1 within a response APDU without data

  // return value of some internal methods
  static final byte NO_ERROR = 1;
  static final byte ERROR_AFTER_WRITE = 2;
  static final byte ERROR_AFTER_COMPARE = 3;

  private PassThruCardService ptcs;

  // proprietary command WRITE NVM
  // CLA || INS || P1 (= start page) || P2 (= end page) || Lc || DATA 1 (= pattern)
  static final byte[] CMD_WRITENVM = {(byte)0x00, (byte)0x01,
                                      (byte)0x20, (byte)0x20, (byte)0x01,
                                      (byte)0x00};

  // proprietary command COMPARE NVM
  // CLA || INS || P1 (= start page) || P2 (= end page) || Lc || DATA 1 (= pattern)
  static final byte[] CMD_COMPNVM = {(byte)0x00, (byte)0x02,
                                     (byte)0x20, (byte)0x20, (byte)0x01,
                                     (byte)0x00};

  // Returncode '9000': command propper executed
  static final byte RC_SW1_CMD_PROPPER_EXECUTED = (byte) 0x90;

  /** set properties for OCF, PC/SC and PassThruCardServce and activates the smart card
   *  @return ATR as byte string in hexadecimal coding
   */
  public byte[] start() {
    byte[] atr = new byte[MAX_ATR_LEN];

    // get and set system properties for OCF, PC/SC and PassThruCardServce
    Properties sysProps = System.getProperties();
    sysProps.put ("OpenCard.terminals", "com.ibm.opencard.terminal.pcsc10.Pcsc10CardTerminalFactory");
    sysProps.put ("OpenCard.services", "opencard.opt.util.PassThruCardServiceFactory");
    try {
      SmartCard.start();
      CardRequest cr = new CardRequest(CardRequest.ANYCARD, null, PassThruCardService.class);
      cr.setTimeout(IFD_TIMEOUT);                 // set timeout for IFD
      SmartCard sc = SmartCard.waitForCard(cr);   // wait for ICC in the IFD
      if (sc != null) {  // no error occured, a smart card is in the terminal
        ptcs = (PassThruCardService) sc.getCardService(PassThruCardService.class, true);
        CardID cardID = sc.getCardID();
        atr = cardID.getATR();
      } // if
    } // try
    catch (Exception e) {
      System.err.println("caught exception '" + e.getClass() + "' - " + e.getMessage() );
    } // catch
    return atr;
  } // start

  /** deactivate the smart card
   */
  public static void stop() {
    try {
      SmartCard.shutdown();
    } // try
    catch (Exception e) {
      System.err.println("caught exception '" + e.getClass() + "' - " + e.getMessage() );
      System.exit(0);
    } // catch
  } // stop


  /** write a byte pattern in a whole EEPROM page from a first page to a last page
   *  @param  pattern to write into EEPROM
   *  @param  firstpage to write the pattern
   *  @param  lastpage to write the pattern
   *  @return result of the write operation
   */
  public byte write(byte pattern, byte firstpage, byte lastpage) {
    CommandAPDU command = new CommandAPDU(MAX_APDU_SIZE);  // create APDU buffer and set size
    command.setLength(0);
    command.append(CMD_WRITENVM);
    command.setByte(CAPDU_P1, firstpage);   // set first page to write the pattern
    command.setByte(CAPDU_P2, lastpage);    // set last page to write the pattern
    command.setByte(CAPDU_D1, pattern);     // set pattern
    try {
      if (EEPROMTest.DEBUG == true) {
        EEPROMTest.showText ("\tDebug: " + EEPROMTest.formatCmdAPDU(command.getBytes(), command.getLength()) + "\n"); // command APDU
      } //if
      ResponseAPDU response = ptcs.sendCommandAPDU(command);
      if (EEPROMTest.DEBUG == true) {
        EEPROMTest.showText ("\tDebug: " + EEPROMTest.formatRspAPDU(response.getBytes(),response.getLength()) + "\n");  // response APDU
      } // if
      if ((byte) response.getByte(RAPDU_SW1) != (byte) RC_SW1_CMD_PROPPER_EXECUTED) {
        // a EEPROM write error occur
        return ERROR_AFTER_WRITE;
      } // if

      // no EEPROM write error occured
      command.setLength(0);
      command.append(CMD_COMPNVM);
      command.setByte(CAPDU_P1, firstpage);   // set first page to write the pattern
      command.setByte(CAPDU_P2, lastpage);    // set last page to write the pattern
      command.setByte(CAPDU_D1, pattern);     // set pattern
      if (EEPROMTest.DEBUG == true) {
        EEPROMTest.showText("\tDebug: " + EEPROMTest.formatCmdAPDU(command.getBytes(), command.getLength()) + "\n"); // command APDU
      } // if
      response = ptcs.sendCommandAPDU(command);
      if (EEPROMTest.DEBUG == true) {
        EEPROMTest.showText("\tDebug: " + EEPROMTest.formatRspAPDU(response.getBytes(),response.getLength()) + "\n");  // response APDU
      } // if
      if ((byte) response.getByte(RAPDU_SW1) != (byte) RC_SW1_CMD_PROPPER_EXECUTED) {
        // a EEPROM write error occur
        return ERROR_AFTER_COMPARE;
      } // if
    } // try
    catch (Exception e) {
      System.err.println("caught exception '" + e.getClass() + "' - " + e.getMessage() );
      System.exit(0);
    } // catch

    return NO_ERROR;
  } // write
} // class
//---------------------------------------------------------------------------------------




ICC.java