6696 lines
192 KiB
C
6696 lines
192 KiB
C
/*****************************************************************************
|
|
@doc INT EXT
|
|
******************************************************************************
|
|
* $ProjectName: $
|
|
* $ProjectRevision: $
|
|
*-----------------------------------------------------------------------------
|
|
* $Source: z:/pr/cmbs0/sw/sccmn50m.ms/rcs/sccmcb.c $
|
|
* $Revision: 1.7 $
|
|
*-----------------------------------------------------------------------------
|
|
* $Author: WFrischauf $
|
|
*-----------------------------------------------------------------------------
|
|
* History: see EOF
|
|
*-----------------------------------------------------------------------------
|
|
*
|
|
* Copyright © 2000 OMNIKEY AG
|
|
******************************************************************************/
|
|
|
|
#include <stdio.h>
|
|
#include "sccmn50m.h"
|
|
|
|
|
|
|
|
|
|
static ULONG dataRatesSupported[] = {9600,38400};
|
|
static ULONG CLKFrequenciesSupported[] = {4000,5000};
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_CardPower(PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
NTSTATUS DebugStatus = STATUS_SUCCESS;
|
|
UCHAR pbAtrBuffer[MAXIMUM_ATR_LENGTH];
|
|
UCHAR abSyncAtrBuffer[MAXIMUM_ATR_LENGTH];
|
|
ULONG ulAtrLength;
|
|
#if DBG
|
|
ULONG i;
|
|
#endif;
|
|
|
|
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!CardPower: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
#if DBG
|
|
switch (pSmartcardExtension->MinorIoControlCode)
|
|
{
|
|
case SCARD_WARM_RESET:
|
|
SmartcardDebug(
|
|
DEBUG_ATR,
|
|
( "%s!SCARD_WARM_RESTART\n",
|
|
DRIVER_NAME)
|
|
);
|
|
break;
|
|
case SCARD_COLD_RESET:
|
|
SmartcardDebug(
|
|
DEBUG_ATR,
|
|
( "%s!SCARD_COLD_RESTART\n",
|
|
DRIVER_NAME)
|
|
);
|
|
break;
|
|
case SCARD_POWER_DOWN:
|
|
SmartcardDebug(
|
|
DEBUG_ATR,
|
|
( "%s!SCARD_POWER_DOWN\n",
|
|
DRIVER_NAME)
|
|
);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
//DbgBreakPoint();
|
|
|
|
switch (pSmartcardExtension->MinorIoControlCode)
|
|
{
|
|
case SCARD_WARM_RESET:
|
|
case SCARD_COLD_RESET:
|
|
status = SCCMN50M_PowerOn(pSmartcardExtension,
|
|
&ulAtrLength,
|
|
pbAtrBuffer,
|
|
sizeof(pbAtrBuffer));
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitReaderPower;
|
|
}
|
|
|
|
pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength;
|
|
|
|
if (pSmartcardExtension->ReaderExtension->fRawModeNecessary == FALSE)
|
|
{
|
|
// copy ATR to smart card structure
|
|
// the lib needs the ATR for evaluation of the card parameters
|
|
|
|
MemCpy(pSmartcardExtension->CardCapabilities.ATR.Buffer,
|
|
sizeof(pSmartcardExtension->CardCapabilities.ATR.Buffer),
|
|
pbAtrBuffer,
|
|
ulAtrLength);
|
|
|
|
pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)ulAtrLength;
|
|
|
|
pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_NEGOTIABLE;
|
|
pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
|
|
|
|
status = SmartcardUpdateCardCapabilities(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitReaderPower;
|
|
}
|
|
|
|
// add extra guard time value to card stop bits
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = (UCHAR)(pSmartcardExtension->CardCapabilities.N);
|
|
|
|
// copy ATR to user space
|
|
MemCpy(pSmartcardExtension->IoRequest.ReplyBuffer,
|
|
pSmartcardExtension->IoRequest.ReplyBufferLength,
|
|
pbAtrBuffer,
|
|
ulAtrLength);
|
|
|
|
*pSmartcardExtension->IoRequest.Information = ulAtrLength;
|
|
#if DBG
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%s!ATR : ",
|
|
DRIVER_NAME));
|
|
for (i = 0;i < ulAtrLength;i++)
|
|
{
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%2.2x ",
|
|
pSmartcardExtension->CardCapabilities.ATR.Buffer[i]));
|
|
}
|
|
SmartcardDebug(DEBUG_ATR,("\n"));
|
|
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
abSyncAtrBuffer[0] = 0x3B;
|
|
abSyncAtrBuffer[1] = 0x04;
|
|
MemCpy(&abSyncAtrBuffer[2],
|
|
sizeof(abSyncAtrBuffer)-2,
|
|
pbAtrBuffer,
|
|
ulAtrLength);
|
|
|
|
|
|
ulAtrLength += 2;
|
|
|
|
MemCpy(pSmartcardExtension->CardCapabilities.ATR.Buffer,
|
|
sizeof(pSmartcardExtension->CardCapabilities.ATR.Buffer),
|
|
abSyncAtrBuffer,
|
|
ulAtrLength);
|
|
|
|
pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)(ulAtrLength);
|
|
|
|
pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
|
|
pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0;
|
|
|
|
status = SmartcardUpdateCardCapabilities(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitReaderPower;
|
|
}
|
|
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]));
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested = TRUE;
|
|
|
|
// copy ATR to user space
|
|
MemCpy(pSmartcardExtension->IoRequest.ReplyBuffer,
|
|
pSmartcardExtension->IoRequest.ReplyBufferLength,
|
|
abSyncAtrBuffer,
|
|
ulAtrLength);
|
|
|
|
*pSmartcardExtension->IoRequest.Information = ulAtrLength;
|
|
}
|
|
|
|
break;
|
|
|
|
case SCARD_POWER_DOWN:
|
|
status = SCCMN50M_PowerOff(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitReaderPower;
|
|
}
|
|
|
|
|
|
pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED;
|
|
pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
|
|
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
ExitReaderPower:
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!CardPower: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_PowerOn (
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
OUT PULONG pulAtrLength,
|
|
OUT PUCHAR pbAtrBuffer,
|
|
IN ULONG ulAtrBufferSize
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
|
|
|
|
// We always use 0x80 for reset delay
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0x80;
|
|
|
|
|
|
if (SCCMN50M_IsAsynchronousSmartCard(pSmartcardExtension) == TRUE)
|
|
{
|
|
if (pSmartcardExtension->MinorIoControlCode == SCARD_COLD_RESET)
|
|
{
|
|
status = SCCMN50M_UseColdWarmResetStrategy(pSmartcardExtension,
|
|
pulAtrLength,
|
|
pbAtrBuffer,
|
|
ulAtrBufferSize,
|
|
FALSE);
|
|
// if cold reset was not succesfull ,it maybe a SAMOS card with the sensor bug
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
status = SCCMN50M_UseColdWarmResetStrategy(pSmartcardExtension,
|
|
pulAtrLength,
|
|
pbAtrBuffer,
|
|
ulAtrBufferSize,
|
|
TRUE);
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
status = SCCMN50M_UseParsingStrategy(pSmartcardExtension,
|
|
pulAtrLength,
|
|
pbAtrBuffer,
|
|
ulAtrBufferSize);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
status = SCCMN50M_UseColdWarmResetStrategy(pSmartcardExtension,
|
|
pulAtrLength,
|
|
pbAtrBuffer,
|
|
ulAtrBufferSize,
|
|
TRUE);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
status = SCCMN50M_UseParsingStrategy(pSmartcardExtension,
|
|
pulAtrLength,
|
|
pbAtrBuffer,
|
|
ulAtrBufferSize);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("check if synchronous smart card is inserted\n"));
|
|
// try to find a synchronous smart card
|
|
status = SCCMN50M_UseSyncStrategy(pSmartcardExtension,
|
|
pulAtrLength,
|
|
pbAtrBuffer,
|
|
ulAtrBufferSize);
|
|
}
|
|
|
|
|
|
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
// smart card not powered
|
|
status = STATUS_UNRECOGNIZED_MEDIA;
|
|
*pulAtrLength = 0;
|
|
DebugStatus = SCCMN50M_PowerOff(pSmartcardExtension);
|
|
return status;
|
|
}
|
|
else
|
|
{
|
|
// add extra guard time value to card stop bits
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = (UCHAR)(pSmartcardExtension->CardCapabilities.N);
|
|
return status;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
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 SCCMN50M_InverseBuffer (
|
|
PUCHAR pbBuffer,
|
|
ULONG ulBufferSize
|
|
)
|
|
{
|
|
ULONG i;
|
|
ULONG j;
|
|
ULONG m;
|
|
ULONG n;
|
|
|
|
for (i=0; i<ulBufferSize; i++)
|
|
{
|
|
n = 0;
|
|
for (j=1; j<=8; j++)
|
|
{
|
|
m = (pbBuffer[i] << j);
|
|
m &= 0x00000100;
|
|
n |= (m >> (9-j));
|
|
}
|
|
pbBuffer[i] = (UCHAR)~n;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
This function always permforms a cold reset of the smart card.
|
|
A SAMOS card with the sensor bug will not be powered by this function.
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_UseParsingStrategy (IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
OUT PULONG pulAtrLength,
|
|
OUT PUCHAR pbAtrBuffer,
|
|
IN ULONG ulAtrBufferSize
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
UCHAR ulCardType;
|
|
UCHAR ReadBuffer[SCARD_ATR_LENGTH];
|
|
UCHAR bAtrBytesRead[SCARD_ATR_LENGTH];
|
|
ULONG ulBytesRead;
|
|
BOOLEAN fInverseAtr = FALSE;
|
|
ULONG ulAtrBufferOffset = 0;
|
|
ULONG ulHistoricalBytes;
|
|
ULONG ulNextStepBytesToRead;
|
|
ULONG ulPrevStepBytesRead;
|
|
ULONG i;
|
|
BOOLEAN fTDxSent;
|
|
BOOLEAN fAtrParsed;
|
|
BOOLEAN fOnlyT0 = TRUE;
|
|
ULONG ulOldReadTotalTimeoutMultiplier;
|
|
|
|
|
|
// DBGBreakPoint();
|
|
|
|
// set ReadTotalTimeoutMultiplier to 250ms (9600 * 372/f = initial waiting time)
|
|
ulOldReadTotalTimeoutMultiplier = pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = 250;
|
|
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0x02;
|
|
|
|
for (ulCardType = ASYNC3_CARD;ulCardType <= ASYNC5_CARD;ulCardType++)
|
|
{
|
|
// power off + resync
|
|
status = SCCMN50M_PowerOff(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitUseParsingStrategy;
|
|
}
|
|
|
|
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS);
|
|
SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY);
|
|
|
|
if (ulCardType == ASYNC3_CARD)
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ);
|
|
else
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ);
|
|
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
0,
|
|
0,
|
|
0,
|
|
2); // TS and T0 expected
|
|
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%s!ResetDelay = %d\n",
|
|
DRIVER_NAME,
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.ResetDelay));
|
|
|
|
// write config + header
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitUseParsingStrategy;
|
|
}
|
|
|
|
|
|
// read state and length + TS + T0
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,4,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer));
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
continue; // try next card
|
|
}
|
|
|
|
|
|
// contents of read buffer
|
|
// [0] ... state
|
|
// [1] ... length
|
|
// [2] ... TS
|
|
// [3] ... T0
|
|
|
|
// TS
|
|
if (ReadBuffer[2] == CHAR_INV)
|
|
{
|
|
fInverseAtr = TRUE;
|
|
}
|
|
|
|
if (fInverseAtr)
|
|
SCCMN50M_InverseBuffer(&ReadBuffer[3],1);
|
|
|
|
ulHistoricalBytes = ReadBuffer[3] & 0x0F;
|
|
ulPrevStepBytesRead = 2;
|
|
|
|
// T0 codes following TA1 - TD1
|
|
|
|
fAtrParsed = TRUE;
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%s!Step : Bytes to read = 2\n",
|
|
DRIVER_NAME));
|
|
|
|
|
|
do
|
|
{
|
|
ulNextStepBytesToRead = ulPrevStepBytesRead;
|
|
fTDxSent = FALSE;
|
|
if (ReadBuffer[ulBytesRead - 1 ] & 0x10)
|
|
ulNextStepBytesToRead++;
|
|
if (ReadBuffer[ulBytesRead - 1 ] & 0x20)
|
|
ulNextStepBytesToRead++;
|
|
if (ReadBuffer[ulBytesRead - 1 ] & 0x40)
|
|
ulNextStepBytesToRead++;
|
|
if (ReadBuffer[ulBytesRead - 1 ] & 0x80)
|
|
{
|
|
ulNextStepBytesToRead++;
|
|
fTDxSent = TRUE;
|
|
}
|
|
|
|
if (ulPrevStepBytesRead != 2 &&
|
|
ReadBuffer[ulBytesRead -1 ] & 0x0f)
|
|
{
|
|
fOnlyT0 = FALSE;
|
|
}
|
|
|
|
// -----------------------
|
|
// POWER OFF
|
|
// -----------------------
|
|
// turn power off and get state
|
|
status = SCCMN50M_PowerOff(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
fAtrParsed = FALSE;
|
|
goto ExitUseParsingStrategy; // try next card
|
|
}
|
|
|
|
// -----------------------
|
|
// POWER ON
|
|
// -----------------------
|
|
// turn on power flag
|
|
SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY);
|
|
|
|
if (ulCardType == ASYNC3_CARD)
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ);
|
|
else
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ);
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
0,
|
|
0,
|
|
0,
|
|
(UCHAR)ulNextStepBytesToRead);
|
|
|
|
|
|
// write config + header
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
fAtrParsed = FALSE;
|
|
goto ExitUseParsingStrategy; // try next card
|
|
}
|
|
|
|
|
|
|
|
// read state and length + TAx,TBx,TCx,TDx
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%s!Step : Bytes to read = %ld\n",
|
|
DRIVER_NAME,
|
|
ulNextStepBytesToRead));
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2 + ulNextStepBytesToRead,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer));
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
fAtrParsed = FALSE;
|
|
break; // try next card
|
|
}
|
|
if (fInverseAtr)
|
|
SCCMN50M_InverseBuffer(&ReadBuffer[2],ulBytesRead-2);
|
|
MemCpy(bAtrBytesRead,sizeof(bAtrBytesRead),&ReadBuffer[2],ulBytesRead -2);
|
|
|
|
#if DBG
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%s!read ATR bytes: ",
|
|
DRIVER_NAME));
|
|
for (i = 0;i < ulBytesRead-2;i++)
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%2.2x ",
|
|
bAtrBytesRead[i]));
|
|
SmartcardDebug(DEBUG_ATR,("\n"));
|
|
|
|
#endif
|
|
|
|
ulPrevStepBytesRead = ulBytesRead - 2;
|
|
|
|
} while (fTDxSent == TRUE);
|
|
|
|
|
|
// +++++++++++++++++++++++++++++++++++++++
|
|
// now we know how long the whole ATR is
|
|
// +++++++++++++++++++++++++++++++++++++++
|
|
|
|
// -----------------------
|
|
// POWER OFF
|
|
// -----------------------
|
|
// turn power off and get state
|
|
status = SCCMN50M_PowerOff(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto ExitUseParsingStrategy;
|
|
}
|
|
|
|
|
|
// -----------------------
|
|
// POWER ON
|
|
// -----------------------
|
|
// turn on power flag
|
|
SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY);
|
|
|
|
if (ulCardType == ASYNC3_CARD)
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ);
|
|
else
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ);
|
|
|
|
// bug fix : old SAMOS cards have a damaged ATR
|
|
if (bAtrBytesRead[0] == 0x3b &&
|
|
bAtrBytesRead[1] == 0xbf &&
|
|
bAtrBytesRead[2] == 0x11 &&
|
|
bAtrBytesRead[3] == 0x00 &&
|
|
bAtrBytesRead[4] == 0x81 &&
|
|
bAtrBytesRead[5] == 0x31 &&
|
|
bAtrBytesRead[6] == 0x90 &&
|
|
bAtrBytesRead[7] == 0x73 )
|
|
{
|
|
ulHistoricalBytes = 4;
|
|
}
|
|
|
|
|
|
ulNextStepBytesToRead = ulPrevStepBytesRead + ulHistoricalBytes;
|
|
if (fOnlyT0 == FALSE)
|
|
ulNextStepBytesToRead++; // TCK !
|
|
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
0,
|
|
0,
|
|
0,
|
|
(UCHAR)ulNextStepBytesToRead);
|
|
|
|
|
|
|
|
// write config + header
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitUseParsingStrategy; // try next card
|
|
}
|
|
|
|
|
|
// read whole ATR
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%s!Step : Bytes to read = %ld\n",
|
|
DRIVER_NAME,
|
|
ulNextStepBytesToRead));
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2+ulNextStepBytesToRead,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer));
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%s!Reading of whole ATR failed\n !",
|
|
DRIVER_NAME));
|
|
continue; // try next card
|
|
}
|
|
|
|
// check ATR
|
|
if (ulBytesRead - 2 < MIN_ATR_LEN)
|
|
{
|
|
status = STATUS_UNRECOGNIZED_MEDIA;
|
|
DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,2+ulNextStepBytesToRead,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer));
|
|
goto ExitUseParsingStrategy;
|
|
}
|
|
|
|
if (ulBytesRead -2 > ulAtrBufferSize)
|
|
{
|
|
// the ATR is larger then 33 bytes !!!
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitUseParsingStrategy;
|
|
}
|
|
|
|
SCCMN50M_CheckAtrModified(pbAtrBuffer,*pulAtrLength);
|
|
|
|
// pass ATR and ATR length to calling function
|
|
MemCpy(pbAtrBuffer,ulAtrBufferSize,&ReadBuffer[2],ulBytesRead -2);
|
|
*pulAtrLength = ulBytesRead -2;
|
|
|
|
|
|
if (fInverseAtr)
|
|
{
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,INVERSE_DATA);
|
|
SCCMN50M_InverseBuffer(pbAtrBuffer,*pulAtrLength);
|
|
pSmartcardExtension->ReaderExtension->fInverseAtr = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pSmartcardExtension->ReaderExtension->fInverseAtr = FALSE;
|
|
}
|
|
pSmartcardExtension->ReaderExtension->fRawModeNecessary = FALSE;
|
|
break;
|
|
}
|
|
|
|
|
|
ExitUseParsingStrategy:
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier
|
|
= ulOldReadTotalTimeoutMultiplier ;
|
|
SCCMN50M_ClearSCRControlFlags(pSmartcardExtension,IGNORE_PARITY);
|
|
SCCMN50M_ClearCardManHeader(pSmartcardExtension);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
This function performs either a cold or a warm reset depending on
|
|
the fWarmReset parameter .
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_UseColdWarmResetStrategy (IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
OUT PULONG pulAtrLength,
|
|
OUT PUCHAR pbAtrBuffer,
|
|
IN ULONG ulAtrBufferSize,
|
|
IN BOOLEAN fWarmReset
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
ULONG ulCardType;
|
|
UCHAR bReadBuffer[SCARD_ATR_LENGTH];
|
|
ULONG ulBytesRead;
|
|
ULONG ulOldReadTotalTimeoutMultiplier;
|
|
|
|
|
|
//DBGBreakPoint();
|
|
// set ReadTotalTimeoutMultiplier to 250ms (9600 * 372/f = initial waiting time)
|
|
ulOldReadTotalTimeoutMultiplier = pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = 250;
|
|
|
|
if (fWarmReset == FALSE)
|
|
{
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,COLD_RESET,ATR_LEN_ASYNC);
|
|
}
|
|
else
|
|
{
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,0,ATR_LEN_ASYNC);
|
|
}
|
|
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0x02;
|
|
|
|
|
|
for (ulCardType = ASYNC3_CARD;ulCardType <= ASYNC5_CARD;ulCardType++)
|
|
{
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS);
|
|
|
|
SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY | CM2_GET_ATR);
|
|
|
|
|
|
if (ulCardType == ASYNC3_CARD)
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_ATR,
|
|
("%s!ASYNC_3\n",
|
|
DRIVER_NAME));
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ);
|
|
}
|
|
else
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_ATR,
|
|
("%s!ASYN_5\n",
|
|
DRIVER_NAME));
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ);
|
|
}
|
|
|
|
|
|
status = SCCMN50M_ResyncCardManII(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitUseColdWarmResetStrategy;
|
|
}
|
|
|
|
// write config + header
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitUseColdWarmResetStrategy;
|
|
}
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
|
|
// read state and length
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer));
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
continue; // try next card
|
|
}
|
|
|
|
|
|
if (bReadBuffer[1] < MIN_ATR_LEN)
|
|
{
|
|
// read all remaining bytes from the CardMan
|
|
DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],&ulBytesRead,bReadBuffer,sizeof(bReadBuffer));
|
|
status = STATUS_UNRECOGNIZED_MEDIA;
|
|
goto ExitUseColdWarmResetStrategy;
|
|
}
|
|
|
|
if (bReadBuffer[1] > ulAtrBufferSize)
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitUseColdWarmResetStrategy;
|
|
}
|
|
|
|
// read ATR
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],pulAtrLength,pbAtrBuffer,ulAtrBufferSize);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
switch (pbAtrBuffer[0])
|
|
{
|
|
case CHAR_INV:
|
|
pSmartcardExtension->ReaderExtension->fRawModeNecessary = FALSE;
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,INVERSE_DATA);
|
|
SCCMN50M_InverseBuffer(pbAtrBuffer,*pulAtrLength);
|
|
pSmartcardExtension->ReaderExtension->fInverseAtr = TRUE;
|
|
break;
|
|
|
|
case CHAR_NORM:
|
|
pSmartcardExtension->ReaderExtension->fRawModeNecessary = FALSE;
|
|
pSmartcardExtension->ReaderExtension->fInverseAtr = FALSE;
|
|
break;
|
|
|
|
default :
|
|
status = STATUS_UNRECOGNIZED_MEDIA;
|
|
goto ExitUseColdWarmResetStrategy;
|
|
break;
|
|
|
|
}
|
|
|
|
// the smart card has been powered
|
|
SCCMN50M_CheckAtrModified(pbAtrBuffer,*pulAtrLength);
|
|
MemCpy(pSmartcardExtension->CardCapabilities.ATR.Buffer,
|
|
sizeof(pSmartcardExtension->CardCapabilities.ATR.Buffer),
|
|
pbAtrBuffer,
|
|
*pulAtrLength);
|
|
|
|
pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)*pulAtrLength;
|
|
|
|
status = SmartcardUpdateCardCapabilities(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
SmartcardDebug(DEBUG_ATR,
|
|
("%s!Invalid ATR received\n",
|
|
DRIVER_NAME));
|
|
goto ExitUseColdWarmResetStrategy;
|
|
}
|
|
if (SCCMN50M_IsAtrValid(pbAtrBuffer,*pulAtrLength) == FALSE)
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_ATR,
|
|
("%s!Invalid ATR received\n",
|
|
DRIVER_NAME));
|
|
status = STATUS_UNRECOGNIZED_MEDIA;
|
|
goto ExitUseColdWarmResetStrategy;
|
|
}
|
|
break;
|
|
} // end for
|
|
|
|
ExitUseColdWarmResetStrategy:
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier
|
|
= ulOldReadTotalTimeoutMultiplier ;
|
|
SCCMN50M_ClearSCRControlFlags(pSmartcardExtension,CM2_GET_ATR | IGNORE_PARITY);
|
|
SCCMN50M_ClearCardManHeader(pSmartcardExtension);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
This function checks if the received ATR is valid.
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
BOOLEAN
|
|
SCCMN50M_IsAtrValid(
|
|
PUCHAR pbAtrBuffer,
|
|
ULONG ulAtrLength
|
|
)
|
|
{
|
|
BOOLEAN fAtrValid = TRUE;
|
|
ULONG ulTD1Offset = 0;
|
|
BOOLEAN fTD1Transmitted = FALSE;
|
|
BOOLEAN fOnlyT0 = FALSE;
|
|
BYTE bXor;
|
|
ULONG ulHistoricalBytes;
|
|
ULONG ulTx2Characters = 0;
|
|
ULONG i;
|
|
|
|
//DBGBreakPoint();
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!IsAtrValid : Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
// basic checks
|
|
if (ulAtrLength < 2 ||
|
|
(pbAtrBuffer[0] != 0x3F &&
|
|
pbAtrBuffer[0] != 0x3B ) ||
|
|
(pbAtrBuffer[1] & 0xF0) == 0x00 )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (pbAtrBuffer[1] & 0x10)
|
|
ulTD1Offset++;
|
|
if (pbAtrBuffer[1] & 0x20)
|
|
ulTD1Offset++;
|
|
if (pbAtrBuffer[1] & 0x40)
|
|
ulTD1Offset++;
|
|
|
|
ulHistoricalBytes = pbAtrBuffer[1] & 0x0F;
|
|
|
|
if (pbAtrBuffer[1] & 0x80) // TD1 in ATR ?
|
|
{
|
|
fTD1Transmitted = TRUE;
|
|
|
|
if ((pbAtrBuffer[2 + ulTD1Offset] & 0x0F) == 0x00) // T0 indicated ?
|
|
fOnlyT0 = TRUE;
|
|
}
|
|
else
|
|
{
|
|
fOnlyT0 = TRUE;
|
|
}
|
|
|
|
|
|
if (fOnlyT0 == FALSE)
|
|
{
|
|
bXor = pbAtrBuffer[1];
|
|
for (i=2;i<ulAtrLength;i++)
|
|
bXor ^= pbAtrBuffer[i];
|
|
|
|
if (bXor != 0x00)
|
|
fAtrValid = FALSE;
|
|
}
|
|
else
|
|
{
|
|
// only T0 protocol is indicated
|
|
if (fTD1Transmitted == TRUE)
|
|
{
|
|
if (pbAtrBuffer[2 + ulTD1Offset] & 0x10)
|
|
ulTx2Characters++;
|
|
if (pbAtrBuffer[2 + ulTD1Offset] & 0x20)
|
|
ulTx2Characters++;
|
|
if (pbAtrBuffer[2 + ulTD1Offset] & 0x40)
|
|
ulTx2Characters++;
|
|
if (ulAtrLength != 2 + ulTD1Offset + 1 + ulTx2Characters + ulHistoricalBytes)
|
|
fAtrValid = FALSE;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
if (ulAtrLength != 2 + ulTD1Offset + ulHistoricalBytes)
|
|
fAtrValid = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!IsAtrValid : Exit %d\n",
|
|
DRIVER_NAME,fAtrValid)
|
|
);
|
|
return fAtrValid;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
This function checks if the received ATR is valid.
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID SCCMN50M_CheckAtrModified (
|
|
PUCHAR pbBuffer,
|
|
ULONG ulBufferSize
|
|
)
|
|
{
|
|
UCHAR bNumberHistoricalBytes;
|
|
UCHAR bXorChecksum;
|
|
ULONG i;
|
|
|
|
if (ulBufferSize < 0x09) // mininmum length of a modified ATR
|
|
return ; // ATR is ok
|
|
|
|
|
|
// 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!correcting SAMOS ATR (variant 2)\n",
|
|
DRIVER_NAME));
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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!correcting SAMOS ATR (variant 1)\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!correcting SAMOS ATR (variant 3)\n",
|
|
DRIVER_NAME));
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_PowerOff (IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus = STATUS_SUCCESS;
|
|
UCHAR pReadBuffer[2];
|
|
ULONG ulBytesRead;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!PowerOff: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
// SCR control bytes
|
|
SCCMN50M_ClearSCRControlFlags(pSmartcardExtension,CARD_POWER);
|
|
// card control bytes
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS);
|
|
// header
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,0,1);
|
|
// rx length = 1 because we don't want to receive a status
|
|
|
|
|
|
|
|
// write config + header
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitSCCMN50M_PowerOff;
|
|
}
|
|
|
|
|
|
|
|
// CardMan echoes a BRK which is recevied in the read functions
|
|
|
|
|
|
DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,pReadBuffer,sizeof(pReadBuffer));
|
|
|
|
#if 0
|
|
if (DebugStatus != STATUS_SUCCESS)
|
|
SmartcardDebug(
|
|
DEBUG_ERROR,
|
|
( "%s!PowerOffBRK received\n",
|
|
DRIVER_NAME)
|
|
);
|
|
#endif
|
|
|
|
|
|
ExitSCCMN50M_PowerOff:
|
|
if (pSmartcardExtension->ReaderExtension->ulOldCardState == POWERED)
|
|
pSmartcardExtension->ReaderExtension->ulOldCardState = INSERTED;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!PowerOff: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_Transmit(PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
|
|
|
|
|
|
switch (pSmartcardExtension->CardCapabilities.Protocol.Selected)
|
|
{
|
|
case SCARD_PROTOCOL_RAW:
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
case SCARD_PROTOCOL_T0:
|
|
status = SCCMN50M_TransmitT0(pSmartcardExtension);
|
|
break;
|
|
|
|
case SCARD_PROTOCOL_T1:
|
|
status = SCCMN50M_TransmitT1(pSmartcardExtension);
|
|
break;
|
|
|
|
default:
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_TransmitT0(PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
UCHAR bWriteBuffer[MIN_BUFFER_SIZE];
|
|
UCHAR bReadBuffer [MIN_BUFFER_SIZE];
|
|
ULONG ulWriteBufferOffset;
|
|
ULONG ulReadBufferOffset;
|
|
ULONG ulBytesToWrite;
|
|
ULONG ulBytesToRead;
|
|
ULONG ulBytesToWriteThisStep;
|
|
ULONG ulBytesToReadThisStep;
|
|
ULONG ulBytesStillToWrite;
|
|
ULONG ulBytesRead;
|
|
ULONG ulBytesStillToRead;
|
|
BOOLEAN fDataDirectionFromCard;
|
|
BYTE bProcedureByte;
|
|
BYTE bINS;
|
|
BOOLEAN fT0TransferToCard = FALSE;
|
|
BOOLEAN fT0TransferFromCard = FALSE;
|
|
BOOLEAN fSW1SW2Sent = FALSE;
|
|
ULONG ulReadTotalTimeoutMultiplier;
|
|
|
|
ULONG ulStatBytesRead;
|
|
BYTE abStatReadBuffer[2];
|
|
|
|
//SmartcardDebug(DEBUG_TRACE,("TransmitT0 : Enter\n"));
|
|
|
|
//
|
|
// Let the lib build a T=0 packet
|
|
//
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = 0; // no bytes additionally needed
|
|
status = SmartcardT0Request(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// This lib detected an error in the data to send.
|
|
//
|
|
// ------------------------------------------
|
|
// ITSEC E2 requirements: clear write buffers
|
|
// ------------------------------------------
|
|
MemSet(bWriteBuffer,
|
|
sizeof(bWriteBuffer),
|
|
'\0',
|
|
sizeof(bWriteBuffer));
|
|
MemSet(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
pSmartcardExtension->SmartcardRequest.BufferSize,
|
|
'\0',
|
|
pSmartcardExtension->SmartcardRequest.BufferSize);
|
|
return status;
|
|
}
|
|
|
|
|
|
// increase timeout for T0 Transmission
|
|
ulReadTotalTimeoutMultiplier = pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier =
|
|
pSmartcardExtension->CardCapabilities.T0.WT/1000 + 1500;
|
|
|
|
|
|
|
|
// ##################################
|
|
// TRANSPARENT MODE
|
|
// ##################################
|
|
|
|
ulBytesStillToWrite = ulBytesToWrite = T0_HEADER_LEN + pSmartcardExtension->T0.Lc;
|
|
ulBytesStillToRead = ulBytesToRead = pSmartcardExtension->T0.Le;
|
|
if (pSmartcardExtension->T0.Lc)
|
|
fT0TransferToCard = TRUE;
|
|
if (pSmartcardExtension->T0.Le)
|
|
fT0TransferFromCard = TRUE;
|
|
|
|
|
|
|
|
|
|
// copy data to the write buffer
|
|
/*
|
|
SmartcardDebug(DEBUG_TRACE,("CLA = %x INS = %x P1 = %x P2 = %X L = %x\n",
|
|
pSmartcardExtension->SmartcardRequest.Buffer[0],
|
|
pSmartcardExtension->SmartcardRequest.Buffer[1],
|
|
pSmartcardExtension->SmartcardRequest.Buffer[2],
|
|
pSmartcardExtension->SmartcardRequest.Buffer[3],
|
|
pSmartcardExtension->SmartcardRequest.Buffer[4]));
|
|
*/
|
|
|
|
MemCpy(bWriteBuffer,
|
|
sizeof(bWriteBuffer),
|
|
pSmartcardExtension->SmartcardRequest.Buffer,
|
|
ulBytesToWrite);
|
|
|
|
bINS = bWriteBuffer[1];
|
|
if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE)
|
|
{
|
|
SCCMN50M_InverseBuffer(bWriteBuffer,ulBytesToWrite);
|
|
}
|
|
|
|
status = SCCMN50M_EnterTransparentMode(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
|
|
// STEP 1 : write config + header to enter transparent mode
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
0, // Tx control
|
|
0, // Tx length
|
|
0, // Rx control
|
|
0); // Rx length
|
|
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
0,
|
|
NULL);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->fTransparentMode = TRUE;
|
|
|
|
// if the inserted card uses inverse convention , we must now switch the COM port
|
|
// to odd parity
|
|
if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = ODD_PARITY;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = SERIAL_DATABITS_8;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl,
|
|
sizeof(SERIAL_LINE_CONTROL));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
}
|
|
ulWriteBufferOffset = 0;
|
|
ulReadBufferOffset = 0;
|
|
|
|
|
|
// STEP 2 : write CLA INS P1 P2 Lc
|
|
|
|
ulBytesToWriteThisStep = 5;
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
ulBytesToWriteThisStep,
|
|
bWriteBuffer+ulWriteBufferOffset);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
ulWriteBufferOffset += ulBytesToWriteThisStep;
|
|
ulBytesStillToWrite -= ulBytesToWriteThisStep;
|
|
|
|
|
|
|
|
|
|
|
|
// STEP 2 : read procedure byte
|
|
do
|
|
{
|
|
do
|
|
{
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,1,&ulBytesRead,&bProcedureByte,sizeof(bProcedureByte));
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
|
|
if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE)
|
|
{
|
|
SCCMN50M_InverseBuffer(&bProcedureByte,ulBytesRead);
|
|
}
|
|
|
|
//SmartcardDebug(DEBUG_TRACE,("Procedure byte = %x\n",bProcedureByte));
|
|
//SmartcardDebug(DEBUG_TRACE,("waiting time = %x\n",pSmartcardExtension->CardCapabilities.T0.WT));
|
|
if (bProcedureByte == 0x60)
|
|
{
|
|
// ISO 7816-3 :
|
|
// This byte is sent by the card to reset the work waiting time and to anticipate
|
|
// a subsequent procedure byte
|
|
// => we do nothing here
|
|
}
|
|
} while (bProcedureByte == 0x60);
|
|
|
|
|
|
// check for ACK
|
|
if ((bProcedureByte & 0xFE) == (bINS & 0xFE) )
|
|
{
|
|
if (fT0TransferToCard)
|
|
{
|
|
ulBytesToWriteThisStep = ulBytesStillToWrite;
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
ulBytesToWriteThisStep,
|
|
bWriteBuffer+ulWriteBufferOffset);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
ulWriteBufferOffset += ulBytesToWriteThisStep;
|
|
ulBytesStillToWrite -= ulBytesToWriteThisStep;
|
|
|
|
}
|
|
if (fT0TransferFromCard)
|
|
{
|
|
ulBytesToReadThisStep = ulBytesStillToRead;
|
|
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,ulBytesToReadThisStep,&ulBytesRead,bReadBuffer + ulReadBufferOffset,sizeof(bReadBuffer)-ulReadBufferOffset);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE)
|
|
{
|
|
SCCMN50M_InverseBuffer(bReadBuffer+ulReadBufferOffset,ulBytesRead);
|
|
}
|
|
|
|
ulReadBufferOffset += ulBytesRead;
|
|
ulBytesStillToRead -= ulBytesRead;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
// check for NAK
|
|
else if ( (~bProcedureByte & 0xFE) == (bINS & 0xFE))
|
|
{
|
|
if (fT0TransferToCard)
|
|
{
|
|
ulBytesToWriteThisStep = 1;
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
ulBytesToWriteThisStep,
|
|
bWriteBuffer+ulWriteBufferOffset);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
ulWriteBufferOffset += ulBytesToWriteThisStep;
|
|
ulBytesStillToWrite -= ulBytesToWriteThisStep;
|
|
|
|
}
|
|
if (fT0TransferFromCard)
|
|
{
|
|
ulBytesToReadThisStep = 1;
|
|
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,ulBytesToReadThisStep,&ulBytesRead,bReadBuffer + ulReadBufferOffset,sizeof(bReadBuffer)-ulReadBufferOffset);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE)
|
|
{
|
|
SCCMN50M_InverseBuffer(bReadBuffer+ulReadBufferOffset,ulBytesRead);
|
|
}
|
|
|
|
ulReadBufferOffset += ulBytesRead;
|
|
ulBytesStillToRead -= ulBytesRead;
|
|
}
|
|
}
|
|
// check for SW1
|
|
else if ( (bProcedureByte > 0x60 && bProcedureByte <= 0x6F) ||
|
|
(bProcedureByte >= 0x90 && bProcedureByte <= 0x9F) )
|
|
{
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE;
|
|
bReadBuffer[ulReadBufferOffset] = bProcedureByte;
|
|
ulReadBufferOffset++;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,1,&ulBytesRead,bReadBuffer+ulReadBufferOffset,sizeof(bReadBuffer)-ulReadBufferOffset);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE)
|
|
{
|
|
SCCMN50M_InverseBuffer(bReadBuffer+ulReadBufferOffset,ulBytesRead);
|
|
}
|
|
ulReadBufferOffset += ulBytesRead;
|
|
fSW1SW2Sent = TRUE;
|
|
}
|
|
else
|
|
{
|
|
status = STATUS_UNSUCCESSFUL;
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
|
|
}while (!fSW1SW2Sent);
|
|
|
|
|
|
// copy received bytes
|
|
MemCpy(pSmartcardExtension->SmartcardReply.Buffer,
|
|
pSmartcardExtension->SmartcardReply.BufferSize,
|
|
bReadBuffer,
|
|
ulReadBufferOffset);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = ulReadBufferOffset;
|
|
|
|
|
|
// let the lib copy the received bytes to the user buffer
|
|
status = SmartcardT0Reply(pSmartcardExtension);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ExitTransparentTransmitT0:
|
|
// ------------------------------------------
|
|
// ITSEC E2 requirements: clear write buffers
|
|
// ------------------------------------------
|
|
MemSet(bWriteBuffer,
|
|
sizeof(bWriteBuffer),
|
|
'\0',
|
|
sizeof(bWriteBuffer));
|
|
MemSet(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
pSmartcardExtension->SmartcardRequest.BufferSize,
|
|
'\0',
|
|
pSmartcardExtension->SmartcardRequest.BufferSize);
|
|
|
|
DebugStatus = SCCMN50M_ExitTransparentMode(pSmartcardExtension);
|
|
pSmartcardExtension->ReaderExtension->fTransparentMode = FALSE;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = ulReadTotalTimeoutMultiplier;
|
|
|
|
// to be sure that the new settings take effect
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 250;
|
|
DebugStatus = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT;
|
|
if (NT_SUCCESS(DebugStatus))
|
|
{
|
|
DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulStatBytesRead,abStatReadBuffer,sizeof(abStatReadBuffer));
|
|
}
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_TransmitT1(PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status;
|
|
ULONG ulBytesToWrite;
|
|
UCHAR bWriteBuffer [256 + T1_HEADER_LEN + MAX_EDC_LEN];
|
|
UCHAR bReadBuffer [256 + T1_HEADER_LEN + MAX_EDC_LEN];
|
|
ULONG ulBytesRead;
|
|
ULONG ulBytesStillToRead;
|
|
|
|
/*
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
("%s!CWT = %ld(ms)\n",
|
|
DRIVER_NAME,
|
|
pSmartcardExtension->CardCapabilities.T1.CWT/1000)
|
|
);
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
("%s!BWT = %ld(ms)\n",
|
|
DRIVER_NAME,
|
|
pSmartcardExtension->CardCapabilities.T1.BWT/1000);
|
|
);
|
|
*/
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant =
|
|
pSmartcardExtension->CardCapabilities.T1.BWT/1000;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier =
|
|
pSmartcardExtension->CardCapabilities.T1.CWT/1000;
|
|
/*
|
|
SmartcardDebug(DEBUG_TRACE,("%s!ReadTotalTimeoutConstant = %ld(ms)\n",
|
|
DRIVER_NAME,
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant));
|
|
|
|
SmartcardDebug(DEBUG_TRACE,("%s!ReadTotalTimeoutMultiplier = %ld(ms)\n",
|
|
DRIVER_NAME,
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier));
|
|
*/
|
|
|
|
// set T1 protocol flag for CardMan
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_T1);
|
|
|
|
if (pSmartcardExtension->CardCapabilities.T1.EDC == T1_CRC_CHECK)
|
|
{
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_CRC);
|
|
}
|
|
|
|
|
|
do
|
|
{
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = 0; // no bytes additionally needed
|
|
|
|
|
|
status = SmartcardT1Request(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitTransmitT1;
|
|
}
|
|
|
|
ulBytesToWrite = pSmartcardExtension->SmartcardRequest.BufferLength;
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
0, // Tx conrol
|
|
(UCHAR)ulBytesToWrite, // Tx length
|
|
0, // Rx control
|
|
T1_HEADER_LEN); // Rx length
|
|
|
|
|
|
|
|
if (sizeof(bWriteBuffer) < ulBytesToWrite)
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitTransmitT1;
|
|
}
|
|
|
|
// copy data to the write buffer
|
|
MemCpy(bWriteBuffer,
|
|
sizeof(bWriteBuffer),
|
|
pSmartcardExtension->SmartcardRequest.Buffer,
|
|
ulBytesToWrite);
|
|
|
|
|
|
// write data to card
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
ulBytesToWrite,
|
|
bWriteBuffer);
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
|
|
// read CardMan Header
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer));
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
ulBytesStillToRead = bReadBuffer[1];
|
|
|
|
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,
|
|
ulBytesStillToRead,
|
|
&ulBytesRead,
|
|
bReadBuffer,
|
|
sizeof(bReadBuffer));
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
if (bReadBuffer[1] == T1_WTX_REQUEST)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant =
|
|
(ULONG)(1000 +((pSmartcardExtension->CardCapabilities.T1.BWT*bReadBuffer[3])/1000));
|
|
SmartcardDebug(DEBUG_PROTOCOL,("%s!ReadTotalTimeoutConstant = %ld(ms)\n",
|
|
DRIVER_NAME,
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant));
|
|
}
|
|
else
|
|
{
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant =
|
|
pSmartcardExtension->CardCapabilities.T1.BWT/1000;
|
|
SmartcardDebug(DEBUG_PROTOCOL,("%s!ReadTotalTimeoutConstant = %ld(ms)\n",
|
|
DRIVER_NAME,
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant));
|
|
}
|
|
// copy received bytes
|
|
MemCpy(pSmartcardExtension->SmartcardReply.Buffer,
|
|
pSmartcardExtension->SmartcardReply.BufferSize,
|
|
bReadBuffer,
|
|
ulBytesRead);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = ulBytesRead;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
// reset serial timeout
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!reseting timeout constant\n",
|
|
DRIVER_NAME)
|
|
);
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant =
|
|
pSmartcardExtension->CardCapabilities.T1.BWT/1000;
|
|
SmartcardDebug(DEBUG_PROTOCOL,("%s!ReadTotalTimeoutConstant = %ld(ms)\n",
|
|
DRIVER_NAME,
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant));
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0L;
|
|
}
|
|
|
|
// bug fix for smclib
|
|
if (pSmartcardExtension->T1.State == T1_IFS_RESPONSE &&
|
|
pSmartcardExtension->T1.OriginalState == T1_I_BLOCK)
|
|
{
|
|
pSmartcardExtension->T1.State = T1_I_BLOCK;
|
|
}
|
|
|
|
status = SmartcardT1Reply(pSmartcardExtension);
|
|
}
|
|
while (status == STATUS_MORE_PROCESSING_REQUIRED);
|
|
|
|
|
|
|
|
ExitTransmitT1:
|
|
// ------------------------------------------
|
|
// ITSEC E2 requirements: clear write buffers
|
|
// ------------------------------------------
|
|
MemSet(bWriteBuffer,
|
|
sizeof(bWriteBuffer),
|
|
'\0',
|
|
sizeof(bWriteBuffer));
|
|
MemSet(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
pSmartcardExtension->SmartcardRequest.BufferSize,
|
|
'\0',
|
|
pSmartcardExtension->SmartcardRequest.BufferSize);
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier =
|
|
DEFAULT_READ_TOTAL_TIMEOUT_MULTIPLIER;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant =
|
|
DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT;
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_InitializeSmartcardExtension(
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN ULONG ulDeviceInstance
|
|
)
|
|
{
|
|
// ==================================
|
|
// Fill the Vendor_Attr structure
|
|
// ==================================
|
|
MemCpy(pSmartcardExtension->VendorAttr.VendorName.Buffer,
|
|
sizeof(pSmartcardExtension->VendorAttr.VendorName.Buffer),
|
|
ATTR_VENDOR_NAME,
|
|
sizeof(ATTR_VENDOR_NAME)
|
|
);
|
|
|
|
//
|
|
// Length of vendor name
|
|
//
|
|
pSmartcardExtension->VendorAttr.VendorName.Length = sizeof(ATTR_VENDOR_NAME);
|
|
|
|
|
|
//
|
|
// Version number
|
|
//
|
|
pSmartcardExtension->VendorAttr.IfdVersion.BuildNumber = IFD_NT_BUILDNUMBER_CARDMAN;
|
|
pSmartcardExtension->VendorAttr.IfdVersion.VersionMinor = IFD_NT_VERSIONMINOR_CARDMAN;
|
|
pSmartcardExtension->VendorAttr.IfdVersion.VersionMajor = IFD_NT_VERSIONMAJOR_CARDMAN;
|
|
|
|
|
|
MemCpy(pSmartcardExtension->VendorAttr.IfdType.Buffer,
|
|
sizeof(pSmartcardExtension->VendorAttr.IfdType.Buffer),
|
|
ATTR_IFD_TYPE_CM,
|
|
sizeof(ATTR_IFD_TYPE_CM));
|
|
|
|
//
|
|
// Length of reader name
|
|
//
|
|
pSmartcardExtension->VendorAttr.IfdType.Length = sizeof(ATTR_IFD_TYPE_CM);
|
|
|
|
|
|
|
|
//
|
|
// Unit number which is zero based
|
|
//
|
|
pSmartcardExtension->VendorAttr.UnitNo = ulDeviceInstance;
|
|
|
|
|
|
|
|
// ================================================
|
|
// Fill the SCARD_READER_CAPABILITIES structure
|
|
// ===============================================
|
|
//
|
|
// Supported protoclols by the reader
|
|
//
|
|
|
|
pSmartcardExtension->ReaderCapabilities.SupportedProtocols = SCARD_PROTOCOL_T1 | SCARD_PROTOCOL_T0;
|
|
|
|
|
|
|
|
|
|
//
|
|
// Reader type serial, keyboard, ....
|
|
//
|
|
pSmartcardExtension->ReaderCapabilities.ReaderType = SCARD_READER_TYPE_SERIAL;
|
|
|
|
//
|
|
// Mechanical characteristics like swallows etc.
|
|
//
|
|
pSmartcardExtension->ReaderCapabilities.MechProperties = 0;
|
|
|
|
|
|
//
|
|
// Current state of the reader
|
|
//
|
|
pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
// Data Rate
|
|
//
|
|
pSmartcardExtension->ReaderCapabilities.DataRate.Default =
|
|
pSmartcardExtension->ReaderCapabilities.DataRate.Max =
|
|
dataRatesSupported[0];
|
|
|
|
|
|
// reader could support higher data rates
|
|
pSmartcardExtension->ReaderCapabilities.DataRatesSupported.List =
|
|
dataRatesSupported;
|
|
pSmartcardExtension->ReaderCapabilities.DataRatesSupported.Entries =
|
|
sizeof(dataRatesSupported) / sizeof(dataRatesSupported[0]);
|
|
|
|
|
|
|
|
|
|
//
|
|
// CLKFrequency
|
|
//
|
|
pSmartcardExtension->ReaderCapabilities.CLKFrequency.Default =
|
|
pSmartcardExtension->ReaderCapabilities.CLKFrequency.Max =
|
|
CLKFrequenciesSupported[0];
|
|
|
|
|
|
pSmartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.List =
|
|
CLKFrequenciesSupported;
|
|
pSmartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.Entries =
|
|
sizeof(CLKFrequenciesSupported) / sizeof(CLKFrequenciesSupported[0]);
|
|
|
|
|
|
//pSmartcardExtension->ReaderCapabilities.CLKFrequency.Default = 3571; //3.571 MHz
|
|
//pSmartcardExtension->ReaderCapabilities.CLKFrequency.Max = 3571; //3.571 MHz
|
|
|
|
//
|
|
// MaxIFSD
|
|
//
|
|
pSmartcardExtension->ReaderCapabilities.MaxIFSD = ATTR_MAX_IFSD_CARDMAN_II;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
StrSet(PUCHAR Buffer,ULONG BufferSize,UCHAR Pattern)
|
|
{
|
|
ULONG i;
|
|
|
|
for (i=0;i < BufferSize;i++)
|
|
Buffer[i] = Pattern;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
StrCpy(PUCHAR pszDestination,ULONG DestinationLen,PUCHAR pszSrc)
|
|
{
|
|
ULONG Len;
|
|
ULONG SrcLen;
|
|
ULONG i;
|
|
|
|
StrSet(pszDestination, DestinationLen,'\0');
|
|
SrcLen = StrLen(pszSrc);
|
|
|
|
if (DestinationLen - 1 < SrcLen)
|
|
{
|
|
Len = DestinationLen - 1;
|
|
}
|
|
else
|
|
{
|
|
Len = SrcLen;
|
|
}
|
|
|
|
|
|
for (i = 0; i < Len; i++)
|
|
{
|
|
pszDestination[i] = pszSrc[i];
|
|
if (pszSrc[i] == '\0')
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
ULONG
|
|
StrLen (PUCHAR pszString)
|
|
{
|
|
ULONG Len = 0;
|
|
|
|
while ( *(pszString+Len) != '\0')
|
|
Len++;
|
|
|
|
return(Len);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
StrCat(PUCHAR pszDestination,ULONG DestinationLen,PUCHAR pszSrc)
|
|
{
|
|
ULONG Len;
|
|
ULONG i;
|
|
ULONG SrcLen;
|
|
ULONG DestLen;
|
|
|
|
SrcLen = StrLen(pszSrc);
|
|
DestLen = StrLen(pszDestination);
|
|
|
|
|
|
if (StrLen(pszDestination)>=DestinationLen)
|
|
return;
|
|
|
|
|
|
if ((DestinationLen-DestLen-1) < SrcLen)
|
|
{
|
|
Len = DestinationLen-DestLen-1;
|
|
}
|
|
else
|
|
{
|
|
Len = SrcLen;
|
|
}
|
|
|
|
|
|
for (i=0; i < Len; i++)
|
|
{
|
|
pszDestination[DestLen+i] = pszSrc[i];
|
|
if (pszSrc[i] == '\0')
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
MemSet(PUCHAR pBuffer,
|
|
ULONG ulBufferSize,
|
|
UCHAR ucPattern,
|
|
ULONG ulCount)
|
|
{
|
|
ULONG i;
|
|
|
|
for (i=0; i<ulCount;i++)
|
|
{
|
|
if (i >= ulBufferSize)
|
|
break;
|
|
pBuffer[i] = ucPattern;
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
MemCpy(PUCHAR pDestination,
|
|
ULONG ulDestinationLen,
|
|
PUCHAR pSource,
|
|
ULONG ulCount)
|
|
{
|
|
ULONG i = 0;
|
|
while ( ulCount-- && ulDestinationLen-- )
|
|
{
|
|
pDestination[i] = pSource[i];
|
|
i++;
|
|
}
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_UpdateCurrentStateThread(
|
|
IN PVOID Context
|
|
)
|
|
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = Context;
|
|
PSMARTCARD_EXTENSION smartcardExtension;
|
|
NTSTATUS status;
|
|
LONG lRetry;
|
|
KIRQL oldIrql;
|
|
LONG ulFailures;
|
|
BOOLEAN fPriorityIncreased;
|
|
LONG lOldPriority;
|
|
|
|
SmartcardDebug(DEBUG_DRIVER,
|
|
("%s!UpdateCurrentStateThread started\n",DRIVER_NAME));
|
|
|
|
ulFailures = 0;
|
|
smartcardExtension = &deviceExtension->SmartcardExtension;
|
|
|
|
//
|
|
// Increase priority for first loop,
|
|
// because state of card must be known for resource manager
|
|
//
|
|
fPriorityIncreased=TRUE;
|
|
lOldPriority=KeSetPriorityThread(KeGetCurrentThread(),HIGH_PRIORITY);
|
|
|
|
do
|
|
{
|
|
KeWaitForSingleObject(&smartcardExtension->ReaderExtension->CardManIOMutex,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
|
|
if ( smartcardExtension->ReaderExtension->TimeToTerminateThread )
|
|
{
|
|
KeReleaseMutex(&smartcardExtension->ReaderExtension->CardManIOMutex,FALSE);
|
|
smartcardExtension->ReaderExtension->TimeToTerminateThread = FALSE;
|
|
PsTerminateSystemThread( STATUS_SUCCESS );
|
|
}
|
|
|
|
lRetry = 1;
|
|
|
|
|
|
|
|
do
|
|
{
|
|
//SmartcardDebug(DEBUG_TRACE,( "%s!*.",DRIVER_NAME));
|
|
|
|
status=SCCMN50M_UpdateCurrentState(smartcardExtension);
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
lRetry--;
|
|
}
|
|
}
|
|
while (lRetry >= 0);
|
|
|
|
if (lRetry < 0)
|
|
{
|
|
ulFailures++;
|
|
if (ulFailures == 1)
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
( "%s!CardMan removed\n",
|
|
DRIVER_NAME)
|
|
);
|
|
// issue a card removal event if reader has been removed
|
|
if (smartcardExtension->ReaderExtension->ulOldCardState == INSERTED ||
|
|
smartcardExtension->ReaderExtension->ulOldCardState == POWERED )
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
( "%s!issuing card removal event\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
SCCMN50M_CompleteCardTracking(smartcardExtension);
|
|
smartcardExtension->ReaderExtension->SyncParameters.fCardPowerRequested = TRUE;
|
|
|
|
smartcardExtension->ReaderExtension->ulNewCardState = REMOVED;
|
|
smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState;
|
|
smartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT;
|
|
smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
|
|
smartcardExtension->CardCapabilities.ATR.Length = 0;
|
|
|
|
SCCMN50M_ClearCardControlFlags(smartcardExtension,ALL_FLAGS);
|
|
smartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0;
|
|
smartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0;
|
|
}
|
|
}
|
|
if (ulFailures == 3)
|
|
{
|
|
// remove the device and terminate this thread
|
|
if (KeReadStateEvent(&deviceExtension->SerialCloseDone) == 0l)
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
( "%s!closing serial driver\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
SCCMN50M_CloseSerialDriver(smartcardExtension->OsData->DeviceObject);
|
|
|
|
|
|
KeReleaseMutex(&smartcardExtension->ReaderExtension->CardManIOMutex,FALSE);
|
|
smartcardExtension->ReaderExtension->TimeToTerminateThread = FALSE;
|
|
smartcardExtension->ReaderExtension->ThreadObjectPointer = NULL;
|
|
PsTerminateSystemThread( STATUS_SUCCESS );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ulFailures = 0;
|
|
}
|
|
|
|
KeReleaseMutex(&smartcardExtension->ReaderExtension->CardManIOMutex,FALSE);
|
|
|
|
if (fPriorityIncreased)
|
|
{
|
|
fPriorityIncreased=FALSE;
|
|
KeSetPriorityThread(KeGetCurrentThread(),lOldPriority);
|
|
|
|
//
|
|
// Lower ourselves down just at tad so that we compete a
|
|
// little less.
|
|
//
|
|
KeSetBasePriorityThread(KeGetCurrentThread(),-1);
|
|
}
|
|
|
|
//SmartcardDebug(DEBUG_TRACE,( "...#\n"));
|
|
|
|
Wait (smartcardExtension,500 * ms_);
|
|
}
|
|
while (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
NTSTATUS SCCMN50M_UpdateCurrentState(
|
|
IN PSMARTCARD_EXTENSION smartcardExtension
|
|
)
|
|
{
|
|
NTSTATUS NTStatus;
|
|
UCHAR pbReadBuffer[2];
|
|
ULONG ulBytesRead;
|
|
BOOLEAN fCardStateChanged;
|
|
|
|
fCardStateChanged = FALSE;
|
|
|
|
|
|
SCCMN50M_ClearCardManHeader(smartcardExtension);
|
|
|
|
smartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 250;
|
|
NTStatus = SCCMN50M_WriteCardMan(smartcardExtension,0,NULL);
|
|
smartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT;
|
|
if (NT_SUCCESS(NTStatus))
|
|
{
|
|
NTStatus = SCCMN50M_ReadCardMan(smartcardExtension,2,&ulBytesRead,pbReadBuffer,sizeof(pbReadBuffer));
|
|
if (ulBytesRead == 0x02 && // two bytes must have benn received
|
|
(pbReadBuffer[0] & 0x0F) && // at least one version bit must be set
|
|
((pbReadBuffer[0] & 0x09) == 0x00)) // Bit 0 and Bit 3 must be 0
|
|
{
|
|
if ((pbReadBuffer[0] & 0x04) == 0x04 &&
|
|
(pbReadBuffer[0] & 0x02) == 0x02)
|
|
smartcardExtension->ReaderExtension->ulNewCardState = INSERTED;
|
|
|
|
if ((pbReadBuffer[0] & 0x04) == 0x00 &&
|
|
(pbReadBuffer[0] & 0x02) == 0x02)
|
|
smartcardExtension->ReaderExtension->ulNewCardState = REMOVED;
|
|
|
|
if ((pbReadBuffer[0] & 0x04) == 0x04 &&
|
|
(pbReadBuffer[0] & 0x02) == 0x00)
|
|
smartcardExtension->ReaderExtension->ulNewCardState = POWERED;
|
|
|
|
|
|
//SmartcardDebug(DEBUG_TRACE,("old %x ",smartcardExtension->ReaderExtension->ulOldCardState ));
|
|
//SmartcardDebug(DEBUG_TRACE,("new %x\n",smartcardExtension->ReaderExtension->ulNewCardState ));
|
|
|
|
|
|
|
|
if (smartcardExtension->ReaderExtension->ulNewCardState == INSERTED &&
|
|
smartcardExtension->ReaderExtension->ulOldCardState == POWERED )
|
|
{
|
|
// card has been removed and reinserted within 500ms
|
|
fCardStateChanged = TRUE;
|
|
SmartcardDebug(DEBUG_DRIVER,( "%s!Smartcard removed and reinserted\n",DRIVER_NAME));
|
|
smartcardExtension->ReaderExtension->ulOldCardState = REMOVED;
|
|
smartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT;
|
|
smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
|
|
|
|
// clear any cardspecific data
|
|
smartcardExtension->CardCapabilities.ATR.Length = 0;
|
|
SCCMN50M_ClearCardControlFlags(smartcardExtension,ALL_FLAGS);
|
|
smartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0;
|
|
smartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0;
|
|
}
|
|
|
|
|
|
if (smartcardExtension->ReaderExtension->ulNewCardState == REMOVED &&
|
|
(smartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN ||
|
|
smartcardExtension->ReaderExtension->ulOldCardState == INSERTED ||
|
|
smartcardExtension->ReaderExtension->ulOldCardState == POWERED ) )
|
|
{
|
|
// card has been removed
|
|
fCardStateChanged = TRUE;
|
|
SmartcardDebug(DEBUG_DRIVER,( "%s!Smartcard removed\n",DRIVER_NAME));
|
|
smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState;
|
|
smartcardExtension->ReaderCapabilities.CurrentState = SCARD_ABSENT;
|
|
smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
|
|
|
|
// clear any cardspecific data
|
|
smartcardExtension->CardCapabilities.ATR.Length = 0;
|
|
SCCMN50M_ClearCardControlFlags(smartcardExtension,ALL_FLAGS);
|
|
smartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0;
|
|
smartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0;
|
|
}
|
|
|
|
|
|
|
|
if (smartcardExtension->ReaderExtension->ulNewCardState == INSERTED &&
|
|
(smartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN ||
|
|
smartcardExtension->ReaderExtension->ulOldCardState == REMOVED ) )
|
|
{
|
|
// card has been inserted
|
|
fCardStateChanged = TRUE;
|
|
SmartcardDebug(DEBUG_DRIVER,( "%s!Smartcard inserted\n",DRIVER_NAME));
|
|
smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState;
|
|
smartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED;
|
|
smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
|
|
}
|
|
|
|
|
|
// state after reset of the PC (only for CardMan Power+ possible)
|
|
if (smartcardExtension->ReaderExtension->ulNewCardState == POWERED &&
|
|
smartcardExtension->ReaderExtension->ulOldCardState == UNKNOWN )
|
|
{
|
|
// card has been inserted
|
|
fCardStateChanged = TRUE;
|
|
SmartcardDebug(DEBUG_DRIVER,( "%s!Smartcard inserted (and powered)\n",DRIVER_NAME));
|
|
smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState;
|
|
smartcardExtension->ReaderCapabilities.CurrentState = SCARD_SWALLOWED;
|
|
smartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
|
|
}
|
|
|
|
if (smartcardExtension->ReaderExtension->ulNewCardState == POWERED &&
|
|
smartcardExtension->ReaderExtension->ulOldCardState == INSERTED )
|
|
{
|
|
smartcardExtension->ReaderExtension->ulOldCardState = smartcardExtension->ReaderExtension->ulNewCardState;
|
|
}
|
|
|
|
|
|
// complete IOCTL_SMARTCARD_IS_ABSENT or IOCTL_SMARTCARD_IS_PRESENT
|
|
if (fCardStateChanged == TRUE &&
|
|
smartcardExtension->OsData->NotificationIrp )
|
|
{
|
|
SCCMN50M_CompleteCardTracking(smartcardExtension);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
return NTStatus;
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS Wait (PSMARTCARD_EXTENSION pSmartcardExtension,ULONG ulMilliseconds)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
LARGE_INTEGER WaitTime;
|
|
|
|
|
|
WaitTime = RtlConvertLongToLargeInteger(ulMilliseconds * WAIT_MS);
|
|
KeDelayExecutionThread(KernelMode,FALSE,&WaitTime);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_SetSCRControlFlags(
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN UCHAR Flags
|
|
)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.SCRControl |= Flags;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_ClearSCRControlFlags(
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN UCHAR Flags
|
|
)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.SCRControl &= ~Flags;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_SetCardControlFlags(
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN UCHAR Flags
|
|
)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.CardControl |= Flags;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_ClearCardControlFlags(
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN UCHAR Flags
|
|
)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.CardControl &= ~Flags;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_ClearCardManHeader(
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension
|
|
)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.TxControl = 0x00;
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.TxLength = 0x00;
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.RxControl = 0x00;
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.RxLength = 0x00;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_SetCardManHeader(
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN UCHAR TxControl,
|
|
IN UCHAR TxLength,
|
|
IN UCHAR RxControl,
|
|
IN UCHAR RxLength
|
|
)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.TxControl = TxControl;
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.TxLength = TxLength;
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.RxControl = RxControl;
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.RxLength = RxLength;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_WriteCardMan (
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN ULONG ulBytesToWrite,
|
|
IN PUCHAR pbWriteBuffer
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
PSERIAL_STATUS pSerialStatus;
|
|
|
|
|
|
// ===============================================
|
|
// Set up timeouts for following read operation
|
|
// ===============================================
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_TIMEOUTS;
|
|
|
|
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts,
|
|
sizeof(SERIAL_TIMEOUTS));
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_TIMEOUTS);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
|
|
/*
|
|
SmartcardDebug(DEBUG_TRACE,("ReadTotalTimeoutMultiplier = %ld\n",
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier));
|
|
SmartcardDebug(DEBUG_TRACE,("ReadTotalTimeoutConstant = %ld\n",
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant));
|
|
*/
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ===============================================
|
|
// write to the CardMan
|
|
// ===============================================
|
|
DebugStatus = SCCMN50M_SetWrite(pSmartcardExtension,ulBytesToWrite,pbWriteBuffer);
|
|
|
|
|
|
// add pseudoboost (0x00) to write buffer for CardManII
|
|
if (pSmartcardExtension->ReaderExtension->fTransparentMode == FALSE )
|
|
{
|
|
pSmartcardExtension->SmartcardRequest.Buffer[pSmartcardExtension->SmartcardRequest.BufferLength] = 0x00;
|
|
pSmartcardExtension->SmartcardRequest.BufferLength++;
|
|
}
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
|
|
|
|
|
|
// overwrite write buffer with '@'
|
|
RtlFillMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
pSmartcardExtension->SmartcardRequest.BufferLength,
|
|
'@');
|
|
|
|
|
|
|
|
// ===============================================
|
|
// error checking
|
|
// ===============================================
|
|
DebugStatus = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
|
|
pSerialStatus = (PSERIAL_STATUS) pSmartcardExtension->SmartcardReply.Buffer;
|
|
if (pSerialStatus->Errors || NT_ERROR(status))
|
|
{
|
|
pSmartcardExtension->ReaderExtension->SerialErrors = pSerialStatus->Errors;
|
|
if (!pSmartcardExtension->ReaderExtension->fTransparentMode )
|
|
DebugStatus = SCCMN50M_ResyncCardManII(pSmartcardExtension);
|
|
goto ExitSCCMN50M_WriteCardMan;
|
|
}
|
|
|
|
|
|
|
|
|
|
ExitSCCMN50M_WriteCardMan:
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!WriteCardMan: Failed, exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS SCCMN50M_ResyncCardManI (IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
|
|
|
|
// SmartcardDebug(DEBUG_TRACE,("%s!ResyncCardManI: Enter\n",DRIVER_NAME))
|
|
|
|
// clear error flags
|
|
pSmartcardExtension->ReaderExtension->SerialErrors = 0;
|
|
|
|
|
|
// clear any pending errors
|
|
status = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManI;
|
|
}
|
|
|
|
|
|
// clear COM buffers
|
|
status = SCCMN50M_PurgeComm(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_PurgeComm failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManI;
|
|
}
|
|
|
|
|
|
|
|
|
|
// ####################################################################
|
|
// set break
|
|
if (!pSmartcardExtension->ReaderExtension->fTransparentMode)
|
|
{
|
|
status = SCCMN50M_SetBRK(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SetBreak failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManI;
|
|
}
|
|
}
|
|
|
|
|
|
// wait 1ms
|
|
Wait(pSmartcardExtension,1 * ms_);
|
|
|
|
// clear RTS
|
|
status = SCCMN50M_ClearRTS(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_ClearRTS failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManI;
|
|
}
|
|
|
|
// wait 2ms
|
|
Wait(pSmartcardExtension,2 * ms_);
|
|
|
|
|
|
// set RTS
|
|
status = SCCMN50M_SetRTS(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_SetRTS failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManI;
|
|
}
|
|
|
|
// wait 1ms
|
|
Wait(pSmartcardExtension,1 * ms_);
|
|
|
|
|
|
|
|
// clear break
|
|
|
|
if (!pSmartcardExtension->ReaderExtension->fTransparentMode)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->BreakSet = FALSE;
|
|
status = SCCMN50M_ClearBRK(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("ClearBreak failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManI;
|
|
}
|
|
}
|
|
|
|
// ####################################################################
|
|
|
|
// next write operation must send config data
|
|
pSmartcardExtension->ReaderExtension->NoConfig = FALSE;
|
|
|
|
// clear COM buffers
|
|
status = SCCMN50M_PurgeComm(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto ExitSCCMN50M_ResyncCardManI;
|
|
}
|
|
|
|
// clear any pending errors
|
|
status = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto ExitSCCMN50M_ResyncCardManI;
|
|
}
|
|
|
|
|
|
ExitSCCMN50M_ResyncCardManI:
|
|
//SmartcardDebug(DEBUG_TRACE,("%s!ResyncCardManI: Exit %lx\n",DRIVER_NAME,status))
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NTSTATUS SCCMN50M_ResyncCardManII (IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!ResyncCardManII: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
// clear error flags
|
|
pSmartcardExtension->ReaderExtension->SerialErrors = 0;
|
|
|
|
|
|
// clear any pending errors
|
|
status = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManII;
|
|
}
|
|
|
|
|
|
// clear COM buffers
|
|
status = SCCMN50M_PurgeComm(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_PurgeComm failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManII;
|
|
}
|
|
|
|
|
|
|
|
// 150 * 0xFE
|
|
RtlFillMemory(pSmartcardExtension->SmartcardRequest.Buffer,150,0xFE);
|
|
pSmartcardExtension->SmartcardRequest.Buffer[150] = 0x00;
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = 151;
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_WRITE;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
Wait(pSmartcardExtension,2 * ms_);
|
|
// try resync once more
|
|
|
|
// clear error flags
|
|
pSmartcardExtension->ReaderExtension->SerialErrors = 0;
|
|
|
|
// clear any pending errors
|
|
status = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManII;
|
|
}
|
|
|
|
// clear COM buffers
|
|
status = SCCMN50M_PurgeComm(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_PurgeComm failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManII;
|
|
}
|
|
|
|
|
|
// 150 * 0xFE
|
|
RtlFillMemory(pSmartcardExtension->SmartcardRequest.Buffer,150,0xFE);
|
|
pSmartcardExtension->SmartcardRequest.Buffer[150] = 0x00;
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = 151;
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_WRITE;
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_SerialIo failed ! status = %x\n",status))
|
|
goto ExitSCCMN50M_ResyncCardManII;
|
|
}
|
|
// normally the second resync command is always successful
|
|
|
|
}
|
|
|
|
|
|
// clear COM buffers
|
|
status = SCCMN50M_PurgeComm(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto ExitSCCMN50M_ResyncCardManII;
|
|
}
|
|
|
|
// clear any pending errors
|
|
status = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto ExitSCCMN50M_ResyncCardManII;
|
|
}
|
|
|
|
|
|
ExitSCCMN50M_ResyncCardManII:
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!ResyncCardManII: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SerialIo(IN PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status;
|
|
IO_STATUS_BLOCK ioStatus;
|
|
KEVENT event;
|
|
PIRP irp;
|
|
PIO_STACK_LOCATION irpNextStack;
|
|
PUCHAR pbRequestBuffer;
|
|
PUCHAR pbReplyBuffer;
|
|
ULONG ulRequestBufferLength;
|
|
ULONG ulReplyBufferLength ;
|
|
|
|
//
|
|
// Check if the buffers are large enough
|
|
//
|
|
ASSERT(pSmartcardExtension->SmartcardReply.BufferLength <=
|
|
pSmartcardExtension->SmartcardReply.BufferSize);
|
|
|
|
ASSERT(pSmartcardExtension->SmartcardRequest.BufferLength <=
|
|
pSmartcardExtension->SmartcardRequest.BufferSize);
|
|
|
|
if (pSmartcardExtension->SmartcardReply.BufferLength >
|
|
pSmartcardExtension->SmartcardReply.BufferSize ||
|
|
pSmartcardExtension->SmartcardRequest.BufferLength >
|
|
pSmartcardExtension->SmartcardRequest.BufferSize)
|
|
{
|
|
SmartcardLogError(pSmartcardExtension->OsData->DeviceObject,
|
|
SCCMN50M_BUFFER_TOO_SMALL,
|
|
NULL,
|
|
0);
|
|
return STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
|
|
|
|
|
|
// set pointer and length of request and reply buffer
|
|
ulRequestBufferLength = pSmartcardExtension->SmartcardRequest.BufferLength;
|
|
pbRequestBuffer = (ulRequestBufferLength ? pSmartcardExtension->SmartcardRequest.Buffer : NULL);
|
|
|
|
pbReplyBuffer = pSmartcardExtension->SmartcardReply.Buffer;
|
|
ulReplyBufferLength = pSmartcardExtension->SmartcardReply.BufferLength;
|
|
|
|
|
|
|
|
KeInitializeEvent(&event,
|
|
NotificationEvent,
|
|
FALSE);
|
|
|
|
|
|
//
|
|
// Build irp to be sent to serial driver
|
|
//
|
|
irp = IoBuildDeviceIoControlRequest(pSmartcardExtension->ReaderExtension->SerialIoControlCode,
|
|
pSmartcardExtension->ReaderExtension->AttachedDeviceObject,
|
|
pbRequestBuffer,
|
|
ulRequestBufferLength,
|
|
pbReplyBuffer,
|
|
ulReplyBufferLength,
|
|
FALSE,
|
|
&event,
|
|
&ioStatus);
|
|
|
|
|
|
ASSERT(irp != NULL);
|
|
if (irp == NULL)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
|
|
irpNextStack = IoGetNextIrpStackLocation(irp);
|
|
|
|
switch (pSmartcardExtension->ReaderExtension->SerialIoControlCode)
|
|
{
|
|
//
|
|
// The serial driver transfers data from/to irp->AssociatedIrp.SystemBuffer
|
|
//
|
|
case SMARTCARD_WRITE:
|
|
irpNextStack->MajorFunction = IRP_MJ_WRITE;
|
|
irpNextStack->Parameters.Write.Length = pSmartcardExtension->SmartcardRequest.BufferLength;
|
|
break;
|
|
|
|
|
|
case SMARTCARD_READ:
|
|
irpNextStack->MajorFunction = IRP_MJ_READ;
|
|
irpNextStack->Parameters.Read.Length = pSmartcardExtension->SmartcardReply.BufferLength;
|
|
break;
|
|
}
|
|
|
|
|
|
status = IoCallDriver(pSmartcardExtension->ReaderExtension->AttachedDeviceObject,irp);
|
|
|
|
|
|
if (status == STATUS_PENDING)
|
|
{
|
|
KeWaitForSingleObject(&event,
|
|
Suspended,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
status = ioStatus.Status;
|
|
}
|
|
|
|
switch (pSmartcardExtension->ReaderExtension->SerialIoControlCode)
|
|
{
|
|
case SMARTCARD_READ:
|
|
if (status == STATUS_TIMEOUT)
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,
|
|
("%s!Timeout while reading from CardMan\n",
|
|
DRIVER_NAME));
|
|
//
|
|
// STATUS_TIMEOUT isn't correctly mapped
|
|
// to a WIN32 error, that's why we change it here
|
|
// to STATUS_IO_TIMEOUT
|
|
//
|
|
status = STATUS_IO_TIMEOUT;
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
#if 0
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
SmartcardDebug(DEBUG_DRIVER,
|
|
("%s!SerialIo = %lx\n",
|
|
DRIVER_NAME,
|
|
status));
|
|
}
|
|
#endif
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_ReadCardMan (
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN ULONG BytesToRead,
|
|
OUT PULONG pBytesRead,
|
|
IN PUCHAR pReadBuffer,
|
|
IN ULONG ReadBufferSize
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
BOOLEAN fRc;
|
|
|
|
// check if read buffer is large enough
|
|
ASSERT(BytesToRead <= ReadBufferSize);
|
|
|
|
|
|
*pBytesRead = 0; // default setting
|
|
|
|
|
|
DebugStatus = SCCMN50M_SetRead(pSmartcardExtension,BytesToRead);
|
|
|
|
//
|
|
// read operation
|
|
//
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
*pBytesRead = pSmartcardExtension->SmartcardReply.BufferLength;
|
|
|
|
MemCpy(pReadBuffer,
|
|
ReadBufferSize,
|
|
pSmartcardExtension->SmartcardReply.Buffer,
|
|
pSmartcardExtension->SmartcardReply.BufferLength);
|
|
|
|
// overwrite read buffer with '@'
|
|
MemSet(pSmartcardExtension->SmartcardReply.Buffer,
|
|
pSmartcardExtension->SmartcardReply.BufferSize,
|
|
'@',
|
|
pSmartcardExtension->SmartcardReply.BufferLength);
|
|
}
|
|
|
|
if (status != STATUS_SUCCESS || SCCMN50M_IOOperationFailed(pSmartcardExtension))
|
|
{
|
|
if (!pSmartcardExtension->ReaderExtension->fTransparentMode)
|
|
{
|
|
DebugStatus = SCCMN50M_ResyncCardManII(pSmartcardExtension);
|
|
}
|
|
goto ExitSCCMN50M_ReadCardMan;
|
|
}
|
|
|
|
|
|
// *****************************************
|
|
// set CardManII to state RH Config
|
|
// *****************************************
|
|
// don't set CardMan to RH config if there are still bytes to be read
|
|
if (pSmartcardExtension->ReaderExtension->ToRHConfig == TRUE)
|
|
{
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
pSmartcardExtension->SmartcardRequest.Buffer [0] = 0x00;
|
|
pSmartcardExtension->SmartcardRequest.Buffer [1] = 0x00;
|
|
pSmartcardExtension->SmartcardRequest.Buffer [2] = 0x00;
|
|
pSmartcardExtension->SmartcardRequest.Buffer [3] = 0x00;
|
|
pSmartcardExtension->SmartcardRequest.Buffer [4] = 0x89;
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = 5;
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_WRITE;
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS || SCCMN50M_IOOperationFailed(pSmartcardExtension))
|
|
{
|
|
DebugStatus = SCCMN50M_ResyncCardManII(pSmartcardExtension);
|
|
goto ExitSCCMN50M_ReadCardMan;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ExitSCCMN50M_ReadCardMan:
|
|
// set default value;
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = TRUE;
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!ReadCardMan: Failed, exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_GetCommStatus (
|
|
IN PSMARTCARD_EXTENSION SmartcardExtension
|
|
)
|
|
{
|
|
PSERIAL_READER_CONFIG configData = &SmartcardExtension->ReaderExtension->SerialConfigData;
|
|
NTSTATUS status;
|
|
PUCHAR request = SmartcardExtension->SmartcardRequest.Buffer;
|
|
|
|
|
|
SmartcardExtension->SmartcardReply.BufferLength = SmartcardExtension->SmartcardReply.BufferSize;
|
|
|
|
SmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_GET_COMMSTATUS;
|
|
|
|
SmartcardExtension->SmartcardRequest.Buffer = (PUCHAR) &configData->SerialStatus;
|
|
|
|
SmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_STATUS);
|
|
|
|
status = SCCMN50M_SerialIo(SmartcardExtension);
|
|
|
|
//
|
|
// restore pointer to original request buffer
|
|
//
|
|
SmartcardExtension->SmartcardRequest.Buffer = request;
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
BOOLEAN
|
|
SCCMN50M_IOOperationFailed(PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS DebugStatus;
|
|
PSERIAL_STATUS pSerialStatus;
|
|
|
|
DebugStatus = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
|
|
pSerialStatus = (PSERIAL_STATUS)pSmartcardExtension->SmartcardReply.Buffer;
|
|
if (pSerialStatus->Errors)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS SCCMN50M_PurgeComm (IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
PSERIAL_READER_CONFIG configData = &pSmartcardExtension->ReaderExtension->SerialConfigData;
|
|
NTSTATUS status;
|
|
PUCHAR request = pSmartcardExtension->SmartcardRequest.Buffer;
|
|
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = pSmartcardExtension->SmartcardReply.BufferSize;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_PURGE;
|
|
|
|
pSmartcardExtension->SmartcardRequest.Buffer = (PUCHAR) &configData->PurgeMask;
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(ULONG);
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
|
|
//
|
|
// restore pointer to original request buffer
|
|
//
|
|
pSmartcardExtension->SmartcardRequest.Buffer = request;
|
|
|
|
// under W2000 & CardMan P+ STATUS_CANCELLED may be returned
|
|
|
|
if (status == STATUS_CANCELLED)
|
|
status = STATUS_SUCCESS;
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetRead(IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN ULONG ulBytesToRead
|
|
)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_READ;
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = 0;
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = ulBytesToRead;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetWrite(IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN ULONG BytesToWrite,
|
|
IN PUCHAR WriteBuffer
|
|
)
|
|
{
|
|
ULONG Offset = 0;
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = SMARTCARD_WRITE;
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
|
|
if (pSmartcardExtension->ReaderExtension->fTransparentMode == FALSE)
|
|
{
|
|
// send always config string for CardManII, expect we set it manualy
|
|
// to NoConfig = TRUE. (note: only one time)
|
|
if (pSmartcardExtension->ReaderExtension->NoConfig == FALSE)
|
|
{
|
|
MemCpy(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
pSmartcardExtension->SmartcardRequest.BufferSize,
|
|
(PUCHAR)&pSmartcardExtension->ReaderExtension->CardManConfig,
|
|
sizeof(CARDMAN_CONFIG));
|
|
Offset = 4;
|
|
}
|
|
else
|
|
{
|
|
pSmartcardExtension->ReaderExtension->NoConfig = FALSE;
|
|
}
|
|
|
|
|
|
|
|
MemCpy(pSmartcardExtension->SmartcardRequest.Buffer + Offset,
|
|
pSmartcardExtension->SmartcardRequest.BufferSize,
|
|
(PUCHAR)&pSmartcardExtension->ReaderExtension->CardManHeader,
|
|
sizeof(CARDMAN_HEADER));
|
|
Offset+=4;
|
|
}
|
|
|
|
|
|
if (BytesToWrite != 0)
|
|
{
|
|
MemCpy(pSmartcardExtension->SmartcardRequest.Buffer + Offset,
|
|
pSmartcardExtension->SmartcardRequest.BufferSize,
|
|
WriteBuffer,
|
|
BytesToWrite);
|
|
}
|
|
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = Offset + BytesToWrite;
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_StartCardTracking(
|
|
PDEVICE_EXTENSION pDeviceExtension
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
HANDLE hThread;
|
|
PSMARTCARD_EXTENSION pSmartcardExtension = &pDeviceExtension->SmartcardExtension;
|
|
|
|
SmartcardDebug(DEBUG_TRACE,
|
|
("%s!StartCardTracking: Enter\n",DRIVER_NAME));
|
|
|
|
KeWaitForSingleObject(&pSmartcardExtension->ReaderExtension->CardManIOMutex,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL);
|
|
|
|
|
|
// create thread for updating current state
|
|
status = PsCreateSystemThread(&hThread,
|
|
THREAD_ALL_ACCESS,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
SCCMN50M_UpdateCurrentStateThread,
|
|
pDeviceExtension);
|
|
if (!NT_ERROR(status))
|
|
{
|
|
//
|
|
// We've got the thread. Now get a pointer to it.
|
|
//
|
|
status = ObReferenceObjectByHandle(hThread,
|
|
THREAD_ALL_ACCESS,
|
|
NULL,
|
|
KernelMode,
|
|
&pSmartcardExtension->ReaderExtension->ThreadObjectPointer,
|
|
NULL);
|
|
|
|
if (NT_ERROR(status))
|
|
{
|
|
pSmartcardExtension->ReaderExtension->TimeToTerminateThread = TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Now that we have a reference to the thread
|
|
// we can simply close the handle.
|
|
//
|
|
ZwClose(hThread);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
|
|
// Release the mutex
|
|
KeReleaseMutex(&pSmartcardExtension->ReaderExtension->CardManIOMutex,
|
|
FALSE);
|
|
|
|
SmartcardDebug(DEBUG_TRACE,
|
|
("%s!StartCardTracking: Exit %lx\n",DRIVER_NAME,status));
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_InitCommPort (PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!InitCommPort: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
// ===============================
|
|
// clear any pending errors
|
|
// ===============================
|
|
status = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %ld\n",status))
|
|
goto ExitInitCommPort;
|
|
}
|
|
|
|
|
|
|
|
// ==============================
|
|
// set baudrate for CardMan
|
|
// ==============================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 38400;
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate,
|
|
sizeof(SERIAL_BAUD_RATE));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status))
|
|
goto ExitInitCommPort;
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===============================
|
|
// set comm timeouts
|
|
// ===============================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadIntervalTimeout = DEFAULT_READ_INTERVAL_TIMEOUT;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = DEFAULT_READ_TOTAL_TIMEOUT_MULTIPLIER;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.WriteTotalTimeoutConstant = DEFAULT_WRITE_TOTAL_TIMEOUT_CONSTANT;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.WriteTotalTimeoutMultiplier = DEFAULT_WRITE_TOTAL_TIMEOUT_MULTIPLIER;
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_TIMEOUTS;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts,
|
|
sizeof(SERIAL_TIMEOUTS));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_TIMEOUTS);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_TIMEOUTS failed ! status = %x\n",status))
|
|
goto ExitInitCommPort;
|
|
}
|
|
|
|
|
|
// ===============================
|
|
// set line control
|
|
// ===============================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = EVEN_PARITY;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = 8;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl,
|
|
sizeof(SERIAL_LINE_CONTROL));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_LINE_CONTROL failed ! status = %x\n",status))
|
|
goto ExitInitCommPort;
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===============================
|
|
// Set handflow
|
|
// ===============================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.XonLimit = 0;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.XoffLimit = 0;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.FlowReplace = 0;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.ControlHandShake = SERIAL_ERROR_ABORT | SERIAL_DTR_CONTROL;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_HANDFLOW;
|
|
|
|
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow,
|
|
sizeof(SERIAL_HANDFLOW));
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_HANDFLOW);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_HANDFLOW failed ! status = %x\n",status))
|
|
goto ExitInitCommPort;
|
|
}
|
|
|
|
|
|
// ===============================
|
|
// set purge mask
|
|
// ===============================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.PurgeMask =
|
|
SERIAL_PURGE_TXABORT | SERIAL_PURGE_RXABORT |
|
|
SERIAL_PURGE_TXCLEAR | SERIAL_PURGE_RXCLEAR;
|
|
|
|
|
|
|
|
// ===============================
|
|
// set DTR
|
|
// ===============================
|
|
status = SCCMN50M_SetDTR(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_DRT failed ! status = %x\n",status))
|
|
goto ExitInitCommPort;
|
|
}
|
|
|
|
// ===============================
|
|
// set RTS
|
|
// ===============================
|
|
status = SCCMN50M_SetRTS(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_RTS failed ! status = %x\n",status))
|
|
goto ExitInitCommPort;
|
|
}
|
|
|
|
|
|
|
|
|
|
ExitInitCommPort:
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!InitCommPort: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetDTR(IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = 0;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_DTR;
|
|
|
|
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
|
|
// under W2000 & CardMan P+ STATUS_CANCELLED may be returned
|
|
|
|
if (status == STATUS_CANCELLED)
|
|
status = STATUS_SUCCESS;
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetRTS(IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = pSmartcardExtension->SmartcardReply.BufferSize;
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = 0;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_RTS;
|
|
|
|
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
|
|
// under W2000 & CardMan P+ STATUS_CANCELLED may be returned
|
|
|
|
if (status == STATUS_CANCELLED)
|
|
status = STATUS_SUCCESS;
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_InitializeCardMan(IN PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status;
|
|
UCHAR pReadBuffer[2];
|
|
ULONG ulBytesRead;
|
|
BOOLEAN fCardManFound = FALSE;
|
|
PREADER_EXTENSION readerExtension = pSmartcardExtension->ReaderExtension;
|
|
ULONG ulRetries;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!InitializeCardMan: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->ulOldCardState = UNKNOWN;
|
|
|
|
|
|
// ==============================================
|
|
// CardManII
|
|
// ==============================================
|
|
pSmartcardExtension->ReaderExtension->NoConfig = FALSE;
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = TRUE;
|
|
|
|
|
|
// This waiting time if necessary for CardMan Power+, because
|
|
// the pnP string may be dumped
|
|
Wait(pSmartcardExtension,200);
|
|
|
|
status = SCCMN50M_InitCommPort(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
goto ExitInitializeCardMan;
|
|
//
|
|
// init CommPort was O.K.
|
|
// now try to find a reader
|
|
//
|
|
|
|
// To be sure wait make an additional wait
|
|
Wait(pSmartcardExtension,100);
|
|
|
|
status = SCCMN50M_ResyncCardManII(pSmartcardExtension);
|
|
status = SCCMN50M_ResyncCardManII(pSmartcardExtension);
|
|
|
|
|
|
// no data except config + header
|
|
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.SCRControl = XMIT_HANDSHAKE_OFF;
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.CardControl = 0x00;
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0x00;
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.ResetDelay = 0x00;
|
|
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.TxControl = 0x00;
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.TxLength = 0x00;
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.RxControl = 0x00;
|
|
pSmartcardExtension->ReaderExtension->CardManHeader.RxLength = 0x00;
|
|
|
|
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,pReadBuffer,sizeof(pReadBuffer));
|
|
|
|
if (status == STATUS_SUCCESS &&
|
|
ulBytesRead == 0x02 && // two bytes received
|
|
pReadBuffer[0] >= 0x40 && // at least one version bit must be set
|
|
pReadBuffer[1] == 0x00 &&
|
|
((pReadBuffer[0] & 0x09) == 0) ) // bit 0 and 3 must be cleared
|
|
{
|
|
pSmartcardExtension->ReaderExtension->ulFWVersion = (pReadBuffer[0] >> 4) * 30 + 120;
|
|
pSmartcardExtension->ReaderExtension->fSPESupported = FALSE;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
( "%s!CardMan (FW %ld) found\n",
|
|
DRIVER_NAME,pSmartcardExtension->ReaderExtension->ulFWVersion)
|
|
);
|
|
fCardManFound = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
ExitInitializeCardMan:
|
|
|
|
if (fCardManFound == TRUE)
|
|
status = STATUS_SUCCESS;
|
|
else
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!InitializeCardMan: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_EnterTransparentMode (IN PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
SmartcardDebug(DEBUG_TRACE,("EnterTransparentMode : enter\n"));
|
|
|
|
// Step 1 : Resync CardMan by RTS usage
|
|
status = SCCMN50M_ResyncCardManI(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_ResyncCardManI failed ! status = %ld\n",status))
|
|
goto ExitEnterTransparentMode;
|
|
}
|
|
|
|
// Step 2 : set baud rate to 9600
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 9600;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate,
|
|
sizeof(SERIAL_BAUD_RATE));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status))
|
|
goto ExitEnterTransparentMode;
|
|
}
|
|
|
|
|
|
|
|
ExitEnterTransparentMode:
|
|
// Step 3 : set ATR and DUMP_BUFFER flags
|
|
// During normal operation these two flags can never be set at the same time
|
|
SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CM2_GET_ATR | TO_STATE_XH);
|
|
|
|
|
|
|
|
|
|
|
|
SmartcardDebug(DEBUG_TRACE,("EnterTransparentMode : exit\n"));
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_ExitTransparentMode (IN PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
SmartcardDebug(DEBUG_TRACE,("ExitTransparentMode : enter\n"));
|
|
|
|
|
|
// ===============================
|
|
// clear any pending errors
|
|
// ===============================
|
|
status = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %ld\n",status))
|
|
goto ExitExitTransparentMode;
|
|
}
|
|
|
|
|
|
// Step 1 : Resync CardMan by RTS usage
|
|
status = SCCMN50M_ResyncCardManI(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_ResyncCardManI failed ! status = %ld\n",status))
|
|
goto ExitExitTransparentMode;
|
|
}
|
|
|
|
// Step 2 : set baud rate to 38400
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 38400;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate,
|
|
sizeof(SERIAL_BAUD_RATE));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status))
|
|
goto ExitExitTransparentMode;
|
|
}
|
|
|
|
|
|
// if the inserted card uses inverse convention , we must now switch the COM port
|
|
// back to even parity
|
|
if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = EVEN_PARITY;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = SERIAL_DATABITS_8;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl,
|
|
sizeof(SERIAL_LINE_CONTROL));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_LINE_CONTROL failed ! status = %x\n",status))
|
|
goto ExitExitTransparentMode;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
ExitExitTransparentMode:
|
|
|
|
// Step 3 : set ATR and DUMP_BUFFER flags
|
|
// During normal operation these two flags can never be set at the same time
|
|
SCCMN50M_ClearSCRControlFlags(pSmartcardExtension,CM2_GET_ATR | TO_STATE_XH);
|
|
|
|
|
|
|
|
status = SCCMN50M_ResyncCardManII(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_ResyncCardManII failed ! status = %x\n",status))
|
|
goto ExitExitTransparentMode;
|
|
}
|
|
|
|
|
|
SmartcardDebug(DEBUG_TRACE,("ExitTransparentMode : exit\n"));
|
|
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_ClearRTS(IN PSMARTCARD_EXTENSION SmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
|
|
|
|
SmartcardExtension->SmartcardReply.BufferLength = SmartcardExtension->SmartcardReply.BufferSize;
|
|
SmartcardExtension->SmartcardRequest.BufferLength = 0;
|
|
|
|
SmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_CLR_RTS;
|
|
|
|
|
|
|
|
status = SCCMN50M_SerialIo(SmartcardExtension);
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_IoCtlVendor(PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
NTSTATUS DebugStatus;
|
|
UCHAR pbAttrBuffer[MAXIMUM_ATR_LENGTH];
|
|
ULONG ulAtrLength;
|
|
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!IoCtlVendor : Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
|
|
switch (pSmartcardExtension->MajorIoControlCode)
|
|
{
|
|
case CM_IOCTL_SET_READER_9600_BAUD:
|
|
status = SCCMN50M_SetFl_1Dl_1(pSmartcardExtension);
|
|
break;
|
|
|
|
case CM_IOCTL_SET_READER_38400_BAUD:
|
|
status = SCCMN50M_SetFl_1Dl_3(pSmartcardExtension);
|
|
break;
|
|
|
|
case CM_IOCTL_CR80S_SAMOS_SET_HIGH_SPEED:
|
|
status = SCCMN50M_SetHighSpeed_CR80S_SAMOS(pSmartcardExtension);
|
|
break;
|
|
|
|
case CM_IOCTL_GET_FW_VERSION:
|
|
status = SCCMN50M_GetFWVersion(pSmartcardExtension);
|
|
break;
|
|
|
|
case CM_IOCTL_READ_DEVICE_DESCRIPTION:
|
|
status = SCCMN50M_ReadDeviceDescription(pSmartcardExtension);
|
|
break;
|
|
|
|
case CM_IOCTL_SET_SYNC_PARAMETERS :
|
|
status = SCCMN50M_SetSyncParameters(pSmartcardExtension);
|
|
break;
|
|
|
|
case CM_IOCTL_3WBP_TRANSFER : // for SLE4428
|
|
status = SCCMN50M_Transmit3WBP(pSmartcardExtension);
|
|
break;
|
|
|
|
case CM_IOCTL_2WBP_TRANSFER : // for SLE4442
|
|
status = SCCMN50M_Transmit2WBP(pSmartcardExtension);
|
|
break;
|
|
|
|
case CM_IOCTL_2WBP_RESET_CARD: // SLE4442 Reset Card
|
|
status = SCCMN50M_ResetCard2WBP(pSmartcardExtension);
|
|
break;
|
|
|
|
case CM_IOCTL_SYNC_CARD_POWERON:
|
|
status = SCCMN50M_SyncCardPowerOn(pSmartcardExtension);
|
|
break;
|
|
default:
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!IoCtlVendor : Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetFl_1Dl_3(IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
NTSTATUS DebugStatus;
|
|
|
|
SmartcardDebug(DEBUG_TRACE,
|
|
("%s!SetFl_1Dl_3 Enter\n",
|
|
DRIVER_NAME));
|
|
|
|
// check if T=1 active
|
|
if (pSmartcardExtension->CardCapabilities.Protocol.Selected !=
|
|
SCARD_PROTOCOL_T1)
|
|
{
|
|
status = STATUS_CTL_FILE_NOT_SUPPORTED;
|
|
goto ExitSetFl_1Dl_3;
|
|
}
|
|
|
|
// Fl=1
|
|
// Dl=3
|
|
// => 38400 Baud for 3.72 MHz
|
|
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ |
|
|
ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST );
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ_FAST);
|
|
|
|
|
|
ExitSetFl_1Dl_3:
|
|
*pSmartcardExtension->IoRequest.Information = 0L;
|
|
SmartcardDebug(DEBUG_TRACE,
|
|
("%s!SetFl_1Dl_3 Exit\n",
|
|
DRIVER_NAME));
|
|
return status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetFl_1Dl_1(IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
SmartcardDebug(DEBUG_TRACE,
|
|
("%s!SetFl_1Dl_1 Enter\n",
|
|
DRIVER_NAME));
|
|
// Fl=1
|
|
// Dl=1
|
|
// => 9600 for 3.72 MHz
|
|
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ |
|
|
ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST );
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ);
|
|
|
|
|
|
*pSmartcardExtension->IoRequest.Information = 0L;
|
|
SmartcardDebug(DEBUG_TRACE,
|
|
("%s!SetFl_1Dl_1 Exit\n",
|
|
DRIVER_NAME));
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_GetFWVersion (IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!GetFWVersion : Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
if (pSmartcardExtension->IoRequest.ReplyBufferLength < sizeof (ULONG))
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitGetFWVersion;
|
|
}
|
|
else
|
|
{
|
|
*(PULONG)(pSmartcardExtension->IoRequest.ReplyBuffer) =
|
|
pSmartcardExtension->ReaderExtension->ulFWVersion;
|
|
}
|
|
|
|
|
|
ExitGetFWVersion:
|
|
*pSmartcardExtension->IoRequest.Information = sizeof(ULONG);
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!GetFWVersion : Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_ReadDeviceDescription(IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!ReadDeviceDescription : Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
if (pSmartcardExtension->IoRequest.ReplyBufferLength < sizeof(pSmartcardExtension->ReaderExtension->abDeviceDescription))
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
*pSmartcardExtension->IoRequest.Information = 0L;
|
|
goto ExitReadDeviceDescription;
|
|
}
|
|
else
|
|
{
|
|
if (pSmartcardExtension->ReaderExtension->abDeviceDescription[0] == 0x00 &&
|
|
pSmartcardExtension->ReaderExtension->abDeviceDescription[1] == 0x00 )
|
|
{
|
|
status = SCCMN50M_GetDeviceDescription(pSmartcardExtension);
|
|
}
|
|
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
StrCpy(pSmartcardExtension->IoRequest.ReplyBuffer,
|
|
pSmartcardExtension->IoRequest.ReplyBufferLength,
|
|
pSmartcardExtension->ReaderExtension->abDeviceDescription);
|
|
*pSmartcardExtension->IoRequest.Information = StrLen(pSmartcardExtension->ReaderExtension->abDeviceDescription) +1;
|
|
}
|
|
else
|
|
{
|
|
MemSet(pSmartcardExtension->ReaderExtension->abDeviceDescription,
|
|
sizeof(pSmartcardExtension->ReaderExtension->abDeviceDescription),
|
|
0x00,
|
|
sizeof(pSmartcardExtension->ReaderExtension->abDeviceDescription));
|
|
|
|
*pSmartcardExtension->IoRequest.Information = 0;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
ExitReadDeviceDescription:
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!ReadDeviceDescription : Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetHighSpeed_CR80S_SAMOS (IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
UCHAR bReadBuffer[16];
|
|
ULONG ulBytesRead;
|
|
BYTE bCR80S_SAMOS_SET_HIGH_SPEED[4] = {0xFF,0x11,0x94,0x7A};
|
|
ULONG ulAtrLength;
|
|
BYTE bAtr[MAXIMUM_ATR_LENGTH];
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!SetHighSpeed_CR80S_SAMOS : Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_SYN | ENABLE_T0 |
|
|
ENABLE_T1 );
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
0, // Tx control
|
|
sizeof(bCR80S_SAMOS_SET_HIGH_SPEED), // Tx length
|
|
0, // Rx control
|
|
sizeof(bCR80S_SAMOS_SET_HIGH_SPEED)); // Rx length
|
|
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,
|
|
sizeof(bCR80S_SAMOS_SET_HIGH_SPEED),
|
|
bCR80S_SAMOS_SET_HIGH_SPEED);
|
|
if (status != STATUS_SUCCESS)
|
|
goto ExitSetHighSpeed;
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer));
|
|
if (status != STATUS_SUCCESS)
|
|
goto ExitSetHighSpeed;
|
|
|
|
if (bReadBuffer[1] > sizeof(bReadBuffer))
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitSetHighSpeed;
|
|
}
|
|
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],&ulBytesRead,bReadBuffer,sizeof(bReadBuffer));
|
|
if (status != STATUS_SUCCESS)
|
|
goto ExitSetHighSpeed;
|
|
|
|
// if the card has accepted this string , the string is echoed
|
|
if (bReadBuffer[0] == bCR80S_SAMOS_SET_HIGH_SPEED[0] &&
|
|
bReadBuffer[1] == bCR80S_SAMOS_SET_HIGH_SPEED[1] &&
|
|
bReadBuffer[2] == bCR80S_SAMOS_SET_HIGH_SPEED[2] &&
|
|
bReadBuffer[3] == bCR80S_SAMOS_SET_HIGH_SPEED[3] )
|
|
{
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ |
|
|
ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST );
|
|
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ_FAST);
|
|
}
|
|
else
|
|
{
|
|
DebugStatus = SCCMN50M_PowerOff(pSmartcardExtension);
|
|
|
|
DebugStatus = SCCMN50M_PowerOn(pSmartcardExtension,&ulAtrLength,bAtr,sizeof(bAtr));
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ExitSetHighSpeed:
|
|
*pSmartcardExtension->IoRequest.Information = 0L;
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!SetHighSpeed_CR80S_SAMOS : Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetBRK(IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = pSmartcardExtension->SmartcardReply.BufferSize;
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = 0;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BREAK_ON;
|
|
|
|
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_ClearBRK(IN PSMARTCARD_EXTENSION SmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
|
|
|
|
SmartcardExtension->SmartcardReply.BufferLength = SmartcardExtension->SmartcardReply.BufferSize;
|
|
SmartcardExtension->SmartcardRequest.BufferLength = 0;
|
|
|
|
SmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BREAK_OFF;
|
|
|
|
|
|
|
|
status = SCCMN50M_SerialIo(SmartcardExtension);
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetProtocol(PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
ULONG ulNewProtocol;
|
|
UCHAR abPTSRequest[4];
|
|
UCHAR abReadBuffer[6];
|
|
UCHAR abPTSReply [4];
|
|
ULONG ulBytesRead;
|
|
UCHAR bTemp;
|
|
ULONG ulPtsType;
|
|
ULONG ulPTSReplyLength=0;
|
|
ULONG ulStatBytesRead;
|
|
BYTE abStatReadBuffer[2];
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!SetProtocol : Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
//
|
|
// Check if the card is already in specific state
|
|
// and if the caller wants to have the already selected protocol.
|
|
// We return success if this is the case.
|
|
//
|
|
if ((pSmartcardExtension->CardCapabilities.Protocol.Selected & pSmartcardExtension->MinorIoControlCode))
|
|
{
|
|
status = STATUS_SUCCESS;
|
|
goto ExitSetProtocol;
|
|
}
|
|
|
|
ulNewProtocol = pSmartcardExtension->MinorIoControlCode;
|
|
|
|
|
|
|
|
ulPtsType = PTS_TYPE_OPTIMAL;
|
|
|
|
// we are not sure if we need this at all
|
|
pSmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_OPTIMAL;
|
|
while (TRUE)
|
|
{
|
|
|
|
// set initial character of PTS
|
|
abPTSRequest[0] = 0xFF;
|
|
|
|
// set the format character
|
|
if (pSmartcardExtension->CardCapabilities.Protocol.Supported &
|
|
ulNewProtocol &
|
|
SCARD_PROTOCOL_T1)
|
|
{
|
|
// select T=1 and indicate that PTS1 follows
|
|
abPTSRequest[1] = 0x11;
|
|
pSmartcardExtension->CardCapabilities.Protocol.Selected =
|
|
SCARD_PROTOCOL_T1;
|
|
}
|
|
else if (pSmartcardExtension->CardCapabilities.Protocol.Supported &
|
|
ulNewProtocol &
|
|
SCARD_PROTOCOL_T0)
|
|
{
|
|
// select T=1 and indicate that PTS1 follows
|
|
abPTSRequest[1] = 0x10;
|
|
pSmartcardExtension->CardCapabilities.Protocol.Selected =
|
|
SCARD_PROTOCOL_T0;
|
|
}
|
|
else
|
|
{
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
goto ExitSetProtocol;
|
|
}
|
|
|
|
// bug fix :
|
|
// don 't use the suggestion from smclib
|
|
pSmartcardExtension->CardCapabilities.PtsData.Fl =
|
|
pSmartcardExtension->CardCapabilities.Fl;
|
|
pSmartcardExtension->CardCapabilities.PtsData.Dl =
|
|
pSmartcardExtension->CardCapabilities.Dl;
|
|
|
|
|
|
// CardMan support higher baudrates only for T=1
|
|
// ==> Dl=1
|
|
if (abPTSRequest[1] == 0x10)
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!overwriting PTS1 for T=0\n",
|
|
DRIVER_NAME)
|
|
);
|
|
pSmartcardExtension->CardCapabilities.PtsData.Fl = 0x01;
|
|
pSmartcardExtension->CardCapabilities.PtsData.Dl = 0x01;
|
|
}
|
|
|
|
|
|
if (ulPtsType == PTS_TYPE_DEFAULT)
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!overwriting PTS1 with default values\n",
|
|
DRIVER_NAME)
|
|
);
|
|
pSmartcardExtension->CardCapabilities.PtsData.Fl = 0x01;
|
|
pSmartcardExtension->CardCapabilities.PtsData.Dl = 0x01;
|
|
}
|
|
|
|
|
|
// set pts1 which codes Fl and Dl
|
|
bTemp = (BYTE) (pSmartcardExtension->CardCapabilities.PtsData.Fl << 4 |
|
|
pSmartcardExtension->CardCapabilities.PtsData.Dl);
|
|
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!PTS1 = %x (suggestion)\n",
|
|
DRIVER_NAME,bTemp)
|
|
);
|
|
|
|
|
|
switch (bTemp)
|
|
{
|
|
case 0x11:
|
|
// do nothing
|
|
// we support these Fl/Dl parameters
|
|
break;
|
|
|
|
case 0x13:
|
|
case 0x94:
|
|
break ;
|
|
|
|
|
|
case 0x14:
|
|
// let's try it with 38400 baud
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!trying 57600 baud\n",DRIVER_NAME)
|
|
);
|
|
// we must correct Fl/Dl
|
|
pSmartcardExtension->CardCapabilities.PtsData.Dl = 0x03;
|
|
pSmartcardExtension->CardCapabilities.PtsData.Fl = 0x01;
|
|
bTemp = (BYTE) (pSmartcardExtension->CardCapabilities.PtsData.Fl << 4 |
|
|
pSmartcardExtension->CardCapabilities.PtsData.Dl);
|
|
break;
|
|
|
|
default:
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!overwriting PTS1(0x%x)\n",
|
|
DRIVER_NAME,bTemp)
|
|
);
|
|
// we must correct Fl/Dl
|
|
pSmartcardExtension->CardCapabilities.PtsData.Dl = 0x01;
|
|
pSmartcardExtension->CardCapabilities.PtsData.Fl = 0x01;
|
|
bTemp = (BYTE) (pSmartcardExtension->CardCapabilities.PtsData.Fl << 4 |
|
|
pSmartcardExtension->CardCapabilities.PtsData.Dl);
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
abPTSRequest[2] = bTemp;
|
|
|
|
// set pck (check character)
|
|
abPTSRequest[3] = (BYTE)(abPTSRequest[0] ^ abPTSRequest[1] ^ abPTSRequest[2]);
|
|
|
|
SmartcardDebug(DEBUG_PROTOCOL,("%s!PTS request: 0x%x 0x%x 0x%x 0x%x\n",
|
|
DRIVER_NAME,
|
|
abPTSRequest[0],
|
|
abPTSRequest[1],
|
|
abPTSRequest[2],
|
|
abPTSRequest[3]));
|
|
|
|
|
|
MemSet(abPTSReply,sizeof(abPTSReply),0x00,sizeof(abPTSReply));
|
|
|
|
|
|
|
|
DebugStatus = SCCMN50M_EnterTransparentMode(pSmartcardExtension);
|
|
|
|
// STEP 1 : write config + header to enter transparent mode
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
0, // Tx control
|
|
0, // Tx length
|
|
0, // Rx control
|
|
0); // Rx length
|
|
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
0,
|
|
NULL);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitSetProtocol;
|
|
}
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->fTransparentMode = TRUE;
|
|
|
|
// if the inserted card uses inverse convention , we must now switch the COM port
|
|
// to odd parity
|
|
/*
|
|
if (pSmartcardExtension->ReaderExtension->fInverseAtr == TRUE)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = ODD_PARITY;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = SERIAL_DATABITS_8;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl,
|
|
sizeof(SERIAL_LINE_CONTROL));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
goto ExitTransparentTransmitT0;
|
|
}
|
|
}
|
|
*/
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!writing PTS request\n",
|
|
DRIVER_NAME)
|
|
);
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,
|
|
4,
|
|
abPTSRequest);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!writing PTS request failed\n",
|
|
DRIVER_NAME)
|
|
);
|
|
goto ExitSetProtocol;
|
|
}
|
|
|
|
|
|
|
|
// read back pts data
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!trying to read PTS reply\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
// first read CardMan header
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,3,&ulBytesRead,abReadBuffer,sizeof(abReadBuffer));
|
|
if (status != STATUS_SUCCESS &&
|
|
status != STATUS_IO_TIMEOUT )
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!reading status failed\n",
|
|
DRIVER_NAME)
|
|
);
|
|
goto ExitSetProtocol;
|
|
}
|
|
ulPTSReplyLength = 3;
|
|
MemCpy(abPTSReply,sizeof(abPTSReply),abReadBuffer,3);
|
|
|
|
|
|
|
|
// check if bit 5 is set
|
|
if (abPTSReply[1] & 0x10)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig= FALSE;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,1,&ulBytesRead,abReadBuffer,sizeof(abReadBuffer));
|
|
if (status != STATUS_SUCCESS &&
|
|
status != STATUS_IO_TIMEOUT )
|
|
{
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!reading status failed\n",
|
|
DRIVER_NAME)
|
|
);
|
|
goto ExitSetProtocol;
|
|
}
|
|
ulPTSReplyLength += 1;
|
|
MemCpy(&abPTSReply[3],sizeof(abPTSReply)-3,abReadBuffer,1);
|
|
}
|
|
|
|
DebugStatus = SCCMN50M_ExitTransparentMode(pSmartcardExtension);
|
|
pSmartcardExtension->ReaderExtension->fTransparentMode = FALSE;
|
|
|
|
// to be sure that the new settings take effect
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 250;
|
|
DebugStatus = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT;
|
|
if (NT_SUCCESS(DebugStatus))
|
|
{
|
|
DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulStatBytesRead,abStatReadBuffer,sizeof(abStatReadBuffer));
|
|
}
|
|
|
|
|
|
#if DBG
|
|
if (ulPTSReplyLength == 3)
|
|
{
|
|
SmartcardDebug(DEBUG_PROTOCOL,("PTS reply: 0x%x 0x%x 0x%x\n",
|
|
abPTSReply[0],
|
|
abPTSReply[1],
|
|
abPTSReply[2]));
|
|
}
|
|
|
|
if (ulPTSReplyLength == 4)
|
|
{
|
|
SmartcardDebug(DEBUG_PROTOCOL,("PTS reply: 0x%x 0x%x 0x%x 0x%x\n",
|
|
abPTSReply[0],
|
|
abPTSReply[1],
|
|
abPTSReply[2],
|
|
abPTSReply[3]));
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
if (ulPTSReplyLength == 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)
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
if (ulPTSReplyLength == 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)
|
|
);
|
|
switch (bTemp)
|
|
{
|
|
case 0x11:
|
|
break;
|
|
|
|
case 0x13:
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ |
|
|
ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST );
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ_FAST);
|
|
break ;
|
|
|
|
case 0x94:
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ENABLE_3MHZ | ENABLE_5MHZ |
|
|
ENABLE_3MHZ_FAST | ENABLE_5MHZ_FAST );
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ_FAST);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (pSmartcardExtension->CardCapabilities.PtsData.Type !=
|
|
PTS_TYPE_DEFAULT)
|
|
{
|
|
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 valies
|
|
ulPtsType = pSmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_DEFAULT;
|
|
pSmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET;
|
|
status = SCCMN50M_CardPower(pSmartcardExtension);
|
|
continue;
|
|
}
|
|
|
|
// the card failed the pts request
|
|
status = STATUS_DEVICE_PROTOCOL_ERROR;
|
|
goto ExitSetProtocol;
|
|
|
|
}
|
|
|
|
|
|
|
|
ExitSetProtocol:
|
|
switch (status)
|
|
{
|
|
case STATUS_IO_TIMEOUT:
|
|
pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
|
|
*pSmartcardExtension->IoRequest.Information = 0;
|
|
break;
|
|
|
|
|
|
case STATUS_SUCCESS:
|
|
|
|
// now indicate that we're in specific mode
|
|
pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
|
|
|
|
// return the selected protocol to the caller
|
|
*(PULONG) pSmartcardExtension->IoRequest.ReplyBuffer =
|
|
pSmartcardExtension->CardCapabilities.Protocol.Selected;
|
|
|
|
*pSmartcardExtension->IoRequest.Information =
|
|
sizeof(pSmartcardExtension->CardCapabilities.Protocol.Selected);
|
|
SmartcardDebug(
|
|
DEBUG_PROTOCOL,
|
|
( "%s!Selected protocol: T=%ld\n",
|
|
DRIVER_NAME,pSmartcardExtension->CardCapabilities.Protocol.Selected-1)
|
|
);
|
|
break;
|
|
|
|
default :
|
|
pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_UNDEFINED;
|
|
*pSmartcardExtension->IoRequest.Information = 0;
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!SetProtocol : Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
The smart card lib requires to have this function. It is called
|
|
to setup event tracking for card insertion and removal events.
|
|
|
|
Arguments:
|
|
|
|
pSmartcardExtension - pointer to the smart card data struct.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_CardTracking(PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
KIRQL oldIrql;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!CardTracking: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
//
|
|
// Set cancel routine for the notification irp
|
|
//
|
|
IoAcquireCancelSpinLock(&oldIrql);
|
|
|
|
IoSetCancelRoutine(pSmartcardExtension->OsData->NotificationIrp,SCCMN50M_Cancel);
|
|
|
|
IoReleaseCancelSpinLock(oldIrql);
|
|
|
|
//
|
|
// Mark notification irp pending
|
|
//
|
|
IoMarkIrpPending(pSmartcardExtension->OsData->NotificationIrp);
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!CardTracking: Exit\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
return STATUS_PENDING;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_StopCardTracking(
|
|
IN PDEVICE_EXTENSION pDeviceExtension
|
|
)
|
|
{
|
|
PSMARTCARD_EXTENSION pSmartcardExtension = &pDeviceExtension->SmartcardExtension;
|
|
NTSTATUS status;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!StopCardTracking: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
if (pSmartcardExtension->ReaderExtension->ThreadObjectPointer != NULL)
|
|
{
|
|
|
|
// kill thread
|
|
KeWaitForSingleObject(&pSmartcardExtension->ReaderExtension->CardManIOMutex,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL
|
|
);
|
|
pSmartcardExtension->ReaderExtension->TimeToTerminateThread = TRUE;
|
|
KeReleaseMutex(&pSmartcardExtension->ReaderExtension->CardManIOMutex,FALSE);
|
|
|
|
|
|
//
|
|
// Wait on the thread handle, when the wait is satisfied, the
|
|
// thread has gone away.
|
|
//
|
|
status = KeWaitForSingleObject(
|
|
pSmartcardExtension->ReaderExtension->ThreadObjectPointer,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL
|
|
);
|
|
|
|
pSmartcardExtension->ReaderExtension->ThreadObjectPointer = NULL;
|
|
}
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!StopCardTracking: Exit %lx\n",
|
|
DRIVER_NAME,
|
|
status)
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_GetDeviceDescription (PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
ULONG ulBytesRead;
|
|
BYTE bByteRead;
|
|
ULONG i,j;
|
|
BYTE abReadBuffer[256];
|
|
ULONG ulPnPStringLength = 0;
|
|
ULONG ulExtend;
|
|
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!GetDeviceDescriptiong: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
|
|
// ===============================
|
|
// clear any pending errors
|
|
// ===============================
|
|
status = SCCMN50M_GetCommStatus(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("SCCMN50M_GetCommStatus failed ! status = %ld\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
|
|
|
|
// =================================
|
|
// set baudrate for CardMan to 1200
|
|
// =================================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 1200;
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate,
|
|
sizeof(SERIAL_BAUD_RATE));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
|
|
// ===============================
|
|
// set comm timeouts
|
|
// ===============================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadIntervalTimeout = DEFAULT_READ_INTERVAL_TIMEOUT;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT + 5000;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutMultiplier = DEFAULT_READ_TOTAL_TIMEOUT_MULTIPLIER;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.WriteTotalTimeoutConstant = DEFAULT_WRITE_TOTAL_TIMEOUT_CONSTANT;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.WriteTotalTimeoutMultiplier = DEFAULT_WRITE_TOTAL_TIMEOUT_MULTIPLIER;
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_TIMEOUTS;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts,
|
|
sizeof(SERIAL_TIMEOUTS));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_TIMEOUTS);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_TIMEOUTS failed ! status = %x\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===============================
|
|
// set line control
|
|
// ===============================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = NO_PARITY;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = 7;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl,
|
|
sizeof(SERIAL_LINE_CONTROL));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_LINE_CONTROL failed ! status = %x\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===============================
|
|
// Set handflow
|
|
// ===============================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.XonLimit = 0;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.XoffLimit = 0;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.FlowReplace = 0;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow.ControlHandShake = SERIAL_ERROR_ABORT | SERIAL_DTR_CONTROL;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_HANDFLOW;
|
|
|
|
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.HandFlow,
|
|
sizeof(SERIAL_HANDFLOW));
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_HANDFLOW);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_HANDFLOW failed ! status = %x\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
|
|
// ===============================
|
|
// set purge mask
|
|
// ===============================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.PurgeMask =
|
|
SERIAL_PURGE_TXABORT | SERIAL_PURGE_RXABORT |
|
|
SERIAL_PURGE_TXCLEAR | SERIAL_PURGE_RXCLEAR;
|
|
|
|
|
|
// ===============================
|
|
// clear RTS
|
|
// ===============================
|
|
status = SCCMN50M_ClearRTS(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_RTS failed ! status = %x\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
Wait(pSmartcardExtension,1);
|
|
|
|
// ===============================
|
|
// set DTR
|
|
// ===============================
|
|
|
|
status = SCCMN50M_SetDTR(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_DRT failed ! status = %x\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
Wait(pSmartcardExtension,1);
|
|
|
|
|
|
// ===============================
|
|
// set RTS
|
|
// ===============================
|
|
status = SCCMN50M_SetRTS(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_RTS failed ! status = %x\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
i=0;
|
|
while (1)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,1,&ulBytesRead,&bByteRead,sizeof(bByteRead));
|
|
if (status == STATUS_SUCCESS)
|
|
{
|
|
abReadBuffer[i++] = bByteRead;
|
|
if (bByteRead == 0x29)
|
|
{
|
|
ulPnPStringLength = i;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (ulPnPStringLength > 11 )
|
|
{
|
|
ulExtend = 0;
|
|
for (i=0;i<ulPnPStringLength;i++)
|
|
{
|
|
if (abReadBuffer[i] == 0x5C)
|
|
ulExtend++;
|
|
if (ulExtend == 4)
|
|
{
|
|
j = 0;
|
|
i++;
|
|
while (i < ulPnPStringLength - 3)
|
|
{
|
|
pSmartcardExtension->ReaderExtension->abDeviceDescription[j] = abReadBuffer[i];
|
|
i++;
|
|
j++;
|
|
}
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
( "%s!Device=%s\n",
|
|
pSmartcardExtension->ReaderExtension->abDeviceDescription)
|
|
);
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ===================
|
|
// restore baud rate
|
|
// ===================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate = 38400;
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_BAUD_RATE;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.BaudRate.BaudRate,
|
|
sizeof(SERIAL_BAUD_RATE));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_BAUD_RATE);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_BAUDRATE failed ! status = %ld\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
// ====================
|
|
// retore line control
|
|
// ====================
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.StopBits = STOP_BITS_2;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.Parity = EVEN_PARITY;
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl.WordLength = 8;
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialIoControlCode = IOCTL_SERIAL_SET_LINE_CONTROL;
|
|
RtlCopyMemory(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
&pSmartcardExtension->ReaderExtension->SerialConfigData.LineControl,
|
|
sizeof(SERIAL_LINE_CONTROL));
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = sizeof(SERIAL_LINE_CONTROL);
|
|
pSmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
|
|
status = SCCMN50M_SerialIo(pSmartcardExtension);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
SmartcardDebug(DEBUG_ERROR,("IOCTL_SERIAL_SET_LINE_CONTROL failed ! status = %x\n",status))
|
|
goto ExitGetDeviceDescription;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ExitGetDeviceDescription:
|
|
DebugStatus = SCCMN50M_ResyncCardManII(pSmartcardExtension);
|
|
|
|
if (status != STATUS_SUCCESS)
|
|
{ // map all errors to STATUS_UNSUCCESSFULL;
|
|
status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!GetDeviceDescriptiong: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SetSyncParameters(IN PSMARTCARD_EXTENSION pSmartcardExtension )
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!SetSyncParameters: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
//DBGBreakPoint();
|
|
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.ulProtocol =
|
|
((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulProtocol;
|
|
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.ulStateResetLineWhileReading =
|
|
((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulStateResetLineWhileReading;
|
|
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.ulStateResetLineWhileWriting =
|
|
((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulStateResetLineWhileWriting;
|
|
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.ulWriteDummyClocks =
|
|
((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulWriteDummyClocks;
|
|
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.ulHeaderLen =
|
|
((PSYNC_PARAMETERS)pSmartcardExtension->IoRequest.RequestBuffer)->ulHeaderLen;
|
|
|
|
// Used for the 2 Wire Protocol. We must make a Card reset after Power On
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested = TRUE;
|
|
|
|
|
|
// return length of reply
|
|
*pSmartcardExtension->IoRequest.Information = 0L;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!SetSyncParameters: Exit\n",
|
|
DRIVER_NAME)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
UCHAR
|
|
SCCMN50M_CalcTxControlByte (IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN ULONG ulBitsToWrite )
|
|
{
|
|
UCHAR bTxControlByte = 0;
|
|
|
|
if (pSmartcardExtension->ReaderExtension->SyncParameters.ulProtocol == SCARD_PROTOCOL_2WBP)
|
|
{
|
|
bTxControlByte = CLOCK_FORCED_2WBP;
|
|
}
|
|
else
|
|
{
|
|
if (ulBitsToWrite >= 255 * 8)
|
|
bTxControlByte |= TRANSMIT_A8;
|
|
|
|
if (pSmartcardExtension->ReaderExtension->SyncParameters.ulStateResetLineWhileWriting ==
|
|
SCARD_RESET_LINE_HIGH)
|
|
bTxControlByte |= SYNC_RESET_LINE_HIGH;
|
|
}
|
|
|
|
bTxControlByte |= (BYTE)((ulBitsToWrite-1) & 0x00000007);
|
|
|
|
return bTxControlByte;
|
|
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
UCHAR
|
|
SCCMN50M_CalcTxLengthByte (IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN ULONG ulBitsToWrite )
|
|
{
|
|
UCHAR bTxLengthByte = 0;
|
|
|
|
bTxLengthByte = (BYTE)( ((ulBitsToWrite - 1) >> 3) + 1);
|
|
|
|
return bTxLengthByte;
|
|
}
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
UCHAR
|
|
SCCMN50M_CalcRxControlByte (IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN ULONG ulBitsToRead )
|
|
{
|
|
UCHAR bRxControlByte = 0;
|
|
|
|
|
|
if (pSmartcardExtension->ReaderExtension->SyncParameters.ulStateResetLineWhileReading ==
|
|
SCARD_RESET_LINE_HIGH)
|
|
bRxControlByte |= SYNC_RESET_LINE_HIGH;
|
|
|
|
if (ulBitsToRead == 0)
|
|
{
|
|
ulBitsToRead = pSmartcardExtension->ReaderExtension->SyncParameters.ulWriteDummyClocks;
|
|
bRxControlByte |= SYNC_DUMMY_RECEIVE;
|
|
}
|
|
|
|
if (ulBitsToRead > 255 * 8)
|
|
bRxControlByte |= RECEIVE_A8;
|
|
|
|
bRxControlByte |= (BYTE)( (ulBitsToRead-1) & 0x00000007);
|
|
|
|
return bRxControlByte;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
UCHAR
|
|
SCCMN50M_CalcRxLengthByte (IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
IN ULONG ulBitsToRead )
|
|
{
|
|
UCHAR bRxLengthByte = 0;
|
|
|
|
// if (pSmartcardExtension->ReaderExtension->SyncParameters.ulProtocol == SCARD_PROTOCOL_3WBP)
|
|
// {
|
|
if (ulBitsToRead == 0)
|
|
ulBitsToRead = pSmartcardExtension->ReaderExtension->SyncParameters.ulWriteDummyClocks;
|
|
|
|
bRxLengthByte = (BYTE)( ((ulBitsToRead - 1) >> 3) + 1);
|
|
// }
|
|
|
|
return bRxLengthByte;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_SyncCardPowerOn (
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
UCHAR pbAtrBuffer[MAXIMUM_ATR_LENGTH];
|
|
UCHAR abSyncAtrBuffer[MAXIMUM_ATR_LENGTH];
|
|
ULONG ulAtrLength = 0;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!SyncCardPowerOn: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
status = SCCMN50M_UseSyncStrategy(pSmartcardExtension,
|
|
&ulAtrLength,
|
|
pbAtrBuffer,
|
|
sizeof(pbAtrBuffer));
|
|
|
|
|
|
abSyncAtrBuffer[0] = 0x3B;
|
|
abSyncAtrBuffer[1] = 0x04;
|
|
MemCpy(&abSyncAtrBuffer[2],
|
|
sizeof(abSyncAtrBuffer)-2,
|
|
pbAtrBuffer,
|
|
ulAtrLength);
|
|
|
|
|
|
ulAtrLength += 2;
|
|
|
|
MemCpy(pSmartcardExtension->CardCapabilities.ATR.Buffer,
|
|
sizeof(pSmartcardExtension->CardCapabilities.ATR.Buffer),
|
|
abSyncAtrBuffer,
|
|
ulAtrLength);
|
|
|
|
pSmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)(ulAtrLength);
|
|
|
|
pSmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
|
|
pSmartcardExtension->CardCapabilities.Protocol.Selected = SCARD_PROTOCOL_T0;
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested = TRUE;
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.fCardPowerRequested = FALSE;
|
|
|
|
|
|
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]));
|
|
|
|
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!SyncCardPowerOn: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
|
|
return status;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_Transmit2WBP(PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
UCHAR bWriteBuffer [128];
|
|
UCHAR bReadBuffer [128];
|
|
UCHAR bTxControlByte;
|
|
UCHAR bTxLengthByte;
|
|
UCHAR bRxControlByte;
|
|
UCHAR bRxLengthByte;
|
|
ULONG ulBytesToWrite;
|
|
ULONG ulBytesToRead;
|
|
ULONG ulBitsToWrite;
|
|
ULONG ulBitsToRead;
|
|
ULONG ulBytesRead;
|
|
// ULONG ulBitsRead;
|
|
ULONG ulBytesStillToRead;
|
|
ULONG ulMaxIFSD;
|
|
PCHAR pbInData;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!Transmit2WBP: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/** Power smartcard - if smartcard was removed and reinserted **/
|
|
/*-----------------------------------------------------------------------*/
|
|
if (pSmartcardExtension->ReaderExtension->SyncParameters.fCardPowerRequested == TRUE)
|
|
{
|
|
status = SCCMN50M_SyncCardPowerOn (pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitTransmit2WBP;
|
|
}
|
|
}
|
|
|
|
|
|
pbInData = pSmartcardExtension->IoRequest.RequestBuffer + sizeof(SYNC_TRANSFER);
|
|
ulBitsToWrite = ((PSYNC_TRANSFER)(pSmartcardExtension->IoRequest.RequestBuffer))->ulSyncBitsToWrite;
|
|
ulBitsToRead = ((PSYNC_TRANSFER)(pSmartcardExtension->IoRequest.RequestBuffer))->ulSyncBitsToRead;
|
|
ulBytesToWrite = ulBitsToWrite/8;
|
|
ulBytesToRead = ulBitsToRead/8 + (ulBitsToRead % 8 ? 1 : 0);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// check buffer sizes
|
|
/*-----------------------------------------------------------------------*/
|
|
ulMaxIFSD = ATTR_MAX_IFSD_CARDMAN_II;
|
|
|
|
|
|
if (ulBytesToRead > ulMaxIFSD ||
|
|
ulBytesToRead > pSmartcardExtension->SmartcardReply.BufferSize)
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitTransmit2WBP;
|
|
}
|
|
|
|
if (ulBytesToWrite > pSmartcardExtension->SmartcardRequest.BufferSize)
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitTransmit2WBP;
|
|
}
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = ulBytesToWrite+1;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// copy data to the Smartcard Request Buffer
|
|
/*-----------------------------------------------------------------------*/
|
|
(pSmartcardExtension->SmartcardRequest.Buffer)[0] = '\x0F';
|
|
MemCpy((pSmartcardExtension->SmartcardRequest.Buffer+1),
|
|
pSmartcardExtension->SmartcardRequest.BufferSize,
|
|
pbInData,
|
|
ulBytesToWrite);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// copy data to the write buffer
|
|
/*-----------------------------------------------------------------------*/
|
|
MemCpy((bWriteBuffer),
|
|
sizeof(bWriteBuffer),
|
|
pSmartcardExtension->SmartcardRequest.Buffer,
|
|
(ulBytesToWrite+1));
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// set SYNC protocol flag for CardMan
|
|
/*-----------------------------------------------------------------------*/
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_SYN);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Header
|
|
/*-----------------------------------------------------------------------*/
|
|
if (pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested == TRUE)
|
|
{
|
|
status = SCCMN50M_ResetCard2WBP(pSmartcardExtension);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransmit2WBP;
|
|
}
|
|
|
|
pSmartcardExtension->ReaderExtension->SyncParameters.fCardResetRequested = FALSE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// 1. Send Carman-Header 4-Byte
|
|
// 2. Send 0x0F, that builds a HIGH-LOW Edge for 4432 CC
|
|
// 3. Send the Data (CC command = 3 Byte)
|
|
/*-----------------------------------------------------------------------*/
|
|
bTxControlByte = SCCMN50M_CalcTxControlByte(pSmartcardExtension,ulBitsToWrite);
|
|
bTxLengthByte = (BYTE)(SCCMN50M_CalcTxLengthByte(pSmartcardExtension,ulBitsToWrite)+1);
|
|
bRxControlByte = 0;
|
|
bRxLengthByte = 0;
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
bTxControlByte,
|
|
bTxLengthByte,
|
|
bRxControlByte,
|
|
bRxLengthByte);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// write data to card
|
|
/*-----------------------------------------------------------------------*/
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
(ulBytesToWrite+1),
|
|
bWriteBuffer);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransmit2WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// read CardMan Header
|
|
// no Data from CC received
|
|
/*-----------------------------------------------------------------------*/
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,
|
|
2,
|
|
&ulBytesRead,
|
|
bReadBuffer,
|
|
sizeof(bReadBuffer));
|
|
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransmit2WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// 1. Send Carman-Header 4-Byte
|
|
// 2. Send 0xF0, that builds a LOW-HIGH Edge for 4432 CC
|
|
// 3. Now the receiviing of card-data begins
|
|
/*-----------------------------------------------------------------------*/
|
|
bTxControlByte = SCCMN50M_CalcTxControlByte(pSmartcardExtension, 8);
|
|
bTxLengthByte = SCCMN50M_CalcTxLengthByte(pSmartcardExtension, 8);
|
|
bRxControlByte = SCCMN50M_CalcRxControlByte(pSmartcardExtension,ulBitsToRead);
|
|
bRxLengthByte = SCCMN50M_CalcRxLengthByte(pSmartcardExtension,ulBitsToRead);
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
bTxControlByte,
|
|
bTxLengthByte,
|
|
bRxControlByte,
|
|
bRxLengthByte);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// in this sequnce SCCMN50M_WriteCardMan must not send the Config string.
|
|
// write 0xF0 -> is the trigger to read data from card or start the
|
|
// processing.
|
|
/*-----------------------------------------------------------------------*/
|
|
pSmartcardExtension->ReaderExtension->NoConfig = TRUE;
|
|
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
1, // one byte to write
|
|
"\xF0"); // LOW-HIGH - Edge
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransmit2WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// read CardMan Header
|
|
// Data from CC received will be received
|
|
/*-----------------------------------------------------------------------*/
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,
|
|
2,
|
|
&ulBytesRead,
|
|
bReadBuffer,
|
|
sizeof(bReadBuffer));
|
|
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransmit2WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Read the data string
|
|
/*-----------------------------------------------------------------------*/
|
|
ulBytesStillToRead = (ULONG)bReadBuffer[1];
|
|
|
|
if (bReadBuffer[0] & RECEIVE_A8)
|
|
ulBytesStillToRead += 256;
|
|
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,
|
|
ulBytesStillToRead,
|
|
&ulBytesRead,
|
|
bReadBuffer,
|
|
sizeof(bReadBuffer));
|
|
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransmit2WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/** calculate data length in bits - this value is not used **/
|
|
/*-----------------------------------------------------------------------*/
|
|
// ulBitsRead = ((ulBytesRead-1) * 8) + ((ulBitsToRead-1 ) & 0x00000007) + 1;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/** shift the bits in the last byte to the correct position **/
|
|
/*-----------------------------------------------------------------------*/
|
|
bReadBuffer[ulBytesRead-1] >>= (7 - ((ulBitsToRead-1) & 0x00000007));
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// the first bit of the returned string is lost
|
|
// so we must shift the whole data string one bit left
|
|
// the first bit of the first data byte is lost while reading
|
|
// this bit maybe incorrect
|
|
/*-----------------------------------------------------------------------*/
|
|
SCCMN50M_Shift_Msg(bReadBuffer, ulBytesRead);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// copy received bytes to Smartcard Reply Buffer
|
|
/*-----------------------------------------------------------------------*/
|
|
MemCpy(pSmartcardExtension->SmartcardReply.Buffer,
|
|
pSmartcardExtension->SmartcardReply.BufferSize,
|
|
bReadBuffer,
|
|
ulBytesRead);
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = ulBytesRead;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// copy received bytes to IoReply Buffer
|
|
/*-----------------------------------------------------------------------*/
|
|
MemCpy(pSmartcardExtension->IoRequest.ReplyBuffer,
|
|
pSmartcardExtension->IoRequest.ReplyBufferLength,
|
|
pSmartcardExtension->SmartcardReply.Buffer,
|
|
ulBytesRead);
|
|
|
|
*(pSmartcardExtension->IoRequest.Information) = ulBytesRead;
|
|
|
|
|
|
ExitTransmit2WBP:
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!Transmit2WBP: Exit\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
VOID
|
|
SCCMN50M_Shift_Msg (PUCHAR pbBuffer,
|
|
ULONG ulMsgLen)
|
|
{
|
|
UCHAR bTmp1, bTmp2;
|
|
int i;
|
|
|
|
for (i=(int)ulMsgLen-1; i>=0; i--)
|
|
{
|
|
bTmp1=(BYTE)((pbBuffer[i] >> 7) & 0x01); /* bTmp1 = bit 7 naechstes byte */
|
|
if (i+1 != (int)ulMsgLen)
|
|
{
|
|
bTmp2=(BYTE)((pbBuffer[i+1] << 1) | bTmp1);
|
|
pbBuffer[i+1] = bTmp2;
|
|
}
|
|
}
|
|
|
|
pbBuffer[0] = (BYTE)(pbBuffer[0] << 1);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
Reset Card 4442
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_ResetCard2WBP(IN PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
BYTE bBuffer[10];
|
|
ULONG ulBytesRead;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// Enter Card Reset
|
|
/*-----------------------------------------------------------------------*/
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!ResetCard2WBP: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// bTxControlByte = 0;
|
|
// bTxLengthByte = 0;
|
|
// bRxControlByte = RESET_CARD;
|
|
// bRxLengthByte = 5;
|
|
/*-----------------------------------------------------------------------*/
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
0, // bTxControlByte
|
|
0, // bTxLengthByte
|
|
COLD_RESET, // bRxControlByte
|
|
5); // bRxLengthByte
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// write data to card
|
|
/*-----------------------------------------------------------------------*/
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
0,
|
|
NULL);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitResetCard2WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// read CardMan Header
|
|
/*-----------------------------------------------------------------------*/
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,
|
|
2, &ulBytesRead, bBuffer, sizeof(bBuffer));
|
|
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitResetCard2WBP;
|
|
}
|
|
|
|
if (bBuffer[1] != 5)
|
|
{
|
|
status = !STATUS_SUCCESS;
|
|
goto ExitResetCard2WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// read ATR
|
|
/*-----------------------------------------------------------------------*/
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,
|
|
5, &ulBytesRead, bBuffer, sizeof(bBuffer));
|
|
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitResetCard2WBP;
|
|
}
|
|
|
|
SmartcardDebug(DEBUG_ATR,("%s!Card Reset ATR : %02x %02x %02x %02x\n",
|
|
DRIVER_NAME,bBuffer[0],bBuffer[1],bBuffer[2],bBuffer[3]));
|
|
|
|
ExitResetCard2WBP:
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!ResetCard2WBP: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_Transmit3WBP(PSMARTCARD_EXTENSION pSmartcardExtension)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
UCHAR bWriteBuffer [128];
|
|
UCHAR bReadBuffer [128];
|
|
UCHAR bTxControlByte;
|
|
UCHAR bTxLengthByte;
|
|
UCHAR bRxControlByte;
|
|
UCHAR bRxLengthByte;
|
|
ULONG ulBytesToWrite;
|
|
ULONG ulBytesToRead;
|
|
ULONG ulBitsToWrite;
|
|
ULONG ulBitsToRead;
|
|
ULONG ulBytesRead;
|
|
// ULONG ulBitsRead;
|
|
ULONG ulBytesStillToRead;
|
|
ULONG ulMaxIFSD;
|
|
PCHAR pbInData;
|
|
|
|
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!Transmit3WBP: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
// DBGBreakPoint();
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/** Power smartcard - if smartcard was removed and reinserted **/
|
|
/*-----------------------------------------------------------------------*/
|
|
if (pSmartcardExtension->ReaderExtension->SyncParameters.fCardPowerRequested == TRUE)
|
|
{
|
|
status = SCCMN50M_SyncCardPowerOn (pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitTransmit3WBP;
|
|
}
|
|
}
|
|
|
|
|
|
pbInData = pSmartcardExtension->IoRequest.RequestBuffer + sizeof(SYNC_TRANSFER);
|
|
ulBitsToWrite = ((PSYNC_TRANSFER)(pSmartcardExtension->IoRequest.RequestBuffer))->ulSyncBitsToWrite;
|
|
ulBitsToRead = ((PSYNC_TRANSFER)(pSmartcardExtension->IoRequest.RequestBuffer))->ulSyncBitsToRead;
|
|
ulBytesToWrite = ulBitsToWrite/8;
|
|
ulBytesToRead = ulBitsToRead/8 + (ulBitsToRead % 8 ? 1 : 0);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// check buffer sizes
|
|
/*-----------------------------------------------------------------------*/
|
|
ulMaxIFSD = ATTR_MAX_IFSD_CARDMAN_II;
|
|
|
|
|
|
if (ulBytesToRead > ulMaxIFSD ||
|
|
ulBytesToRead > pSmartcardExtension->SmartcardReply.BufferSize)
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitTransmit3WBP;
|
|
}
|
|
|
|
if (ulBytesToWrite > pSmartcardExtension->SmartcardRequest.BufferSize)
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitTransmit3WBP;
|
|
}
|
|
|
|
pSmartcardExtension->SmartcardRequest.BufferLength = ulBytesToWrite;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// copy data to the Smartcard Request Buffer
|
|
/*-----------------------------------------------------------------------*/
|
|
MemCpy(pSmartcardExtension->SmartcardRequest.Buffer,
|
|
pSmartcardExtension->SmartcardRequest.BufferSize,
|
|
pbInData,
|
|
ulBytesToWrite);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// copy data to the write buffer
|
|
/*-----------------------------------------------------------------------*/
|
|
MemCpy(bWriteBuffer,
|
|
sizeof(bWriteBuffer),
|
|
pSmartcardExtension->SmartcardRequest.Buffer,
|
|
ulBytesToWrite);
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// set SYNC protocol flag for CardMan
|
|
/*-----------------------------------------------------------------------*/
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_SYN);
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// build cardman header
|
|
/*-----------------------------------------------------------------------*/
|
|
bTxControlByte = SCCMN50M_CalcTxControlByte(pSmartcardExtension,ulBitsToWrite);
|
|
bTxLengthByte = SCCMN50M_CalcTxLengthByte(pSmartcardExtension,ulBitsToWrite);
|
|
bRxControlByte = SCCMN50M_CalcRxControlByte(pSmartcardExtension,ulBitsToRead);
|
|
bRxLengthByte = SCCMN50M_CalcRxLengthByte(pSmartcardExtension,ulBitsToRead);
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,
|
|
bTxControlByte,
|
|
bTxLengthByte,
|
|
bRxControlByte,
|
|
bRxLengthByte);
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/** write data to card **/
|
|
/*-----------------------------------------------------------------------*/
|
|
status = SCCMN50M_WriteCardMan (pSmartcardExtension,
|
|
ulBytesToWrite,
|
|
bWriteBuffer);
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransmit3WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
/** read CardMan Header **/
|
|
/*-----------------------------------------------------------------------*/
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer));
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransmit3WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// calc data length to receive
|
|
/*-----------------------------------------------------------------------*/
|
|
ulBytesStillToRead = (ULONG)(bReadBuffer[1]);
|
|
if (bReadBuffer[0] & RECEIVE_A8)
|
|
ulBytesStillToRead += 256;
|
|
|
|
|
|
// read data from card
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,
|
|
ulBytesStillToRead,
|
|
&ulBytesRead,
|
|
bReadBuffer,
|
|
sizeof(bReadBuffer));
|
|
if (NT_ERROR(status))
|
|
{
|
|
goto ExitTransmit3WBP;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// calculate data length in bits - this value is not used
|
|
/*-----------------------------------------------------------------------*/
|
|
// ulBitsRead = ((ulBytesRead-1) * 8) + ((ulBitsToRead-1 ) & 0x00000007) + 1;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// shift the bits in the last byte to the correct position
|
|
/*-----------------------------------------------------------------------*/
|
|
bReadBuffer[ulBytesRead-1] >>= (7 - ((ulBitsToRead-1) & 0x00000007));
|
|
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// copy received bytes to Smartcard Reply Buffer
|
|
/*-----------------------------------------------------------------------*/
|
|
MemCpy(pSmartcardExtension->SmartcardReply.Buffer,
|
|
pSmartcardExtension->SmartcardReply.BufferSize,
|
|
bReadBuffer,
|
|
ulBytesRead);
|
|
|
|
pSmartcardExtension->SmartcardReply.BufferLength = ulBytesRead;
|
|
|
|
/*-----------------------------------------------------------------------*/
|
|
// copy received bytes to IoReply Buffer
|
|
// this Memcpy should respond to SmartcardRawReply function
|
|
/*-----------------------------------------------------------------------*/
|
|
MemCpy(pSmartcardExtension->IoRequest.ReplyBuffer,
|
|
pSmartcardExtension->IoRequest.ReplyBufferLength,
|
|
pSmartcardExtension->SmartcardReply.Buffer,
|
|
ulBytesRead);
|
|
|
|
*pSmartcardExtension->IoRequest.Information = ulBytesRead;
|
|
|
|
|
|
ExitTransmit3WBP:
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!Transmit3WBP: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
This function powers a synchronous smart card.
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
NTSTATUS
|
|
SCCMN50M_UseSyncStrategy (
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension,
|
|
OUT PULONG pulAtrLength,
|
|
OUT PUCHAR pbAtrBuffer,
|
|
IN ULONG ulAtrBufferSize
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
NTSTATUS DebugStatus;
|
|
UCHAR bReadBuffer[SCARD_ATR_LENGTH];
|
|
ULONG ulBytesRead;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!UseSyncStrategy: Enter\n",
|
|
DRIVER_NAME)
|
|
);
|
|
//DBGBreakPoint();
|
|
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,SYNC_ATR_RX_CONTROL,ATR_LEN_SYNC);
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.ResetDelay = SYNC_RESET_DELAY;
|
|
pSmartcardExtension->ReaderExtension->CardManConfig.CardStopBits = 0x02;
|
|
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS);
|
|
SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY );
|
|
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_SYN);
|
|
|
|
status = SCCMN50M_ResyncCardManII(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitPowerSynchronousCard;
|
|
}
|
|
|
|
|
|
// write config + header
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitPowerSynchronousCard;
|
|
}
|
|
|
|
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
// read state and length
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,bReadBuffer,sizeof(bReadBuffer));
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitPowerSynchronousCard;
|
|
}
|
|
|
|
if (bReadBuffer[1] < MIN_ATR_LEN )
|
|
{
|
|
// read all remaining bytes from the CardMan
|
|
DebugStatus = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],&ulBytesRead,bReadBuffer,sizeof(bReadBuffer));
|
|
status = STATUS_UNRECOGNIZED_MEDIA;
|
|
goto ExitPowerSynchronousCard;
|
|
}
|
|
|
|
if (bReadBuffer[1] > ulAtrBufferSize)
|
|
{
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
goto ExitPowerSynchronousCard;
|
|
}
|
|
|
|
// read ATR
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,bReadBuffer[1],pulAtrLength,pbAtrBuffer,ulAtrBufferSize);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitPowerSynchronousCard;
|
|
}
|
|
|
|
if (pbAtrBuffer[0] == 0x00 ||
|
|
pbAtrBuffer[0] == 0xff )
|
|
{
|
|
status = STATUS_UNRECOGNIZED_MEDIA;
|
|
goto ExitPowerSynchronousCard;
|
|
}
|
|
pSmartcardExtension->ReaderExtension->fRawModeNecessary = TRUE;
|
|
|
|
|
|
ExitPowerSynchronousCard:
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!UseSyncStrategy: Exit %lx\n",
|
|
DRIVER_NAME,status)
|
|
);
|
|
SCCMN50M_ClearSCRControlFlags(pSmartcardExtension,IGNORE_PARITY | CM2_GET_ATR);
|
|
SCCMN50M_ClearCardManHeader(pSmartcardExtension);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
Routine Description:
|
|
|
|
This function checks if the inserted card is a synchronous one
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
*****************************************************************************/
|
|
BOOLEAN
|
|
SCCMN50M_IsAsynchronousSmartCard(
|
|
IN PSMARTCARD_EXTENSION pSmartcardExtension
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
UCHAR ReadBuffer[3];
|
|
ULONG ulBytesRead;
|
|
BOOLEAN fIsAsynchronousSmartCard = TRUE;
|
|
UCHAR abATR[33];
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!IsAsynchronousSmartcard: Enter \n",
|
|
DRIVER_NAME)
|
|
);
|
|
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = 200;
|
|
|
|
// 3MHz smart card ?
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,0,1);
|
|
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS);
|
|
|
|
SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY | CM2_GET_ATR);
|
|
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_3MHZ);
|
|
|
|
// write config + header
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitIsAsynchronousSmartCard;
|
|
}
|
|
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
|
|
// read state and length
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer));
|
|
if (status == STATUS_SUCCESS &&
|
|
ReadBuffer[1] == 0x01 )
|
|
{
|
|
goto ExitIsAsynchronousSmartCard;
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------
|
|
// power off card
|
|
// ---------------------------------------
|
|
status = SCCMN50M_PowerOff(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitIsAsynchronousSmartCard;
|
|
}
|
|
|
|
|
|
// 5MHz smart card ?
|
|
SCCMN50M_SetCardManHeader(pSmartcardExtension,0,0,0,1);
|
|
|
|
SCCMN50M_ClearCardControlFlags(pSmartcardExtension,ALL_FLAGS);
|
|
|
|
SCCMN50M_SetSCRControlFlags(pSmartcardExtension,CARD_POWER| IGNORE_PARITY | CM2_GET_ATR);
|
|
|
|
SCCMN50M_SetCardControlFlags(pSmartcardExtension,ENABLE_5MHZ);
|
|
|
|
// write config + header
|
|
status = SCCMN50M_WriteCardMan(pSmartcardExtension,0,NULL);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitIsAsynchronousSmartCard;
|
|
}
|
|
|
|
pSmartcardExtension->ReaderExtension->ToRHConfig = FALSE;
|
|
|
|
// read state and length
|
|
status = SCCMN50M_ReadCardMan(pSmartcardExtension,2,&ulBytesRead,ReadBuffer,sizeof(ReadBuffer));
|
|
if (status == STATUS_SUCCESS &&
|
|
ReadBuffer[1] == 0x01 )
|
|
{
|
|
goto ExitIsAsynchronousSmartCard;
|
|
}
|
|
|
|
// now we assume that it is a synchronous smart card
|
|
fIsAsynchronousSmartCard = FALSE;
|
|
// ---------------------------------------
|
|
// power off card
|
|
// ---------------------------------------
|
|
status = SCCMN50M_PowerOff(pSmartcardExtension);
|
|
if (status != STATUS_SUCCESS)
|
|
{
|
|
goto ExitIsAsynchronousSmartCard;
|
|
}
|
|
|
|
|
|
|
|
ExitIsAsynchronousSmartCard:
|
|
pSmartcardExtension->ReaderExtension->SerialConfigData.Timeouts.ReadTotalTimeoutConstant = DEFAULT_READ_TOTAL_TIMEOUT_CONSTANT;
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "%s!IsAsynchronousSmartcard: Exit \n",
|
|
DRIVER_NAME)
|
|
);
|
|
return fIsAsynchronousSmartCard;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
* History:
|
|
* $Log: sccmcb.c $
|
|
* Revision 1.7 2001/01/22 08:39:41 WFrischauf
|
|
* No comment given
|
|
*
|
|
* Revision 1.6 2000/09/25 10:46:22 WFrischauf
|
|
* No comment given
|
|
*
|
|
* Revision 1.5 2000/08/24 09:05:44 TBruendl
|
|
* No comment given
|
|
*
|
|
* Revision 1.4 2000/08/16 08:24:04 TBruendl
|
|
* warning :uninitialized memory removed
|
|
*
|
|
* Revision 1.3 2000/07/28 09:24:12 TBruendl
|
|
* Changes for OMNIKEY on Whistler CD
|
|
*
|
|
* Revision 1.16 2000/06/27 11:56:28 TBruendl
|
|
* workaraound for SAMOR smart cards with invalid ATR (ITSEC)
|
|
*
|
|
* Revision 1.15 2000/06/08 10:08:47 TBruendl
|
|
* bug fix : warm reset for ScfW
|
|
*
|
|
* Revision 1.14 2000/05/23 09:58:26 TBruendl
|
|
* OMNIKEY 3.0.0.1
|
|
*
|
|
* Revision 1.13 2000/04/13 08:07:22 TBruendl
|
|
* PPS bug fix for SCfW
|
|
*
|
|
* Revision 1.12 2000/04/04 07:52:18 TBruendl
|
|
* problem with the new WfsC fixed
|
|
*
|
|
* Revision 1.11 2000/03/03 09:50:50 TBruendl
|
|
* No comment given
|
|
*
|
|
* Revision 1.10 2000/03/01 09:32:04 TBruendl
|
|
* R02.20.0
|
|
*
|
|
* Revision 1.9 2000/01/04 10:40:33 TBruendl
|
|
* bug fix: status instead of DebugStatus used
|
|
*
|
|
* Revision 1.8 1999/12/16 14:10:16 TBruendl
|
|
* After transparent mode has been left, the status is read from the CardMan to be sure that
|
|
* the new settings are effective.
|
|
*
|
|
* Revision 1.6 1999/12/13 07:55:38 TBruendl
|
|
* Bug fix for P+ druing initialization
|
|
* PTS for 4.9 mhz smartcards added
|
|
*
|
|
* Revision 1.5 1999/11/04 07:53:21 WFrischauf
|
|
* bug fixes due to error reports 2 - 7
|
|
*
|
|
* Revision 1.4 1999/07/12 12:49:04 TBruendl
|
|
* Bug fix: Resync after GET_DEVICE_DESCRIPTION
|
|
* Power On SLE4428
|
|
*
|
|
* Revision 1.3 1999/06/10 09:03:57 TBruendl
|
|
* No comment given
|
|
*
|
|
* Revision 1.2 1999/02/25 10:12:22 TBruendl
|
|
* No comment given
|
|
*
|
|
* Revision 1.1 1999/02/02 13:34:37 TBruendl
|
|
* This is the first release (R01.00) of the IFD handler for CardMan running under NT5.0.
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
|