Working with USB Pipes in UMDF 1.x Drivers
[This topic applies to UMDF 1.x.]
The framework represents each pipe in a USB interface as a framework USB pipe object. When a driver configures a USB device, the framework creates a framework USB pipe object for each pipe in each selected interface. Pipe object methods enable a driver to:
After a UMDF driver calls the IWDFUsbInterface::RetrieveUsbPipeObject method to obtain a pointer to the IWDFUsbTargetPipe interface for a USB pipe object, the driver can call the following methods that the USB pipe object defines for obtaining information about the USB pipe:
Retrieves information about a USB pipe and its endpoint.
Returns the type of a USB pipe.
Determines whether a USB pipe is connected to an input endpoint.
Determines whether a USB pipe is connected to an output endpoint.
Retrieves a WinUsb pipe policy.
To read data from a USB input pipe, your driver can use either (or both) of the following techniques:
Read data synchronously.
To read data synchronously from a USB input pipe, a UMDF driver first calls the IWDFIoTarget::FormatRequestForRead method to build a read request. Then the driver calls the IWDFIoRequest::Send method, specifying the WDF_REQUEST_SEND_OPTION_SYNCHRONOUS flag, to send the request synchronously.
Read data asynchronously.
To read data asynchronously from a USB input pipe, a UMDF driver first calls the IWDFIoTarget::FormatRequestForRead method to build a read request. Then the driver calls the IWDFIoRequest::Send method without specifying the WDF_REQUEST_SEND_OPTION_SYNCHRONOUS flag.
Read data synchronously and continuously.
A continuous reader is a framework-supplied mechanism that ensures a read request is always available to a USB pipe. This mechanism guarantees that the driver is always ready to receive data from a device that provides an asynchronous, unsolicited input stream. For example, a driver for a network interface card (NIC) might use a continuous reader to receive input data.
To configure a continuous reader for an input pipe, the driver's IPnpCallbackHardware::OnPrepareHardware callback function must call the IWDFUsbTargetPipe2::ConfigureContinuousReader method. This method queues a set of read requests to the device's I/O target.
Also, the driver's IPnpCallback::OnD0Entry callback function must call IWDFIoTargetStateManagement::Start to start the continuous reader and the driver's IPnpCallback::OnD0Exit callback function must call IWDFIoTargetStateManagement::Stop to stop the continuous reader.
Each time that data is available from the device, the I/O target will complete a read request and the framework will call one of two callback functions: IUsbTargetPipeContinuousReaderCallbackReadComplete::OnReaderCompletion if the I/O target successfully read the data, or IUsbTargetPipeContinuousReaderCallbackReadersFailed::OnReaderFailure if the I/O target reports an error.
After a driver has called IWDFUsbTargetPipe2::ConfigureContinuousReader, the driver cannot use IWDFIoRequest::Send to send I/O requests to the pipe unless the driver's IUsbTargetPipeContinuousReaderCallbackReadersFailed::OnReaderFailure callback function is called and returns FALSE.
Continuous readers are supported in UMDF versions 1.9 and later.
To write data to a USB output pipe, a UMDF driver can first call the IWDFIoTarget::FormatRequestForWrite method to build a write request. Then the driver can call the IWDFIoRequest::Send method to send the request asynchronously.
A UMDF driver can call the following methods to stop, flush, or reset a USB pipe:
Synchronously sends a request to stop all pending transfers on a USB pipe.
Synchronously sends a request to discard any data that WinUsb saved when the device returned more data than the client requested.
Synchronously sends a request to reset a USB pipe.
A UMDF driver can call the IWDFUsbTargetPipe::SetPipePolicy method to control the behavior that is used by WinUsb for a USB pipe (for example, time-outs, handling short packets, and other behaviors).
If your driver's USB target completes an I/O request with an error status value, your driver should do the following:
Call IWDFIoTargetStateManagement::Stop with the WdfIoTargetCancelSentIo flag set. This call stops the pipe and cancels any additional I/O requests that the driver has sent to the USB target, if the target has not completed the requests.
Call IWDFUsbTargetPipe::Abort to send an abort request to the pipe.
Call IWDFUsbTargetPipe::Reset to send a reset request to the pipe.
Call IWDFIoTargetStateManagement::Start to restart the pipe.
Resend the I/O request that failed, and all I/O requests that followed the failed request.