Package uk.co.nimp.scard

Source Code of uk.co.nimp.scard.MP65TerminalManager$Win32Mp300ComDll

/**
*
* @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 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.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.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 MP65TerminalManager extends GenericTerminalManager {

public static final int  MP65=      65;


    public MP65TerminalManager(){

    }
   
    static public interface Win32Mp300ComDll extends Library {
// Functions from mp300com.dll

        //WORD MPOS_OpenResource ( DWORD ResID, BYTE CplNum, DWORD BlockingMode);
        short MPOS_OpenResource(int ResID, int CplNum, int BlockingMode);
        //WORD MPOS_CloseResource ( DWORD ResID, BYTE CplNum);

        short MPOS_CloseResource(int ResID, int CplNum);

        //WORD MPS_ResetHard(BYTE CplNum);
        short MPS_ResetHard(int CplNum);

        //void CALL SetDLLTimeOutValue(WORD timeout);
        void SetDLLTimeOutValue(int timeout);

        //WORD CALL GetDLLTimeOutValue(void);
        short GetDLLTimeOutValue();

        //int  CALL OpenCommunication(char * host);
        //int  OpenCommunication(String host);
        int OpenCommunication(byte[] host);

        //int  CALL CloseCommunication(void);
        int CloseCommunication();

        //WORD MPS_SendPPS2 (BYTE CplNum, DWORD PPS, BYTE *pPPSResponse);
        short MPS_SendPPS2(int CplNum, int PPS, byte[] pPPSResponse);
//void CALL SetDLLTimeOutValue(WORD timeout);
//WORD CALL GetDLLTimeOutValue(void);
//WORD CALL GetLastComError(void);
//int  CALL SendFrame(HANDLE hcom, int  noanswer, WORD  timeout, char * command, char * repbuf);
//int  CALL UseSequenceNumber(int onoff);
//WORD CALL StartDownloadTo (BYTE CplNum, char *pFileName);
//WORD CALL StartDownload (BYTE CplNum, PROC_DOWNLOAD pfunc, DWORD reserved, DWORD UserDefined);
//int  CALL SetDLLMode( int Flag);
        int SetDLLMode(int Flag);
//WORD CALL AbortCoupler( BYTE CplNum, char * host);
        int AbortCoupler( int CplNum, byte[] host);
//WORD MPS_CouplerAbort (BYTE CplNum);
        int MPS_CouplerAbort( int CplNum);
//WORD CALL MPS_BatchOpen( DWORD *pdwBatchId);
        short MPS_BatchOpen( IntByReference pdwBatchId);
//WORD CALL MPS_Add2Batch( DWORD dwBatchId, WORD wRetCode, char *pstrRcmd);
        short MPS_Add2Batch( int dwBatchId, int wRetCode, byte[] pstrRcmd);
//WORD MPS_AddResponse2Batch ( DWORD dwBatchId, char *pstrRcmd);
        short MPS_AddResponse2Batch ( int dwBatchId, byte[] pstrRcmd);
//WORD CALL MPS_ExecuteBatch( DWORD dwBatchId, DWORD dwExecutionMode, DWORD *pdwFaulthyLine);
        short MPS_ExecuteBatch( int dwBatchId, int dwExecutionMode, IntByReference pdwFaultyLine);
//WORD CALL MPS_CloseBatch( DWORD dwBatchId) ;
        short MPS_CloseBatch( int dwBatchId) ;
//int  CALL SelectActiveDevice(DWORD dwActDev);
        short SelectActiveDevice(int dwActDev);


//WORD StartDownloadTo (BYTE CplNum, char * pFileName)
        short StartDownloadTo (int CplNum, byte[] pFileName);
        //WORD CALL MPS_EndDownload (BYTE CplNum);
        short MPS_EndDownload(int CplNum);
        /*-----------------*
* Concurrent mode *
*-----------------*/
//WORD CALL MPS_IsoOpen (BYTE CplNum);
//WORD CALL MPS_IsoClose (BYTE CplNum);
//WORD CALL MPS_SpyOpen (BYTE CplNum);
        short MPS_SpyOpen(int CplNum);
//WORD CALL MPS_SpyClose (BYTE CplNum);
        short MPS_SpyClose(int CplNum);



/*------------*
* Spy module *
*------------*/

//WORD CALL MPS_OpenLog (BYTE CplNum, DWORD mask_event, DWORD Reserved);
        short MPS_OpenLog (int CplNum, int mask_event, int Reserved);
