Windows 中的 USB ContainerID

本文提供有关 Windows 操作系统 USB ContainerID 的信息。 它包括设备制造商编程其多功能 USB 设备的指南,以便 Windows 能正确检测这些设备。

用户可以利用与计算机连接的设备的所有功能。 这包括多功能设备,如打印机、扫描仪和复印机组合设备。 Windows 支持将单个物理设备的所有功能合并到设备容器中。 设备容器是物理设备的虚拟表示形式。 这种合并是通过为物理设备枚举的每个设备功能分配 ContainerID 属性来实现的。 通过为每个设备功能分配相同的 ContainerID 值,Windows 可以识别所有设备功能都属于同一物理设备。

所有通过不同总线类型连接到计算机的设备均可支持设备容器。 但是,并非所有总线类型都会使用相同的机制来生成 ContainerID。 对于 USB 设备,设备供应商可以使用 ContainerID 描述符来描述物理设备的 ContainerIDContainerID 描述符是微软操作系统的功能描述符,可存储在 USB 设备的固件中。 要利用 Windows 中可用的新设备功能,USB 设备制造商必须在其设备中正确实现这些 ContainerID 描述符。 无论设备支持多少设备功能,USB 设备制造商只需为每个物理设备实施一个 ContainerID 即可。

有关将单个设备的所有功能合并到设备容器中的更多信息,请参阅如何生成容器 ID

有关 USB 设备的 Microsoft 操作系统描述符的更多信息,请参阅 USB 设备的 Microsoft 操作系统描述符

如何生成 USB ContainerID

以下是为 USB 设备生成 ContainerID 的两种方法:

  • USB 设备制造商通过 Microsoft OS ContainerID 描述符在设备固件中指定 ContainerID
  • Microsoft USB 中心驱动程序会根据设备的产品 ID (PID)、供应商 ID (VID)、修订号和序列号的组合自动为设备创建 ContainerID。 在这种情况下,Microsoft USB 中心驱动程序会创建一个具有最小功能的 ContainerID。 此方法仅适用于具有唯一序列号的设备。

USB ContainerID 内容

USB ContainerID 会以通用唯一标识符 (UUID) 字符串的形式呈现给操作系统。 ContainerID UUID 包含在 ContainerID 描述符中。 ContainerID 描述符是设备级Microsoft OS 功能描述符。 因此,在操作系统请求 USB ContainerID 时,描述符请求的 wValue 字段必须始终设置为零。 有关 Microsoft OS 功能描述符和描述符请求的详细信息,请参阅 Microsoft OS 1.0 描述符规范

ContainerID 描述符由标头部分组成。

Offset 字段 大小 类型 描述
0 dwLength 4 未签名的 DWord 整个 ContainerID 描述符的长度(以字节为单位)。 此字段必须始终设置为 0x18。
4 bcdVersion 2 BCD ContainerID 描述符的版本号,以二进制编码十进制 (BCD) 表示,每个小数点对应一位数字。 最重要的字节 (MSB) 包含小数点前的两位数,最不重要的字节 (LSB) 包含小数点后的两位数。 例如,版本 1.00 表示为 0x0100。 此字段必须始终设置为 0x0100。
6 wIndex 2 Word 对于 USB ContainerID 描述符,此字段始终设置为 6。

ContainerID 描述符由 ContainerID 部分组成。

Offset 字段 大小 类型 描述
0 bContainerID 16 未签名的 DWord ContainerID 数据。

设备制造商负责确保设备的每个实例都有一个普遍唯一的 16 字节 ContainerID 值。 此外,设备每次开机都必须报告相同的 ContainerID 值。 有几种成熟的算法可以生成几乎零重复的 UUID。 设备制造商可以选择最适合自己需要的 UUID 生成算法。 只要结果是唯一的,使用哪种 UUID 生成算法并不重要。

USB ContainerID 语法

ContainerID 是以 {xxxxxxxx-xxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxxxx} 的标准 UUID 字符串格式报告的。 以下是固件中 0C B4 A7 2C D1 7B 25 4F B5 73 A1 3A 97 5D DC 07 USB ContainerID 的表示示例,其格式为 {2CA7B40C-7BD1-4F25-B573-A13A975DDC07} UUID 字符串。

