For Linux Developer
The reader using PC/SC Lite in Linux platform, if you are using the reader in Linux platform, you may need check your system installed latest CCID driver.
If you confirm you have install the CCID driver, make sure your pcscd service has running, and you also install the pcsclite-dev.
Programming Languages
Use C to get reader USB iSerialNumber
C for PC/SC API
#include <stdio.h>
#include <PCSC/wintypes.h>
#include <PCSC/winscard.h>
typedef unsigned int uint32_t;
#define PANIC 0
#define DONT_PANIC 1
#define SCARD_ATTR_ATR_STRING 590595
void test_rv(LONG rv, SCARDCONTEXT hContext, int dont_panic);
void test_rv(LONG rv, SCARDCONTEXT hContext, int dont_panic)
{
if (rv != SCARD_S_SUCCESS)
{
if (dont_panic)
printf( "%s (don't panic)\n" , pcsc_stringify_error(rv));
else
{
printf( "%s\n" , pcsc_stringify_error(rv));
SCardReleaseContext(hContext);
}
}
else
puts(pcsc_stringify_error(rv));
}
int main(int argc, char **argv)
{
SCARDHANDLE hCard;
SCARDCONTEXT hContext;
SCARD_READERSTATE_A rgReaderStates[1];
DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
DWORD dwPref, dwReaders = 0;
char *pcReaders, *mszReaders;
unsigned char pbAtr[MAX_ATR_SIZE];
char *mszGroups;
DWORD dwGroups = 0;
LONG rv;
DWORD i;
int p, iReader;
int iList[16];
SCARD_IO_REQUEST pioRecvPci;
SCARD_IO_REQUEST pioSendPci;
unsigned char bSendBuffer[MAX_BUFFER_SIZE];
unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
DWORD send_length, length;
printf("\nMUSCLE PC/SC Lite unitary test Program\n\n");
printf("Testing SCardEstablishContext\t: ");
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
test_rv(rv, hContext, PANIC);
printf("Testing SCardGetStatusChange \n");
printf("Please insert a working reader\t: ");
fflush(stdout);
rv = SCardGetStatusChange(hContext, INFINITE, 0, 0);
test_rv(rv, hContext, PANIC);
printf("Testing SCardListReaderGroups\t: ");
rv = SCardListReaderGroups(hContext, 0, &dwGroups);
test_rv(rv, hContext, PANIC);
printf("Testing SCardListReaderGroups\t: ");
mszGroups = calloc(dwGroups, sizeof(char));
rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
test_rv(rv, hContext, PANIC);
/*
* Have to understand the multi-string here
*/
p = 0;
for (i = 0; i+1 < dwGroups; i++)
{
++p;
printf( "Group %02d: %s\n" , p, &mszGroups[i]);
iList[p] = i;
while (mszGroups[++i] != 0) ;
}
wait_for_card_again:
printf("Testing SCardListReaders\t: ");
mszGroups = NULL;
rv = SCardListReaders(hContext, mszGroups, 0, &dwReaders);
test_rv(rv, hContext, PANIC);
printf("Testing SCardListReaders\t: ");
mszReaders = calloc(dwReaders, sizeof(char));
rv = SCardListReaders(hContext, mszGroups, mszReaders, &dwReaders);
test_rv(rv, hContext, PANIC);
/*
* Have to understand the multi-string here
*/
p = 0;
for (i = 0; i+1 < dwReaders; i++)
{
++p;
printf( "Reader %02d: %s\n" , p, &mszReaders[i]);
iList[p] = i;
while (mszReaders[++i] != 0) ;
}
if (p > 1)
do
{
char input[80];
printf("Enter the reader number\t\t: ");
fgets(input, sizeof(input), stdin);
sscanf(input, "%d", &iReader);
if (iReader > p || iReader <= 0)
printf("Invalid Value - try again\n");
}
while (iReader > p || iReader <= 0);
else
iReader = 1;
rgReaderStates[0].szReader = &mszReaders[iList[iReader]];
rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
printf("Waiting for card insertion\t: ");
fflush(stdout);
rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
test_rv(rv, hContext, PANIC);
if (SCARD_STATE_EMPTY == rgReaderStates[0].dwEventState)
{
printf("\nA reader has been connected/disconnected\n");
goto wait_for_card_again;
}
printf("Testing SCardConnect\t\t: ");
rv = SCardConnect(hContext, &mszReaders[iList[iReader]],
SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
&hCard, &dwPref);
test_rv(rv, hContext, PANIC);
switch(dwPref)
{
case SCARD_PROTOCOL_T0:
pioSendPci = *SCARD_PCI_T0;
break;
case SCARD_PROTOCOL_T1:
pioSendPci = *SCARD_PCI_T1;
break;
default:
printf("Unknown protocol\n");
return -1;
}
/* APDU select file */
printf("Select file:");
send_length = 7;
memcpy(bSendBuffer, "\x00\xA4\x00\x00\x02\x3F\x00", send_length);
for (i=0; i<send_length; i++)
printf(" %02X", bSendBuffer[i]);
printf("\n");
length = sizeof(bRecvBuffer);
printf("Testing SCardTransmit\t\t: ");
rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
&pioRecvPci, bRecvBuffer, &length);
printf("%s\n", pcsc_stringify_error(rv));
printf(" card response:" );
for (i=0; i<length; i++)
printf(" %02X", bRecvBuffer[i]);
printf("\n" );
/* APDU ramdom */
printf("Get 8 bytes Ramdom Number:");
send_length = 5;
memcpy(bSendBuffer, "\x00\x84\x00\x00\x08", send_length);
for (i=0; i<send_length; i++)
printf(" %02X", bSendBuffer[i]);
printf("\n");
length = sizeof(bRecvBuffer);
printf("Testing SCardTransmit\t\t: ");
rv = SCardTransmit(hCard, &pioSendPci, bSendBuffer, send_length,
&pioRecvPci, bRecvBuffer, &length);
printf("%s\n", pcsc_stringify_error(rv));
printf(" card response:" );
for (i=0; i<length; i++)
printf(" %02X", bRecvBuffer[i]);
printf("\n" );
printf("Testing SCardGetAttrib\t\t: ");
rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &dwAtrLen);
test_rv(rv, hContext, DONT_PANIC);
if (rv == SCARD_S_SUCCESS)
printf("SCARD_ATTR_ATR_STRING length: " "%ld\n" , dwAtrLen);
printf("Testing SCardGetAttrib\t\t: ");
dwAtrLen = sizeof(pbAtr);
rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAtr, &dwAtrLen);
test_rv(rv, hContext, DONT_PANIC);
if (rv == SCARD_S_SUCCESS)
{
printf("SCARD_ATTR_ATR_STRING: " );
for (i = 0; i < dwAtrLen; i++)
printf("%02X ", pbAtr[i]);
printf("\n" );
}
printf("Testing SCardStatus\t\t: ");
dwReaderLen = 100;
pcReaders = malloc(sizeof(char) * 100);
dwAtrLen = MAX_ATR_SIZE;
rv = SCardStatus(hCard, pcReaders, &dwReaderLen, &dwState, &dwProt,
pbAtr, &dwAtrLen);
test_rv(rv, hContext, PANIC);
printf("Current Reader Name\t\t: " "%s\n" , pcReaders);
printf("Current Reader State\t\t: " "0x%.4x\n" , dwState);
printf("Current Reader Protocol\t\t: T=" "%u\n" , dwProt - 1);
printf("Current Reader ATR Size\t\t: " "%u" " bytes\n",
dwAtrLen);
printf("Current Reader ATR Value\t: " );
for (i = 0; i < dwAtrLen; i++)
{
printf("%02X ", pbAtr[i]);
}
printf( "\n");
if (rv != SCARD_S_SUCCESS)
{
SCardDisconnect(hCard, SCARD_RESET_CARD);
SCardReleaseContext(hContext);
}
//sleep(1);
printf("Testing SCardReconnect\t\t: ");
rv = SCardReconnect(hCard, SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_UNPOWER_CARD, &dwPref);
test_rv(rv, hContext, PANIC);
printf("Testing SCardDisconnect\t\t: ");
rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
test_rv(rv, hContext, PANIC);
printf("Testing SCardReleaseContext\t: ");
rv = SCardReleaseContext(hContext);
test_rv(rv, hContext, PANIC);
printf("\n");
printf("PC/SC Test Completed Successfully !\n");
return 0;
}
GO
package main
import(
"fmt"
"github.com/ebfe/scard"
)
func main() {
// Establish a PC/SC context
context,
err: = scard.EstablishContext()
if err != nil {
fmt.Println("Error EstablishContext:", err)
return
}
// Release the PC/SC context (when needed)
defer context.Release()
// List available readers
readers,
err: = context.ListReaders()
if err != nil {
fmt.Println("Error ListReaders:", err)
return
}
// Use the first reader
reader: = readers[0]
fmt.Println("Using reader:", reader)
// Connect to the card
card,
err: = context.Connect(reader, scard.ShareShared, scard.ProtocolAny)
if err != nil {
fmt.Println("Error Connect:", err)
return
}
// Disconnect (when needed)
defer card.Disconnect(scard.LeaveCard)
// Send select APDU
var cmd_select = [] byte {
0x00,
0xa4,
0x04,
0x00,
0x0A,
0xA0,
0x00,
0x00,
0x00,
0x62,
0x03,
0x01,
0x0C,
0x06,
0x01
}
rsp,
err: = card.Transmit(cmd_select)
if err != nil {
fmt.Println("Error Transmit:", err)
return
}
fmt.Println(rsp)
// Send command APDU
var cmd_command = [] byte { 0x00, 0x00, 0x00, 0x00 }
rsp,
err = card.Transmit(cmd_command)
if err != nil {
fmt.Println("Error Transmit:", err)
return
}
fmt.Println(rsp)
for i: = 0;i < len(rsp)‐ 2;i++{
fmt.Printf("%c", rsp[i])
}
fmt.Println()
}
LUA
function hex_tostring(data)
local r = ""
local i
for i = 0, #data ‐ 1 do
r = r..string.char(data[i])
end
return r
end
if card.connect() then
card.tree_startup("ATR") ‐‐ Select applet
select = bytes.new(8, "00 A4 04 00 0A A0 00 00 00 62 03 01 0C 06 01")
sw, resp = card.send(select)
print(string.format("SW: %X", sw))
print(resp) ‐‐ Send command
command = bytes.new(8, "00 00 00 00")
sw, resp = card.send(command)
print(string.format("SW: %X", sw))
print(hex_tostring(resp))
card.disconnect()
end
JAVA
import java.util.List;
import javax.smartcardio.*;
public class Blog {
public static void main(String[] args) {
try {
// Display the list of terminals
TerminalFactory factory = TerminalFactory.getDefault();
List < CardTerminal > terminals = factory.terminals().list();
System.out.println("Terminals: " + terminals);
// Use the first terminal
CardTerminal terminal = terminals.get(0);
// Connect wit hthe card
Card card = terminal.connect("*");
System.out.println("card: " + card);
CardChannel channel = card.getBasicChannel();
// Send Select Applet command
byte[] aid = {(byte) 0xA0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0C, 0x06, 0x01 };
ResponseAPDU answer = channel.transmit(new CommandAPDU(0x00, 0xA4, 0x04, 0x00,
aid));
System.out.println("answer: " + answer.toString());
// Send test command
answer = channel.transmit(new CommandAPDU(0x00, 0x00, 0x00, 0x00));
System.out.println("answer: " + answer.toString());
byte r[] = answer.getData();
for (int i = 0; i < r.length; i++)
System.out.print((char) r[i]);
System.out.println();
// Disconnect the card
card.disconnect(false);
} catch (Exception e) {
System.out.println("Ouch: " + e.toString());
}
}
}
JavaScript(Node.js)
var pcsc = require('./lib/pcsclite');
var pcsc = pcsc();
pcsc.on('reader', function(reader) {
function exit() {
reader.close();
pcsc.close();
}
cmd_select = new Buffer([0x00, 0xA4, 0x04, 0x00, 0x0A, 0xA0, 0x00, 0x00, 0x00, 0x6
2, 0x03, 0x01, 0x0C, 0x06, 0x01
]);
cmd_command = new Buffer([0x00, 0x00, 0x00, 0x00]);
console.log('Using:', reader.name);
reader.connect(function(err, protocol) {
if (err) {
console.log(err);
return exit();
}
reader.transmit(cmd_select, 255, protocol, function(err, data) {
if (err) {
console.log(err);
return exit();
}
console.log('Data received', data);
reader.transmit(cmd_command, 255, protocol, function(err, data) {
if (err) {
console.log(err);
} else {
console.log('Data received', data);
console.log('Data received', data.toString());
}
return exit();
});
});
});
});
pcsc.on('error', function(err) {
console.log('PCSC error', err.message);
});
Lisp
code here: http://lisp.ystok.ru/ycard/
UEFI
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#include <Protocol/SmartCardReader.h>
int HelloWorld(EFI_SMART_CARD_READER_PROTOCOL * SmartCardReader) {
EFI_STATUS Status;
UINT32 ActiveProtocol;
int i;
UINT8 CAPDU_select[] = {
0x00,
0xA4,
0x04,
0x00,
0x0A,
0xA0,
0x00,
0x00,
0x00,
0x62,
0x03,
0x01,
0x0C,
0x06,
0x01
};
UINT8 CAPDU_command[] = { 0x00, 0x00, 0x00, 0x00 };
UINTN CAPDULength, RAPDULength;
UINT8 RAPDU[256 + 2];
/*
* SCardConnect
*/
Status = SmartCardReader‐ > SCardConnect(SmartCardReader,
SCARD_AM_CARD,
SCARD_CA_COLDRESET,
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &
ActiveProtocol);
if (EFI_ERROR(Status)) {
Print(L "ERROR: SCardConnect: %d\n", Status);
return 0;
}
/*
* SCardTransmit Select
*/
CAPDULength = sizeof CAPDU_select;
RAPDULength = sizeof RAPDU;
Status = SmartCardReader‐ > SCardTransmit(SmartCardReader,
CAPDU_select, CAPDULength,
RAPDU, & RAPDULength);
if (EFI_ERROR(Status)) {
Print(L "ERROR: SCardTransmit: %d\n", Status);
return 0;
}
Print(L "RAPDU: ");
for (i = 0; i < RAPDULength; i++)
Print(L "%02X ", RAPDU[i]);
Print(L "\n");
/*
* SCardTransmit Command
*/
CAPDULength = sizeof CAPDU_command;
RAPDULength = sizeof RAPDU;
Status = SmartCardReader‐ > SCardTransmit(SmartCardReader,
CAPDU_command, CAPDULength,
RAPDU, & RAPDULength);
if (EFI_ERROR(Status)) {
Print(L "ERROR: SCardTransmit: %d\n", Status);
return 0;
}
Print(L "RAPDU: ");
for (i = 0; i < RAPDULength; i++)
Print(L "%02X ", RAPDU[i]);
Print(L "\n");
for (i = 0; i < RAPDULength; i++)
Print(L "%c", RAPDU[i]);
Print(L "\n");
/*
* SCardDisconnect
*/
Status = SmartCardReader‐ > SCardDisconnect(SmartCardReader,
SCARD_CA_NORESET);
if (EFI_ERROR(Status)) {
Print(L "ERROR: SCardDisconnect: %d\n", Status);
return 0;
}
return 0;
}
INTN EFIAPI ShellAppMain(
IN UINTN Argc,
IN CHAR16 ** Argv
) {
EFI_STATUS Status;
UINTN HandleIndex, HandleCount;
EFI_HANDLE * DevicePathHandleBuffer = NULL;
EFI_SMART_CARD_READER_PROTOCOL * SmartCardReader;
/* EFI_SMART_CARD_READER_PROTOCOL */
Status = gBS‐ > LocateHandleBuffer(
ByProtocol, &
gEfiSmartCardReaderProtocolGuid,
NULL, &
HandleCount, &
DevicePathHandleBuffer);
if (EFI_ERROR(Status)) {
Print(L "ERROR: Get EFI_SMART_CARD_READER_PROTOCOL count fail.\n");
return 0;
}
Print(L "Found %d reader(s)\n", HandleCount);
for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
ZeroMem( & SmartCardReader, sizeof SmartCardReader);
Status = gBS‐ > HandleProtocol(
DevicePathHandleBuffer[HandleIndex], &
gEfiSmartCardReaderProtocolGuid,
(VOID ** ) & SmartCardReader);
if (EFI_ERROR(Status)) {
Print(L "ERROR: Open Protocol fail.\n");
gBS‐ > FreePool(DevicePathHandleBuffer);
return 0;
}
HelloWorld(SmartCardReader);
}
gBS‐ > FreePool(DevicePathHandleBuffer);
return (0);
}
Ruby
apt‐get install ruby rake rubygems libopenssl‐ruby ruby1.8‐dev
sudo gem install echoe
require 'smartcard'
context = Smartcard::PCSC::Context.new(Smartcard::PCSC::SCOPE_SYSTEM)
readers = context.list_readers nil
context.cancel# Use the first reader
reader = readers.first# Connect to the card
card = Smartcard::PCSC::Card.new(context, reader, Smartcard::PCSC::SHARE_SHARED, Smart card::PCSC::PROTOCOL_ANY)# Get the protocol to use
card_status = card.status# Select applet
aid = [0xA0, 0x00, 0x00, 0x00, 0x62, 0x03, 0x01, 0x0C, 0x06, 0x01]
select_apdu = [0x00, 0xA4, 0x04, 0x00, aid.length, aid].flatten
send_ioreq = {
Smartcard::PCSC::PROTOCOL_T0 => Smartcard::PCSC::IOREQUEST_T0,
Smartcard::PCSC::PROTOCOL_T1 => Smartcard::PCSC::IOREQUEST_T1
} [card_stat
us[: protocol]
]
recv_ioreq = Smartcard::PCSC::IoRequest.new
response = card.transmit(select_apdu.map { | byte | byte.chr }.join(''), send_ioreq, recv_ ioreq)
response_str = (0...response.length).map { | i | ' %02x' % response[i].to_i }.join('')
puts "Answer: #{response_str}\n"#
test APDU
test_apdu = [0, 0, 0, 0]
response = card.transmit(test_apdu.map { | byte | byte.chr }.join(''), send_ioreq, recv_io req)
response_str = (0...response.length).map { | i | ' %02x' % response[i].to_i }.join('')
puts "Answer: #{response_str}\n"
response_str = (0...response.length‐ 2).map { | i | '%c' % response[i].to_i }.join('')
puts "Answer: #{response_str}\n"#
Deconnect
card.disconnect Smartcard::PCSC::DISPOSITION_LEAVE
context.release
Rust
extern crate pcsc;
use pcsc:: * ;
use std::str;
fn main() {
// Establish a PC/SC context.
let ctx = Context::establish(Scope::User)
.expect("failed to establish context");
// List available readers.
let mut readers_buf = [0;2048];
let mut readers = ctx.list_readers( & mut readers_buf)
.expect("failed to list readers");
// Use the first reader.
let reader = readers.next().ok_or(())
.expect("no readers are connected");
println!("Using reader: {:?}", reader);
// Connect to the card.
let card = ctx.connect(reader, ShareMode::Shared, PROTOCOL_ANY)
.expect("failed to connect to card");
// Send an SELECT APDU command.
let apdu = b "\x00\xA4\x04\x00\x0A\xA0\x00\x00\x00\x62\x03\x01\x0C\x06\x01";
let mut rapdu_buf = [0;MAX_BUFFER_SIZE];
let rapdu = card.transmit(apdu, & mut rapdu_buf)
.expect("failed to transmit APDU to card");
println!("{:?}", rapdu);
// Send an COMMAND APDU command.
let apdu = b "\x00\x00\x00\x00";
let mut rapdu_buf = [0;MAX_BUFFER_SIZE];
let rapdu = card.transmit(apdu, & mut rapdu_buf)
.expect("failed to transmit APDU to card");
println!("{:?}", rapdu);
// remove the extra 2 SW bytes at the end
let text = & rapdu[0..rapdu.len()‐ 2];
// convert to UTF‐8 (ASCII in fact)
println!("{}", str::from_utf8( & text).unwrap());
}
Python
#! /usr/bin/env python
from smartcard.scard
import *
import smartcard.util
SELECT = [0x00, 0xA4, 0x04, 0x00, 0x0A, 0xA0, 0x00, 0x00, 0x00, 0x62,
0x03, 0x01, 0x0C, 0x06, 0x01
]
COMMAND = [0x00, 0x00, 0x00, 0x00]
try:
hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to establish context : ' +
SCardGetErrorMessage(hresult))
print 'Context established!'
try:
hresult, readers = SCardListReaders(hcontext, [])
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to list readers: ' +
SCardGetErrorMessage(hresult))
print 'PCSC Readers:', readers
if len(readers) < 1:
raise Exception('No smart card readers')
reader = readers[0]
print "Using reader:", reader
try:
hresult, hcard, dwActiveProtocol = SCardConnect(hcontext, reader,
SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
if hresult != SCARD_S_SUCCESS:
raise Exception('Unable to connect: ' +
SCardGetErrorMessage(hresult))
print 'Connected with active protocol', dwActiveProtocol
try:
hresult, response = SCardTransmit(hcard, dwActiveProtocol,
SELECT)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to transmit: ' +
SCardGetErrorMessage(hresult))
print 'Select: ' + smartcard.util.toHexString(response,
smartcard.util.HEX)
hresult, response = SCardTransmit(hcard, dwActiveProtocol,
COMMAND)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to transmit: ' +
SCardGetErrorMessage(hresult))
print 'Command: ' + smartcard.util.toHexString(response,
smartcard.util.HEX)
finally:
hresult = SCardDisconnect(hcard, SCARD_UNPOWER_CARD)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to disconnect: ' +
SCardGetErrorMessage(hresult))
print 'Disconnected'
except Exception, message:
print "Exception:", message
finally:
hresult = SCardReleaseContext(hcontext)
if hresult != SCARD_S_SUCCESS:
raise Exception('Failed to release context: ' +
SCardGetErrorMessage(hresult))
print 'Released context.'
except Exception, message:
print "Exception:", message
import sys
if 'win32' == sys.platform:
print 'press Enter to continue'
sys.stdin.read(1)
Perl
Get the source code from http://ludovic.rousseau.free.fr/softwares/pcscperl/.
The current version is 1.4.8. If
you distribution does not provide a package (Debian does with libpcscperl)
you can install it by hand using:
pcsc‐perl‐1.4.8$ perl Makefile.PL
osname: linux
LDDFLAGS:
INC: `pkg‐config ‐‐cflags libpcsclite`
Checking if your kit is complete...
Looks good
Writing Makefile for Chipcard::PCSC::Card
Writing Makefile for Chipcard::PCSC
pcsc‐perl‐1.4.7$ make
[...]
pcsc‐perl‐1.4.7$ make test
[...]
pcsc‐perl‐1.4.7$ make install
[...]
#!/usr/bin/perl ‐w
use Chipcard::PCSC;
# create a new object
$hContext = new Chipcard::PCSC();
die ("Can't create the PCSC object: $Chipcard::PCSC::errno\n")
unless defined $hContext;
# get the reader list
@ReadersList = $hContext‐>ListReaders();
die ("Can't get readers' list: $Chipcard::PCSC::errno\n")
unless defined $ReadersList[0];
# connect to the first reader
$hCard = new Chipcard::PCSC::Card($hContext, $ReadersList[0]);
die ("Can't connect: $Chipcard::PCSC::errno\n")
unless defined $hCard;
# send the Select Applet APDU
$cmd = Chipcard::PCSC::ascii_to_array("00 A4 04 00 0A A0 00 00 00 62 03 01 0C 06 01");
$RecvData = $hCard‐>Transmit($cmd);
die ("Can't transmit data: $Chipcard::PCSC::errno") unless defined $RecvData;
print Chipcard::PCSC::array_to_ascii($RecvData)."\n";
# send the test APDU
$cmd = Chipcard::PCSC::ascii_to_array("00 00 00 00");
$RecvData = $hCard‐>Transmit($cmd);
die ("Can't transmit data: $Chipcard::PCSC::errno") unless defined $RecvData;
print Chipcard::PCSC::array_to_ascii($RecvData)."\n";
$hCard‐>Disconnect();
OCaml
open Pcscmacros;;
open Printf;;
open PcscML;;
open Str;;
let func() =
let (rvEstablishContext, hContext) = sCardEstablishContext scard_scope_system()() in
if (rvEstablishContext != scard_s_success) then(
printf "SCardEstablishContext: Cannot Connect to Resource Manager %d\n"
rvEstabl ishContext; flush(stdout);
()
);
let (rvListReaders, readers) = sCardListReaders() in
printf "Readers List: \n";
Array.iter(fun z‐ > print_string(z ^ " : ")) readers;
printf "\n";
flush(stdout);
let reader1 = readers.(0) in
let (rvSCardConnect, hCard, dwActiveProtocol) = sCardConnect reader1 scard_share
_shared scard_protocol_t1 in
if (rvSCardConnect != scard_s_success) then(
printf "SCardConnect: Cannot connect to card %d\n"
rvSCardConnect; flush(stdout);
()
);
let pioSendPci = (scard_protocol_t1, 0) in
let commande1 = [ | 0x00;0xA4;0x04;0x00;0x0A;0xA0;0x00;0x00;0x00;0x62;
0x03;0x01;0x0C;0x06;0x01 |
] in
let dwSendLength = Array.length commande1 in
let (rvSCardTransmit, pioRecvPci, pcRecvBuffer) = sCardTransmit hCard pioSendP
ci commande1 dwSendLength in
if (rvSCardTransmit != scard_s_success) then(
printf "SCardTransmit: Cannot transmit to card %d\n"
rvSCardTransmit; flush(stdout);
()
)
else(
let (_, _) = pioRecvPci in
printf "Data transmited with success: "; Array.iter(fun z‐ > print_string((string_of_int z) ^ " : ")) pcRecvBuf fer; print_string "\n"; flush(stdout)
);
let commande2 = [ | 0x00;0x00;0x00;0x00 | ] in
let dwSendLength = Array.length commande2 in
let (rvSCardTransmit, pioRecvPci, pcRecvBuffer) = sCardTransmit hCard pioSen
dPci commande2 dwSendLength in
if (rvSCardTransmit != scard_s_success) then(
printf "SCardTransmit: Cannot transmit to card %d\n"
rvSCardTransmit; flush(stdout);
()
)
else(
let (_, _) = pioRecvPci in
printf "Data transmited with success: "; Array.iter(fun z‐ > print_string((string_of_int z) ^ " : ")) pcRecvB uffer; print_string "\n"; Array.iter(fun z‐ > print_char(char_of_int z)) pcRecvBuffer; print_string "\n"; flush(stdout)
);
let rvSCardDisconnect = sCardDisconnect hCard scard_leave_card in
if (rvSCardDisconnect != scard_s_success) then(
printf "SCardDisconnect: Cannot disconect card %d\n"
rvSCardDisconnect; flush(stdout);
()
);;;
let _ = func();;
( ** ocamlopt‐ c demo.ml ** )
( ** ocamlopt‐ pp camlp4o str.cmxa‐ cclib '‐lpcsclite convert.o pcscC.o'‐
o demo pcscM L.cmx pcscmacros.cmx demo.cmx ** )