📄 uscr.c
字号:
/*++
Copyright (c) 2004 QWY MicroSystem Inc.
Module Name:
uscr.c
Abstract:
USB SmartCard Reader driver for CCID/lsCCID compatible device.
Environment:
kernel mode only
Notes:
Reference:
doc:
USB Chip/Smart Card Interface Devices
Low Speed USB Chip/Smart Card Interface Devices
code:
NTDDK\src\smartcrd
NTDDK\src\wdm\usb
Tools:
ddk
debugview
softice
sniffusb-0.13
Revision History:
4/19/2005: Adapted from the bulltlp3 DDK sample.
--*/
#include "uscr.h"
NTSTATUS
USCRPower(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS status = STATUS_SUCCESS;
ULONG Command;
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
PUCHAR replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
PULONG replyLength = &SmartcardExtension->SmartcardReply.BufferLength;
#if DBG || DEBUG
static PCHAR request[] = { "PowerDown", "ColdReset", "WarmReset" };
#endif
SmartcardDebug(
DEBUG_TRACE,
( "USCRPower: Enter, Request = %s\n",
request[SmartcardExtension->MinorIoControlCode])
);
Command = SmartcardExtension->MinorIoControlCode;
switch ( Command )
{
case SCARD_WARM_RESET:
case SCARD_COLD_RESET:
*replyLength = MAXIMUM_ATTR_STRING_LENGTH;
status = CmdPowerOn(ReaderExtension,
replyLength,
replyBuffer
);
HEXDUMP(replyBuffer,*replyLength);
if(status == STATUS_SUCCESS)
{
SmartcardExtension->CardCapabilities.ATR.Length = (UCHAR)*replyLength;
RtlCopyMemory(
SmartcardExtension->CardCapabilities.ATR.Buffer,
replyBuffer,
*replyLength
);
SmartcardExtension->CardCapabilities.PtsData.Type = PTS_TYPE_OPTIMAL;
status = SmartcardUpdateCardCapabilities(SmartcardExtension);
USCR_DumpCardCapabilities(SmartcardExtension);
}
if(status == STATUS_SUCCESS)
{
/*
RtlCopyMemory(
SmartcardExtension->IoRequest.ReplyBuffer,
replyBuffer,
*replyLength
);
*/
//In case of InversConvention,the CardCapabilities.ATR.Buffer is the result. 2005-7-23 yanglq
RtlCopyMemory(
SmartcardExtension->IoRequest.ReplyBuffer,
SmartcardExtension->CardCapabilities.ATR.Buffer,
SmartcardExtension->CardCapabilities.ATR.Length
);
*SmartcardExtension->IoRequest.Information = *replyLength;
if(SmartcardExtension->ReaderCapabilities.CurrentState < SCARD_POWERED)
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_POWERED;
}
break;
case SCARD_POWER_DOWN:
status = CmdPowerOff(
ReaderExtension
);
if (SmartcardExtension->ReaderCapabilities.CurrentState > SCARD_PRESENT)
{
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_PRESENT;
}
break;
}
SmartcardDebug(
DEBUG_TRACE,
( "USCRPower: Leave, status = %x\n",
status)
);
return status;
}
NTSTATUS
USCRSetProtocol(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS status = STATUS_SUCCESS;
USHORT newProtocol;
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
SmartcardDebug(
DEBUG_TRACE,
("USCRSetProtocol: Enter\n")
);
//only support T0 now.(ylq)
newProtocol = ( USHORT )( SmartcardExtension->MinorIoControlCode );
if (SmartcardExtension->ReaderCapabilities.CurrentState == SCARD_SPECIFIC &&
(SmartcardExtension->CardCapabilities.Protocol.Selected & newProtocol)) {
SmartcardDebug(
DEBUG_TRACE,
("USCRSetProtocol: SCARD_SPECIFIC\n")
);
return STATUS_SUCCESS;
}
SmartcardDebug(
DEBUG_TRACE,
("newProtocol:%x\n",newProtocol)
);
if (newProtocol & (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1))
{
#if 0
// do the PTS
PUCHAR ptsRequest = SmartcardExtension->SmartcardRequest.Buffer;
PUCHAR ptsReply = SmartcardExtension->SmartcardReply.Buffer;
PULONG requestLength = &SmartcardExtension->SmartcardRequest.BufferLength;
PULONG replyLength = &SmartcardExtension->SmartcardReply.BufferLength;
while(TRUE) {
// set initial character of PTS
ptsRequest[0] = 0xff;
if(newProtocol & SCARD_PROTOCOL_T1)
ptsRequest[1] = 0x11;
else if(newProtocol & SCARD_PROTOCOL_T0)
ptsRequest[1] = 0x10;
// set pts1 which codes Fl and Dl
ptsRequest[2] =
SmartcardExtension->CardCapabilities.PtsData.Fl << 4 |
SmartcardExtension->CardCapabilities.PtsData.Dl;
// set pck (check character)
ptsRequest[3] = ptsRequest[0] ^ ptsRequest[1] ^ ptsRequest[2];
*requestLength = 4;
*replyLength = 4;
status = CmdXfrBlockTPDU_T0(
ReaderExtension,
*requestLength,
ptsRequest,
replyLength,
ptsReply
);
if (status != STATUS_SUCCESS) {
break;
}
if (NT_SUCCESS(status) &&
memcmp(ptsRequest, ptsReply, 4) == 0) {
// the card replied correctly to our pts-request
// Set Reader CLK Data Rate parameters
break;
}
if (SmartcardExtension->CardCapabilities.PtsData.Type != PTS_TYPE_DEFAULT) {
SmartcardDebug(
DEBUG_TRACE,
("USCRSetProtocol: PTS failed. Trying default parameters...\n")
);
//
// The card did either NOT reply or it replied incorrectly
// so try default values
//
//SmartcardExtension->CardCapabilities.PtsData.Type =
// PTS_TYPE_DEFAULT;
//SmartcardExtension->MinorIoControlCode = SCARD_COLD_RESET;
//status = USCRPower(SmartcardExtension);
continue;
}
// the card failed the pts-request
status = STATUS_DEVICE_PROTOCOL_ERROR;
break;
}//TRUE
#endif
}else{
// we don't support other modi
status = STATUS_INVALID_DEVICE_REQUEST;
}
// if protocol selection failed, prevent from calling invalid protocols
if( NT_SUCCESS( status ))
{
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
newProtocol = (newProtocol & SCARD_PROTOCOL_T1 &
SmartcardExtension->CardCapabilities.Protocol.Supported) ?
SCARD_PROTOCOL_T1 :
SCARD_PROTOCOL_T0;
}
else
{
newProtocol = SCARD_PROTOCOL_UNDEFINED;
}
SmartcardExtension->ReaderCapabilities.CurrentState = SCARD_SPECIFIC;
// Return the selected protocol to the caller.
SmartcardExtension->CardCapabilities.Protocol.Selected = newProtocol;
*( PULONG )( SmartcardExtension->IoRequest.ReplyBuffer ) = newProtocol;
*( SmartcardExtension->IoRequest.Information ) = sizeof( ULONG );
SmartcardDebug(
DEBUG_TRACE,
( "USCRSetProtocol: Exit (%lx)\n", status )
);
return ( status );
}
NTSTATUS
USCRTransmitT0(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
PUCHAR requestBuffer = SmartcardExtension->SmartcardRequest.Buffer;
PULONG requestLength = &SmartcardExtension->SmartcardRequest.BufferLength;
PUCHAR replyBuffer = SmartcardExtension->SmartcardReply.Buffer;
PULONG replyLength = &SmartcardExtension->SmartcardReply.BufferLength;
NTSTATUS status = STATUS_SUCCESS;
ULONG bytesToRead;
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
SmartcardDebug(
DEBUG_TRACE,
("USCRTransmitT0: Enter\n")
);
status = SmartcardT0Request(SmartcardExtension);
ASSERT(status == STATUS_SUCCESS);
SmartcardDebug(
DEBUG_TRACE,
("requestLength = %d\n",*requestLength)
);
HEXDUMP(requestBuffer,*requestLength);
bytesToRead = SmartcardExtension->T0.Le;
*replyLength = bytesToRead+2;
status = CmdXfrBlockTPDU_T0(
ReaderExtension,
*requestLength,
requestBuffer,
replyLength,
replyBuffer
);
SmartcardDebug(
DEBUG_TRACE,
("bytesToRead = %d,replyLength = %d\n",bytesToRead,*replyLength)
);
HEXDUMP(replyBuffer,*replyLength);
if (status == STATUS_SUCCESS) {
status = SmartcardT0Reply(SmartcardExtension);
}else
*replyLength = 0;
SmartcardDebug(
(status == STATUS_SUCCESS ? DEBUG_TRACE : DEBUG_ERROR),
("USCRTransmitT0: Exit(%lx)\n",
status)
);
return status;
}
NTSTATUS
USCRTransmit(
PSMARTCARD_EXTENSION SmartcardExtension
)
{
NTSTATUS NTStatus = STATUS_SUCCESS;
SmartcardDebug(
DEBUG_TRACE,
("USCRTransmit: Enter\n")
);
// dispatch on the selected protocol
// only support T0 now.(ylq)
switch( SmartcardExtension->CardCapabilities.Protocol.Selected )
{
case SCARD_PROTOCOL_T0:
NTStatus = USCRTransmitT0( SmartcardExtension );
break;
case SCARD_PROTOCOL_T1:
NTStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
case SCARD_PROTOCOL_RAW:
NTStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
default:
NTStatus = STATUS_INVALID_DEVICE_REQUEST;
break;
}
SmartcardDebug(
DEBUG_TRACE,
( "USCRTransmit: Exit (%lx)\n", NTStatus )
);
return( NTStatus );
}
void
USCRCompleteCardTracking(
IN PSMARTCARD_EXTENSION SmartcardExtension
)
{
KIRQL ioIrql, keIrql;
PIRP notificationIrp;
SmartcardDebug(
DEBUG_TRACE,
( "USCRCompleteCardTracking: Enter.\n" )
);
IoAcquireCancelSpinLock(&ioIrql);
KeAcquireSpinLock(
&SmartcardExtension->OsData->SpinLock,
&keIrql
);
notificationIrp = SmartcardExtension->OsData->NotificationIrp;
SmartcardExtension->OsData->NotificationIrp = NULL;
KeReleaseSpinLock(
&SmartcardExtension->OsData->SpinLock,
keIrql
);
if (notificationIrp) {
IoSetCancelRoutine(
notificationIrp,
NULL
);
}
IoReleaseCancelSpinLock(ioIrql);
if (notificationIrp) {
SmartcardDebug(
DEBUG_INFO,
("USCRCompleteCardTracking: Completing NotificationIrp %lxh\n",
notificationIrp)
);
// finish the request
if (notificationIrp->Cancel) {
notificationIrp->IoStatus.Status = STATUS_CANCELLED;
} else {
notificationIrp->IoStatus.Status = STATUS_SUCCESS;
}
notificationIrp->IoStatus.Information = 0;
IoCompleteRequest(
notificationIrp,
IO_NO_INCREMENT
);
}
SmartcardDebug(
DEBUG_TRACE,
( "USCRCompleteCardTracking: Exit.\n" )
);
}
static VOID
CardStatusWorkItemRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context
)
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PSMARTCARD_EXTENSION smartcardExtension = &deviceExtension->SmartcardExtension;
PREADER_EXTENSION readerExtension = smartcardExtension->ReaderExtension;
UCHAR CardStatus;
ULONG len = 1;
ULONG OldState = smartcardExtension->ReaderCapabilities.CurrentState > SCARD_ABSENT;
NTSTATUS status;
SmartcardDebug(
DEBUG_TRACE,
( "---------------CardStatusWorkItemRoutine----------------\n" )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -