You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1740 lines
50 KiB

%
% MUSCLE Smart Card Development ( http://www.linuxnet.com )
%
% Copyright (C) 2004
% David Corcoran <corcoran@linuxnet.com>
% Ludovic Rousseau <ludovic.rousseau@free.fr>
%
% $Id: pcsc-lite.tex 2967 2008-05-23 13:35:29Z rousseau $
\documentclass[a4paper,12pt]{article}
\usepackage{longtable}
\usepackage{url}
\usepackage{varioref}
% Détection de pdflatex
\ifx\pdfcompresslevel\undefined
% Si on fait un postscript
\typeout{Postscript version}
\usepackage[dvips]{graphicx,rotating}
%\usepackage[dvips,matrix,line,curve,arrow,frame]{xy}
\DeclareGraphicsExtensions{.eps}
\else
% Si on fait un PDF
\typeout{PDF version}
\usepackage[pdftex]{graphicx,rotating}
%\usepackage[matrix,line,curve,arrow,frame]{xy}
\DeclareGraphicsExtensions{.jpg,.pdf}
\usepackage[pdftex]{hyperref}
\usepackage{ae,aeguill}
\fi
% smaller margins
\usepackage{fullpage}
% do not number subsubsection
\setcounter{tocdepth}{2}
\setcounter{secnumdepth}{2}
\newcommand{\synopsis}{\subsubsection{Synopsis:}}
\newcommand{\parameters}{\subsubsection{Parameters:}}
\newcommand{\desc}{\subsubsection{Description:}}
\newcommand{\example}{\subsubsection{Example:}}
\newcommand{\returns}{\subsubsection{Returns:}}
\title{MUSCLE PC/SC Lite API \\ Toolkit API Reference Documentation}
\author{David Corcoran \& Ludovic Rousseau\\
\url{corcoran@linuxnet.com}, \url{ludovic.rousseau@free.fr}}
\date{May 26, 2004}
\begin{document}
\maketitle
\begin{abstract}
This toolkit and documentation is provided on an \emph{as is} basis.
The authors shall not be held responsible for any mishaps caused by the
use of this software.
For more information please visit \url{http://www.musclecard.com/}.
\end{abstract}
% space between paragraphs
\parskip = 8pt
% remove paragraph indentation
\addtolength{\parindent}{-\parindent}
Document history: \\
\begin{tabular}{|l|l|l|}
\hline
0.8.7 & March 8, 2001 & latest PDF only version \\
\hline
0.9.0 & May 26, 2004 & reformat using \LaTeX{}, correct bugs and add
parts 4 and 5 \\
\hline
0.9.1 & Jan 10, 2007 & add SCardIsValidContext() \\
\hline
\end{tabular}
\newpage
\tableofcontents
\newpage
%---------%---------%---------%---------%---------%---------%---------
\section{Introduction/Overview}
This document contains the reference API calls for communicating to the
MUSCLE PC/SC Smart Card Resource Manager. PC/SC is a standard proposed by
the PC/SC workgroup \cite{pcsc_workgroup} which is a conglomerate of
representative from major smart card manufacturers and other companies.
This specification tries to abstract the smart card layer into a high
level API so that smart cards and their readers can be accessed in a
homogeneous fashion.
This toolkit was written in ANSI C that can be used with most compilers
and does NOT use complex and large data structures such as vectors,
\textit{etc}. The C API emulates the winscard API that is used on the
Windows platform. It is contained in the library \texttt{libpcsclite.so}
that is linked to your application.
I would really like to hear from you. If you have any feedback either on
this documentation or on the MUSCLE project please feel free to email me
at: \url{corcoran@musclecard.com}.
%---------%---------%---------%---------%---------%---------%---------
\section{Definitions}
%---------%---------%---------%---------%---------%---------
\subsection{Defined types}
The following is a list of commonly used type definitions in the
following API. These definitions and more can be found in the
\url{include/pcsclite.h} file.
{\tt
\begin{longtable}{|l|l|}
\hline
\textrm{PC/SC type} & \textrm{C type} \\
\hline
\hline
BOOL & short \\
BYTE & unsigned char \\
DWORD & unsigned long \\
LONG & long \\
LPBYTE & unsigned char * \\
LPCBYTE & const unsigned char * \\
LPCSTR & const char * \\
LPCVOID & const void * \\
LPCWSTR & char * \\
LPDWORD & unsigned long * \\
LPSCARDCONTEXT & unsigned long * \\
LPSCARDHANDLE & unsigned long * \\
LPSTR & char * \\
LPVOID & void * \\
PSCARDCONTEXT & unsigned long * \\
PSCARDHANDLE & unsigned long * \\
RESPONSECODE & long \\
SCARDCONTEXT & unsigned long \\
SCARDHANDLE & unsigned long \\
ULONG & unsigned long \\
USHORT & unsigned short \\
WORD & unsigned long \\
\hline
\end{longtable}
}
%---------%---------%---------%---------%---------%---------
\subsection{Error codes}
\label{Error codes}
The following is a list of commonly used errors. Since different
cards produce different errors they must map over to these error
messages.
{\tt
\begin{longtable}{|l|}
\hline
SCARD\_S\_SUCCESS \\
\hline
SCARD\_E\_CANCELLED \\
SCARD\_E\_CANT\_DISPOSE \\
SCARD\_E\_CARD\_UNSUPPORTED \\
SCARD\_E\_DUPLICATE\_READER \\
SCARD\_E\_INSUFFICIENT\_BUFFER \\
SCARD\_E\_INVALID\_ATR \\
SCARD\_E\_INVALID\_HANDLE \\
SCARD\_E\_INVALID\_PARAMETER \\
SCARD\_E\_INVALID\_TARGET \\
SCARD\_E\_INVALID\_VALUE \\
SCARD\_E\_NO\_MEMORY \\
SCARD\_E\_NO\_SERVICE \\
SCARD\_E\_NO\_SMARTCARD \\
SCARD\_E\_NOT\_READY \\
SCARD\_E\_NOT\_TRANSACTED \\
SCARD\_E\_PCI\_TOO\_SMALL \\
SCARD\_E\_PROTO\_MISMATCH \\
SCARD\_E\_READER\_UNAVAILABLE \\
SCARD\_E\_READER\_UNSUPPORTED \\
SCARD\_E\_SERVICE\_STOPPED \\
SCARD\_E\_SHARING\_VIOLATION \\
SCARD\_E\_SYSTEM\_CANCELLED \\
SCARD\_E\_TIMEOUT \\
SCARD\_E\_UNKNOWN\_CARD \\
SCARD\_E\_UNKNOWN\_READER \\
SCARD\_F\_COMM\_ERROR \\
SCARD\_F\_INTERNAL\_ERROR \\
SCARD\_F\_UNKNOWN\_ERROR \\
SCARD\_F\_WAITED\_TOO\_LONG \\
\hline
SCARD\_W\_UNSUPPORTED\_CARD \\
SCARD\_W\_UNRESPONSIVE\_CARD \\
SCARD\_W\_UNPOWERED\_CARD \\
SCARD\_W\_RESET\_CARD \\
SCARD\_W\_REMOVED\_CARD \\
\hline
\end{longtable}
}
%---------%---------%---------%---------%---------%---------%---------
\section{API Routines}
These routines specified here are winscard routines like those in the
winscard API provided under Windows{\textregistered}. These are
compatible with the Microsoft{\textregistered} API calls. This list of
calls is mainly an abstraction of readers. It gives a common API for
communication to most readers in a homogeneous fashion.
Since all functions can produce a wide array of errors, please refer to
\S~\vref{Error codes} for a list of error returns.
For a human readable representation of an error the function
\url{pcsc_stringify_error()} is declared in \texttt{pcsclite.h}.
This function is not available on Microsoft{\textregistered} winscard
API and is pcsc-lite specific.
%---------%---------%---------%---------%---------%---------
\subsection{SCardEstablishContext}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardEstablishContext(DWORD dwScope,
LPCVOID pvReserved1,
LPCVOID pvReserved2,
LPSCARDCONTEXT phContext);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{dwScope} & IN & Scope of the establishment \\
& & This can either be a local or remote connection\\
\texttt{pvReserved1} & IN & Reserved for future use. Can be used for remote
connection \\
\texttt{pvReserved2} & IN & Reserved for future use \\
\texttt{phContext} & OUT & Returned reference to this connection \\
\end{tabular}
\desc
This function creates a communication context to the PC/SC Resource
Manager. This must be the first function called in a PC/SC application.
\begin{tabular}{|l|l|}
\hline
Value of \texttt{dwScope} & Meaning\\
\hline
\hline
\texttt{SCARD\_SCOPE\_USER} & Not used\\
\hline
\texttt{SCARD\_SCOPE\_TERMINAL} & Not used\\
\hline
\texttt{SCARD\_SCOPE\_GLOBAL} & Not used\\
\hline
\texttt{SCARD\_SCOPE\_SYSTEM} & Services on the local machine\\
\hline
\end{tabular}
% Note: If \texttt{SCARD\_SCOPE\_GLOBAL} is used then \texttt{pvReserved1}
% is a string that is the hostname of the machine which the Resource
% Manager services reside. If \texttt{NULL} is specified then it defaults
% to the localhost.
\example
\begin{verbatim}
SCARDCONTEXT hContext;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid scope type passed
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardReleaseContext}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardReleaseContext(SCARDCONTEXT hContext);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hContext} & IN & Connection context to be closed
\end{tabular}
\desc
This function destroys a communication context to the PC/SC Resource
Manager. This must be the last function called in a PC/SC application.
\example
\begin{verbatim}
SCARDCONTEXT hContext;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardReleaseContext(hContext);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardIsValidContext}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardIsValidContext(SCARDCONTEXT hContext);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hContext} & IN & Connection context to be checked
\end{tabular}
\desc
This function determines whether a smart card context handle is still
valid. After a smart card context handle has been set by
SCardEstablishContext(), it may become not valid if the resource manager
service has been shut down.
\example
\begin{verbatim}
SCARDCONTEXT hContext;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardIsValidContext(hContext);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardListReaders}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardListReaders(SCARDCONTEXT hContext,
LPCSTR mszGroups,
LPSTR mszReaders,
LPDWORD pcchReaders);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
\texttt{mszGroups} & IN & List of groups to list readers (not used)\\
\texttt{mszReaders} & OUT & Multi-string with list of readers\\
\texttt{pcchReaders} & INOUT & Size of multi-string buffer including NULL's
\end{tabular}
\desc
This function returns a list of currently available readers on the
system. \texttt{mszReaders} is a pointer to a character string that is
allocated by the application. If the application sends
\texttt{mszGroups} and \texttt{mszReaders} as \texttt{NULL} then this
function will return the size of the buffer needed to allocate in
\texttt{pcchReaders}.
The reader names is a multi-string and separated by a nul character
(\verb+'\0'+) and ended by a double nul character.
\verb+"Reader A\0Reader B\0\0"+.
\example
\begin{verbatim}
SCARDCONTEXT hContext;
LPSTR mszReaders;
DWORD dwReaders;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardListReaders(hContext, NULL, NULL, &dwReaders);
mszReaders = malloc(sizeof(char)*dwReaders);
rv = SCardListReaders(hContext, NULL, mszReaders, &dwReaders);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful \\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid Scope Handle\\
\texttt{SCARD\_E\_INSUFFICIENT\_BUFFER} & Reader buffer not large enough
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardListReaderGroups}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardListReaderGroups(SCARDCONTEXT hContext,
LPSTR mszGroups,
LPDWORD pcchGroups);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
\texttt{mszGroups} & OUT & List of groups to list readers\\
\texttt{pcchGroups} & INOUT & Size of multi-string buffer including NULL's
\end{tabular}
\desc
This function returns a list of currently available reader groups on the
system. \texttt{mszGroups} is a pointer to a character string that is
allocated by the application. If the application sends
\texttt{mszGroups} as \texttt{NULL} then this function will return the
size of the buffer needed to allocate in \texttt{pcchGroups}.
The group names is a multi-string and separated by a nul character
(\verb+'\0'+) and ended by a double nul character.
\verb+"SCard$DefaultReaders\0Group 2\0\0"+.
\example
\begin{verbatim}
SCARDCONTEXT hContext;
LPSTR mszGroups;
DWORD dwGroups;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardListReaderGroups(hContext, NULL, &dwGroups);
mszGroups = malloc(sizeof(char)*dwGroups);
rv = SCardListReaderGroups(hContext, mszGroups, &dwGroups);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful \\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid Scope Handle\\
\texttt{SCARD\_E\_INSUFFICIENT\_BUFFER} & Reader buffer not large enough
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardConnect}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardConnect(SCARDCONTEXT hContext,
LPCSTR szReader,
DWORD dwShareMode,
DWORD dwPreferredProtocols,
LPSCARDHANDLE phCard,
LPDWORD pdwActiveProtocol);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
\texttt{szReader} & IN & Reader name to connect to\\
\texttt{dwShareMode} & IN & Mode of connection type: exclusive or shared\\
\texttt{dwPreferredProtocols} & IN & Desired protocol use\\
\texttt{phCard} & OUT & Handle to this connection\\
\texttt{pdwActiveProtocol} & OUT & Established protocol to this connection.
\end{tabular}
\desc
This function establishes a connection to the friendly name of
the reader specified in \texttt{szReader}. The first connection will
power up and perform a reset on the card.
\begin{tabular}{|l|l|}
\hline
Value of \texttt{dwShareMode} & Meaning\\
\hline
\hline
\texttt{SCARD\_SHARE\_SHARED} & This application will allow others to share the reader \\
\hline
\texttt{SCARD\_SHARE\_EXCLUSIVE} & This application will NOT allow
others to share the reader \\
\hline
\texttt{SCARD\_SHARE\_DIRECT} & Direct control of the reader, even
without a card \\
\hline
\end{tabular}
\texttt{SCARD\_SHARE\_DIRECT} can be used before using
\texttt{SCardControl()} to send control commands to the reader even if a
card is not present in the reader.
\begin{tabular}{|l|l|}
\hline
Value of \texttt{dwPreferredProtocols} & Meaning \\
\hline
\hline
\texttt{SCARD\_PROTOCOL\_T0} & Use the T=0 protocol \\
\hline
\texttt{SCARD\_PROTOCOL\_T1} & Use the T=1 protocol \\
\hline
\texttt{SCARD\_PROTOCOL\_RAW} & Use with memory type cards \\
\hline
\end{tabular}
\texttt{dwPreferredProtocols} is a bit mask of acceptable protocols for
the connection. You can use \texttt{(SCARD\_PROTOCOL\_T0 |
SCARD\_PROTOCOL\_T1)} if you do not have a preferred protocol.
\example
\begin{verbatim}
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle\\
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid sharing mode, requested protocol, or reader name\\
\texttt{SCARD\_E\_NOT\_READY} & Could not allocate the desired port\\
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & Could not power up the reader or card\\
\texttt{SCARD\_E\_SHARING\_VIOLATION} & Someone else has exclusive rights\\
\texttt{SCARD\_E\_UNSUPPORTED\_FEATURE} & Protocol not supported\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardReconnect}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardReconnect(SCARDHANDLE hCard,
DWORD dwShareMode,
DWORD dwPreferredProtocols,
DWORD dwInitialization,
LPDWORD pdwActiveProtocol);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hCard} & IN & Handle to a previous call to connect\\
\texttt{dwShareMode} & IN & Mode of connection type: exclusive/shared\\
\texttt{dwPreferredProtocols} & IN & Desired protocol use\\
\texttt{dwInitialization} & IN & Desired action taken on the card/reader\\
\texttt{pdwActiveProtocol} & OUT & Established protocol to this connection\\
\end{tabular}
\desc
This function reestablishes a connection to a reader that was previously
connected to using \texttt{SCardConnect()}. In a multi application
environment it is possible for an application to reset the card in
shared mode. When this occurs any other application trying to access
certain commands will be returned the value
\texttt{SCARD\_W\_RESET\_CARD}. When this occurs
\texttt{SCardReconnect()} must be called in order to acknowledge that
the card was reset and allow it to change it's state accordingly.
\begin{tabular}{|l|l|}
\hline
Value of \texttt{dwShareMode} & Meaning \\
\hline
\hline
\texttt{SCARD\_SHARE\_SHARED} & This application will allow others to share the
reader\\
\hline
\texttt{SCARD\_SHARE\_EXCLUSIVE} & This application will NOT allow others to
share the reader\\
\hline
\end{tabular}
\begin{tabular}{|l|l|}
\hline
Value of \texttt{dwPreferredProtocols} & Meaning \\
\hline
\hline
\texttt{SCARD\_PROTOCOL\_T0} & Use the T=0 protocol \\
\hline
\texttt{SCARD\_PROTOCOL\_T1} & Use the T=1 protocol \\
\hline
\texttt{SCARD\_PROTOCOL\_RAW} & Use with memory type cards \\
\hline
\end{tabular}
\texttt{dwPreferredProtocols} is a bit mask of acceptable protocols for
the connection. You can use \texttt{(SCARD\_PROTOCOL\_T0 |
SCARD\_PROTOCOL\_T1)} if you do not have a preferred protocol.
\begin{tabular}{|l|l|}
\hline
Value of \texttt{dwInitialization} & Meaning \\
\hline
\hline
\texttt{SCARD\_LEAVE\_CARD} & Do nothing \\
\hline
\texttt{SCARD\_RESET\_CARD} & Reset the card (warm reset) \\
\hline
\texttt{SCARD\_UNPOWER\_CARD} & Unpower the card (cold reset) \\
\hline
\texttt{SCARD\_EJECT\_CARD} & Eject the card \\
\hline
\end{tabular}
\example
\begin{verbatim}
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
LONG rv;
BYTE pbRecvBuffer[10];
BYTE pbSendBuffer[] = {0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00};
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
dwSendLength = sizeof(pbSendBuffer);
dwRecvLength = sizeof(pbRecvBuffer);
rv = SCardTransmit(hCard, SCARD_PCI_T0, pbSendBuffer, dwSendLength,
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
/* Card has been reset by another application */
if (rv == SCARD_W_RESET_CARD)
{
rv = SCardReconnect(hCard, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0,
SCARD_RESET_CARD, &dwActiveProtocol);
}
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
\texttt{SCARD\_E\_NOT\_READY} & Could not allocate the desired port\\
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid sharing mode, requested protocol, or reader name\\
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
\texttt{SCARD\_E\_UNSUPPORTED\_FEATURE} & Protocol not supported\\
\texttt{SCARD\_E\_SHARING\_VIOLATION} & Someone else has exclusive rights\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardDisconnect}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect} \\
\texttt{dwDisposition} & IN & Reader function to execute \\
\end{tabular}
\desc
This function terminates a connection to the connection made through
SCardConnect. dwDisposition can have the following values:
\begin{tabular}{|l|l|}
\hline
Value of \texttt{dwDisposition} & Meaning \\
\hline
\hline
\texttt{SCARD\_LEAVE\_CARD} & Do nothing\\
\texttt{SCARD\_RESET\_CARD} & Reset the card (warm reset) \\
\texttt{SCARD\_UNPOWER\_CARD} & Unpower the card (cold reset) \\
\texttt{SCARD\_EJECT\_CARD} & Eject the card\\
\hline
\end{tabular}
\example
\begin{verbatim}
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
rv = SCardDisconnect(hCard, SCARD_UNPOWER_CARD);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful \\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle \\
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid \texttt{dwDisposition} \\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardBeginTransaction}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardBeginTransaction(SCARDHANDLE hCard);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect} \\
\end{tabular}
\desc
This function establishes a temporary exclusive access mode for doing a
series of commands or transaction. You might want to use this when you
are selecting a few files and then writing a large file so you can make
sure that another application will not change the current file. If
another application has a lock on this reader or this application is in
\texttt{SCARD\_SHARE\_EXCLUSIVE} there will be no action taken.
\example
\begin{verbatim}
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
rv = SCardBeginTransaction(hCard);
/* Do some transmit commands */
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
\texttt{SCARD\_E\_SHARING\_VIOLATION} & Someone else has exclusive rights\\
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardEndTransaction}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardEndTransaction(SCARDHANDLE hCard,
DWORD dwDisposition);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect}\\
\texttt{dwDisposition} & IN & Action to be taken on the reader\\
\end{tabular}
\desc
This function ends a previously begun transaction. The calling
application must be the owner of the previously begun transaction or an
error will occur. \texttt{dwDisposition} can have the following values:
The disposition action is not currently used in this release.
\begin{tabular}{|l|l|}
\hline
Value of dwDisposition & Meaning \\
\hline
\hline
\texttt{SCARD\_LEAVE\_CARD} & Do nothing\\
\texttt{SCARD\_RESET\_CARD} & Reset the card\\
\texttt{SCARD\_UNPOWER\_CARD} & Unpower the card\\
\texttt{SCARD\_EJECT\_CARD} & Eject the card\\
\hline
\end{tabular}
\example
\begin{verbatim}
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
rv = SCardBeginTransaction(hCard);
/* Do some transmit commands */
rv = SCardEndTransaction(hCard, SCARD_LEAVE_CARD);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
\texttt{SCARD\_E\_SHARING\_VIOLATION} & Someone else has exclusive rights\\
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardTransmit}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardTransmit(SCARDHANDLE hCard,
LPCSCARD_IO_REQUEST pioSendPci,
LPCBYTE pbSendBuffer,
DWORD cbSendLength,
LPSCARD_IO_REQUEST pioRecvPci,
LPBYTE pbRecvBuffer,
LPDWORD pcbRecvLength);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect} \\
\texttt{pioSendPci} & INOUT & Structure of protocol information\\
\texttt{pbSendBuffer} & IN & APDU to send to the card\\
\texttt{cbSendLength} & IN & Length of the APDU\\
\texttt{pioRecvPci} & INOUT & Structure of protocol information\\
\texttt{pbRecvBuffer} & OUT & Response from the card\\
\texttt{pcbRecvLength} & INOUT & Length of the response\\
\end{tabular}
\desc
This function sends an APDU to the smart card contained in the reader
connected to by \texttt{SCardConnect()}. The card responds from the
APDU and stores this response in \texttt{pbRecvBuffer} and it's length
in \texttt{SpcbRecvLength}. \texttt{SSendPci} and \texttt{SRecvPci} are
structures containing the following:
\begin{verbatim}
typedef struct {
DWORD dwProtocol; /* SCARD_PROTOCOL_T0 or SCARD_PROTOCOL_T1 */
DWORD cbPciLength; /* Length of this structure - not used */
} SCARD_IO_REQUEST;
\end{verbatim}
\begin{tabular}{|l|l|}
\hline
Value of \texttt{pioSendPci} & Meaning \\
\hline
\hline
\texttt{SCARD\_PCI\_T0} & Pre-defined T=0 PCI structure\\
\texttt{SCARD\_PCI\_T1} & Pre-defined T=1 PCI structure\\
\hline
\end{tabular}
\example
\begin{verbatim}
LONG rv;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
SCARD_IO_REQUEST pioRecvPci;
BYTE pbRecvBuffer[10];
BYTE pbSendBuffer[] = { 0xC0, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00 };
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
dwSendLength = sizeof(pbSendBuffer);
dwRecvLength = sizeof(pbRecvBuffer);
rv = SCardTransmit(hCard, SCARD_PCI_T0, pbSendBuffer, dwSendLength,
&pioRecvPci, pbRecvBuffer, &dwRecvLength);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
\texttt{SCARD\_E\_NOT\_TRANSACTED} & APDU exchange not successful\\
\texttt{SCARD\_E\_PROTO\_MISMATCH} & Connect protocol is different than desired\\
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid Protocol, reader name, etc\\
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
\texttt{SCARD\_W\_RESET\_CARD} & The card has been reset by another application\\
\texttt{SCARD\_W\_REMOVED\_CARD} & The card has been removed from the reader\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardControl}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardControl(SCARDHANDLE hCard,
DWORD dwControlCode,
LPCVOID pbSendBuffer,
DWORD cbSendLength,
LPVOID pbRecvBuffer,
DWORD pcbRecvLength,
LPDWORD lpBytesReturned);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect}\\
\texttt{dwControlCode} & IN & Control code for the operation \\
\texttt{pbSendBuffer} & IN & Command to send to the reader\\
\texttt{cbSendLength} & IN & Length of the command\\
\texttt{pbRecvBuffer} & OUT & Response from the reader\\
\texttt{pcbRecvLength} & IN & Length of the response buffer\\
\texttt{lpBytesReturned} & OUT & Length of the response\\
\end{tabular}
\desc
This function sends a command directly to the IFD Handler to be
processed by the reader. This is useful for creating client side reader
drivers for functions like PIN pads, biometrics, or other extensions to
the normal smart card reader that are not normally handled by PC/SC.
Note: the API of this function changed. In pcsc-lite 1.2.0 and before
the API was not Windows{\textregistered} PC/SC compatible. This has been
corrected.
see \S~\ref{Some SCardControl commands} for a list of supported commands
by some drivers.
\example
\begin{verbatim}
LONG rv;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol, dwSendLength, dwRecvLength;
BYTE pbRecvBuffer[10];
BYTE pbSendBuffer[] = { 0x06, 0x00, 0x0A, 0x01, 0x01, 0x10 0x00 };
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_RAW &hCard, &dwActiveProtocol);
dwSendLength = sizeof(pbSendBuffer);
dwRecvLength = sizeof(pbRecvBuffer);
rv = SCardControl(hCard, 0x42000001, pbSendBuffer, dwSendLength,
pbRecvBuffer, sizeof(pbRecvBuffer), &dwRecvLength);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_NOT\_TRANSACTED} & Data exchange not successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid value was presented\\
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
\texttt{SCARD\_W\_RESET\_CARD} & The card has been reset by another application\\
\texttt{SCARD\_W\_REMOVED\_CARD} & The card has been removed from the reader\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardStatus}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardStatus(SCARDHANDLE hCard,
LPSTR szReaderName,
LPDWORD pcchReaderLen,
LPDWORD pdwState,
LPDWORD pdwProtocol,
LPBYTE pbAtr,
LPDWORD pcbAtrLen);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect} \\
\texttt{szReaderName} & INOUT & Friendly name of this reader\\
\texttt{pcchReaderLen} & INOUT & Size of the \texttt{szReaderName} multistring\\
\texttt{pdwState} & OUT & Current state of this reader\\
\texttt{pdwProtocol} & OUT & Current protocol of this reader\\
\texttt{pbAtr} & OUT & Current ATR of a card in this reader\\
\texttt{pcbAtrLen} & OUT & Length of ATR\\
\end{tabular}
\desc
This function returns the current status of the reader connected to by
\texttt{hCard}. It's friendly name will be stored in
\texttt{szReaderName}. \texttt{pcchReaderLen} will be the size of the
allocated buffer for \texttt{szReaderName}, while \texttt{pcbAtrLen}
will be the size of the allocated buffer for \texttt{pbAtr}. If either
of these is too small, the function will return with
\texttt{SCARD\_E\_INSUFFICIENT\_BUFFER} and the necessary size in
\texttt{pcchReaderLen} and \texttt{pcbAtrLen}. The current state, and
protocol will be stored in \texttt{pdwState} and \texttt{pdwProtocol}
respectively. \texttt{pdwState} is a \texttt{DWORD} possibly OR'd with
the following values:
\begin{tabular}{|l|p{12cm}|}
\hline
Value of \texttt{pdwState} & Meaning \\
\hline
\hline
\texttt{SCARD\_ABSENT} & There is no card in the reader\\
\texttt{SCARD\_PRESENT} & There is a card in the reader, but it has not been moved into position for use\\
\texttt{SCARD\_SWALLOWED} & There is a card in the reader in position for use. The card is not powered\\
\texttt{SCARD\_POWERED} & Power is being provided to the card, but the reader driver is unaware of the mode of the card\\
\texttt{SCARD\_NEGOTIABLE} & The card has been reset and is awaiting PTS negotiation\\
\texttt{SCARD\_SPECIFIC} & The card has been reset and specific communication protocols have been established\\
\hline
\end{tabular}
\begin{tabular}{|l|l|}
\hline
Value of \texttt{pdwProtocol} & Meaning \\
\hline
\hline
\texttt{SCARD\_PROTOCOL\_T0} & Use the T=0 protocol\\
\texttt{SCARD\_PROTOCOL\_T1} & Use the T=1 protocol\\
\hline
\end{tabular}
\example
\begin{verbatim}
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
DWORD dwState, dwProtocol, dwAtrLen, dwReaderLen;
BYTE pbAtr[MAX_ATR_SIZE];
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
dwAtrLen = sizeof(pbAtr);
rv = SCardStatus(hCard, NULL, &dwReaderLen, &dwState, &dwProtocol,
pbAtr, &dwAtrLen);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hCard} handle\\
\texttt{SCARD\_E\_INSUFFICIENT\_BUFFER} & Not enough allocated memory for \texttt{szReaderName}\\
& or for \texttt{pbAtr} \\
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader has been removed\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardGetStatusChange}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardGetStatusChange(SCARDCONTEXT hContext,
DWORD dwTimeout,
LPSCARD_READERSTATE rgReaderStates,
DWORD cReaders);
\end{verbatim}
\parameters
\begin{tabular}{llp{10cm}}
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
\texttt{dwTimeout} & IN & Maximum waiting time (in miliseconds)
for status change, zero (or \texttt{INFINITE}) for infinite\\
\texttt{rgReaderStates} & INOUT & Structures of readers with current states\\
\texttt{cReaders} & IN & Number of structures\\
\end{tabular}
\desc
This function receives a structure or list of structures containing
reader names. It then blocks for a change in state to occur on any of
the OR'd values contained in \texttt{dwCurrentState} for a maximum
blocking time of \texttt{dwTimeout} or forever if \texttt{INFINITE} is
used. The new event state will be contained in \texttt{dwEventState}.
A status change might be a card insertion or removal event, a change in
ATR, \textit{etc}.
This function will block for reader availability if \texttt{cReaders} is
equal to zero and \texttt{rgReaderStates} is \texttt{NULL}.
\begin{verbatim}
typedef struct {
LPCSTR szReader; /* Reader name */
LPVOID pvUserData; /* User defined data */
DWORD dwCurrentState; /* Current state of reader */
DWORD dwEventState; /* Reader state after a state change */
DWORD cbAtr; /* ATR Length, usually MAX_ATR_SIZE */
BYTE rgbAtr[MAX_ATR_SIZE]; /* ATR Value */
} SCARD_READERSTATE;
typedef SCARD_READERSTATE *PSCARD_READERSTATE, **LPSCARD_READERSTATE;
\end{verbatim}
\begin{tabular}{|p{5cm}|p{10.5cm}|}
\hline
Value of \texttt{dwCurrentState} and \texttt{dwEventState} & Meaning \\
\hline
\hline
\texttt{SCARD\_STATE\_UNAWARE} & The application is unaware of the
current state, and would like to know. The use of this value results in
an immediate return from state transition monitoring services. This is
represented by all bits set to zero\\
\texttt{SCARD\_STATE\_IGNORE} & This reader should be ignored\\
\texttt{SCARD\_STATE\_CHANGED} & There is a difference between the state
believed by the application, and the state known by the resource
manager. When this bit is set, the application may assume a significant
state change has occurred on this reader\\
\texttt{SCARD\_STATE\_UNKNOWN} & The given reader name is not recognized
by the resource manager. If this bit is set, then
\texttt{SCARD\_STATE\_CHANGED} and \texttt{SCARD\_STATE\_IGNORE} will
also be set\\
\hline
\end{tabular}
\begin{tabular}{|p{5cm}|p{10.5cm}|}
\hline
Value of \texttt{dwCurrentState} and \texttt{dwEventState} & Meaning \\
\hline
\hline
\texttt{SCARD\_STATE\_UNAVAILABLE} & The actual state of this reader is
not available. If this bit is set, then all the following bits are clear\\
\texttt{SCARD\_STATE\_EMPTY} & There is no card in the reader. If this
bit is set, all the following bits will be clear\\
\texttt{SCARD\_STATE\_PRESENT} & There is a card in the reader\\
\texttt{SCARD\_STATE\_ATRMATCH} & There is a card in the reader with an
ATR matching one of the target cards. If this bit is set,
\texttt{SCARD\_STATE\_PRESENT} will also be set. This bit is only
returned on the SCardLocateCards function\\
\texttt{SCARD\_STATE\_EXCLUSIVE} & The card in the reader is allocated
for exclusive use by another application. If this bit is set,
\texttt{SCARD\_STATE\_PRESENT} will also be set\\
\texttt{SCARD\_STATE\_INUSE} & The card in the reader is in use by one
or more other applications, but may be connected to in shared mode. If
this bit is set, SCARD\_STATE\_PRESENT will also be set\\
\texttt{SCARD\_STATE\_MUTE} & There is an unresponsive card in the reader\\
\hline
\end{tabular}
\example
\begin{verbatim}
SCARDCONTEXT hContext;
SCARD_READERSTATE_A rgReaderStates[1];
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rgReaderStates[0].szReader = "Reader X";
rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
rv = SCardGetStatusChange(hContext, INFINITE, rgReaderStates, 1);
printf("reader state: 0x%04X\n", rgReaderStates[0].dwEventState);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_VALUE} & Invalid States, reader name, etc\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle\\
\texttt{SCARD\_E\_READER\_UNAVAILABLE} & The reader is unavailable\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardCancel}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardCancel(SCARDCONTEXT hContext);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
\end{tabular}
\desc
This function cancels all pending blocking requests on the
\texttt{GetStatusChange()} function.
\example
\begin{verbatim}
SCARDCONTEXT hContext;
DWORD cReaders;
SCARD_READERSTATE rgReaderStates;
LONG rv;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rgReaderStates.szReader = strdup("Reader X");
rgReaderStates.dwCurrentState = SCARD_STATE_EMPTY;
/* Spawn off thread for following function */
rv = SCardGetStatusChange(hContext, 0, rgReaderStates, cReaders);
rv = SCardCancel(hContext);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_INVALID\_HANDLE} & Invalid \texttt{hContext} handle\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardSetTimeout}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardSetTimeout(SCARDCONTEXT hContext,
DWORD dwTimeout);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hContext} & IN & Connection context to the PC/SC Resource Manager\\
\texttt{dwTimeout} & IN & New timeout value\\
\end{tabular}
\desc
This function is not in Microsoft{\textregistered} WinSCard API and is
deprecated in pcsc-lite API.
The function does not do anything except returning
\texttt{SCARD\_S\_SUCCESS}.
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardGetAttrib}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardGetAttrib(SCARDHANDLE hCard,
DWORD dwAttrId,
LPBYTE pbAttr,
LPDWORD pcbAttrLen);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect}\\
\texttt{dwAttrId} & IN & Identifier for the attribute to get \\
\texttt{pbAttr} & OUT & Pointer to a buffer that receives the attribute \\
\texttt{pcbAttrLen} & IN/OUT & Length of the \texttt{pbAttr} buffer in bytes \\
\end{tabular}
\desc
This function get an attribute from the IFD Handler. The list of
possible attributes is available in the file \texttt{pcsclite.h}.
\begin{itemize}
\item \texttt{SCARD\_ATTR\_ASYNC\_PROTOCOL\_TYPES}
\item \texttt{SCARD\_ATTR\_ATR\_STRING}
\item \texttt{SCARD\_ATTR\_CHANNEL\_ID}
\item \texttt{SCARD\_ATTR\_CHARACTERISTICS}
\item \texttt{SCARD\_ATTR\_CURRENT\_BWT}
\item \texttt{SCARD\_ATTR\_CURRENT\_CLK}
\item \texttt{SCARD\_ATTR\_CURRENT\_CWT}
\item \texttt{SCARD\_ATTR\_CURRENT\_D}
\item \texttt{SCARD\_ATTR\_CURRENT\_EBC\_ENCODING}
\item \texttt{SCARD\_ATTR\_CURRENT\_F}
\item \texttt{SCARD\_ATTR\_CURRENT\_IFSC}
\item \texttt{SCARD\_ATTR\_CURRENT\_IFSD}
\item \texttt{SCARD\_ATTR\_CURRENT\_IO\_STATE}
\item \texttt{SCARD\_ATTR\_CURRENT\_N}
\item \texttt{SCARD\_ATTR\_CURRENT\_PROTOCOL\_TYPE}
\item \texttt{SCARD\_ATTR\_CURRENT\_W}
\item \texttt{SCARD\_ATTR\_DEFAULT\_CLK}
\item \texttt{SCARD\_ATTR\_DEFAULT\_DATA\_RATE}
\item \texttt{SCARD\_ATTR\_DEVICE\_FRIENDLY\_NAME\_A}
\item \texttt{SCARD\_ATTR\_DEVICE\_FRIENDLY\_NAME\_W}
\item \texttt{SCARD\_ATTR\_DEVICE\_IN\_USE}
\item \texttt{SCARD\_ATTR\_DEVICE\_SYSTEM\_NAME\_A}
\item \texttt{SCARD\_ATTR\_DEVICE\_SYSTEM\_NAME\_W}
\item \texttt{SCARD\_ATTR\_DEVICE\_UNIT}
\item \texttt{SCARD\_ATTR\_ESC\_AUTHREQUEST}
\item \texttt{SCARD\_ATTR\_ESC\_CANCEL}
\item \texttt{SCARD\_ATTR\_ESC\_RESET}
\item \texttt{SCARD\_ATTR\_EXTENDED\_BWT}
\item \texttt{SCARD\_ATTR\_ICC\_INTERFACE\_STATUS}
\item \texttt{SCARD\_ATTR\_ICC\_PRESENCE}
\item \texttt{SCARD\_ATTR\_ICC\_TYPE\_PER\_ATR}
\item \texttt{SCARD\_ATTR\_MAX\_CLK}
\item \texttt{SCARD\_ATTR\_MAX\_DATA\_RATE}
\item \texttt{SCARD\_ATTR\_MAX\_IFSD}
\item \texttt{SCARD\_ATTR\_MAXINPUT}
\item \texttt{SCARD\_ATTR\_POWER\_MGMT\_SUPPORT}
\item \texttt{SCARD\_ATTR\_SUPRESS\_T1\_IFS\_REQUEST}
\item \texttt{SCARD\_ATTR\_SYNC\_PROTOCOL\_TYPES}
\item \texttt{SCARD\_ATTR\_USER\_AUTH\_INPUT\_DEVICE}
\item \texttt{SCARD\_ATTR\_USER\_TO\_CARD\_AUTH\_DEVICE}
\item \texttt{SCARD\_ATTR\_VENDOR\_IFD\_SERIAL\_NO}
\item \texttt{SCARD\_ATTR\_VENDOR\_IFD\_TYPE}
\item \texttt{SCARD\_ATTR\_VENDOR\_IFD\_VERSION}
\item \texttt{SCARD\_ATTR\_VENDOR\_NAME}
\end{itemize}
Not all the \texttt{dwAttrId} values listed above may be implemented in
the IFD Handler you are using. And some \texttt{dwAttrId} values not
listed here may be implemented.
\example
\begin{verbatim}
LONG rv;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
unsigned char pbAtr[MAX_ATR_SIZE];
DWORD dwAtrLen;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_RAW &hCard, &dwActiveProtocol);
rv = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, pbAtr, &dwAtrLen);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_NOT\_TRANSACTED} & Data exchange not successful\\
\texttt{SCARD\_E\_INSUFFICIENT\_BUFFER} & Reader buffer not large enough \\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{SCardSetAttrib}
\synopsis
\begin{verbatim}
#include <winscard.h>
LONG SCardSetAttrib(SCARDHANDLE hCard,
DWORD dwAttrId,
LPCBYTE pbAttr,
DWORD cbAttrLen);
\end{verbatim}
\parameters
\begin{tabular}{lll}
\texttt{hCard} & IN & Connection made from \texttt{SCardConnect}\\
\texttt{dwAttrId} & IN & Identifier for the attribute to get \\
\texttt{pbAttr} & IN & Pointer to a buffer that receives the attribute \\
\texttt{pcbAttrLen} & IN & Length of the \texttt{pbAttr} buffer in bytes \\
\end{tabular}
\desc
This function set an attribute of the IFD Handler. The list of
attributes you can set is dependent on the IFD Handler you are using.
\example
\begin{verbatim}
LONG rv;
SCARDCONTEXT hContext;
SCARDHANDLE hCard;
DWORD dwActiveProtocol;
unsigned char pbAtr[MAX_ATR_SIZE];
DWORD dwAtrLen;
rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
rv = SCardConnect(hContext, "Reader X", SCARD_SHARE_SHARED,
SCARD_PROTOCOL_RAW &hCard, &dwActiveProtocol);
rv = SCardSetAttrib(hCard, 0x42000001, "\x12\x34\x56", 3);
\end{verbatim}
\returns
\begin{tabular}{ll}
\texttt{SCARD\_S\_SUCCESS} & Successful\\
\texttt{SCARD\_E\_NOT\_TRANSACTED} & Data exchange not successful\\
\end{tabular}
%---------%---------%---------%---------%---------%---------
\subsection{pcsc\_stringify\_error}
\synopsis
\begin{verbatim}
#include <pcsclite.h>
char *pcsc_stringify_error(long error);
\end{verbatim}
\desc
This function return a human readable text for the given PC/SC error
code.
\example
\begin{verbatim}
SCARDCONTEXT hContext;
LONG rv;
rv = SCardEstablishContext(SCARD\_SCOPE\_SYSTEM, NULL, NULL, &hContext);
if (rv != SCARD_S_SUCCESS)
printf("SCardEstablishContext: %s (0x%lX)\n",
pcsc_stringify_error(rv), rv);
\end{verbatim}
%---------%---------%---------%---------%---------%---------
\subsection{log\_msg and log\_xxd}
The \texttt{pcscd} daemon (part of pcsc-lite) provides two functions
that can be used to log debug messages. You should not use
\texttt{log\_msg()} directly but use the macros defined in
\texttt{/usr/include/PCSC/debuglog.h}.
These logging functions are used by some IFD handlers (smart card
driver) like the CCID driver
\url{http://pcsclite.alioth.debian.org/ccid.html} to benefit from the
log framework offered by \texttt{pcscd} (the daemon). With these
functions it is easy to change the log level (debug, info, error or
critical) and the log output (syslog or stderr) without recompiling the
driver.
%---------%---------%---------%---------%---------%---------%---------
\section{Multithreading and contexts}
From version 1.2.0 pcsc-lite is much more multithreading friendly.
You have to follow some rules:
\begin{itemize}
\item For security reasons, a context can only be released (using
\texttt{SCardReleaseContext()}) by the thread that created it.
\item To access different readers (\emph{i.e.} cards) in different
threads, each thread must use a different context (not necessarily
created by this thread itself).
\end{itemize}
Each thread should create his own context with
\texttt{SCardEstablishContext()} and should release it with
\texttt{SCardReleaseContext()} when the context is not necessary any
more.
If different threads share a same context, the calls to different
functions of the pcsc-lite API are stored in a queue and the executions
serialised for this context because there is a mutex shared for all the
(critical) operations of this context.
Note: The SCF (Smart Card Framework) used by Solaris has not been
updated. So if you compile pcsc-lite using \texttt{./configure
--enable-scf} you will still have a global lock mechanism.
%---------%---------%---------%---------%---------%---------%---------
\section{Some SCardControl commands}
\label{Some SCardControl commands}
The commands described here may not be implemented by all the drivers.
They are implemented by the CCID driver available at
\url{http://pcsclite.alioth.debian.org/ccid.html} and maybe some other.
The tag names used by these functions are
\texttt{IOCTL\_SMARTCARD\_VENDOR\_*}. They are vendor (driver) specific.
%---------%---------%---------%---------%---------%---------
\subsection{IFD\_EXCHANGE}
This command is used to send a proprietary command to a reader.
The CCID specification~\cite{ccid_spec} describes a
\texttt{PC\_to\_RDR\_Escape} command to send proprietary commands to the
reader.
\example
\begin{verbatim}
#include <winscard.h>
#include <reader.h>
#define IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE SCARD_CTL_CODE(1)
SCARDHANDLE hCard;
unsigned char bSendBuffer[MAX_BUFFER_SIZE];
unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
DWORD length;
/* get firmware */
bSendBuffer[0] = 0x02; /* proprietary code for Gemplus CCID readers */
rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE,
bSendBuffer, 1, bRecvBuffer, sizeof(bRecvBuffer), &length);
printf(" Firmware: ");
for (i=0; i<length; i++)
printf("%02X ", bRecvBuffer[i]);
printf("\n");
\end{verbatim}
%---------%---------%---------%---------%---------%---------
\subsection{VERIFY\_PIN and MODIFY\_PIN}
The CCID specification~\cite{ccid_spec} describes a
\texttt{PC\_to\_RDR\_Secure} command to perform a PIN verification or
PIN modification without sending the PIN to the host. The reader must
have a keyboard, and optionnaly a display.
The command format is described in the PCSCv2 part 10
specifications~\cite{pcsc_v2_part10}.
The \texttt{bSendBuffer} to pass to \texttt{SCardControl()} contains:
\begin{itemize}
\item the CCID \texttt{abPINDataStructure}
This is the CCID structure used to parameter the PIN verification
command.
\item the VERIFY APDU
That is the APDU sent to the card with the PIN code values replaced by
the actually entered PIN code. See the CCID
specification~\cite{ccid_spec} for a more precise descruption.
\end{itemize}
\example
\begin{verbatim}
#include <winscard.h>
#include <reader.h>
LONG rv;
SCARDHANDLE hCard;
unsigned char bSendBuffer[MAX_BUFFER_SIZE];
unsigned char bRecvBuffer[MAX_BUFFER_SIZE];
DWORD verify_ioctl = 0;
DWORD modify_ioctl = 0;
PIN_VERIFY_STRUCTURE *pin_verify;
/* does the reader support PIN verification? */
rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0,
bRecvBuffer, sizeof(bRecvBuffer), &length);
/* get the number of elements instead of the complete size */
length /= sizeof(PCSC_TLV_STRUCTURE);
pcsc_tlv = (PCSC_TLV_STRUCTURE *)bRecvBuffer;
for (i = 0; i < length; i++)
{
if (pcsc_tlv[i].tag == FEATURE_VERIFY_PIN_DIRECT)
verify_ioctl = pcsc_tlv[i].value;
if (pcsc_tlv[i].tag == FEATURE_MODIFY_PIN_DIRECT)
modify_ioctl = pcsc_tlv[i].value;
}
if (0 == verify_ioctl)
{
printf("Reader %s does not support PIN verification\n",
readers[reader_nb]);
return;
}
pin_verify = (PIN_VERIFY_STRUCTURE *)bSendBuffer;
/* PC/SC v2.0.2 Part 10 PIN verification data structure */
pin_verify -> bTimerOut = 0x00;
pin_verify -> bTimerOut2 = 0x00;
pin_verify -> bmFormatString = 0x82;
pin_verify -> bmPINBlockString = 0x04;
pin_verify -> bmPINLengthFormat = 0x00;
pin_verify -> wPINMaxExtraDigit = HOST_TO_CCID_16(0x0408); /* Min Max */
pin_verify -> bEntryValidationCondition = 0x02; /* validation key pressed */
pin_verify -> bNumberMessage = 0x01;
pin_verify -> wLangId = HOST_TO_CCID_16(0x0904);
pin_verify -> bMsgIndex = 0x00;
pin_verify -> bTeoPrologue[0] = 0x00;
pin_verify -> bTeoPrologue[1] = 0x00;
pin_verify -> bTeoPrologue[2] = 0x00;
/* pin_verify -> ulDataLength = 0x00; we don't know the size yet */
/* APDU: 00 20 00 00 08 30 30 30 30 00 00 00 00 */
offset = 0;
pin_verify -> abData[offset++] = 0x00; /* CLA */
pin_verify -> abData[offset++] = 0x20; /* INS: VERIFY */
pin_verify -> abData[offset++] = 0x00; /* P1 */
pin_verify -> abData[offset++] = 0x00; /* P2 */
pin_verify -> abData[offset++] = 0x08; /* Lc: 8 data bytes */
pin_verify -> abData[offset++] = 0x30; /* '0' */
pin_verify -> abData[offset++] = 0x30; /* '0' */
pin_verify -> abData[offset++] = 0x30; /* '0' */
pin_verify -> abData[offset++] = 0x30; /* '0' */
pin_verify -> abData[offset++] = 0x00; /* '\0' */
pin_verify -> abData[offset++] = 0x00; /* '\0' */
pin_verify -> abData[offset++] = 0x00; /* '\0' */
pin_verify -> abData[offset++] = 0x00; /* '\0' */
pin_verify -> ulDataLength = HOST_TO_CCID_32(offset); /* APDU size */
length = sizeof(PIN_VERIFY_STRUCTURE) + offset -1;
/* -1 because PIN_VERIFY_STRUCTURE contains the first byte of abData[] */
printf("Enter your PIN: ");
fflush(stdout);
rv = SCardControl(hCard, verify_ioctl, bSendBuffer,
length, bRecvBuffer, sizeof(bRecvBuffer), &length);
\end{verbatim}
%---------%---------%---------%---------%---------%---------
\bibliographystyle{plain}
\bibliography{pcsc-lite}
\end{document}