[KMDF] Create driver with multiple device interface

Hello Everybody,

In First, HAPPY NEW YEAR 2011 (^_^)

I have already posted a thread for understand how to proceed for develop a smartcard reader driver multislot ( multi interface ).

I have already developped an USB smartcard reader driver with one interface ( mono slot).

Now last step is to rewrite this driver for work with multi interface.

I have added a fileObject and executed this code :

RtlInitUnicodeString(&DeviceName0, L"VIRTUAL_SM_0");
RtlInitUnicodeString(&DeviceName1, L"VIRTUAL_SM_1");

WDF_FILEOBJECT_CONFIG_INIT(
&fileobjectConfig,
virtualSM_DeviceFileCreate, // Create
virtualSM_DeviceEvtFileClose, // Close
virtualSM_EvtFileCleanup // Cleanup
);

WdfDeviceInitSetFileObjectConfig(
DeviceInit,
&fileobjectConfig,
WDF_NO_OBJECT_ATTRIBUTES
);


status = WdfDeviceCreateDeviceInterface(
device,
&SmartCardReaderGuid_0,
&DeviceName0 // VIRTUAL_SM_0
);

status = WdfDeviceCreateDeviceInterface(
device,
&SmartCardReaderGuid_1,
&DeviceName1 // VIRTUAL_SM_1
);

both evtAddDevice and evtPrepareHW are called successfully.

Driver is correctly installed, and evtIoDeviceControl process fine.
Now When I try to list smartcardreader, DeviceFileCreate function is called two times.
(thanks to Doron’s link,then thank you, http://blogs.msdn.com/b/doronh/archive/2006/08/18/706717.aspx)

VOID
virtualSM_DeviceFileCreate (
IN WDFDEVICE Device,
IN WDFREQUEST Request,
IN WDFFILEOBJECT FileObject
)
/*++

Routine Description:

The framework calls a driver’s EvtDeviceFileCreate callback
when the framework receives an IRP_MJ_CREATE request.
The system sends this request when a user application opens the
device to perform an I/O operation, such as reading or writing to a device.
This callback is called in the context of the thread
that created the IRP_MJ_CREATE request.

Arguments:

Device - Handle to a framework device object.
FileObject - Pointer to fileobject that represents the open handle.
CreateParams - Parameters for create

Return Value:

NT status code

–*/
{
PDEVICE_CONTEXT fdoData;
PUNICODE_STRING deviceName;

//UNREFERENCED_PARAMETER(FileObject);

KdPrint( (“virtualSM_DeviceFileCreate %p\n”, Device));

PAGED_CODE ();

//
// Get the device context given the device handle.
//
fdoData = GetDeviceContext(Device);

//deviceName = WdfFileObjectGetFileName(FileObject);
deviceName = WdfFileObjectGetFileName(WdfRequestGetFileObject(Request));

WdfRequestComplete(Request, STATUS_SUCCESS);

return;
}

and return good deviceName (“VIRTUAL_SM_0” and “VIRTUAL_SM_1”)

Now I have a problem for understand clearly how to proceed for visualize both device interface ( Slot0 and Slot1 ),
Clearly :
_ If I need to create 2 FDO (If it’s possible, call 2 times “SmartcardInitialize”) .
_ If I need to use 2 different DEVICE_CONTEXT Structure.
_ How dispatch IOCTL and IRP for communicate with one device interface.
_ If it’s possible to instantiate entirely the FDO in the fileDeviceCreate function,

Thanks in advance,

Best regard,

Kamel

Hello All,

I have implemented a fileContext structure for define different information for any slots interface.

typedef struct _FILE_SLOT_CONTEXT {

UCHAR slotNumber;
ULONG DeviceInstanceNo;
UNICODE_STRING slotName;
SMARTCARD_EXTENSION SmartCardExtension;
WDFDEVICE Device;
BOOLEAN alreadyOpen;

} FILE_SLOT_CONTEXT, *PFILE_SLOT_CONTEXT;

WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(FILE_SLOT_CONTEXT, GetFileSlotContext)

in the evtDeviceAdd function I have added :

WDF_FILEOBJECT_CONFIG_INIT(
&fileobjectConfig,
virtualSM_DeviceFileCreate, // Create
virtualSM_DeviceEvtFileClose, // Close
virtualSM_EvtFileCleanup // Cleanup
);

WDF_OBJECT_ATTRIBUTES_INIT(&fileObjectAttributes);

WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fileObjectAttributes, FILE_SLOT_CONTEXT);

WdfDeviceInitSetFileObjectConfig(
DeviceInit,
&fileobjectConfig,
&fileObjectAttributes //WDF_NO_OBJECT_ATTRIBUTES // KL 04/01/2011
);

status = WdfDeviceCreateDeviceInterface(
device,
&SmartCardReaderGuid_0,
&DeviceName0
);

status = WdfDeviceCreateDeviceInterface(
device,
&SmartCardReaderGuid_1,
&DeviceName1
);

I precise that “SmartCardReaderGuid_0” and “SmartCardReaderGuid_1” have the same GUID Value,
I have just defined 2 different name.

Now the EvtFileCreate function updated :