/*

WORD CALL MPS_SetUserEvent( BYTE CplNum, BYTE UserEventNum);
#define USER_EVENT1    0
#define USER_EVENT2    1
#define USER_EVENT3    2
#define USER_EVENT4    3
#define USER_EVENT5    4
#define USER_EVENT6    5
#define USER_EVENT7    6
#define USER_EVENT8    7

WORD CALL MPS_TriggerOut (BYTE CplNum, DWORD Event, DWORD Rfu);
#define MSK_TRIGOUT_EVENT        0x0000FFFF
  #define  TRIGOUT_NO_EVENT        0
  #define TRIGOUT_C1            1
  #define TRIGOUT_C2            2
  #define TRIGOUT_C3            3
  #define TRIGOUT_C4            4
  #define TRIGOUT_C6            5
  #define TRIGOUT_C7            6
  #define TRIGOUT_C8            7
  #define TRIGOUT_SWP_S2          8
  #define TRIGOUT_SWP_S1_LOGIC      17
  #define TRIGOUT_SWP_S2_LOGIC      18
  #define  TRIGOUT_CARD_DETECTION      21
  #define  TRIGOUT_ISO_SENSE_OUT      22  // IFD to ICC
  #define  TRIGOUT_ISO_SENSE_IN      23  // ICC to IFD
  #define TRIGOUT_SWP_UICC_SOF      32
  #define TRIGOUT_SWP_CLF_SOF        33
  #define TRIGOUT_SWP_UICC_EOF      34
  #define TRIGOUT_SWP_CLF_EOF        35
  #define  TRIGOUT_TRIGGER_IN        36
  #define  TRIGOUT_USB_SYNC        39
  #define  TRIGOUT_USB_EOP          40
  #define  TRIGOUT_MDR_IN          42
  #define  TRIGOUT_TTL_IN1          44
  #define  TRIGOUT_TTL_IN2          45
  #define  TRIGOUT_TTL_IN3          46
  #define  TRIGOUT_CLOCK_DETECTION      47
  // Following events can be activated on a specific character value
  #define TRIGOUT_ISO_CHAR_IFD      28
  #define TRIGOUT_ISO_CHAR_ICC      29
  #define TRIGOUT_SWP_CHAR_CLF      30
  #define TRIGOUT_SWP_CHAR_UICC      31
  #define TRIGOUT_SWP_CHAR_USB      41
    #define MSK_TRIGOUT_CHAR_VALUE      0xFF000000


WORD CALL MPS_FlushLog( BYTE CplNum);
*/
//WORD CALL MPS_CloseLog( BYTE CplNum);
        short MPS_CloseLog( int CplNum);

//WORD CALL MPS_LogClockSelect( BYTE CplNum, WORD Mode);
        short MPS_LogClockSelect( int CplNum, int Mode);

//WORD CALL MPS_SetClkDiv( BYTE CplNum, DWORD value);
        short MPS_SetClkDiv( int CplNum, int value);

/*
WORD CALL MPS_VccSpyStepSelect( BYTE CplNum, DWORD Pin, long StepValue);
#define VCC_SPY_MIN    10
#define VCC_SPY_MAX    5000
WORD CALL MPS_IccSpyStepSelect( BYTE CplNum, DWORD Pin, DWORD Range, long StepValue);

WORD CALL MPS_LaunchDownload (BYTE CplNum, DWORD reserved, char *target);
WORD CALL MPS_EndDownload (BYTE CplNum);
WORD CALL MPS_SetSpyMode( BYTE CplNum, DWORD Mode);
#define SPY_MODE_INTERNAL  1
#define SPY_MODE_EXTERNAL  2
WORD CALL MPS_SetSpySensitivity( BYTE CplNum, DWORD State);*/






        //WORD MPS_LedOn( BYTE LedNum, BYTE Colour);
        short MPS_LedOn(int LedNum, int Colour);
        //WORD MPS_LedOff(BYTE LedNum);

        short MPS_LedOff(int LedNum);

//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_SendPPS2 (BYTE CplNum, DWORD PPS, BYTE *pPPSResponse);
//WORD CALL MPS_SendIFSRequest( BYTE CplNum, BYTE IFSValue);
//
//// Change protocol parameters
//WORD CALL MPS_ChangeProtocolParameters( BYTE CplNum, DWORD TypeParam, void *Param, DWORD 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_ClockStop( BYTE CplNum, DWORD TgClockCount, DWORD ThClockCount,DWORD PinState);
        short MPS_ClockStop( int CplNum, int TgClockCount, int ThClockCount,int PinState);
