Technology Sharing

Windows USB device driver development - USB bandwidth

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

This article discusses guidance on how to carefully manage USB bandwidth. Each USB client driver is responsible for minimizing the USB bandwidth it uses and returning unused bandwidth to the pool of available bandwidth as quickly as possible.

Here, we think that the speed of USB 2.0 is 480Mbps, 12Mbps, and 1.5Mbps, which correspond to high speed, full speed, and low speed respectively. But in fact, the bandwidth of USB 2.0 is very tight, which is also one of the premises of this article. USB 3.0 seems to alleviate the bandwidth problem, but the bandwidth problem is not that the upper limit is insufficient but the scheduling problem.

Why do I get insufficient bandwidth errors with my USB driver?

Competition for bandwidth on the USB bus comes from many sources, both hardware and software. It is difficult to accurately predict the amount of bandwidth available to a USB client driver. A USB host controller requires a certain amount of bandwidth to operate. The amount required depends on whether the controller is high-speed. It varies from system to system. A USB hub operating at high speed must sometimes translate transactions between a high-speed upstream port and a downstream low-speed device, and this translation process consumes bandwidth. However, whether or not bandwidth is required for transaction translation depends on the type of device connected and the topology of the device tree.

The most severe pressure on bandwidth resources often comes from USB client drivers that monopolize bandwidth. The system allocates bandwidth on a first-come, first-served basis. If the first USB driver loaded requests all available bandwidth, USB drivers loaded later are not allowed any bandwidth for their devices. The system cannot configure the device and cannot enumerate it. Because the reason for the enumeration failure is not obvious, the user experience is poor.

Sometimes a client driver exhausts available bandwidth with high-speed interrupt transfers. But by far the most common situation is that the client driver allocates too much bandwidth for constant transfers and fails to release the bandwidth in a timely manner. The system reserves the allocated bandwidth until the driver that requested it closes its endpoint by opening another endpoint, or removes the device to which the bandwidth was allocated. The system does not allocate guaranteed bandwidth for bulk transfers, so bulk transfers are never a cause of enumeration failure. However, the performance of bulk transfer devices depends on the amount of bandwidth allocated to the device for periodic (constant isochronous and interrupt) transfers.

The USB 2.0 specification requires that constant devices have zero-bandwidth endpoints on their default interface settings. This ensures that no bandwidth is reserved for the device until the function driver opens the non-default interface, which helps prevent enumeration failures due to excessive bandwidth requests during device configuration. It does not prevent a client driver from allocating excessive bandwidth after configuring its device, thereby preventing other devices from functioning properly.

The key to proper bandwidth management is that every USB device in the system that performs constant transfers must provide multiple alternate (Alt) settings for each interface that contains constant endpoints, and the client driver must use these Alt settings judiciously. The client driver should first request the interface setting with the highest bandwidth. If the request fails, the client driver should request interface settings with increasingly smaller bandwidths until the request succeeds.

For example, suppose a webcam device has the following interface:

Interface 0 (default interface settings: no endpoints with non-zero constant bandwidth in the default settings)

Constant Endpoint1: Maximum Packet Size = 0 Bytes

Constant Endpoint2: Maximum Packet Size = 0 Bytes

Interface 0 Alt Setting 1

Constant Endpoint1: Maximum Packet Size = 256 Bytes

Constant Endpoint2: Maximum Packet Size = 256 Bytes

Interface 0 Alt Setting 2

Constant Endpoint1: Maximum Packet Size = 512 Bytes

Constant Endpoint2: Maximum Packet Size = 512 Bytes

The webcam's driver configures the webcam to use default interface settings at initialization. The default settings do not have constant bandwidth, so using the default settings during initialization avoids the danger of the webcam failing to enumerate due to a failed constant bandwidth request.

When the client driver is ready to perform an isochronous transfer, it should try using Alt setting 2 because Alt setting 2 has the largest packet size. If the request fails, the driver can make a second attempt using Alt setting 1. Because Alt setting 1 requires less bandwidth, this request might succeed even if the first request failed. Multiple Alt settings allow the driver to make multiple attempts before giving up.

Once the webcam becomes idle, the allocated bandwidth can be returned to the available bandwidth pool by selecting the default setting again.

Users can see how much bandwidth is allocated by the USB controller by checking the controller's properties in Windows Device Manager. Select the controller's properties and look under the Advanced tab. This readout does not indicate how much bandwidth the USB hub is allocating for transaction translation.

