pcsc-lite  1.8.3
atrhandler.c
Go to the documentation of this file.
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 }