Windows-Server-2003/drivers/smartcrd/cmbp0/cmbp0scr.c

3098 lines
107 KiB
C
Raw Normal View History

2020-09-28 16:13:45 -07:00
/*****************************************************************************
@doc INT EXT
******************************************************************************
* $ProjectName: $
* $ProjectRevision: $
*-----------------------------------------------------------------------------
* $Source: z:/pr/cmbp0/sw/cmbp0.ms/rcs/cmbp0scr.c $
* $Revision: 1.7 $
*-----------------------------------------------------------------------------
* $Author: WFrischauf $
*-----------------------------------------------------------------------------
* History: see EOF
*-----------------------------------------------------------------------------
*
* Copyright <EFBFBD> 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;
KIRQL irql;
#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;
ReaderExtension->fTActive=TRUE;
NTStatus = CMMOB_SetFlags1(ReaderExtension);
if (NTStatus != STATUS_SUCCESS) {
goto ExitCardPower;
}
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) {
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);
KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
&irql);
SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength;
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_NEGOTIABLE;
SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
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);
KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
&irql);
SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength;
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_NEGOTIABLE;
SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
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;
KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
&irql);
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0;
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
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;
}
KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
&irql);
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED;
SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
break;
}
ExitCardPower:
ReaderExtension->fTActive=FALSE;
CMMOB_SetFlags1(ReaderExtension);
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;
KIRQL irql;
SmartcardDebug(DEBUG_TRACE,
("%s!SetProtocol: Enter\n",DRIVER_NAME ));
ReaderExtension = SmartcardExtension->ReaderExtension;
ReaderExtension->fTActive=TRUE;
NTStatus = CMMOB_SetFlags1(ReaderExtension);
if (NTStatus != STATUS_SUCCESS) {
goto ExitSetProtocol;
}
NTStatus = STATUS_PENDING;
usSCLibProtocol = ( USHORT )( SmartcardExtension->MinorIoControlCode );
//
// check card insertion
//
KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
&irql);
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;
}
}
}
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
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<6F>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
//
KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
&irql);
if (NTStatus==STATUS_SUCCESS) {
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
} else {
SmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
}
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
//
// Return the selected protocol to the caller.
//
*(PULONG) (SmartcardExtension->IoRequest.ReplyBuffer) = SmartcardExtension->CardCapabilities.Protocol.Selected;
*SmartcardExtension->IoRequest.Information = sizeof( ULONG );
ReaderExtension->fTActive=FALSE;
CMMOB_SetFlags1(ReaderExtension);
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
SmartcardExtension->ReaderExtension->fTActive=TRUE;
NTStatus = CMMOB_SetFlags1(SmartcardExtension->ReaderExtension);
if (NTStatus != STATUS_SUCCESS) {
goto ExitTransmitT0;
}
// 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
if ( (MAXULONG - ulBytesToWrite < ulBytesToReceive + 1) ||
(ulBytesToReceive == MAXULONG)) {
NTStatus = STATUS_BUFFER_OVERFLOW;
goto ExitTransmitT0;
}
ulBytesToRead = ulBytesToWrite + ulBytesToReceive + 1;
if (ulBytesToRead > MIN_BUFFER_SIZE) {
NTStatus = STATUS_BUFFER_OVERFLOW;
goto ExitTransmitT0;
}
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);
SmartcardExtension->ReaderExtension->fTActive=FALSE;
CMMOB_SetFlags1(SmartcardExtension->ReaderExtension);
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;
SmartcardExtension->ReaderExtension->fTActive=TRUE;
NTStatus = CMMOB_SetFlags1(SmartcardExtension->ReaderExtension);
if (NTStatus != STATUS_SUCCESS) {
goto ExitTransmitT1;
}
// 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);
SmartcardExtension->ReaderExtension->fTActive=FALSE;
CMMOB_SetFlags1(SmartcardExtension->ReaderExtension);
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;
KIRQL irql;
SmartcardDebug(DEBUG_TRACE,
("%s!SetReader_9600Baud: Enter\n",DRIVER_NAME));
// check if card is already in specific mode
KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
&irql);
if (SmartcardExtension->ReaderCapabilities.CurrentState != SCARD_SPECIFIC) {
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
NTStatus = STATUS_INVALID_DEVICE_REQUEST;
goto ExitSetReader9600;
}
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
// 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;
KIRQL irql;
SmartcardDebug(DEBUG_TRACE,
("%s!SetReader_38400Baud: Enter\n",DRIVER_NAME));
// check if card is already in specific mode
KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
&irql);
if (SmartcardExtension->ReaderCapabilities.CurrentState != SCARD_SPECIFIC) {
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
NTStatus = STATUS_INVALID_DEVICE_REQUEST;
goto ExitSetReader38400;
}
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
// 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));
SmartcardExtension->ReaderExtension->fTActive=TRUE;
NTStatus = CMMOB_SetFlags1(SmartcardExtension->ReaderExtension);
if (NTStatus != STATUS_SUCCESS) {
goto ExitSetSpeed;
}
#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;
}
SmartcardExtension->ReaderExtension->fTActive=FALSE;
CMMOB_SetFlags1(SmartcardExtension->ReaderExtension);
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)) {
ZwClose(hThread);
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);
//
// Wait on the thread handle, when the wait is satisfied, the
// thread has gone away.
//
KeWaitForSingleObject(SmartcardExtension->ReaderExtension->ThreadObjectPointer,
Executive,
KernelMode,
FALSE,
NULL);
}
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);
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;
KIRQL irql;
//
// 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;
KeAcquireSpinLock(&SmartcardExtension->OsData->SpinLock,
&irql);
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);
}
KeReleaseSpinLock(&SmartcardExtension->OsData->SpinLock,
irql);
// 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;
// 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;
}
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;
if (ReaderExtension->bAddressHigh == 1)
bFlags1 |= FLAG_BUFFER_ADDR_B9;
if (ReaderExtension->fTActive)
bFlags1 |= FLAG_TACTIVE;
if (ReaderExtension->fReadCIS)
bFlags1 |= FLAG_READ_CIS;
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) {
if (ulBytesReceived - ulBytesSent > MIN_BUFFER_SIZE) {
NTStatus = STATUS_BUFFER_OVERFLOW;
goto ExitReadT0;
}
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 > CMMOB_MAXBUFFER) {
NTStatus = STATUS_BUFFER_OVERFLOW;
}
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
)
{
*pbData = READ_PORT_UCHAR(ReaderExtension->pbRegsBase+usAddress);
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
)
{
WRITE_PORT_UCHAR(ReaderExtension->pbRegsBase+usAddress,bData);
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;
if ((ulOffset & 0x100) == 0x100) {
ReaderExtension->bAddressHigh=1;
} else {
ReaderExtension->bAddressHigh=0;
}
NTStatus = CMMOB_SetFlags1(ReaderExtension);
if (NTStatus!=STATUS_SUCCESS) {
goto ExitReadBuffer;
}
for (i=0; i<ulLength; i++) {
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);
}
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;
ReaderExtension->bAddressHigh=0;
NTStatus = CMMOB_SetFlags1(ReaderExtension);
if (NTStatus!=STATUS_SUCCESS) {
goto ExitWriteBuffer;
}
for (i=0; i<ulLength; i++) {
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));
}
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
*
*
******************************************************************************/