Working with USB Pipes in UMDF 1.x Drivers
Warning
UMDF 2 is the latest version of UMDF and supersedes UMDF 1. All new UMDF drivers should be written using UMDF 2. No new features are being added to UMDF 1 and there is limited support for UMDF 1 on newer versions of Windows 10. Universal Windows drivers must use UMDF 2.
The archived UMDF 1 samples can be found in the Windows 11, version 22H2 - May 2022 Driver Samples Update.
For more info, see Getting Started with UMDF.
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:
Obtaining UMDF-USB Pipe Information
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:
IWDFUsbTargetPipe::GetInformation
Retrieves information about a USB pipe and its endpoint.
IWDFUsbTargetPipe::GetType
Returns the type of a USB pipe.
IWDFUsbTargetPipe::IsInEndPoint
Determines whether a USB pipe is connected to an input endpoint.
IWDFUsbTargetPipe::IsOutEndPoint
Determines whether a USB pipe is connected to an output endpoint.
IWDFUsbTargetPipe::RetrievePipePolicy
Retrieves a WinUsb pipe policy.
Reading from a UMDF-USB Pipe
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.
Writing to a UMDF-USB Pipe
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.
Stopping, Flushing, and Resetting a UMDF-USB Pipe
A UMDF driver can call the following methods to stop, flush, or reset a USB pipe:
IWDFUsbTargetPipe::Abort
Synchronously sends a request to stop all pending transfers on a USB pipe.
IWDFUsbTargetPipe::Flush
Synchronously sends a request to discard any data that WinUsb saved when the device returned more data than the client requested.
IWDFUsbTargetPipe::Reset
Synchronously sends a request to reset a USB pipe.
Setting Policy for a UMDF-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).
Handling Pipe Errors
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.