![]() |
![]() |
All Products | Support | Search | microsoft.com Home | |
![]() |
![]() | ||
Home | Technologies | Initiatives | Design Guides | Resources | About This Site | |
WDM USB Driver Interface
Introduction
Important: This document is provided for an early view of the proposed interfaces. Changes may be made to any part of this document, especially the details.
The USB Driver Interface (USBDI) is part of the Microsoft® Windows® Driver Model (WDM) layered architecture for the Microsoft Windows operating systems. USBDI is the interface offered to client drivers by the operating system USB driver stack.
Part of the WDM architecture is shown in Figure 1, with the USBDI highlighted. USBDI is an IRP-based interface; individual requests are packaged within a WDM I/O request packet (IRP) and are passed to the device object of the next driver in the stack - the device object is returned from the client driver's call to IoAttachDeviceToStack
Figure 1. A portion of the WDM layered architecture, with the USB driver interface highlighted.
The following modules are shown in Figure 1.
- HIDCLASS.SYS is the HID class driver. It sends and receives HID reports to and from its minidrivers.
- HIDUSB.SYS is the HID device driver. It sends and receives HID reports over the USB bus.
- USBHUB.SYS is the USB hub driver. It is loaded when USBD.SYS enumerates the root hub built into each USB host controller, as the driver for each host controller is loaded. USBHUB.SYS is also loaded each time USBHUB.SYS enumerates an external hub to the bus.
- USBD.SYS is the USB class driver.
- UHCD.SYS and OpenHCI.SYS are USB host controller drivers. (OpenHCI.SYS for the Open Host Controller Interface or UHCD.SYS for the Universal Host Controller Driver)
- PCI Enumerator takes care of loading the USB stack driver components when a USB bus is detected on a platform and always loads at least the other core components.
Overview
A WDM USB device driver communicates with a WDM USB stack through an IRP interface. There are two ways to call DDIs:
- The client device driver passes USB request block (URB) structures to the next-lower driver as a parameter in an IRP with Irp->MajorFunction set to IRP_MJ_INTERNAL_DEVICE_CONTROL and the next IRP stack location Parameters.DeviceIoControl.IoControlCode field set to IOCTL_INTERNAL_USB_SUBMIT_URB.
- The client device driver passes an IRP with Irp->Majorfunction set to IRP_MJ_INTERNAL_DEVICE_CONTROL, and the next IRP stack location Parameters.DeviceIoControl.IoControlCode field set to one of the IOCTL_INTERNAL_USB_ other function codes.
The client device driver and bus driver share information in the common structures USBD_INTERFACE_INFORMATION and USBD_PIPE_INFORMATION.
I/O Request Packet Transfers
IRPs are passed to the next lower driver by using the WDM function IoCallDriver with the device object of the next lower driver as a parameter. The device object of the next lower driver for all USB client device drivers is the DeviceObject returned from the call to IoAttachDeviceToStack.
IOCTL Codes
USB client device drivers must use the IOCTL codes listed in the following table for IRP_MJ_INTERNAL_DEVICE_CONTROL. The parameter format expected for this function is:
IO_STACK_LOCATION.Parameters.Others.Argument1 = pointer to USB request block
IRP Major Function Description IOCTL_INTERNAL_USB_SUBMIT_URB Used by USB client device drivers to submit URBs to the USB stack. IOCTL_INTERNAL_USB_RESET_PORT Details to be provided in a later draft. IOCTL_INTERNAL_USB_ENUMERATE Used to retrieve a list of all devices on the bus. IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO Details to be provided in a later draft.
USB Request Block Transfers
Clients send these requests to the bus by including them in an IRP pointer to a URB structure; a function code within the URB identifies the specific request.
For transfer requests, multiple URB structures may be linked and passed in with a single IRP.
The USB driver stack components assume all URB structures passed to them are allocated from the nonpaged pool.
Common URB Header Structure
Different URB structures are defined for each function. However, every URB has a common header, which is defined below. The header portion of a URB must always be initialized with the input parameters Length and Function, and will always return the output parameter Status.
struct _URB_HEADER {
USHORT Length;
USHORT Function;
USBD_STATUS Status;
PVOID UsbdDeviceHandle;
ULONG UsbdFlags;
};Length
Specifies the size (in bytes) of the specific URB_XXX request structure.Function
Function code set to URB_FUNCTION_XXX, where XXX refers to USB device driver-provided functions.Status
USB_STATUS_XXX status code for the given request.UsbdDeviceHandle
This field is reserved for operating system USB stack use.UsbdFlags
This field is reserved for operating system USB stack use.Bandwidth Allocation
Bandwidth allocation occurs through the process of selecting a configuration or interface and acquiring open pipe handles. While a driver holds an open handle for a specific pipe, the bandwidth necessary to transfer data on that pipe (based on maximum packet size and service interval) is reserved.
URB Transfer Requests
This section describes the following aspects of URB transfer requests: transfer flags, status codes, halt/stall behavior, and linked URBs.
Transfer Flags
The TransferFlags parameter of the URB is used to control certain options of a transfer and to indicate direction. The following flags are defined:
Transfer Flag Value Description USBD_SHORT_TRANSFER_OK This bit is used only when the USBD_TRANSFER_DIRECTION_IN bit is set.
When a packet is received from a device that is shorter than MaxPacket for the endpoint and does not exactly fill the buffer (unless USBD_SHORT_TRANSFER_OK is set) the transfer will be terminated with an error.
For control endpoints, if a short transfer occurs and USB_SHORT_TRANSFER_OK is set, then the HCD will immediately proceed to the status phase of the command; otherwise, the error is reported and neither the status phase nor the remainder of the data phase will be run.
USBD_START_ISO_TRANSFER_ASAP Details to be provided in a later draft. USBD_TRANSFER_DIRECTION_IN This bit is set if the data payload direction is device-to-host.
This bit needs to be set by the client drivers only when issuing a control transfer for the nondefault pipe. The proper value will be set by USBD for all other transfer requests, including control transfer requests on the default pipe.
Status Codes
Usbdi.h defines a set of private USB_STATUS_XXX values that are returned from calls to IRP_MJ_INTERNAL_DEVICE_CONTROL in the status field of the URB. The status field in the IRP is always set to a valid NTSTATUS code. USBD maps the URB status code to a valid NTSTATUS code and sets the status field in the IRP to the NTSTATUS code when it completes the IRP. This way, a USB client device driver does not need to perform mapping of USB error codes unless it wishes to. See Usbdi.h for a list of these.Halt/Stall Behavior
PIPE HALTED is the term used to refer to a host-side stall, the condition where current transfers for a pipe are halted and new transfers are rejected by the software stack.When an error occurs during a transfer (for example, a time-out or a stall PID returned), the HCD immediately completes the URB with whatever the error code was for that URB. All subsequent linked URBs in the IRP complete with USBD_STATUS_CANCELED. The pipe is set to the HALTED state, and no further transfers can be submitted to the pipe associated with this endpoint. If any additional requests are queued for this pipe, they will remain queued (these transfers will not be completed).
When the USB driver issues the URB_FUNCTION_RESET_PIPE request for the halted pipe, transfers to the associated pipe will resume with the next queued URB.
- Halt behavior on the default control pipe. Since devices are required to always accept a setup packet on the control pipe, the USB stack implements an autoclearing mechanism for the halt condition on this pipe. In addition to automatically clearing the HALTED state of the endpoint, the returned USBD_STATUS_XXX value will have the HALT bit clear, that is the value will be 8xxxxxxxh instead of Cxxxxxxxh. Because of this, the control pipe will never enter the HALTED state and the client driver need not take any special action to clear the condition when an error occurs.
- Halt behavior on isochronous pipes. Because of the nature of isochronous data transfers, these pipes will never enter the halted state.
![]() |
|
|