FileDocCategorySizeDatePackage
CardSlot.javaAPI DocphoneME MR2 API (J2ME)10642Wed May 02 18:00:38 BST 2007com.sun.cardreader

CardSlot

public class CardSlot extends Object
This class represents card slot abstraction.

Fields Summary
private CardDevice
device
Device object.
private int
slotNumber
Local slot number (inside the device).
SecurityToken
securityToken
Security token for this slot.
private boolean
opened
Indicates that the slot has been opened.
private int
cardSessionId
Unique card session identifier.
private static int
sessionId
This field is used to assign unique card session identifiers.
private byte[]
ATR
ATR bytes kept since last reset.
private boolean
cardChanged
A flag which shows if the card was changed.
private byte[]
isAliveAPDU
isAlive command APDU.
private byte[]
isAliveResponse
isAlive command response buffer.
Constructors Summary
public CardSlot(CardDevice device, int slot, SecurityToken token)
Creates card slot on the specified device.

param
device Card device for which the slot is created
param
slot Local device slot number
param
token Security token for this slot
throws
IOException If slot creation failed.


                                             
          
	  
        this.device = device;
        this.slotNumber = slot;
        this.securityToken = token;
        opened = false;
        cardChanged = true;
        isAliveAPDU = new byte[] {0, 0x70, (byte) 0x80, 0};
        isAliveResponse = new byte[2];
    
Methods Summary
public voidcloseSlot()
Closes the slot in case of error. device.closeSlot usually does nothing. Used for socket-like 'devices'.

throws
IOException If something fails.

        if (opened) {
            device.closeSlot(slotNumber);
        }
        opened = false;
    
private booleandoIsAlive()
Checks if the the connection is still live or not by trying to send an APDU to close channel 0. If we get an IOException back that means a card or cref is gone.

return
true if the connection is alive

        try {
            lockSlot();
            xferData(true, isAliveAPDU, isAliveResponse);
            unlockSlot();
            return true;
        } catch (IOException e) {
            return false;
        }
    
public byte[]getATR()
Gets ATR bytes from the device.

return
ATR bytes.

        byte[] result;

        if (opened && ATR.length > 0) {
            result = new byte[ATR.length];
            System.arraycopy(ATR, 0, result, 0, ATR.length);
        } else {
            result = null;
        }
        return result;
    
public intgetCardSessionId()
Returns the card session identifier. This number is different for different card sessions.

return
the card session identifier or -1 when slot is closed

        return (opened && !cardChanged) ? cardSessionId : -1;
    
protected CardDevicegetDevice()
Gets device of this slot. For using in derived classes.

return
Slot device

        return this.device;
    
public intgetSlotNumber()
Gets local device slot number.

return
Local slot number.

        return slotNumber;
    
public voidinitACL()
Initializes ACL for the slot.

        boolean changed;
        try {
            lockSlot();
            changed = isCardChanged();
            unlockSlot();
            if (changed) {
                com.sun.satsa.acl.AccessControlManager.init(slotNumber);
            }
        } catch (IOException e) {} // ignored
    
public booleaninitConnection()
Makes sure that slot is ready for connection.

return
true if this is first connection to inserted card
throws
IOException If something fails.

        boolean prevCardChanged;
        lockSlot();
        prevCardChanged = isCardChanged();
        unlockSlot();
        cardChanged = false;
        return prevCardChanged;
    
public booleanisAlive()
Checks if the the connection is still live or not. It is a public wrapper for doIsAlive. Also checks if a card was changed. Slot must not be locked.

return
true if the connection is alive

        boolean alive = doIsAlive();
        if (!alive) {
            try {
                if (!alive) {
                    lockSlot();
                    boolean changed = isCardChanged();
                    unlockSlot();
                    if (changed) {
                        alive = doIsAlive();
                    }
                }
            } catch (IOException e) {
                alive = false;
            }
        }
        return alive;
    
private booleanisCardChanged()
Checks if the card was withdrawn or inserted. The device must be locked.

return
true if a card was changed, false otherwise
throws
IOException If something wrong.

        try {
            if (device.isCardChanged()) {
                closeSlot();
            }
            open();
        } catch (IOException e) {
            unlockSlot();
            throw e;
        }
        if (cardChanged) {
            return true;
        }
        return false;
    
public booleanisSAT()
Checks if this slot is SAT slot.

return
SAT check result
throws
IOException If an error occured.

        return device.isSatSlot(slotNumber);
    
public voidlockSlot()
Starts operations with the slot. All the transfer operations (xferData) should be performed when the device is locked. If any problem occurs an unlock must be done.

throws
IOException If something fails.

        try {
            device.lock();
            open();
            device.selectSlot(slotNumber);
        }
        catch (IOException e) {
            unlockSlot();
            throw e;
        }
    
private voidopen()
Tries to open slot if it closed. Performes the 'RESET' command. The device must be locked.

throws
IOException If open fails.

        boolean openedSuccessfuly = false;
        if (!opened) {
            try {
                device.openSlot(slotNumber, securityToken);
                openedSuccessfuly = true;
                device.selectSlot(slotNumber);
                device.reset();
                cardSessionId = sessionId++;
            } catch (IOException ie) {
                if (openedSuccessfuly) {
                    try {
                        device.closeSlot(slotNumber);
                    } catch (IOException ign) {} // ignored
                }
                throw new IOException("Cannot open slot #" +
                            slotNumber + ": " + ie);
            }
            ATR = device.getATR();
            cardChanged = true;
            opened = true;
        }
    
public voidunlockSlot()
Ends operations with the slot. IOException is ignored.

        try {
            device.unlock();
        }
        catch (IOException e) {}
    
public intxferData(byte[] request, byte[] response)
Performs data transfer to the device slot. It must be called where slot is locked.

param
request Request APDU bytes
param
response Response bytes
return
Length of response
throws
IOException If a data transfer failed or the card was changed.

        return xferData(false, request, response);
    
private intxferData(boolean aliveChecking, byte[] request, byte[] response)
Performs data transfer to the device slot. It must be called where slot is locked.

param
aliveChecking true if isAlive command is performed, false otherwise
param
request Request APDU bytes
param
response Response bytes
return
Length of response
throws
IOException If a data transfer failed or the card was changed.

        int bytes_read;

        if (isCardChanged() && !aliveChecking) {
            unlockSlot();
            throw new InterruptedIOException("Card changed");
        }

        try {
            bytes_read = device.xfer(request, response);
        }
        catch (IOException e) {
            if (isCardChanged() && !aliveChecking) {
                unlockSlot();
                throw new InterruptedIOException("Card changed: " + e);
            }
            unlockSlot();
            throw e;
        }
        catch (RuntimeException e) { // We must unlock slot
            unlockSlot();
            throw e;
        }
        if (isCardChanged() && !aliveChecking) {
            unlockSlot();
            throw new InterruptedIOException("Card changed");
        }
        return bytes_read;