2
* MUSCLE SmartCard Development ( http://www.linuxnet.com )
4
* Copyright (C) 1999-2004
5
* David Corcoran <corcoran@linuxnet.com>
6
* Ludovic Rousseau <ludovic.rousseau@free.fr>
8
* $Id: atrhandler.c 1421 2005-04-12 12:09:21Z rousseau $
14
* @brief This keeps track of smartcard protocols, timing issues
15
* and ATR (Answer-to-Reset) handling.
17
* @note use ./configure --enable-debugatr to enable debug messages
27
#include "atrhandler.h"
30
* Uncomment the following for ATR debugging
31
* or use ./configure --enable-debugatr
33
/* #define ATR_DEBUG */
42
short ATRDecodeAtr(PSMARTCARD_EXTENSION psExtension,
43
PUCHAR pucAtr, DWORD dwLength)
46
UCHAR K, TCK; /* MSN of T0/Check Sum */
47
UCHAR Y1i, T; /* MSN/LSN of TDi */
48
int i = 1; /* value of the index in TAi, TBi, etc. */
53
p = K = TCK = Y1i = T = 0;
57
LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength);
61
return 0; /** @retval 0 Atr must have TS and T0 */
64
* Zero out the bitmasks
66
psExtension->CardCapabilities.AvailableProtocols = SCARD_PROTOCOL_UNSET;
67
psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_UNSET;
72
if (pucAtr[0] == 0x3F)
73
{ /* Inverse convention used */
74
psExtension->CardCapabilities.Convention = SCARD_CONVENTION_INVERSE;
77
if (pucAtr[0] == 0x3B)
78
{ /* Direct convention used */
79
psExtension->CardCapabilities.Convention = SCARD_CONVENTION_DIRECT;
83
memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION));
84
return 0; /** @retval 0 Unable to decode TS byte */
88
* Here comes the platform dependant stuff
94
Y1i = pucAtr[1] >> 4; /* Get the MSN in Y1 */
95
K = pucAtr[1] & 0x0F; /* Get the LSN in K */
100
Log4(PCSC_LOG_DEBUG, "Conv: %02X, Y1: %02X, K: %02X",
101
psExtension->CardCapabilities.Convention, Y1i, K);
109
short TAi, TBi, TCi, TDi; /* Interface characters */
111
TAi = (Y1i & 0x01) ? pucAtr[p++] : -1;
112
TBi = (Y1i & 0x02) ? pucAtr[p++] : -1;
113
TCi = (Y1i & 0x04) ? pucAtr[p++] : -1;
114
TDi = (Y1i & 0x08) ? pucAtr[p++] : -1;
118
"TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X",
119
i, TAi, i, TBi, i, TCi, i, TDi);
123
* Examine TDi to determine protocol and more
127
Y1i = TDi >> 4; /* Get the MSN in Y1 */
128
T = TDi & 0x0F; /* Get the LSN in K */
131
* Set the current protocol TD1 (first TD only)
133
if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNSET)
138
psExtension->CardCapabilities.CurrentProtocol =
142
psExtension->CardCapabilities.CurrentProtocol =
146
return 0; /** @retval 0 Unable to decode LNS */
151
Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T);
155
psExtension->CardCapabilities.AvailableProtocols |=
157
psExtension->CardCapabilities.T0.BGT = 0;
158
psExtension->CardCapabilities.T0.BWT = 0;
159
psExtension->CardCapabilities.T0.CWT = 0;
160
psExtension->CardCapabilities.T0.CGT = 0;
161
psExtension->CardCapabilities.T0.WT = 0;
166
psExtension->CardCapabilities.AvailableProtocols |=
168
psExtension->CardCapabilities.T1.BGT = 0;
169
psExtension->CardCapabilities.T1.BWT = 0;
170
psExtension->CardCapabilities.T1.CWT = 0;
171
psExtension->CardCapabilities.T1.CGT = 0;
172
psExtension->CardCapabilities.T1.WT = 0;
177
psExtension->CardCapabilities.AvailableProtocols |=
183
* Do nothing for now since other protocols are not
184
* supported at this time
188
/* test presence of TA2 */
189
if ((2 == i) && (TAi >= 0))
193
Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T);
198
psExtension->CardCapabilities.CurrentProtocol =
199
psExtension->CardCapabilities.AvailableProtocols =
204
psExtension->CardCapabilities.CurrentProtocol =
205
psExtension->CardCapabilities.AvailableProtocols =
210
return 0; /** @retval 0 Unable do decode T protocol */
216
if (p > MAX_ATR_SIZE)
218
memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION));
219
return 0; /** @retval 0 Maximum attribute size */
222
/* next interface characters index */
228
* If TDx is not set then the current must be T0
230
if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNSET)
232
psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_T0;
233
psExtension->CardCapabilities.AvailableProtocols |= SCARD_PROTOCOL_T0;
237
* Take care of the historical characters
239
psExtension->ATR.HistoryLength = K;
240
memcpy(psExtension->ATR.HistoryValue, &pucAtr[p], K);
245
* Check to see if TCK character is included It will be included if
246
* more than T=0 is supported
248
if (psExtension->CardCapabilities.AvailableProtocols & SCARD_PROTOCOL_T1)
251
memcpy(psExtension->ATR.Value, pucAtr, p);
252
psExtension->ATR.Length = p; /* modified from p-1 */
255
Log3(PCSC_LOG_DEBUG, "CurrentProtocol: %d, AvailableProtocols: %d",
256
psExtension->CardCapabilities.CurrentProtocol,
257
psExtension->CardCapabilities.AvailableProtocols);
260
return 1; /** @retval 1 Success */