Package uk.co.nimp.scard

Source Code of uk.co.nimp.scard.MP65Terminal

/**
*
* @author Sebastien Riou
*/
package uk.co.nimp.scard;

import com.atolsystems.atolutilities.AFileChooser;
import uk.co.nimp.scard.log.ScardPrintStreamLogHandler;
import com.atolsystems.atolutilities.AStringUtilities;
import com.atolsystems.atolutilities.InputFileFormatException;
import com.atolsystems.atolutilities.StopRequestFromUserException;
import com.sun.jna.ptr.IntByReference;
import java.io.*;
import java.nio.charset.Charset;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.smartcardio.CardException;
import javax.smartcardio.CardNotPresentException;
import uk.co.nimp.smartcard.Apdu;
import uk.co.nimp.smartcard.UnexpectedCardResponseException;
import static uk.co.nimp.scard.MP65TerminalManager.*;
import static uk.co.nimp.scard.MP300Exception.*;

class MP65Terminal extends GenericContactTerminal{

    final protected int couplerId;
    final protected int deviceId;
    final protected byte[] host;
   
    final static public int DEFAULT_FREQUENCY=4000000;
    final static public int DEFAULT_VOLTAGE=5000;

    int stoppedClkHertz=-1;
   
    MP65Terminal(int deviceId, int couplerId, String name, byte[] host) {
        super(name);
        this.deviceId=deviceId;
        this.couplerId = couplerId;
        this.host=host;
    }

    @Override
    public boolean isCardPresent() throws ScardException {
        return MP65TerminalManager.SCardIsPresent(deviceId, couplerId) == GenericTerminal.State.CARD_PRESENT;
    }

