/*
*/
/**
*
* @author Sebastien Riou
*/
package uk.co.nimp.scard;
import uk.co.nimp.scard.log.ScardPrintStreamLogHandler;
import com.atolsystems.atolutilities.AFileUtilities;
import com.atolsystems.atolutilities.AStringUtilities;
import com.atolsystems.atolutilities.ATimeUtilities;
import com.sun.jna.ptr.IntByReference;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.smartcardio.ATR;
import javax.smartcardio.CardException;
import javax.smartcardio.CardNotPresentException;
import uk.co.nimp.smartcard.AnswerToReset;
import uk.co.nimp.smartcard.Apdu;
import uk.co.nimp.smartcard.UnexpectedCardResponseException;
import static uk.co.nimp.scard.SmartwareTerminalManager.*;
class SmartwareTerminal extends GenericContactTerminal {
final protected Win32CardDll.card_Type card;
final protected int couplerId;
final protected int model;
final public int DEFAULT_FREQUENCY=3579000;
final public int DEFAULT_VOLTAGE=5000;
//protected boolean firstConnection=true;
SmartwareTerminal(Win32CardDll.card_Type card, int model, int couplerId, String name) {
super(name);
this.couplerId = couplerId;
this.model = model;
this.card = card;
}
@Override
public boolean isCardPresent() throws ScardException {
return SCardIsPresent(card) == 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 (SCardIsPresent(card) == GenericTerminal.State.CARD_PRESENT) {
exit = true;
out = true;
}
} else {
if (SCardIsPresent(card) == 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 {
atr = SCardConnect(card, protocol, activation, negociateComSpeed);//, firstConnection);
//firstConnection=false;
if(null==vddMillivolts)
vddMillivolts=DEFAULT_VOLTAGE;
if(null==clkHertz)
clkHertz=DEFAULT_FREQUENCY;
logAtr(atr);
//TODO: retrieve the actual protocol
this.protocol = PROTOCOL_T_0;
state = State.CARD_PRESENT;
}
@Override
protected void disconnectImpl() throws ScardException {
if (GenericTerminal.State.CARD_PRESENT != state) {
return;
}
SCardDisconnect(card);
}
@Override
protected void forceDisconnectImpl() throws ScardException {
disconnectImpl();
}
@Override
public void sendApduImpl(Apdu apdu) throws ScardException, UnexpectedCardResponseException {
Apdu.CardResponse response = SCardTransmit(card, apdu);
apdu.setResponse(response);
}
@Override
public void setFrequencyImpl(int hertz) throws ScardException {
SCardSetClk(card, hertz);
}
@Override
public int getFrequencyImpl() throws ScardException {
return SCardGetClk(card);
}
@Override
public void setVoltageImpl(int millivolts) throws ScardException {
SCardSetVdd(card, millivolts);
}
@Override
protected void InitSetClkPinCapabilities(){
setClkPinCapabilities=new SetPinCapabilities(true,true,true);
}
@Override
public void setClkPinImpl(boolean high) throws ScardException {
if (high) {
SCardSetClk(card, 1000);
} else {
SCardSetClk(card, 0);
}
clkHertz=0;
}
public static void main(String[] args) throws ScardException, CardException {
String batchScriptFileName = "smartwarescript.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.initContext();
SmartwareTerminalManager manager = new SmartwareTerminalManager();
List<GenericTerminal> terminals = manager.list();
terminals = manager.list();
terminals = manager.list();
if (0 == terminals.size()) {
System.out.println("Smartware terminal not detected.");
return;
}
SmartwareTerminal terminal = (SmartwareTerminal) terminals.get(0);
terminals = manager.list();
terminal.addLogHandler(new ScardPrintStreamLogHandler(System.out));
System.out.println("Please insert a card in terminal " + terminal.getName());
while (false == terminal.isCardPresent()) {
try {
Thread.sleep(200);
} catch (InterruptedException ex) {
Logger.getLogger(SmartwareTerminal.class.getName()).log(Level.SEVERE, null, ex);
}
}
terminals = manager.list();
terminals = manager.list();
System.out.println("Try to connect to " + terminal.getName());
Apdu apdu;
terminal.coldConnect();
GenericContactTerminal contactTerminal=terminal;
contactTerminal.logFrequency();
contactTerminal.logVoltage();
apdu = new Apdu(0x00, 0x8A, 0x00, 0x44, 0x02);
terminal.sendApdu(apdu);
/*apdu = new Apdu(0x00, 0x32, 0x01, 0x03, 0x00);
terminal.sendApdu(apdu);
apdu = new Apdu(0x00, 0x7E, 0x00, 0x00, 0x00);
terminal.sendApdu(apdu);*/
apdu = new Apdu("FC39000720000010000051C000FFEEFFEE0000000802AA0051C000000010000000000800AA");
terminal.sendApdu(apdu);
terminal.logLine(ScardLogHandler.LOG_INFO, "Force clock to 5MHz");
contactTerminal.setFrequency(5000000);
contactTerminal.logFrequency(false);
contactTerminal.logFrequency(true);
if(5000000!=contactTerminal.getFrequency(true)) throw new RuntimeException();
terminal.logLine(ScardLogHandler.LOG_INFO, "Force clock to low");
contactTerminal.setClkPin(false);
contactTerminal.logFrequency(false);
contactTerminal.logFrequency(true);
if(0!=contactTerminal.getFrequency(true)) throw new RuntimeException();
terminal.logLine(ScardLogHandler.LOG_INFO, "Force clock to high");
contactTerminal.setClkPin(true);
contactTerminal.logFrequency(true);
if(0!=contactTerminal.getFrequency(true)) throw new RuntimeException();
terminal.logLine(ScardLogHandler.LOG_INFO, "Force clock to 3MHz");
contactTerminal.setFrequency(3000000);
contactTerminal.logFrequency(false);
contactTerminal.logFrequency(true);
if(3000000!=contactTerminal.getFrequency(true)) throw new RuntimeException();
terminal.logLine(ScardLogHandler.LOG_INFO, "Force voltage to 1620mV");
contactTerminal.setVoltage(1620);
contactTerminal.logVoltage();
apdu = new Apdu(0x00, 0x8A, 0x00, 0xDC, 0x01);
terminal.sendApdu(apdu);
terminal.logLine(ScardLogHandler.LOG_INFO, "Force voltage to 3000mV");
contactTerminal.setVoltage(3000);
contactTerminal.logVoltage();
terminal.sendApdu(apdu);
terminal.logLine(ScardLogHandler.LOG_INFO, "Force voltage to 4500mV");
contactTerminal.setVoltage(4500);
contactTerminal.logVoltage();
terminal.sendApdu(apdu);
terminal.disconnect();
contactTerminal.logFrequency(false);
contactTerminal.logFrequency(true);
contactTerminal.logVoltage();
terminal.connect(GenericTerminal.PROTOCOL_ANY, GenericTerminal.ACTIVATION_ANY);
terminal.sendApdu(apdu);
terminal.connect(GenericTerminal.PROTOCOL_ANY, GenericTerminal.ACTIVATION_FORCE_WARM);
terminal.sendApdu(apdu);
terminal.connect(GenericTerminal.PROTOCOL_ANY, GenericTerminal.ACTIVATION_FORCE_COLD);
terminal.sendApdu(apdu);
terminal.connect(GenericTerminal.PROTOCOL_ANY, GenericTerminal.ACTIVATION_FORCE_WARM);
terminal.sendApdu(apdu);
} /*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();*/
}
}