PCSC(3)

πŸ’– Chipcard::PCSC β€” the PCSC(3) manual page, but make it make sense πŸŽ€

okay so bestie, welcome to PCSC(3) β€” yes that's the perl section 3 manual page for Chipcard::PCSC, and no I will not be normal about it.


✨ NAME ✨

Chipcard::PCSC β€” the Smart card reader interface library. it's giving "your perl code wants to talk to a card reader" and honestly? iconic.


πŸ¦‹ SYNOPSIS πŸ¦‹

 my $hContext = new Chipcard::PCSC();

 @ReadersList = $hContext->ListReaders ();

 $hContext->GetStatusChange(\@readers_states, $timeout);

 $apdu = Chipcard::PCSC::array_to_ascii(@apdu);

 @apdu = Chipcard::PCSC::ascii_to_array($apdu);

 $hContext = undef;

like, that's the whole vibe right there. build a context, list your readers, watch for status changes, convert your APDUs, then yeet the context into the void with undef. slay.


🌸 DESCRIPTION 🌸

okay so the PCSC module implements the Chipcard::PCSC class. objects of this class are literally how you communicate with the PCSC-lite daemon (go read pcscd(1) for more info, iykyk).

PC/SC is an abstraction layer for smart card readers. it gives you a communication layer to a wide variety of smart card readers through a standardized API β€” like a universal adapter for card readers, no cap. πŸ’…

one PCSC object can talk to more than one reader through Chipcard::PCSC::Card objects. please go read Chipcard::PCSC::Card for the extended lore on how to actually talk to a smart card reader. 🫢

a PCSC object uses this one property: $pcsc_object->{hContext} β€” which is the context returned by the pcsc library. that's it, that's the property.


🧚 CONSTRUCTORS 🧚

these are the methods you can use to construct a PCSC object, bestie:

  • $hContext = new Chipcard::PCSC($scope, $remote_host);
    • $scope is the scope of the connection to the PC/SC daemon. it can be any of these:
 $Chipcard::PCSC::SCARD_SCOPE_USER     (not used by PCSClite);
 $Chipcard::PCSC::SCARD_SCOPE_TERMINAL (not used by PCSClite);
 $Chipcard::PCSC::SCARD_SCOPE_SYSTEM   Services on the local machine;
 $Chipcard::PCSC::SCARD_SCOPE_GLOBAL   Services on a remote host.
  • $remote_host is the host name of the remote machine to contact. it's only used when $scope equals $Chipcard::PCSC::SCARD_SCOPE_GLOBAL. a null value means localhost.
  • $hContext = new Chipcard::PCSC($scope); this one is literally equivalent to:
 $hContext = new Chipcard::PCSC($scope, 0);
  • $hContext = new Chipcard::PCSC(); and the no-args one is equivalent to:
 $hContext = new Chipcard::PCSC($Chipcard::PCSC::SCARD_SCOPE_SYSTEM, 0);

πŸ’€ CONSTRUCTION FAILURE πŸ’€ (it happens to the best of us)

Chipcard::PCSC constructors return an undef value when the object can't be created. so like, no object for you. 😭

$Chipcard::PCSC::errno is what you use to get more info about the error. (see the "ERROR HANDLING" section below for the full tea β˜•)


πŸ‘‘ Chipcard::PCSC METHODS πŸ‘‘

here's the full list of every method you can use with a PCSC object. no skips, no skips, periodt.

  • hContext->ListReaders( $group ); this method returns the available readers in the given $group. if it's omitted, $group defaults to a null value which means "all groups". also real talk: as of this writing, $group can safely be omitted because it's not used by PCSClite. πŸ™ˆ

on successful completion, the return value is an array of strings: one string per available reader. if an error occurred, the undef value is returned and you should use $Chipcard::PCSC::errno to get more info about the error. (see the "ERROR HANDLING" section below for more.) here's an example that describes the use of ListReaders:

 $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  ";
 print @ReadersList . "\n";
  • $hContext->GetStatusChange(\@readers_states, $timeout); okay so this method β€” $hContext->GetStatusChange(\@readers_states, $timeout) β€” uses a reference to a list of hashes. yes, hashes, plural, we're fancy.
 # create the list or readers to watch
 map { push @readers_states, ({'reader_name'=>"$_"}) } @ReadersList;

 @StatusResult = $hContext->GetStatusChange(\@readers_states);

the keys of the hash are: 'reader_name', 'current_state', 'event_state' and 'ATR'.

to detect a status change you have to first get the status and then copy the 'event_state' into the 'current_state'. the method will return when both states are different or a timeout occurs. like a vibe check but for card readers:

 @StatusResult = $hContext->GetStatusChange(\@readers_states);
 foreach $reader (@readers_states)
 {
   $reader->{current_state} = $reader->{event_state};
 }
 @StatusResult = $hContext->GetStatusChange(\@readers_states);
  • $hContext->GetStatusChange(\@readers_states); this one is equivalent to:
 $hContext->GetStatusChange(\@readers_states, 0xFFFFFFFF);

the timeout is set to infinite. infinite!! main character energy, honestly. ⭐

  • $apdu_ref = Chipcard::PCSC::ascii_to_array($apdu); Chipcard::PCSC::Card::Transmit() uses references to arrays as in and out parameters. so Chipcard::PCSC::ascii_to_array() is what you use to transform an APDU in ASCII format into a reference to an array in the good format. 🧚