/*-----------*
* Sequencer *
*-----------*/
// Additional pin state
static public final int CLOCK_APPLIED=  11;
static public final int CLOCK_STOP_HIGH=12;
static public final int CLOCK_STOP_LOW=  13;
static public final int CLOCK_RESUME=  14;
        //WORD MPS_CardDetect( BYTE CplNum);
        short MPS_CardDetect(int CplNum);
    }


        // Resources ID define
public static final int  SIMULATOR=    0x100// For MP300SC1 only
public static final int  SPY=        0x200// For MP300TC3 only

public static final int  PORT_SERIAL1=  1;
public static final int  PORT_SERIAL2=  2;
public static final int  PORT_USB_EP1=  101;
public static final int  PORT_USB_EP2=  102;
public static final int  C1=        201;
public static final int  C2=        207;
public static final int  C3=        67;
public static final int  CSWP=      224;
public static final int  MC1=        228;
public static final int  TC1=        202;
public static final int  TC2=        205;
public static final int  TC3=        131;
public static final int  CL1=        203;
public static final int  CL2=        206;
public static final int  TCL1=      120;
public static final int  TCL2=      122;
public static final int  MHC6=      204;
public static final int  SWPSPY=      232;
public static final int  SC1=        (SIMULATOR | SWPSPY);
public static final int  MT1=        210;
public static final int  SCL1=      200;
public static final int  TPC1=      208;




    static protected Throwable initException;
    static protected final Win32Mp300ComDll win32Mp300ComDll;
    static private final int RES_ID = MP65;

    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="Mp65TerminalManager.conf";

    //static final String DEFAULT_IP="USB";
   
    //static final String DEFAULT_MP300_DLL="MP300Com_forNimp";//MP300COM";//we should offer a way to override this in future
    static final String DEFAULT_MP300_DLL="MP300COM";   
   
    static final String DEFAULT_COM="USB";//could be something like "USB:MSQ.08.46.27" if we want to work only with this MP65
    static final int DEFAULT_COUPLER=0;

    static final int DLL_MODE=2;//allow to work with several MP65, but does not work anymore after MPManager2.0 installed
    //static final int DLL_MODE=0;
   
    static {
        Throwable ex;
        Win32Mp300ComDll trial;
        try {
            //throw new RuntimeException("MP65 DLL disabled for test");
            couplers=new HashMap<String,Integer>();
            Map<String, Object> options = new HashMap<String, Object>();
            options.put(Library.OPTION_FUNCTION_MAPPER, new StdCallFunctionMapper());
            //trial = (Win32Mp300ComDll) Native.loadLibrary("C:\\MP300COM.dll", Win32Mp300ComDll.class);
            trial = (Win32Mp300ComDll) Native.loadLibrary(DEFAULT_MP300_DLL, Win32Mp300ComDll.class, options);
            trial=(Win32Mp300ComDll) Native.synchronizedLibrary(trial);

            ex = null;
        } catch (Throwable e) {
            ex = e;
            trial = null;
        }
        win32Mp300ComDll = trial;
        initException = ex;
        if(null==ex){
            try {
                initContext();
            } catch (ScardException ex1) {
                initException = ex1;
                //Logger.getLogger(MP65TerminalManager.class.getName()).log(Level.SEVERE, null, ex1);
            }
        }
    }
    static void cleanupCoupler(int deviceId,int couplerId){
        try {
            int status=win32Mp300ComDll.SelectActiveDevice(deviceId);
            if (RET_OK != status) {
                System.out.println("SelectActiveDevice returned " + status);
                //throw new ScardException("MPOS_CloseResource returned " + status);
            }
            status=win32Mp300ComDll.MPOS_CloseResource(RES_ID, couplerId);
            if (RET_OK != status) {
                System.out.println("MPOS_CloseResource returned " + status);
                //throw new ScardException("MPOS_CloseResource returned " + status);
            }
        } catch (Throwable e) {
        }
    }
    static public void initContext() throws ScardException {
        //System.out.println("win32Mp300ComDll=" + win32Mp300ComDll);
       
        if (null != initException) {
            throw new ScardException("", initException);
        }
       
        if(2==DLL_MODE){
            int status = win32Mp300ComDll.SetDLLMode(DLL_MODE);
            if (RET_OK != status) {
                throw new MP300Exception("SetDLLMode failed", status);
            }
        }
        Runtime.getRuntime().addShutdownHook(new Thread() {

            @Override
            public void run() {
                {
                    //release all resources
                    for(Entry<Integer, Integer>coupler:toClean.entrySet()){
                        cleanupCoupler(coupler.getKey(),coupler.getValue());
                    }
                }
            }
        });
    }
    protected String getConfFileName(){
        return CONF_FILE_NAME;
    }
    @Override
    protected void loadConfigurationImpl(File argFile) throws Exception {
        if(null!=initException)
            throw new Exception(initException);
        if(null==win32Mp300ComDll)
            throw new NullPointerException(DEFAULT_MP300_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("Mp65TerminalManager 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 \"USB\", \"USB:MSQ.08.46.31\" and so on\n");
                                System.out.println(sb.toString());
                                break;
                            case ARG_ADD_COM_PORT_ID:
                                curPort=curArg.value;
                                couplers.put(curPort, DEFAULT_COUPLER);
                                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);
        }
    }

    @Override
    public List<GenericTerminal> list() throws ScardException {
        List<GenericTerminal> terminalsList = new ArrayList<GenericTerminal>();
        if(null!=initException)
            return Collections.unmodifiableList(terminalsList);

        /*win32Mp300ComDll.MPS_LedOff(LED1);
        win32Mp300ComDll.MPS_LedOn(LED1, LED_RED);
        win32Mp300ComDll.MPS_LedOff(LED1);
        win32Mp300ComDll.MPS_LedOn(LED1, LED_ORANGE);
        win32Mp300ComDll.MPS_LedOff(LED1);
        win32Mp300ComDll.MPS_LedOn(LED1, LED_GREEN);*/

       
        for(Entry<String, Integer>coupler:couplers.entrySet()){
            try {
                GenericTerminal terminal = getTerminalImpl(RES_ID, coupler.getKey(), coupler.getValue());
                terminalsList.add(terminal);
            } catch (MP300Exception e) {
            }
        }
        //listDone = true;//attempt connection only once
        return Collections.unmodifiableList(terminalsList);
    }

    public static String resourceId2Name(int resourceId){
        switch(resourceId){
            case MP65:
                return "MP65";
            case TC3:
                return "MP300TC3";
            default:
                throw new RuntimeException("unknown resourceId: "+ resourceId);
        }
    }
    public static void main(String[] args) throws MP300Exception, ScardException  {
        //String host="192.168.107.80";
        //String host="192.168.107.80:MP65";
        //String host="10779:192.168.107.80";
        //String host="MP65:192.168.107.80";
        String host="USB:MSQ.08.46.31";
        //String host="10779:MP65";
        int couplerId=0;
        int deviceId = 0;
        int resourceId=RES_ID;
        byte[] readerBytes = AStringUtilities.StringToBytesWithFinalNull(host);
        int status = win32Mp300ComDll.OpenCommunication(readerBytes);
        if (RET_OK != status)
            throw new MP300Exception("Fail to establish communication with " + host, status);
        status = win32Mp300ComDll.MPOS_OpenResource(resourceId, couplerId, OVERRIDE);
        if (RET_OK != status)
            throw new MP300Exception("Fail to establish communication with " + host, status);
        status = win32Mp300ComDll.MPS_ResetHard(couplerId);
        if (RET_OK != status) throw new MP300Exception("Fail to establish communication with " + host, status);

       
        SCardSetVdd(deviceId,couplerId,5000);
       
       
        status = win32Mp300ComDll.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);
        }
        System.out.println(out);
        win32Mp300ComDll.CloseCommunication();
    }

    private static final Map<String, Reference<GenericTerminal>> terminals = new HashMap<String, Reference<GenericTerminal>>();
    private static final Map<Integer, Integer> toClean = new HashMap<Integer, Integer>();
    private static int nextDeviceId=0;
    private static int currentDeviceId=0;
    //static boolean listDone = false;
    protected static synchronized GenericTerminal getTerminalImpl(int resourceId, String host, int couplerId) throws ScardException {
        String name = resourceId2Name(resourceId)+" on "+ host + " coupler " + couplerId;
        Reference<GenericTerminal> ref = terminals.get(name);
        GenericTerminal terminal = (ref != null) ? ref.get() : null;
        if (terminal != null) {
            try{
                terminal.isCardPresent();
                return terminal;
            }catch(Throwable e){
                terminals.remove(name);
                MP65Terminal mp65 = (MP65Terminal) terminal;
                cleanupCoupler(mp65.deviceId,mp65.couplerId);
                System.out.println("MP65 disconnected, to use it again, please restart the application.");
                return null;
            }
           
        } //else if(listDone) return null;
       
        int status;

        int bu=win32Mp300ComDll.GetDLLTimeOutValue();
        try{
            win32Mp300ComDll.SetDLLTimeOutValue(1);
            currentDeviceId=nextDeviceId;
            if(2==DLL_MODE){
                status = win32Mp300ComDll.SelectActiveDevice(currentDeviceId);
                if (RET_OK != status)
                    throw new MP300Exception("SelectActiveDevice failed: ", status);
            }
           
            byte[] readerBytes = AStringUtilities.StringToBytesWithFinalNull(host);
            status = win32Mp300ComDll.OpenCommunication(readerBytes);
            if (RET_OK != status)
                throw new MP300Exception("Fail to establish communication with " + host, status);
            status = win32Mp300ComDll.MPOS_OpenResource(resourceId, couplerId, OVERRIDE);
            if (RET_OK != status)
                throw new MP300Exception("Fail to establish communication with " + host, status);
            status = win32Mp300ComDll.MPS_ResetHard(couplerId);
            if (RET_OK != status) throw new MP300Exception("Fail to establish communication with " + host, status);

            toClean.put(currentDeviceId, couplerId);
            nextDeviceId++;

            switch(resourceId){
                case MP65:
                    terminal = new MP65Terminal(currentDeviceId, couplerId, name, readerBytes);
                    break;
                case TC3:
                    terminal = new MP300TC3Terminal(currentDeviceId, couplerId, name,readerBytes);
                    break;
            }
            terminals.put(name, new WeakReference<GenericTerminal>(terminal));
        }finally{
            win32Mp300ComDll.SetDLLTimeOutValue(bu);
        }

        return terminal;
    }
    static synchronized void setDeviceId(int deviceId) throws MP300Exception{
        if(2==DLL_MODE){
            if(deviceId!=currentDeviceId){
                int status = win32Mp300ComDll.SelectActiveDevice(deviceId);
                if (RET_OK != status) throw new MP300Exception("SelectActiveDevice failed: ", status);
                currentDeviceId=deviceId;
            }
        }
    }
    static synchronized void SCardSetVdd(int deviceId, int couplerId, int vddMillivolts) throws ScardException {
        int status;
        setDeviceId(deviceId);
        status = win32Mp300ComDll.MPS_VCCSelectMV(couplerId, vddMillivolts);
        if (RET_OK != status) {
            throw new MP300Exception("MPS_VCCSelectMV failed. deviceId = "+deviceId+", couplerId="+couplerId+", vddMillivolts = "+vddMillivolts, status);
        }
    }
    static synchronized void SCardSetClk(int deviceId, int couplerId, int clkHertz) throws ScardException {
        int status;
        setDeviceId(deviceId);
        status = win32Mp300ComDll.MPS_FrequencySelect(couplerId, clkHertz);
        if (RET_OK != status) {
            throw new MP300Exception("MPS_FrequencySelect failed", status);
        }
    }
    static synchronized void SCardClkStop(int deviceId, int couplerId,int TgClockCount, int ThClockCount,int PinState) throws ScardException {
        int status;
        setDeviceId(deviceId);
        status = win32Mp300ComDll.MPS_ClockStop(couplerId, TgClockCount, ThClockCount, PinState);
        if (RET_OK != status) {
            throw new MP300Exception("MPS_ClockStop failed", status);
        }
    }

    //static AnswerToReset SCardConnect(int couplerId, int vddMillivolts, int clkHertz, int protocol) throws ScardException {
    static synchronized AnswerToReset SCardConnect(int deviceId, int couplerId, int clkHertz, int protocol, boolean autoPps) throws ScardException {
        setDeviceId(deviceId);
        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];

        /*status = win32Mp300ComDll.MPS_VCCSelectMV(couplerId, vddMillivolts);
        if (RET_OK != status) {
            throw new MP300Exception("MPS_VCCSelectMV failed, couplerId="+couplerId+", vddMillivolts="+vddMillivolts, status);
        }*/
        status = win32Mp300ComDll.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);

        if(autoPps && out.acceptPps() && (out.getSupportedFiDi()!=0x11)){
            byte ppsBuf[] = new byte[10];
            for (int i = 0; i < ppsBuf.length; i++) {
                ppsBuf[i] = 0;
            }
            int pps=0x10000000+(out.getSupportedFiDi()<<16);
            if(GenericTerminal.PROTOCOL_T_1==protocol)
                pps|=0x01000000;
            status = win32Mp300ComDll.MPS_SendPPS2(couplerId, pps, ppsBuf);
            if (RET_OK != status) {
                throw new MP300Exception("MPS_SendPPS2 failed",status);
            }
        }
       
        return out;
    }

    static synchronized Apdu.CardResponse SCardTransmit(int deviceId, int couplerId, int command, byte[] lcData, int le) throws ScardException {
        setDeviceId(deviceId);
        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 = win32Mp300ComDll.MPS_SendAPDU( couplerId, command, lc,  lcData,
            internalLe, leData, actualLeByRef,internalSw);
        if (RET_OK != status) {
            throw new MP300Exception("MPS_SendAPDU failed",status);
        }
        int actualLe=(int)actualLeByRef.getValue();
        //if(actualLe!=internalLe){
        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 synchronized void SCardDisconnect(int deviceId, int couplerId) throws MP300Exception {
        setDeviceId(deviceId);
        int status = win32Mp300ComDll.MPS_OffCmm(couplerId);
        if (RET_OK != status) {
            throw new MP300Exception("MPS_OffCmm failed",status);
        }
    }
    static void SCardForceDisconnection(int deviceId, int couplerId) throws MP300Exception {
        setDeviceId(deviceId);
        //int status = win32Mp300ComDll.MPS_CouplerAbort(couplerId);//more complicate to use, we need to use OpenComm and CloseComm
        int status = win32Mp300ComDll.AbortCoupler(couplerId,null);
        if (RET_OK != status) {
            throw new MP300Exception("AbortCoupler failed",status);
        }
    }

    static synchronized GenericTerminal.State SCardIsPresent(int deviceId, int couplerId) throws ScardException {
        setDeviceId(deviceId);
        int status = win32Mp300ComDll.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
//
//// Define for SLOT number
//static public final int SLOT_A  0
//static public final int SLOT_B  1
//static public final int SLOT_C  2
//static public final int SLOT_D  3

    static public final int LED1 = 1;
    static public final int LED_RED = 0;
    static public final int LED_GREEN = 1;
    static public final int LED_ORANGE = 2;
    static public final int LED_OFF = 3;
    static public final int LED_MAX = 2;
    static public final int SEM_MODE_WAIT = 1;
    static public final int SEM_MODE_NO_WAIT = 0;
    // Blocking mode
    static public final int BLOCKING = SEM_MODE_WAIT;
    static public final int NOT_BLOCKING = SEM_MODE_NO_WAIT;
    static public final int CONCURRENT_MODE = 2// Only for CSWP, MC1, TC2, TC3
    static public final int OVERRIDE = 3;



    void batchInterfaceTest() throws ScardException {
        int status=0;
        IntByReference pdwBatchId=new IntByReference();
        status=win32Mp300ComDll.MPS_BatchOpen(pdwBatchId);
        if (RET_OK != status) {
            throw new ScardException("MPS_BatchOpen returned " + status);
        }
        int batchId=pdwBatchId.getValue();
        String command="CPSR 0 5 008A004402 05";
        //String command="CPSA 0 008C0000 00000002 01EF";
        status=win32Mp300ComDll.MPS_Add2Batch(batchId, 0, AStringUtilities.StringToBytes(command));
        if (RET_OK != status) {
            throw new ScardException("MPS_Add2Batch returned " + status);
        }
        String expected="CPSR 0 5 8A00089000";
        //String expected="CPSA 0000";
        status=win32Mp300ComDll.MPS_AddResponse2Batch(batchId, AStringUtilities.StringToBytes(expected));
        if (RET_OK != status) {
            throw new ScardException("MPS_AddResponse2Batch returned " + status);
        }
        IntByReference pdwFaultyLine=new IntByReference();
        status=win32Mp300ComDll.MPS_ExecuteBatch(batchId, BATCH_EXECUTE_STOP_ON_ERROR, pdwFaultyLine);
        if (RET_OK != status) {
            throw new ScardException("MPS_ExecuteBatch returned " + status + "\n" +
                    "pdwFaultyLine="+pdwFaultyLine.getValue());
        }
        status=win32Mp300ComDll.MPS_CloseBatch(batchId);
        if (RET_OK != status) {
            throw new ScardException("MPS_CloseBatch returned " + status);
        }
    }


}
TOP

Related Classes of uk.co.nimp.scard.MP65TerminalManager$Win32Mp300ComDll

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.