UCHAR ExampleContainerIDDescriptor[24] =
{
    0x18, 0x00, 0x00, 0x00,     // dwLength - 24 bytes
    0x00, 0x01,                 // bcdVersion - 1.00
    0x06, 0x00,                 // wIndex – 6 for a ContainerID
    0x0C, 0xB4, 0xA7, 0x2C,     // bContainerID -
    0xD1, 0x7B, 0x25, 0x4F,     // {2CA7B40C-7BD1-4F25-B573-A13A975DDC07}
    0xB5, 0x73, 0xA1, 0x3A,     // 0C B4 A7 2C D1 7B 25 4F B5 73 A1 3A 97 5D DC 07
    0x97, 0x5D, 0xDC, 0x07      //
}

请注意,在将其格式化为 UUID 字符串时,前 8 个字节的字节顺序发生了变化。

Microsoft OS 描述符变更

为了保留旧的 ContainerID 功能,Microsoft OS 字符串描述符包含一个标志字段,可用于指明对 ContainerID 描述符的支持。

Microsoft OS 字符串描述符的当前定义在描述符末尾包含一个 1 字节填充字段 bPad,该字段通常设置为 0。 对于支持新的 ContainerID 的 USB 设备,bPad 字段被重新定义为标志字段 bFlags。 此字段的第 1 位用于指明对 ContainerID 描述符的支持。 表 3 介绍了 USB 设备的 Microsoft OS 字符串描述符的字段。

字段 长度(字节) 说明
bLength 1 0x12 描述符的长度。
bDescriptorType 1 0x03 描述符类型。 值为 0x03 表示 Microsoft OS 字符串描述符。
qwSignature 14 'MSFT100' 签名字段。
bMS_VendorCode 1 供应商代码 供应商代码。
bFlags 1 0x02 位 0:保留
位 1:ContainerID 支持
 0:不支持 ContainerID
 1:支持 ContainerID
位 2–7:保留

目前,支持 Microsoft OS 描述符但不支持 ContainerID 描述符的出货 USB 设备的 bPad 字段设置为 0x00。 USB 中心驱动程序不会查询此类设备的 USB ContainerID 描述符。

USB 多功能设备的容器视图

ContainerID 为多功能 USB 设备提供合并设备的信息。 图 1 显示了一个示例,说明当产品中的所有单个设备使用相同的 ContainerID 时,如何将多功能打印机中的所有设备合并到单个设备容器中。

设备管理器的屏幕截图,其中显示了多功能打印机中所有设备的合并情况。

USB ContainerID HCK 要求

设备制造商必须确保其生产的每个设备实例都具有全局唯一的 ContainerID 值,这样 Windows 才能成功合并每个 USB 多功能设备的功能。 Windows 硬件认证工具包包括一项要求 (DEVFUND-0034),即在设备中实现时必须使用 USB ContainerID。 如果设备实现了 USB ContainerID,Windows 硬件认证将测试 ContainerID 作为 Microsoft OS 描述符测试的一部分,并检查 ContainerID 值是否全局唯一。 有关 Windows 硬件认证要求的详细信息,请参阅 Windows 硬件认证网站。

实现 USB ContainerID 的建议。以下是针对设计、制造和交付 USB 设备的设备供应商提出的建议:

  • 了解 Windows 如何通过使用 ContainerID 来改进对多功能和多传输 USB 设备的支持。 建议首先阅读“Windows 中的多功能设备支持和设备容器分组”。

  • 确保每个 USB 设备上的序列号都是唯一的。 Windows 硬件认证要求规定,如果设备包含序列号,则每个设备实例的序列号必须是唯一的。

  • 不要为嵌入系统的 USB 设备提供 ContainerID。 集成 USB 设备应依赖于 ACPI BIOS 设置或端口的 USB 中心描述符 DeviceRemovable 位。

  • 确保连接到系统的所有 USB 设备都有唯一的 ContainerID 值。 不要在产品线之间共享 ContainerID 值或 USB 序列号。

  • 确保正确设置设备的可移动设备功能。

    注意

    将 USB ContainerID 描述符添加到先前出货的 USB 设备的设备供应商必须增加设备描述符中的设备发布编号 (bcdDevice)。 之所以需要这样做,是因为 USB 中心驱动程序会根据设备的供应商 ID、产品 ID 和设备版本号来缓存 Microsoft OS 字符串描述符(或缺少一个字符串描述符)。 如果不递增设备版本号,中心驱动程序将不会查询新设备的 USB ContainerID(如果它之前枚举的设备实例具有相同的供应商 ID、产品 ID 和设备版本号,并且不支持 USB ContainerID 描述符)。