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
1740 lines
50 KiB
4 years ago
|
%
|
||
|
% 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}
|
||
|
|