|
|
/*****************************************************************************
@doc INT EXT ****************************************************************************** * $ProjectName: $ * $ProjectRevision: $ *----------------------------------------------------------------------------- * $Source: z:/pr/cmbp0/sw/cmbp0.ms/rcs/cmbp0scr.c $ * $Revision: 1.7 $ *----------------------------------------------------------------------------- * $Author: WFrischauf $ *----------------------------------------------------------------------------- * History: see EOF *----------------------------------------------------------------------------- * * Copyright � 2000 OMNIKEY AG ******************************************************************************/
#include <cmbp0wdm.h>
#include <cmbp0scr.h>
#include <cmbp0log.h>
// this is a FI / Fi assignment
const ULONG Fi[] = { 372, 372, 588, 744, 1116, 1488, 1860, 372, 372, 512, 768, 1024, 1536, 2048, 372, 372};
// this is a DI / Di assignment
const ULONG Di[] = { 1, 1, 2, 4, 8, 16, 32, 1, 12, 20, 1, 1, 1, 1, 1, 1};
/*****************************************************************************
CMMOB_CorrectAtr
Routine Description: This function checks if the received ATR is valid.
Arguments:
Return Value:
*****************************************************************************/ VOID CMMOB_CorrectAtr( PUCHAR pbBuffer, ULONG ulBufferSize ) { UCHAR bNumberHistoricalBytes; UCHAR bXorChecksum; ULONG i;
if (ulBufferSize < 0x09) // mininmum length of a modified ATR
return ; // ATR is ok
// variant 1
if (pbBuffer[0] == 0x3b && pbBuffer[1] == 0xb4 && pbBuffer[2] == 0x11 && pbBuffer[3] == 0x00 && pbBuffer[4] == 0x81 && pbBuffer[5] == 0x31 && pbBuffer[6] == 0x90 && pbBuffer[7] == 0x73 && ulBufferSize == 13 ) { // correct checksum byte
bXorChecksum = pbBuffer[1]; for (i=2;i<ulBufferSize-1;i++) bXorChecksum ^= pbBuffer[i];
if (pbBuffer[ulBufferSize -1 ] != bXorChecksum ) { pbBuffer[ulBufferSize -1 ] = bXorChecksum; SmartcardDebug(DEBUG_ATR, ("%s!CorrectAtr: Correcting SAMOS ATR (variant 1)\n", DRIVER_NAME)); } }
// variant 2
if (pbBuffer[0] == 0x3b && pbBuffer[1] == 0xbf && pbBuffer[2] == 0x11 && pbBuffer[3] == 0x00 && pbBuffer[4] == 0x81 && pbBuffer[5] == 0x31 && pbBuffer[6] == 0x90 && pbBuffer[7] == 0x73 && ulBufferSize == 13 ) { // correct number of historical bytes
bNumberHistoricalBytes = 4;
pbBuffer[1] &= 0xf0; pbBuffer[1] |= bNumberHistoricalBytes;
// correct checksum byte
bXorChecksum = pbBuffer[1]; for (i=2;i<ulBufferSize-1;i++) bXorChecksum ^= pbBuffer[i];
pbBuffer[ulBufferSize -1 ] = bXorChecksum; SmartcardDebug(DEBUG_ATR, ("%s!CorrectAtr: Correcting SAMOS ATR (variant 2)\n", DRIVER_NAME)); }
// variant 3
if (pbBuffer[0] == 0x3b && pbBuffer[1] == 0xbf && pbBuffer[2] == 0x11 && pbBuffer[3] == 0x00 && pbBuffer[4] == 0x81 && pbBuffer[5] == 0x31 && pbBuffer[6] == 0x90 && pbBuffer[7] == 0x73 && ulBufferSize == 9 ) { // correct number of historical bytes
bNumberHistoricalBytes = 0;
pbBuffer[1] &= 0xf0; pbBuffer[1] |= bNumberHistoricalBytes;
// correct checksum byte
bXorChecksum = pbBuffer[1]; for (i=2;i<ulBufferSize-1;i++) bXorChecksum ^= pbBuffer[i];
pbBuffer[ulBufferSize -1 ] = bXorChecksum; SmartcardDebug(DEBUG_ATR, ("%s!CorrectAtr: Correcting SAMOS ATR (variant 3)\n",DRIVER_NAME)); }
}
/*****************************************************************************
CMMOB_CardPower: callback handler for SMCLIB RDF_CARD_POWER
Arguments: SmartcardExtension context of call
Return Value: STATUS_SUCCESS STATUS_NO_MEDIA STATUS_TIMEOUT STATUS_BUFFER_TOO_SMALL ******************************************************************************/ NTSTATUS CMMOB_CardPower ( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; PREADER_EXTENSION ReaderExtension; UCHAR pbAtrBuffer[MAXIMUM_ATR_LENGTH]; ULONG ulAtrLength; BOOLEAN fMaxWaitTime=FALSE;
#if DBG || DEBUG
static PCHAR request[] = { "PowerDown", "ColdReset", "WarmReset"}; #endif
SmartcardDebug(DEBUG_TRACE, ("%s!CardPower: Enter, Request = %s\n", DRIVER_NAME,request[SmartcardExtension->MinorIoControlCode]));
ReaderExtension = SmartcardExtension->ReaderExtension; #ifdef IOCARD
ReaderExtension->fTActive=TRUE; NTStatus = CMMOB_SetFlags1(ReaderExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; } #endif
switch (SmartcardExtension->MinorIoControlCode) { case SCARD_WARM_RESET: case SCARD_COLD_RESET: // try asynchronous cards first
// because some asynchronous cards
// do not return 0xFF in the first byte
NTStatus = CMMOB_PowerOnCard(SmartcardExtension, pbAtrBuffer, fMaxWaitTime, &ulAtrLength);
if (NTStatus != STATUS_SUCCESS) { // try a second time, with maximum waiting time
fMaxWaitTime=TRUE; NTStatus = CMMOB_PowerOnCard(SmartcardExtension, pbAtrBuffer, fMaxWaitTime, &ulAtrLength); }
/*
if (NTStatus != STATUS_SUCCESS && NTStatus!= STATUS_NO_MEDIA) { NTStatus = CMMOB_PowerOnSynchronousCard(SmartcardExtension, pbAtrBuffer, &ulAtrLength); } */ if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; }
// correct ATR in case of old Samos cards, with wrong number of historical bytes / checksum
CMMOB_CorrectAtr(pbAtrBuffer, ulAtrLength);
if (ReaderExtension->CardParameters.fSynchronousCard == FALSE) { // copy ATR to smart card structure
// the lib needs the ATR for evaluation of the card parameters
RtlCopyBytes((PVOID)SmartcardExtension->CardCapabilities.ATR.Buffer, (PVOID)pbAtrBuffer, ulAtrLength);
SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength;
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_NEGOTIABLE;
SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
NTStatus = SmartcardUpdateCardCapabilities(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { if (!fMaxWaitTime) { // try a second time, with maximum waiting time
fMaxWaitTime=TRUE; NTStatus = CMMOB_PowerOnCard(SmartcardExtension, pbAtrBuffer, fMaxWaitTime, &ulAtrLength); if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; } RtlCopyBytes((PVOID)SmartcardExtension->CardCapabilities.ATR.Buffer, (PVOID)pbAtrBuffer, ulAtrLength); SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength; SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_NEGOTIABLE; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
NTStatus = SmartcardUpdateCardCapabilities(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; } } else goto ExitCardPower; }
// -----------------------
// set parameters
// -----------------------
if (SmartcardExtension->CardCapabilities.N != 0xff) { // 0 <= N <= 254
ReaderExtension->CardParameters.bStopBits = 2 + SmartcardExtension->CardCapabilities.N; } else { // N = 255
if (SmartcardExtension->CardCapabilities.Protocol.Selected & SCARD_PROTOCOL_T0) { // 12 etu for T=0;
ReaderExtension->CardParameters.bStopBits = 2; } else { // 11 etu for T=1
ReaderExtension->CardParameters.bStopBits = 1; } }
if (SmartcardExtension->CardCapabilities.InversConvention) { ReaderExtension->CardParameters.fInversRevers = TRUE; SmartcardDebug(DEBUG_ATR, ("%s!Card with invers convention !\n",DRIVER_NAME )); }
CMMOB_SetCardParameters (ReaderExtension);
#if DBG
{ ULONG i; SmartcardDebug(DEBUG_ATR,("%s!ATR : ",DRIVER_NAME)); for (i = 0;i < ulAtrLength;i++) SmartcardDebug(DEBUG_ATR,("%2.2x ",SmartcardExtension->CardCapabilities.ATR.Buffer[i])); SmartcardDebug(DEBUG_ATR,("\n")); } #endif
} else { SmartcardExtension->CardCapabilities.ATR.Buffer[0] = 0x3B; SmartcardExtension->CardCapabilities.ATR.Buffer[1] = 0x04;
RtlCopyBytes((PVOID)&SmartcardExtension->CardCapabilities.ATR.Buffer[2], (PVOID)pbAtrBuffer, ulAtrLength);
ulAtrLength += 2; SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength;
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0;
NTStatus = SmartcardUpdateCardCapabilities(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; }
SmartcardDebug(DEBUG_ATR,("ATR of synchronous smart card : %2.2x %2.2x %2.2x %2.2x\n", pbAtrBuffer[0],pbAtrBuffer[1],pbAtrBuffer[2],pbAtrBuffer[3]));
}
// copy ATR to user space
if (SmartcardExtension->IoRequest.ReplyBufferLength >= SmartcardExtension->CardCapabilities.ATR.Length) { RtlCopyBytes((PVOID)SmartcardExtension->IoRequest.ReplyBuffer, (PVOID)SmartcardExtension->CardCapabilities.ATR.Buffer, SmartcardExtension->CardCapabilities.ATR.Length);
*SmartcardExtension->IoRequest.Information = SmartcardExtension->CardCapabilities.ATR.Length; } else { NTStatus = STATUS_BUFFER_TOO_SMALL; *SmartcardExtension->IoRequest.Information = 0; }
break;
case SCARD_POWER_DOWN: NTStatus = CMMOB_PowerOffCard(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitCardPower; }
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
break; }
ExitCardPower: #ifdef IOCARD
ReaderExtension->fTActive=FALSE; CMMOB_SetFlags1(ReaderExtension); #endif
SmartcardDebug(DEBUG_TRACE, ("%s!CardPower: Exit %X\n",DRIVER_NAME,NTStatus ));
return( NTStatus );
}
/*****************************************************************************
Routine Description: CMMOB_PowerOnCard
Arguments:
Return Value:
*****************************************************************************/ NTSTATUS CMMOB_PowerOnCard ( IN PSMARTCARD_EXTENSION SmartcardExtension, IN PUCHAR pbATR, IN BOOLEAN fMaxWaitTime, OUT PULONG pulATRLength ) { NTSTATUS NTStatus = STATUS_SUCCESS; KTIMER TimerWait; UCHAR bPowerCmd; ULONG ulCardType; ULONG ulBytesReceived; UCHAR bFirstByte; LONG lWaitTime; LARGE_INTEGER liWaitTime; BOOLEAN fTimeExpired;
SmartcardDebug(DEBUG_TRACE, ("%s!PowerOnCard: Enter\n",DRIVER_NAME));
SmartcardExtension->ReaderExtension->CardParameters.bStopBits=2; SmartcardExtension->ReaderExtension->CardParameters.fSynchronousCard=FALSE; SmartcardExtension->ReaderExtension->CardParameters.fInversRevers=FALSE; SmartcardExtension->ReaderExtension->CardParameters.bClockFrequency=4; SmartcardExtension->ReaderExtension->CardParameters.fT0Mode=FALSE; SmartcardExtension->ReaderExtension->CardParameters.fT0Write=FALSE; SmartcardExtension->ReaderExtension->fReadCIS = FALSE;
// reset the state machine of the reader
NTStatus = CMMOB_ResetReader (SmartcardExtension->ReaderExtension); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOnCard;
if (CMMOB_CardInserted (SmartcardExtension->ReaderExtension)) {
//initialize Timer
KeInitializeTimer(&TimerWait);
//we have to differentiate between cold and warm reset
if (SmartcardExtension->MinorIoControlCode == SCARD_WARM_RESET && CMMOB_CardPowered (SmartcardExtension->ReaderExtension)) { //warm reset
bPowerCmd=CMD_POWERON_WARM; } else { //cold reset
bPowerCmd=CMD_POWERON_COLD;
//if card is powerde we have to turn it off for cold reset
if (CMMOB_CardPowered (SmartcardExtension->ReaderExtension)) CMMOB_PowerOffCard (SmartcardExtension); }
#define MAX_CARD_TYPE 2
for (ulCardType = 0; ulCardType < MAX_CARD_TYPE; ulCardType++) { switch (ulCardType) { case 0: // BaudRate divider 372 - 1
SmartcardExtension->ReaderExtension->CardParameters.bBaudRateHigh = 0x01; SmartcardExtension->ReaderExtension->CardParameters.bBaudRateLow = 0x73; if (fMaxWaitTime) lWaitTime=1000; else lWaitTime=100; SmartcardDebug(DEBUG_ATR, ("%s!trying 3.57 Mhz smart card, waiting time %ims\n",DRIVER_NAME,lWaitTime)); break;
case 1: // BaudRate divider 512 - 1
SmartcardExtension->ReaderExtension->CardParameters.bBaudRateHigh = 0x01; SmartcardExtension->ReaderExtension->CardParameters.bBaudRateLow = 0xFF; if (fMaxWaitTime) lWaitTime=1400; else lWaitTime=140; SmartcardDebug(DEBUG_ATR, ("%s!trying 4.92 Mhz smart card, waiting time %ims\n",DRIVER_NAME,lWaitTime)); break; }
//set baud rate
NTStatus=CMMOB_SetCardParameters(SmartcardExtension->ReaderExtension); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOnCard;
//issue power on command
NTStatus=CMMOB_WriteRegister(SmartcardExtension->ReaderExtension, ADDR_WRITEREG_FLAGS0, bPowerCmd); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOnCard;
// maximum wait for power on first byte 100 ms
liWaitTime = RtlConvertLongToLargeInteger(100L * -10000L); KeSetTimer(&TimerWait,liWaitTime,NULL); do { fTimeExpired = KeReadStateTimer(&TimerWait); NTStatus=CMMOB_BytesReceived (SmartcardExtension->ReaderExtension,&ulBytesReceived); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOnCard; // wait 1 ms, so that processor is not blocked
SysDelay(1); } while (fTimeExpired==FALSE && ulBytesReceived == 0x00);
if (fTimeExpired) { NTStatus = STATUS_IO_TIMEOUT; } else { ULONG ulBytesReceivedPrevious;
KeCancelTimer(&TimerWait);
// maximum wait for power on last byte 1 s for 3.58 card
// and 1.4 seconds for 4.91 cards
liWaitTime = RtlConvertLongToLargeInteger(lWaitTime * -10000L); do { KeSetTimer(&TimerWait,liWaitTime,NULL); NTStatus=CMMOB_BytesReceived (SmartcardExtension->ReaderExtension,&ulBytesReceivedPrevious); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOnCard; do { fTimeExpired = KeReadStateTimer(&TimerWait); NTStatus=CMMOB_BytesReceived (SmartcardExtension->ReaderExtension,&ulBytesReceived); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOnCard; // wait 1 ms, so that processor is not blocked
SysDelay(1); } while (fTimeExpired==FALSE && ulBytesReceivedPrevious == ulBytesReceived);
if (!fTimeExpired) { KeCancelTimer(&TimerWait); } } while (!fTimeExpired);
//now we should have received an ATR
NTStatus=CMMOB_ResetReader (SmartcardExtension->ReaderExtension); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOnCard;
NTStatus=CMMOB_ReadBuffer(SmartcardExtension->ReaderExtension, 0, 1, &bFirstByte); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOnCard;
if ((bFirstByte != 0x3B && bFirstByte != 0x03 )|| ulBytesReceived > MAXIMUM_ATR_LENGTH) { NTStatus=STATUS_UNRECOGNIZED_MEDIA; } else { pbATR[0]=bFirstByte; NTStatus=CMMOB_ReadBuffer(SmartcardExtension->ReaderExtension, 1, ulBytesReceived, &pbATR[1]); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOnCard; *pulATRLength = ulBytesReceived; // success leave the loop
break; } } // if not the last time in the loop power off
// the card to get a well defined condition
// (after the last pass the power off is
// done outside the loop if necessary)
if (ulCardType < MAX_CARD_TYPE-1) { CMMOB_PowerOffCard(SmartcardExtension); } } } else { NTStatus=STATUS_NO_MEDIA; }
ExitPowerOnCard:
if (NTStatus!=STATUS_SUCCESS) { if (NTStatus != STATUS_NO_MEDIA) { NTStatus = STATUS_UNRECOGNIZED_MEDIA; } CMMOB_PowerOffCard(SmartcardExtension); }
SmartcardDebug(DEBUG_TRACE, ("%s!PowerOnCard: Exit %lx\n",DRIVER_NAME,NTStatus));
return NTStatus; }
/*****************************************************************************
Routine Description: CMMOB_PowerOffCard
Arguments:
Return Value:
*****************************************************************************/ NTSTATUS CMMOB_PowerOffCard ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; BYTE* pbRegsBase; KTIMER TimerWait; LARGE_INTEGER liWaitTime; BOOLEAN fTimeExpired;
SmartcardDebug(DEBUG_TRACE, ("%s!PowerOffCard: Enter\n",DRIVER_NAME));
NTStatus = CMMOB_ResetReader (SmartcardExtension->ReaderExtension); if (NTStatus!=STATUS_SUCCESS) goto ExitPowerOffCard;
pbRegsBase=SmartcardExtension->ReaderExtension->pbRegsBase; if (CMMOB_CardInserted (SmartcardExtension->ReaderExtension)) { // set card state for update thread
// otherwise a card removal/insertion would be recognized
if (SmartcardExtension->ReaderExtension->ulOldCardState == POWERED) SmartcardExtension->ReaderExtension->ulOldCardState = INSERTED;
//issue power off command
CMMOB_WriteRegister(SmartcardExtension->ReaderExtension, ADDR_WRITEREG_FLAGS0, CMD_POWEROFF);
KeInitializeTimer(&TimerWait); // maximum wait for power down 1 second
liWaitTime = RtlConvertLongToLargeInteger(1000L * -10000L); KeSetTimer(&TimerWait,liWaitTime,NULL); do { fTimeExpired = KeReadStateTimer(&TimerWait); // wait 1 ms, so that processor is not blocked
SysDelay(1); } while (fTimeExpired==FALSE && CMMOB_CardPowered (SmartcardExtension->ReaderExtension));
if (fTimeExpired) { NTStatus = STATUS_IO_TIMEOUT; } else { KeCancelTimer(&TimerWait); } } else { NTStatus=STATUS_NO_MEDIA; }
ExitPowerOffCard:
CMMOB_ResetReader (SmartcardExtension->ReaderExtension);
SmartcardDebug(DEBUG_TRACE, ("%s!PowerOffCard: Exit %lx\n",DRIVER_NAME,NTStatus));
return NTStatus; }
/*****************************************************************************
CMMOB_SetProtocol: callback handler for SMCLIB RDF_SET_PROTOCOL
Arguments: SmartcardExtension context of call
Return Value: STATUS_SUCCESS STATUS_NO_MEDIA STATUS_TIMEOUT STATUS_BUFFER_TOO_SMALL STATUS_INVALID_DEVICE_STATE STATUS_INVALID_DEVICE_REQUEST ******************************************************************************/ NTSTATUS CMMOB_SetProtocol( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus; PREADER_EXTENSION ReaderExtension; USHORT usSCLibProtocol; UCHAR abPTSRequest[4]; UCHAR abPTSReply [4]; ULONG ulBytesRead; ULONG ulBaudRateDivider; ULONG ulWaitTime; UCHAR bTemp; ULONG i;
SmartcardDebug(DEBUG_TRACE, ("%s!SetProtocol: Enter\n",DRIVER_NAME ));
ReaderExtension = SmartcardExtension->ReaderExtension;
#ifdef IOCARD
ReaderExtension->fTActive=TRUE; NTStatus = CMMOB_SetFlags1(ReaderExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitSetProtocol; } #endif
NTStatus = STATUS_PENDING;
usSCLibProtocol = ( USHORT )( SmartcardExtension->MinorIoControlCode );
//
// check card insertion
//
if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_ABSENT) { NTStatus = STATUS_NO_MEDIA; } else { //
// Check if the card is already in specific state and if the caller
// wants to have the selected protocol
//
if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC) { if (SmartcardExtension->CardCapabilities.Protocol.Selected == usSCLibProtocol) { NTStatus = STATUS_SUCCESS; } } } if (NTStatus == STATUS_PENDING) {
//
// reset the state machine of the reader
//
NTStatus=CMMOB_ResetReader(ReaderExtension); if (NTStatus==STATUS_SUCCESS) { // try 2 times,
// 0 - optimal
// 1 - default
for (i=0; i<2; i++) {
// set initial character of PTS
abPTSRequest[0] = 0xFF;
// set the format character (PTS0)
if (SmartcardExtension->CardCapabilities.Protocol.Supported & usSCLibProtocol & SCARD_PROTOCOL_T1) { // select T=1 and indicate that PTS1 follows
abPTSRequest[1] = 0x11; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T1; } else if (SmartcardExtension->CardCapabilities.Protocol.Supported & usSCLibProtocol & SCARD_PROTOCOL_T0) { // select T=0 and indicate that PTS1 follows
abPTSRequest[1] = 0x10; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0; } else { // we do not support other protocols
NTStatus = STATUS_INVALID_DEVICE_REQUEST; goto ExitSetProtocol; }
if (i==0) { // optimal
bTemp = (BYTE) (SmartcardExtension->CardCapabilities.PtsData.Fl << 4 | SmartcardExtension->CardCapabilities.PtsData.Dl); SmartcardDebug(DEBUG_PROTOCOL, ("%s! from library suggested PTS1(0x%x)\n",DRIVER_NAME,bTemp));
SmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_OPTIMAL; SmartcardExtension->CardCapabilities.PtsData.Fl=SmartcardExtension->CardCapabilities.Fl; SmartcardExtension->CardCapabilities.PtsData.Dl=SmartcardExtension->CardCapabilities.Dl; } else { // default
// we don�t know if it is correct to set 4.91Mhz cards to 0x11
// but we have no card to try now
SmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_DEFAULT; SmartcardExtension->CardCapabilities.PtsData.Fl=1; SmartcardExtension->CardCapabilities.PtsData.Dl=1; }
bTemp = (BYTE) (SmartcardExtension->CardCapabilities.PtsData.Fl << 4 | SmartcardExtension->CardCapabilities.PtsData.Dl); SmartcardDebug(DEBUG_PROTOCOL, ("%s! trying PTS1(0x%x)\n",DRIVER_NAME,bTemp)); switch (SmartcardExtension->CardCapabilities.PtsData.Fl) { case 1: // here we can handle all baudrates
break; case 2: case 3: if (SmartcardExtension->CardCapabilities.PtsData.Dl == 1) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! overwriting PTS1(0x%x)\n",DRIVER_NAME,bTemp)); // we must correct Fl/Dl
SmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; SmartcardExtension->CardCapabilities.PtsData.Fl = 0x01; } break; case 4: case 5: case 6: if (SmartcardExtension->CardCapabilities.PtsData.Dl == 1 || SmartcardExtension->CardCapabilities.PtsData.Dl == 2) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! overwriting PTS1(0x%x)\n",DRIVER_NAME,bTemp)); // we must correct Fl/Dl
SmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; SmartcardExtension->CardCapabilities.PtsData.Fl = 0x01; } break; case 9: // here we can handle all baudrates
break; case 10: case 11: if (SmartcardExtension->CardCapabilities.PtsData.Dl == 1) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! overwriting PTS1(0x%x)\n",DRIVER_NAME,bTemp)); // we must correct Fl/Dl
SmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; SmartcardExtension->CardCapabilities.PtsData.Fl = 0x09; } break; case 12: case 13: if (SmartcardExtension->CardCapabilities.PtsData.Dl == 1 || SmartcardExtension->CardCapabilities.PtsData.Dl == 2) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! overwriting PTS1(0x%x)\n",DRIVER_NAME,bTemp)); // we must correct Fl/Dl
SmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; SmartcardExtension->CardCapabilities.PtsData.Fl = 0x09; } break; default: // this are the RFUs
SmartcardDebug(DEBUG_PROTOCOL, ("%s! overwriting PTS1(0x%x)\n",DRIVER_NAME,bTemp)); // we must correct Fl/Dl
SmartcardExtension->CardCapabilities.PtsData.Dl = 0x01; SmartcardExtension->CardCapabilities.PtsData.Fl = 0x01; break; }
// set PTS1 with codes Fl and Dl
abPTSRequest[2] = (BYTE) (SmartcardExtension->CardCapabilities.PtsData.Fl << 4 | SmartcardExtension->CardCapabilities.PtsData.Dl);
// set PCK (check character)
abPTSRequest[3] = (BYTE)(abPTSRequest[0] ^ abPTSRequest[1] ^ abPTSRequest[2]);
if (ReaderExtension->CardParameters.fInversRevers) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! PTS request for InversConvention\n",DRIVER_NAME)); CMMOB_InverseBuffer (abPTSRequest,4); }
#if DBG
{ ULONG k; SmartcardDebug(DEBUG_PROTOCOL,("%s! writing PTS request: ",DRIVER_NAME)); for (k = 0;k < 4;k++) SmartcardDebug(DEBUG_PROTOCOL,("%2.2x ",abPTSRequest[k])); SmartcardDebug(DEBUG_PROTOCOL,("\n")); } #endif
NTStatus = CMMOB_WriteT1(ReaderExtension,4,abPTSRequest); if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_ERROR, ("%s! writing PTS request failed\n", DRIVER_NAME)); goto ExitSetProtocol; }
// read back PTS data
ulWaitTime=1000; if (SmartcardExtension->CardCapabilities.PtsData.Fl >= 8) ulWaitTime=1400; NTStatus = CMMOB_ReadT1(ReaderExtension,4, ulWaitTime,ulWaitTime, abPTSReply,&ulBytesRead); // in case of an short PTS reply an timeout will occur,
// but that's not the standard case
if (NTStatus != STATUS_SUCCESS && NTStatus != STATUS_IO_TIMEOUT) { SmartcardDebug(DEBUG_ERROR, ("%s! reading PTS reply: failed\n",DRIVER_NAME)); goto ExitSetProtocol; } #if DBG
{ ULONG k; SmartcardDebug(DEBUG_PROTOCOL,("%s! reading PTS reply: ",DRIVER_NAME)); for (k = 0;k < ulBytesRead;k++) SmartcardDebug(DEBUG_PROTOCOL,("%2.2x ",abPTSReply[k])); SmartcardDebug(DEBUG_PROTOCOL,("\n")); } #endif
if (ulBytesRead == 4 && abPTSReply[0] == abPTSRequest[0] && abPTSReply[1] == abPTSRequest[1] && abPTSReply[2] == abPTSRequest[2] && abPTSReply[3] == abPTSRequest[3] ) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! PTS request and reply match\n",DRIVER_NAME));
if ((SmartcardExtension->CardCapabilities.PtsData.Fl >= 3 && SmartcardExtension->CardCapabilities.PtsData.Fl < 8) || (SmartcardExtension->CardCapabilities.PtsData.Fl >= 11 && SmartcardExtension->CardCapabilities.PtsData.Fl < 16)) { ReaderExtension->CardParameters.bClockFrequency=8; }
ulBaudRateDivider = Fi[SmartcardExtension->CardCapabilities.PtsData.Fl] / Di[SmartcardExtension->CardCapabilities.PtsData.Dl]; // decrease by 1, because these values have to be written to CardMan
ulBaudRateDivider--; if (ulBaudRateDivider < 512) { ReaderExtension->CardParameters.bBaudRateLow=(UCHAR)(ulBaudRateDivider & 0xFF); if (ulBaudRateDivider>255) { ReaderExtension->CardParameters.bBaudRateHigh=1; } else { ReaderExtension->CardParameters.bBaudRateHigh=0; }
NTStatus = CMMOB_SetCardParameters (ReaderExtension); if (NTStatus == STATUS_SUCCESS) { //
// we had success, leave the loop
//
break; } } }
if (ulBytesRead == 3 && abPTSReply[0] == abPTSRequest[0] && (abPTSReply[1] & 0x7F) == (abPTSRequest[1] & 0x0F) && abPTSReply[2] == (BYTE)(abPTSReply[0] ^ abPTSReply[1] )) { SmartcardDebug(DEBUG_PROTOCOL, ("%s! Short PTS reply received\n",DRIVER_NAME));
if (SmartcardExtension->CardCapabilities.PtsData.Fl >= 9) { ulBaudRateDivider = 512; } else { ulBaudRateDivider = 372; } // decrease by 1, because these values have to be written to CardMan
ulBaudRateDivider--;
NTStatus = CMMOB_SetCardParameters (ReaderExtension); if (NTStatus == STATUS_SUCCESS) { //
// we had success, leave the loop
//
break; } }
if (i==0) { // this was the first try
// we have a second with default values
SmartcardDebug(DEBUG_PROTOCOL, ("%s! PTS failed : Trying default parameters\n",DRIVER_NAME));
// the card did either not reply or it replied incorrectly
// so try default values
SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET; NTStatus = CMMOB_CardPower(SmartcardExtension); } else { // the card failed the PTS request
NTStatus = STATUS_DEVICE_PROTOCOL_ERROR; } } } }
ExitSetProtocol:
//
// if protocol selection failed, prevent from calling invalid protocols
//
if (NTStatus==STATUS_SUCCESS) { SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC; } else { SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; }
//
// Return the selected protocol to the caller.
//
*(PULONG) (SmartcardExtension->IoRequest.ReplyBuffer) = SmartcardExtension->CardCapabilities.Protocol.Selected; *SmartcardExtension->IoRequest.Information = sizeof( ULONG );
#ifdef IOCARD
ReaderExtension->fTActive=FALSE; CMMOB_SetFlags1(ReaderExtension); #endif
SmartcardDebug(DEBUG_TRACE, ("%s!SetProtocol: Exit %X\n",DRIVER_NAME,NTStatus ));
return( NTStatus ); }
/*****************************************************************************
CMMOB_Transmit: callback handler for SMCLIB RDF_TRANSMIT
Arguments: SmartcardExtension context of call
Return Value: STATUS_SUCCESS STATUS_NO_MEDIA STATUS_TIMEOUT STATUS_INVALID_DEVICE_REQUEST ******************************************************************************/ NTSTATUS CMMOB_Transmit ( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS;
SmartcardDebug(DEBUG_TRACE, ("%s!Transmit: Enter\n",DRIVER_NAME )); //
// dispatch on the selected protocol
//
switch (SmartcardExtension->CardCapabilities.Protocol.Selected) { case SCARD_PROTOCOL_T0: NTStatus = CMMOB_TransmitT0(SmartcardExtension); break;
case SCARD_PROTOCOL_T1: NTStatus = CMMOB_TransmitT1(SmartcardExtension); break;
/*
case SCARD_PROTOCOL_RAW: break; */
default: NTStatus = STATUS_INVALID_DEVICE_REQUEST; break; }
SmartcardDebug(DEBUG_TRACE, ("%s!Transmit: Exit %X\n",DRIVER_NAME,NTStatus ));
return( NTStatus ); }
/*****************************************************************************
CMMOB_TransmitT0: callback handler for SMCLIB RDF_TRANSMIT
Arguments: SmartcardExtension context of call
Return Value: STATUS_SUCCESS STATUS_NO_MEDIA STATUS_TIMEOUT STATUS_INVALID_DEVICE_REQUEST ******************************************************************************/ NTSTATUS CMMOB_TransmitT0 ( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus; UCHAR abWriteBuffer[MIN_BUFFER_SIZE]; UCHAR abReadBuffer[MIN_BUFFER_SIZE]; ULONG ulBytesToWrite; //length written to card
ULONG ulBytesToReceive; //length expected from card
ULONG ulBytesToRead; //length expected from reader
ULONG ulBytesRead; //length received from reader
//(without length written)
ULONG ulCWTWaitTime; BOOLEAN fDataSent; //data longer than T0_HEADER
#ifdef IOCARD
SmartcardExtension->ReaderExtension->fTActive=TRUE; NTStatus = CMMOB_SetFlags1(SmartcardExtension->ReaderExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitTransmitT0; } #endif
// reset the state machine of the reader
NTStatus = CMMOB_ResetReader (SmartcardExtension->ReaderExtension); if (NTStatus!=STATUS_SUCCESS) { // there must be severe error
goto ExitTransmitT0; }
// set T0 mode
SmartcardExtension->ReaderExtension->CardParameters.fT0Mode=TRUE;
// increase timeout for T0 Transmission
ulCWTWaitTime = SmartcardExtension->CardCapabilities.T0.WT/1000 + 1500;
//
// Let the lib build a T=0 packet
//
// no bytes additionally needed
SmartcardExtension->SmartcardRequest.BufferLength = 0; NTStatus = SmartcardT0Request(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { // the lib detected an error in the data to send.
goto ExitTransmitT0; }
// copy data to the write buffer
ulBytesToWrite = T0_HEADER_LEN + SmartcardExtension->T0.Lc; RtlCopyMemory(abWriteBuffer,SmartcardExtension->SmartcardRequest.Buffer,ulBytesToWrite); ulBytesToReceive = SmartcardExtension->T0.Le;
#if DBG
{ ULONG i; SmartcardDebug(DEBUG_PROTOCOL,("%s!TransmitT0: Request ",DRIVER_NAME)); for (i = 0;i < ulBytesToWrite;i++) SmartcardDebug(DEBUG_PROTOCOL,("%2.2x ",abWriteBuffer[i])); SmartcardDebug(DEBUG_PROTOCOL,("\n")); } #endif
// set T0 write flag correctly
if (ulBytesToReceive == 0) { SmartcardExtension->ReaderExtension->CardParameters.fT0Write=TRUE; } else { SmartcardExtension->ReaderExtension->CardParameters.fT0Write=FALSE; } NTStatus=CMMOB_SetCardParameters(SmartcardExtension->ReaderExtension); if (NTStatus != STATUS_SUCCESS) goto ExitTransmitT0;
NTStatus = CMMOB_WriteT0 (SmartcardExtension->ReaderExtension, ulBytesToWrite, ulBytesToReceive, abWriteBuffer); if (NTStatus != STATUS_SUCCESS) { goto ExitTransmitT0; }
// bytes to write + answer + SW2
ulBytesToRead = ulBytesToWrite + ulBytesToReceive + 1; NTStatus = CMMOB_ReadT0 (SmartcardExtension->ReaderExtension, ulBytesToRead, ulBytesToWrite, ulCWTWaitTime, abReadBuffer, &ulBytesRead, &fDataSent);
#if DBG
{ ULONG i; SmartcardDebug(DEBUG_PROTOCOL,("%s!TransmitT0: Reply ",DRIVER_NAME)); for (i = 0;i < ulBytesRead;i++) SmartcardDebug(DEBUG_PROTOCOL,("%2.2x ",abReadBuffer[i])); SmartcardDebug(DEBUG_PROTOCOL,("\n")); } #endif
if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_PROTOCOL,("%s!TransmitT0: Read failed!\n",DRIVER_NAME)); goto ExitTransmitT0; }
// copy received bytes
if (ulBytesRead <= SmartcardExtension->SmartcardReply.BufferSize) { RtlCopyBytes((PVOID)SmartcardExtension->SmartcardReply.Buffer, (PVOID) abReadBuffer, ulBytesRead); SmartcardExtension->SmartcardReply.BufferLength = ulBytesRead; } else { NTStatus=STATUS_BUFFER_OVERFLOW; goto ExitTransmitT0; }
// let the lib copy the received bytes to the user buffer
NTStatus = SmartcardT0Reply(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitTransmitT0; }
ExitTransmitT0: // ------------------------------------------
// ITSEC E2 requirements: clear write buffers
// ------------------------------------------
RtlFillMemory((PVOID)abWriteBuffer,sizeof(abWriteBuffer),0x00); RtlFillMemory((PVOID)SmartcardExtension->SmartcardRequest.Buffer, SmartcardExtension->SmartcardRequest.BufferSize,0x00);
// set T0 mode back
SmartcardExtension->ReaderExtension->CardParameters.fT0Mode=FALSE; SmartcardExtension->ReaderExtension->CardParameters.fT0Write=FALSE; CMMOB_SetCardParameters(SmartcardExtension->ReaderExtension);
#ifdef IOCARD
SmartcardExtension->ReaderExtension->fTActive=FALSE; CMMOB_SetFlags1(SmartcardExtension->ReaderExtension); #endif
return NTStatus; }
/*****************************************************************************
CMMOB_TransmitT1: callback handler for SMCLIB RDF_TRANSMIT
Arguments: SmartcardExtension context of call
Return Value: STATUS_SUCCESS STATUS_NO_MEDIA STATUS_TIMEOUT STATUS_INVALID_DEVICE_REQUEST ******************************************************************************/ NTSTATUS CMMOB_TransmitT1 ( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus; UCHAR abReadBuffer[CMMOB_MAXBUFFER]; LONG lBytesToRead; ULONG ulBytesRead; ULONG ulCurrentWaitTime; ULONG ulCWTWaitTime; ULONG ulBWTWaitTime; ULONG ulWTXWaitTime; ULONG ulTemp;
SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT1 CWT = %ld(ms)\n",DRIVER_NAME, SmartcardExtension->CardCapabilities.T1.CWT/1000)); SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT1 BWT = %ld(ms)\n",DRIVER_NAME, SmartcardExtension->CardCapabilities.T1.BWT/1000));
ulCWTWaitTime = (ULONG)(100 + 32*(SmartcardExtension->CardCapabilities.T1.CWT/1000)); ulBWTWaitTime = (ULONG)(1000 + SmartcardExtension->CardCapabilities.T1.BWT/1000); ulWTXWaitTime = 0;
#ifdef IOCARD
SmartcardExtension->ReaderExtension->fTActive=TRUE; NTStatus = CMMOB_SetFlags1(SmartcardExtension->ReaderExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitTransmitT1; } #endif
// reset the state machine of the reader
NTStatus = CMMOB_ResetReader (SmartcardExtension->ReaderExtension); if (NTStatus!=STATUS_SUCCESS) { // there must be severe error
goto ExitTransmitT1; }
do { // no bytes additionally needed
SmartcardExtension->SmartcardRequest.BufferLength = 0;
NTStatus = SmartcardT1Request(SmartcardExtension); if (NTStatus != STATUS_SUCCESS) { // this should never happen, so we return immediately
goto ExitTransmitT1; }
#if DBG
{ ULONG i; SmartcardDebug(DEBUG_PROTOCOL,("%s!TransmitT1: Request ",DRIVER_NAME)); for (i = 0;i < SmartcardExtension->SmartcardRequest.BufferLength;i++) SmartcardDebug(DEBUG_PROTOCOL,("%2.2x ",SmartcardExtension->SmartcardRequest.Buffer[i])); SmartcardDebug(DEBUG_PROTOCOL,("\n")); } #endif
// write to the reader
NTStatus = CMMOB_WriteT1 (SmartcardExtension->ReaderExtension, SmartcardExtension->SmartcardRequest.BufferLength, SmartcardExtension->SmartcardRequest.Buffer); if (NTStatus == STATUS_SUCCESS) {
if (ulWTXWaitTime == 0 ) // use BWT
{ /*
SmartcardDebug(DEBUG_TRACE, ("%s!ulCurrentWaitTime = %ld\n",DRIVER_NAME,ulCurrentWaitTime)); */ ulCurrentWaitTime = ulBWTWaitTime; } else // use WTX time
{ /*
SmartcardDebug(DEBUG_TRACE, ("%s!ulCurrentWaitTime = %ld\n",DRIVER_NAME,ulWTXWaitTime)); */ ulCurrentWaitTime = ulWTXWaitTime; }
if (SmartcardExtension->CardCapabilities.T1.EDC == T1_CRC_CHECK) { // in case of card with CRC check read reply + 5 bytes
// a negative value indicates a relative number of bytes to read
lBytesToRead=-5; } else { // in case of card with CRC check read reply + 4 bytes
// a negative value indicates a relative number of bytes to read
lBytesToRead=-4; }
NTStatus = CMMOB_ReadT1(SmartcardExtension->ReaderExtension,lBytesToRead, ulCurrentWaitTime,ulCWTWaitTime,abReadBuffer,&ulBytesRead); if (NTStatus == STATUS_SUCCESS) {
if (abReadBuffer[1] == T1_WTX_REQUEST) { ulWTXWaitTime = (ULONG)(1000 +((SmartcardExtension->CardCapabilities.T1.BWT*abReadBuffer[3])/1000)); SmartcardDebug(DEBUG_PROTOCOL, ("%s!TransmitT1 WTX = %ld(ms)\n",DRIVER_NAME,ulWTXWaitTime)); } else { ulWTXWaitTime = 0; }
#if DBG
{ ULONG i; SmartcardDebug(DEBUG_PROTOCOL,("%s!TransmitT1: Reply ",DRIVER_NAME)); for (i = 0;i < ulBytesRead;i++) SmartcardDebug(DEBUG_PROTOCOL,("%2.2x ",abReadBuffer[i])); SmartcardDebug(DEBUG_PROTOCOL,("\n")); } #endif
// copy received bytes
if (ulBytesRead <= SmartcardExtension->SmartcardReply.BufferSize) { RtlCopyBytes((PVOID)SmartcardExtension->SmartcardReply.Buffer, (PVOID)abReadBuffer, ulBytesRead); SmartcardExtension->SmartcardReply.BufferLength = ulBytesRead; } else { NTStatus=STATUS_BUFFER_OVERFLOW; goto ExitTransmitT1; } } }
if (NTStatus != STATUS_SUCCESS) { SmartcardExtension->SmartcardReply.BufferLength = 0L; }
// bug fix for smclib
if (SmartcardExtension->T1.State == T1_IFS_RESPONSE && SmartcardExtension->T1.OriginalState == T1_I_BLOCK) { SmartcardExtension->T1.State = T1_I_BLOCK; }
NTStatus = SmartcardT1Reply(SmartcardExtension); } while (NTStatus == STATUS_MORE_PROCESSING_REQUIRED);
ExitTransmitT1: // ------------------------------------------
// ITSEC E2 requirements: clear write buffers
// ------------------------------------------
RtlFillMemory((PVOID)SmartcardExtension->SmartcardRequest.Buffer, SmartcardExtension->SmartcardRequest.BufferSize,0x00); #ifdef IOCARD
SmartcardExtension->ReaderExtension->fTActive=FALSE; CMMOB_SetFlags1(SmartcardExtension->ReaderExtension); #endif
return NTStatus; }
/*****************************************************************************
CMMOB_IoCtlVendor: Performs generic callbacks to the reader
Arguments: SmartcardExtension context of the call
Return Value: STATUS_SUCCESS ******************************************************************************/ NTSTATUS CMMOB_IoCtlVendor( PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus=STATUS_SUCCESS; PIRP Irp; PIO_STACK_LOCATION IrpStack;
SmartcardDebug(DEBUG_TRACE, ("%s!IoCtlVendor: Enter\n",DRIVER_NAME ));
//
// get pointer to current IRP stack location
//
Irp = SmartcardExtension->OsData->CurrentIrp; IrpStack = IoGetCurrentIrpStackLocation( Irp ); Irp->IoStatus.Information = 0;
//
// dispatch IOCTL
//
switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) { case CM_IOCTL_GET_FW_VERSION: NTStatus = CMMOB_GetFWVersion(SmartcardExtension); break;
case CM_IOCTL_CR80S_SAMOS_SET_HIGH_SPEED: NTStatus = CMMOB_SetHighSpeed_CR80S_SAMOS(SmartcardExtension); break;
case CM_IOCTL_SET_READER_9600_BAUD: NTStatus = CMMOB_SetReader_9600Baud(SmartcardExtension); break;
case CM_IOCTL_SET_READER_38400_BAUD: NTStatus = CMMOB_SetReader_38400Baud(SmartcardExtension); break;
case CM_IOCTL_READ_DEVICE_DESCRIPTION: NTStatus = CMMOB_ReadDeviceDescription(SmartcardExtension); break;
default: NTStatus = STATUS_INVALID_DEVICE_REQUEST; break; }
//
// set NTStatus of the packet
//
Irp->IoStatus.Status = NTStatus;
SmartcardDebug(DEBUG_TRACE, ("%s!IoCtlVendor: Exit %X\n",DRIVER_NAME,NTStatus ));
return( NTStatus ); }
/*****************************************************************************
Routine Description:
Arguments:
Return Value: STATUS_UNSUCCESSFUL STATUS_SUCCESS
*****************************************************************************/ NTSTATUS CMMOB_SetReader_9600Baud ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS;;
SmartcardDebug(DEBUG_TRACE, ("%s!SetReader_9600Baud: Enter\n",DRIVER_NAME));
// check if card is already in specific mode
if (SmartcardExtension->ReaderCapabilities.CurrentState != SCARD_SPECIFIC) { NTStatus = STATUS_INVALID_DEVICE_REQUEST; goto ExitSetReader9600; }
// set 9600 Baud for 3.58 MHz
SmartcardExtension->ReaderExtension->CardParameters.bBaudRateHigh=0x01; SmartcardExtension->ReaderExtension->CardParameters.bBaudRateLow=0x73; NTStatus = CMMOB_SetCardParameters (SmartcardExtension->ReaderExtension);
ExitSetReader9600: *SmartcardExtension->IoRequest.Information = 0L; SmartcardDebug(DEBUG_TRACE, ("%s!SetReader_9600Baud: Exit %lx\n",DRIVER_NAME,NTStatus));
return(NTStatus); }
/*****************************************************************************
Routine Description:
Arguments:
Return Value: STATUS_UNSUCCESSFUL STATUS_SUCCESS
*****************************************************************************/ NTSTATUS CMMOB_SetReader_38400Baud ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS;;
SmartcardDebug(DEBUG_TRACE, ("%s!SetReader_38400Baud: Enter\n",DRIVER_NAME));
// check if card is already in specific mode
if (SmartcardExtension->ReaderCapabilities.CurrentState != SCARD_SPECIFIC) { NTStatus = STATUS_INVALID_DEVICE_REQUEST; goto ExitSetReader38400; }
// set 384000 Baud for 3.58 MHz card
SmartcardExtension->ReaderExtension->CardParameters.bBaudRateHigh=0x00; SmartcardExtension->ReaderExtension->CardParameters.bBaudRateLow=0x5D; NTStatus = CMMOB_SetCardParameters (SmartcardExtension->ReaderExtension);
ExitSetReader38400: *SmartcardExtension->IoRequest.Information = 0L; SmartcardDebug(DEBUG_TRACE, ("%s!SetReader_38400Baud: Exit %lx\n",DRIVER_NAME,NTStatus));
return(NTStatus); }
/*****************************************************************************
Routine Description:
Arguments:
Return Value: STATUS_UNSUCCESSFUL STATUS_SUCCESS
*****************************************************************************/ NTSTATUS CMMOB_SetHighSpeed_CR80S_SAMOS ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus; UCHAR abCR80S_SAMOS_SET_HIGH_SPEED[4] = {0xFF,0x11,0x94,0x7A};
SmartcardDebug(DEBUG_TRACE, ("%s!SetHighSpeed_CR80S_SAMOS: Enter\n",DRIVER_NAME));
NTStatus = CMMOB_SetSpeed (SmartcardExtension, abCR80S_SAMOS_SET_HIGH_SPEED); SmartcardDebug(DEBUG_TRACE, ("%s!SetHighSpeed_CR80S_SAMOS: Exit %lx\n",DRIVER_NAME,NTStatus));
return(NTStatus); }
/*****************************************************************************
Routine Description:
Arguments:
Return Value: STATUS_UNSUCCESSFUL STATUS_SUCCESS
*****************************************************************************/ NTSTATUS CMMOB_SetSpeed ( IN PSMARTCARD_EXTENSION SmartcardExtension, IN PUCHAR abFIDICommand ) { NTSTATUS NTStatus; NTSTATUS DebugStatus; UCHAR abReadBuffer[16]; ULONG ulBytesRead; ULONG ulWaitTime;
SmartcardDebug(DEBUG_TRACE, ("%s!SetSpeed: Enter\n",DRIVER_NAME));
#ifdef IOCARD
SmartcardExtension->ReaderExtension->fTActive=TRUE; NTStatus = CMMOB_SetFlags1(SmartcardExtension->ReaderExtension); if (NTStatus != STATUS_SUCCESS) { goto ExitSetSpeed; } #endif
#if DBG
{ ULONG k; SmartcardDebug(DEBUG_PROTOCOL,("%s!SetSpeed: writing: ",DRIVER_NAME)); for (k = 0;k < 4;k++) SmartcardDebug(DEBUG_PROTOCOL,("%2.2x ",abFIDICommand[k])); SmartcardDebug(DEBUG_PROTOCOL,("\n")); } #endif
NTStatus = CMMOB_WriteT1(SmartcardExtension->ReaderExtension,4, abFIDICommand); if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_ERROR, ("%s!SetSpeed: writing high speed command failed\n",DRIVER_NAME)); goto ExitSetSpeed; }
// read back pts data
// maximim initial waiting time is 9600 * etu
// clock divider of this card 512 => 1.4 sec is sufficient
ulWaitTime = 1400; NTStatus = CMMOB_ReadT1(SmartcardExtension->ReaderExtension,4, ulWaitTime,ulWaitTime,abReadBuffer,&ulBytesRead);
SmartcardDebug(DEBUG_PROTOCOL, ("%s!SetSpeed: reading echo: ",DRIVER_NAME));
if (NTStatus != STATUS_SUCCESS) { SmartcardDebug(DEBUG_PROTOCOL,("failed\n")); goto ExitSetSpeed; }
#if DBG
{ ULONG k; for (k = 0;k < ulBytesRead;k++) SmartcardDebug(DEBUG_PROTOCOL,("%2.2x ",abReadBuffer[k])); SmartcardDebug(DEBUG_PROTOCOL,("\n")); } #endif
// if the card has accepted this string , the string is echoed
if (abReadBuffer[0] == abFIDICommand[0] && abReadBuffer[1] == abFIDICommand[1] && abReadBuffer[2] == abFIDICommand[2] && abReadBuffer[3] == abFIDICommand[3] ) { SmartcardExtension->ReaderExtension->CardParameters.bBaudRateLow=63; SmartcardExtension->ReaderExtension->CardParameters.bBaudRateHigh=0; NTStatus = CMMOB_SetCardParameters (SmartcardExtension->ReaderExtension); } else { SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET; CMMOB_CardPower(SmartcardExtension);
NTStatus = STATUS_UNSUCCESSFUL; }
ExitSetSpeed:
*SmartcardExtension->IoRequest.Information = 0L; if (NTStatus != STATUS_SUCCESS) { NTStatus = STATUS_UNSUCCESSFUL; } #ifdef IOCARD
SmartcardExtension->ReaderExtension->fTActive=FALSE; CMMOB_SetFlags1(SmartcardExtension->ReaderExtension); #endif
SmartcardDebug(DEBUG_TRACE, ("%s!SetSpeed: Exit %lx\n",DRIVER_NAME,NTStatus));
return NTStatus; }
/*****************************************************************************
Routine Description: This function always returns 'CardManMobile'.
Arguments: pointer to SMARTCARD_EXTENSION
Return Value: NT status
*****************************************************************************/ NTSTATUS CMMOB_ReadDeviceDescription( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; BYTE abDeviceDescription[] = "CardManMobile";
SmartcardDebug(DEBUG_TRACE, ("%s!ReadDeviceDescription : Enter\n",DRIVER_NAME));
if (SmartcardExtension->IoRequest.ReplyBufferLength < sizeof(abDeviceDescription)) { NTStatus = STATUS_BUFFER_OVERFLOW; *SmartcardExtension->IoRequest.Information = 0L; goto ExitReadDeviceDescription; } else { RtlCopyBytes((PVOID)SmartcardExtension->IoRequest.ReplyBuffer, (PVOID)abDeviceDescription,sizeof(abDeviceDescription)); *SmartcardExtension->IoRequest.Information = sizeof(abDeviceDescription); }
ExitReadDeviceDescription: SmartcardDebug(DEBUG_TRACE, ("%s!ReadDeviceDescription : Exit %lx\n",DRIVER_NAME,NTStatus)); return NTStatus; }
/*****************************************************************************
Routine Description:
Arguments:
Return Value:
*****************************************************************************/ NTSTATUS CMMOB_GetFWVersion ( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS;
SmartcardDebug(DEBUG_TRACE, ("%s!GetFWVersion : Enter\n",DRIVER_NAME));
if (SmartcardExtension->IoRequest.ReplyBufferLength < sizeof (ULONG)) { NTStatus = STATUS_BUFFER_OVERFLOW; *SmartcardExtension->IoRequest.Information = 0; } else { *(PULONG)(SmartcardExtension->IoRequest.ReplyBuffer) = SmartcardExtension->ReaderExtension->ulFWVersion; *SmartcardExtension->IoRequest.Information = sizeof(ULONG); }
SmartcardDebug(DEBUG_TRACE, ("%s!GetFWVersion : Exit %lx\n",DRIVER_NAME,NTStatus));
return NTStatus; }
/*****************************************************************************
CMMOB_CardTracking: callback handler for SMCLIB RDF_CARD_TRACKING. the requested event was validated by the smclib (i.e. a card removal request will only be passed if a card is present). for a win95 build STATUS_PENDING will be returned without any other action. for NT the cancel routine for the irp will be set to the drivers cancel routine.
Arguments: SmartcardExtension context of call
Return Value: STATUS_PENDING ******************************************************************************/ NTSTATUS CMMOB_CardTracking( PSMARTCARD_EXTENSION SmartcardExtension ) { KIRQL CurrentIrql;
SmartcardDebug(DEBUG_TRACE, ("%s!CardTracking: Enter\n",DRIVER_NAME ));
//
// set cancel routine
//
IoAcquireCancelSpinLock( &CurrentIrql ); IoSetCancelRoutine(SmartcardExtension->OsData->NotificationIrp, CMMOB_CancelCardTracking); IoReleaseCancelSpinLock( CurrentIrql );
//
// Mark notification irp pending
//
IoMarkIrpPending(SmartcardExtension->OsData->NotificationIrp);
SmartcardDebug(DEBUG_TRACE, ("%s!CardTracking: Exit\n",DRIVER_NAME ));
return( STATUS_PENDING ); }
/*****************************************************************************
CMMOB_CompleteCardTracking: finishes a pending tracking request if the device will be unloaded
Arguments: DeviceObject context of the request NTStatus NTStatus to report to the calling process
Return Value:
******************************************************************************/ VOID CMMOB_CompleteCardTracking( PSMARTCARD_EXTENSION SmartcardExtension ) { KIRQL ioIrql, keIrql; PIRP NotificationIrp;
IoAcquireCancelSpinLock(&ioIrql); KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock, &keIrql);
NotificationIrp = SmartcardExtension->OsData->NotificationIrp; SmartcardExtension->OsData->NotificationIrp = NULL;
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock, keIrql);
if (NotificationIrp!=NULL) { IoSetCancelRoutine(NotificationIrp, NULL); }
IoReleaseCancelSpinLock(ioIrql);
if (NotificationIrp!=NULL) { //finish the request
if (NotificationIrp->Cancel) { NotificationIrp->IoStatus.Status = STATUS_CANCELLED; } else { NotificationIrp->IoStatus.Status = STATUS_SUCCESS; } NotificationIrp->IoStatus.Information = 0;
SmartcardDebug(DEBUG_DRIVER, ("%s!CompleteCardTracking: Completing Irp %lx Status=%lx\n", DRIVER_NAME, NotificationIrp,NotificationIrp->IoStatus.Status));
IoCompleteRequest(NotificationIrp, IO_NO_INCREMENT ); } }
/*****************************************************************************
CMMOB_CancelCardTracking This routine is called by the I/O system when the irp should be cancelled
Arguments:
DeviceObject - Pointer to device object for this miniport Irp - IRP involved.
Return Value:
STATUS_CANCELLED ******************************************************************************/ NTSTATUS CMMOB_CancelCardTracking( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension;
SmartcardDebug(DEBUG_TRACE, ("%s!CancelCardTracking: Enter\n",DRIVER_NAME));
ASSERT(Irp == SmartcardExtension->OsData->NotificationIrp);
IoReleaseCancelSpinLock(Irp->CancelIrql);
CMMOB_CompleteCardTracking(SmartcardExtension);
SmartcardDebug(DEBUG_TRACE, ("%s!CancelCardTracking: Exit\n",DRIVER_NAME));
return STATUS_CANCELLED; }
/*****************************************************************************
CMMOB_StartCardTracking:
Arguments: DeviceObject context of call
Return Value: STATUS_SUCCESS NTStatus returned by LowLevel routines ******************************************************************************/ NTSTATUS CMMOB_StartCardTracking( IN PDEVICE_OBJECT DeviceObject ) { NTSTATUS NTStatus = STATUS_SUCCESS; HANDLE hThread; PDEVICE_EXTENSION DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension;
DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension;
SmartcardDebug(DEBUG_TRACE, ( "%s!StartCardTracking: Enter\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ( "%s!StartCardTracking: IRQL %i\n",DRIVER_NAME,KeGetCurrentIrql()));
KeWaitForSingleObject(&SmartcardExtension->ReaderExtension->CardManIOMutex, Executive, KernelMode, FALSE, NULL);
// settings for thread synchronization
SmartcardExtension->ReaderExtension->fTerminateUpdateThread = FALSE;
// create thread for updating current state
NTStatus = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, NULL, NULL, NULL, CMMOB_UpdateCurrentStateThread, DeviceObject);
if (NT_SUCCESS(NTStatus)) { //
// We've got the thread. Now get a pointer to it.
//
NTStatus = ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, &SmartcardExtension->ReaderExtension->ThreadObjectPointer, NULL);
if (NT_ERROR(NTStatus)) { SmartcardExtension->ReaderExtension->fTerminateUpdateThread = TRUE; } else { //
// Now that we have a reference to the thread
// we can simply close the handle.
//
ZwClose(hThread);
SmartcardExtension->ReaderExtension->fUpdateThreadRunning = TRUE; } }
SmartcardDebug(DEBUG_DRIVER, ("%s!-----------------------------------------------------------\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ("%s!STARTING THREAD\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ("%s!-----------------------------------------------------------\n",DRIVER_NAME));
KeReleaseMutex(&SmartcardExtension->ReaderExtension->CardManIOMutex,FALSE);
SmartcardDebug(DEBUG_TRACE, ( "%s!CMMOB_StartCardTracking: Exit %lx\n",DRIVER_NAME,NTStatus));
return NTStatus; }
/*****************************************************************************
CMMOB_StopCardTracking:
Arguments: DeviceObject context of call
Return Value: ******************************************************************************/ VOID CMMOB_StopCardTracking( IN PDEVICE_OBJECT DeviceObject ) { PDEVICE_EXTENSION DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension;
SmartcardDebug(DEBUG_TRACE, ( "%s!StopCardTracking: Enter\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ( "%s!StopCardTracking: IRQL %i\n",DRIVER_NAME,KeGetCurrentIrql()));
DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension;
if (SmartcardExtension->ReaderExtension->fUpdateThreadRunning) {
// kill thread
KeWaitForSingleObject(&SmartcardExtension->ReaderExtension->CardManIOMutex, Executive, KernelMode, FALSE, NULL );
SmartcardExtension->ReaderExtension->fTerminateUpdateThread = TRUE;
KeReleaseMutex(&SmartcardExtension->ReaderExtension->CardManIOMutex,FALSE);
/* this doesn't work with Win98
//
// Wait on the thread handle, when the wait is satisfied, the
// thread has gone away.
//
KeWaitForSingleObject(SmartcardExtension->ReaderExtension->ThreadObjectPointer, Executive, KernelMode, FALSE, NULL); */
while (SmartcardExtension->ReaderExtension->fUpdateThreadRunning==TRUE) { SysDelay(1); } }
SmartcardDebug(DEBUG_TRACE, ( "%s!StopCardTracking: Exit\n",DRIVER_NAME));
return; }
/*****************************************************************************
CMMOB_UpdateCurrentStateThread:
Arguments: DeviceObject context of call
Return Value: ******************************************************************************/ VOID CMMOB_UpdateCurrentStateThread( IN PVOID Context ) { NTSTATUS NTStatus = STATUS_SUCCESS; PDEVICE_OBJECT DeviceObject = Context; PDEVICE_EXTENSION DeviceExtension; PSMARTCARD_EXTENSION SmartcardExtension; ULONG ulInterval;
DeviceExtension = DeviceObject->DeviceExtension; SmartcardExtension = &DeviceExtension->SmartcardExtension;
KeWaitForSingleObject(&DeviceExtension->CanRunUpdateThread, Executive, KernelMode, FALSE, NULL);
SmartcardDebug(DEBUG_DRIVER, ( "%s!UpdateCurrentStateThread: started\n",DRIVER_NAME));
while (TRUE) { // every 500 ms the NTStatus request is sent
ulInterval = 500; KeWaitForSingleObject(&SmartcardExtension->ReaderExtension->CardManIOMutex, Executive, KernelMode, FALSE, NULL); /*
SmartcardDebug(DEBUG_TRACE, ("%s!UpdateCurrentStateThread executed\n",DRIVER_NAME)); */ if (SmartcardExtension->ReaderExtension->fTerminateUpdateThread) { SmartcardDebug(DEBUG_DRIVER, ("%s!-----------------------------------------------------------\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentStateThread: STOPPING THREAD\n",DRIVER_NAME)); SmartcardDebug(DEBUG_DRIVER, ("%s!-----------------------------------------------------------\n",DRIVER_NAME));
KeReleaseMutex(&SmartcardExtension->ReaderExtension->CardManIOMutex,FALSE); SmartcardExtension->ReaderExtension->fUpdateThreadRunning = FALSE; PsTerminateSystemThread( STATUS_SUCCESS ); }
//
// get current card state
//
NTStatus = CMMOB_UpdateCurrentState(SmartcardExtension); if (NTStatus == STATUS_DEVICE_DATA_ERROR) { SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentStateThread: setting update interval to 1ms\n",DRIVER_NAME)); ulInterval = 1; } else if (NTStatus != STATUS_SUCCESS && NTStatus != STATUS_NO_SUCH_DEVICE) { SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentStateThread: UpdateCurrentState failed!\n",DRIVER_NAME)); }
KeReleaseMutex(&SmartcardExtension->ReaderExtension->CardManIOMutex,FALSE);
SysDelay (ulInterval); }
}
/*****************************************************************************
CMMOB_UpdateCurrentState:
Arguments: DeviceObject context of call
Return Value: ******************************************************************************/ NTSTATUS CMMOB_UpdateCurrentState( IN PSMARTCARD_EXTENSION SmartcardExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; BOOL fCardStateChanged = FALSE;
/*
SmartcardDebug(DEBUG_TRACE, ("%s!UpdateCurrentState executed\n",DRIVER_NAME)); */ //
// get card state from cardman
//
NTStatus = CMMOB_ResetReader(SmartcardExtension->ReaderExtension); if (NTStatus == STATUS_SUCCESS || NTStatus == STATUS_NO_SUCH_DEVICE) { if (NTStatus == STATUS_SUCCESS) { if (CMMOB_CardInserted(SmartcardExtension->ReaderExtension)) { if (CMMOB_CardPowered(SmartcardExtension->ReaderExtension)) SmartcardExtension->ReaderExtension->ulNewCardState = POWERED; else SmartcardExtension->ReaderExtension->ulNewCardState = INSERTED; } else SmartcardExtension->ReaderExtension->ulNewCardState = REMOVED; } else SmartcardExtension->ReaderExtension->ulNewCardState = REMOVED;
if (SmartcardExtension->ReaderExtension->ulNewCardState == INSERTED && SmartcardExtension->ReaderExtension->ulOldCardState == POWERED ) { // card has been removed and reinserted
SmartcardExtension->ReaderExtension->ulNewCardState = REMOVED; }
if ((SmartcardExtension->ReaderExtension->ulNewCardState == INSERTED && (SmartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN || SmartcardExtension->ReaderExtension->ulOldCardState == REMOVED )) || (SmartcardExtension->ReaderExtension->ulNewCardState == POWERED && SmartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN )) { // card has been inserted
SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentState: smartcard inserted\n",DRIVER_NAME)); SmartcardExtension->ReaderExtension->ulOldCardState = SmartcardExtension->ReaderExtension->ulNewCardState; SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; fCardStateChanged = TRUE; }
if (SmartcardExtension->ReaderExtension->ulNewCardState == REMOVED && (SmartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN || SmartcardExtension->ReaderExtension->ulOldCardState == INSERTED || SmartcardExtension->ReaderExtension->ulOldCardState == POWERED )) { // card has been removed
SmartcardDebug(DEBUG_DRIVER, ("%s!UpdateCurrentState: smartcard removed\n",DRIVER_NAME)); SmartcardExtension->ReaderExtension->ulOldCardState = SmartcardExtension->ReaderExtension->ulNewCardState; SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT; SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED; fCardStateChanged = TRUE;
// clear any cardspecific data
SmartcardExtension->CardCapabilities.ATR.Length = 0; RtlFillMemory((PVOID)&SmartcardExtension->ReaderExtension->CardParameters, sizeof(CARD_PARAMETERS), 0x00); }
// complete IOCTL_SMARTCARD_IS_ABSENT or IOCTL_SMARTCARD_IS_PRESENT
if (fCardStateChanged == TRUE && SmartcardExtension->OsData->NotificationIrp ) { SmartcardDebug(DEBUG_DRIVER,("%s!UpdateCurrentState: completing IRP\n",DRIVER_NAME)); CMMOB_CompleteCardTracking(SmartcardExtension); }
}
return NTStatus; }
/*****************************************************************************
CMMOB_ResetReader: Resets the reader
Arguments: ReaderExtension context of the call
Return Value: none ******************************************************************************/ NTSTATUS CMMOB_ResetReader( PREADER_EXTENSION ReaderExtension ) { NTSTATUS NTStatus; BOOLEAN fToggle; UCHAR bFlags1;
NTStatus = CMMOB_WriteRegister(ReaderExtension,ADDR_WRITEREG_FLAGS0,CMD_RESET_SM); if (NTStatus != STATUS_SUCCESS) return NTStatus;
#ifdef IOCARD
// check for reader presence
bFlags1 = ReaderExtension->bPreviousFlags1; bFlags1 |= FLAG_CHECK_PRESENCE; NTStatus = CMMOB_WriteRegister(ReaderExtension, ADDR_WRITEREG_FLAGS1, bFlags1); // don't check for status because
// we have to set back fCheckPresence for proper working
fToggle = CMMOB_GetReceiveFlag(ReaderExtension); bFlags1 = ReaderExtension->bPreviousFlags1; NTStatus = CMMOB_WriteRegister(ReaderExtension, ADDR_WRITEREG_FLAGS1, bFlags1); if (NTStatus != STATUS_SUCCESS) return NTStatus; if (fToggle == CMMOB_GetReceiveFlag(ReaderExtension)) { SmartcardDebug(DEBUG_DRIVER, ("%s!ResetReader: CardMan Mobile removed!\n",DRIVER_NAME)); return STATUS_NO_SUCH_DEVICE; } #endif
return NTStatus; }
/*****************************************************************************
CMMOB_BytesReceived: Reads how many bytes are already received from the card by the reader
Arguments: ReaderExtension context of the call
Return Value: NTStatus ******************************************************************************/ NTSTATUS CMMOB_BytesReceived( PREADER_EXTENSION ReaderExtension, PULONG pulBytesReceived ) { NTSTATUS NTStatus = STATUS_SUCCESS; ULONG ulBytesReceived; ULONG ulBytesReceivedCheck; UCHAR bReg;
/*
SmartcardDebug(DEBUG_TRACE, ( "%s!BytesReceived Enter\n",DRIVER_NAME)); */ *pulBytesReceived=0; if (CMMOB_GetReceiveFlag(ReaderExtension) || ReaderExtension->CardParameters.fT0Mode) { do { NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_BYTES_RECEIVED,&bReg); if (NTStatus!=STATUS_SUCCESS) return NTStatus; ulBytesReceived=bReg; NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_FLAGS0,&bReg); if (NTStatus!=STATUS_SUCCESS) return NTStatus; if ((bReg & FLAG_BYTES_RECEIVED_B9) == FLAG_BYTES_RECEIVED_B9) { ulBytesReceived+=0x100; }
NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_BYTES_RECEIVED,&bReg); if (NTStatus!=STATUS_SUCCESS) return NTStatus; ulBytesReceivedCheck=bReg; NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_FLAGS0,&bReg); if (NTStatus!=STATUS_SUCCESS) return NTStatus; if ((bReg & FLAG_BYTES_RECEIVED_B9) == FLAG_BYTES_RECEIVED_B9) { ulBytesReceivedCheck+=0x100; } } while (ulBytesReceived!=ulBytesReceivedCheck); *pulBytesReceived=ulBytesReceived; } /*
SmartcardDebug(DEBUG_TRACE, ( "%s!BytesReceived Exit\n",DRIVER_NAME)); */ return NTStatus; }
/*****************************************************************************
CMMOB_SetFlags1: Sets register Flags1
Arguments: ReaderExtension context of the call
Return Value: none ******************************************************************************/ NTSTATUS CMMOB_SetFlags1 ( PREADER_EXTENSION ReaderExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS; UCHAR bFlags1;
bFlags1 = ReaderExtension->CardParameters.bBaudRateHigh; if (ReaderExtension->CardParameters.fInversRevers) bFlags1 |= FLAG_INVERS_PARITY; if (ReaderExtension->CardParameters.bClockFrequency==8) bFlags1 |= FLAG_CLOCK_8MHZ; if (ReaderExtension->CardParameters.fT0Write) bFlags1 |= FLAG_T0_WRITE; #ifdef IOCARD
if (ReaderExtension->bAddressHigh == 1) bFlags1 |= FLAG_BUFFER_ADDR_B9; if (ReaderExtension->fTActive) bFlags1 |= FLAG_TACTIVE; if (ReaderExtension->fReadCIS) bFlags1 |= FLAG_READ_CIS; #endif
ReaderExtension->bPreviousFlags1=bFlags1; NTStatus = CMMOB_WriteRegister(ReaderExtension, ADDR_WRITEREG_FLAGS1, bFlags1); return NTStatus; }
/*****************************************************************************
CMMOB_SetCardParameters: Sets card parameters (baudrate, stopbits)
Arguments: ReaderExtension context of the call
Return Value: none ******************************************************************************/ NTSTATUS CMMOB_SetCardParameters ( PREADER_EXTENSION ReaderExtension ) { NTSTATUS NTStatus = STATUS_SUCCESS;
NTStatus = CMMOB_SetFlags1 (ReaderExtension); if (NTStatus!=STATUS_SUCCESS) return NTStatus;
NTStatus = CMMOB_WriteRegister(ReaderExtension, ADDR_WRITEREG_BAUDRATE, ReaderExtension->CardParameters.bBaudRateLow); if (NTStatus!=STATUS_SUCCESS) return NTStatus;
NTStatus = CMMOB_WriteRegister(ReaderExtension, ADDR_WRITEREG_STOPBITS, ReaderExtension->CardParameters.bStopBits); return NTStatus; }
/*****************************************************************************
CMMOB_CardInserted: Sets card parameters (baudrate, stopbits)
Arguments: ReaderExtension context of the call
Return Value: TRUE if card is inserted ******************************************************************************/ BOOLEAN CMMOB_CardInserted( IN PREADER_EXTENSION ReaderExtension ) { NTSTATUS NTStatus=STATUS_SUCCESS; UCHAR bReg;
NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_FLAGS0,&bReg); if (NTStatus!=STATUS_SUCCESS) return FALSE; /*
SmartcardDebug(DEBUG_TRACE, ("%s!CardInserted: ReadReg Flags0 = %x\n",DRIVER_NAME, (ULONG)bReg)); */ if ((bReg & FLAG_INSERTED)==FLAG_INSERTED) { return TRUE; } return FALSE; }
/*****************************************************************************
CMMOB_CardPowered: Sets card parameters (baudrate, stopbits)
Arguments: ReaderExtension context of the call
Return Value: TRUE if card is powered ******************************************************************************/ BOOLEAN CMMOB_CardPowered( IN PREADER_EXTENSION ReaderExtension ) { NTSTATUS NTStatus=STATUS_SUCCESS; UCHAR bReg;
NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_FLAGS0,&bReg); if (NTStatus!=STATUS_SUCCESS) return FALSE; if ((bReg & FLAG_POWERED)==FLAG_POWERED) { return TRUE; } return FALSE; }
/*****************************************************************************
CMMOB_ProcedureReceived:
Arguments: ReaderExtension context of the call
Return Value: TRUE if a procedure byte has been received ******************************************************************************/ BOOLEAN CMMOB_ProcedureReceived( IN PREADER_EXTENSION ReaderExtension ) { NTSTATUS NTStatus=STATUS_SUCCESS; UCHAR bReg;
NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_FLAGS1,&bReg); if (NTStatus!=STATUS_SUCCESS) return FALSE; if ((bReg & FLAG_NOPROCEDURE_RECEIVED)!=FLAG_NOPROCEDURE_RECEIVED) { return TRUE; } return FALSE; }
/*****************************************************************************
CMMOB_GetReceiveFlag:
Arguments: ReaderExtension context of the call
Return Value: TRUE if a receive flag is set ******************************************************************************/ BOOLEAN CMMOB_GetReceiveFlag( IN PREADER_EXTENSION ReaderExtension ) { NTSTATUS NTStatus=STATUS_SUCCESS; UCHAR bReg;
NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_FLAGS0,&bReg); /*
SmartcardDebug(DEBUG_TRACE, ("%s!GetReceiveFlag: ReadReg Flags0 = %x\n",DRIVER_NAME, (ULONG)bReg)); */ if (NTStatus!=STATUS_SUCCESS) return FALSE; if ((bReg & FLAG_RECEIVE)==FLAG_RECEIVE) { return TRUE; } return FALSE; }
/*****************************************************************************
CMMOB_GetProcedureByte: Reads how many bytes are already received from the card by the reader
Arguments: ReaderExtension context of the call
Return Value: NTStatus ******************************************************************************/ NTSTATUS CMMOB_GetProcedureByte( IN PREADER_EXTENSION ReaderExtension, OUT PUCHAR pbProcedureByte ) { NTSTATUS NTStatus = STATUS_SUCCESS; UCHAR bReg; UCHAR bRegPrevious;
do { NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_LASTPROCEDURE_T0,&bRegPrevious); if (NTStatus!=STATUS_SUCCESS) return NTStatus; NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_LASTPROCEDURE_T0,&bReg); if (NTStatus!=STATUS_SUCCESS) return NTStatus; } while (bReg!=bRegPrevious); *pbProcedureByte=bReg; return NTStatus; }
/*****************************************************************************
CMMOB_WriteT0: Writes T0 request to card
Arguments: ReaderExtension context of the call
Return Value: NT STATUS ******************************************************************************/ NTSTATUS CMMOB_WriteT0( IN PREADER_EXTENSION ReaderExtension, IN ULONG ulBytesToWrite, IN ULONG ulBytesToReceive, IN PUCHAR pbData ) { NTSTATUS NTStatus = STATUS_SUCCESS; UCHAR bFlags0; UCHAR bReg;
if (ulBytesToWrite > CMMOB_MAXBUFFER) { NTStatus = STATUS_BUFFER_OVERFLOW; return NTStatus; } // dummy read, to reset flag procedure received
NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_FLAGS1,&bReg);
NTStatus = CMMOB_WriteBuffer(ReaderExtension,ulBytesToWrite,pbData); if (NTStatus != STATUS_SUCCESS) return NTStatus;
// write instruction byte to register
NTStatus = CMMOB_WriteRegister(ReaderExtension,ADDR_WRITEREG_PROCEDURE_T0,pbData[1]); if (NTStatus != STATUS_SUCCESS) return NTStatus;
// write message length
NTStatus = CMMOB_WriteRegister(ReaderExtension,ADDR_WRITEREG_MESSAGE_LENGTH, (UCHAR)((ulBytesToWrite+ulBytesToReceive) & 0xFF)); if (NTStatus != STATUS_SUCCESS) return NTStatus; if ((ulBytesToWrite+ulBytesToReceive) > 0xFF) { bFlags0=1; } else { bFlags0=0; } bFlags0 |= CMD_WRITE_T0; NTStatus = CMMOB_WriteRegister(ReaderExtension,ADDR_WRITEREG_FLAGS0,bFlags0); return NTStatus; }
/*****************************************************************************
CMMOB_WriteT1: Writes T1 request to card
Arguments: ReaderExtension context of the call
Return Value: NT STATUS ******************************************************************************/ NTSTATUS CMMOB_WriteT1( IN PREADER_EXTENSION ReaderExtension, IN ULONG ulBytesToWrite, IN PUCHAR pbData ) { NTSTATUS NTStatus = STATUS_SUCCESS; UCHAR bFlags0;
if (ulBytesToWrite > CMMOB_MAXBUFFER) { NTStatus = STATUS_BUFFER_OVERFLOW; return NTStatus; } NTStatus = CMMOB_WriteBuffer(ReaderExtension,ulBytesToWrite,pbData); if (NTStatus != STATUS_SUCCESS) return NTStatus; NTStatus = CMMOB_WriteRegister(ReaderExtension,ADDR_WRITEREG_MESSAGE_LENGTH, (UCHAR)(ulBytesToWrite & 0xFF)); if (NTStatus != STATUS_SUCCESS) return NTStatus; if (ulBytesToWrite > 0xFF) { bFlags0=1; } else { bFlags0=0; } bFlags0 |= CMD_WRITE_T1; NTStatus = CMMOB_WriteRegister(ReaderExtension,ADDR_WRITEREG_FLAGS0,bFlags0); return NTStatus; }
/*****************************************************************************
CMMOB_ReadT0: Reads T0 reply from card
Arguments: ReaderExtension context of the call
Return Value: NT STATUS ******************************************************************************/ NTSTATUS CMMOB_ReadT0( IN PREADER_EXTENSION ReaderExtension, IN ULONG ulBytesToRead, IN ULONG ulBytesSent, IN ULONG ulCWT, OUT PUCHAR pbData, OUT PULONG pulBytesRead, OUT PBOOLEAN pfDataSent ) { NTSTATUS NTStatus = STATUS_SUCCESS; KTIMER TimerWait; ULONG ulBytesReceived; ULONG ulBytesReceivedPrevious; LARGE_INTEGER liWaitTime; BOOLEAN fTimeExpired; BOOLEAN fProcedureReceived; BOOLEAN fTransmissionFinished; UCHAR bProcedureByte=0;
SmartcardDebug(DEBUG_TRACE, ("%s!ReadT0: Enter BytesToRead = %li\n",DRIVER_NAME,ulBytesToRead));
//initialize Timer
KeInitializeTimer(&TimerWait); liWaitTime = RtlConvertLongToLargeInteger(ulCWT * -10000L);
*pulBytesRead = 0; *pfDataSent = FALSE;
do { KeSetTimer(&TimerWait,liWaitTime,NULL); NTStatus=CMMOB_BytesReceived (ReaderExtension,&ulBytesReceivedPrevious); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT0; do { fTimeExpired = KeReadStateTimer(&TimerWait); fTransmissionFinished=CMMOB_GetReceiveFlag(ReaderExtension); fProcedureReceived=CMMOB_ProcedureReceived(ReaderExtension); NTStatus=CMMOB_BytesReceived (ReaderExtension,&ulBytesReceived); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT0; // wait 1 ms, so that processor is not blocked
SysDelay(1); } while (fTimeExpired==FALSE && fProcedureReceived==FALSE && ulBytesReceivedPrevious == ulBytesReceived && fTransmissionFinished==FALSE);
if (fProcedureReceived) { NTStatus=CMMOB_GetProcedureByte (ReaderExtension,&bProcedureByte); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT0; // check for SW1
if (ReaderExtension->CardParameters.fInversRevers) { CMMOB_InverseBuffer(&bProcedureByte,1); } }
if (!fTimeExpired) { KeCancelTimer(&TimerWait); } #ifdef DBG
else { SmartcardDebug(DEBUG_PROTOCOL,( "%s!----------------------------------------------\n",DRIVER_NAME)); SmartcardDebug(DEBUG_PROTOCOL,( "%s!Read T0 timed out\n",DRIVER_NAME)); SmartcardDebug(DEBUG_PROTOCOL,( "%s!----------------------------------------------\n",DRIVER_NAME)); } #endif
} while (fTimeExpired==FALSE && fTransmissionFinished==FALSE);
// read once more ulBytesReceived
// this value could have changed in the meantime
NTStatus=CMMOB_BytesReceived (ReaderExtension,&ulBytesReceived); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT0;
SmartcardDebug(DEBUG_PROTOCOL, ("%s!ReadT0: BytesReceived = %li\n",DRIVER_NAME,ulBytesReceived));
//now we should have received a reply
NTStatus=CMMOB_ResetReader (ReaderExtension); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT0;
// check for valid SW1
if ((bProcedureByte > 0x60 && bProcedureByte <= 0x6F) || (bProcedureByte >= 0x90 && bProcedureByte <= 0x9F)) { if (ReaderExtension->CardParameters.fInversRevers) { CMMOB_InverseBuffer(&bProcedureByte,1); } if (ulBytesReceived > ulBytesSent) { NTStatus=CMMOB_ReadBuffer(ReaderExtension, ulBytesSent, ulBytesReceived-ulBytesSent, pbData); if (NTStatus==STATUS_SUCCESS) { // we have to insert the procedure byte (SW1)
pbData[ulBytesReceived-ulBytesSent]=pbData[ulBytesReceived-ulBytesSent-1]; pbData[ulBytesReceived-ulBytesSent-1]=bProcedureByte; *pulBytesRead=ulBytesReceived-ulBytesSent+1; }
if (ulBytesSent > T0_HEADER_LEN) { *pfDataSent = TRUE; } } else { if (ulBytesReceived > T0_HEADER_LEN) { // it seems not all bytes were accepted by the card
// but we got SW1 SW2 - return only SW1 SW2
pbData[0]=bProcedureByte; NTStatus=CMMOB_ReadBuffer(ReaderExtension, ulBytesReceived-1, 1, &pbData[1]); *pulBytesRead=2; } else { NTStatus = STATUS_IO_TIMEOUT; } } } else { NTStatus = STATUS_IO_TIMEOUT; }
ExitReadT0:
SmartcardDebug(DEBUG_TRACE, ("%s!ReadT0: Exit\n",DRIVER_NAME ));
return NTStatus; }
/*****************************************************************************
CMMOB_ReadT1: Reads T1 reply from card
Arguments: ReaderExtension context of the call
Return Value: NT STATUS ******************************************************************************/ NTSTATUS CMMOB_ReadT1( IN PREADER_EXTENSION ReaderExtension, IN LONG lBytesToRead, IN ULONG ulBWT, IN ULONG ulCWT, OUT PUCHAR pbData, OUT PULONG pulBytesRead ) // a negative value of ulBytesToRead indicates a relative number of bytes to read
{ NTSTATUS NTStatus = STATUS_SUCCESS; KTIMER TimerWait; ULONG ulBytesReceived; LARGE_INTEGER liWaitTime; BOOLEAN fTimeExpired; ULONG ulBytesReceivedPrevious;
/*
SmartcardDebug(DEBUG_TRACE, ("%s!ReadT1: Enter\n",DRIVER_NAME )); */
//initialize Timer
KeInitializeTimer(&TimerWait);
*pulBytesRead = 0; // first wait BWT (block waiting time)
liWaitTime = RtlConvertLongToLargeInteger(ulBWT * -10000L); do { KeSetTimer(&TimerWait,liWaitTime,NULL); NTStatus=CMMOB_BytesReceived (ReaderExtension,&ulBytesReceivedPrevious); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT1; do { fTimeExpired = KeReadStateTimer(&TimerWait); NTStatus=CMMOB_BytesReceived (ReaderExtension,&ulBytesReceived); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT1; // wait 1 ms, so that processor is not blocked
SysDelay(1);
// make an adjustment of lBytesToRead (only one time)
if (lBytesToRead<= 0 && ulBytesReceived >= 3) { // get number of bytes to receive from reader
UCHAR bReg; UCHAR bRegPrevious; lBytesToRead = -lBytesToRead; do { NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_BYTESTORECEIVE_T1,&bRegPrevious); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT1; NTStatus=CMMOB_ReadRegister(ReaderExtension,ADDR_READREG_BYTESTORECEIVE_T1,&bReg); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT1; } while (bReg!=bRegPrevious); lBytesToRead += bReg; } } while (fTimeExpired==FALSE && ulBytesReceivedPrevious == ulBytesReceived && (lBytesToRead<=0 || ulBytesReceived!=(ULONG)lBytesToRead));
if (!fTimeExpired) { KeCancelTimer(&TimerWait); liWaitTime = RtlConvertLongToLargeInteger(ulCWT * -10000L); // now wait only CWT (character waiting time)
} #ifdef DBG
else { SmartcardDebug(DEBUG_PROTOCOL,( "%s!----------------------------------------------\n",DRIVER_NAME)); SmartcardDebug(DEBUG_PROTOCOL,( "%s!Read T1 timed out\n",DRIVER_NAME)); SmartcardDebug(DEBUG_PROTOCOL,( "%s!----------------------------------------------\n",DRIVER_NAME)); } #endif
} while (!fTimeExpired && (lBytesToRead<=0 || ulBytesReceived!=(ULONG)lBytesToRead));
//now we should have received a reply
NTStatus=CMMOB_ResetReader (ReaderExtension); if (NTStatus!=STATUS_SUCCESS) goto ExitReadT1;
if (ulBytesReceived==(ULONG)lBytesToRead && lBytesToRead > 0) { NTStatus=CMMOB_ReadBuffer(ReaderExtension, 0, (ULONG)lBytesToRead, pbData); if (NTStatus==STATUS_SUCCESS) { *pulBytesRead=(ULONG)lBytesToRead; } } else { NTStatus=CMMOB_ReadBuffer(ReaderExtension, 0, ulBytesReceived, pbData); if (NTStatus==STATUS_SUCCESS) { *pulBytesRead=ulBytesReceived; } NTStatus = STATUS_IO_TIMEOUT; }
ExitReadT1:
/*
SmartcardDebug(DEBUG_TRACE, ("%s!ReadT1: Exit\n",DRIVER_NAME )); */ return NTStatus; }
/*****************************************************************************
CMMOB_ReadRegister: Sets card parameters (baudrate, stopbits)
Arguments: ReaderExtension context of the call
Return Value: NT STATUS ******************************************************************************/ NTSTATUS CMMOB_ReadRegister( IN PREADER_EXTENSION ReaderExtension, IN USHORT usAddress, OUT PUCHAR pbData ) { #ifdef MEMORYCARD
*pbData = READ_REGISTER_UCHAR(ReaderExtension->pbRegsBase+usAddress); #endif
#ifdef IOCARD
*pbData = READ_PORT_UCHAR(ReaderExtension->pbRegsBase+usAddress); #endif
return STATUS_SUCCESS; }
/*****************************************************************************
CMMOB_WriteRegister: Sets card parameters (baudrate, stopbits)
Arguments: ReaderExtension context of the call
Return Value: NT STATUS ******************************************************************************/ NTSTATUS CMMOB_WriteRegister( IN PREADER_EXTENSION ReaderExtension, IN USHORT usAddress, IN UCHAR bData ) { #ifdef MEMORYCARD
WRITE_REGISTER_UCHAR(ReaderExtension->pbRegsBase+usAddress,bData); #endif
#ifdef IOCARD
WRITE_PORT_UCHAR(ReaderExtension->pbRegsBase+usAddress,bData); #endif
return STATUS_SUCCESS; }
/*****************************************************************************
CMMOB_ReadBuffer: Sets card parameters (baudrate, stopbits)
Arguments: ReaderExtension context of the call
Return Value: NT STATUS ******************************************************************************/ NTSTATUS CMMOB_ReadBuffer( IN PREADER_EXTENSION ReaderExtension, IN ULONG ulOffset, IN ULONG ulLength, OUT PUCHAR pbData ) { NTSTATUS NTStatus = STATUS_SUCCESS; ULONG i;
#ifdef IOCARD
if ((ulOffset & 0x100) == 0x100) { ReaderExtension->bAddressHigh=1; } else { ReaderExtension->bAddressHigh=0; } NTStatus = CMMOB_SetFlags1(ReaderExtension); if (NTStatus!=STATUS_SUCCESS) { goto ExitReadBuffer; } #endif
for (i=0; i<ulLength; i++) { #ifdef MEMORYCARD
*(pbData+i)=READ_REGISTER_UCHAR(ReaderExtension->pbDataBase+(2*(i+ulOffset))); // erase buffer - required for certification
WRITE_REGISTER_UCHAR(ReaderExtension->pbDataBase+(2*(i+ulOffset)),0); #endif
#ifdef IOCARD
WRITE_PORT_UCHAR(ReaderExtension->pbRegsBase+ADDR_WRITEREG_BUFFER_ADDR, (BYTE)((ulOffset+i)&0xFF)); // because we are counting up in a loop we have to set
// bit 9 of address only once
if (ulOffset+i == 0x100) { ReaderExtension->bAddressHigh=1; NTStatus = CMMOB_SetFlags1(ReaderExtension); if (NTStatus!=STATUS_SUCCESS) { goto ExitReadBuffer; } } *(pbData+i)=READ_PORT_UCHAR(ReaderExtension->pbRegsBase+ADDR_WRITEREG_BUFFER_DATA); // erase buffer - required for certification
WRITE_PORT_UCHAR(ReaderExtension->pbRegsBase+ADDR_WRITEREG_BUFFER_DATA,0); #endif
} ExitReadBuffer: return NTStatus; }
/*****************************************************************************
CMMOB_WriteBuffer: Sets card parameters (baudrate, stopbits)
Arguments: ReaderExtension context of the call
Return Value: NT STATUS ******************************************************************************/ NTSTATUS CMMOB_WriteBuffer( IN PREADER_EXTENSION ReaderExtension, IN ULONG ulLength, IN PUCHAR pbData ) { NTSTATUS NTStatus = STATUS_SUCCESS; ULONG i;
#ifdef IOCARD
ReaderExtension->bAddressHigh=0; NTStatus = CMMOB_SetFlags1(ReaderExtension); if (NTStatus!=STATUS_SUCCESS) { goto ExitWriteBuffer; } #endif
for (i=0; i<ulLength; i++) { #ifdef MEMORYCARD
WRITE_REGISTER_UCHAR(ReaderExtension->pbDataBase+(2*i),*(pbData+i)); #endif
#ifdef IOCARD
WRITE_PORT_UCHAR(ReaderExtension->pbRegsBase+ADDR_WRITEREG_BUFFER_ADDR, (BYTE)(i & 0xFF)); // because we are counting up in a loop we have to set
// bit 9 of address only once
if (i == 0x100) { ReaderExtension->bAddressHigh=1; NTStatus = CMMOB_SetFlags1(ReaderExtension); if (NTStatus!=STATUS_SUCCESS) { goto ExitWriteBuffer; } } WRITE_PORT_UCHAR(ReaderExtension->pbRegsBase+ADDR_WRITEREG_BUFFER_DATA,*(pbData+i)); #endif
}
ExitWriteBuffer: return NTStatus; }
/*****************************************************************************
Routine Description: This routine inverts the buffer Bit0 -> Bit 7 Bit1 -> Bit 6 Bit2 -> Bit 5 Bit3 -> Bit 4 Bit4 -> Bit 3 Bit5 -> Bit 2 Bit6 -> Bit 1 Bit7 -> Bit 0
Arguments: pbBuffer ... pointer to buffer ulBufferSize ... size of buffer
Return Value: none
*****************************************************************************/ VOID CMMOB_InverseBuffer ( PUCHAR pbBuffer, ULONG ulBufferSize ) { ULONG i,j; UCHAR bRevers; UCHAR bTemp;
for (i=0; i<ulBufferSize; i++) { bRevers = 0; for (j=0; j<8; j++) { bTemp = pbBuffer[i] << j; bTemp &= 0x80; bRevers |= bTemp >> (7-j); } pbBuffer[i] = ~bRevers; }
return; }
/*****************************************************************************
* History: * $Log: cmbp0scr.c $ * Revision 1.7 2001/01/22 07:12:36 WFrischauf * No comment given * * Revision 1.6 2000/09/25 14:24:31 WFrischauf * No comment given * * Revision 1.5 2000/08/24 09:05:13 TBruendl * No comment given * * Revision 1.4 2000/08/09 12:45:57 WFrischauf * No comment given * * Revision 1.3 2000/07/27 13:53:03 WFrischauf * No comment given * * ******************************************************************************/
|