Hi, I’m Kristina Hotz, a Program Manager on the USB team. In December, I wrote a blog post - How to Generate a Container ID for a USB Device. A natural follow-up question is, as a device developer, When should I supply a container ID and how should I supply that ID so that Windows enumerates the device correctly? This post answers those questions.
First, a quick refresher:
A container ID is an identification string, which is supplied to Windows by the USB bus driver. Generally, the bus driver obtains the ID from the device. The ID is unique to a physical device; no other device has that same ID. For a composite device (print/scan/ fax machine), the container ID is the same for all the functional devnodes because they belong to the same physical device.
The Microsoft-provided USB driver stack obtains the container ID by:
- Reading the device’s container ID(s) from the Microsoft OS ContainerID descriptor
- Generating a container ID by hashing certain device information
- Generating a random GUID
- Inheriting the container ID of the parent devnode
For a flowchart that outlines the details of the assignment process, see How USB Devices are Assigned Container IDs.
For a device that is not integrated into the computer (that is, an external device), the best way to provide a container ID is through the Microsoft OS Descriptor’s ContainerID. This is particularly important if you are building a multi-transport device. If the device connects, for example, over Wi-Fi and USB, the device must report the same container ID for both transports so that Windows recognizes the device as a single piece of plastic. Without the reported container ID, during device enumeration, Windows will generate two different container IDs (one for USB, another for Wi-Fi). As a result, the physical device will appear as two devices in Devices and Printers.
If you are building a device that connects over USB exclusively, you should supply a container ID but that is not mandatory. If you do not supply a container ID, the USB bus driver generates a container ID for the device. For a composite device, Windows uses the same container ID for each of the device’s functions. For a compound device (a device with embedded hubs), as long as the removable bit is set accurately in the hub descriptor, Windows recognizes the compound device as a single device and uses the same ID for each component. Devices and Printers uses the container ID to glom pieces together and displays the device (single, composite, or compound) as a single device icon.
A device might be enumerated differently based on the speed of the port to which the device is connected. In this case, it’s still important to understand how Windows relies on the container ID to recognize the device.
For example, your device requires a set of drivers for a USB 2.0 port, and another set for a USB 3.0 port. To support this scenario the device provides a different VID/PID for each speed port but does not supply a container ID. If a user plugs-in the device to a USB 2.0 port and then moves it to a USB 3.0 port, Windows will recognize the device as two separate devices. Windows will treat each enumeration as the first for the device even if it supplies the same serial number for each speed port.
To avoid that situation, the device should supply a container ID.
By using the container ID, Windows is able to determine that the device has already been enumerated. This prevents Windows from taking unnecessary actions, like downloading photorealistic icons again.
A container ID must be a GUID. A number of tools exist to generate GUIDs. A favorite at Microsoft is guidgen.exe.
A container ID is more unique than a serial number because a serial number needs to be unique only with respect to other devices with same vendor ID and product ID. Container ID must be universally unique for each device. If two devices report the same container ID, Windows displays them as a single device. Imagine the confusion when two flash drives are connected, and the user only sees one icon in Devices and Printers.
To report a container ID, use the Microsoft OS Descriptor’s ContainerID descriptor. USB 3.0 offers an additional mechanism to report the container ID by using a Binary Device Object Store (BOS) descriptor. If you use both mechanisms, make sure that both mechanisms report the same container ID.
Windows 7 does not support USB 3.0 natively. If you are a third-party USB driver stack developer, retrieve Container IDs from the USB 3.0 BOS Descriptor and the Microsoft OS Descriptor. There should not be any discrepancy between the two identifiers; if there is, your stack should use get the container ID from the Microsoft OS Descriptor.
Multifunction Device Support and Device Container Groupings in Windows 7
Container IDs for USB Devices
Microsoft OS Descriptors