VOID
virtualSM_DeviceFileCreate (
IN WDFDEVICE Device,
IN WDFREQUEST Request,
IN WDFFILEOBJECT FileObject
)
{
PDEVICE_CONTEXT fdoData;
PFILE_SLOT_CONTEXT slotContext;
PUNICODE_STRING deviceName;
NTSTATUS status = STATUS_SUCCESS;
PCUNICODE_STRING pName;
UNICODE_STRING DeviceName0, DeviceName1;

RtlInitUnicodeString(&DeviceName0, L"\VIRTUAL_SM_0"); // KL 03/01/2011
RtlInitUnicodeString(&DeviceName1, L"\VIRTUAL_SM_1"); // KL 03/01/2011

KdPrint( (“virtualSM_DeviceFileCreate %p\n”, Device));

PAGED_CODE ();

slotContext = GetFileSlotContext(FileObject);

deviceName = WdfFileObjectGetFileName(WdfRequestGetFileObject(Request));

if (RtlCompareUnicodeString(deviceName, &DeviceName0, TRUE) == 0x0)
{
RtlInitUnicodeString(&slotContext->slotName, L"VIRTUAL_SM_0");
slotContext->slotNumber = 0;
}
else if (RtlCompareUnicodeString(deviceName, &DeviceName1, TRUE) == 0x0)
{
RtlInitUnicodeString(&slotContext->slotName, L"VIRTUAL_SM_1");
slotContext->slotNumber = 1;

}

if(!slotContext->alreadyOpen)
{

slotContext->Device = Device;
status = virtualSM_RegisterWithSmcLib(slotContext);

WdfRequestComplete(Request, STATUS_SUCCESS);
}

return;
}

This function is called two times for both deviceInterface created.
The registration is correctly executed.

I have updated the “evtDeviceIoControl” function for use the “fileSlotContext” instead of deviceContext

NTSTATUS virtualSM_SmartCardIoControl(IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
)
{
NTSTATUS status;
WDFDEVICE device;
PDEVICE_CONTEXT pDevContext;
PFILE_SLOT_CONTEXT fileSlotContext;
PIRP Irp;

device = WdfIoQueueGetDevice(Queue);
pDevContext = GetDeviceContext(device);

fileSlotContext = GetFileSlotContext(WdfRequestGetFileObject(Request));

//status = SmartcardAcquireRemoveLock(&pDevContext->SmartCardExtension);
status = SmartcardAcquireRemoveLock(&fileSlotContext->SmartCardExtension);
KdPrint((" virtualSM_SmartCardIoControl is called\n"));
if(status != STATUS_SUCCESS)
{
KdPrint((" virtualSM_SmartCardIoControl status != STATUS_SUCCESS\n"));
WdfRequestCompleteWithInformation(Request, status, 0);
}
else
{
Irp = WdfRequestWdmGetIrp(Request);
KdPrint((" The value of IRP = 0x%x",Irp));
KdPrint((" The value of SMART CARD EXTENSION = 0x%x\n",&pDevContext->SmartCardExtension));

switch (IoControlCode)
{
case IOCTL_SMARTCARD_POWER:
KdPrint((“IOCTL_SMARTCARD_POWER\n”));
case IOCTL_SMARTCARD_GET_ATTRIBUTE:
KdPrint((“IOCTL_SMARTCARD_GET_ATTRIBUTE\n”));
case IOCTL_SMARTCARD_SET_ATTRIBUTE:
KdPrint((“IOCTL_SMARTCARD_SET_ATTRIBUTE\n”));
case IOCTL_SMARTCARD_CONFISCATE:
KdPrint((“IOCTL_SMARTCARD_CONFISCATE\n”));
case IOCTL_SMARTCARD_TRANSMIT:
KdPrint((“IOCTL_SMARTCARD_TRANSMIT\n”));
case IOCTL_SMARTCARD_EJECT:
KdPrint((“IOCTL_SMARTCARD_EJECT\n”));
case IOCTL_SMARTCARD_SWALLOW:
KdPrint((“IOCTL_SMARTCARD_SWALLOW\n”));
case IOCTL_SMARTCARD_IS_PRESENT:
KdPrint((“IOCTL_SMARTCARD_IS_PRESENT\n”));
case IOCTL_SMARTCARD_IS_ABSENT:
KdPrint((“IOCTL_SMARTCARD_IS_ABSENT\n”));
case IOCTL_SMARTCARD_SET_PROTOCOL:
KdPrint((“IOCTL_SMARTCARD_SET_PROTOCOL\n”));
case IOCTL_SMARTCARD_GET_STATE:
KdPrint((“IOCTL_SMARTCARD_GET_STATE\n”));
case IOCTL_SMARTCARD_GET_LAST_ERROR:
KdPrint((“IOCTL_SMARTCARD_GET_LAST_ERROR\n”));
default:
KdPrint((“UNKNOWN IOCTL\n”));
//status = SmartcardDeviceControl(&pDevContext->SmartCardExtension, Irp);
status = SmartcardDeviceControl(&fileSlotContext->SmartCardExtension, Irp);

}

//SmartcardReleaseRemoveLock(&pDevContext->SmartCardExtension);
SmartcardReleaseRemoveLock(&fileSlotContext->SmartCardExtension);

}
return status;
}

IOCTL are correctly executed, but When I try to execute a “listReaders” I don’t have both interfaces smartcard listed.

Someone could explain me if my approch is correct and why I don’t have a “listReaders” filled.
I have a problem for understand clearly how to distinguish treatment between “deviceInterfaces”

Regards,

Kamel

Hi all,

I have solved this problem,
for those who encounter the same problem, it’s necessary to implement all callback function smartcard.

SmartCardExtension->ReaderFunction[RDF_CARD_TRACKING] =
virtualSM_ScardTracking;
SmartCardExtension->ReaderFunction[RDF_TRANSMIT] =
virtualSM_ScardTransmit;
SmartCardExtension->ReaderFunction[RDF_SET_PROTOCOL] =
virtualSM_ScardSetProtocol;
SmartCardExtension->ReaderFunction[RDF_CARD_POWER] =
virtualSM_ScardPower;

And in cardPower function callback, call :
status = SmartcardUpdateCardCapabilities(SmartcardExtension);

For update Card detection state.

Best Regard,

Kamel