pcsc-lite
1.8.3
|
00001 /* 00002 * MUSCLE SmartCard Development ( http://www.linuxnet.com ) 00003 * 00004 * Copyright (C) 1999-2002 00005 * David Corcoran <corcoran@linuxnet.com> 00006 * Copyright (C) 2002-2011 00007 * Ludovic Rousseau <ludovic.rousseau@free.fr> 00008 * 00009 * $Id: atrhandler.c 5962 2011-09-24 08:24:34Z rousseau $ 00010 */ 00011 00022 #include "config.h" 00023 #include <string.h> 00024 00025 #include "misc.h" 00026 #include "pcsclite.h" 00027 #include "debuglog.h" 00028 #include "atrhandler.h" 00029 00030 /* 00031 * Uncomment the following for ATR debugging 00032 * or use ./configure --enable-debugatr 00033 */ 00034 /* #define ATR_DEBUG */ 00035 00045 short ATRDecodeAtr(int *availableProtocols, int *currentProtocol, 00046 PUCHAR pucAtr, DWORD dwLength) 00047 { 00048 USHORT p; 00049 UCHAR Y1i, T; /* MSN/LSN of TDi */ 00050 int i = 1; /* value of the index in TAi, TBi, etc. */ 00051 00052 #ifdef ATR_DEBUG 00053 if (dwLength > 0) 00054 LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength); 00055 #endif 00056 00057 if (dwLength < 2) 00058 return 0; 00060 /* 00061 * Zero out the bitmasks 00062 */ 00063 *availableProtocols = SCARD_PROTOCOL_UNDEFINED; 00064 *currentProtocol = SCARD_PROTOCOL_UNDEFINED; 00065 00066 /* 00067 * Decode the TS byte 00068 */ 00069 if ((pucAtr[0] != 0x3F) && (pucAtr[0] != 0x3B)) 00070 return 0; 00072 /* 00073 * Here comes the platform dependant stuff 00074 */ 00075 00076 /* 00077 * Decode the T0 byte 00078 */ 00079 Y1i = pucAtr[1] >> 4; /* Get the MSN in Y1 */ 00080 00081 p = 2; 00082 00083 /* 00084 * Examine Y1 00085 */ 00086 do 00087 { 00088 short TAi, TBi, TCi, TDi; /* Interface characters */ 00089 00090 TAi = (Y1i & 0x01) ? pucAtr[p++] : -1; 00091 TBi = (Y1i & 0x02) ? pucAtr[p++] : -1; 00092 TCi = (Y1i & 0x04) ? pucAtr[p++] : -1; 00093 TDi = (Y1i & 0x08) ? pucAtr[p++] : -1; 00094 00095 #ifdef ATR_DEBUG 00096 Log9(PCSC_LOG_DEBUG, 00097 "TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X", 00098 i, TAi, i, TBi, i, TCi, i, TDi); 00099 #endif 00100 00101 /* 00102 * Examine TDi to determine protocol and more 00103 */ 00104 if (TDi >= 0) 00105 { 00106 Y1i = TDi >> 4; /* Get the MSN in Y1 */ 00107 T = TDi & 0x0F; /* Get the LSN in K */ 00108 00109 /* 00110 * Set the current protocol TD1 (first TD only) 00111 */ 00112 if (*currentProtocol == SCARD_PROTOCOL_UNDEFINED) 00113 { 00114 switch (T) 00115 { 00116 case 0: 00117 *currentProtocol = SCARD_PROTOCOL_T0; 00118 break; 00119 case 1: 00120 *currentProtocol = SCARD_PROTOCOL_T1; 00121 break; 00122 default: 00123 return 0; 00124 } 00125 } 00126 00127 #ifdef ATR_DEBUG 00128 Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T); 00129 #endif 00130 if (0 == T) 00131 { 00132 *availableProtocols |= SCARD_PROTOCOL_T0; 00133 } 00134 else 00135 if (1 == T) 00136 { 00137 *availableProtocols |= SCARD_PROTOCOL_T1; 00138 } 00139 else 00140 if (15 == T) 00141 { 00142 *availableProtocols |= SCARD_PROTOCOL_T15; 00143 } 00144 else 00145 { 00146 /* 00147 * Do nothing for now since other protocols are not 00148 * supported at this time 00149 */ 00150 } 00151 } 00152 else 00153 Y1i = 0; 00154 00155 /* test presence of TA2 */ 00156 if ((2 == i) && (TAi >= 0)) 00157 { 00158 T = TAi & 0x0F; 00159 #ifdef ATR_DEBUG 00160 Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T); 00161 #endif 00162 switch (T) 00163 { 00164 case 0: 00165 *currentProtocol = *availableProtocols = SCARD_PROTOCOL_T0; 00166 break; 00167 00168 case 1: 00169 *currentProtocol = *availableProtocols = SCARD_PROTOCOL_T1; 00170 break; 00171 00172 default: 00173 return 0; 00174 } 00175 } 00176 00177 if (p > MAX_ATR_SIZE) 00178 return 0; 00180 /* next interface characters index */ 00181 i++; 00182 } 00183 while (Y1i != 0); 00184 00185 /* 00186 * If TDx is not set then the current must be T0 00187 */ 00188 if (*currentProtocol == SCARD_PROTOCOL_UNDEFINED) 00189 { 00190 *currentProtocol = SCARD_PROTOCOL_T0; 00191 *availableProtocols |= SCARD_PROTOCOL_T0; 00192 } 00193 00194 #ifdef ATR_DEBUG 00195 Log3(PCSC_LOG_DEBUG, "CurrentProtocol: %d, AvailableProtocols: %d", 00196 *currentProtocol, *availableProtocols); 00197 #endif 00198 00199 return 1; 00200 }