PCSC sample in OCaml

Here is the PCSC sample in OCaml language I promised in PC/SC sample in different languages.

Manuel Preliteiro wrote a OCaml PC/SC OCaml PC/SC
Binding to the PCSC standard
started in 2003 and still active in 2007. The latest version of the project is 0.6 and is still in beta but works fine according to my tests.

Installation


You first need to install OCaml. A simple apt-get install ocaml is enough on a Debian (or derivative like Ubuntu) system. Then get the ocamlpcsc-0.6.tar.gz archive from OCaml PC/SC
Binding to the PCSC standard
.

ocamlpcsc-0.6$ make
cc `pkg-config libpcsclite --cflags` -c convert.c
ocamlopt -c pcscmacros.ml
ocamlc -c pcscmacros.ml
cc -I /usr/lib/ocaml/3.10.2 `pkg-config libpcsclite --cflags` -c pcscC.c
ocamlopt -pp camlp4o -c pcscML.ml
ocamlc -custom -pp camlp4o -c pcscML.ml

Source code


I am not a Caml or OCaml expert. The example is just a modification of the example from Manuel to use my applet.

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" rvEstablishContext;
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 pioSendPci 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) ^ " : ")) pcRecvBuffer;
print_string "\n";
flush(stdout)
);

let commande2 = [|0x00; 0x00; 0x00; 0x00|] in
let dwSendLength = Array.length commande2 in

let (rvSCardTransmit, pioRecvPci, pcRecvBuffer) = sCardTransmit hCard pioSendPci 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) ^ " : ")) pcRecvBuffer;
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 pcscML.cmx pcscmacros.cmx demo.cmx **)


The last two line are the commands to execute to compile the program.

Output


Readers List: 
Gemplus GemPC Twin 00 00 :
Data transmited with success: 144 : 0 :
Data transmited with success: 72 : 101 : 108 : 108 : 111 : 32 : 119 : 111 : 114 : 108 : 100 : 33 : 144 : 0 :
Hello world!?

You can see a ? character at the end. It is the status word 0x90 0x90 badly converted in ASCII. An improvement would be to only display n-2 first characters. This is left as an exercise to the reader.

Conclusion


Nothing much to say. If you are a OCaml user you may be interested by this wrapper.

This blog entry is dedicated to Alexandre.


Flattr this
Previous
Next Post »