WinUSB
+ -

USB WCID设备中特殊字符描述符

2021-10-14 3352 1

WCID全称”Windows Compatible ID,中文名为“Windows兼容ID”。 WCID设备是一种向Windows系统提供额外信息的USB设备,以便于自动安装驱动程序,并在某些情况下允许立即访问。

USB设备驱动的匹配安装一般是以VID/PID进行驱动匹配的,但WCID设备却是根据Compatible ID来进行匹配的。

使用Compatible ID匹配的设备,只要是 WCID 相同的设备,即使是不同厂家生产的,也可以使用相同的驱动,这样也规避了不同厂家相同功能设备的PID问题。

为了支持WCID,设备需要响应一个特殊的字符串描述符请求,并返回一个特殊的字符描串述符。 Windows 系统会根据这个字符描述符中的参数,发起厂商自定义请求来获取设备的 WCID。获取到 WCID 后,根据 WCID进行驱动匹配与安装。

其实Windows中的大部分兼容驱动设备,都是使用的兼容ID(Compatible ID)来进行匹配的。如标准的UVC设备,UAC设备和HID设备。当然系统在进行驱动匹配时会优先匹配硬件ID相同的驱动。

Windows系统中预装的WinUSB驱动支持 WCID 设备,它的兼容ID是“WINUSB”,只要我们设备的 WCID 能被识别为“ WINUSB”就能自动安装上WinUSB驱动,不需要编写INF文件。

WCID的获取条件

  • 只有 USB 2.0 或更高版本的设备才能被识别为 WCID。如果 USB 设备描述符的 bcdUSB 字段等于0x0100或0x0110,集线器驱动程序将跳过对 MS OS 描述符的查询并进入“序列号字符串描述符查询”状态

WCID的获取步骤

第一步:获取字符串描述符

USB设备接入USB端口号,Microsoft USB 端口驱动程序 ( usbport.sys) 除了读取标准 USB 描述符,其中包括标准设备、配置、接口和字符串描述符。它还将尝试读取index=0xEE 附加字符串描述符。
该字符串描描述符的结构如下:

类型 描述
0x12 字节 描述符长度(18 字节)
0x03 字节 描述符类型(3 = 字符串)
0x4D, 0x00, 0x53, 0x00,<br>0x46, 0x00, 0x54, 0x00,<br>0x31, 0x00, 0x30, 0x00,<br>0x30, 0x00 7字Unicode 字符串 (LE) 签名: “MSFT100”
0x## 字节 供应商代码
0x00 字节 填充

当系统正确并获取到此字符串前,在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\usbflags\[VID+PID+BCD_RELEASE_NUMBER]的位置创建一个键值为osvc字节的REG_BINARY的2字节密钥。

  • 如果0xEE描述符不存在,或者它与 Microsoft 签名 ( “MSFT100”)不匹配,则osvc设置为0x0000,表示该设备不是 WCID设备。
  • 如果0xEE描述符存在并且与 Microsoft 操作系统字符串描述符的预期组织相匹配,则oscv设置为0x01##,其中01表示设备满足 MS 操作系统供应商扩展,其中##是供应商代码字节值

以下是 Windows 7 为 WCID 设备(LibusbDotNet 的标准设备,其中VID为0x04D8、 PID为0xFA2E和BCD版本号0x0001)创建的密钥示例:
密钥示例
在上面的示例中,供应商代码为0x20。因此,可以通过检查注册获取设备是否是WCID设备。

第二步:获取设备的兼容ID

WCID不同的兼容ID支持的应用类型不同,所以对应的上层也是不相同的。通过获取兼容ID可以根据该兼容ID类型适配相应的应用。
Windows的兼容ID类型有以下:

由于在第一步中,系统判断oscv字段有效,这时系统会下发一个厂商自定义的USB标准请求用于获取 Compatible ID Feature Descriptor.

1字节 1字节 2字节 2字节 2字节
bmRequestType(1) bRequest(1) wValue(2) wIndex(2) wLength(2)
0xC0 供应商代码0x## 0x0000 0x0004 0x0028

返回的兼容ID特性描述符内容如下:

