907 lines
28 KiB
C
907 lines
28 KiB
C
/*++
|
|
|
|
Copyright (c) 1997 - 1999 SCM Microsystems, Inc.
|
|
|
|
Module Name:
|
|
|
|
PscrCB.c
|
|
|
|
Abstract:
|
|
|
|
callback handler for PSCR.xxx driver
|
|
|
|
Author:
|
|
|
|
Andreas Straub
|
|
|
|
Environment:
|
|
|
|
Win 95 Sys... calls are resolved by Pscr95Wrap.asm functions and
|
|
Pscr95Wrap.h macros, resp.
|
|
|
|
NT 4.0 Sys... functions resolved by PscrNTWrap.c functions and
|
|
PscrNTWrap.h macros, resp.
|
|
|
|
Revision History:
|
|
|
|
Andreas Straub 8/18/1997 1.00 Initial Version
|
|
Andreas Straub 9/24/1997 1.02 Flush Interface if card tracking
|
|
requested
|
|
|
|
--*/
|
|
|
|
#if defined( SMCLIB_VXD )
|
|
|
|
#include <Pscr95.h>
|
|
|
|
#else // SMCLIB_VXD
|
|
|
|
#include <PscrNT.h>
|
|
|
|
#endif // SMCLIB_VXD
|
|
|
|
|
|
#include <PscrRdWr.h>
|
|
#include <PscrCmd.h>
|
|
#include <PscrCB.h>
|
|
|
|
|
|
NTSTATUS
|
|
CBCardPower(
|
|
PSMARTCARD_EXTENSION SmartcardExtension
|
|
)
|
|
/*++
|
|
|
|
CBCardPower:
|
|
callback handler for SMCLIB RDF_CARD_POWER
|
|
|
|
Arguments:
|
|
SmartcardExtension context of call
|
|
|
|
Return Value:
|
|
STATUS_SUCCESS
|
|
STATUS_NO_MEDIA
|
|
STATUS_TIMEOUT
|
|
STATUS_BUFFER_TOO_SMALL
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NTStatus = STATUS_SUCCESS;
|
|
UCHAR ATRBuffer[ ATR_SIZE ], TLVList[16];
|
|
ULONG Command,
|
|
ATRLength;
|
|
PREADER_EXTENSION ReaderExtension;
|
|
BYTE CardState;
|
|
#if DBG || DEBUG
|
|
static PCHAR request[] = { "PowerDown", "ColdReset", "WarmReset" };
|
|
#endif
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBCardPower: Enter, Request = %s\n",
|
|
request[SmartcardExtension->MinorIoControlCode])
|
|
);
|
|
|
|
ReaderExtension = SmartcardExtension->ReaderExtension;
|
|
|
|
//
|
|
// update actual power state
|
|
//
|
|
Command = SmartcardExtension->MinorIoControlCode;
|
|
|
|
switch ( Command )
|
|
{
|
|
case SCARD_WARM_RESET:
|
|
|
|
// if the card was not powerd, fall thru to cold reset
|
|
if( SmartcardExtension->ReaderCapabilities.CurrentState >
|
|
SCARD_SWALLOWED )
|
|
{
|
|
// reset the card
|
|
ATRLength = ATR_SIZE;
|
|
NTStatus = CmdReset(
|
|
ReaderExtension,
|
|
ReaderExtension->Device,
|
|
TRUE, // warm reset
|
|
ATRBuffer,
|
|
&ATRLength
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
// warm reset not possible because card was not powerd
|
|
case SCARD_COLD_RESET:
|
|
|
|
// reset the card
|
|
ATRLength = ATR_SIZE;
|
|
NTStatus = CmdReset(
|
|
ReaderExtension,
|
|
ReaderExtension->Device,
|
|
FALSE, // cold reset
|
|
ATRBuffer,
|
|
&ATRLength
|
|
);
|
|
break;
|
|
|
|
case SCARD_POWER_DOWN:
|
|
ATRLength = 0;
|
|
NTStatus = CmdDeactivate(
|
|
ReaderExtension,
|
|
ReaderExtension->Device
|
|
);
|
|
|
|
// discard old card status
|
|
CardState = CBGetCardState(SmartcardExtension);
|
|
CBUpdateCardState(SmartcardExtension, CardState, FALSE);
|
|
break;
|
|
}
|
|
|
|
if (NT_SUCCESS(NTStatus)) {
|
|
|
|
//
|
|
// Set the 'restart of work waiting time' counter for T=0
|
|
// This will send a WTX request for n NULL bytes received
|
|
//
|
|
TLVList[0] = TAG_SET_NULL_BYTES;
|
|
TLVList[1] = 1;
|
|
TLVList[2] = 0x05;
|
|
|
|
NTStatus = CmdSetInterfaceParameter(
|
|
ReaderExtension,
|
|
DEVICE_READER,
|
|
TLVList,
|
|
3
|
|
);
|
|
}
|
|
|
|
ASSERT(NT_SUCCESS(NTStatus));
|
|
|
|
// finish the request
|
|
if( NT_SUCCESS( NTStatus ))
|
|
{
|
|
// update all neccessary data if an ATR was received
|
|
if( ATRLength > 2 )
|
|
{
|
|
//
|
|
// the lib expects only the ATR, so we skip the
|
|
// 900x from the reader
|
|
//
|
|
ATRLength -= 2;
|
|
|
|
// copy ATR to user buffer buffer
|
|
if( ATRLength <= SmartcardExtension->IoRequest.ReplyBufferLength )
|
|
{
|
|
SysCopyMemory(
|
|
SmartcardExtension->IoRequest.ReplyBuffer,
|
|
ATRBuffer,
|
|
ATRLength
|
|
);
|
|
*SmartcardExtension->IoRequest.Information = ATRLength;
|
|
}
|
|
else
|
|
{
|
|
NTStatus = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
// copy ATR to card capability buffer
|
|
if( ATRLength <= MAXIMUM_ATR_LENGTH )
|
|
{
|
|
SysCopyMemory(
|
|
SmartcardExtension->CardCapabilities.ATR.Buffer,
|
|
ATRBuffer,
|
|
ATRLength
|
|
);
|
|
|
|
SmartcardExtension->CardCapabilities.ATR.Length =
|
|
( UCHAR )ATRLength;
|
|
|
|
// let the lib update the card capabilities
|
|
NTStatus = SmartcardUpdateCardCapabilities(
|
|
SmartcardExtension
|
|
);
|
|
}
|
|
else
|
|
{
|
|
NTStatus = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !NT_SUCCESS( NTStatus ))
|
|
{
|
|
switch( NTStatus )
|
|
{
|
|
case STATUS_NO_MEDIA:
|
|
case STATUS_BUFFER_TOO_SMALL:
|
|
break;
|
|
|
|
case STATUS_TIMEOUT:
|
|
NTStatus = STATUS_IO_TIMEOUT;
|
|
break;
|
|
|
|
default:
|
|
NTStatus = STATUS_UNRECOGNIZED_MEDIA;
|
|
break;
|
|
}
|
|
}
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBCardPower: Exit (%lx)\n", NTStatus )
|
|
);
|
|
|
|
return( NTStatus );
|
|
}
|
|
|
|
NTSTATUS
|
|
CBSetProtocol(
|
|
PSMARTCARD_EXTENSION SmartcardExtension
|
|
)
|
|
|
|
/*++
|
|
|
|
CBSetProtocol:
|
|
callback handler for SMCLIB RDF_SET_PROTOCOL
|
|
|
|
Arguments:
|
|
SmartcardExtension context of call
|
|
|
|
Return Value:
|
|
STATUS_SUCCESS
|
|
STATUS_NO_MEDIA
|
|
STATUS_TIMEOUT
|
|
STATUS_BUFFER_TOO_SMALL
|
|
STATUS_INVALID_DEVICE_STATE
|
|
STATUS_INVALID_DEVICE_REQUEST
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NTStatus = STATUS_PENDING;
|
|
USHORT SCLibProtocol;
|
|
UCHAR TLVList[ TLV_BUFFER_SIZE ];
|
|
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
|
|
|
|
if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC) {
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBSetProtocol: Enter\n" )
|
|
);
|
|
|
|
SCLibProtocol = ( USHORT )( SmartcardExtension->MinorIoControlCode );
|
|
|
|
if (SCLibProtocol & (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1))
|
|
{
|
|
//
|
|
// setup the TLV list for the Set Interface Parameter List
|
|
//
|
|
TLVList[ 0 ] = TAG_ICC_PROTOCOLS;
|
|
TLVList[ 1 ] = 0x01;
|
|
TLVList[ 2 ] =
|
|
(SCLibProtocol & SCARD_PROTOCOL_T1 ? PSCR_PROTOCOL_T1 : PSCR_PROTOCOL_T0);
|
|
|
|
// do the PTS
|
|
NTStatus = CmdSetInterfaceParameter(
|
|
ReaderExtension,
|
|
ReaderExtension->Device,
|
|
TLVList,
|
|
3 // size of list
|
|
);
|
|
|
|
} else {
|
|
|
|
// we don't support other modi
|
|
NTStatus = STATUS_INVALID_DEVICE_REQUEST;
|
|
}
|
|
|
|
// if protocol selection failed, prevent from calling invalid protocols
|
|
if( NT_SUCCESS( NTStatus ))
|
|
{
|
|
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
|
|
SCLibProtocol = (SCLibProtocol & SCARD_PROTOCOL_T1 &
|
|
SmartcardExtension->CardCapabilities.Protocol.Supported) ?
|
|
SCARD_PROTOCOL_T1 :
|
|
SCARD_PROTOCOL_T0;
|
|
}
|
|
else
|
|
{
|
|
SCLibProtocol = SCARD_PROTOCOL_UNDEFINED;
|
|
}
|
|
|
|
// Return the selected protocol to the caller.
|
|
SmartcardExtension->CardCapabilities.Protocol.Selected = SCLibProtocol;
|
|
*( PULONG )( SmartcardExtension->IoRequest.ReplyBuffer ) = SCLibProtocol;
|
|
*( SmartcardExtension->IoRequest.Information ) = sizeof( ULONG );
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBSetProtocol: Exit (%lx)\n", NTStatus )
|
|
);
|
|
|
|
return ( NTStatus );
|
|
}
|
|
|
|
NTSTATUS
|
|
CBTransmit(
|
|
PSMARTCARD_EXTENSION SmartcardExtension
|
|
)
|
|
/*++
|
|
|
|
CBTransmit:
|
|
callback handler for SMCLIB RDF_TRANSMIT
|
|
|
|
Arguments:
|
|
SmartcardExtension context of call
|
|
|
|
Return Value:
|
|
STATUS_SUCCESS
|
|
STATUS_NO_MEDIA
|
|
STATUS_TIMEOUT
|
|
STATUS_INVALID_DEVICE_REQUEST
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NTStatus = STATUS_SUCCESS;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBTransmit: Enter\n" )
|
|
);
|
|
|
|
// dispatch on the selected protocol
|
|
switch( SmartcardExtension->CardCapabilities.Protocol.Selected )
|
|
{
|
|
case SCARD_PROTOCOL_T0:
|
|
NTStatus = CBT0Transmit( SmartcardExtension );
|
|
break;
|
|
|
|
case SCARD_PROTOCOL_T1:
|
|
NTStatus = CBT1Transmit( SmartcardExtension );
|
|
break;
|
|
|
|
case SCARD_PROTOCOL_RAW:
|
|
NTStatus = CBRawTransmit( SmartcardExtension );
|
|
break;
|
|
|
|
default:
|
|
NTStatus = STATUS_INVALID_DEVICE_REQUEST;
|
|
break;
|
|
}
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBTransmit: Exit (%lx)\n", NTStatus )
|
|
);
|
|
|
|
return( NTStatus );
|
|
}
|
|
|
|
NTSTATUS
|
|
CBRawTransmit(
|
|
PSMARTCARD_EXTENSION SmartcardExtension
|
|
)
|
|
/*++
|
|
|
|
CBRawTransmit:
|
|
finishes the callback RDF_TRANSMIT for the RAW protocol
|
|
|
|
Arguments:
|
|
SmartcardExtension context of call
|
|
|
|
Return Value:
|
|
STATUS_SUCCESS
|
|
STATUS_NO_MEDIA
|
|
STATUS_TIMEOUT
|
|
STATUS_INVALID_DEVICE_REQUEST
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NTStatus = STATUS_SUCCESS;
|
|
UCHAR TLVList[ TLV_BUFFER_SIZE ],
|
|
Val,
|
|
Len;
|
|
ULONG TLVListLen;
|
|
PREADER_EXTENSION ReaderExtension;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBRawTransmit: Enter\n" )
|
|
);
|
|
|
|
ReaderExtension = SmartcardExtension->ReaderExtension;
|
|
//
|
|
// read the status file of ICC1 from the reader
|
|
//
|
|
TLVListLen = TLV_BUFFER_SIZE;
|
|
NTStatus = CmdReadStatusFile(
|
|
ReaderExtension,
|
|
ReaderExtension->Device,
|
|
TLVList,
|
|
&TLVListLen
|
|
);
|
|
|
|
//
|
|
// check the active protocol of the reader
|
|
//
|
|
if( NT_SUCCESS( NTStatus ))
|
|
{
|
|
NTStatus = CmdGetTagValue(
|
|
TAG_ICC_PROTOCOLS,
|
|
TLVList,
|
|
TLVListLen,
|
|
&Len,
|
|
( PVOID ) &Val
|
|
);
|
|
|
|
// execute the active protocol
|
|
if( NT_SUCCESS( NTStatus ))
|
|
{
|
|
|
|
// translate the actual protocol to a value the lib can understand
|
|
switch( Val )
|
|
{
|
|
case PSCR_PROTOCOL_T0:
|
|
NTStatus = CBT0Transmit( SmartcardExtension );
|
|
break;
|
|
case PSCR_PROTOCOL_T1:
|
|
NTStatus = CBT1Transmit( SmartcardExtension );
|
|
break;
|
|
default:
|
|
NTStatus = STATUS_UNSUCCESSFUL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBRawTransmit: Exit (%lx)\n", NTStatus )
|
|
);
|
|
return ( NTStatus );
|
|
}
|
|
|
|
NTSTATUS
|
|
CBT1Transmit(
|
|
PSMARTCARD_EXTENSION SmartcardExtension
|
|
)
|
|
/*++
|
|
|
|
CBT1Transmit:
|
|
finishes the callback RDF_TRANSMIT for the T1 protocol
|
|
|
|
Arguments:
|
|
SmartcardExtension context of call
|
|
|
|
Return Value:
|
|
STATUS_SUCCESS
|
|
STATUS_NO_MEDIA
|
|
STATUS_TIMEOUT
|
|
STATUS_INVALID_DEVICE_REQUEST
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NTStatus = STATUS_SUCCESS;
|
|
ULONG IOBytes;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBT1Transmit: Enter\n" )
|
|
);
|
|
//
|
|
// use the lib support to construct the T=1 packets
|
|
//
|
|
do {
|
|
//
|
|
// no header for the T=1 protocol
|
|
//
|
|
SmartcardExtension->SmartcardRequest.BufferLength = 0;
|
|
//
|
|
// SCM-TM: Siemens 4440 accepts only NAD=0!!!
|
|
//
|
|
SmartcardExtension->T1.NAD = 0;
|
|
//
|
|
// let the lib setup the T=1 APDU & check for errors
|
|
//
|
|
NTStatus = SmartcardT1Request( SmartcardExtension );
|
|
if( NT_SUCCESS( NTStatus ))
|
|
{
|
|
|
|
// send command (don't calculate LRC because CRC may be used!)
|
|
IOBytes = 0;
|
|
NTStatus = PscrWriteDirect(
|
|
SmartcardExtension->ReaderExtension,
|
|
SmartcardExtension->SmartcardRequest.Buffer,
|
|
SmartcardExtension->SmartcardRequest.BufferLength,
|
|
&IOBytes
|
|
);
|
|
//
|
|
// extend the timeout if a Wtx request was sent by the card. if the
|
|
// card responds before the waiting time extension expires, the data are
|
|
// buffered in the reader. A delay without polling the reader status
|
|
// slows down the performance of the driver, but wtx is an exeption,
|
|
// not the rule.
|
|
//
|
|
if (SmartcardExtension->T1.Wtx)
|
|
{
|
|
SysDelay(
|
|
(( SmartcardExtension->T1.Wtx *
|
|
SmartcardExtension->CardCapabilities.T1.BWT + 999L )/
|
|
1000L)
|
|
);
|
|
|
|
}
|
|
|
|
// get response
|
|
SmartcardExtension->SmartcardReply.BufferLength = 0;
|
|
NTStatus = PscrRead(
|
|
SmartcardExtension->ReaderExtension,
|
|
SmartcardExtension->SmartcardReply.Buffer,
|
|
MAX_T1_BLOCK_SIZE,
|
|
&SmartcardExtension->SmartcardReply.BufferLength
|
|
);
|
|
|
|
// if PscrRead detects an LRC error, ignore it (maybe CRC used)
|
|
if( NTStatus == STATUS_CRC_ERROR )
|
|
{
|
|
NTStatus = STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// We even continue if the prev. read failed.
|
|
// We let the smart card library continue, because it might
|
|
// send a resynch. request in case of a timeout
|
|
//
|
|
NTStatus = SmartcardT1Reply( SmartcardExtension );
|
|
}
|
|
|
|
// continue if the lib wants to send the next packet
|
|
} while( NTStatus == STATUS_MORE_PROCESSING_REQUIRED );
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBT1Transmit: Exit (%lx)\n", NTStatus )
|
|
);
|
|
|
|
return ( NTStatus );
|
|
}
|
|
|
|
NTSTATUS
|
|
CBT0Transmit(
|
|
PSMARTCARD_EXTENSION SmartcardExtension
|
|
)
|
|
/*++
|
|
|
|
CBT0Transmit:
|
|
finishes the callback RDF_TRANSMIT for the T0 protocol
|
|
|
|
Arguments:
|
|
SmartcardExtension context of call
|
|
|
|
Return Value:
|
|
STATUS_SUCCESS
|
|
STATUS_NO_MEDIA
|
|
STATUS_TIMEOUT
|
|
STATUS_INVALID_DEVICE_REQUEST
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NTStatus = STATUS_SUCCESS;
|
|
PUCHAR pRequest,pReply;
|
|
ULONG IOBytes, APDULength, RequestLength;
|
|
UCHAR IOData[ MAX_T1_BLOCK_SIZE ];
|
|
UCHAR WtxReply[16];
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBT0Transmit: Enter\n" )
|
|
);
|
|
|
|
pRequest = SmartcardExtension->SmartcardRequest.Buffer;
|
|
pReply = SmartcardExtension->SmartcardReply.Buffer;
|
|
|
|
// setup the command header
|
|
pRequest[ PSCR_NAD ] =
|
|
( SmartcardExtension->ReaderExtension->Device == DEVICE_ICC1 ) ?
|
|
NAD_TO_ICC1 : NAD_TO_ICC1;
|
|
|
|
pRequest[ PSCR_PCB ] = PCB_DEFAULT;
|
|
//
|
|
// get the length of the user data packet & set the appropriate LEN
|
|
// information the complete user packet consists of a SCARD_IO_REQUEST
|
|
// structure followed by the APDU. the length of SCARD_IO_REQUEST is
|
|
// transferred in the member cbPciLength of the structure
|
|
//
|
|
APDULength = SmartcardExtension->IoRequest.RequestBufferLength;
|
|
APDULength -= ((PSCARD_IO_REQUEST) SmartcardExtension->
|
|
IoRequest.RequestBuffer)->cbPciLength;
|
|
//
|
|
// a 4 byte APDU will be patched to a 5 byte TPDU by the lib; see
|
|
// annex of the ISO
|
|
//
|
|
if( APDULength == 4 ) APDULength++;
|
|
//
|
|
// if the total length of the T1 (reader) packet is larger than 0xFF
|
|
// the extended length notation will be used
|
|
//
|
|
if( APDULength >= 0xFF )
|
|
{
|
|
pRequest[ PSCR_LEN ] = 0xFF;
|
|
pRequest[ PSCR_LEN+1 ] = HIBYTE( APDULength );
|
|
pRequest[ PSCR_LEN+2 ] = LOBYTE( APDULength );
|
|
SmartcardExtension->SmartcardRequest.BufferLength =
|
|
PSCR_EXT_PROLOGUE_LENGTH;
|
|
}
|
|
else
|
|
{
|
|
pRequest[ PSCR_LEN ] = ( UCHAR ) APDULength;
|
|
SmartcardExtension->SmartcardRequest.BufferLength =
|
|
PSCR_PROLOGUE_LENGTH;
|
|
}
|
|
|
|
// let the lib setup the T=1 APDU & check for errors
|
|
NTStatus = SmartcardT0Request( SmartcardExtension );
|
|
RequestLength = SmartcardExtension->SmartcardRequest.BufferLength;
|
|
|
|
while( NT_SUCCESS( NTStatus ))
|
|
{
|
|
// send command
|
|
IOBytes = 0;
|
|
NTStatus = PscrWrite(
|
|
SmartcardExtension->ReaderExtension,
|
|
pRequest,
|
|
RequestLength,
|
|
&IOBytes
|
|
);
|
|
|
|
// get response
|
|
if( NT_SUCCESS( NTStatus ))
|
|
{
|
|
IOBytes = 0;
|
|
NTStatus = PscrRead(
|
|
SmartcardExtension->ReaderExtension,
|
|
IOData,
|
|
MAX_T1_BLOCK_SIZE,
|
|
&IOBytes
|
|
);
|
|
|
|
// extract APDU from T=1 transport packet
|
|
if( NT_SUCCESS( NTStatus ))
|
|
{
|
|
if (IOData[ PSCR_PCB ] == WTX_REQUEST) {
|
|
|
|
WtxReply[PSCR_NAD] = NAD_TO_PSCR;
|
|
WtxReply[PSCR_PCB] = WTX_REPLY;
|
|
WtxReply[PSCR_LEN] = 1;
|
|
WtxReply[PSCR_INF] = IOData[PSCR_INF];
|
|
|
|
RequestLength = 4;
|
|
pRequest = WtxReply;
|
|
continue;
|
|
}
|
|
|
|
if( IOData[ PSCR_LEN ] == 0xFF )
|
|
{
|
|
//
|
|
// extended length byte used
|
|
//
|
|
APDULength = IOData[ PSCR_LEN + 1 ] << 8;
|
|
APDULength += IOData[ PSCR_LEN + 2 ];
|
|
|
|
SmartcardExtension->SmartcardReply.BufferLength = APDULength ;
|
|
SysCopyMemory( pReply, &IOData[ PSCR_APDU + 2 ], APDULength );
|
|
}
|
|
else
|
|
{
|
|
SmartcardExtension->SmartcardReply.BufferLength =
|
|
IOData[ PSCR_LEN ];
|
|
|
|
SysCopyMemory(
|
|
pReply,
|
|
&IOData[ PSCR_APDU ],
|
|
IOData[ PSCR_LEN ]
|
|
);
|
|
}
|
|
|
|
// let the lib evaluate the result & tansfer the data
|
|
NTStatus = SmartcardT0Reply( SmartcardExtension );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBT0Transmit: Exit (%lx)\n", NTStatus )
|
|
);
|
|
|
|
return( NTStatus );
|
|
}
|
|
|
|
NTSTATUS
|
|
CBCardTracking(
|
|
PSMARTCARD_EXTENSION SmartcardExtension
|
|
)
|
|
/*++
|
|
|
|
CBCardTracking:
|
|
callback handler for SMCLIB RDF_CARD_TRACKING. the requested event was
|
|
validated by the smclib (i.e. a card removal request will only be passed
|
|
if a card is present).
|
|
for a win95 build STATUS_PENDING will be returned without any other action.
|
|
for NT the cancel routine for the irp will be set to the drivers cancel
|
|
routine.
|
|
|
|
Arguments:
|
|
SmartcardExtension context of call
|
|
|
|
Return Value:
|
|
STATUS_PENDING
|
|
|
|
--*/
|
|
{
|
|
KIRQL CancelIrql;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBCardTracking: Enter\n" )
|
|
);
|
|
|
|
// set cancel routine
|
|
IoAcquireCancelSpinLock( &CancelIrql );
|
|
|
|
IoSetCancelRoutine(
|
|
SmartcardExtension->OsData->NotificationIrp,
|
|
PscrCancel
|
|
);
|
|
|
|
IoReleaseCancelSpinLock( CancelIrql );
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBCardTracking: Exit \n" )
|
|
);
|
|
|
|
return( STATUS_PENDING );
|
|
}
|
|
|
|
VOID
|
|
CBUpdateCardState(
|
|
PSMARTCARD_EXTENSION SmartcardExtension,
|
|
UCHAR IccState,
|
|
BOOLEAN SystemWakeUp
|
|
)
|
|
{
|
|
ULONG oldState;
|
|
KIRQL currentIrql, irql;
|
|
|
|
KeAcquireSpinLock(
|
|
&SmartcardExtension->OsData->SpinLock,
|
|
&irql
|
|
);
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBUpdateCardState: Enter \n" )
|
|
);
|
|
|
|
oldState =
|
|
(SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT ?
|
|
SCARD_PRESENT : SCARD_ABSENT);
|
|
|
|
SmartcardExtension->ReaderCapabilities.CurrentState =
|
|
(IccState == PSCR_ICC_PRESENT ? SCARD_PRESENT : SCARD_ABSENT);
|
|
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
( "PSCR!CBUpdateCardState: Smart card %s\n",
|
|
IccState == PSCR_ICC_PRESENT ? "inserted" : "removed")
|
|
);
|
|
|
|
IoAcquireCancelSpinLock( ¤tIrql );
|
|
|
|
if( SmartcardExtension->OsData->NotificationIrp != NULL && (
|
|
SystemWakeUp && (
|
|
oldState == SCARD_PRESENT ||
|
|
SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_PRESENT) ||
|
|
SmartcardExtension->ReaderCapabilities.CurrentState != oldState)) {
|
|
|
|
PIRP notificationIrp = InterlockedExchangePointer(
|
|
&(SmartcardExtension->OsData->NotificationIrp),
|
|
NULL
|
|
);
|
|
|
|
IoSetCancelRoutine(
|
|
notificationIrp,
|
|
NULL
|
|
);
|
|
|
|
IoReleaseCancelSpinLock( currentIrql );
|
|
|
|
if (notificationIrp->Cancel == FALSE) {
|
|
|
|
// finish the request
|
|
notificationIrp->IoStatus.Status = STATUS_SUCCESS;
|
|
notificationIrp->IoStatus.Information = 0;
|
|
|
|
SmartcardDebug(
|
|
DEBUG_DRIVER,
|
|
( "PSCR!CBUpdateCardState: Completing Irp %lx\n",
|
|
notificationIrp)
|
|
);
|
|
|
|
IoCompleteRequest(notificationIrp, IO_NO_INCREMENT );
|
|
}
|
|
|
|
} else {
|
|
|
|
IoReleaseCancelSpinLock( currentIrql );
|
|
}
|
|
|
|
SmartcardDebug(
|
|
DEBUG_TRACE,
|
|
( "PSCR!CBUpdateCardState: Exit \n" )
|
|
);
|
|
|
|
KeReleaseSpinLock(
|
|
&SmartcardExtension->OsData->SpinLock,
|
|
irql
|
|
);
|
|
}
|
|
|
|
UCHAR
|
|
CBGetCardState(
|
|
PSMARTCARD_EXTENSION SmartcardExtension
|
|
)
|
|
/*++
|
|
|
|
CBUpdateCardState:
|
|
updates the variable CurrentState in SmartcardExtension
|
|
|
|
Arguments:
|
|
SmartcardExtension context of call
|
|
|
|
Return Value:
|
|
STATUS_SUCCESS
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS NTStatus = STATUS_SUCCESS;
|
|
UCHAR TLVList[ TLV_BUFFER_SIZE ], Val, Len;
|
|
ULONG TLVListLen;
|
|
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
|
|
|
|
// read the status file of ICC1 from the reader
|
|
TLVListLen = TLV_BUFFER_SIZE;
|
|
|
|
if( NT_SUCCESS( CmdReadStatusFile(
|
|
ReaderExtension,
|
|
ReaderExtension->Device,
|
|
TLVList,
|
|
&TLVListLen
|
|
))) {
|
|
|
|
// get reader status value
|
|
CmdGetTagValue(
|
|
TAG_READER_STATUS,
|
|
TLVList,
|
|
TLVListLen,
|
|
&Len,
|
|
( PVOID ) &Val
|
|
);
|
|
}
|
|
else
|
|
{
|
|
// IO-error is interpreted as card absent
|
|
Val = PSCR_ICC_ABSENT;
|
|
}
|
|
|
|
return Val;
|
|
}
|
|
|
|
// -------------------------------- END OF FILE ------------------------------
|
|
|
|
|