example:

 $SendData = Chipcard::PCSC::ascii_to_array("00 A4 01 00 02 01 00");
  • $apdu = Chipcard::PCSC::array_to_ascii($apdu_ref); this method converts the result of a Chipcard::PCSC::Card::Transmit() into ASCII format. the round trip, bestie. πŸ”₯

example:

 $RecvData = $hCard->Transmit($SendData);
 print Chipcard::PCSC::array_to_ascii($RecvData);

πŸ”₯ ERROR HANDLING πŸ”₯

all functions from PCSC objects save the return value in a global variable called $Chipcard::PCSC::errno. so that variable literally holds the latest status of PCSC. it's the group chat's last message, basically.

it's a double-typed magical variable that behaves just like $!. means it both holds a numerical value describing the error and the corresponding string. the numerical value may change from a system to another as it depends on the PCSC library... so like, don't hardcode it, bestie. 😭

here's a small example of how to use it:

 $hContext = new Chipcard::PCSC();
 die ("Can't create the PCSC object: $Chipcard::PCSC::errno\n")
     unless (defined $hContext);

in case the last call was successful, $Chipcard::PCSC::errno contains the SCARD_S_SUCCESS status. πŸŽ€ and here's the full list of all possible error codes β€” they're defined as read-only variables within the PCSC module:

 $Chipcard::PCSC::SCARD_S_SUCCESS
 $Chipcard::PCSC::SCARD_E_CANCELLED
 $Chipcard::PCSC::SCARD_E_CANT_DISPOSE
 $Chipcard::PCSC::SCARD_E_CARD_UNSUPPORTED
 $Chipcard::PCSC::SCARD_E_DUPLICATE_READER
 $Chipcard::PCSC::SCARD_E_INSUFFICIENT_BUFFER
 $Chipcard::PCSC::SCARD_E_INVALID_ATR
 $Chipcard::PCSC::SCARD_E_INVALID_HANDLE
 $Chipcard::PCSC::SCARD_E_INVALID_PARAMETER
 $Chipcard::PCSC::SCARD_E_INVALID_TARGET
 $Chipcard::PCSC::SCARD_E_INVALID_VALUE
 $Chipcard::PCSC::SCARD_E_NO_MEMORY
 $Chipcard::PCSC::SCARD_E_NO_SERVICE
 $Chipcard::PCSC::SCARD_E_NO_SMARTCARD
 $Chipcard::PCSC::SCARD_E_NOT_READY
 $Chipcard::PCSC::SCARD_E_NOT_TRANSACTED
 $Chipcard::PCSC::SCARD_E_PCI_TOO_SMALL
 $Chipcard::PCSC::SCARD_E_PROTO_MISMATCH
 $Chipcard::PCSC::SCARD_E_READER_UNAVAILABLE
 $Chipcard::PCSC::SCARD_E_READER_UNSUPPORTED
 $Chipcard::PCSC::SCARD_E_SERVICE_STOPPED
 $Chipcard::PCSC::SCARD_E_SHARING_VIOLATION
 $Chipcard::PCSC::SCARD_E_SYSTEM_CANCELLED
 $Chipcard::PCSC::SCARD_E_TIMEOUT
 $Chipcard::PCSC::SCARD_E_UNKNOWN_CARD
 $Chipcard::PCSC::SCARD_E_UNKNOWN_READER
 $Chipcard::PCSC::SCARD_E_UNSUPPORTED_FEATURE

 $Chipcard::PCSC::SCARD_W_REMOVED_CARD
 $Chipcard::PCSC::SCARD_W_RESET_CARD
 $Chipcard::PCSC::SCARD_W_SECURITY_VIOLATION
 $Chipcard::PCSC::SCARD_W_UNPOWERED_CARD
 $Chipcard::PCSC::SCARD_W_UNRESPONSIVE_CARD
 $Chipcard::PCSC::SCARD_W_UNSUPPORTED_CARD

PCSClite users also get these (PCSClite specific) codes, lucky you:

 $Chipcard::PCSC::SCARD_INSERTED
 $Chipcard::PCSC::SCARD_REMOVED
 $Chipcard::PCSC::SCARD_RESET
 $Chipcard::PCSC::SCARD_SCOPE_GLOBAL

in addition, the wrapper defines these two:

 $Chipcard::PCSC::SCARD_P_ALREADY_CONNECTED
 $Chipcard::PCSC::SCARD_P_NOT_CONNECTED

🌈 SEE ALSO 🌈

  • the pcscd(1) manpage has useful information about PC/SC lite. go read it, bestie. πŸ“–
  • the Chipcard::PCSC::Card manpage gives information about how to communicate with a reader and the smart card inside it. that's where the ✨real✨ conversations happen.

(C) Lionel VICTOR & Ludovic ROUSSEAU, 2001-2004, GNU GPL (C) Ludovic ROUSSEAU, 2005-2008, GNU GPL


πŸ’œ AUTHORS / ACKNOWLEDGEMENT πŸ’œ

 Lionel VICTOR <lionel.victor@unforgettable.com>
               <lionel.victor@free.fr>

 Ludovic ROUSSEAU <ludovic.rousseau@free.fr>

and that's the whole page, bestie 🫢 β€” brought to you by perl v5.40.2 dated 2026-07-22, filed under PCSC(3). now go forth and talk to your smart card reader, you've got this πŸ’…βœ¨

πŸ“¦ where this page comes from