    private boolean waitForCard(boolean wantPresent, long timeout) throws ScardException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout must not be negative");
        }
        long start = System.currentTimeMillis();
        boolean exit = false;
        boolean out = false;
        do {
            if (wantPresent) {
                if (MP65TerminalManager.SCardIsPresent(deviceId, couplerId) == GenericTerminal.State.CARD_PRESENT) {
                    exit = true;
                    out = true;
                }
            } else {
                if (MP65TerminalManager.SCardIsPresent(deviceId, couplerId) == GenericTerminal.State.CARD_ABSENT) {
                    exit = true;
                    out = true;
                }
            }
            if ((0 != timeout) && (System.currentTimeMillis() - start < timeout)) {
                exit = true;
            }
        } while (false == exit);
        return out;
    }

    @Override
    public boolean waitForCardPresent(long timeout) throws ScardException {
        return waitForCard(true, timeout);
    }

    @Override
    public boolean waitForCardAbsent(long timeout) throws ScardException {
        return waitForCard(false, timeout);
    }

    @Override
    public void connectImpl(int protocol, int activation) throws ScardException, CardNotPresentException {
       
        try {
            if(connected && (activation==GenericTerminal.ACTIVATION_FORCE_COLD))
                SCardDisconnect(deviceId, couplerId);
            if(null==vddMillivolts){
                SCardSetVdd(deviceId, couplerId, DEFAULT_VOLTAGE);
                vddMillivolts=DEFAULT_VOLTAGE;
            }
            int hertz;
            if(null==clkHertz)
                hertz=DEFAULT_FREQUENCY;
            else
                hertz=clkHertz;
            atr = SCardConnect(deviceId, couplerId, hertz, protocol, negociateComSpeed);
            clkHertz=hertz;
            logAtr(atr);
            //TODO: retrieve the actual protocol
            this.protocol = PROTOCOL_T_0;
            state = State.CARD_PRESENT;
        } catch (MP300Exception e) {
            if (e.code == MP300Exception.CRET_ABSENT) {
                throw new CardNotPresentException("No card present", e);
            } else {
                throw new ScardException("connect() failed", e);
            }
        }
    }

    @Override
    protected void disconnectImpl() throws ScardException {
        if (GenericTerminal.State.CARD_PRESENT != state) {
            return;
        }
        SCardDisconnect(deviceId, couplerId);
    }
    @Override
    protected void forceDisconnectImpl() throws ScardException {
        if (GenericTerminal.State.CARD_PRESENT != state) {
            return;
        }
        SCardForceDisconnection(deviceId, couplerId);
    }

    @Override
    public void sendApduImpl(Apdu apdu) throws ScardException, UnexpectedCardResponseException {
        int tpduHeader = (0xFF & apdu.getCla());
        tpduHeader = (tpduHeader << 8) + (0xFF & apdu.getIns());
        tpduHeader = (tpduHeader << 8) + (0xFF & apdu.getP1());
        tpduHeader = (tpduHeader << 8) + (0xFF & apdu.getP2());
        Apdu.CardResponse response = SCardTransmit(deviceId, couplerId, tpduHeader, apdu.getLcDataAsBytes(), apdu.getExpectedLe());
       
  apdu.setResponse(response);
    }

    @Override
    public void setFrequencyImpl(int hertz) throws ScardException {
        if(stoppedClkHertz==hertz){
            stoppedClkHertz=-1;
            SCardClkStop(deviceId, couplerId, 0,0,win32Mp300ComDll.CLOCK_RESUME);
        }else
            SCardSetClk(deviceId, couplerId, hertz);
    }
    @Override
    protected void InitSetClkPinCapabilities(){
        setClkPinCapabilities=new SetPinCapabilities(true,true,true);
    }
    @Override
    public void setClkPinImpl(boolean high) throws ScardException {
        if (high) {
            SCardClkStop(deviceId, couplerId, 0,0,win32Mp300ComDll.CLOCK_STOP_HIGH);
        } else {
            SCardClkStop(deviceId, couplerId, 0,0,win32Mp300ComDll.CLOCK_STOP_LOW );
        }
        stoppedClkHertz=clkHertz;
        clkHertz=0;
    }

    @Override
    public void setVoltageImpl(int millivolts) throws ScardException {
        SCardSetVdd(deviceId, couplerId, millivolts);
    }


    String getNextCommand(BufferedReader reader) throws IOException{
        String command="";
        do{
            command=reader.readLine();
            if(null==command)
                return "";
        }while(command.isEmpty() || command.startsWith("//"));
        return command;
    }

    void execBatchScript(InputStream batchCommands, int nRun) throws ScardException, IOException {
        InputStreamReader reader = new InputStreamReader(batchCommands);
        execBatchScript(reader, nRun);
    }

    void execBatchScript(String batchCommands, int nRun) throws ScardException, IOException {
        StringReader reader = new StringReader(batchCommands);
        execBatchScript(reader, nRun);
    }

    void execBatchScript(Reader batchCommandsReader, int nRun) throws ScardException, IOException {
        int status=0;
        BufferedReader reader = new BufferedReader(batchCommandsReader);
        IntByReference pdwBatchId=new IntByReference();
        status=win32Mp300ComDll.MPS_BatchOpen(pdwBatchId);
        if (RET_OK != status) {
            throw new ScardException("MPS_BatchOpen returned " + status);
        }
        StringBuilder debug=new StringBuilder();
        int batchId=pdwBatchId.getValue();
        String command=getNextCommand(reader);
        while(false==command.isEmpty()){
            debug.append(command);

            status=win32Mp300ComDll.MPS_Add2Batch(batchId, 0, AStringUtilities.StringToBytes(command));
            if (RET_OK != status) {
                throw new ScardException("MPS_Add2Batch returned " + status);
            }
            command=getNextCommand(reader);
            if(command.startsWith("-->")){
                command=command.substring(3);
                debug.append(" --> ");
                debug.append(command);
                status=win32Mp300ComDll.MPS_AddResponse2Batch(batchId, AStringUtilities.StringToBytes(command));
                if (RET_OK != status) {
                    throw new ScardException("MPS_AddResponse2Batch returned " + status);
                }
                command=getNextCommand(reader);
            }
            debug.append("\n");
        }

        IntByReference pdwFaultyLine=new IntByReference();
        System.out.println("Start batch:");
        System.out.println(debug);
        for(int i=1;i<=nRun;i++){
            status=win32Mp300ComDll.MPS_ExecuteBatch(batchId, BATCH_EXECUTE_STOP_ON_ERROR, pdwFaultyLine);
            if (RET_OK != status) {
                throw new MP300Exception("Batch iteration "+i+": MPS_ExecuteBatch returned " + status + "\n" +
                        "pdwFaultyLine="+pdwFaultyLine.getValue(), status);
            }
            if(0==(i%25))
                System.out.print(".");
            if(0==(i%1000))
                System.out.println(i+" iterations done");
        }
        status=win32Mp300ComDll.MPS_CloseBatch(batchId);
        if (RET_OK != status) {
            throw new MP300Exception("MPS_CloseBatch returned " + status, status);
        }
        if(0!=(nRun%10))
            System.out.println(nRun+" iterations done");
        System.out.println("Batch terminated succesfully");
    }

    static void batchScriptTest(MP65Terminal terminal) throws ScardException, IOException{
        String commands=
                "CPSA 0 001C0000 00000002 01EF\n"+
                "-->CPSA 0000\n"+
                 "CPSA 0 001A0000 2\n"+
                "-->CPSA 0000\n";
        terminal.execBatchScript(commands, 1);
    }
   
    static void batchScriptFileTest(MP65Terminal terminal, File scriptFile, int nRun) throws ScardException, IOException{
        //String commands=(String) AFileUtilities.file2CharSequence(scriptFile, Charset.forName("UTF-16"));
        //terminal.execBatchScript(commands, nRun);
        InputStreamReader reader = new InputStreamReader(new FileInputStream(scriptFile), Charset.forName("UTF-16"));
        terminal.execBatchScript(reader, nRun);
    }

    //small command line app to execute Micropross remote commands from a file
    public static void mainBatch(String[] args) throws ScardException, CardException, Exception {
        String batchScriptFileName="mp65script.txt";
        int nRun=1;
        if(args.length>=1)
            batchScriptFileName=args[0];
        if(args.length>=2)
            nRun=Integer.decode(args[1]);

        //create a thread, as recommended by micropross support for stack overflow problems
        /*Thread testThread = new Thread() {

            @Override
            public void run() {
                {*/
                    try {
                        MP65TerminalManager manager = new MP65TerminalManager();
                        manager.loadConfiguration(Main.getDefaultConfFolder(), "MP65Test");
                       

                        List<GenericTerminal> terminals = manager.list();
                         terminals = manager.list();
                          terminals = manager.list();
                        if(0==terminals.size()){
                            System.out.println("MP65 terminal not detected.");
                            return;
                        }
                        MP65Terminal mp65 = (MP65Terminal) terminals.get(0);
                         terminals = manager.list();
                        mp65.addLogHandler(new ScardPrintStreamLogHandler(System.out));
                        System.out.println("Please insert a card in terminal "+ mp65.getName());
                        while(false==mp65.isCardPresent()){
                            try {
                                Thread.sleep(200);
                            } catch (InterruptedException ex) {
                                Logger.getLogger(MP65Terminal.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                         terminals = manager.list();
                          terminals = manager.list();
                        System.out.println("Try to connect to " + mp65.getName());
                        mp65.coldConnect();
                        /*Apdu apdu = new Apdu(0x00, 0x8A, 0x00, 0x44, 0x02);
                        mp65.sendApdu(apdu);*/
                        //manager.batchInterfaceTest();
                        //batchScriptTest(mp65);
                        batchScriptFileTest(mp65, new File(batchScriptFileName), nRun);
                    } catch (IOException ex) {
                        Logger.getLogger(MP65Terminal.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (ScardException ex) {
                        Logger.getLogger(MP65Terminal.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (CardException ex) {
                        Logger.getLogger(MP65Terminal.class.getName()).log(Level.SEVERE, null, ex);
                    }
              /*  }
            }
        };
        testThread.start();*/
    }
   
    public static void main(String[] args) throws Exception {
        MP65TerminalManager manager = new MP65TerminalManager();
        manager.loadConfiguration(Main.getDefaultConfFolder(), "MP65Test");


        List<GenericTerminal> terminals = manager.list();

        if(0==terminals.size()){
            System.out.println("MP65 terminal not detected.");
            return;
        }
        MP65Terminal mp65 = (MP65Terminal) terminals.get(0);
        System.out.println("Connected to " + mp65.getName());
        ScriptPlayer player = new ScriptPlayer();
        do{      
            try {  
                File script = AFileChooser.askForFile("choose a script file", false);
                if(null==script) return;
                StarScriptReader reader = new StarScriptReader(script);
                player.play(mp65, reader.getCmds());
            } catch (Throwable ex) {
                Logger.getLogger(MP65Terminal.class.getName()).log(Level.SEVERE, null, ex);
            }   
        }while(true);
    }
}
TOP

Related Classes of uk.co.nimp.scard.MP65Terminal

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.