Authored by Martin Borve [MSFT]
In 2009 we posted a detailed description of how Windows 7 enumerates a USB device. In Windows 8, we’ve made modifications in the USB driver stack on how the stack enumerates USB 2.1, 2.0, and 1.1 devices. Those modifications support new USB features and improve device enumeration performance. The purpose of this article is to bring awareness to these subtle changes and enable device/firmware builders to easily determine the root cause of enumeration failures.
Before Windows 8, the timing for delays were approximately 15-30 milliseconds longer than delays required by the official USB 2.0 specification. Cumulatively, those delays added several 100 milliseconds to the device enumeration time. In Windows 8, we’ve reduced the timing delays to 0-15 milliseconds resulting in faster enumeration.
Before Windows 8, the USB driver stack reset the device’s upstream port twice. That behavior was to support legacy USB devices that were confused by the second request for the Device Descriptor. To allow those devices to enumerate successfully, the driver stack had to reset the upstream port between the first and second requests for the Device Descriptor. This second reset was expensive in terms of enumeration time.
Because that second reset was required just to support legacy low and full-speed devices, we’ve removed it for high-speed devices in Windows 8. Just in case the first attempt to enumerate a high-speed device fails, the driver stack reverts to resetting the port twice when it retries enumeration for the device.
The USB 3.0 and USB 2.0 LPM specifications define a new USB descriptor called the Binary Device Object Store (BOS). The BOS descriptor returns a set of device-level capability descriptors for the USB device. For a USB device, which reports a bcdUSB value greater than 0x0200 in their device descriptor, in Windows 8, the USB driver stack requests for the BOS descriptor header immediately after the Language ID query request. If that request fails, the driver stack proceeds to the Product ID String query request.
If the request for the BOS descriptor header succeeds, the driver stack requests the entire BOS descriptor set by using the value returned in the BOS descriptor’s wTotalLength field as the request length. If that request fails, the driver stack will fail enumeration of the device.
Note: To make sure your device enumerates on Windows 8 and future versions of Windows, do not rely on the sequence in which the USB driver stack queries for the BOS descriptor. Instead, make sure that the device reports correct values to pass validation checks as described in these sections.
The USB driver stack validates the retrieved BOS descriptor. Make sure that in your device:
If any of those validation checks fail, the driver stack will fail enumeration of the device. Otherwise the stack validates each Device Capability Descriptor.
For each device capability descriptor returned within the BOS descriptor set, the USB driver stack validates these conditions:
If any of those validations fail, the driver stack discards the BOS descriptor and proceeds to the Product ID String query.
The driver stack validates the USB 2.0 Extension Capability Descriptor. If your device has that descriptor, make sure that:
If any of those validation checks fail, the driver stack discards the BOS descriptor and proceeds to the Product ID String query.
The USB driver stack validates the Container ID Descriptor. If your device has that descriptor, make sure that:
The USB driver stack performs generic validation checks on any other capability descriptors found. Beyond that they are ignored.