Hi ,
I am working on smart card reader driver. And the stack looks like this
Smart Card reader Driver[KMDF]
Creates PDO |
Multifunction Drive[KMDF]r-----------------------> PDO[KMDF]
|
WUSB.sys
I tried lots of method , gone through the Smart card reader driver provided in winddk6001.But still does not work.The code snip it will give the info what is required for basic enumeration.
The code looks as follows:[its bit, but gives u entire input of how i am writing the code]
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
WDF_DRIVER_CONFIG config;
NTSTATUS status;
// MODULE_INIT()
WDF_DRIVER_CONFIG_INIT(&config, phNfc4Win_PCSCAddDevice);
status = WdfDriverCreate( DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
WDF_NO_HANDLE);
if (!NT_SUCCESS(status)) {
KdPrint((“WdfDriverCreate failed 0x%x\n”, status));
}
return status;
}
NTSTATUS phNfc4Win_PCSCAddDevice(IN WDFDRIVER Driver,IN PWDFDEVICE_INIT DeviceInit)
{
WDF_OBJECT_ATTRIBUTES attributes;
NTSTATUS status;
WDFDEVICE device;
PDEVICE_CONTEXT pDevContext;
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
WDF_IO_QUEUE_CONFIG ioQueueConfig;
PSMARTCARD_EXTENSION smartcardExtension;
PREADER_EXTENSION pReaderExtension = NULL;
PDEVICE_OBJECT fdo;
UNICODE_STRING DeviceName;
UNICODE_STRING LinkName;
UNREFERENCED_PARAMETER(Driver);
KdPrint((“RtlInitUnicodeString called\n”));
RtlInitUnicodeString(&DeviceName, L"\??\NFC CARD READER0");
KdPrint((“EvtDeviceAdd called \n”));
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_SMARTCARD);
WdfDeviceInitSetExclusive(DeviceInit, TRUE);
//WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
pnpPowerCallbacks.EvtDevicePrepareHardware = phNfc4Win_PCSCPrepareHW;
WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
KdPrint((“WdfDeviceCreate called \n”));
/*Create the FDO here for the device */
status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
if (!NT_SUCCESS(status))
{
KdPrint((“WdfDeviceCreate failed 0x%x\n”, status));
return status;
}
pDevContext = GetDeviceContext(device);
pDevContext->device = device;
WdfDeviceWdmGetDeviceObject(pDevContext->device)->StackSize++;
/*Create symbolic link name for the device */
status = WdfDeviceCreateSymbolicLink(device,&DeviceName);
/*create a smart card Interface */
KdPrint((“WdfDeviceCreateDeviceInterface called \n”));
status = WdfDeviceCreateDeviceInterface(device,
(LPGUID) &SmartCardReaderGuid,
NULL);
if (!NT_SUCCESS(status))
{
KdPrint((“WdfDeviceCreateDeviceInterface failed 0x%x\n”, status));
return status;
}
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig,
WdfIoQueueDispatchParallel);
ioQueueConfig.EvtIoDeviceControl = phNfc4win_IoDevCtrl;
/*create queue for handling the requests */
KdPrint((“WdfIoQueueCreate called \n”));
status = WdfIoQueueCreate(device,&ioQueueConfig,WDF_NO_OBJECT_ATTRIBUTES,WDF_NO_HANDLE);
if (!NT_SUCCESS(status))
{
KdPrint((“WdfIoQueueCreate failed %!STATUS!\n”, status));
return status;
}
/*Get the FDO */
fdo = WdfDeviceWdmGetDeviceObject(device);
smartcardExtension = &pDevContext->SmartCardExtension;
KdPrint((“smartcardExtension =0x%x\n”,smartcardExtension));
if ((pReaderExtension = (PREADER_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(READER_EXTENSION))) != NULL)
{
KdPrint((“pReaderExtension allocation sucessful\n”));
RtlZeroMemory(pReaderExtension, sizeof(READER_EXTENSION));
}
else
{
KdPrint((“pReaderExtension is equal to NULL\n”));
}
if(1)
{
smartcardExtension->Version = SMCLIB_VERSION;
smartcardExtension->SmartcardRequest.BufferSize = MIN_BUFFER_SIZE;
smartcardExtension->SmartcardReply.BufferSize = MIN_BUFFER_SIZE;
KdPrint((“SmartcardInitialize\n”));
status = SmartcardInitialize(smartcardExtension);
KdPrint((" SmartcardExtension->SmartcardRequest.BufferSize = 0x%x \n",smartcardExtension->SmartcardRequest.BufferSize));
KdPrint((" smartcardExtension->SmartcardReply.BufferSize = 0x%x \n",smartcardExtension->SmartcardReply.BufferSize));
KdPrint((" status = SmartcardInitialize(smartcardExtension); \n"));
if(status == STATUS_INSUFFICIENT_RESOURCES)
{
KdPrint((“STATUS_INSUFFICIENT_RESOURCES \n”));
status = STATUS_UNSUCCESSFUL;
}
else if (status != STATUS_SUCCESS)
{
KdPrint((“SmartcardInitialize failed \n”));
status = STATUS_UNSUCCESSFUL;
}
}
else
{
KdPrint((“smartcardExtension is NULL\n”));
status = STATUS_UNSUCCESSFUL;
}
/*Register the call back functions with the Smart card library */
KdPrint((“register callbacks \n”));
smartcardExtension->ReaderFunction[RDF_CARD_TRACKING] = phNfc4Win_ScardTracking;
smartcardExtension->ReaderFunction[RDF_TRANSMIT] = phNfc4Win_ScardTransmit;
smartcardExtension->ReaderFunction[RDF_SET_PROTOCOL] = phNfc4Win_ScardSetProtocol;
smartcardExtension->ReaderFunction[RDF_CARD_POWER] = phNfc4Win_ScardPower;
KdPrint((“register callbacks completed \n”));
KdPrint((“vendor attribute started \n”));
strcpy(((char*)smartcardExtension->VendorAttr.VendorName.Buffer), “NXP”);
smartcardExtension->VendorAttr.VendorName.Length =
(USHORT) strlen((char*)pDevContext->SmartCardExtension.VendorAttr.VendorName.Buffer);
strcpy((char *)smartcardExtension->VendorAttr.IfdType.Buffer, “NFC CARD READER”);
smartcardExtension->VendorAttr.IfdType.Length =
(USHORT) strlen((char *)smartcardExtension->VendorAttr.IfdType.Buffer);
smartcardExtension->VendorAttr.UnitNo = MAXULONG;
smartcardExtension->VendorAttr.UnitNo = 0;
KdPrint((“vendor attribute completed \n”));
/*Set the Smart Card Reader Cabalities structre*/ // Set the reader capabilities
KdPrint((“Reader capabilites started \n”));
smartcardExtension->ReaderCapabilities.SupportedProtocols = SCARD_PROTOCOL_RAW;
smartcardExtension->ReaderCapabilities.ReaderType = SCARD_READER_TYPE_VENDOR;
smartcardExtension->ReaderCapabilities.MechProperties = 0x8;
smartcardExtension->ReaderCapabilities.CurrentState = SCARD_UNKNOWN;
smartcardExtension->ReaderCapabilities.Channel = 0x200000;
smartcardExtension->ReaderCapabilities.CLKFrequency.Default = 13560;
smartcardExtension->ReaderCapabilities.CLKFrequency.Max = 13560;
smartcardExtension->ReaderCapabilities.DataRate.Default = 10600;//dataRatesSupported[0];
smartcardExtension->ReaderCapabilities.DataRate.Max = 10600;//dataRatesSupported[2];
smartcardExtension->ReaderCapabilities.MaxIFSD = 254;
smartcardExtension->ReaderCapabilities.PowerMgmtSupport = 0;
smartcardExtension->ReaderCapabilities.CardConfiscated = FALSE;
/*smartcardExtension->ReaderCapabilities.DataRatesSupported.List = dataRatesSupported;
smartcardExtension->ReaderCapabilities.DataRatesSupported.Entries =
sizeof(dataRatesSupported) / sizeof(dataRatesSupported);
smartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.List = Clkfrequencies;
smartcardExtension->ReaderCapabilities.CLKFrequenciesSupported.Entries =
sizeof(Clkfrequencies) / sizeof(Clkfrequencies)*/
KdPrint((“Reader capabilites end \n”));
smartcardExtension->ReaderExtension = pReaderExtension;
KdPrint((“SmartcardCreateLink is called \n”));
if ((status = SmartcardCreateLink(&LinkName, &DeviceName)) == STATUS_SUCCESS)
{
smartcardExtension->OsData->DeviceObject = fdo;
fdo->Flags |= DO_BUFFERED_IO;
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
KdPrint((“WdfDeviceCreateDeviceInterface called \n”));
status = WdfDeviceCreateDeviceInterface(device,(LPGUID) &SmartCardReaderGuid,NULL);
if(NT_SUCCESS(status))
{
//WdfDeviceSetDeviceInterfaceState (device,(LPGUID) &SmartCardReaderGuid,NULL,TRUE);
}
}
else
{
KdPrint((“\t%sCreateDevice SmartCardCreateLink FAILED\n”, (ULONG) status));
}
return status;
}
NTSTATUS
phNfc4Win_PCSCPrepareHW(
IN WDFDEVICE Device,
IN WDFCMRESLIST ResourceList,
IN WDFCMRESLIST ResourceListTranslated
)
{
NTSTATUS status = STATUS_SUCCESS;
BYTE count = 0, i = 0,numberConfiguredPipes =0 ;
PDEVICE_CONTEXT pDeviceContext;
KdPrint((“EvtDevicePrepareHardware called \n”));
UNREFERENCED_PARAMETER(ResourceList);
UNREFERENCED_PARAMETER(ResourceListTranslated);
pDeviceContext = GetDeviceContext(Device);
return status;
}
NTSTATUS phNfc4win_IoDevCtrl(IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
)
{
NTSTATUS status;
WDFDEVICE device;
PDEVICE_CONTEXT pDevContext;
PIRP Irp;
device = WdfIoQueueGetDevice(Queue);
pDevContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
//
// Since smart card library expects an IRP, we will get the underlying
// irp.
//
Irp = WdfRequestWdmGetIrp(Request);
//
// We will store the Request handle in the IRP DriverContext field so
// that we can get the handle back in vendor-ioctl callback routine.
//
SET_REQUEST_IN_IRP(Irp, Request);
//
// To workaround the problem of smart card completing the IRP we provided.
// we will use the extra stack location to set a completion routine so that
// when it completes the IRP, our completion routine will be called, where
// we can interrupt the completion and complete the actual WDFREQUEST.
//
KdPrint((" SET_REQUEST_IN_IRP is called\n"));
IoCopyCurrentIrpStackLocationToNext(Irp);
KdPrint((" IoSetCompletionRoutine is called\n"));
IoSetCompletionRoutine (Irp,
phNfc4Win_SmcLibComplete,
Request,
TRUE,
TRUE,
TRUE
);
KdPrint((" IoSetNextIrpStackLocation is called\n"));
IoSetNextIrpStackLocation(Irp);
//
// Ignore the return value because framework has marked the irp pending
// and will return status-pending when we return from this routine.
//
status = SmartcardAcquireRemoveLock(&pDevContext->SmartCardExtension);
KdPrint((" phNfc4Win_SmartCardIoControl is called\n"));
if(status != STATUS_SUCCESS)
{
KdPrint((" phNfc4Win_SmartCardIoControl status != STATUS_SUCCESS\n"));
WdfRequestCompleteWithInformation(Request, status, 0);
}
else
{
KdPrint((" Else entered\n"));
Irp = WdfRequestWdmGetIrp(Request);
KdPrint((" The value of IRP = 0x%x",Irp));
KdPrint((" The value of SMART CARD EXTENSION = 0x%x",&pDevContext->SmartCardExtension));
switch (IoControlCode)
{
case IOCTL_SMARTCARD_POWER:
KdPrint((“IOCTL_SMARTCARD_POWER\n”));
break;
case IOCTL_SMARTCARD_GET_ATTRIBUTE:
KdPrint((“IOCTL_SMARTCARD_GET_ATTRIBUTE\n”));
break;
case IOCTL_SMARTCARD_SET_ATTRIBUTE:
KdPrint((“IOCTL_SMARTCARD_SET_ATTRIBUTE\n”));
break;
case IOCTL_SMARTCARD_CONFISCATE:
KdPrint((“IOCTL_SMARTCARD_CONFISCATE\n”));
break;
case IOCTL_SMARTCARD_TRANSMIT:
KdPrint((“IOCTL_SMARTCARD_TRANSMIT\n”));
break;
case IOCTL_SMARTCARD_EJECT:
KdPrint((“IOCTL_SMARTCARD_EJECT\n”));
break;
case IOCTL_SMARTCARD_SWALLOW:
KdPrint((“IOCTL_SMARTCARD_SWALLOW\n”));
break;
case IOCTL_SMARTCARD_IS_PRESENT:
KdPrint((“IOCTL_SMARTCARD_IS_PRESENT\n”));
break;
case IOCTL_SMARTCARD_IS_ABSENT:
KdPrint((“IOCTL_SMARTCARD_IS_ABSENT\n”));
break;
case IOCTL_SMARTCARD_SET_PROTOCOL:
KdPrint((“IOCTL_SMARTCARD_SET_PROTOCOL\n”));
break;
case IOCTL_SMARTCARD_GET_STATE:
KdPrint((“IOCTL_SMARTCARD_GET_STATE\n”));
break;
case IOCTL_SMARTCARD_GET_LAST_ERROR:
KdPrint((“IOCTL_SMARTCARD_GET_LAST_ERROR\n”));
break;
default:
KdPrint((“UNKNOWN IOCTL\n”));
}
KdPrint((" Else exit\n"));
KdPrint((" SmartcardReleaseRemoveLock is calledwill be made next\n"));
status = SmartcardDeviceControl(&pDevContext->SmartCardExtension, Irp);
SmartcardReleaseRemoveLock(&pDevContext->SmartCardExtension);
}
return status;
}
NTSTATUS
phNfc4Win_SmcLibComplete (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
Completion routine is called when the IRP is completed by the smclib.
We will interrupt the completion of the IRP, and inturn complete the
WDFREQUEST given to us by the framework.
–*/
{
UNREFERENCED_PARAMETER(DeviceObject);
KdPrint((“<– PscrSmcLibComplete called Request \n”));
WdfRequestComplete((WDFREQUEST)Context, Irp->IoStatus.Status);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS phNfc4Win_ScardTracking(PSMARTCARD_EXTENSION SmartcardExtension)
{
KIRQL CancelIrql;
PDEVICE_CONTEXT pDevContext;
NRB Nrb;
NFY_NRB NfyRb;
phNfc4Win_eStatusCodes_t instatus;
NTSTATUS status = STATUS_SUCCESS;
pDevContext = GetDeviceContext(SmartcardExtension->OsData->DeviceObject);
IoAcquireCancelSpinLock(&CancelIrql);
IoSetCancelRoutine(SmartcardExtension->OsData->NotificationIrp, phNfc4Win_TamaCancel);
IoReleaseCancelSpinLock(CancelIrql);
return STATUS_PENDING;
}