Hi,
As you’ve seen, there are a series of Configuration to accomplish in order to have a fully transactional USB Driver, now is the time on I/O Configuration which sounds also as IO Implementation. Essentially we have to implement a Device IO Control Handler, in other words a mechanism that for each IO Request provides a different procedure.
This is the procedure to send an IO Request (directly taken from Microsoft USB_WDF Documentation):
- Create the request or use a request that the framework delivered.
- Set up the memory objects and buffers for the request.
- Format the request.
- Set an I/O completion callback for the request, if appropriate.
- Send the request.
Let’s consider an InGoing requests are processed troughout In/Out Endpoints, so everything you put into In-Endpoint are pulled out the Out-Endpoint, we have the called Double Buffered Mechanism.
VOID
EvtDeviceIoWrite(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT devCtx = NULL;
WDFMEMORY requestMem;
devCtx = GetDeviceContext(WdfIoQueueGetDevice(Queue));
status = WdfRequestRetrieveInputMemory(Request, &requestMem);
status = WdfUsbTargetPipeFormatRequestForWrite(
devCtx->UsbBulkOutPipe,
Request,
requestMem,
NULL);
WdfRequestSetCompletionRoutine(Request,
EvtIoWriteComplete,
devCtx->UsbBulkOutPipe);
status = WdfRequestGetStatus(Request);
WdfRequestComplete(Request, status);
The EvtIoWriteComplete associated with our EvtDeviceIoWrite to fix unreferenced parameters as Context and Target.
Let’s se now an Asynchronous Read Request:
VOID EvtIoReadRequest(IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t Length
)
{
WDFUSBPIPE pipe;
NTSTATUS status;
WDFMEMORY reqMemory;
PDEVICE_CONTEXT pDeviceContext;
pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));
pipe = pDeviceContext->BulkReadPipe;
status = WdfRequestRetrieveOutputMemory(Request, &reqMemory);
status = WdfUsbTargetPipeFormatRequestForRead(pipe,
Request,
reqMemory,
NULL // Offsets
);
WdfRequestSetCompletionRoutine( Request,
EvtRequestReadCompletionRoutine,
pipe
);
if (WdfRequestSend(Request,
WdfUsbTargetPipeGetIoTarget(pipe),
WDF_NO_SEND_OPTIONS) == FALSE) {
status = WdfRequestGetStatus(Request);
goto Exit;
}
Exit:
if (!NT_SUCCESS(status)) {
WdfRequestCompleteWithInformation(Request, status, 0);
}
return;
}
[Code is taken from USB_WDF.doc]
As you’ve seen from the code, the involved Functions are WdfRequestRetrieveOutputMemory, WdfUsbTargetPipeFormatRequestForRead and WdfUsbTargetPipeGetIoTarget, for the Reading Process.
For write request we have WdfUsbTargetPipeFormatRequestForWrite and WdfUsbTargetPipeWriteSynchronously.
Here some coding reference:
http://www.microsoft.com/whdc/driver/wdf/default.mspx
http://www.microsoft.com/whdc/driver/wdf/kmdf-arch.mspx
http://go.microsoft.com/fwlink/?LinkId=80613
http://go.microsoft.com/fwlink/?LinkId=80619
With this post, ends the pure theoretical part, next post will contains 1 or 2 downloadable source code drivers, and observations about USB Security.
http://go.microsoft.com/fwlink/?LinkId=83355