Contents Previous Next Index

Appendix   A

SATSA-APDU Examples


This Appendix contains complete examples of the SATSA-APDU API. APDUMIDlet makes several APDU connections to the Java Card platform simulator (cref). SATMIDlet connects to the card and sends a SAT envelope.

The APDUMIDlet Example

To run the APDUMIDlet example, first run the Java Card platform simulator. When APDUMIDlet attempts to connect to a smart card, it does so by making local socket connections. In addition, APDUMIDlet expects to connect to specification card applets that must be running on the simulator.

Preparing the Java Card Platform Simulator

APDUMIDlet connects to example card applets that are distributed with the Java Card Development Kit. The first step is to create a card EEPROM image that contains the required applets.

To do this, run the card simulator, specifying that its EEPROM image should be saved. In this example, the file name is demo2.eeprom:

start cref -o demo2.eeprom 

In DOS, start launches cref in a separate window. The next step is to load some of the Java Card Development Kit example applets onto the card. This example assumes that the Java Card Development Kit is installed in \java_card_kit-2_2_1.

apdutool /java_card_kit-2_2_1/samples/src/demo/demo2.scr 

After this step is complete, cref exits, saving its EEPROM image in the file you specified. You only need to perform this step once.

When you have the EEPROM image file, run two instances of cref as follows:

start cref -p 9025 -i demo2.eeprom 
start cref -p 9026 -i demo2.eeprom 

When you run APDUMIDlet, the SATSA RI is able to find two simulated cards that are running the demo2 card applets.

Source Code

/* 
 * Copyright © 2004 Sun Microsystems, Inc.  All rights reserved. 
 * Use is subject to license terms. 
 */ 
 
import java.io.*; 
import javax.microedition.io.Connector; 
import javax.microedition.apdu.APDUConnection; 
import javax.microedition.midlet.*; 
import javax.microedition.lcdui.*; 
 
