⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parseatr.cpp

📁 usblsccid-0.9.2: ED1x Smart Card Reader Driver
💻 CPP
字号:
//adapt from wince driver smcutil.c
#include "stdafx.h"
#include "parseATR.h"

static ULONG 
Pow2(
	UCHAR Exponent
	)
{
	ULONG result = 1;

	while(Exponent--)
		result *= 2;

	return result;
}	

VOID
SmartcardInvertData(
	PUCHAR Buffer,
	ULONG Length
    )
{
	ULONG i;

	for (i = 0; i < Length; i++) {

		UCHAR j, inv = 0;

		for (j = 0; j < 8; j++) {

			if (Buffer[i] & (1 << j)) {

				inv |= 1 << (7 - j);
			}
		}
		Buffer[i] = (inv ^ 0xFF);
	}
}

CString parseATR(
    PUCHAR atrString, ULONG atrLength,PSCARD_CARD_CAPABILITIES cardCapabilities ,ULONG fs
    )
{
	UCHAR Y, Tck, TA[MAXIMUM_ATR_CODES], TB[MAXIMUM_ATR_CODES];
	UCHAR TC[MAXIMUM_ATR_CODES], TD[MAXIMUM_ATR_CODES];
	ULONG i,numProtocols = 0, protocolTypes = 0;
	BOOLEAN TA2Present = FALSE;

	if (atrLength < 2)
		return _T("ATR is too short (Min. length is 2)");

	if (atrString[0] != 0x3b && atrString[0] != 0x3f && atrString[0] != 0x03)
        return _T("Initial character of ATR is invalid");

	// Test for invers convention
	if (*atrString == 0x03) {
		cardCapabilities->InversConvention = TRUE;
        //
        // When the ATR starts with 0x03 then it 
        // has not been inverted already         	
        //
    	SmartcardInvertData(
            cardCapabilities->ATR.Buffer, 
            cardCapabilities->ATR.Length
            );             	
        TRACE(_T("Card uses Inverse Convention\n"));
	} 


	//
	// The caller might be calling this function repeatedly in order to 
	// test if the ATR is valid. If the ATR we currently have here is
	// not valid then we need to be able re-invert an inverted ATR.
	//

	atrString += 1;
	atrLength -= 1;

	//
	// Calculate check char, but do not test now since if only T=0 
	// is present the ATR doesn't contain a check char
	//
	for (i = 0, Tck = 0; i < atrLength; i++)
		    Tck ^= atrString[i];

	// Initialize various data
	cardCapabilities->Protocol.Supported = 0;

	memset(TA,0, sizeof(TA));
	memset(TB,0, sizeof(TB));
	memset(TC,0, sizeof(TC));
	memset(TD,0, sizeof(TD));

	//
	// Set default values as described in ISO 7816-3
	//
    
	// TA1 codes Fl in high-byte and Dl in low-byte;
	TA[0] = 0x11;
	// TB1 codes II in bits b7/b6 and Pl1 in b5-b1. b8 has to be 0
	TB[0] = 0x25;
	// TC2 codes T=0 WI
	TC[1] = 10;

	// Translate ATR string to TA to TD values (See ISO)
	cardCapabilities->HistoricalChars.Length = *atrString & 0x0f;

	Y = *atrString++ & 0xf0;
	atrLength -= 1;

	for (i = 0; i < MAXIMUM_ATR_CODES; i++) {
		if (Y & 0x10) {
			if (i == 1)
				TA2Present = TRUE;              	
			TA[i] = *atrString++;
        	atrLength -= 1;
		}
		if (Y & 0x20) {
			TB[i] = *atrString++;
			atrLength -= 1;
		}
		if (Y & 0x40) {
			TC[i] = *atrString++;
			atrLength -= 1;
		}
		if (Y & 0x80) {
			Y = *atrString & 0xf0;
			TD[i] = *atrString++ & 0x0f;
			atrLength -= 1;
			// Check if the next parameters are for a new protocol.
			if (((1 << TD[i]) & protocolTypes) == 0) {
				// Count the number of protocols that the card supports
				numProtocols++;
			}
			protocolTypes |= 1 << TD[i];
		} else {
			    break;
		}
	} 

	// Check if the card supports a protocol other than T=0
	if (protocolTypes & ~1) {
		//
		// The atr contains a checksum byte.
		// Exclude that from the historical byte length check
		//
		atrLength -=1;     	

		//
		// This card supports more than one protocol or a protocol 
		// other than T=0, so test if the checksum is correct
		//
		if (Tck != 0)
                return _T("ATR Checksum is invalid");
	}

	if (atrLength < 0 ||
            atrLength != cardCapabilities->HistoricalChars.Length) {
            return _T("ATR length is inconsistent");
	}
       
    // store historical characters
	memcpy(
		cardCapabilities->HistoricalChars.Buffer,
		atrString,
		cardCapabilities->HistoricalChars.Length
		);

    //
	// Now convert TA - TD values to global interface bytes
    //

	// Clock rate conversion
	cardCapabilities->Fl = (TA[0] & 0xf0) >> 4;

	// bit rate adjustment
	cardCapabilities->Dl = (TA[0] & 0x0f);

	// Maximum programming current factor
	cardCapabilities->II = (TB[0] & 0xc0) >> 6;

	// Programming voltage in 0.1 Volts
	cardCapabilities->P = (TB[1] ? TB[1] : (TB[0] & 0x1f) * 10);

	// Extra guard time
	cardCapabilities->N = TC[0];

	//
	// Check if the Dl and Fl values are valid
	// 
	if (BitRateAdjustment[cardCapabilities->Dl].DNumerator == 0 ||
		ClockRateConversion[cardCapabilities->Fl].F == 0) {
        return _T("Dl or Fl invalid");
	}

    TRACE(
        _T("Card parameters from ATR:\n      Fl = %02x (%ld KHz), Dl = %02x, I = %02x, P = %02x, N = %02x\n"),
        cardCapabilities->Fl,
        ClockRateConversion[cardCapabilities->Fl].fs / 1000,
        cardCapabilities->Dl,
        cardCapabilities->II,
        cardCapabilities->P,
        cardCapabilities->N
        );

    //
    // assume default clock frequency
    //
    if (fs == 0) 
        fs = 372 * 9600l;

    cardCapabilities->PtsData.Fl = cardCapabilities->Fl;
    cardCapabilities->PtsData.Dl = cardCapabilities->Dl;
    //
    // We calculate the ETU on basis of the timing supplied by the 
    // clk-frequency of the reader
    //
    //
    // Work etu in units of time resolution(TR) (NOT in seconds)
    //
    cardCapabilities->etu = 
        1 +     // required to round up
   		(TR * 
   		BitRateAdjustment[cardCapabilities->Dl].DDivisor *
		ClockRateConversion[cardCapabilities->Fl].F) /
   		(BitRateAdjustment[cardCapabilities->Dl].DNumerator * 
        fs);

    //
	// guard time in micro seconds
    // the guard time is the gap between the end of the
    // current character and the beginning of the next character
    //
    cardCapabilities->GT = 0;

    if (cardCapabilities->N == 0)
        cardCapabilities->PtsData.StopBits = 2;
    else if (cardCapabilities->N == 255)
        cardCapabilities->PtsData.StopBits = 1;   	
    else
	    cardCapabilities->GT = cardCapabilities->N * cardCapabilities->etu;

    TRACE(
        _T("Calculated timing values:\n      Work etu = %ld micro sec, Guard time = %ld micro sec\n"),
        cardCapabilities->etu,
        cardCapabilities->GT);

    //
	// Now find protocol specific data
    //

    if (TD[0] == 0) {
        
		cardCapabilities->Protocol.Supported |=
			SCARD_PROTOCOL_T0;

		cardCapabilities->T0.WI = TC[1];

		if (cardCapabilities->PtsData.Dl > 0 && 
            cardCapabilities->PtsData.Dl < 6) {

			cardCapabilities->T0.WT = 1 +
				cardCapabilities->T0.WI *
				960 * cardCapabilities->etu * 
		   		Pow2((UCHAR) (cardCapabilities->PtsData.Dl - 1));

		} else { 

			cardCapabilities->T0.WT = 1+
				cardCapabilities->T0.WI *
				960 * cardCapabilities->etu /
		   		Pow2((UCHAR) (cardCapabilities->PtsData.Dl - 1));			        
		} 

        TRACE(
            _T("T=0 Values from ATR:\n      WI = %ld\n"),
            cardCapabilities->T0.WI
            );
        TRACE(
            _T("T=0 Timing from ATR:\n      WT = %ld ms\n"),
            cardCapabilities->T0.WT / 1000
            );
    }

    if (protocolTypes & SCARD_PROTOCOL_T1) {

        for (i = 0; TD[i] != 1 && i < MAXIMUM_ATR_CODES; i++)
            ;
    
        for (; TD[i] == 1 && i < MAXIMUM_ATR_CODES; i++) 
            ;

        if (i == MAXIMUM_ATR_CODES) {

            return _T("Parse T1 error");         	
        }

		cardCapabilities->Protocol.Supported |= 
			SCARD_PROTOCOL_T1;

		cardCapabilities->T1.IFSC = 
			(TA[i] ? TA[i] : 32);

		cardCapabilities->T1.CWI = 
			((TB[i] & 0x0f) ? (TB[i] & 0x0f) : T1_CWI_DEFAULT);

		cardCapabilities->T1.BWI = 
			((TB[i] & 0xf0) >> 4 ? (TB[i] & 0xf0) >> 4 : T1_BWI_DEFAULT);

		cardCapabilities->T1.EDC = 
			(TC[i] & 0x01);

		cardCapabilities->T1.CWT = 1 +
			(Pow2(cardCapabilities->T1.CWI) + 11) * cardCapabilities->etu;

		cardCapabilities->T1.BWT = 1 +
			((Pow2(cardCapabilities->T1.BWI) * TR) / 10) + 
			11 * cardCapabilities->etu;

        TRACE(
            _T("   T=1 Values from ATR:\n      IFSC = %ld, CWI = %ld, BWI = %ld, EDC = %02x\n"),
            cardCapabilities->T1.IFSC,
            cardCapabilities->T1.CWI,
            cardCapabilities->T1.BWI,
            cardCapabilities->T1.EDC
            );
        TRACE(
            _T("   T=1 Timing from ATR:\n      CWT = %ld ms, BWT = %ld ms\n"),
            cardCapabilities->T1.CWT / 1000,
            cardCapabilities->T1.BWT / 1000
            );
    }

   return _T("");
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -