/**
*
* @author Sebastien Riou
*/
package uk.co.nimp.scard;
import com.atolsystems.atolutilities.ACommandLineUtilities;
import com.atolsystems.atolutilities.ACommandLineUtilities.Arg;
import com.atolsystems.atolutilities.AStringUtilities;
import com.atolsystems.atolutilities.ArgSpec;
import com.atolsystems.atolutilities.MutableInteger;
import java.io.IOException;
import java.util.List;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallFunctionMapper;
import java.io.File;
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.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import uk.co.nimp.smartcard.AnswerToReset;
import static uk.co.nimp.scard.MP300Exception.*;
import uk.co.nimp.smartcard.Apdu;
public class Star265TerminalManager extends GenericTerminalManager {
static public interface Win32Stcp250Dll extends Library {
// Functions from Stcp250.dll
//WORD MPS_ResetHard(void);
short MPS_ResetHard();
//void CALL SetDLLTimeOutValue(WORD timeout);
void SetDLLTimeOutValue(int timeout);
//WORD CALL GetDLLTimeOutValue(void);
short GetDLLTimeOutValue();
//WORD CALL MPS_OnCmm( BYTE CplNum, DWORD Frequency, WORD *pATRLg, BYTE *pATRBuf);
short MPS_OnCmm(int CplNum, int Frequency, ShortByReference pATRLg, byte[] pATRBuf);
//WORD CALL MPS_OffCmm( BYTE CplNum);
short MPS_OffCmm(int CplNum);
//
// WORD CALL MPS_SendAPDU( BYTE CplNum, DWORD Command, DWORD Lc, BYTE *pLcField, DWORD Le, BYTE *pLeField, DWORD *pLeFieldLen, WORD *SW1SW2);
short MPS_SendAPDU( int CplNum, int Command, int Lc, byte[] pLcField,
int Le, byte[] pLeField, LongByReference pLeFieldLen,IntByReference SW1SW2);
//WORD CALL MPS_SendIFSRequest( BYTE CplNum, BYTE IFSValue);
//
//// Change protocol parameters
//WORD CALL MPS_ChangeProtocolParameters( BYTE CplNum, DWORD TypeParam, void *Param, DWORD ParamSize);
//short MPS_ChangeProtocolParameters(byte NoCPL,int TypeParam, Pointer Param, int ParamSize);
short MPS_ChangeProtocolParameters(int NoCPL,int TypeParam, byte Param[], int ParamSize);
//WORD CALL MPS_GetProtocolParameters( BYTE CplNum, DWORD TypeParam, void *Param, DWORD SizeofParam, DWORD *pParamSize);
short MPS_GetProtocolParameters( int CplNum, int TypeParam, Pointer Param, int SizeofParam, LongByReference pParamSize);
static public final int CPP_IFSC= 1; // Force IFSC value
static public final int CPP_IFSD= 2; // Force IFSD value
static public final int CPP_SIM_ATR= 3; // Change ATR specification
//static public final int CPP_INITIAL_WAITING_TIME 4 // Force initial waiting time (9600 ETU) with another value
//static public final int CPP_ATR_LEN 5 // For no ISO ATR specify ATR length
//static public final int CPP_INITIAL_ETU 6 // Change initial ETU for next MPS_OnCmm
//static public final int CPP_MAX_CLK_ATR 10 // Clock count after reset before card mute
//static public final int CPP_CLK_RST 11 // Clock count where RST is low
//static public final int CPP_STANDARD_USED 12 // Change the standard used
// static public final int STD_ISO_7816 0 // Standard ISO 7816
// static public final int STD_EMV_2000 1 // Standard EMV 2000
// static public final int STD_3GPP 2 // Standard 3GPP
//static public final int CPP_ERROR_SIGNAL 14 // Enable/Disable error signal handling
//static public final int CPP_CWT 15 // Change CWT in ETU
//static public final int CPP_BWT 16 // Change BWT in ETU
//static public final int CPP_WWT 17 // Change WWT in ETU
//static public final int CPP_BGT 18 // Change BGT in ETU
//static public final int CPP_EGT 19 // Change EGT in ETU
//static public final int CPP_RGT 20 // Change RGT in ETU
//static public final int CPP_PROTOCOL_TIMEOUT 21 // Enable/Disable protocol timeout IWT,WWT,BWT et CWT
//static public final int CPP_CURRENT_F_D 22 // Change and apply current F/D factor
//static public final int CPP_TIMEOUT_NULL_BYTE 23 // NULL byte timeout in T=0 protocol
//static public final int CPP_RGT1 24 // Change RGT1 in C3 clock count
//static public final int CPP_RGT2 25 // Change RGT2 in C3 clock count
//static public final int CPP_CHECK_ATR 28 // ON or OFF for enable/disable ATR analyze
//static public final int CPP_POWER_OFF_ON_ATR_ERROR 29 // ON or OFF for enable power off on ATR analyze error
//static public final int CPP_CURRENT_PROTOCOL 31 // Protocol in use (T=0 ou T=1)
//static public final int CPP_C6CONTROL 33 // control behaviour of C6 during activation/deactivation
//static public final int CPP_CURRENT_ETU 34
//
///*-----------------------------------------------*
// * Setting voltages and miscellaneous parameters *
// *-----------------------------------------------*/
//WORD CALL MPS_VCCSelectMV( BYTE CplNum, short ValVcc);
short MPS_VCCSelectMV(int CplNum, int ValVcc);
//static public final int VCC_MIN_MV 0L // 0 volts
//static public final int VCC_MAX_USB_IC 3600 // +3.6 volts max in USB-IC mode
//static public final int VCC_MAX_MV 6000L // +6 volts
//
//
//WORD CALL MPS_SetPullup(BYTE CplNum, BYTE PinNum, DWORD Pullup);
//static public final int PULLUP_IO_OFF 0 // Without pullup
//static public final int PULLUP_IO_5K 5000
//static public final int PULLUP_IO_22K 22000
//static public final int PULLUP_IO_INFINITE 1000000
//
//
//WORD CALL MPS_FrequencySelect( BYTE CplNum, DWORD Frequency);
short MPS_FrequencySelect(int CplNum, int Frequency);
//static public final int FREQ_MIN 500000
//static public final int FREQ_MAX 10000000
//WORD MPS_ModeSelect( BYTE CplNum, BYTE Mode);
short MPS_ModeSelect( int CplNum, int Mode);
// define for configuration mode : synchronous or asynchronous
static public final int CMM_MODE_SYNC= 1;//synchronous mode allow to force clock to high
static public final int CMM_MODE_ASYNC= 2;
//WORD MPS_PinWrite( BYTE CplNum, BYTE PinNum, BYTE PinState);
short MPS_PinWrite( int CplNum, int PinNum, int PinState);
// Define for smart card pin name
static public final int PIN_VCC= 0; // C1
static public final int PIN_RESET= 1; // C2
static public final int PIN_CLOCK= 2; // C3
static public final int PIN_RFU1= 3; // C4
static public final int PIN_GND= 4; // C5
static public final int PIN_VPP= 5; // C6
static public final int PIN_IO= 6; // C7
static public final int PIN_RFU2= 7; // C8
static public final int PIN_FUSE= PIN_RFU2;
static public final int PIN_RFU3= 8; // INPUT TTL
static public final int PIN_RFU4= 9; // OUTPUT TTL
// Define for pins VCC and VPP and pin state
static public final int OFF= 0; // LOW TTL
static public final int ON= 1; // HIGH TTL ( PullUp for C4,C7 and C8)
static public final int ON_MEASURE= 2; // HIGH TTL ( True high for C4,C7 and C8)
static public final int LOW= 3; // LOW TTL ( For all pins same as OFF)
static public final int HIGH= 4; // HIGH TTL ( True high for all pins)
static public final int PULLUP= 5; // HIGH TTL ( PullUp for only C4,C7 and C8)
static public final int HZ_STATE= 6; // High Z state ( for all pins)
/* define for APIs
* MPS_VCCSelect
* MPS_VIISelect
* MPS_VPPSelect
*/
static public final int VCC_MIN= 2; // 0.2 volts
static public final int VCC_MAX= 100; // 10.0 volts
static public final int VPP_MIN= 5; // 0.5 volts
static public final int VPP_MAX= 255; // 25.5 volts
static public final int VII_MIN= 20; // 2 volts
static public final int VII_MAX= 70; // 7.0 volts
/* define for APIs
* MPS_VCCSelectMV
* MPS_VIISelectMV
* MPS_VPPSelectMV
*/
static public final int VCC_MIN_MV= 20; // 0.2 volts
static public final int VCC_MAX_MV= 10000; // 10.0 volts
static public final int VPP_MIN_MV= 50; // 0.5 volts
static public final int VPP_MAX_MV= 25500; // 25.5 volts
static public final int VII_MIN_MV= 2000; // 2 volts
static public final int VII_MAX_MV= 7000; // 7.0 volts
// define for convention selection
static public final int DIRECT_CONVENTION= 1;
static public final int INVERSE_CONVENTION= 2;
// define for parity generation in transmit
static public final int EVEN_PARITY= 1;
static public final int ODD_PARITY= 2;
static public final int MARK_PARITY= 3;
static public final int SPACE_PARITY= 4;
// Define bit in StatIrq status
static public final int IRQ_VCC0= 0x01;
static public final int IRQ_VCC1= 0x02;
static public final int IRQ_VPP0= 0x04;
static public final int IRQ_VPP1= 0x08;
static public final int IRQ_VII0= 0x10;
static public final int IRQ_VII1= 0x20;
//WORD MPS_CardDetect( BYTE CplNum);
short MPS_CardDetect(int CplNum);
//STAR265 specific
//int StartDebug(char * strport)
int StartDebug(byte[] host);
//WORD MPS_SendPPSCmm( BYTE CplNum, BYTE Protocol, BYTE ParamFI, BYTE ParamDI);
short MPS_SendPPSCmm( int CplNum, int Protocol, int ParamFI, int ParamDI);
//WORD MPS_SendPTSCmm( BYTE CplNum, BYTE FIparam, BYTE DIparam);
short MPS_SendPTSCmm( int CplNum, int FIparam, int DIparam);
//WORD MPS_GetCmm( BYTE CplNum, DWORD TimeOut, BYTE *pChar);
short MPS_GetCmm( int CplNum, int TimeOut, byte[] pChar);
//WORD MPS_PutCmm( BYTE CplNum, BYTE Val);
short MPS_PutCmm( int CplNum, int Val);
//WORD MPS_SetETUWidth( BYTE CplNum, WORD ClockCount) ;
short MPS_SetETUWidth( int CplNum, int ClockCount) ;
//WORD MPS_SendReceiveCmm( BYTE CplNum, WORD LngIn, WORD *pLngOut, BYTE*pDataIn, BYTE *pDataOut)
short MPS_SendReceiveCmm( int CplNum, int LngIn, ShortByReference pLngOut, byte[] pDataIn, byte[] pDataOut);
//WORD MPS_WaitETUCpt( BYTE CplNum, DWORD Count);
short MPS_WaitETUCpt( int CplNum, int Count);
//WORD MPS_PortInit( BYTE PortNum, BYTE BaudRate, BYTE Frame);
short MPS_PortInit( int PortNum, int BaudRate, int Frame);
//WORD MPS_GetVersion( char *pVersion);
short MPS_GetVersion( byte[] pVersion);
// Communication port
static public final int PORT_SERIE1= 1;
static public final int PORT_SERIE2 = 2;
static public final int PORT_SERIESUP= 3;
static public final int PORT_SERIEINT = 4;
static public final int PORT_ETHERNET = 5;
// Baudrate
static public final int BAUDS_9600= 0;
static public final int BAUDS_19200= 1;
static public final int BAUDS_38400= 2;
static public final int BAUDS_115200= 3;
// Serial Frame
static public final int SERIAL_NOP= 0x00;
static public final int SERIAL_EVENP= 0x01;
static public final int SERIAL_ODDP= 0x02;
static public final int SERIAL_1STOP= 0x00;
static public final int SERIAL_2STOP= 0x04;
static public final int SERIAL_7BIT = 0x00;
static public final int SERIAL_8BIT = 0x10 ;
static public final int SERIAL_BINARY = 0x00;
static public final int SERIAL_XONXOFF= 0x08;
}
static final int MAX_CLOCK_FOR_16CYCLES_PER_ETU=3756000;//seems to be the upper limit when using STAR260
static final String DEFAULT_COM="COM1";
static final String DEFAULT_COM_PARAMS=":19200,N,8,2";
static final int DEFAULT_COUPLER=0x02;//bit0 means coupler0, bit1 coupler1...
static protected final Throwable initException;
static protected final Win32Stcp250Dll win32Stcp250Dll;
static transient Map<String,Integer> couplers;
static final String ARG_HELP = "-help";
static final int ARG_HELP_ID = 0;
static final String ARG_ADD_COM_PORT = "-addComPort:";
static final int ARG_ADD_COM_PORT_ID = 1;
static final String ARG_ADD_COUPLER = "-addCoupler:";
static final int ARG_ADD_COUPLER_ID = 2;
static final String CONF_FILE_NAME="Star265TerminalManager.conf";
static final String DEFAULT_STCP250_DLL="Stcp250";//we should offer a way to override this in future
static {
Throwable ex;
Win32Stcp250Dll trial;
try {
couplers=new HashMap<String,Integer>();
//ports = new String[0];//make sure ports will not be null
Map<String, Object> options = new HashMap<String, Object>();
options.put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper());
trial = (Win32Stcp250Dll) Native.loadLibrary(DEFAULT_STCP250_DLL, Win32Stcp250Dll.class, options);
trial=(Win32Stcp250Dll) Native.synchronizedLibrary(trial);
ex = null;
} catch (Throwable e) {
ex = e;
trial = null;
}
win32Stcp250Dll = trial;
initException = ex;
if(null==initException){
try {
initContext();
} catch (ScardException ex1) {
Logger.getLogger(Star265TerminalManager.class.getName()).log(Level.SEVERE, null, ex1);
}
}
}
public Star265TerminalManager(){
}
protected String getConfFileName(){
return CONF_FILE_NAME;
}
@Override
protected void loadConfigurationImpl(File argFile) throws Exception {
if(null!=initException)
throw new Exception(initException);
if(null==win32Stcp250Dll)
throw new NullPointerException(DEFAULT_STCP250_DLL+" could not be loaded");
try{
if(argFile.exists()){
ArrayList<String> argList=ACommandLineUtilities.processArgFile(argFile);
if((null==argList) || argList.isEmpty())
return;
String args[] = new String[argList.size()];
argList.toArray(args);
Integer curArgIndex = null;
Arg curArg = null;
curArgIndex = 0;
ArgSpec argSpecs[] = {
new ArgSpec(ARG_HELP, ARG_HELP_ID),
new ArgSpec(ARG_ADD_COM_PORT, ARG_ADD_COM_PORT_ID, ArgSpec.UNLIMITED_OCCURENCE),
new ArgSpec(ARG_ADD_COUPLER, ARG_ADD_COUPLER_ID, ArgSpec.UNLIMITED_OCCURENCE),
};
Set<ArgSpec> specs=ACommandLineUtilities.addArgFileArgSpecs(argSpecs);
argSpecs=new ArgSpec[specs.size()];
specs.toArray(argSpecs);
args = ACommandLineUtilities.processArgFile(new File("").getAbsoluteFile(), args);
ACommandLineUtilities.checkArgs(args, argSpecs);
String curPort=DEFAULT_COM;
while (curArgIndex < args.length) {
curArg = ACommandLineUtilities.getArg(args, argSpecs, curArgIndex, null);
if(null!=curArg){
switch (curArg.id) {
case ARG_HELP_ID:
StringBuilder sb=new StringBuilder();
sb.append("Star265TerminalManager configuration file help\n\n");
sb.append(ARG_ADD_COM_PORT);
sb.append("<name of port>\n");
sb.append("Add a port. Typical name looks like \"COM1\", \"COM2\" and so on\n");
System.out.println(sb.toString());
break;
case ARG_ADD_COM_PORT_ID:
curPort=curArg.value;
break;
case ARG_ADD_COUPLER_ID:
int couplerId=Integer.decode(curArg.value);
couplers.put(curPort, couplerId);
break;
}
}
curArgIndex++;
}
}else{
couplers.put(DEFAULT_COM, DEFAULT_COUPLER);
}
}catch(Throwable e){
throw new RuntimeException("Exception occured during processing of configuration file below\n"+argFile.getAbsolutePath()+"\n", e);
}
}
static public void initContext() throws ScardException {
//System.out.println("win32Stcp250Dll=" + win32Stcp250Dll);
if (null != initException) {
throw new ScardException("", initException);
}
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
{
//release all resources
//TODO: currently both calls return "bad argument"
int status = 0;
//status=win32Stcp250Dll.MPOS_CloseResource(RES_ID, 0);
//status=win32Stcp250Dll.MPOS_CloseResource(RES_ID, 1);
if (RET_OK != status) {
//throw new ScardException("MPOS_CloseResource returned " + status);
}
//status = win32Stcp250Dll.MPOS_CloseResource(RES_ID, 1);
}
}
});
}
@Override
public List<GenericTerminal> list() throws ScardException {
List<GenericTerminal> terminalsList = new ArrayList<GenericTerminal>();
if(null!=initException)
return Collections.unmodifiableList(terminalsList);
for(Entry<String, Integer>coupler:couplers.entrySet()){
try {
GenericTerminal terminal = getTerminalImpl(coupler.getKey(), coupler.getValue());
terminalsList.add(terminal);
} catch (MP300Exception e) {
}
}
return Collections.unmodifiableList(terminalsList);
}
private static final Map<String, Reference<GenericTerminal>> terminals = new HashMap<String, Reference<GenericTerminal>>();
protected static GenericTerminal getTerminalImpl(String ip, int couplerId) throws ScardException {
int status;
String name = "STAR265 on "+ip+" coupler"+ couplerId;
String strport=ip+DEFAULT_COM_PARAMS;
//String strport=ip+":38400,N,8,2";
Reference<GenericTerminal> ref = terminals.get(name);
GenericTerminal terminal = (ref != null) ? ref.get() : null;
if (terminal != null) {
return terminal;
}
byte[] readerBytes = AStringUtilities.StringToBytesWithFinalNull(strport);
int bu=win32Stcp250Dll.GetDLLTimeOutValue();
win32Stcp250Dll.SetDLLTimeOutValue(1);
boolean is260=false;
try{
status = win32Stcp250Dll.StartDebug(readerBytes);
if (RET_OK != status) throw new MP300Exception("Fail to establish communication with " + ip, status);
status = win32Stcp250Dll.MPS_ResetHard();
if (RET_OK != status) throw new MP300Exception("Fail to establish communication with " + ip, status);
byte[] version=new byte[256];
status=win32Stcp250Dll.MPS_GetVersion(version);
if (RET_OK != status) {
throw new MP300Exception("MPS_GetVersion failed: ", status);
}
String versionStr=AStringUtilities.bytesToString(version);
/*if(versionStr.indexOf("260")!=-1)
is260=true;*/
/*{//looks like we cannot change the speed of the port on the fly :-S
status = win32Stcp250Dll.MPS_PortInit(win32Stcp250Dll.PORT_SERIE2, win32Stcp250Dll.BAUDS_9600,
win32Stcp250Dll.SERIAL_8BIT|win32Stcp250Dll.SERIAL_1STOP|win32Stcp250Dll.SERIAL_NOP|win32Stcp250Dll.SERIAL_XONXOFF);
if (RET_OK != status) {
throw new MP300Exception("Fail to establish communication with " + ip, status);
}
}*/
}catch(MP300Exception e){
throw e;
}finally{
win32Stcp250Dll.SetDLLTimeOutValue(bu);
}
terminal = new Star265Terminal(couplerId, name, is260);
terminals.put(name, new WeakReference<GenericTerminal>(terminal));
return terminal;
}
static void SCardSetDllTimeout(int dllTimeoutS){
win32Stcp250Dll.SetDLLTimeOutValue(dllTimeoutS);
}
static void SCardSetVdd(int couplerId, int vddMillivolts) throws ScardException {
int status;
int timeout=win32Stcp250Dll.GetDLLTimeOutValue();
status = win32Stcp250Dll.MPS_VCCSelectMV(couplerId, vddMillivolts);
if (RET_OK != status) throw new MP300Exception("MPS_VCCSelectMV failed, couplerId="+couplerId+", vddMillivolts="+vddMillivolts+", Dll Timeout="+timeout, status);
}
static void SCardSetClk(int couplerId, int clkHertz) throws ScardException {
int status;
//this does not work: switch to synchronous mode seems to reset async mode parameters...
//status = win32Stcp250Dll.MPS_ModeSelect(couplerId, Win32Stcp250Dll.CMM_MODE_ASYNC);
//if (RET_OK != status) throw new MP300Exception("MPS_ModeSelect failed", status);
status = win32Stcp250Dll.MPS_FrequencySelect(couplerId, clkHertz);
if (RET_OK != status) throw new MP300Exception("MPS_FrequencySelect failed", status);
}
static void SCardClkStop(int couplerId,int PinState) throws ScardException {
int status;
//this does not work: switch to synchronous mode seems to reset async mode parameters...
//status = win32Stcp250Dll.MPS_ModeSelect(couplerId, Win32Stcp250Dll.CMM_MODE_SYNC);
//if (RET_OK != status) throw new MP300Exception("MPS_ModeSelect failed", status);
status = win32Stcp250Dll.MPS_PinWrite( couplerId, Win32Stcp250Dll.PIN_CLOCK, PinState);
if (RET_OK != status) throw new MP300Exception("MPS_PinWrite failed", status);
}
static void SCardClkRestore(int couplerId) throws ScardException {
int status;
//this does not work: switch to synchronous mode seems to reset async mode parameters...
//status = win32Stcp250Dll.MPS_ModeSelect(couplerId, Win32Stcp250Dll.CMM_MODE_ASYNC);
//if (RET_OK != status) throw new MP300Exception("MPS_ModeSelect failed", status);
status = win32Stcp250Dll.MPS_PinWrite( couplerId, Win32Stcp250Dll.PIN_CLOCK, Win32Stcp250Dll.ON);
if (RET_OK != status) throw new MP300Exception("MPS_PinWrite failed", status);
}
static AnswerToReset SCardConnect(int couplerId, int vddMillivolts, int clkHertz, int protocol, MutableInteger cyclesPerEtu) 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));
}
ShortByReference atrLenRef = new ShortByReference();
atrLenRef.setValue((short) 256);
int status;
byte atrBuf[] = new byte[256];
int timeout=win32Stcp250Dll.GetDLLTimeOutValue();
status = win32Stcp250Dll.MPS_VCCSelectMV(couplerId, vddMillivolts);
if (RET_OK != status) {
throw new MP300Exception("MPS_VCCSelectMV failed, couplerId="+couplerId+", vddMillivolts="+vddMillivolts+", Dll Timeout="+timeout, status);
}
status = win32Stcp250Dll.MPS_OnCmm(couplerId, clkHertz, atrLenRef, atrBuf);
if (RET_OK != status) {
throw new MP300Exception("MPS_OnCmm failed", status);
}
short len = atrLenRef.getValue();
AnswerToReset out=new AnswerToReset(atrBuf,0,len);
int fi=out.getSupportedFiDi()>>4;
int di=out.getSupportedFiDi()&0x0F;
//System.out.println("ATR:" + out.toString());
if(out.acceptPps() & (out.getSupportedFiDi()!=0x11)){
byte ppsBuf[] = new byte[10];
for (int i = 0; i < ppsBuf.length; i++) {
ppsBuf[i] = 0;
}
int p=0;
if(GenericTerminal.PROTOCOL_T_1==protocol)
p=1;
if(7==di){
//not supported by STAR265
byte fakeAtr[]=out.getData();
di=0x06;
fakeAtr[2]=(byte) ((out.getSupportedFiDi()&0xF0)|di);
status = win32Stcp250Dll.MPS_ChangeProtocolParameters(couplerId, win32Stcp250Dll.CPP_SIM_ATR ,fakeAtr,fakeAtr.length);
if (RET_OK != status) {
throw new MP300Exception("MPS_ChangeProtocolParameters failed",status);
}
}
status = win32Stcp250Dll.MPS_SendPPSCmm( couplerId, p, fi, di);
if (RET_OK != status) throw new MP300Exception("MPS_SendPPSCmm failed",status);
}
cyclesPerEtu.value= AnswerToReset.fiDi2cyclesPerEtu(fi, di);
return out;
}
static Apdu.CardResponse SCardTransmit(int couplerId, int command, byte[] lcData, int le) throws ScardException {
LongByReference actualLeByRef= new LongByReference();
actualLeByRef.setValue(le);
IntByReference internalSw=new IntByReference();
internalSw.setValue(0);
byte[] leData=new byte[le];
int internalLe=le;
if(0==le)
internalLe=NO_LE;
if(256==le)
internalLe=0;
int lc=lcData.length;
if(0==lc)
lc=NO_LC;
int status = win32Stcp250Dll.MPS_SendAPDU( couplerId, command, lc, lcData,
internalLe, leData, actualLeByRef,internalSw);
if (RET_OK != status) {
int timeout=win32Stcp250Dll.GetDLLTimeOutValue();
throw new MP300Exception("MPS_SendAPDU failed, timeout value="+timeout,status);
}
int actualLe=(int)actualLeByRef.getValue();
if(actualLe!=le){
byte[] actualLeData=new byte[actualLe];
for(int i=0;i<actualLe;i++)
actualLeData[i]=leData[i];
leData=actualLeData;
}
Apdu.CardResponse out=new Apdu.CardResponse(leData,(short)internalSw.getValue());
return out;
}
static void SCardDisconnect(int couplerId) throws MP300Exception {
int status = win32Stcp250Dll.MPS_OffCmm(couplerId);
if (RET_OK != status) {
throw new MP300Exception("MPS_OffCmm failed",status);
}
}
static void ScardForceDisconnection(int couplerId) throws MP300Exception {
int status = win32Stcp250Dll.MPS_ResetHard();
if (RET_OK != status) {
throw new MP300Exception("MPS_ResetHard",status);
}
}
static GenericTerminal.State SCardIsPresent(int couplerId) throws ScardException {
int status = win32Stcp250Dll.MPS_CardDetect(couplerId);
GenericTerminal.State out;
switch (status) {
case RET_OK:
out = GenericTerminal.State.CARD_PRESENT;
break;
case CRET_ABSENT:
out = GenericTerminal.State.CARD_ABSENT;
break;
default:
throw new MP300Exception("MPS_CardDetect failed", status);
}
return out;
}
static public final int NO_LC= 0x80000000; // No Lc field in CAPDU
static public final int LC_EXTENDED= 0x40000000; // Extended Lc field in CAPDU
static public final int NO_LC_SEND= 0x20000000; // The Lc field is not transmit
//
static public final int NO_LE = 0x80000000; // No Le field in CAPDU
static public final int LE_EXTENDED= 0x40000000; // Extended Le field in CAPDU
static public final int NO_LE_SEND= 0x20000000; // The Le field is not transmit
static public final int BATCH_EXECUTE_STOP_ON_ERROR=0;
static public final int BATCH_EXECUTE_IGNORE_ERRORS=1;
///*******************
// * SYSTEM API CALL *
// *******************/
//// Define programming head number
//static public final int CPL0 0
//static public final int CPL1 1
//static public final int CPL2 2
//static public final int CPL3 3
//static public final int CPL4 4
//static public final int CPL5 5
//static public final int CPL6 6
//static public final int CPL7 7
//static public final int CPL8 8
//static public final int CPL9 9
//static public final int CPL10 10
//static public final int CPL11 11
//
}