类型 描述
0x28, 0x00, 0x00, 0x00 DWORD (LE) Descriptor length (40 bytes)
0x00, 0x01 BCD WORD (LE) Version (‘1.0’)
0x04, 0x00 WORD (LE) Compatibility ID Descriptor index (0x0004)
0x01 BYTE Number of sections (1)
0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00 7 BYTES Reserved
0x00 BYTE Interface Number (Interface #0)
0x01 BYTE Reserved
0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00 8 BYTES (NUL-terminated)ASCII String Compatible ID (“WINUSB\0\0”)
0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00 8 BYTES (NUL-terminated?)ASCII String Sub-Compatible ID(unused)
0x00, 0x00, 0x00, 0x00,0x00, 0x00 6 BYTES Reserved

这时,系统会在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB的位置存储该设备的兼容ID.如VID_04D8&PID_FA2E目录下:
兼容ID
兼容ID的格式为USB\MS_COMP_XXXXXXXX,如这里为USB\MS_COMP_WINUSB

自定义接口GUID

上面Index=4用于获取设备的兼容ID,在windows领域内使用index=5用于获取固件自己定义的设备interface guid.

  • 如果设备只有一个接口,DeviceInterfaceGUID的GUID以NULL为结束
    一个接口

  • 如果有多个接口GUID,则以双NULL为结束。

接口GUID

感谢USB中文网文先的让反馈 https://github.com/pbatard/libwdi/issues/252

如果定义了接口GUID,在注册表中可以显示如下:

GUID
如图所述,GUID {F70242C7-FB25-443B-9E7E-A4260F373982}写入了注册表中,我们可以Setup api函数使用该GUID来枚举设备。

WCID描述符符和特性描述符示例

这里使用从http://libusb.info 下载最新的xusb通过可执行文件运行显示信息:

D:\libusb\Win32\Debug\examples>xusb -i 04d8:fa2f
Using libusb v1.0.21.11121

Opening device 04D8:FA2F...

Device properties:
        bus number: 2
         port path: 3 (from root hub)
             speed: 12 Mbit/s (USB FullSpeed)

Reading device descriptor:
            length: 18
      device class: 0
               S/N: 3
           VID:PID: 04D8:FA2F
         bcdDevice: 0001
   iMan:iProd:iSer: 1:2:3
          nb confs: 1

Reading BOS descriptor: no descriptor

Reading first configuration descriptor:
             nb interfaces: 1
              interface[0]: id = 5
interface[0].altsetting[0]: num endpoints = 2
   Class.SubClass.Protocol: 00.00.00
       endpoint[0].address: 01
           max packet size: 0020
          polling interval: 00
       endpoint[1].address: 81
           max packet size: 0020
          polling interval: 00

Claiming interface 0...

Reading string descriptors:
   String (0x01): "Travis Robinson"
   String (0x02): "Benchmark Device"
   String (0x03): "LUSBW1"
   String (0xEE): "MSFT100 "

Reading Extended Compat ID OS Feature Descriptor (wIndex = 0x0004):

  00000000  28 00 00 00 00 01 04 00 01 00 00 00 00 00 00 00  (...............
  00000010  00 01 57 49 4e 55 53 42 00 00 00 00 00 00 00 00  ..WINUSB........
  00000020  00 00 00 00 00 00 00 00                          ........

Reading Extended Properties OS Feature Descriptor (wIndex = 0x0005):

  00000000  8e 00 00 00 00 01 05 00 01 00 84 00 00 00 01 00  ................
  00000010  00 00 28 00 44 00 65 00 76 00 69 00 63 00 65 00  ..(.D.e.v.i.c.e.
  00000020  49 00 6e 00 74 00 65 00 72 00 66 00 61 00 63 00  I.n.t.e.r.f.a.c.
  00000030  65 00 47 00 55 00 49 00 44 00 00 00 4e 00 00 00  e.G.U.I.D...N...
  00000040  7b 00 46 00 37 00 30 00 32 00 34 00 32 00 43 00  {.F.7.0.2.4.2.C.
  00000050  37 00 2d 00 46 00 42 00 32 00 35 00 2d 00 34 00  7.-.F.B.2.5.-.4.
  00000060  34 00 33 00 42 00 2d 00 39 00 45 00 37 00 45 00  4.3.B.-.9.E.7.E.
  00000070  2d 00 41 00 34 00 32 00 36 00 30 00 46 00 33 00  -.A.4.2.6.0.F.3.
  00000080  37 00 33 00 39 00 38 00 32 00 7d 00 00 00        7.3.9.8.2.}...

Releasing interface 0...
Closing device...

参考资料:

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

USB WCID设备中特殊字符描述符
WCID全称”Windows Compatible ID,中文名为“Windows兼容ID”。 WCID设备是一种向Windows系统提供额外信息的USB设备,以便于自动安装驱动程序,并在某些情况下允许立即访问。USB设备驱动的匹配安装一般是以VID/PID进行驱动匹配的,但WCID设备却是根据C......
使用WinUSB读写USB设备
Windows为WinUSB设备提供了API,主要通过以下几个步骤访问设备。通过扩展描述符中的GUID查看接口的路径用接口的路径作为参数,调用CreateFile打开接口使用WinUsb_Initialize得到WinUSB句柄通过WinUsb_WritePipe和WinUsb_ReadPipe对......
使用微软系统描述符1.0制作免驱动自定义USB设备
本文作者XTOOLBOX,本站得到了作者本人的转载授权。本文介绍如何使用微软的操作系统描述符来实现自定义USB设备在Windows系统上的免驱动使用。前言在Linux上开发USB设备是不需要特别的驱动的,Linux内核的USB驱动会将USB设备的基本操作都暴露到应用层,由应用层来完成实际的业......
使用微软系统描述符2.0制作免驱动自定义USB设备
本文作者XTOOLBOX,本站得到了作者本人的转载授权。前言在《使用微软系统描述符1.0制作免驱动自定义USB设备》一文中,介绍了如何使用1.0版本的系统描述符来制作免驱动设备,这里将介绍如何使用2.0版本的系统描述符来制作免驱动设备。无论是1.0还是2.0,都是为了让系统给设备安装WinUS......
简单几步,让自定义USB设备也能免驱动运行
本文作者XTOOLBOX,本站得到了作者本人的转载授权。更完整的说明见《使用微软系统描述符1.0制作免驱动自定义USB设备》和《使用微软系统描述符2.0制作免驱动自定义USB设备》做过USB设备开发的人,对USB中的自定义HID设备一定不陌生。很多时候为了通过USB接口与上位机进行通讯,都会......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!