public class APDUMIDlet 
    extends MIDlet 
    implements CommandListener, Runnable { 
  private final String kPurseSlot0 = "apdu:0;target=a0.00.00.00.62.03.01.0c.02.01"; 
  private final String kPurseSlot1 = "apdu:1;target=a0.00.00.00.62.03.01.0c.02.01"; 
  private final String kWalletSlot0 = "apdu:0;target=a0.00.00.00.62.03.01.0c.06.01"; 
   
  private APDUConnection mPurseConnection0; 
  private APDUConnection mPurseConnection1;  
  private APDUConnection mWalletConnection; 
   
  private Display mDisplay; 
  private Form mMainForm; 
  private Command mExitCommand, mGoCommand, mBackCommand; 
  private Form mProgressForm; 
 
  public APDUMIDlet() { 
    mExitCommand = new Command("Exit", Command.EXIT, 0); 
    mGoCommand = new Command("Go", Command.SCREEN, 0); 
    mBackCommand = new Command("Back", Command.BACK, 0); 
 
    mMainForm = new Form("APDU Example"); 
    mMainForm.append("Press Go to use the SATSA-APDU API " + 
        "to connect to card applications."); 
    mMainForm.addCommand(mExitCommand); 
    mMainForm.addCommand(mGoCommand); 
    mMainForm.setCommandListener(this); 
  } 
   
  public void startApp() { 
    mDisplay = Display.getDisplay(this); 
     
    mDisplay.setCurrent(mMainForm); 
  } 
   
  public void pauseApp() {} 
   
  public void destroyApp(boolean unconditional) {} 
   
  public void commandAction(Command c, Displayable s) { 
    if (c == mExitCommand) { 
      notifyDestroyed(); 
    } 
    else if (c == mGoCommand) { 
      mProgressForm = new Form("Working..."); 
      mDisplay.setCurrent(mProgressForm); 
       
      Thread t = new Thread(this); 
      t.start(); 
    } 
    else if (c == mBackCommand) { 
      mDisplay.setCurrent(mMainForm); 
    } 
  } 
   
  public void run() { 
    try { 
      setProgress("Opening purse slot 0"); 
      mPurseConnection0 = (APDUConnection)Connector.open(kPurseSlot0); 
      setProgress("Opening purse slot 1"); 
      mPurseConnection1 = (APDUConnection)Connector.open(kPurseSlot1); 
      setProgress("Opening wallet slot 0"); 
      mWalletConnection = (APDUConnection)Connector.open(kWalletSlot0); 
       
      setProgress("Exchanging APDUs with purse slot 0"); 
      for (int i = 0; i < kPurseAPDUs.length; i++) { 
        byte[] apdu = kPurseAPDUs[i]; 
        byte[] response = mPurseConnection0.exchangeAPDU(apdu); 
        // Process response. 
      } 
       
      setProgress("Closing purse slot 0"); 
      mPurseConnection0.close(); 
 
      setProgress("Exchanging APDUs with wallet"); 
      for (int i = 0; i < kWalletAPDUs.length; i++) { 
        byte[] apdu = kWalletAPDUs[i]; 
        byte[] response = mWalletConnection.exchangeAPDU(apdu); 
        // Process response. 
      } 
       
      setProgress("Closing wallet"); 
      mWalletConnection.close(); 
 
      setProgress("Exchanging APDUs with purse slot 1"); 
      for (int i = 0; i < kPurseAPDUs.length; i++) { 
        byte[] apdu = kPurseAPDUs[i]; 
        byte[] response = mPurseConnection1.exchangeAPDU(apdu); 
        // Process response. 
      } 
       
      setProgress("Closing purse slot 1"); 
      mPurseConnection1.close(); 
 
      mProgressForm.setTitle("Working...done."); 
      mProgressForm.addCommand(mBackCommand); 
      mProgressForm.setCommandListener(this); 
    } 
    catch (Exception e) { 
      try { mPurseConnection0.close(); } catch (Throwable t) {} 
      try { mPurseConnection1.close(); } catch (Throwable t) {} 
      try { mWalletConnection.close(); } catch (Throwable t) {} 
       
      Form f = new Form("Exception"); 
      f.append(e.toString()); 
      f.addCommand(mBackCommand); 
      f.setCommandListener(this); 
      mDisplay.setCurrent(f); 
    } 
  } 
   
  private void setProgress(String s) { 
    StringItem si = new StringItem(null, s); 
    si.setLayout(Item.LAYOUT_2 | Item.LAYOUT_NEWLINE_AFTER); 
    mProgressForm.append(si); 
  } 
 
  private final byte[][] kPurseAPDUs = { 
    // Verify PIN (User PIN 01020304) 
    {(byte)0x00, (byte)0x20, (byte)0x00, (byte)0x82, (byte)0x04,  
     (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x00}, 
    // should return 90 00 
     
    // Initialize Transaction: Credit $250.00  
    {(byte)0x80, (byte)0x20, (byte)0x01, (byte)0x00, (byte)0x0a,  
     (byte)0x61, (byte)0xa8, (byte)0x22, (byte)0x44, (byte)0x66,  
     (byte)0x88, (byte)0x00, (byte)0x00, (byte)0x00,  
     (byte)0x00, (byte)0x7F}, 
    // 05 05 05 05 0c 1f 62 00 00 00 07 00 00 00 00 00 00 00 00 90 00  
    // = Purse ID : 0x05050505; ExpDate 12/31/98; TN=7 
     
    // Complete Transaction: Date 10/27/97; Time 15:33 
    {(byte)0x80, (byte)0x22, (byte)0x00, (byte)0x00, (byte)0x0d,  
     (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,  
     (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0a,  
     (byte)0x1b, (byte)0x61, (byte)0x0f, (byte)0x21, (byte)0x7F}, 
    // 61 a8 00 00 00 00 00 00 00 00 90 00	= Purse Balance $250.00; 
     
    // Initialize Transaction: Debit $25.00; 
    {(byte)0x80, (byte)0x20, (byte)0x02, (byte)0x00, (byte)0x0a,  
     (byte)0x09, (byte)0xc4, (byte)0x22, (byte)0x44, (byte)0x66,  
     (byte)0x88, (byte)0x00, (byte)0x00, (byte)0x00,  
     (byte)0x00, (byte)0x7F}, 
    // 05 05 05 05 0c 1f 62 61 a8 00 08 00 00 00 00 00 00 00 00 90 00; 
    // = Purse ID : 0x05050505; ExpDate 12/31/98; TN=8 
     
    // Complete Transaction: Date 10/27/97; Time 15:35 
    {(byte)0x80, (byte)0x22, (byte)0x00, (byte)0x00, (byte)0x0d,  
     (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,  
     (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0a,  
     (byte)0x1b, (byte)0x61, (byte)0x0f, (byte)0x23, (byte)0x7F} 
    // 57 e4 00 00 00 00 00 00 00 00 90 00	= Purse Balance $225.00; 
  }; 
   
  public final byte[][] kWalletAPDUs = { 
    // verify PIN expects 90 00 
    {(byte)0x80, (byte)0x20, (byte)0x00, (byte)0x00, (byte)0x05,  
     (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05,  
     (byte)0x7F}, 
     
    // get wallet balance 
    {(byte)0x80, (byte)0x50, (byte)0x00, (byte)0x00, (byte)0x00,  
     (byte)0x02}, 
     
    // credit 128 to the wallet 
    {(byte)0x80, (byte)0x30, (byte)0x00, (byte)0x00, (byte)0x01,  
     (byte)0x80, (byte)0x7F}, 
     
    // get wallet balance 
    {(byte)0x80, (byte)0x50, (byte)0x00, (byte)0x00, (byte)0x00,  
     (byte)0x02} 
  }; 
} 

The SATMIDlet Example

SATMIDlet connects to a card applet and sends a SAT envelope.

Setting Up the Java Card Platform Simulator

The first step (as with APDUMIDlet) is to create a card EEPROM image that contains the required applet. Run the card simulator, specifying that its EEPROM image should be saved. In this example, the file name is sat.eeprom:

start cref -o sat.eeprom 

Next, load the necessary applet onto the card. This applet is distributed with the SATSA RI in the file javacard_classes\jc_script\satsimulator.scr. Assuming the SATSA RI is installed in \satsa1.0, you can install the applet with this command:

apdutool /satsa1.0/javacard_classes/jc_script/satsimulator.scr 

After this step is complete, cref exits, saving its EEPROM image in the file you specified. You only need to perform this step once.

When you have the EEPROM image file, run an instance of cref:

start cref -i sat.eeprom 

When you run SATMIDlet, the SATSA RI is able to find the simulated card that is running the satsimulator card applet.

Source Code

/* 
 * Copyright © 2004 Sun Microsystems, Inc.  All rights reserved. 
 * Use is subject to license terms. 
 */ 
 
import java.io.*; 
import javax.microedition.io.Connector; 
import javax.microedition.apdu.APDUConnection; 
import javax.microedition.midlet.*; 
import javax.microedition.lcdui.*; 
 
public class SATMIDlet 
    extends MIDlet 
    implements CommandListener, Runnable { 
  private APDUConnection mSATConnection1; 
  private APDUConnection mSATConnection2; 
   
  private Display mDisplay; 
  private Form mMainForm; 
  private Command mExitCommand, mGoCommand, mBackCommand; 
  private Form mProgressForm; 
 
  public SATMIDlet() { 
    mExitCommand = new Command("Exit", Command.EXIT, 0); 
    mGoCommand = new Command("Go", Command.SCREEN, 0); 
    mBackCommand = new Command("Back", Command.BACK, 0); 
 
    mMainForm = new Form("SAT Example"); 
    mMainForm.append("Press Go to use the SATSA-APDU API " +  
        "to connect to a SAT application."); 
    mMainForm.addCommand(mExitCommand); 
    mMainForm.addCommand(mGoCommand); 
    mMainForm.setCommandListener(this); 
  } 
   
  public void startApp() { 
    mDisplay = Display.getDisplay(this); 
     
    mDisplay.setCurrent(mMainForm); 
  } 
   
  public void pauseApp() {} 
   
  public void destroyApp(boolean unconditional) {} 
   
  public void commandAction(Command c, Displayable s) { 
    if (c == mExitCommand) { 
      notifyDestroyed(); 
    } 
    else if (c == mGoCommand) { 
      mProgressForm = new Form("Working..."); 
      mDisplay.setCurrent(mProgressForm); 
       
      Thread t = new Thread(this); 
      t.start(); 
    } 
    else if (c == mBackCommand) { 
      mDisplay.setCurrent(mMainForm); 
    } 
  } 
   
  public void run() { 
    try { 
      String url = "apdu:0;target=SAT"; 
       
      setProgress("Opening first SAT connection"); 
      mSATConnection1 = (APDUConnection)Connector.open(url); 
      // The second connection demonstrates that two SAT 
      // connections can be open simultaneously. 
      setProgress("Opening second SAT connection"); 
      mSATConnection2 = (APDUConnection)Connector.open(url); 
       
      setProgress("Sending envelopes"); 
      byte[] response1 = mSATConnection1.exchangeAPDU(kEnvelope); 
      byte[] response2 = mSATConnection2.exchangeAPDU(kEnvelope); 
   
      setProgress("Closing first SAT connection"); 
      mSATConnection1.close(); 
       
      setProgress("Closing second SAT connection"); 
      mSATConnection2.close(); 
 
      mProgressForm.setTitle("Working...done."); 
      mProgressForm.addCommand(mBackCommand); 
      mProgressForm.setCommandListener(this); 
    } 
    catch (Exception e) { 
      try { mSATConnection1.close(); } catch (Throwable t) {} 
      try { mSATConnection2.close(); } catch (Throwable t) {} 
       
      Form f = new Form("Exception"); 
      f.append(e.toString()); 
      f.addCommand(mBackCommand); 
      f.setCommandListener(this); 
      mDisplay.setCurrent(f); 
    } 
  } 
 
  private void setProgress(String s) { 
    StringItem si = new StringItem(null, s); 
    si.setLayout(Item.LAYOUT_2 | Item.LAYOUT_NEWLINE_AFTER); 
    mProgressForm.append(si); 
  } 
 
  // Update the binary file EFpuct (Price per unit and currency table) 
  private final byte[] kEnvelope = { 
    (byte)0xA0, (byte)0xC2, (byte)0x00, (byte)0x00, (byte)0x2f, 
    (byte)0xD1, (byte)0x2d, (byte)0x82, (byte)0x02, (byte)0x83, 
    (byte)0x81, (byte)0x06, (byte)0x05, (byte)0x80, (byte)0x11, 
    (byte)0x22, (byte)0x33, (byte)0x44, (byte)0x8B, (byte)0x20, 
    (byte)0x10, (byte)0x02, (byte)0x81, (byte)0x55, (byte)0x7F, 
    (byte)0xF6, (byte)0x00, (byte)0x11, (byte)0x29, (byte)0x12, 
    (byte)0x00, (byte)0x00, (byte)0x04, (byte)0x14, (byte)0x10, 
    (byte)0x11, (byte)0x12, (byte)0x13, (byte)0x14, (byte)0x15, 
    (byte)0x16, (byte)0x17, (byte)0x18, (byte)0x19, (byte)0x1a, 
    (byte)0x1b, (byte)0x1c, (byte)0x1d, (byte)0x41, (byte)0xAB, 
    (byte)0xCD, (byte)0xEF 
  }; 
} 

 


Contents Previous Next Index SATSA Developer's Guide
SATSA Reference Implementation 1.0