2
% MUSCLE Smart Card Development ( http://www.linuxnet.com )
5
% David Corcoran <corcoran@linuxnet.com>
6
% Ludovic Rousseau <ludovic.rousseau@free.fr>
8
% $Id: pcsc-lite.tex,v 1.1.1.1 2004/05/11 13:44:18 rousseau Exp $
10
\documentclass[a4paper,12pt]{article}
12
\usepackage{longtable}
16
% D�tection de pdflatex
17
\ifx\pdfcompresslevel\undefined
18
% Si on fait un postscript
19
\typeout{Postscript version}
20
\usepackage[dvips]{graphicx,rotating}
21
%\usepackage[dvips,matrix,line,curve,arrow,frame]{xy}
22
\DeclareGraphicsExtensions{.eps}
26
\usepackage[pdftex]{graphicx,rotating}
27
%\usepackage[matrix,line,curve,arrow,frame]{xy}
28
\DeclareGraphicsExtensions{.jpg,.pdf}
29
\usepackage[pdftex]{hyperref}
30
\usepackage{ae,aeguill}
36
% do not number subsubsection
37
\setcounter{tocdepth}{2}
38
\setcounter{secnumdepth}{2}
40
\newcommand{\synopsis}{\subsubsection{Synopsis:}}
41
\newcommand{\parameters}{\subsubsection{Parameters:}}
42
\newcommand{\desc}{\subsubsection{Description:}}
43
\newcommand{\example}{\subsubsection{Example:}}
44
\newcommand{\returns}{\subsubsection{Returns:}}
46
\title{MUSCLE PC/SC Lite API \\ Toolkit API Reference Documentation}
47
\author{David Corcoran \& Ludovic Rousseau\\
48
\url{corcoran@linuxnet.com}, \url{ludovic.rousseau@free.fr}}
57
This toolkit and documentation is provided on an \emph{as is} basis.
58
The authors shall not be held responsible for any mishaps caused by the
61
For more information please visit \url{http://www.musclecard.com/}.
65
% space between paragraphs
68
% remove paragraph indentation
69
\addtolength{\parindent}{-\parindent}
72
\begin{tabular}{|l|l|l|}
74
0.8.7 & March 8, 2001 & latest PDF only version \\
76
0.9.0 & April 14, 2004 & reformat using \LaTeX{} and correct bugs \\
84
%---------%---------%---------%---------%---------%---------%---------
85
\section{Introduction/Overview}
87
This document contains the reference API calls for communicating to the
88
MUSCLE PC/SC Smart Card Resource Manager. PC/SC is a standard proposed by
89
the PC/SC workgroup \cite{pcsc_workgroup} which is a conglomerate of
90
representative from major smart card manufacturers and other companies.
91
This specification tries to abstract the smart card layer into a high
92
level API so that smart cards and their readers can be accessed in a
95
This toolkit was written in ANSI C that can be used with most compilers
96
and does NOT use complex and large data structures such as vectors,
97
\textit{etc}. The C API emulates the winscard API that is used on the
98
Windows platform. It is contained in the library \texttt{libpcsclite.so}
99
that is linked to your application.
101
I would really like to hear from you. If you have any feedback either on
102
this documentation or on the MUSCLE project please feel free to email me
103
at: \url{corcoran@musclecard.com}.
106
%---------%---------%---------%---------%---------%---------%---------
107
\section{Definitions}
110
%---------%---------%---------%---------%---------%---------
111
\subsection{Defined types}
113
The following is a list of commonly used type definitions in the
114
following API. These definitions and more can be found in the
115
\url{include/pcsclite.h} file.
118
\begin{longtable}{|l|l|}
120
\textrm{PC/SC type} & \textrm{C type} \\
124
BYTE & unsigned char \\
125
DWORD & unsigned long \\
127
LPBYTE & unsigned char * \\
128
LPCBYTE & const unsigned char * \\
129
LPCSTR & const char * \\
130
LPCVOID & const void * \\
132
LPDWORD & unsigned long * \\
133
LPSCARDCONTEXT & unsigned long * \\
134
LPSCARDHANDLE & unsigned long * \\
137
PSCARDCONTEXT & unsigned long * \\
138
PSCARDHANDLE & unsigned long * \\
139
RESPONSECODE & long \\
140
SCARDCONTEXT & unsigned long \\
141
SCARDHANDLE & unsigned long \\
142
ULONG & unsigned long \\
143
USHORT & unsigned short \\
144
WORD & unsigned long \\
149
%---------%---------%---------%---------%---------%---------
150
\subsection{Error codes}
153
The following is a list of commonly used errors. Since different
154
cards produce different errors they must map over to these error
158
\begin{longtable}{|l|}
162
SCARD\_E\_CANCELLED \\
163
SCARD\_E\_CANT\_DISPOSE \\
164
SCARD\_E\_CARD\_UNSUPPORTED \\
165
SCARD\_E\_DUPLICATE\_READER \\
166
SCARD\_E\_INSUFFICIENT\_BUFFER \\
167
SCARD\_E\_INVALID\_ATR \\
168
SCARD\_E\_INVALID\_HANDLE \\
169
SCARD\_E\_INVALID\_PARAMETER \\
170
SCARD\_E\_INVALID\_TARGET \\
171
SCARD\_E\_INVALID\_VALUE \\
172
SCARD\_E\_NO\_MEMORY \\
173
SCARD\_E\_NO\_SERVICE \\
174
SCARD\_E\_NO\_SMARTCARD \\
175
SCARD\_E\_NOT\_READY \\
176
SCARD\_E\_NOT\_TRANSACTED \\
177
SCARD\_E\_PCI\_TOO\_SMALL \\
178
SCARD\_E\_PROTO\_MISMATCH \\
179
SCARD\_E\_READER\_UNAVAILABLE \\
180
SCARD\_E\_READER\_UNSUPPORTED \\
181
SCARD\_E\_SERVICE\_STOPPED \\
182
SCARD\_E\_SHARING\_VIOLATION \\
183
SCARD\_E\_SYSTEM\_CANCELLED \\
185
SCARD\_E\_UNKNOWN\_CARD \\
186
SCARD\_E\_UNKNOWN\_READER \\
187
SCARD\_F\_COMM\_ERROR \\
188
SCARD\_F\_INTERNAL\_ERROR \\
189
SCARD\_F\_UNKNOWN\_ERROR \\
190
SCARD\_F\_WAITED\_TOO\_LONG \\
192
SCARD\_W\_UNSUPPORTED\_CARD \\
193
SCARD\_W\_UNRESPONSIVE\_CARD \\
194
SCARD\_W\_UNPOWERED\_CARD \\
195
SCARD\_W\_RESET\_CARD \\
196
SCARD\_W\_REMOVED\_CARD \\
202
%---------%---------%---------%---------%---------%---------%---------
203
\section{API Routines}
205
These routines specified here are winscard routines like those in the
206
winscard API provided under Windows{\textregistered}. These are
207
compatible with the Microsoft{\textregistered} API calls. This list of
208
calls is mainly an abstraction of readers. It gives a common API for
209
communication to most readers in a homogeneous fashion.
211
Since all functions can produce a wide array of errors, please refer to
212
\S~\vref{Error codes} for a list of error returns.
214
For a human readable representation of an error the function
215
\url{pcsc_stringify_error()} is declared in \texttt{pcsclite.h}.
216
This function is not available on Microsoft{\textregistered} winscard
217
API and is pcsc-lite specific.
220
%---------%---------%---------%---------%---------%---------
221
\subsection{SCardEstablishContext}
225
#include <winscard.h>
227
LONG SCardEstablishContext(DWORD dwScope,
230
LPSCARDCONTEXT phContext);
236
\texttt{dwScope} & IN & Scope of the establishment \\
237
& & This can either be a local or remote connection\\
239
\texttt{pvReserved1} & IN & Reserved for future use. Can be used for remote
242
\texttt{pvReserved2} & IN & Reserved for future use \\
243
\texttt{phContext} & OUT & Returned reference to this connection \\
248
This function creates a communication context to the PC/SC Resource
249
Manager. This must be the first function called in a PC/SC application.
251
\begin{tabular}{|l|l|}
253
Value of \texttt{dwScope} & Meaning\\
256
\texttt{SCARD\_SCOPE\_USER} & Not used\\
258
\texttt{SCARD\_SCOPE\_TERMINAL} & Not used\\
260
\texttt{SCARD\_SCOPE\_GLOBAL} & Not used\\
262
\texttt{SCARD\_SCOPE\_SYSTEM} & Services on the local machine\\
266
% Note: If \texttt{SCARD\_SCOPE\_GLOBAL} is used then \texttt{pvReserved1}
267
% is a string that is the hostname of the machine which the Resource
268
% Manager services reside. If \texttt{NULL} is specified then it defaults
273
SCARDCONTEXT hContext;
276
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
282
\texttt{SCARD\_S\_SUCCESS} & Successful\\
283
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid scope type passed
287
%---------%---------%---------%---------%---------%---------
288
\subsection{SCardReleaseContext}
292
#include <winscard.h>
294
LONG SCardReleaseContext(SCARDCONTEXT hContext);
300
\texttt{hContext} & IN & Connection context to be closed
305
This function destroys a communication context to the PC/SC Resource
306
Manager. This must be the last function called in a PC/SC application.
310
SCARDCONTEXT hContext;
313
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
314
rv = SCardReleaseContext(hContext);
320
\texttt{SCARD\_S\_SUCCESS} & Successful\\
321
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle
325
%---------%---------%---------%---------%---------%---------
326
\subsection{SCardListReaders}
330
#include <winscard.h>
332
LONG SCardListReaders(SCARDCONTEXT hContext,
335
LPDWORD pcchReaders);
341
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
342
\texttt{mszGroups} & IN & List of groups to list readers (not used)\\
343
\texttt{mszReaders} & OUT & Multi-string with list of readers\\
344
\texttt{pcchReaders} & INOUT & Size of multi-string buffer including NULL's
349
This function returns a list of currently available readers on the
350
system. \texttt{mszReaders} is a pointer to a character string that is
351
allocated by the application. If the application sends
352
\texttt{mszGroups} and \texttt{mszReaders} as \texttt{NULL} then this
353
function will return the size of the buffer needed to allocate in
354
\texttt{pcchReaders}.
356
The reader names is a multi-string and separated by a nul character
357
(\verb+'\0'+) and ended by a double nul character.
358
\verb+"Reader A\0Reader B\0\0"+.
362
SCARDCONTEXT hContext;
367
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
368
rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
369
mszReaders = (LPSTR)malloc(sizeof(char)*dwReaders);
370
rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
376
\texttt{SCARD\_S\_SUCCESS} & Successful \\
377
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid Scope Handle\\
378
\texttt{SCARD\_E\_INSUFFICIENT\_BUFFER} & Reader buffer not large enough
382
%---------%---------%---------%---------%---------%---------
383
\subsection{SCardListReaderGroups}
387
#include <winscard.h>
389
LONG SCardListReaderGroups(SCARDCONTEXT hContext,
397
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
398
\texttt{mszGroups} & OUT & List of groups to list readers\\
399
\texttt{pcchGroups} & INOUT & Size of multi-string buffer including NULL's
404
This function returns a list of currently available reader groups on the
405
system. \texttt{mszGroups} is a pointer to a character string that is
406
allocated by the application. If the application sends
407
\texttt{mszGroups} as \texttt{NULL} then this function will return the
408
size of the buffer needed to allocate in \texttt{pcchGroups}.
410
The group names is a multi-string and separated by a nul character
411
(\verb+'\0'+) and ended by a double nul character.
412
\verb+"SCard$DefaultReaders\0Group 2\0\0"+.
416
SCARDCONTEXT hContext;
421
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
422
rv = SCardListReaderGroups(hContext, NULL, &dwGroups);
423
mszGroups = (LPSTR)malloc(sizeof(char)*dwGroups);
424
rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
430
\texttt{SCARD\_S\_SUCCESS} & Successful \\
431
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid Scope Handle\\
432
\texttt{SCARD\_E\_INSUFFICIENT\_BUFFER} & Reader buffer not large enough
436
%---------%---------%---------%---------%---------%---------
437
\subsection{SCardConnect}
441
#include <winscard.h>
443
LONG SCardConnect(SCARDCONTEXT hContext,
446
DWORD dwPreferredProtocols,
447
LPSCARDHANDLE phCard,
448
LPDWORD pdwActiveProtocol);
454
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
455
\texttt{szReader} & IN & Reader name to connect to\\
456
\texttt{dwShareMode} & IN & Mode of connection type: exclusive or shared\\
457
\texttt{dwPreferredProtocols} & IN & Desired protocol use\\
458
\texttt{phCard} & OUT & Handle to this connection\\
459
\texttt{pdwActiveProtocol} & OUT & Established protocol to this connection.
464
This function establishes a connection to the friendly name of
465
the reader specified in \texttt{szReader}. The first connection will
466
power up and perform a reset on the card.
468
\begin{tabular}{|l|l|}
470
Value of \texttt{dwScope} & Meaning\\
473
\texttt{SCARD\_SHARE\_SHARED} & This application will allow others to share the reader \\
475
\texttt{SCARD\_SHARE\_EXCLUSIVE} & This application will NOT allow
476
others to share the reader \\
478
\texttt{SCARD\_SHARE\_DIRECT} & not used \\
483
\begin{tabular}{|l|l|}
485
Value of \texttt{dwPreferredProtocols} & Meaning \\
488
\texttt{SCARD\_PROTOCOL\_T0} & Use the T=0 protocol \\
490
\texttt{SCARD\_PROTOCOL\_T1} & Use the T=1 protocol \\
492
\texttt{SCARD\_PROTOCOL\_RAW} & Use with memory type cards \\
500
SCARDCONTEXT hContext;
502
DWORD dwActiveProtocol;
505
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
506
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
507
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
513
\texttt{SCARD\_S\_SUCCESS} & Successful\\
514
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle\\
515
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid sharing mode, requested protocol, or reader name\\
516
\texttt{SCARD\_E\_NOT\_READY} & Could not allocate the desired port\\
517
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & Could not power up the reader or card\\
518
\texttt{SCARD\_E\_SHARING\_VIOLATION} & Someone else has exclusive rights\\
519
\texttt{SCARD\_E\_UNSUPPORTED\_FEATURE} & Protocol not supported\\
523
%---------%---------%---------%---------%---------%---------
524
\subsection{SCardReconnect}
529
#include <winscard.h>
531
LONG SCardReconnect(SCARDHANDLE hCard,
533
DWORD dwPreferredProtocols,
534
DWORD dwInitialization,
535
LPDWORD pdwActiveProtocol);
541
\texttt{hCard} & IN & Handle to a previous call to connect\\
542
\texttt{dwShareMode} & IN & Mode of connection type: exclusive/shared\\
543
\texttt{dwPreferredProtocols} & IN & Desired protocol use\\
544
\texttt{dwInitialization} & IN & Desired action taken on the card/reader\\
545
\texttt{pdwActiveProtocol} & OUT & Established protocol to this connection\\
550
This function reestablishes a connection to a reader that was previously
551
connected to using \texttt{SCardConnect()}. In a multi application
552
environment it is possible for an application to reset the card in
553
shared mode. When this occurs any other application trying to access
554
certain commands will be returned the value
555
\texttt{SCARD\_W\_RESET\_CARD}. When this occurs
556
\texttt{SCardReconnect()} must be called in order to acknowledge that
557
the card was reset and allow it to change it's state accordingly.
560
\begin{tabular}{|l|l|}
562
Value of \texttt{dwShareMode} & Meaning \\
565
\texttt{SCARD\_SHARE\_SHARED} & This application will allow others to share the
568
\texttt{SCARD\_SHARE\_EXCLUSIVE} & This application will NOT allow others to
573
\begin{tabular}{|l|l|}
575
Value of \texttt{dwPreferredProtocols} & Meaning \\
578
\texttt{SCARD\_PROTOCOL\_T0} & Use the T=0 protocol \\
580
\texttt{SCARD\_PROTOCOL\_T1} & Use the T=1 protocol \\
582
\texttt{SCARD\_PROTOCOL\_RAW} & Use with memory type cards \\
586
\begin{tabular}{|l|l|}
588
Value of \texttt{dwInitialization} & Meaning \\
591
\texttt{SCARD\_LEAVE\_CARD} & Do nothing \\
593
\texttt{SCARD\_RESET\_CARD} & Reset the card (warm reset) \\
595
\texttt{SCARD\_UNPOWER\_CARD} & Unpower the card (cold reset) \\
597
\texttt{SCARD\_EJECT\_CARD} & Eject the card \\
605
SCARDCONTEXT hContext;
607
DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
609
BYTE pbRecvBuffer[10];
610
BYTE pbSendBuffer[] = {0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00};
612
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
613
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
614
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
615
dwSendLength = sizeof(pbSendBuffer);
616
dwRecvLength = sizeof(pbRecvBuffer);
617
rv = SCardTransmit(hCard, SCARD_PCI_T0, pbSendBuffer, dwSendLength,
618
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
620
/* Card has been reset by another application */
621
if (rv == SCARD_W_RESET_CARD)
623
rv = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0,
624
SCARD_RESET_CARD, &dwActiveProtocol);
632
\texttt{SCARD\_S\_SUCCESS} & Successful\\
633
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
634
\texttt{SCARD\_E\_NOT\_READY} & Could not allocate the desired port\\
635
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid sharing mode, requested protocol, or reader name\\
636
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
637
\texttt{SCARD\_E\_UNSUPPORTED\_FEATURE} & Protocol not supported\\
638
\texttt{SCARD\_E\_SHARING\_VIOLATION} & Someone else has exclusive rights\\
642
%---------%---------%---------%---------%---------%---------
643
\subsection{SCardDisconnect}
648
#include <winscard.h>
650
LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition);
656
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect} \\
657
\texttt{dwDisposition} & IN & Reader function to execute \\
662
This function terminates a connection to the connection made through
663
SCardConnect. dwDisposition can have the following values:
665
\begin{tabular}{|l|l|}
667
Value of \texttt{dwDisposition} & Meaning \\
670
\texttt{SCARD\_LEAVE\_CARD} & Do nothing\\
671
\texttt{SCARD\_RESET\_CARD} & Reset the card (warm reset) \\
672
\texttt{SCARD\_UNPOWER\_CARD} & Unpower the card (cold reset) \\
673
\texttt{SCARD\_EJECT\_CARD} & Eject the card\\
679
SCARDCONTEXT hContext;
681
DWORD dwActiveProtocol;
684
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
685
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
686
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
687
rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
693
\texttt{SCARD\_S\_SUCCESS} & Successful \\
694
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle \\
695
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid \texttt{dwDisposition} \\
699
%---------%---------%---------%---------%---------%---------
700
\subsection{SCardBeginTransaction}
704
#include <winscard.h>
706
LONG SCardBeginTransaction(SCARDHANDLE hCard);
712
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect} \\
717
This function establishes a temporary exclusive access mode for doing a
718
series of commands or transaction. You might want to use this when you
719
are selecting a few files and then writing a large file so you can make
720
sure that another application will not change the current file. If
721
another application has a lock on this reader or this application is in
722
\texttt{SCARD\_SHARE\_EXCLUSIVE} there will be no action taken.
727
SCARDCONTEXT hContext;
729
DWORD dwActiveProtocol;
732
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
733
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
734
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
735
rv = SCardBeginTransaction(hCard);
737
/* Do some transmit commands */
743
\texttt{SCARD\_S\_SUCCESS} & Successful\\
744
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
745
\texttt{SCARD\_E\_SHARING\_VIOLATION} & Someone else has exclusive rights\\
746
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
750
%---------%---------%---------%---------%---------%---------
751
\subsection{SCardEndTransaction}
756
#include <winscard.h>
758
LONG SCardEndTransaction(SCARDHANDLE hCard,
759
DWORD dwDisposition);
765
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect}\\
766
\texttt{dwDisposition} & IN & Action to be taken on the reader\\
771
This function ends a previously begun transaction. The calling
772
application must be the owner of the previously begun transaction or an
773
error will occur. \texttt{dwDisposition} can have the following values:
774
The disposition action is not currently used in this release.
776
\begin{tabular}{|l|l|}
778
Value of dwDisposition & Meaning \\
781
\texttt{SCARD\_LEAVE\_CARD} & Do nothing\\
782
\texttt{SCARD\_RESET\_CARD} & Reset the card\\
783
\texttt{SCARD\_UNPOWER\_CARD} & Unpower the card\\
784
\texttt{SCARD\_EJECT\_CARD} & Eject the card\\
792
SCARDCONTEXT hContext;
794
DWORD dwActiveProtocol;
797
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
798
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
799
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
800
rv = SCardBeginTransaction(hCard);
802
/* Do some transmit commands */
804
rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
810
\texttt{SCARD\_S\_SUCCESS} & Successful\\
811
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
812
\texttt{SCARD\_E\_SHARING\_VIOLATION} & Someone else has exclusive rights\\
813
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
817
%---------%---------%---------%---------%---------%---------
818
\subsection{SCardTransmit}
823
#include <winscard.h>
825
LONG SCardTransmit(SCARDHANDLE hCard,
826
LPCSCARD_IO_REQUEST pioSendPci,
827
LPCBYTE pbSendBuffer,
829
LPSCARD_IO_REQUEST pioRecvPci,
831
LPDWORD pcbRecvLength);
837
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect} \\
838
\texttt{pioSendPci} & INOUT & Structure of protocol information\\
839
\texttt{pbSendBuffer} & IN & APDU to send to the card\\
840
\texttt{cbSendLength} & IN & Length of the APDU\\
841
\texttt{pioRecvPci} & INOUT & Structure of protocol information\\
842
\texttt{pbRecvBuffer} & OUT & Response from the card\\
843
\texttt{pcbRecvLength} & INOUT & Length of the response\\
848
This function sends an APDU to the smart card contained in the reader
849
connected to by \texttt{SCardConnect()}. The card responds from the
850
APDU and stores this response in \texttt{pbRecvBuffer} and it's length
851
in \texttt{SpcbRecvLength}. \texttt{SSendPci} and \texttt{SRecvPci} are
852
structures containing the following:
856
DWORD dwProtocol; /* SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1 */
857
DWORD cbPciLength; /* Length of this structure - not used */
861
\begin{tabular}{|l|l|}
863
Value of \texttt{pioSendPci} & Meaning \\
866
\texttt{SCARD\_PCI\_T0} & Pre defined T=0 PCI structure\\
867
\texttt{SCARD\_PCI\_T1} & Pre defined T=1 PCI structure\\
875
SCARDCONTEXT hContext;
877
DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
878
SCARD_IO_REQUEST pioRecvPci;
879
BYTE pbRecvBuffer[10];
880
BYTE pbSendBuffer[] = { 0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };
882
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
883
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
884
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
885
dwSendLength = sizeof(pbSendBuffer);
886
dwRecvLength = sizeof(pbRecvBuffer);
887
rv = SCardTransmit(hCard, SCARD_PCI_T0, pbSendBuffer, dwSendLength,
888
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
894
\texttt{SCARD\_S\_SUCCESS} & Successful\\
895
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
896
\texttt{SCARD\_E\_NOT\_TRANSACTED} & APDU exchange not successful\\
897
\texttt{SCARD\_E\_PROTO\_MISMATCH} & Connect protocol is different than desired\\
898
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid Protocol, reader name, etc\\
899
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
900
\texttt{SCARD\_W\_RESET\_CARD} & The card has been reset by another application\\
901
\texttt{SCARD\_W\_REMOVED\_CARD} & The card has been removed from the reader\\
905
%---------%---------%---------%---------%---------%---------
906
\subsection{SCardControl}
911
#include <winscard.h>
913
LONG SCardControl(SCARDHANDLE hCard,
915
LPCBYTE pbSendBuffer,
919
LPDWORD lpBytesReturned);
925
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect}\\
926
\texttt{dwControlCode} & IN & Control code for the operation \\
927
\texttt{pbSendBuffer} & IN & Command to send to the reader\\
928
\texttt{cbSendLength} & IN & Length of the command\\
929
\texttt{pbRecvBuffer} & OUT & Response from the reader\\
930
\texttt{pcbRecvLength} & IN & Length of the response buffer\\
931
\texttt{lpBytesReturned} & OUT & Length of the response\\
936
This function sends a command directly to the IFD Handler to be
937
processed by the reader. This is useful for creating client side reader
938
drivers for functions like PIN pads, biometrics, or other extensions to
939
the normal smart card reader that are not normally handled by PC/SC.
941
Note: the API of this function changed. In pcsc-lite 1.2.0 and before
942
the API was not Windows{\textregistered} PC/SC compatible. This has been
949
SCARDCONTEXT hContext;
951
DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
952
BYTE pbRecvBuffer[10];
953
BYTE pbSendBuffer[] = { 0x06, 0x00, 0x0A, 0x01, 0x01, 0x10 0x00 };
955
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
956
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
957
SCARD_PROTOCOL_RAW &hCard, &dwActiveProtocol);
958
dwSendLength = sizeof(pbSendBuffer);
959
dwRecvLength = sizeof(pbRecvBuffer);
960
rv = SCardControl(hCard, 0x42000001, pbSendBuffer, dwSendLength,
961
pbRecvBuffer, sizeof(pbRecvBuffer), &dwRecvLength);
967
\texttt{SCARD\_S\_SUCCESS} & Successful\\
968
\texttt{SCARD\_E\_NOT\_TRANSACTED} & Data exchange not successful\\
969
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
970
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid value was presented\\
971
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
972
\texttt{SCARD\_W\_RESET\_CARD} & The card has been reset by another application\\
973
\texttt{SCARD\_W\_REMOVED\_CARD} & The card has been removed from the reader\\
977
%---------%---------%---------%---------%---------%---------
978
\subsection{SCardStatus}
983
#include <winscard.h>
985
LONG SCardStatus(SCARDHANDLE hCard,
987
LPDWORD pcchReaderLen,
997
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect} \\
998
\texttt{szReaderName} & INOUT & Friendly name of this reader\\
999
\texttt{pcchReaderLen} & INOUT & Size of the \texttt{szReaderName} multistring\\
1000
\texttt{pdwState} & OUT & Current state of this reader\\
1001
\texttt{pdwProtocol} & OUT & Current protocol of this reader\\
1002
\texttt{pbAtr} & OUT & Current ATR of a card in this reader\\
1003
\texttt{pcbAtrLen} & OUT & Length of ATR\\
1008
This function returns the current status of the reader connected to by
1009
\texttt{hCard}. It's friendly name will be stored in
1010
\texttt{szReaderName}. \texttt{pcchReaderLen} will be the size of the
1011
allocated buffer for \texttt{szReaderName}. If this is too small the
1012
function will return with the necessary size in \texttt{pcchReaderLen}.
1013
The current state, and protocol will be stored in \texttt{pdwState} and
1014
\texttt{pdwProtocol} respectively. \texttt{pdwState} is a
1015
\texttt{DWORD} possibly OR'd with the following values:
1018
\begin{tabular}{|l|p{12cm}|}
1020
Value of \texttt{pdwState} & Meaning \\
1023
\texttt{SCARD\_ABSENT} & There is no card in the reader\\
1024
\texttt{SCARD\_PRESENT} & There is a card in the reader, but it has not been moved into position for use\\
1025
\texttt{SCARD\_SWALLOWED} & There is a card in the reader in position for use. The card is not powered\\
1026
\texttt{SCARD\_POWERED} & Power is being provided to the card, but the reader driver is unaware of the mode of the card\\
1027
\texttt{SCARD\_NEGOTIABLE} & The card has been reset and is awaiting PTS negotiation\\
1028
\texttt{SCARD\_SPECIFIC} & The card has been reset and specific communication protocols have been established\\
1032
\begin{tabular}{|l|l|}
1034
Value of \texttt{dwPreferredProtocols} & Meaning \\
1037
\texttt{SCARD\_PROTOCOL\_T0} & Use the T=0 protocol\\
1038
\texttt{SCARD\_PROTOCOL\_T1} & Use the T=1 protocol\\
1045
SCARDCONTEXT hContext;
1047
DWORD dwActiveProtocol;
1048
DWORD dwState, dwProtocol, dwAtrLen, dwReaderLen;
1049
BYTE pbAtr[MAX_ATR_SIZE];
1051
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
1052
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
1053
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
1054
dwAtrLen = sizeof(pbAtr);
1055
rv=SCardStatus(hCard, NULL, &dwReaderLen, &dwState, &dwProtocol,
1062
\texttt{SCARD\_S\_SUCCESS} & Successful\\
1063
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
1064
\texttt{SCARD\_E\_INSUFFICIENT\_BUFFER} & Not enough allocated memory for \texttt{szReaderName}\\
1065
& or for \texttt{pbAtr} \\
1066
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
1070
%---------%---------%---------%---------%---------%---------
1071
\subsection{SCardGetStatusChange}
1076
#include <winscard.h>
1078
LONG SCardGetStatusChange(SCARDCONTEXT hContext,
1080
LPSCARD_READERSTATE rgReaderStates,
1087
\begin{tabular}{lll}
1088
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
1089
\texttt{dwTimeout} & IN & Maximum block waiting time for status change, zero for infinite\\
1090
\texttt{rgReaderStates} & INOUT & Structures of readers with current states\\
1091
\texttt{cReaders} & IN & Number of structures\\
1096
This function receives a structure or list of structures containing
1097
reader names. It then blocks for a change in state to occur on any of
1098
the OR'd values contained in \texttt{dwCurrentState} for a maximum
1099
blocking time of \texttt{dwTimeout} or forever if \texttt{INFINITE} is
1100
used. The new event state will be contained in \texttt{dwEventState}.
1101
A status change might be a card insertion or removal event, a change in
1104
This function will block for reader availability if \texttt{cReaders} is
1105
equal to zero and \texttt{rgReaderStates} is \texttt{NULL}.
1109
LPCTSTR szReader; /* Reader name */
1110
LPVOID pvUserData; /* User defined data */
1111
DWORD dwCurrentState; /* Current state of reader */
1112
DWORD dwEventState; /* Reader state after a state change */
1113
DWORD cbAtr; /* ATR Length, usually MAX_ATR_SIZE */
1114
BYTE rgbAtr[MAX_ATR_SIZE]; /* ATR Value */
1115
} SCARD_READERSTATE;
1117
typedef SCARD_READERSTATE *PSCARD_READERSTATE, **LPSCARD_READERSTATE;
1120
\begin{tabular}{|p{5cm}|p{10.5cm}|}
1122
Value of \texttt{dwCurrentState} and \texttt{dwEventState} & Meaning \\
1125
\texttt{SCARD\_STATE\_UNAWARE} & The application is unaware of the
1126
current state, and would like to know. The use of this value results in
1127
an immediate return from state transition monitoring services. This is
1128
represented by all bits set to zero\\
1130
\texttt{SCARD\_STATE\_IGNORE} & This reader should be ignored\\
1131
\texttt{SCARD\_STATE\_CHANGED} & There is a difference between the state
1132
believed by the application, and the state known by the resource
1133
manager. When this bit is set, the application may assume a significant
1134
state change has occurred on this reader\\
1136
\texttt{SCARD\_STATE\_UNKNOWN} & The given reader name is not recognized
1137
by the resource manager. If this bit is set, then
1138
\texttt{SCARD\_STATE\_CHANGED} and \texttt{SCARD\_STATE\_IGNORE} will
1144
\begin{tabular}{|p{5cm}|p{10.5cm}|}
1146
Value of \texttt{dwCurrentState} and \texttt{ddwEventState} & Meaning \\
1149
\texttt{SCARD\_STATE\_UNAVAILABLE} & The actual state of this reader is
1150
not available. If this bit is set, then all the following bits are clear\\
1152
\texttt{SCARD\_STATE\_EMPTY} & There is no card in the reader. If this
1153
bit is set, all the following bits will be clear\\
1155
\texttt{SCARD\_STATE\_PRESENT} & There is a card in the reader\\
1156
\texttt{SCARD\_STATE\_ATRMATCH} & There is a card in the reader with an
1157
ATR matching one of the target cards. If this bit is set,
1158
\texttt{SCARD\_STATE\_PRESENT} will also be set. This bit is only
1159
returned on the SCardLocateCards function\\
1161
\texttt{SCARD\_STATE\_EXCLUSIVE} & The card in the reader is allocated
1162
for exclusive use by another application. If this bit is set,
1163
\texttt{SCARD\_STATE\_PRESENT} will also be set\\
1165
\texttt{SCARD\_STATE\_INUSE} & The card in the reader is in use by one
1166
or more other applications, but may be connected to in shared mode. If
1167
this bit is set, SCARD\_STATE\_PRESENT will also be set\\
1169
\texttt{SCARD\_STATE\_MUTE} & There is an unresponsive card in the reader\\
1176
SCARDCONTEXT hContext;
1178
DWORD dwActiveProtocol, cReaders;
1179
SCARD_READERSTATE_A rgReaderStates[1];
1182
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
1184
rgReaderStates[0].szReader = strdup("Reader X");
1185
rgReaderStates[0].dwCurrentState = SCARD_STATE_EMPTY;
1188
rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, cReaders);
1189
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
1190
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
1197
\texttt{SCARD\_S\_SUCCESS} & Successful\\
1198
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid States, reader name, etc\\
1199
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle\\
1200
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader is unavailable\\
1204
%---------%---------%---------%---------%---------%---------
1205
\subsection{SCardCancel}
1210
#include <winscard.h>
1212
LONG SCardCancel(SCARDCONTEXT hContext);
1217
\begin{tabular}{lll}
1218
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
1223
This function cancels all pending blocking requests on the
1224
\texttt{GetStatusChange()} function.
1228
SCARDCONTEXT hContext;
1230
SCARD_READERSTATE rgReaderStates;
1233
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
1235
rgReaderStates.szReader = strdup("Reader X");
1236
rgReaderStates.dwCurrentState = SCARD_STATE_EMPTY;
1238
/* Spawn off thread for following function */
1239
rv = SCardGetStatusChange(hContext, 0, rgReaderStates, cReaders);
1241
rv = SCardCancel(hContext);
1247
\texttt{SCARD\_S\_SUCCESS} & Successful\\
1248
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle\\
1252
%---------%---------%---------%---------%---------%---------
1253
\subsection{SCardSetTimeout}
1258
#include <winscard.h>
1260
LONG SCardSetTimeout(SCARDCONTEXT hContext,
1266
\begin{tabular}{lll}
1267
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
1268
\texttt{dwTimeout} & IN & New timeout value\\
1273
This function updates the working waiting time that RPC uses when
1274
waiting for a server function to return. This needs to be updated when
1275
a card command is sent that might take more time than usual.
1277
This command is pcsc-lite specific and does not exist in Windows PC/SC.
1282
SCARDCONTEXT hContext;
1285
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
1286
rv = SCardSetTimeout(hContext, 50); /* 50 second timeout */
1292
\texttt{SCARD\_S\_SUCCESS} & Successful\\
1293
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle\\
1297
%---------%---------%---------%---------%---------%---------
1298
\subsection{SCardGetAttrib}
1303
#include <winscard.h>
1305
LONG SCardGetAttrib(SCARDHANDLE hCard,
1308
LPDWORD pcbAttrLen);
1313
\begin{tabular}{lll}
1314
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect}\\
1315
\texttt{dwAttrId} & IN & Identifier for the attribute to get \\
1316
\texttt{pbAttr} & OUT & Pointer to a buffer that receives the attribute \\
1317
\texttt{pcbAttrLen} & IN/OUT & Length of the \texttt{pbAttr} buffer in bytes \\
1322
This function get an attribute from the IFD Handler. The list of
1323
possible attributes is available in the file \texttt{pcsclite.h}.
1326
\item \texttt{SCARD\_ATTR\_ASYNC\_PROTOCOL\_TYPES}
1327
\item \texttt{SCARD\_ATTR\_ATR\_STRING}
1328
\item \texttt{SCARD\_ATTR\_CHANNEL\_ID}
1329
\item \texttt{SCARD\_ATTR\_CHARACTERISTICS}
1330
\item \texttt{SCARD\_ATTR\_CURRENT\_BWT}
1331
\item \texttt{SCARD\_ATTR\_CURRENT\_CLK}
1332
\item \texttt{SCARD\_ATTR\_CURRENT\_CWT}
1333
\item \texttt{SCARD\_ATTR\_CURRENT\_D}
1334
\item \texttt{SCARD\_ATTR\_CURRENT\_EBC\_ENCODING}
1335
\item \texttt{SCARD\_ATTR\_CURRENT\_F}
1336
\item \texttt{SCARD\_ATTR\_CURRENT\_IFSC}
1337
\item \texttt{SCARD\_ATTR\_CURRENT\_IFSD}
1338
\item \texttt{SCARD\_ATTR\_CURRENT\_IO\_STATE}
1339
\item \texttt{SCARD\_ATTR\_CURRENT\_N}
1340
\item \texttt{SCARD\_ATTR\_CURRENT\_PROTOCOL\_TYPE}
1341
\item \texttt{SCARD\_ATTR\_CURRENT\_W}
1342
\item \texttt{SCARD\_ATTR\_DEFAULT\_CLK}
1343
\item \texttt{SCARD\_ATTR\_DEFAULT\_DATA\_RATE}
1344
\item \texttt{SCARD\_ATTR\_DEVICE\_FRIENDLY\_NAME\_A}
1345
\item \texttt{SCARD\_ATTR\_DEVICE\_FRIENDLY\_NAME\_W}
1346
\item \texttt{SCARD\_ATTR\_DEVICE\_IN\_USE}
1347
\item \texttt{SCARD\_ATTR\_DEVICE\_SYSTEM\_NAME\_A}
1348
\item \texttt{SCARD\_ATTR\_DEVICE\_SYSTEM\_NAME\_W}
1349
\item \texttt{SCARD\_ATTR\_DEVICE\_UNIT}
1350
\item \texttt{SCARD\_ATTR\_ESC\_AUTHREQUEST}
1351
\item \texttt{SCARD\_ATTR\_ESC\_CANCEL}
1352
\item \texttt{SCARD\_ATTR\_ESC\_RESET}
1353
\item \texttt{SCARD\_ATTR\_EXTENDED\_BWT}
1354
\item \texttt{SCARD\_ATTR\_ICC\_INTERFACE\_STATUS}
1355
\item \texttt{SCARD\_ATTR\_ICC\_PRESENCE}
1356
\item \texttt{SCARD\_ATTR\_ICC\_TYPE\_PER\_ATR}
1357
\item \texttt{SCARD\_ATTR\_MAX\_CLK}
1358
\item \texttt{SCARD\_ATTR\_MAX\_DATA\_RATE}
1359
\item \texttt{SCARD\_ATTR\_MAX\_IFSD}
1360
\item \texttt{SCARD\_ATTR\_MAXINPUT}
1361
\item \texttt{SCARD\_ATTR\_POWER\_MGMT\_SUPPORT}
1362
\item \texttt{SCARD\_ATTR\_SUPRESS\_T1\_IFS\_REQUEST}
1363
\item \texttt{SCARD\_ATTR\_SYNC\_PROTOCOL\_TYPES}
1364
\item \texttt{SCARD\_ATTR\_USER\_AUTH\_INPUT\_DEVICE}
1365
\item \texttt{SCARD\_ATTR\_USER\_TO\_CARD\_AUTH\_DEVICE}
1366
\item \texttt{SCARD\_ATTR\_VENDOR\_IFD\_SERIAL\_NO}
1367
\item \texttt{SCARD\_ATTR\_VENDOR\_IFD\_TYPE}
1368
\item \texttt{SCARD\_ATTR\_VENDOR\_IFD\_VERSION}
1369
\item \texttt{SCARD\_ATTR\_VENDOR\_NAME}
1372
Not all the \texttt{dwAttrId} values listed above may be implemented in
1373
the IFD Handler you are using. And some \texttt{dwAttrId} values not
1374
listed here may be implemented.
1380
SCARDCONTEXT hContext;
1382
DWORD dwActiveProtocol;
1383
unsigned char pbAtr[MAX_ATR_SIZE];
1386
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
1387
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
1388
SCARD_PROTOCOL_RAW &hCard, &dwActiveProtocol);
1389
rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAtr, &dwAtrLen);
1395
\texttt{SCARD\_S\_SUCCESS} & Successful\\
1396
\texttt{SCARD\_E\_NOT\_TRANSACTED} & Data exchange not successful\\
1397
\texttt{SCARD\_E\_INSUFFICIENT\_BUFFER} & Reader buffer not large enough \\
1401
%---------%---------%---------%---------%---------%---------
1402
\subsection{SCardSetAttrib}
1407
#include <winscard.h>
1409
LONG SCardSetAttrib(SCARDHANDLE hCard,
1417
\begin{tabular}{lll}
1418
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect}\\
1419
\texttt{dwAttrId} & IN & Identifier for the attribute to get \\
1420
\texttt{pbAttr} & IN & Pointer to a buffer that receives the attribute \\
1421
\texttt{pcbAttrLen} & IN & Length of the \texttt{pbAttr} buffer in bytes \\
1426
This function set an attribute of the IFD Handler. The list of
1427
attributes you can set is dependent on the IFD Handler you are using.
1433
SCARDCONTEXT hContext;
1435
DWORD dwActiveProtocol;
1436
unsigned char pbAtr[MAX_ATR_SIZE];
1439
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
1440
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
1441
SCARD_PROTOCOL_RAW &hCard, &dwActiveProtocol);
1442
rv = SCardSetAttrib(hCard, 0x42000001, "\x12\x34\x56", 3);
1448
\texttt{SCARD\_S\_SUCCESS} & Successful\\
1449
\texttt{SCARD\_E\_NOT\_TRANSACTED} & Data exchange not successful\\
1453
%---------%---------%---------%---------%---------%---------
1454
\subsection{pcsc\_stringify\_error}
1459
#include <pcsclite.h>
1461
char *pcsc_stringify_error(long error);
1466
This function return a human readable text for the given PC/SC error
1473
SCARDCONTEXT hContext;
1476
rv = SCardEstablishContext(SCARD\_SCOPE\_SYSTEM, NULL, NULL, &hContext);
1477
if (rv != SCARD_S_SUCCESS)
1478
printf("SCardReleaseContext: %s (0x%lX)\n", pcsc_stringify_error(rv), rv);
1482
%---------%---------%---------%---------%---------%---------%---------
1483
\section{Multithreading and contexts}
1485
From version 1.2.0 pcsc-lite is much more multithreading friendly.
1487
You have to follow some rules:
1490
\item For security reasons, a context can only be released (using
1491
\texttt{SCardReleaseContext()}) by the thread that created it.
1493
\item To access different readers (\emph{i.e.} cards) in different
1494
threads, each thread must use a different context (not necessarily
1495
created by this thread itself).
1499
Each thread should create his own context with
1500
\texttt{SCardEstablishContext()} and should release it with
1501
\texttt{SCardReleaseContext()} when the context is not necessary any
1504
If different threads share a same context, the calls to different
1505
functions of the pcsc-lite API are stored in a queue and the executions
1506
serialised for this context because there is a mutex shared for all the
1507
(critical) operations of this context.
1510
%---------%---------%---------%---------%---------%---------
1511
\bibliographystyle{plain}
1512
\bibliography{pcsc-lite}