You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
338 lines
9.6 KiB
338 lines
9.6 KiB
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <ntddk.h>
|
|
#include <usbdrivr.h>
|
|
#include "usbutil.h"
|
|
#include "usbsc.h"
|
|
#include "smclib.h"
|
|
#include "usbscnt.h"
|
|
#include "usbsccb.h"
|
|
#include "usbscpnp.h"
|
|
#include "usbscpwr.h"
|
|
|
|
// declare pageable/initialization code
|
|
#pragma alloc_text( INIT, DriverEntry )
|
|
#pragma alloc_text( PAGEABLE, UsbScAddDevice )
|
|
#pragma alloc_text( PAGEABLE, UsbScCreateClose )
|
|
#pragma alloc_text( PAGEABLE, UsbScUnloadDriver )
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Drivers DriverEntry function
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
#ifdef BETA_SPEW
|
|
#if DEBUG
|
|
SmartcardSetDebugLevel(DEBUG_PROTOCOL | DEBUG_ERROR);
|
|
#endif
|
|
#endif
|
|
__try
|
|
{
|
|
SmartcardDebug( DEBUG_TRACE, ("%s!DriverEntry Enter\n",DRIVER_NAME ));
|
|
|
|
// Initialize the Driver Object with driver's entry points
|
|
DriverObject->DriverUnload = ScUtil_UnloadDriver;
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScUtil_CreateClose;
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScUtil_CreateClose;
|
|
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ScUtil_Cleanup;
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScUtil_DeviceIOControl;
|
|
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = ScUtil_SystemControl;
|
|
DriverObject->MajorFunction[IRP_MJ_PNP] = ScUtil_PnP;
|
|
DriverObject->MajorFunction[IRP_MJ_POWER] = ScUtil_Power;
|
|
DriverObject->DriverExtension->AddDevice = UsbScAddDevice;
|
|
|
|
|
|
}
|
|
|
|
__finally
|
|
{
|
|
|
|
SmartcardDebug( DEBUG_TRACE, ("%s!DriverEntry Exit : 0x%x\n",DRIVER_NAME, status ));
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
UsbScAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT Pdo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
AddDevice routine. Creates the FDO and does initialization work.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
|
|
NTSTATUS status;
|
|
PDEVICE_EXTENSION pDevExt;
|
|
PSMARTCARD_EXTENSION pSmartcardExtension;
|
|
PREADER_EXTENSION pReaderExtension;
|
|
RTL_QUERY_REGISTRY_TABLE parameters[3];
|
|
PDEVICE_OBJECT pDevObj = NULL;
|
|
PURB urb;
|
|
|
|
__try
|
|
{
|
|
SmartcardDebug( DEBUG_TRACE, ("%s!UsbScAddDevice Enter\n",DRIVER_NAME ));
|
|
|
|
|
|
// create the device object
|
|
status = IoCreateDevice(DriverObject,
|
|
sizeof( DEVICE_EXTENSION ),
|
|
NULL,
|
|
FILE_DEVICE_SMARTCARD,
|
|
0,
|
|
TRUE,
|
|
&pDevObj);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
// initialize device extension
|
|
pDevExt = pDevObj->DeviceExtension;
|
|
|
|
pSmartcardExtension = &pDevExt->SmartcardExtension;
|
|
|
|
pDevObj->Flags |= DO_POWER_PAGABLE;
|
|
|
|
IoInitializeRemoveLock(&pDevExt->RemoveLock,
|
|
SMARTCARD_POOL_TAG,
|
|
0,
|
|
10);
|
|
|
|
pDevExt->DeviceDescriptor = NULL;
|
|
pDevExt->Interface = NULL;
|
|
|
|
// allocate & initialize reader extension
|
|
pSmartcardExtension->ReaderExtension = ExAllocatePool(NonPagedPool,
|
|
sizeof( READER_EXTENSION ));
|
|
|
|
if ( pSmartcardExtension->ReaderExtension == NULL ) {
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
__leave;
|
|
|
|
}
|
|
|
|
pReaderExtension = pSmartcardExtension->ReaderExtension;
|
|
|
|
ASSERT( pReaderExtension != NULL );
|
|
|
|
RtlZeroMemory(pReaderExtension, sizeof( READER_EXTENSION ));
|
|
pReaderExtension->DeviceObject = pDevObj;
|
|
|
|
// initialize smartcard extension - version & callbacks
|
|
|
|
// Write the version of the lib we use to the smartcard extension
|
|
pSmartcardExtension->Version = SMCLIB_VERSION;
|
|
pSmartcardExtension->SmartcardRequest.BufferSize =
|
|
pSmartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
|
|
|
|
//
|
|
// Now let the lib allocate the buffer for data transmission
|
|
// We can either tell the lib how big the buffer should be
|
|
// by assigning a value to BufferSize or let the lib
|
|
// allocate the default size
|
|
//
|
|
status = SmartcardInitialize(pSmartcardExtension);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
__leave;
|
|
|
|
}
|
|
|
|
|
|
pSmartcardExtension->ReaderFunction[RDF_TRANSMIT] = UsbScTransmit;
|
|
pSmartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = UsbScSetProtocol;
|
|
pSmartcardExtension->ReaderFunction[RDF_CARD_POWER] = UsbScCardPower;
|
|
pSmartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = UsbScCardTracking;
|
|
pSmartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR] = UsbScVendorIoctl;
|
|
pSmartcardExtension->ReaderFunction[RDF_READER_SWALLOW] = NULL; //UsbScCardSwallow;
|
|
pSmartcardExtension->ReaderFunction[RDF_CARD_EJECT] = NULL; //UsbScCardEject;
|
|
|
|
|
|
// Save deviceObject
|
|
pSmartcardExtension->OsData->DeviceObject = pDevObj;
|
|
|
|
pDevExt = pDevObj->DeviceExtension;
|
|
|
|
// attach the device object to the physical device object
|
|
pDevExt->LowerDeviceObject = IoAttachDeviceToDeviceStack(pDevObj,
|
|
Pdo);
|
|
|
|
ASSERT( pDevExt->LowerDeviceObject != NULL );
|
|
|
|
|
|
if ( pDevExt->LowerDeviceObject == NULL ) {
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
__leave;
|
|
|
|
}
|
|
|
|
pDevExt->PhysicalDeviceObject = Pdo;
|
|
|
|
pDevObj->Flags |= DO_BUFFERED_IO;
|
|
pDevObj->Flags |= DO_POWER_PAGABLE;
|
|
pDevObj->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
ScUtil_Initialize(&pDevExt->ScUtilHandle,
|
|
Pdo,
|
|
pDevExt->LowerDeviceObject,
|
|
pSmartcardExtension,
|
|
&pDevExt->RemoveLock,
|
|
UsbScStartDevice,
|
|
UsbScStopDevice,
|
|
UsbScRemoveDevice,
|
|
NULL,
|
|
UsbScSetDevicePowerState);
|
|
|
|
}
|
|
|
|
__finally
|
|
{
|
|
SmartcardDebug(DEBUG_TRACE, ( "%s!DrvAddDevice: Exit (%lx)\n", DRIVER_NAME, status ));
|
|
|
|
}
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
UsbScSetDevicePowerState(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN DEVICE_POWER_STATE DeviceState,
|
|
OUT PBOOLEAN PostWaitWake
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Handles whatever changes need to be made when the device is changing
|
|
power states.
|
|
|
|
Arguments:
|
|
DeviceObject
|
|
DeviceState - the device power state that the reader is entering
|
|
PostWaitWakeIrp - used for future compatability with WDM Wrapper
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PDEVICE_EXTENSION pDevExt;
|
|
PSMARTCARD_EXTENSION smartcardExtension;
|
|
KIRQL irql;
|
|
PIO_STACK_LOCATION irpStack;
|
|
__try
|
|
{
|
|
SmartcardDebug( DEBUG_TRACE, ("%s!UsbScSetDevicePowerState Enter\n",DRIVER_NAME ));
|
|
|
|
pDevExt = DeviceObject->DeviceExtension;
|
|
smartcardExtension = &pDevExt->SmartcardExtension;
|
|
|
|
if (DeviceState < pDevExt->PowerState) {
|
|
// We are coming up!
|
|
|
|
//
|
|
// According to the spec, we need to assume that all cards were removed.
|
|
// We will get insertion notification if a card is present.
|
|
// So if there is a removal irp pending, we should complete that.
|
|
//
|
|
KeAcquireSpinLock(&smartcardExtension->OsData->SpinLock,
|
|
&irql);
|
|
|
|
if (smartcardExtension->OsData->NotificationIrp) {
|
|
irpStack = IoGetCurrentIrpStackLocation(smartcardExtension->OsData->NotificationIrp);
|
|
|
|
if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SMARTCARD_IS_ABSENT) {
|
|
KeReleaseSpinLock(&smartcardExtension->OsData->SpinLock,
|
|
irql);
|
|
UsbScCompleteCardTracking(smartcardExtension);
|
|
|
|
} else {
|
|
|
|
KeReleaseSpinLock(&smartcardExtension->OsData->SpinLock,
|
|
irql);
|
|
|
|
|
|
}
|
|
} else {
|
|
|
|
KeReleaseSpinLock(&smartcardExtension->OsData->SpinLock,
|
|
irql);
|
|
|
|
}
|
|
|
|
//
|
|
// Continue polling the interrupt pipe for insertion notifications
|
|
//
|
|
USBStartInterruptTransfers(pDevExt->WrapperHandle);
|
|
|
|
pDevExt->PowerState = DeviceState;
|
|
|
|
|
|
|
|
|
|
} else if (DeviceState > pDevExt->PowerState) {
|
|
|
|
//
|
|
// We are going down!
|
|
//
|
|
|
|
|
|
// Stop polling for insertion notifications
|
|
USBStopInterruptTransfers(pDevExt->WrapperHandle);
|
|
|
|
|
|
pDevExt->PowerState = DeviceState;
|
|
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
__finally
|
|
{
|
|
SmartcardDebug( DEBUG_TRACE, ("%s!UsbScSetDevicePowerState Exit : 0x%x\n",DRIVER_NAME, status ));
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|