Hi guys,
I'm new on driver development, starting from the osr USB WDK example I'd like to develope a kernel mode driver that can manage the UI
"CancelIO", so that can cancel all the DeviceIoControl on a WDFQUEUE. My device can recieve data continuously with an internal
small buffer, in order to not have any hole on data transfer I continuously feed my device with data that is quequed on the driver.
The user must have the possibility to abort the transfer and delete the pending write operations at any time. I tried to define an
EVT_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE funciton but when I issue a "CancelIO" from my UI, this "EvtRequestCancel" callback function is never called. What
can be the problem? below the involved code.
Thanks in advance to anyone that can give me hints.
Robbie
The UI side is implemented as:
hDeviceF2[DevCount]=CreateFile(
functionClassDeviceData->DevicePath,
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_WRITE | FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
// header struct contains variable to be set inside the driver, while the buffer contains transfer data
DeviceIoControl (hDeviceF2[pTransferStruct->DeviceNumber],
IOCTL_WRITE,
pTransferStruct->pHeader,
SizeHeader,
pTransferStruct->buffer,
pTransferStruct->sizeBuffer,
NULL,
&(pTransferStruct->OverlappedData));
#define IOCTL_WRITE CTL_CODE( FILE_DEVICE_UNKNOWN, 0x010, METHOD_IN_DIRECT, FILE_ANY_ACCESS )
Driver side:
DEVICE CREATE:
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueCon fig,
WdfIoQueueDispatchParallel);
ioQueueConfig.EvtIoDeviceControl = UsbSamp_EvtIoDeviceControl;
ioQueueConfig.EvtIoCanceledOnQueue = EvtRequestCancel;
ioQueueConfig.EvtIoStop = UsbSampEvtIoStop;
status = WdfIoQueueCreate(device,&ioQueueConfig,WDF_NO_OBJE CT_ATTRIBUTES,&queue);
QUEUE DEVICE IO CONTROL:
VOID
UsbSamp_EvtIoDeviceControl(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength,
IN ULONG IoControlCode
)
...
PAGED_CODE();
//
// initialize variables
//
device = WdfIoQueueGetDevice(Queue);
pDevContext = GetDeviceContext(device);
switch(IoControlCode) {
case IOCTL_WRITE:
...
status= MyReadWriteBulkEndPoints(Queue, Request, (ULONG) bufLength, WdfRequestTypeWrite,PipeNum);
break;
BULK WRITE:
NTSTATUS MyReadWriteBulkEndPoints(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN ULONG Length,
IN WDF_REQUEST_TYPE RequestType,
IN ULONG PipeNum
)
...
deviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
UsbInterface = WdfUsbTargetDeviceGetInterface(deviceContext->WdfUsbTargetDevice,0);
pipe = WdfUsbInterfaceGetConfiguredPipe(UsbInterface,(UCH AR)PipeNum,NULL);
WDF_USB_PIPE_INFORMATION_INIT(&pipeInfo);
WdfUsbTargetPipeGetInformation(pipe, &pipeInfo);
rwContext = GetRequestContext(Request);
status = WdfRequestRetrieveOutputWdmMdl(Request, &requestMdl);
if(RequestType == WdfRequestTypeRead)
{
urbFlags |= USBD_TRANSFER_DIRECTION_IN;
rwContext->Read = TRUE;
}
else
{
urbFlags |= USBD_TRANSFER_DIRECTION_OUT;
rwContext->Read = FALSE;
}
urbFlags |= USBD_SHORT_TRANSFER_OK;
virtualAddress = (ULONG_PTR) MmGetMdlVirtualAddress(requestMdl);
newMdl = IoAllocateMdl((PVOID) virtualAddress,
totalLength,
FALSE,
FALSE,
NULL);
IoBuildPartialMdl(requestMdl,
newMdl,
(PVOID) virtualAddress,
totalLength);
WDF_OBJECT_ATTRIBUTES_INIT(&objectAttribs);
objectAttribs.ParentObject = Request;
status = WdfMemoryCreate(&objectAttribs,
NonPagedPool,
POOL_TAG,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
&urbMemory,
(PVOID*) &urb);
usbdPipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(pipe);
UsbBuildInterruptOrBulkTransferRequest(urb,
sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
usbdPipeHandle,
NULL,
newMdl,
totalLength,
urbFlags,
NULL);
status = WdfUsbTargetPipeFormatRequestForUrb(pipe, Request, urbMemory, NULL );
WdfRequestSetCompletionRoutine(Request, MyReadWriteCompletion, NULL);
WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(pipe), WDF_NO_SEND_OPTIONS));