/*
*/
/**
*
* @author
*/
package uk.co.nimp.scard;
import com.atolsystems.atolutilities.AStringUtilities;
import com.atolsystems.atolutilities.ATimeUtilities;
import java.util.List;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallFunctionMapper;
import java.io.File;
import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import uk.co.nimp.smartcard.AnswerToReset;
import static uk.co.nimp.scard.SmartwareTerminalManager.Win32MlOsMainDll.*;
import static uk.co.nimp.scard.SmartwareTerminalManager.Win32CardDll.*;
import uk.co.nimp.smartcard.Apdu;
public class SmartwareTerminalManager extends GenericTerminalManager {
//public static final int unknown_constant=-1 ;
static public interface Win32MlOsMainDll extends Library {
/*-----------------------------------------------------------------------*
Common error codes
*-----------------------------------------------------------------------*/
public static final int sys__err = 0;
public static final int sys__ok = 0; /* Every thing's OK */
public static final int sys__noobj = 1 + sys__err; /* Object not found */
public static final int sys__noop = 2 + sys__err; /* Operation not found */
public static final int sys__arg = 3 + sys__err; /* Wrong parameter */
public static final int sys__timeout = 4 + sys__err; /* Timeout */
public static final int sys__resp = 5 + sys__err; /* Too long answer length */
public static final int sys__escape = 6 + sys__err; /* User escape */
public static final int sys__mem = 7 + sys__err; /* Wrong memory model */
public static final int sys__nodrv = sys__noobj;
/*-----------------------------------------------------------------------*
APPLICATION INTERFACE
*-----------------------------------------------------------------------*/
//public static final int sysct_wait= sysobj_Wait;//this is actualy a function, not a constant
//public static final int sysct_exec= sysobj_Call;
/* struct {
unsigned long Mode; // Mode and parameter mask
char IniPath[256+1]; // .INI file (ex: "C:\\MLOS.INI") or ""
char AppName[32+1]; // Appli name or ""
#if !config_CONSO && config_WIN32
HWND syst_PrintWnd; // 0 or Print window
#endif
char * Options; // 0 or Options
err_Type (* syst_PrintFunc)(char *); // 0 or Print function
} mloscfg_Type;*/
public static class mloscfg_Type extends Structure {
//public long Mode=0; // Mode and parameter mask
public int Mode = 0; // Mode and parameter mask
public byte[] IniPath = new byte[256 + 1]; // .INI file (ex: "C:\\MLOS.INI") or ""
public byte[] AppName = new byte[32 + 1]; // Appli name or ""
//#if !config_CONSO && config_WIN32
//public Pointer syst_PrintWnd; // 0 or Print window
public int syst_PrintWnd = 0;
//#endif
//public Pointer Options; // 0 or Options
public int Options = 0;
//public Pointer syst_PrintFunc; // 0 or Print function
public int syst_PrintFunc = 0;
}
/*-----------------------------------------------------------------------*
Init specific data
*-----------------------------------------------------------------------*/
/*err_Type mloscfg_Init(
mloscfg_Type * Cfg // (IN): Cfg with default
);*/
int mloscfg_Init(mloscfg_Type Cfg); // (IN): Cfg with default
/*-----------------------------------------------------------------------*
Create tasks of configuration
*-----------------------------------------------------------------------*/
//err_Type mloscfg_Start(mloscfg_Type * Cfg);
int mloscfg_Start(mloscfg_Type Cfg);
/*-----------------------------------------------------------------------*
End tasks of configuration
*-----------------------------------------------------------------------*/
//err_Type mloscfg_End(mloscfg_Type * Cfg);
int mloscfg_End(mloscfg_Type Cfg);
/*err_Type err_Msg( err_Type Erno, // (IN): Error code
char ** pMsg // (OUT): Message
);*/
int err_Msg(int Erno, // (IN): Error code
PointerByReference pMsg // (OUT): Message
);
/*long err_Msg( long Erno, // (IN): Error code
String[] pMsg // (OUT): Message
);*/
}
static public interface Win32CardDll extends Library {
//public static final int sys__noobj=unknown_constant ;
//public static final int sys__arg=unknown_constant ;
/*----------------------------------------------------------------------*
Card Object Codes
*----------------------------------------------------------------------*/
/* Contact Interfaces */
public static final int sys_CdId = 0x10; // Secu card
public static final int sys_CdpId = 0x18; // Perso card
public static final int sys_Cd1Id = 0x10; // Contact Card 1
public static final int sys_Cd2Id = 0x18; // Contact Card 2
public static final int sys_Cd3Id = 0x20; // Contact Card 3
public static final int sys_Cd4Id = 0x28; // Contact Card 4
public static final int sys_Cd5Id = 0xD0; // Contact Card 5
public static final int sys_Cd6Id = 0xD8; // Contact Card 6
public static final int sys_Cd7Id = 0xC0; // Contact Card 7
public static final int sys_Cd8Id = 0xC8; // Contact Card 8
public static final int sys_Cd9Id = 0xB0; // Contact Card 9
public static final int sys_Cd10Id = 0xB8; // Contact Card 10
/* Contactless Interfaces */
public static final int sys_CdP1Id = 0x40; // Proximity Card 1
public static final int sys_CdP2Id = 0x48; // Proximity Card 2
public static final int sys_CdP3Id = 0xB0; // Proximity Card 3
public static final int sys_CdP4Id = 0xB8; // Proximity Card 4
public static final int sys_CdP5Id = 0xC0; // Proximity Card 5
public static final int sys_CdP6Id = 0xC8; // Proximity Card 6
public static final int sys_CdP7Id = 0xD0; // Proximity Card 7
public static final int sys_CdP8Id = 0xD8; // Proximity Card 8
/*----------------------------------------------------------------------*
CARD Error Codes
*----------------------------------------------------------------------*/
public static final int card__Ok = 0x00;
public static final int card__err = sys_CdId;
public static final int card__no_card = card__err; // No card
public static final int card__card_gone = card__err + 1; // Card pulled out
public static final int card__card_off = card__err + 2; // Card is not powered
public static final int card__timeout = card__err + 3; // Card mute
public static final int card__reemit = card__err + 4; // Too many parity errors
public static final int card__comm = card__err + 5; // Communication error
public static final int card__lng = card__err + 6; // header LNG != exchanged lng
public static final int card__sw12 = card__err + 7; // sw1-sw2 != 90H-00H
public static final int card__NA = card__err + 8; // Card Operation Not Available
public static final int card__Type = card__err + 9; // Invalid interface or model selected
public static final int card__Open = card__err + 10; // Interface not opened
public static final int card__Coupler = Win32MlOsMainDll.sys__noobj; // Bad Coupler Number
public static final int card__NullPtr = Win32MlOsMainDll.sys__arg; // NullPtr
public static final int card__Ko = card__comm; // General Error
/*----------------------------------------------------------------------*
Card Models
Contact models Range : [00h...0Fh], [C0h...FFh]
Contactless models Range : [10h...BFh]
*----------------------------------------------------------------------*/
// ICC models
public static final int card_ModelCAsync = 0x02; // ISO 7816
public static final int card_ModelCIsoEh = 0x03; // ISO 7816 for Enhanced SW reader
public static final int card_ModelCUsb = 0x05; // ICC USB Cards
public static final int card_ModelCRaw = 0x0F; // RAW
// PICC models
public static final int card_ModelPMifare = 0x18; // MIFARE I
public static final int card_ModelP14443A = 0x58; // ISO 14443-A with SW Modem
public static final int card_ModelP14443B = 0x38; // ISO 14443-B with SW Modem
public static final int card_ModelP14443A_RC = 0x28; // ISO 14443-A with RC Modem
public static final int card_ModelP14443B_RC = 0x88; // ISO 14443-B with RC Modem
public static final int card_ModelPFeliCa = 0x48; // FeliCa
public static final int card_ModelP15693 = 0x68; // ISO 15693
public static final int card_ModelPIcode = 0x78; // Icode
public static final int card_ModelPPayPassA = 0x59; // PAYPASS-A with SW Modem
public static final int card_ModelPPayPassB = 0x39; // PAYPASS-B with SW Modem
public static final int card_ModelPPayPassA_RC = 0x29; // PAYPASS-A with RC Modem
public static final int card_ModelPPayPassB_RC = 0x89; // PAYPASS-B with RC Modem
// ICC Checksum type (T=1)
public static final int card_T1CheckLRC = 0;
public static final int card_T1CheckCRC = 1;
// card Object buffers sizes
public static final int card_ATRMaxL = 40; // Max length of ATR
public static final int card_BufMaxL = 255; // Max length of card data
public static final int card_InfoMaxL = 56; // Max length of info
// Default card methods timeout
public static final int card_TimeoutOp = 6000; // 6 seconds
/*----------------------------------------------------------------------*
card_CfgXType : Card Extended Configuration Structure
*----------------------------------------------------------------------*/
public static final int card_CfgxFD = 0x00000001;
public static final int card_CfgxFI = 0x00000002;
public static final int card_CfgxDI = 0x00000004;
public static final int card_CfgxN = 0x00000008;
public static final int card_CfgxCD = 0x00000010;
public static final int card_CfgxCDU = 0x00000020;
public static final int card_CfgxWI = 0x00000040;
public static final int card_CfgxWWT = 0x00000080;
public static final int card_CfgxODMT = 0x00000100;
public static final int card_CfgxODTU = 0x00000200;
public static final int card_CfgxCWI = 0x00000400;
public static final int card_CfgxCWT = 0x00000800;
public static final int card_CfgxBWI = 0x00001000;
public static final int card_CfgxBWT = 0x00002000;
public static final int card_CfgxBGT = 0x00004000;
public static final int card_CfgxNAD = 0x00008000;
public static final int card_CfgxIFSD = 0x00010000;
public static final int card_CfgxIFSC = 0x00020000;
public static final int card_CfgxTSWT = 0x00040000;
public static final int card_CfgxTSWWT = 0x00080000;
public static final int card_CfgxRSTWT = 0x00100000;
public static final int card_CfgxRSTMode = 0x00200000;
public static final int card_CfgxT1ErrReemit = 0x00400000;
public static final int card_CfgxPPSGT = 0x00800000;
public static final int card_CfgxAll = 0x00FFFFFF;
public static final int cCfgStructSize1 = 96;
public static final int cCfgStructSize2 = 100;
public static final int cCfgStructSize3 = 104;
// RSTMode Flag
public static final int card_RSTModeStayOn = 0x01;
public static final int card_RSTModeAtrGet = 0x02;
/*public class err_Type{
short err_Type;
}
public class card_NOType{
short card_NOType;
}
public class syst_TType{
short syst_TType;
}*/
public static class card_Type extends Structure {
public short Size; // sizeof card_Type
//public card_NOType NObj; // Node/Obj number
public short NObj; // Node/Obj number
public byte Model; // Card type
public byte ATR[] = new byte[card_ATRMaxL]; // Last Answer To Reset
public byte ATRLg; // Length of ATR
public byte SW1; // Last card procedure byte SW1
public byte SW2; // Last card procedure byte SW2
//public err_Type CplStatus; // Last card method error
//public short CplStatus; // Last card method error
public int CplStatus; // Last card method error
//public syst_TType timeout; // Current card methods timeout (ms)
//public short timeout; // Current card methods timeout (ms)
public int timeout; // Current card methods timeout (ms)
public byte Pcb; // Obsolete
public byte PcbChain;
public byte fPcbChain;
public byte Check;
public byte Buf[] = new byte[card_BufMaxL + 16]; // Com buffer
public byte Info[] = new byte[card_InfoMaxL]; // Local data
public byte CardFlag; // Card Object Flag
public Pointer pHwi; // Reference on Card Hardware Interface
}
public static final int SIZEOF_CARD_CFGXTYPE = 26 * 4;
public static class card_CfgXType extends Structure {
public int StructSize; /* Structure Size */
public int Mask; /* Selection Mask */
public int FD; /* Ratio F/D to fix the ETU value*/
public int FI; /* Clock rate conversion Factor */
public int DI; /* Baudrate adjustment factor */
public int N; /* Extra Guard time in Transmission */
public int CD; /* Character Duration in Transmission */
public int CDU; /* Character Duration Unit */
public int WI; /* Wait Integer (T=0) */
public int WWT; /* Work Waiting Time (T=0) */
public int ODMT; /* Opposite Direction Minimum Time (T=0)*/
public int ODTU; /* Opposite Direction Time Unit (T=0)*/
public int CWI; /* Character Waiting time Integer (T=1) */
public int CWT; /* Character Waiting Time (T=1) */
public int BWI; /* Block Waiting time Integer (T=1) */
public int BWT; /* Block Waiting Time(T=1) */
public int BGT; /* Block GuardTime (T=1) */
public int NAD; /* Node Address Byte (T=1) */
public int IFSD; /* IFS for the Reader (T=1) */
public int IFSC; /* IFS for the Card (T=1) - Read Only */
public int TSWT; /* TS byte Waiting Time (ATR) */
public int TSWWT; /* TS Work Waiting Time */
public int RSTWT; /* Waiting Time after Reset */
public int RSTMode; /* Reset Mode */
public int T1ErrReemit; /* Number of Reemission when Errors in T=1 */
public int PPSGT; /* PPS Guard Time */
};
/*err_Type card_Open( card_Ref Obj, // Card object
uchar Model, // (IN) Model of Communication
card_NOType NObj); // (IN) Physical Interface*/
int card_Open(card_Type Obj, // Card object
int Model, // (IN) Model of Communication
int NObj); // (IN) Physical Interface
/*err_Type card_DetectGet( card_Ref Obj, // Card object
ulong *Value); // (OUT) Value */
int card_DetectGet(card_Type Obj, // Card object
int Value[]); // (OUT) Value
/*err_Type card_FreqXSet( card_Ref Obj, // Card object
ulong Freq); // (IN) Card frequency in kHz */
int card_FreqXDef(card_Type Obj, // Card object
int Freq); // (IN) Card frequency in kHz
/*err_Type card_FreqXGet( card_Ref Obj, // Card object
ulong * Freq); // (OUT) Frequency in kHz*/
int card_FreqXGet(card_Type Obj, // Card object
int Freq[]); // (OUT) Frequency in kHz*/
/*err_Type card_VccDef( card_Ref Obj, // Card object
ushort Vcc); // (IN) Voltage in mV */
int card_VccDef(card_Type Obj, // Card object
int Vcc); // (IN) Voltage in mV
//err_Type card_Reset(card_Ref Obj);// Card object
int card_Reset(card_Type Obj);
//err_Type card_ResetWarm(card_Ref Obj);// Card object
int card_ResetWarm(card_Type Obj);// Card object
/*err_Type card_PPSX( card_Ref Obj, // Card object
uchar * Buf, // (IN/OUT) PPS Command / Card Answer
card_LType LngIn, // (IN) Data length to send
card_LType * pLngOut); // (IN/OUT) Max. Response / Current Response Length */
int card_PTSX(card_Type Obj, // Card object
byte Buf[], // (IN/OUT) PPS Command / Card Answer
int LngIn, // (IN) Data length to send
int pLngOut[]); // (IN/OUT) Max. Response / Current Response Length
/*int card_InX( card_Type Obj, // Card object
byte Buf[]); // (IN) Data buffer*/
int card_InXH(card_Type Obj, // Card object
byte Cla, // (IN) Class
byte Ins, // (IN) Instruction
byte P1, // (IN) P1 parameter
byte P2, // (IN) P2 parameter
byte Lng, // (IN) P3 parameter : Data length
byte Buf[]); // (IN) Data Buffer
/*err_Type card_OutXH( card_Ref Obj, // Card object
uchar Cla, // (IN) Class
uchar Ins, // (IN) Instruction
uchar P1, // (IN) P1 parameter
uchar P2, // (IN) P2 parameter
uchar Lng, // (IN) P3 parameter : Data length
uchar * pBuf, // (OUT) Buffer of Data received
sysobj_LType * pLng); // (OUT) Length of Data received */
int card_OutXH(card_Type Obj, // Card object
byte Cla, // (IN) Class
byte Ins, // (IN) Instruction
byte P1, // (IN) P1 parameter
byte P2, // (IN) P2 parameter
byte Lng, // (IN) P3 parameter : Data length
byte pBuf[], // (OUT) Buffer of Data received
int pLng[]); // (OUT) Length of Data received
//err_Type card_Off(card_Ref Obj); // Card object
int card_Off(card_Type Obj); // Card object
//err_Type card_Close(card_Ref Obj); // Card object
int card_Close(card_Type Obj); // Card object
int card_CardCfgX(card_Type Obj, // Card object
card_CfgXType pConfig); // (IN/OUT) Configuration Structure
}
static protected final Throwable initException;
static protected final Win32CardDll win32CardDll;
static protected final Win32MlOsMainDll win32MlOsMainDll;
static protected final Win32MlOsMainDll.mloscfg_Type conf;
static final String CONF_FILE_NAME="SmartwareTerminalManager.conf";
static public String couplerId2Name(int model, int couplerId) {
StringBuilder sb = new StringBuilder("Smartware #");
sb.append(AStringUtilities.byteToHex(couplerId >> 8));
if (isContactModel(model)) {
sb.append(" Contact ");
switch (couplerId & 0xFF) {
case sys_Cd1Id:
sb.append("Card 1");
break;
case sys_Cd2Id:
sb.append("Card 2");
break;
case sys_Cd3Id:
sb.append("Card 3");
break;
case sys_Cd4Id:
sb.append("Card 4");
break;
case sys_Cd5Id:
sb.append("Card 5");
break;
case sys_Cd6Id:
sb.append("Card 6");
break;
case sys_Cd7Id:
sb.append("Card 7");
break;
case sys_Cd8Id:
sb.append("Card 8");
break;
case sys_Cd9Id:
sb.append("Card 9");
break;
case sys_Cd10Id:
sb.append("Card 10");
break;
default:
throw new IllegalArgumentException("Invalid couplerId:0x" + Integer.toHexString(couplerId));
}
} else {
sb.append(" Proximity ");
switch (couplerId & 0xFF) {
case sys_CdP1Id:
sb.append("Card 1");
break;
case sys_CdP2Id:
sb.append("Card 2");
break;
case sys_CdP3Id:
sb.append("Card 3");
break;
case sys_CdP4Id:
sb.append("Card 4");
break;
case sys_CdP5Id:
sb.append("Card 5");
break;
case sys_CdP6Id:
sb.append("Card 6");
break;
case sys_CdP7Id:
sb.append("Card 7");
break;
case sys_CdP8Id:
sb.append("Card 8");
break;
default:
throw new IllegalArgumentException("Invalid couplerId:0x" + Integer.toHexString(couplerId));
}
}
return sb.toString();
}
public static boolean isIso7816Model(int model) {
if ((Win32CardDll.card_ModelCAsync == model) || (Win32CardDll.card_ModelCIsoEh == model)) {
return true;
}
return false;
}
public static boolean isContactModel(int model) {
if ((Win32CardDll.card_ModelCAsync == model) || (Win32CardDll.card_ModelCIsoEh == model) || (Win32CardDll.card_ModelCRaw == model) || (Win32CardDll.card_ModelCUsb == model)) {
return true;
}
return false;
}
public static void main(String args[]) throws ScardException {
System.out.println(win32CardDll);
SmartwareTerminalManager manager = new SmartwareTerminalManager();
manager.list();
}
public SmartwareTerminalManager() {
}
protected String getConfFileName(){
return CONF_FILE_NAME;
}
@Override
protected void loadConfigurationImpl(File argFile) throws IOException {
}
static final String DEFAULT_CARD_DLL="CARD";//we should offer a way to override this in future
static final String DEFAULT_MLOSMAIN_DLL="MLOSMAIN";//we should offer a way to override this in future
static {
Throwable ex = null;
Win32CardDll trial = null;
Win32MlOsMainDll win32MlOsMainDllTrial = null;
Win32MlOsMainDll.mloscfg_Type confTrial = null;
try {
Map<String, Object> options = new HashMap<String, Object>();
//options.put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper());
Native.setProtected(true);
trial = (Win32CardDll) Native.loadLibrary(DEFAULT_CARD_DLL, Win32CardDll.class, options);
} catch (Throwable e) {
ex = e;
trial = null;
}
win32CardDll = trial;
try {
Map<String, Object> options = new HashMap<String, Object>();
//options.put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper());
win32MlOsMainDllTrial = (Win32MlOsMainDll) Native.loadLibrary(DEFAULT_MLOSMAIN_DLL, Win32MlOsMainDll.class, options);
confTrial = new Win32MlOsMainDll.mloscfg_Type();
int status = win32MlOsMainDllTrial.mloscfg_Init(confTrial);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("mloscfg_Init failed", status);
}
confTrial.IniPath = AStringUtilities.StringToBytesWithFinalNull("C:\\mlos.ini");
confTrial.AppName = AStringUtilities.StringToBytesWithFinalNull("");
status = win32MlOsMainDllTrial.mloscfg_Start(confTrial);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("mloscfg_Start failed", status);
}
} catch (Throwable e) {
ex = e;
win32MlOsMainDllTrial = null;
}
win32MlOsMainDll = win32MlOsMainDllTrial;
initException = ex;
conf = confTrial;
if (null == initException) {
try {
initContext();
} catch (ScardException ex1) {
Logger.getLogger(SmartwareTerminalManager.class.getName()).log(Level.SEVERE, null, ex1);
}
}
}
static public void initContext() throws ScardException {
if (null != initException) {
throw new ScardException("", initException);
}
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
{
//release all resources
for (Reference<SmartwareTerminal> tRef : terminals.values()) {
try {
SmartwareTerminal t = tRef.get();
if(null==t) continue;
if(null==t.card) continue;
int status = win32CardDll.card_Close(t.card);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_Close failed", status);
}
} catch (SmartwareException ex) {
Logger.getLogger(SmartwareTerminalManager.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
});
}
@Override
public List<GenericTerminal> list() throws ScardException {
List<GenericTerminal> terminalsList = new ArrayList<GenericTerminal>();
if(null!=initException)
return Collections.unmodifiableList(terminalsList);
try {
GenericTerminal terminal = getTerminalImpl(Win32CardDll.card_ModelCIsoEh, Win32CardDll.sys_CdId);
terminalsList.add(terminal);
} catch (ScardException e) {
}
return Collections.unmodifiableList(terminalsList);
}
private static final Map<String, Reference<SmartwareTerminal>> terminals = new HashMap<String, Reference<SmartwareTerminal>>();
protected static GenericTerminal getTerminalImpl(int model, int couplerId) throws ScardException {
String name = couplerId2Name(model, couplerId);
Reference<SmartwareTerminal> ref = terminals.get(name);
SmartwareTerminal terminal = (ref != null) ? ref.get() : null;
if (terminal != null) {
return terminal;
}
Win32CardDll.card_Type card = new Win32CardDll.card_Type();
int status = win32CardDll.card_Open(card, model, couplerId);
if (Win32CardDll.card__Ok != status) throw new SmartwareException("card_Open failed", status);
//card.timeout=3*60*1000;//3 minutes as timeout
card.timeout = 1000;//1s as timeout
//System.out.println(card);
card_CfgXType configX = new card_CfgXType();
configX.StructSize = configX.size();//SIZEOF_CARD_CFGXTYPE; // Initialize StructSize Field
configX.Mask = 0;
status = win32CardDll.card_CardCfgX(card, configX); // Read the current configuration
if (Win32CardDll.card__Ok != status) throw new SmartwareException("card_CardCfgX failed", status);
//System.out.println("WI="+configX.WI+", WWT="+configX.WWT);
configX.N = 255;//12ETU for T=0 and 11ETU for T=1
configX.ODMT = 12;//12ETU in case of direction change
configX.TSWT = 400;//ATR should start not before 400cycles after reset release
configX.RSTWT = 0;//no waiting time after ATR
configX.RSTMode = 0x03;//keep card activated even if ATR is invalid and return the invalid ATR
configX.PPSGT = 0;//no waiting time after PPS
configX.Mask = (win32CardDll.card_CfgxN | win32CardDll.card_CfgxODMT | win32CardDll.card_CfgxTSWT | win32CardDll.card_CfgxRSTWT | win32CardDll.card_CfgxRSTMode | win32CardDll.card_CfgxPPSGT);
configX.Mask = 0;
status = win32CardDll.card_CardCfgX(card, configX); // Update parameters
if (Win32CardDll.card__Ok != status) throw new SmartwareException("card_CardCfgX failed", status);
//System.out.println(card);
terminal = new SmartwareTerminal(card, model, couplerId, name);
terminals.put(name, new WeakReference<SmartwareTerminal>(terminal));
return terminal;
}
static void SCardSetVdd(card_Type card, int vddMillivolts) throws ScardException {
int status = win32CardDll.card_VccDef(card, vddMillivolts);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_VccDef failed", status);
}
}
static void SCardSetClk(card_Type card, int clkHertz) throws ScardException {
int status = win32CardDll.card_FreqXDef(card, clkHertz / 1000);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_FreqXDef failed", status);
}
}
static int SCardGetClk(card_Type card) throws SmartwareException {
int clkHertz[] = new int[1];
int status = win32CardDll.card_FreqXGet(card, clkHertz);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_FreqXGet failed", status);
}
return clkHertz[0] * 1000;
}
static AnswerToReset SCardConnect(card_Type card, int protocol, int activation, boolean autoPps) throws ScardException {
switch (protocol) {
case GenericTerminal.PROTOCOL_T_0:
//connectProtocol = SCARD_PROTOCOL_T0;
break;
case GenericTerminal.PROTOCOL_T_1:
//connectProtocol = SCARD_PROTOCOL_T1;
break;
case GenericTerminal.PROTOCOL_ANY:
//connectProtocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
break;
case GenericTerminal.PROTOCOL_DIRECT:
case GenericTerminal.PROTOCOL_T_15:
case GenericTerminal.PROTOCOL_T_CL_A:
case GenericTerminal.PROTOCOL_T_CL_B:
case GenericTerminal.PROTOCOL_ANY_STD_CL:
default:
throw new IllegalArgumentException("protocol = " + GenericTerminal.getProtocolName(protocol));
}
int status;
if (GenericTerminal.ACTIVATION_FORCE_COLD == activation) {
status = win32CardDll.card_Reset(card);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_Reset failed", status);
}
} else {
status = win32CardDll.card_ResetWarm(card);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_ResetWarm failed", status);
}
}
//status=win32CardDll.card_CardCfgX(card, configX); // get parameters
//System.out.println("WI="+configX.WI+", WWT="+configX.WWT);
AnswerToReset out = new AnswerToReset(card.ATR, 0, card.ATRLg);
//System.out.println("ATR:" + out.toString());
int fiDi = out.getSupportedFiDi();
if(autoPps && out.acceptPps() && (out.getSupportedFiDi()!=0x11)){
int pLngOut[] = new int[1];
pLngOut[0] = 10;
byte ppsBuf[] = new byte[pLngOut[0]];
ppsBuf[0] = (byte) 0xFF;
if (GenericTerminal.PROTOCOL_T_1 == protocol) {
ppsBuf[1] = 0x11;
} else {
ppsBuf[1] = 0x10;
}
ppsBuf[2] = (byte) fiDi;
for (int i = 3; i < ppsBuf.length; i++) {
ppsBuf[i] = 0;
}
status = win32CardDll.card_PTSX(card, ppsBuf, 3, pLngOut);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_PTSX failed", status);
}
//System.out.println("PPS response:" + AStringUtilities.bytesToHex(ppsBuf, 0, pLngOut[0]));
}
return out;
}
static public int getStatusWord(card_Type card) {
int out = 0xFF & card.SW1;
out = out << 8;
out |= 0xFF & card.SW2;
return out;
}
static Apdu.CardResponse SCardTransmit(card_Type card, Apdu apdu) throws ScardException {
Apdu.CardResponse out;
int tpduLe = apdu.getExpectedLe();
byte[] leData = new byte[tpduLe];
if (256 == tpduLe) {
tpduLe = 0;
}
int actualTpduLeRef[] = new int[1];
byte[] lcData = apdu.getLcDataAsBytes();
byte tpduLc = (byte) (lcData.length & 0xFF);
int apduCase = apdu.getIsoApduCase();
int status;
long start = System.nanoTime();
int timeoutBu = card.timeout;
card.timeout = 3 * 60 * 1000;//3 minutes as timeout
try {
switch (apduCase) {
case Apdu.CASE1:
case Apdu.CASE3S:
status = win32CardDll.card_InXH(card,
(byte) apdu.getCla(),
(byte) apdu.getIns(),
(byte) apdu.getP1(),
(byte) apdu.getP2(),
tpduLc, lcData);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_InXH failed, time from start of APDU to failure:" + ATimeUtilities.getUserFriendlyTimeUs(System.nanoTime() - start), status);
}
out = new Apdu.CardResponse(getStatusWord(card));
break;
case Apdu.CASE2S:
status = win32CardDll.card_OutXH(card,
(byte) apdu.getCla(),
(byte) apdu.getIns(),
(byte) apdu.getP1(),
(byte) apdu.getP2(),
(byte) tpduLe, leData, actualTpduLeRef);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_InXH failed, time from start of APDU to failure:" + ATimeUtilities.getUserFriendlyTimeUs(System.nanoTime() - start), status);
}
int actualTpduLe = actualTpduLeRef[0];
if (actualTpduLe != apdu.getExpectedLe()) {
byte[] actualLeData = new byte[actualTpduLe];
for (int i = 0; i < actualTpduLe; i++) {
actualLeData[i] = leData[i];
}
leData = actualLeData;
}
out = new Apdu.CardResponse(leData, getStatusWord(card));
break;
default:
throw new ScardException("Apdu case not supported: 0x" + Integer.toHexString(apduCase));
}
} finally {
card.timeout = timeoutBu;
}
return out;
}
static void SCardDisconnect(card_Type card) throws SmartwareException {
int status = win32CardDll.card_Off(card);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_Off failed", status);
}
}
static GenericTerminal.State SCardIsPresent(card_Type card) throws ScardException {
int value[] = new int[1];
int status = win32CardDll.card_DetectGet(card, value);
if (Win32CardDll.card__Ok != status) {
throw new SmartwareException("card_DetectGet failed", status);
}
GenericTerminal.State out;
switch (value[0]) {
case 0:
out = GenericTerminal.State.CARD_ABSENT;
break;
case 1:
out = GenericTerminal.State.CARD_PRESENT;
break;
default:
throw new ScardException("card_DetectGet returned a unsupported value: " + value[0]);
}
return out;
}
}