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

3098 lines
107 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*****************************************************************************
@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;
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´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
*
*
******************************************************************************/