Methods Summary |
---|
public static void | checkSlotNumber(int slot)Verifies that slot number is correct. Invokes init method
if necessary.
try {
init();
} catch (IOException e) {
throw new ConnectionNotFoundException(
"Invalid configuration: " + e);
}
if (slot < 0 || slot >= getSlotCount()) {
throw new ConnectionNotFoundException(
"Invalid slot identifier: " + slot);
}
|
private static void | clean(Slot slot)Cleans the slot object before a reset.
slot.basicChannelInUse = false;
slot.SIMPresent = false;
slot.FCI = null;
|
private static void | closeChannel(Slot slot, int channel)This method is used to close connection with the card. If the
channel number passed to this method is for basic channel then
the basic channel is marked as available and nothing is
communicated with the card.
If the channel is not the basic channel, a request to close the
channel is sent to the card.
if (channel == 0) {
slot.basicChannelInUse = false;
return;
}
try {
slot.closeChannelAPDU[3] = (byte) channel;
exchangeAPDU(slot, slot.closeChannelAPDU);
} catch (IOException ioException) {
throw new IOException("Error closing connection: " + ioException);
}
|
public static void | closeConnection(Handle h)Closes the connection.
Slot cardSlot = h.cardSlot;
synchronized (cardSlot) {
h.opened = false;
if (h.cardSessionId != cardSlot.cardSessionId) {
throw new IOException();
}
closeChannel(cardSlot, h.channel);
}
|
public static byte[] | exchangeAPDU(Handle h, byte[] apduData)This public method takes in the command APDU in the form of
a byte array and calls the native exchangeAPDU0 method
to send the APDU to the card. If there are no errors, this method
gets the response APDU data from the card and returns that.
byte[] retData;
Slot slot = h.cardSlot;
try {
synchronized (slot) {
byte[] respBuffer = slot.respBuffer;
int respLen = exchangeAPDU0(h, null, apduData, respBuffer);
retData = new byte[respLen];
System.arraycopy(respBuffer, 0, retData, 0, respLen);
}
return retData;
} catch (IOException e) {
if (!slot.powered) {
// power up the slot after removal/insertion
isAlive(slot);
}
throw e;
}
|
private static byte[] | exchangeAPDU(Slot slot, byte[] apduData)This internal method takes in the command APDU in the form of
a byte array and calls the native exchangeAPDU0 method
to send the APDU to the card. If there are no errors, this method
gets the response APDU data from the card and returns that.
byte[] retData;
synchronized (slot) {
byte[] respBuffer = slot.respBuffer;
int respLen = exchangeAPDU0(null, slot, apduData, respBuffer);
retData = new byte[respLen];
System.arraycopy(respBuffer, 0, retData, 0, respLen);
}
return retData;
|
private static native int | exchangeAPDU0(Handle h, Slot slot, byte[] request, byte[] response)Performs data transfer to the device. This method must be called within
synchronize block with the Slot object.
|
public static byte[] | getATR(int slot)This method returns the ATR received from the card.
byte[] result = null;
Slot cardSlot = slots[slot];
if (isAlive(cardSlot) && cardSlot.atr != null) {
int len = cardSlot.atr.length;
result = new byte[len];
System.arraycopy(cardSlot.atr, 0, result, 0, len);
}
return result;
|
public static int | getSlotCount()Returns the number of slots.
try {
init();
}
catch (IOException e) {
return 0;
}
return slots.length;
|
private static synchronized void | init()This method reads the configuration file for number of slots
and their parameters and performs necessary initialization.
if (slots != null) {
return;
}
int slotCount = init0();
slots = new Slot[slotCount];
for (int i = 0; i < slotCount; i++) {
slots[i] = new Slot(i);
}
|
private static native int | init0()Initializes the device.
|
public static void | initACL(int slot, com.sun.midp.security.SecurityToken securityToken)Initializes ACL for the slot (if needed). This method is invoked
when an establishment of new connection is being performed.
try {
checkSlotNumber(slot);
Slot cardSlot = slots[slot];
if (!cardSlot.powered) {
reset(cardSlot); // here a reading of ACL is being performed
}
} catch (IOException e) {} // ignored
|
private static boolean | isAlive(Slot slot)Checks if the the connection is still live or not. It sends special
isAliveAPDU to the card and checks if an error occured.
int tries = 2;
do {
if (!slot.powered) {
try {
clean(slot);
reset(slot);
} catch (IOException e) {} // ignored
}
try {
exchangeAPDU(slot, slot.isAliveAPDU);
return true;
} catch (IOException e) {} // ignored
} while (--tries > 0);
return false;
|
private static native boolean | isSAT(int slot)Checks if this slot is SAT slot. This method is invoked once after
a reset of the card.
|
public static boolean | isSatSlot(int slot)Checks if this slot is SAT slot.
checkSlotNumber(slot);
return isSAT(slot);
|
public static Handle | openACLConnection(byte[] apdu, int slot, com.sun.midp.security.SecurityToken securityToken)Opens a connection to a smart card for reading of ACL.
This method is called from reset
method, so it does not need synchronized
statement.
checkSlotNumber(slot);
return selectApplication(true, apdu, slot, securityToken);
|
static Handle | openSATConnection(int slot, com.sun.midp.security.SecurityToken securityToken)Creates SAT connection.
Handle h = null;
checkSlotNumber(slot);
Slot cardSlot = slots[slot];
String satAPDU = Configuration.getProperty(SAT_APDU_PROP);
if (satAPDU != null) {
byte[] apdu = new byte[24];
boolean ok;
try {
int len = parseDottedBytes(satAPDU, apdu, 0);
ok = len >= 10 && len <= 22; // 5 bytes hdr + AID + Le
int Lc = (apdu[4] & 0xFF);
if (ok && (len < Lc + 5 ||
len > Lc + 5 + 1 ||
apdu[0] != (byte)0x00 ||
apdu[1] != (byte)0xA4 ||
apdu[2] != (byte)0x04)) {
ok = false;
}
if (ok && len == Lc + 5) {
apdu[len] = 0x7F;
}
} catch (NullPointerException npe) {
ok = false;
} catch (IndexOutOfBoundsException iobe) {
ok = false;
} catch (IllegalArgumentException iae) {
ok = false;
}
if (ok) {
h = selectApplication(true, apdu, slot, securityToken);
}
}
if (h == null) {
if (!isAlive(cardSlot)) {
throw new ConnectionNotFoundException("SIM not found");
}
h = new Handle(slot, 0, securityToken);
}
return h;
|
public static int | parseDottedBytes(java.lang.String src, byte[] dest, int offset)Parses string that contains hexadecimal byte values separated by
dots. May throw runtime exceptions.
int i = 0;
int len = 0;
int j;
while (i != src.length() + 1) {
if ((j = src.indexOf('.", i)) == -1) {
j = src.length();
}
int l = Integer.parseInt(src.substring(i, j), 16);
if (l != (l & 0xff)) {
throw new IllegalArgumentException();
}
dest[offset + len++] = (byte) l;
i = j + 1;
}
return len;
|
private static void | reset(Slot cardSlot)Performs reset of device.
Saves ATR into provided slot object. After the reset invokes
an ACL loading for this slot.
synchronized (cardSlot) {
byte[] atr = reset0(cardSlot);
cardSlot.atr = atr;
// after reset we must reload access control file
com.sun.satsa.acl.AccessControlManager.init(cardSlot.slot);
}
|
private static native byte[] | reset0(Slot slot)Performs reset of the card in the slot. This method must be called within
synchronize block with the Slot object.
|
public static Handle | selectApplication(byte[] selectAPDU, int slot, com.sun.midp.security.SecurityToken securityToken)The public method which should be called when application
selection is required. Calls an internal method.
checkSlotNumber(slot);
return selectApplication(false, selectAPDU, slot, securityToken);
|
private static Handle | selectApplication(boolean forSAT, byte[] selectAPDU, int slot, com.sun.midp.security.SecurityToken securityToken)This method is called when there is a connection creation is in
progress
and specifically card application selection is required. If the card
application selection is successful
this method gets the channel information from the CAD which it returns
to the APDUConnection object.
int channel;
Slot cardSlot = slots[slot]; // we have checked slot number earlier
// Test if 'POWER UP' is needed or a card was changed
if (!isAlive(cardSlot)) {
throw new ConnectionNotFoundException("SmartCard not found");
}
if (!forSAT && (cardSlot.basicChannelInUse || cardSlot.SIMPresent)) {
// get another channel for communication.
byte[] response = exchangeAPDU(cardSlot, cardSlot.getChannelAPDU);
if (response.length == 2) {
// just got back the status word
throw new IOException("No logical channel available");
}
// new channel number is in the first byte of response
channel = response[0];
} else {
cardSlot.basicChannelInUse = true;
channel = 0;
}
selectAPDU[0] = (byte)((selectAPDU[0] & 0xFC) | channel);
byte[] result = exchangeAPDU(cardSlot, selectAPDU);
int sw1 = result[result.length - 2] & 0xFF;
int sw2 = result[result.length - 1] & 0xFF;
if ((sw1 << 8) + sw2 != 0x9000) {
closeChannel(cardSlot, channel);
throw new ConnectionNotFoundException(
"Card application selection failed");
}
cardSlot.FCI = result;
return new Handle(slot, channel, securityToken);
|