📄 pscrnt.c
字号:
PscrStartDevice(
PDEVICE_OBJECT DeviceObject,
PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor
)
/*++
Routine Description:
get the actual configuration from the passed FullResourceDescriptor
and initializes the reader hardware
Note:
for an NT 4.00 build the resources must be translated by the HAL
Arguments:
DeviceObject context of call
FullResourceDescriptor actual configuration of the reader
Return Value:
STATUS_SUCCESS
status returned from the HAL (NT 4.00 only )
status returned by LowLevel routines
--*/
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PSMARTCARD_EXTENSION SmartcardExtension = &DeviceExtension->SmartcardExtension;
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
NTSTATUS status;
ULONG Count;
SmartcardDebug(
DEBUG_TRACE,
("PSCR!PscrStartDevice: Enter\n")
);
// Get the number of resources we need
Count = FullResourceDescriptor->PartialResourceList.Count;
PartialDescriptor = FullResourceDescriptor->PartialResourceList.PartialDescriptors;
// parse all partial descriptors
while(Count--)
{
switch(PartialDescriptor->Type)
{
case CmResourceTypePort: {
// 0 - memory, 1 - IO
ULONG AddressSpace = 1;
BOOLEAN Translated;
PHYSICAL_ADDRESS PhysicalAddress;
ReaderExtension->IOBase =
(PPSCR_REGISTERS) PartialDescriptor->u.Port.Start.LowPart;
ASSERT(PartialDescriptor->u.Port.Length >= 4);
SmartcardDebug(
DEBUG_TRACE,
("PSCR!PscrStartDevice: IoBase = %lxh\n",
ReaderExtension->IOBase)
);
break;
}
case CmResourceTypeInterrupt: {
KINTERRUPT_MODE Mode;
BOOLEAN Shared;
KIRQL Irql;
KAFFINITY Affinity;
ULONG Vector;
Mode = (
PartialDescriptor->Flags &
CM_RESOURCE_INTERRUPT_LATCHED ?
Latched : LevelSensitive
);
Shared = (
PartialDescriptor->ShareDisposition ==
CmResourceShareShared
);
Vector = PartialDescriptor->u.Interrupt.Vector;
Affinity = PartialDescriptor->u.Interrupt.Affinity;
Irql = (KIRQL) PartialDescriptor->u.Interrupt.Level;
// store IRQ to allow query configuration
ReaderExtension->CurrentIRQ =
PartialDescriptor->u.Interrupt.Vector;
SmartcardDebug(
DEBUG_TRACE,
("PSCR!PscrStartDevice: Irql: %d\n",
PartialDescriptor->u.Interrupt.Level)
);
// connect the driver's isr
status = IoConnectInterrupt(
&DeviceExtension->InterruptObject,
PscrIrqServiceRoutine,
(PVOID) DeviceExtension,
NULL,
Vector,
Irql,
Irql,
Mode,
Shared,
Affinity,
FALSE
);
break;
}
case CmResourceTypeDevicePrivate:
break;
default:
ASSERT(FALSE);
status = STATUS_UNSUCCESSFUL;
break;
}
PartialDescriptor++;
}
try {
HANDLE handle;
UCHAR CardState;
// IOBase initialized ?
if( ReaderExtension->IOBase == NULL ) {
//
// under NT 4.0 the failure of this fct for the second reader
// means there is only one device
//
SmartcardLogError(
DeviceObject,
PSCR_ERROR_IO_PORT,
NULL,
0
);
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
// irq connected ?
if( DeviceExtension->InterruptObject == NULL ) {
SmartcardLogError(
DeviceObject,
PSCR_ERROR_INTERRUPT,
NULL,
0
);
status = STATUS_INSUFFICIENT_RESOURCES;
leave;
}
ReaderExtension->Device = DEVICE_ICC1;
ReaderExtension->MaxRetries = PSCR_MAX_RETRIES;
status = CmdResetInterface( ReaderExtension );
SmartcardExtension->ReaderCapabilities.MaxIFSD =
ReaderExtension->MaxIFSD;
if (status != STATUS_SUCCESS) {
SmartcardLogError(
DeviceObject,
PSCR_CANT_INITIALIZE_READER,
NULL,
0
);
leave;
}
status = CmdReset(
ReaderExtension,
0x00, // reader
FALSE, // cold reset
NULL, // no atr
NULL
);
if (status != STATUS_SUCCESS) {
SmartcardLogError(
DeviceObject,
PSCR_CANT_INITIALIZE_READER,
NULL,
0
);
leave;
}
PscrFlushInterface(DeviceExtension->SmartcardExtension.ReaderExtension);
CmdGetFirmwareRevision(
DeviceExtension->SmartcardExtension.ReaderExtension
);
// If you change the min. firmware version here, please update
// the .mc file for the correct error message, too
if (SmartcardExtension->ReaderExtension->FirmwareMajor < 2 ||
SmartcardExtension->ReaderExtension->FirmwareMajor == 2 &&
SmartcardExtension->ReaderExtension->FirmwareMinor < 0x30) {
SmartcardLogError(
DeviceObject,
PSCR_WRONG_FIRMWARE,
NULL,
0
);
}
//
// make sure the ICC1 status file in the reader file system will
// be selected
//
ReaderExtension->StatusFileSelected = FALSE;
CardState = CBGetCardState(&DeviceExtension->SmartcardExtension);
CBUpdateCardState(&DeviceExtension->SmartcardExtension, CardState, FALSE);
// signal that the reader has been started (again)
KeSetEvent(&DeviceExtension->ReaderStarted, 0, FALSE);
status = IoSetDeviceInterfaceState(
&DeviceExtension->DeviceName,
TRUE
);
if (status == STATUS_OBJECT_NAME_EXISTS) {
// We tried to re-enable the device which is ok
// This can happen after a stop - start sequence
status = STATUS_SUCCESS;
}
ASSERT(status == STATUS_SUCCESS);
}
finally {
if (status != STATUS_SUCCESS) {
PscrStopDevice(DeviceObject);
}
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!PscrStartDevice: Exit %x\n",
status )
);
return status;
}
}
VOID
PscrStopDevice(
PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Diconnect the interrupt used by the device & unmap the IO port
--*/
{
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS status;
LARGE_INTEGER delayPeriod;
if (DeviceObject == NULL) {
return;
}
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!PscrStopDevice: Enter\n" )
);
DeviceExtension = DeviceObject->DeviceExtension;
KeClearEvent(&DeviceExtension->ReaderStarted);
// disconnect the interrupt
if( DeviceExtension->InterruptObject != NULL )
{
IoDisconnectInterrupt(DeviceExtension->InterruptObject);
DeviceExtension->InterruptObject = NULL;
}
// unmap ports
if(DeviceExtension->UnMapPort)
{
MmUnmapIoSpace(
DeviceExtension->SmartcardExtension.ReaderExtension->IOBase,
DeviceExtension->SmartcardExtension.ReaderExtension->IOWindow
);
DeviceExtension->UnMapPort = FALSE;
}
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!PscrStopDevice: Exit\n" )
);
}
VOID
PscrUnloadDevice(
PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
close connections to smclib.sys and the pcmcia driver, delete symbolic
link and mark the slot as unused.
Arguments:
DeviceObject device to unload
Return Value:
void
--*/
{
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS status;
if (DeviceObject == NULL) {
return;
}
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!PscrUnloadDevice: Enter\n" )
);
DeviceExtension = DeviceObject->DeviceExtension;
ASSERT(
DeviceExtension->SmartcardExtension.VendorAttr.UnitNo <
PSCR_MAX_DEVICE
);
if (DeviceExtension->DeviceName.Buffer != NULL) {
// disble our device so no one can open it
IoSetDeviceInterfaceState(
&DeviceExtension->DeviceName,
FALSE
);
}
// Mark this slot as available
DeviceSlot[DeviceExtension->SmartcardExtension.VendorAttr.UnitNo] = FALSE;
// report to the lib that the device will be unloaded
if(DeviceExtension->SmartcardExtension.OsData != NULL)
{
KIRQL CancelIrql;
PSMARTCARD_EXTENSION SmartcardExtension =
&DeviceExtension->SmartcardExtension;
ASSERT(SmartcardExtension->OsData->NotificationIrp == NULL);
IoAcquireCancelSpinLock( &CancelIrql );
if( SmartcardExtension->OsData->NotificationIrp != NULL )
{
PIRP notificationIrp;
notificationIrp = InterlockedExchangePointer(
&(SmartcardExtension->OsData->NotificationIrp),
NULL
);
IoSetCancelRoutine(
notificationIrp,
NULL
);
IoReleaseCancelSpinLock( CancelIrql );
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!PscrUnloadDevice: Completing NotificationIrp %lx\n",
notificationIrp)
);
// finish the request
notificationIrp->IoStatus.Status = STATUS_SUCCESS;
notificationIrp->IoStatus.Information = 0;
IoCompleteRequest(
notificationIrp,
IO_NO_INCREMENT
);
} else {
IoReleaseCancelSpinLock( CancelIrql );
}
// Wait until we can safely unload the device
SmartcardReleaseRemoveLockAndWait(SmartcardExtension);
SmartcardExit(&DeviceExtension->SmartcardExtension);
}
// delete the symbolic link
if( DeviceExtension->DeviceName.Buffer != NULL )
{
RtlFreeUnicodeString(&DeviceExtension->DeviceName);
DeviceExtension->DeviceName.Buffer = NULL;
}
if (DeviceExtension->SmartcardExtension.ReaderExtension != NULL) {
ExFreePool(DeviceExtension->SmartcardExtension.ReaderExtension);
DeviceExtension->SmartcardExtension.ReaderExtension = NULL;
}
// Detach from the pcmcia driver
if (DeviceExtension->AttachedPDO) {
IoDetachDevice(DeviceExtension->AttachedPDO);
DeviceExtension->AttachedPDO = NULL;
}
// delete the device object
IoDeleteDevice(DeviceObject);
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!PscrUnloadDevice: Exit\n" )
);
}
VOID
PscrUnloadDriver(
PDRIVER_OBJECT DriverObject
)
/*++
PscrUnloadDriver:
unloads all devices for a given driver object
Arguments:
DriverObject context of driver
--*/
{
SmartcardDebug(
DEBUG_TRACE,
( "PSCR!PscrUnloadDriver\n" )
);
}
NTSTATUS
PscrCreateClose(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
/*++
PscrCreateClose:
allowes only one open process a time
Arguments:
DeviceObject context of device
Irp context of call
Return Value:
STATUS_SUCCESS
STATUS_DEVICE_BUSY
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_SUCCESS;
__try {
if (irpStack->MajorFunction == IRP_MJ_CREATE) {
status = SmartcardAcquireRemoveLockWithTag(
&deviceExtension->SmartcardExtension,
'lCrC'
);
if (status != STATUS_SUCCESS) {
status = STATUS_DEVICE_REMOVED;
__leave;
}
// test if the device has been opened already
if (InterlockedCompareExchange(
&deviceExtension->ReaderOpen,
TRUE,
FALSE) == FALSE) {
SmartcardDebug(
DEBUG_DRIVER,
("%s!PscrCreateClose: Open\n",
DRIVER_NAME)
);
} else {
// the device is already in use
status = STATUS_UNSUCCESSFUL;
// release the lock
SmartcardReleaseRemoveLockWithTag(
&deviceExtension->SmartcardExtension,
'lCrC'
);
}
} else {
SmartcardDebug(
DEBUG_DRIVER,
("%s!PscrCreateClose: Close\n",
DRIVER_NAME)
);
SmartcardReleaseRemoveLockWithTag(
&deviceExtension->SmartcardExtension,
'lCrC'
);
deviceExtension->ReaderOpen = FALSE;
}
}
__finally {
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return status;
}
NTSTATUS
PscrDeviceIoControl(
PDEVICE_OBJECT DeviceObject,
PIRP Irp
)
/*++
PscrDeviceIoControl:
all IRP's requiring IO are queued to the StartIo routine, other requests
are served immediately
--*/
{
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
NTSTATUS status;
KIRQL irql;
LARGE_INTEGER timeout;
KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
if (deviceExtension->IoCount == 0) {
KeReleaseSpinLock(&deviceExtension->SpinLock, irql);
status = KeWaitForSingleObject(
&deviceExtension->ReaderStarted,
Executive,
KernelMode,
FALSE,
NULL
);
ASSERT(status == STATUS_SUCCESS);
KeAcquireSpinLock(&deviceExtension->SpinLock, &irql);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -