#!/usr/bin/perl # chipknip.pl: lees chipknip saldo en laatste transacties # based on # test.pl: simple sample program to test the PCSC Perl wrapper # Copyright (C) 2001 Lionel Victor, 2003,2006 Ludovic Rousseau # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # $Id: test.pl,v 1.14 2006-12-09 13:04:26 rousseau Exp $ use Chipcard::PCSC; use Chipcard::PCSC::Card; use warnings; use strict; my $hContext; my @ReadersList; my $hCard; my @StatusResult; my $tmpVal; my $SendData; my $RecvData; my $sw; #------------------------------------------------------------------------------- $hContext = new Chipcard::PCSC(); die ("Can't create the pcsc object: $Chipcard::PCSC::errno\n") unless (defined $hContext); #------------------------------------------------------------------------------- @ReadersList = $hContext->ListReaders (); die ("Can't get readers' list: $Chipcard::PCSC::errno\n") unless (defined($ReadersList[0])); $, = "\n "; $" = "\n "; #------------------------------------------------------------------------------- my (@readers_states, $reader_state, $timeout, $event_state); # create the list or readers to watch map { push @readers_states, ({'reader_name'=>"$_"}) } @ReadersList; @StatusResult = $hContext->GetStatusChange(\@readers_states); for my $i (0..$#readers_states) { print("reader: " . $readers_states[$i]{'reader_name'} . "\n"); print(" ATR: " . Chipcard::PCSC::array_to_ascii($readers_states[$i]{'ATR'}) . "\n") if (defined $readers_states[$i]{'ATR'}); print(" state:"); $event_state = $readers_states[$i]{'event_state'}; print(" state changed") if ($event_state & $Chipcard::PCSC::SCARD_STATE_CHANGED); print(" card present") if ($event_state & $Chipcard::PCSC::SCARD_STATE_PRESENT); print(" card absent") if ($event_state & $Chipcard::PCSC::SCARD_STATE_EMPTY); print(" card mute") if ($event_state & $Chipcard::PCSC::SCARD_STATE_MUTE); print("\n"); $readers_states[$i]{'current_state'} = $event_state; } if (! ($readers_states[0]{'event_state'} & $Chipcard::PCSC::SCARD_STATE_PRESENT)) { $timeout = 10 * 1000; # 10 seconds print("Insert a card in the first reader please (timeout in $timeout ms) ...\n"); @StatusResult = $hContext->GetStatusChange(\@readers_states, $timeout); print("Ok\n"); } #------------------------------------------------------------------------------- $hCard = new Chipcard::PCSC::Card ($hContext); die ("Can't create the reader object: $Chipcard::PCSC::errno\n") unless (defined($hCard)); $tmpVal = $hCard->Connect($ReadersList[0], $Chipcard::PCSC::SCARD_SHARE_SHARED); unless ($tmpVal) { # Try to reconnect and reset if connect fails warn "Connect failed: trying to reset the card:"; $tmpVal = $hCard->Reconnect ($Chipcard::PCSC::SCARD_SHARE_SHARED, $Chipcard::PCSC::SCARD_PROTOCOL_T0, $Chipcard::PCSC::SCARD_RESET_CARD); die ("Can't reconnect to the reader '$ReadersList[0]': $Chipcard::PCSC::errno\n") unless ($tmpVal); } unless ($hCard->{dwProtocol}==$Chipcard::PCSC::SCARD_PROTOCOL_T0 || $hCard->{dwProtocol}==$Chipcard::PCSC::SCARD_PROTOCOL_T1 || $hCard->{dwProtocol}==$Chipcard::PCSC::SCARD_PROTOCOL_RAW) { die "Can understand the current protocol: $hCard->{dwProtocol}"; } #------------------------------------------------------------------------------- @StatusResult = $hCard->Status(); die ("Can't get status: $Chipcard::PCSC::errno\n") unless ($StatusResult[0]); print("Reader name is $StatusResult[0]\n"); print("State: $StatusResult[1]\n"); print("Current protocol: $StatusResult[2]\n"); print("ATR: " . Chipcard::PCSC::array_to_ascii ($StatusResult[3]). "\n"); #------------------------------------------------------------------------------- die ("Can't initiate transaction: $Chipcard::PCSC::errno\n") unless ($hCard->BeginTransaction()); print("Trying chipknip..\n"); $SendData = Chipcard::PCSC::ascii_to_array ("E1 B4 00 01 05"); # cl in p1 p2 le # cl E1 # in B4 # p1 00 # p2 01 # lc ? # data null # le 05 $RecvData = $hCard->Transmit($SendData); die ("Can't transmit data: $Chipcard::PCSC::errno") unless (defined ($RecvData)); if (scalar @{$RecvData} == 7){ my $cents=65536*${$RecvData}[0]+256*${$RecvData}[1]+${$RecvData}[2]; printf "Chipknip saldo %u currency %02x%02x\n",$cents,${$RecvData}[3],${$RecvData}[4]; } print("Chipknip transactions"); # selectfile purse $SendData = Chipcard::PCSC::ascii_to_array ("BC A4 00 00 02 29 01"); $RecvData = $hCard->Transmit($SendData); die ("Can't transmit data: $Chipcard::PCSC::errno") unless (defined ($RecvData)); #readfirstrecord $SendData = Chipcard::PCSC::ascii_to_array ("E1 B6 00 01 24"); # cl in p1 p2 le $RecvData = $hCard->Transmit($SendData); die ("Can't transmit data: $Chipcard::PCSC::errno") unless (defined ($RecvData)); print "Transaction 1\n"; &parserecord($RecvData); for (my $cnt=2;$cnt<=5;$cnt++){ #readnextrecord $SendData = Chipcard::PCSC::ascii_to_array ("E1 B6 00 03 24"); # cl in p1 p2 le $RecvData = $hCard->Transmit($SendData); die ("Can't transmit data: $Chipcard::PCSC::errno") unless (defined ($RecvData)); printf "Transaction %d\n",$cnt; &parserecord($RecvData); } die ("Can't terminate transaction: $Chipcard::PCSC::errno\n") unless ($hCard->EndTransaction($Chipcard::PCSC::SCARD_LEAVE_CARD)); $tmpVal = $hCard->Disconnect($Chipcard::PCSC::SCARD_LEAVE_CARD); die ("Can't disconnect the Chipcard::PCSC object: $Chipcard::PCSC::errno\n") unless $tmpVal; $hCard = undef; $hContext = undef; # End of File # sub parserecord { my ($rcrd)=@_; printf "Type %02x Error %02x SAM_ID %02x%02x%02x%02x SAM_STAN %02x%02x%02x%02x PUR_STAN %02x%02x\n",${$rcrd}[0],${$rcrd}[1],${$rcrd}[11],${$rcrd}[12],${$rcrd}[13],${$rcrd}[14],${$rcrd}[15],${$rcrd}[16],${$rcrd}[17],${$rcrd}[18],${$rcrd}[20],${$rcrd}[21]; printf "Balance %u currency %02x%02x amount %u date %02x%02x\n",65536*${$rcrd}[2]+256*${$rcrd}[3]+${$rcrd}[4],${$rcrd}[9],${$rcrd}[10],,65536*${$rcrd}[6]+256*${$rcrd}[7]+${$rcrd}[8],${$rcrd}[27],${$rcrd}[28]; # printf "PUR_TX_TYPE = %d\n",${$rcrd}[0]; # printf "PUR_TX_ERR = %d\n",${$rcrd}[1]; # printf "PUR_BAL = %u\n",65536*${$rcrd}[2]+256*${$rcrd}[3]+${$rcrd}[4]; # printf "CHECKSUM1 = %d\n",${$rcrd}[5]; # printf "IEP_TX_AMT_TOT = %u\n",65536*${$rcrd}[6]+256*${$rcrd}[7]+${$rcrd}[8]; # printf "PUR_CURCY = %02x %02x\n",${$rcrd}[9],${$rcrd}[10]; # printf "SAM_ID = %02x %02x %02x %02x\n",${$rcrd}[11],${$rcrd}[12],${$rcrd}[13],${$rcrd}[14]; # printf "SAM_STAN = %02x %02x %02x %02x\n",${$rcrd}[15],${$rcrd}[16],${$rcrd}[17],${$rcrd}[18]; # printf "CHECKSUM2 = %d\n",${$rcrd}[19]; # printf "PUR_STAN = %02x %02x\n",${$rcrd}[20],${$rcrd}[21]; # printf "CHECKSUM3 = %d\n",${$rcrd}[22]; # printf "GEN_CHECKSUM = %d\n",${$rcrd}[23]; # printf "PUR_SAM_GEN_TOT= %02x %02x %02x\n",${$rcrd}[24],${$rcrd}[25],${$rcrd}[26]; # printf "PUR_TX_LOG_DATE= %02x %02x\n",${$rcrd}[27],${$rcrd}[28]; } sub dumprecord { my ($rcrd)=@_; printf "PUR_TX_TYPE = %d\n",${$rcrd}[0]; printf "PUR_TX_ERR = %d\n",${$rcrd}[1]; printf "PUR_BAL = %u\n",65536*${$rcrd}[2]+256*${$rcrd}[3]+${$rcrd}[4]; printf "CHECKSUM1 = %d\n",${$rcrd}[5]; printf "IEP_TX_AMT_TOT = %u\n",65536*${$rcrd}[6]+256*${$rcrd}[7]+${$rcrd}[8]; printf "PUR_CURCY = %02x %02x\n",${$rcrd}[9],${$rcrd}[10]; printf "SAM_ID = %02x %02x %02x %02x\n",${$rcrd}[11],${$rcrd}[12],${$rcrd}[13],${$rcrd}[14]; printf "SAM_STAN = %02x %02x %02x %02x\n",${$rcrd}[15],${$rcrd}[16],${$rcrd}[17],${$rcrd}[18]; printf "CHECKSUM2 = %d\n",${$rcrd}[19]; printf "PUR_STAN = %02x %02x\n",${$rcrd}[20],${$rcrd}[21]; printf "CHECKSUM3 = %d\n",${$rcrd}[22]; printf "GEN_CHECKSUM = %d\n",${$rcrd}[23]; printf "PUR_SAM_GEN_TOT= %02x %02x %02x\n",${$rcrd}[24],${$rcrd}[25],${$rcrd}[26]; printf "PUR_TX_LOG_DATE= %02x %02x\n",${$rcrd}[27],${$rcrd}[28]; }