import sim.toolkit.*;
import sim.access.*;
import javacard.framework.*;
public class MyToolkitApplet extends javacard.framework.Applet implements ToolkitInterface, ToolkitConstants
{
// BIP Constants
private static final byte TAG_DATA_DESTINATION_ADDRESS = (byte) 0x3E;
private static byte[] myAPN = {(byte)0x0A,(byte)'m',(byte)'y',(byte)'o',(byte)'p',(byte)'e',(byte)'r',(byte)'a',(byte)'t',(byte)'o',
(byte)'r',(byte)0x09,(byte)'m',(byte)'y',(byte)'c',(byte)'o',(byte)'u',(byte)'n',(byte)'t',
(byte)'r',(byte)'y'};
//GPRS = 0x02
private static final byte BEARER_TYPE_GPRS = (byte) 0x02;
// The service precedence class indicates the relative priority of maintaining the service
//Precedence Class n? => High priority.
private static final byte BEARER_PARAMETER_PRECEDENCE_CLASS1 = (byte) 0x01;
private static final byte BEARER_PARAMETER_DELAY_CLASS1 = (byte) 0x01;
private static final byte BEARER_PARAMETER_RELIABILITY_CLASS1 = (byte) 0x01;
private static final byte BEARER_PARAMETER_PEAK_THROUGHPUT_CLASS1= (byte) 0x01;
private static final byte BEARER_PARAMETER_MEAN_THROUGHPUT_CLASS1 = (byte) 0x01;
// PDP Type --> IP
private static final byte BEARER_PARAMETER_PDP_IP = (byte) 0x02;
// Define parameters necessary to launch a PDP context
private static byte[] BearerParameters= {(byte) BEARER_TYPE_GPRS, (byte) BEARER_PARAMETER_PRECEDENCE_CLASS1,
(byte) BEARER_PARAMETER_DELAY_CLASS1, (byte) BEARER_PARAMETER_RELIABILITY_CLASS1,
(byte) BEARER_PARAMETER_PEAK_THROUGHPUT_CLASS1, (byte) BEARER_PARAMETER_MEAN_THROUGHPUT_CLASS1,
(byte) BEARER_PARAMETER_PDP_IP };
// Type of Address IPV4=21,
private static final byte TYPE_OF_ADDRESS_IPV4 = (byte) 0x21;
// SIM/ME interface transport level UDP=01
private static final byte TRANSPORT_PROTOCOL_TYPE = (byte) 0x01;
// --> ... end GPRS case
public static final byte MY_INSTRUCTION = (byte)0x46;
public static final byte SERVER_OPERATION = (byte)0x0F;
public static final byte CMD_QUALIFIER = (byte)0x80;
public static final byte EXIT_REQUESTED_BY_USER = (byte)0x10;
private byte[] menuEntry = {(byte)'0',(byte)'3',(byte)'.',(byte)'1',(byte)'9',(byte)' ',(byte)'A',(byte)'p',(byte)'p',(byte)'l',(byte)'e',(byte)'t'};
private byte[] menuTitle= {(byte)'M',(byte)'y',(byte)'M',(byte)'e',(byte)'n' ,(byte)'u'};
private byte[] item1 = {(byte)'I',(byte)'T',(byte)'E',(byte)'M',(byte)'1' };
private byte[] item2 = {(byte)'I',(byte)'T',(byte)'E',(byte)'M',(byte)'2' };
private byte[] item3 = {(byte)'I',(byte)'T',(byte)'E',(byte)'M',(byte)'3' };
private byte[] item4 = {(byte)'I',(byte)'T',(byte)'E',(byte)'M',(byte)'4' };
private Object[] ItemList = { item1, item2, item3, item4 };
private byte[] textDText = {(byte)'H',(byte)'e',(byte)'l',(byte)'l',(byte)'o',(byte)' ',
(byte)'w',(byte)'o',(byte)'r',(byte)'l',(byte)'d',(byte)'2'};
private byte[] textGInput = {(byte)'Y',(byte)'o',(byte)'u',(byte)'r',(byte)' ',(byte)'n',
(byte)'a',(byte)'m',(byte)'e',(byte)'?'};
private byte[] baGSMAID = {(byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, (byte)0x00, (byte)0x01};
private ToolkitRegistry reg;
private SIMView gsmFile;
private byte buffer[] = new byte[10];
private byte itemId;
private byte result;
private static final short BUFFER_SIZE = (short)0x01F4;
private static final short MAX_TLV_OVERHEAD = (short)0x0012;
private static short myRspHdlrCapacity;
private static byte[] portNumber = {(byte)0x00,(byte)0x23};
private static byte channelID = 0x00;
private static byte[] channelData = new byte [BUFFER_SIZE];
private static byte[] IPAddress = {(byte)163,(byte)187,(byte)203,(byte)1};
public MyToolkitApplet() {
gsmFile = SIMSystem.getTheSIMView();
reg = ToolkitRegistry.getEntry();
itemId = reg.initMenuEntry(menuEntry, (short)0x0000, (short)menuEntry.length,
PRO_CMD_DISPLAY_TEXT, false, (byte) 0x00, (short) 0x0000);
reg.setEvent(EVENT_UNFORMATTED_SMS_PP_ENV);
reg.setEvent(EVENT_EVENT_DOWNLOAD_DATA_AVAILABLE);
}
public static void install(byte bArray[], short bOffset, byte bLength) {
MyToolkitApplet MyApplet = new MyToolkitApplet();
MyApplet.register();
}
public Shareable getShareableInterfaceObject(AID clientAID, byte parameter){
if (parameter == (byte) 0x00){
if ( clientAID.partialEquals(baGSMAID, (byte) 0x00, (byte) baGSMAID.length) == true )
return((Shareable) this);
}
return(null);
}
public void processToolkit(byte event) {
EnvelopeHandler envHdlr = EnvelopeHandler.getTheHandler();
ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
ProactiveResponseHandler rspHdlr ;
boolean repeat;
switch(event) {
case EVENT_MENU_SELECTION:
proHdlr.init(PRO_CMD_SELECT_ITEM,(byte)0x00,DEV_ID_ME);
proHdlr.appendTLV((byte) (TAG_ALPHA_IDENTIFIER | TAG_SET_CR),
menuTitle,(short)0x0000,(short)menuTitle.length);
for (short i=(short) 0x0000; i<(short) 0x0004; i++) {
proHdlr.appendTLV((byte) (TAG_ITEM | TAG_SET_CR),(byte) (i+1),
(byte[])ItemList[i],(short) 0x0000,
(short)((byte[])ItemList[i]).length);
}
if((result = proHdlr.send()) == RES_CMD_PERF){
rspHdlr = ProactiveResponseHandler.getTheHandler();
switch (rspHdlr.getItemIdentifier()) {
case 1:
case 2:
proHdlr.init(PRO_CMD_OPEN_CHANNEL,(byte)0x00, DEV_ID_ME);
proHdlr.appendTLV((byte)(TAG_BEARER_DESCRIPTION | TAG_SET_CR),(byte)BEARER_TYPE_GPRS,
BearerParameters, (short)0x0000, (short)BearerParameters.length);
proHdlr.appendTLV((byte)(TAG_BUFFER_SIZE | TAG_SET_CR),(byte)(BUFFER_SIZE>>(byte)8),(byte)BUFFER_SIZE);
proHdlr.appendTLV((byte)(TAG_NETWORK_ACCESS_NAME | TAG_SET_CR),myAPN,(short)0,(short)myAPN.length);
proHdlr.appendTLV((byte) (TAG_SIM_ME_INTERFACE_TRANSPORT_LEVEL | TAG_SET_CR),TRANSPORT_PROTOCOL_TYPE,
portNumber, (short)0, (short)portNumber.length);
proHdlr.appendTLV((byte) (TAG_DATA_DESTINATION_ADDRESS | TAG_SET_CR),TYPE_OF_ADDRESS_IPV4,
IPAddress,(short)0, (short) IPAddress.length);
result = proHdlr.send();
if (result == RES_CMD_PERF){
rspHdlr = ProactiveResponseHandler.getTheHandler();
channelID = rspHdlr.getChannelIdentifier();
myRspHdlrCapacity = rspHdlr.getCapacity();
}
else {
channelID = 0x00;
}
break;
case 3:
proHdlr.init(PRO_CMD_DISPLAY_TEXT, CMD_QUALIFIER,DEV_ID_DISPLAY);
proHdlr.appendTLV((byte)(TAG_TEXT_STRING| TAG_SET_CR), DCS_8_BIT_DATA,
textDText,(short)0x0000, (short)textDText.length);
proHdlr.send();
break;
case 4: // Ask the user to enter data and display it
do {
repeat = false;
try {
proHdlr.initGetInput((byte)0x01, DCS_8_BIT_DATA, textGInput,(byte)0x00,
(short)textGInput.length,(short)0x0001,(short)0x0002);
proHdlr.send();
rspHdlr.copyTextString(textDText,(short)0x0000);
proHdlr.initDisplayText((byte)0x00,DCS_8_BIT_DATA, textDText,
(short)0x0000,(short) textDText.length);
proHdlr.send();
}
catch (ToolkitException MyException) {
if (MyException.getReason() == ToolkitException.UNAVAILABLE_ELEMENT ){
if (rspHdlr.getGeneralResult() != EXIT_REQUESTED_BY_USER)
repeat = true;
break;
}
}
}
while(repeat);
break;
}
}
break;
case EVENT_UNFORMATTED_SMS_PP_ENV:
short TPUDOffset = (short) (envHdlr.getTPUDLOffset() + SERVER_OPERATION);
switch (envHdlr.getValueByte((short)TPUDOffset) ) {
case 0x41 : // Update of a gsm file
envHdlr.copyValue((short)(TPUDOffset+1),buffer,(short)0x0000,(short)0x0003);
gsmFile.select(SIMView.FID_DF_GSM);
gsmFile.select(SIMView.FID_EF_PUCT);
gsmFile.updateBinary((short)0x0000,buffer,(short)0x0000,(short)0x0003);
break;
case 0x36 : // change the MenuTitle for the SelectItem
envHdlr.copyValue((short)(TPUDOffset+1), menuTitle,(short)0x0000,(short)0x0006);
break;
}
break;
case EVENT_EVENT_DOWNLOAD_DATA_AVAILABLE:
if ( channelID == envHdlr.getChannelIdentifier()) {
byte channelDataRemainingLgth;
short channelDataOffset = 0;
envHdlr.findTLV(TAG_CHANNEL_DATA_LENGTH ,(byte)0x01);
channelDataRemainingLgth = envHdlr.getValueByte((short)0x0000);
do {
if ( (short)(myRspHdlrCapacity - MAX_TLV_OVERHEAD) < (short)(( (short)(channelDataRemainingLgth) & (short)0x00FF))) {
channelDataRemainingLgth = (byte)((short)(myRspHdlrCapacity - MAX_TLV_OVERHEAD));
}
proHdlr.init(PRO_CMD_RECEIVE_DATA,(byte)0,channelID);
proHdlr.appendTLV((byte)(TAG_CHANNEL_DATA_LENGTH | TAG_SET_CR),channelDataRemainingLgth);
result = proHdlr.send();
if ( result == RES_CMD_PERF ) {
rspHdlr = ProactiveResponseHandler.getTheHandler();
rspHdlr.findTLV(TAG_CHANNEL_DATA,(byte)0x01);
channelDataOffset = rspHdlr.copyChannelData(channelData,channelDataOffset, rspHdlr.getValueLength() );
rspHdlr.findTLV(TAG_CHANNEL_DATA_LENGTH ,(byte)0x01);
channelDataRemainingLgth = rspHdlr.getValueByte((short)0x0000);
}
} while( channelDataRemainingLgth != (byte)0);
proHdlr.initCloseChannel(channelID);
proHdlr.send();
// Process the data received in channelData
//.....
//....
}
break;
}
}
public void process(APDU apdu) {
if(selectingApplet())
return;
switch(apdu.getBuffer()[1]) {
case (byte)MY_INSTRUCTION:
if(apdu.setIncomingAndReceive() > (short)0) {
Util.arrayCopy(apdu.getBuffer(),(short)0x0005,menuTitle,(short)0x0000,(short)0x0006);
}
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
}