#include <syslog.h>
#include <string.h>
#include "config.h"
#include "wintypes.h"
#include "pcsclite.h"
#include "debuglog.h"
#include "atrhandler.h"
short ATRDecodeAtr(PSMARTCARD_EXTENSION psExtension,
const unsigned char *pucAtr, DWORD dwLength)
{
USHORT p;
UCHAR K, TCK;
UCHAR Y1i, T;
int i = 1;
p = K = TCK = Y1i = T = 0;
#ifdef ATR_DEBUG
if (dwLength > 0)
LogXxd(PCSC_LOG_DEBUG, "ATR: ", pucAtr, dwLength);
#endif
if (dwLength < 2)
return 0;
psExtension->CardCapabilities.AvailableProtocols = SCARD_PROTOCOL_UNDEFINED;
psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_UNDEFINED;
if (pucAtr[0] == 0x3F)
{
psExtension->CardCapabilities.Convention = SCARD_CONVENTION_INVERSE;
}
else
if (pucAtr[0] == 0x3B)
{
psExtension->CardCapabilities.Convention = SCARD_CONVENTION_DIRECT;
}
else
{
memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION));
return 0;
}
Y1i = pucAtr[1] >> 4;
K = pucAtr[1] & 0x0F;
p = 2;
#ifdef ATR_DEBUG
Log4(PCSC_LOG_DEBUG, "Conv: %02X, Y1: %02X, K: %02X",
psExtension->CardCapabilities.Convention, Y1i, K);
#endif
do
{
short TAi, TBi, TCi, TDi;
TAi = (Y1i & 0x01) ? pucAtr[p++] : -1;
TBi = (Y1i & 0x02) ? pucAtr[p++] : -1;
TCi = (Y1i & 0x04) ? pucAtr[p++] : -1;
TDi = (Y1i & 0x08) ? pucAtr[p++] : -1;
#ifdef ATR_DEBUG
Log9(PCSC_LOG_DEBUG,
"TA%d: %02X, TB%d: %02X, TC%d: %02X, TD%d: %02X",
i, TAi, i, TBi, i, TCi, i, TDi);
#endif
if (TDi >= 0)
{
Y1i = TDi >> 4;
T = TDi & 0x0F;
if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNDEFINED)
{
switch (T)
{
case 0:
psExtension->CardCapabilities.CurrentProtocol =
SCARD_PROTOCOL_T0;
break;
case 1:
psExtension->CardCapabilities.CurrentProtocol =
SCARD_PROTOCOL_T1;
break;
default:
return 0;
}
}
#ifdef ATR_DEBUG
Log2(PCSC_LOG_DEBUG, "T=%d Protocol Found", T);
#endif
if (0 == T)
{
psExtension->CardCapabilities.AvailableProtocols |=
SCARD_PROTOCOL_T0;
}
else
if (1 == T)
{
psExtension->CardCapabilities.AvailableProtocols |=
SCARD_PROTOCOL_T1;
}
else
if (15 == T)
{
psExtension->CardCapabilities.AvailableProtocols |=
SCARD_PROTOCOL_T15;
}
else
{
}
} else
Y1i = 0;
if ((2 == i) && (TAi >= 0))
{
T = TAi & 0x0F;
#ifdef ATR_DEBUG
Log2(PCSC_LOG_DEBUG, "Specific mode: T=%d", T);
#endif
switch (T)
{
case 0:
psExtension->CardCapabilities.CurrentProtocol =
psExtension->CardCapabilities.AvailableProtocols =
SCARD_PROTOCOL_T0;
break;
case 1:
psExtension->CardCapabilities.CurrentProtocol =
psExtension->CardCapabilities.AvailableProtocols =
SCARD_PROTOCOL_T1;
break;
default:
return 0;
}
}
if (p > MAX_ATR_SIZE)
{
memset(psExtension, 0x00, sizeof(SMARTCARD_EXTENSION));
return 0;
}
i++;
}
while (Y1i != 0);
if (psExtension->CardCapabilities.CurrentProtocol == SCARD_PROTOCOL_UNDEFINED)
{
psExtension->CardCapabilities.CurrentProtocol = SCARD_PROTOCOL_T0;
psExtension->CardCapabilities.AvailableProtocols |= SCARD_PROTOCOL_T0;
}
psExtension->ATR.HistoryLength = K;
memcpy(psExtension->ATR.HistoryValue, &pucAtr[p], K);
p = p + K;
if (psExtension->CardCapabilities.AvailableProtocols & SCARD_PROTOCOL_T1)
TCK = pucAtr[p++];
memcpy(psExtension->ATR.Value, pucAtr, p);
psExtension->ATR.Length = p;
#ifdef ATR_DEBUG
Log3(PCSC_LOG_DEBUG, "CurrentProtocol: %d, AvailableProtocols: %d",
psExtension->CardCapabilities.CurrentProtocol,
psExtension->CardCapabilities.AvailableProtocols);
#endif
return 1;
}