Hello Everybody,
I have a problem for a driver development.
I try to develop a driver for smartcard reader USB.
I have never developed in KMDF and I have some problem for understand his function.
I have merged the sample OSRFXUsb ( for USB Interrupt Part for PDO) and the pscr sample ( for smartcard reader part for FDO).
My problem is for sending WDFRequest to the FDO.
I have implemented like presented the evtIoDeviceControl, but problem this callback is never called.
For my understanding, it’s necessary to implement a child Device for initialize a smartcard reader ? Or It’s possible to add all attributes in same deviceContext ?
typedef struct _DEVICE_CONTEXT {
WDFDEVICE device;
WDFDRIVER driver;
ULONG deviceInstanceNbr;
WDFINTERRUPT Interrupt;
SMARTCARD_EXTENSION SmartcardExtension;
WDFQUEUE NotificationQueue;
WDFQUEUE IoctlQueue;
USB_DEVICE_DESCRIPTOR usbDeviceDescriptor;
PUSB_CONFIGURATION_DESCRIPTOR usbConfigurationDescriptor;
WDFUSBDEVICE UsbDevice;
WDFUSBINTERFACE UsbInterface;
WDFUSBPIPE BulkReadPipe;
WDFUSBPIPE BulkWritePipe;
WDFUSBPIPE InterruptPipe;
WDFQUEUE InterruptMsgQueue;
ULONG UsbDeviceTraits;
} DEVICE_CONTEXT, *PDEVICE_CONTEXT;
NTSTATUS
busEvtDeviceAdd(
IN WDFDRIVER Driver,
IN PWDFDEVICE_INIT DeviceInit
)
{
NTSTATUS status;
WDFDEVICE device;
PDEVICE_CONTEXT pDevContext;
GUID activity;
WDF_DEVICE_PNP_CAPABILITIES pnpCaps;
WDF_FILEOBJECT_CONFIG fileConfig; // KL 26-11-2010
WDF_IO_QUEUE_CONFIG ioQueueConfig;
WDF_INTERRUPT_CONFIG interruptConfig;
WDF_OBJECT_ATTRIBUTES attributes;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDFQUEUE queue;
DECLARE_CONST_UNICODE_STRING(symbolikNameSlot0, SLOT_SYMBOLIK_NAME_0);
DECLARE_CONST_UNICODE_STRING(symbolikNameSlot1, SLOT_SYMBOLIK_NAME_1);
DECLARE_CONST_UNICODE_STRING(symbolikNameSlot2, SLOT_SYMBOLIK_NAME_2);
UNREFERENCED_PARAMETER(Driver);
PAGED_CODE();
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SMARTCARD);
// WdfDeviceInitSetExclusive(DeviceInit, TRUE);
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDevicePrepareHardware = busEvtDevicePrepareHardware;
pnpPowerCallbacks.EvtDeviceReleaseHardware = busEvtDeviceReleaseHardware;
pnpPowerCallbacks.EvtDeviceD0Entry = busEvtDeviceD0Entry;
pnpPowerCallbacks.EvtDeviceD0Exit = busEvtDeviceD0Exit;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); // KL 01-12-2010
//WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);
WDF_FILEOBJECT_CONFIG_INIT(
&fileConfig,
busEvtDeviceFileCreate,
busEvtFileClose,
WDF_NO_EVENT_CALLBACK // not interested in Cleanup
);
WdfDeviceInitSetFileObjectConfig(DeviceInit,
&fileConfig,
WDF_NO_OBJECT_ATTRIBUTES);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
if (!NT_SUCCESS(status)) {
BulkUsb_DebugPrint(1, (“WdfDeviceCreate failed status = 0x%x\n”, status));
return status;
}
attributes.ParentObject = device;
pDevContext = GetDeviceContext(device);
pDevContext->driver = Driver; // KL 02-12-2010
pDevContext->device= device;
WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps);
pnpCaps.SurpriseRemovalOK = WdfTrue;
WdfDeviceSetPnpCapabilities(device, &pnpCaps);
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
WdfIoQueueDispatchParallel);
ioQueueConfig.EvtIoDeviceControl = EvtIoDeviceControl;
//ioQueueConfig.EvtIoInternalDeviceControl = EvtIoDeviceInternalControl;
status = WdfIoQueueCreate(device,
&ioQueueConfig,
&attributes,// WDF_NO_OBJECT_ATTRIBUTES,
&queue);// pointer to default queue
if (!NT_SUCCESS(status)) {
BulkUsb_DebugPrint(1, (“busEvtDeviceAdd - WdfIoQueueCreate failed 0x%X \n”, status));
return status;
}
WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);
ioQueueConfig.EvtIoRead = usbEvtIoRead;
ioQueueConfig.EvtIoStop = usbEvtIoStop;
status = WdfIoQueueCreate(
device,
&ioQueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&queue // queue handle
);
if (!NT_SUCCESS (status)) {
BulkUsb_DebugPrint(1, (“busEvtDeviceAdd - WdfIoQueueCreate failed %!STATUS!\n”, status));
return status;
}
status = WdfDeviceConfigureRequestDispatching(
device,
queue,
WdfRequestTypeRead);
if(!NT_SUCCESS (status)){
ASSERT(NT_SUCCESS(status));
BulkUsb_DebugPrint(1, (“busEvtDeviceAdd - WdfDeviceConfigureRequestDispatching failed %!STATUS!\n”, status));
//goto Error;
return status;
}
//
// We will create another sequential queue and configure it
// to receive write requests.
//
WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchSequential);
ioQueueConfig.EvtIoWrite = usbEvtIoWrite;
ioQueueConfig.EvtIoStop = usbEvtIoStop;
status = WdfIoQueueCreate(
device,
&ioQueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&queue // queue handle
);
if (!NT_SUCCESS (status)) {
BulkUsb_DebugPrint(1, (“busEvtDeviceAdd - WdfIoQueueCreate failed %!STATUS!\n”, status));
//goto Error;
return status;
}
status = WdfDeviceConfigureRequestDispatching(
device,
queue,
WdfRequestTypeWrite);
if(!NT_SUCCESS (status)){
ASSERT(NT_SUCCESS(status));
BulkUsb_DebugPrint(1, (“busEvtDeviceAdd - WdfDeviceConfigureRequestDispatching failed %!STATUS!\n”, status));
//goto Error;
return status;
}
WDF_IO_QUEUE_CONFIG_INIT(&ioQueueConfig, WdfIoQueueDispatchManual);
ioQueueConfig.PowerManaged = WdfFalse;
ioQueueConfig.EvtIoCanceledOnQueue = slotEvtIoCanceledOnQueue;
status = WdfIoQueueCreate (
device,
&ioQueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&pDevContext->NotificationQueue
);
if(!NT_SUCCESS (status)){
BulkUsb_DebugPrint(1, (“busEvtDeviceAdd - WdfIoQueueCreate failed %!STATUS!\n”, status));
return status;
}
ioQueueConfig.PowerManaged = WdfFalse;
status = WdfIoQueueCreate(device,
&ioQueueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&pDevContext->InterruptMsgQueue
);
if (!NT_SUCCESS(status)) {
BulkUsb_DebugPrint(1, (“busEvtDeviceAdd - WdfIoQueueCreate failed %!STATUS!\n”, status));
return status;
}
//
// Register with smartcard libarary.
//
status = slotRegisterWithSmcLib(pDevContext);
if (!NT_SUCCESS (status)) {
BulkUsb_DebugPrint(1, (" slotRegisterWithSmcLib failed status = 0x%x \n", status));
return status;
}
status = WdfDeviceCreateDeviceInterface(device,
(LPGUID) &GUID_DEVINTERFACE_KL,
//(LPGUID) &GUID_BUS_DEVINTERFACE_KL_0,
NULL); //&symbolikNameSlot0);// Reference String
if (!NT_SUCCESS(status)) {
//KdPrint((“WdfDeviceCreateDeviceInterface failed 0x%x\n”, status));
BulkUsb_DebugPrint(1, (“0) WdfDeviceCreateDeviceInterface failed status = 0x%x \n”, status));
return status;
}
BulkUsb_DebugPrint(1, (" <<<=== busEvtDeviceAdd - SUCCESS = status = 0x%X\n", status));
return status;
}
NTSTATUS
busEvtDeviceD0Entry(
WDFDEVICE Device,
WDF_POWER_DEVICE_STATE PreviousState
)
{
PDEVICE_CONTEXT pDeviceContext;
NTSTATUS status = STATUS_SUCCESS;
PSMARTCARD_EXTENSION SmartcardExtension;
UCHAR state;
WDF_INTERRUPT_INFO interruptInfo;
pDeviceContext = GetDeviceContext(Device);
BulkUsb_DebugPrint(1, (" ===>>> busEvtDeviceD0Entry\n\n"));
status = WdfIoTargetStart(WdfUsbTargetPipeGetIoTarget(pDeviceContext->InterruptPipe));
BulkUsb_DebugPrint(1, (“busEvtDeviceD0Entry - WdfIoTargetStart - [status = 0x%X]\n”, status));
SmartcardExtension = (PSMARTCARD_EXTENSION) &pDeviceContext->SmartcardExtension;
SmartcardExtension->ReaderExtension->StatusFileSelected = FALSE;
state = CBGetCardState(SmartcardExtension);
// save the current power state of the reader
SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderWorking;
if (PreviousState != WdfPowerDeviceD3Final) {
//
// The device is resuming from a suspended state.
//
CBUpdateCardState(SmartcardExtension, state, TRUE);
} else {
//
// The device is starting up for the first time.
//
CBUpdateCardState(SmartcardExtension, state, FALSE);
}
BulkUsb_DebugPrint(1, (" <<<=== busEvtDeviceD0Entry\n"));
return status;
}
NTSTATUS
slotRegisterWithSmcLib(
PDEVICE_CONTEXT DeviceExtension
)
{
PREADER_EXTENSION ReaderExtension;
PSMARTCARD_EXTENSION SmartcardExtension;
UNICODE_STRING vendorNameU, ifdTypeU;
ANSI_STRING vendorNameA, ifdTypeA;
WDFSTRING vendorNameStr, ifdTypeStr;
NTSTATUS status;
UNICODE_STRING vendor;
PAGED_CODE();
BulkUsb_DebugPrint(1, (" ===>>> slotRegisterWithSmcLib\n"));
vendorNameStr = NULL;
ifdTypeStr = NULL;
RtlZeroMemory(&vendorNameA, sizeof(vendorNameA));
RtlZeroMemory(&ifdTypeA, sizeof(ifdTypeA));
// set up the device extension.
SmartcardExtension = &DeviceExtension->SmartcardExtension;
// allocate the reader extension
ReaderExtension = ExAllocatePoolWithTag(
NonPagedPool,
sizeof( READER_EXTENSION ),
SMARTCARD_POOL_TAG
);
if ( ReaderExtension == NULL ) {
SmartcardLogError(
WdfDriverWdmGetDriverObject(WdfGetDriver()),
SLOT_INSUFFICIENT_RESOURCES,
NULL,
0
);
status = STATUS_INSUFFICIENT_RESOURCES;
return status;
}
RtlZeroMemory( ReaderExtension, sizeof( READER_EXTENSION ));
SmartcardExtension->ReaderExtension = ReaderExtension;
ReaderExtension->CompletionRoutine = CBUpdateCardState;
ReaderExtension->TrackingContext = SmartcardExtension;
// Initialize the RequestInterrupt flag
ReaderExtension->RequestInterrupt = FALSE;
// setup smartcard extension - callback’s
SmartcardExtension->ReaderFunction[RDF_CARD_POWER] = CBCardPower;
SmartcardExtension->ReaderFunction[RDF_TRANSMIT] = CBTransmit;
SmartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = CBCardTracking;
SmartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = CBSetProtocol;
SmartcardExtension->ReaderFunction[RDF_IOCTL_VENDOR] = slotGenericIOCTL;
// enter correct version of the lib
SmartcardExtension->Version = SMCLIB_VERSION;
SmartcardExtension->SmartcardRequest.BufferSize = MIN_BUFFER_SIZE;
SmartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
SmartcardExtension->ReaderExtension->ReaderPowerState = PowerReaderWorking;
status = SmartcardInitialize(SmartcardExtension);
if (status != STATUS_SUCCESS) {
BulkUsb_DebugPrint(1, (" slotRegisterWithSmcLib - SmartcardInitialize FAILED - status = 0x%X\n", status));
return status;
}
SmartcardExtension->OsData->DeviceObject =
WdfDeviceWdmGetDeviceObject(DeviceExtension->device);
RtlCopyMemory(
SmartcardExtension->VendorAttr.VendorName.Buffer,
DRIVER_NAME,
sizeof(DRIVER_NAME)
);
SmartcardExtension->VendorAttr.VendorName.Length = sizeof(DRIVER_NAME);
RtlCopyMemory(
SmartcardExtension->VendorAttr.IfdType.Buffer,
IFD_TYPE,
sizeof(IFD_TYPE)
);
SmartcardExtension->VendorAttr.IfdType.Length = sizeof(IFD_TYPE);
BulkUsb_DebugPrint(1, (" <<<=== slotRegisterWithSmcLib\n"));
return status;
}
UCHAR
CBGetCardState(
PSMARTCARD_EXTENSION SmartcardExtension
)
/*++
CBUpdateCardState:
updates the variable CurrentState in SmartcardExtension
Arguments:
SmartcardExtension context of call
Return Value:
STATUS_SUCCESS
–*/
{
PREADER_EXTENSION ReaderExtension = SmartcardExtension->ReaderExtension;
Val = 0x0;
BulkUsb_DebugPrint(1, (" ===>>> CBGetCardState\n"));
// NEED TO SEND WDFREQUEST TO THE PIPE BULKWRITE FOR EXECUTE GET_STATE COMMAND
BulkUsb_DebugPrint(1, (" <<<=== CBGetCardState\n"));
return Val;
}
Thanks in advance,
Best regard,
Kamel