The Device Manager feature that reports USB controller bandwidth usage does not work properly in Windows XP.

USB Transfer and Packet Size
Maximum transfer size

Maximum transfer sizes specify hard-coded limits in the USB driver stack. Transfer sizes below these limits might fail due to system resource limitations. To avoid these types of failures and ensure compatibility across all versions of Windows, avoid using large transfer sizes for USB transfers.

The MaximumTransferSize member of the USBD_PIPE_INFORMATION structure is obsolete. The USB driver stack ignores the value in MaximumTransferSize for composite and non-composite devices.

In Windows 2000, the USB driver stack initializes MaximumTransferSize to USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE. The client driver can set a smaller value when configuring the device. For composite devices, the client driver can change MaximumTransferSize for pipes in non-default interface settings per function only.

USB transfer sizes are subject to the following limitations:

Limiting the transfer size using MaximumTransferSize does not directly affect the bandwidth consumed by the device. The client driver must either change the interface settings or limit the maximum packet size set in the MaximumPacketSize member of USBD_PIPE_INFORMATION.

Maximum packet size

The maximum packet size is defined by the wMaxPacketSize field of the endpoint descriptor. The client driver can adjust the USB packet size in the select interface request to the device. Changing this value does not change the wMaxPacketSize on the device.

In the URB of the request is a USBD_PIPE_INFORMATION structure for the pipe. In this structure,

  • Modify the MaximumPacketSize member of the USBD_PIPE_INFORMATION structure. Set it to a value less than or equal to the wMaxPacketSize defined in the device firmware for the current interface settings.
  • Set the USBD_PF_CHANGE_MAX_PACKET flag in the PipeFlags member of the USBD_PIPE_INFORMATION structure.
Read the maximum packet size limit for the transmit buffer

When the client driver issues a read request, the transfer buffer must be a multiple of the maximum packet size. Even if the driver requires less data than the maximum packet size, it must still request the entire packet. When the device sends a packet that is smaller than the maximum size (a short packet), the transfer is complete.

On older controllers, the client driver can override this behavior. In the TransferFlags member of the data transfer URB, the client driver must set the USBD_SHORT_TRANSFER_OK flag. This flag allows the device to send packets smaller than wMaxPacketSize.

On xHCI host controllers, USBD_SHORT_TRANSFER_OK is ignored for bulk and interrupt endpoints. Transmitting short packets on EHCI controllers does not cause an error condition.

On EHCI host controllers, USBD_SHORT_TRANSFER_OK is ignored for bulk and interrupt endpoints.

On UHCI and OHCI host controllers, if USBD_SHORT_TRANSFER_OK is not set for bulk or interrupt transfers, short packet transfers stall the endpoint and return an error code for the transfer.

Use short packets to separate write transfers

The USB driver stack driver imposes different limits on packet sizes when writing to a device than when reading from a device. Some client drivers must frequently transmit small amounts of control data to manage their device. In this case, it is impractical to restrict data transfers to packets of a uniform size. Therefore, during data writes, the driver stack does not assign any special meaning to packets whose size is less than the maximum size for the endpoint. This allows the client driver to break up large transfers to the device into multiple URBs whose sizes are less than or equal to the maximum.

The driver must end the transfer with a packet smaller than the maximum size, or with a zero-length packet to delimit the end of the transfer. The transfer is not complete until the driver sends a packet smaller than wMaxPacketSize. If the transfer size is an exact multiple of the maximum, the driver must send a zero-length delimiting packet to explicitly terminate the transfer.

As required by the USB specification, the client driver is responsible for delimiting data transfers using zero-length packets. The USB driver stack does not automatically generate these packets.

Use packets smaller than wMaxPacketSize to separate USB data transfers

Compliant USB 2.0 and USB 1.1 drivers must transfer packets of the maximum size (wMaxPacketSize) and then terminate the transfer with a packet smaller than the maximum size, or with a zero-length packet to delimit the end of the transfer. The transfer is not complete until the driver sends a packet smaller than wMaxPacketSize. If the transfer size is an exact multiple of the maximum, the driver must send a zero-length delimiting packet to explicitly terminate the transfer.

The device driver is responsible for delimiting data transfers with zero-length packets as required by the USB specification. The system USB stack does not automatically generate these packets.