UWP中获取USB字符串描述符及识别同一物理设备双接口方法
我之前在做UWP和多接口USB设备通信时也踩过一模一样的坑,咱们一步步来搞定这两个核心需求:
一、关联同一物理设备的HID和WinUSB接口
核心思路是利用容器ID(Container ID)——这是Windows给每个物理USB设备分配的唯一标识,同一设备的所有接口(不管是HID还是WinUSB)都会共享这个ID。具体操作如下:
1. 获取HID设备的Container ID
假设你已经成功打开了HidDevice实例,通过它的设备信息ID获取对应的DeviceInformation对象,再读取System.Devices.ContainerId属性:
// 已初始化的HidDevice实例 HidDevice hidDevice = ...; var hidDeviceInfo = await DeviceInformation.CreateFromIdAsync( hidDevice.DeviceInformation.Id, new[] { "System.Devices.ContainerId" }); // 指定只获取需要的属性,提升性能 Guid hidContainerId = Guid.Parse(hidDeviceInfo.Properties["System.Devices.ContainerId"].ToString());
2. 获取WinUSB设备的Container ID
对已打开的UsbDevice实例,用同样的方式获取Container ID:
// 已初始化的UsbDevice实例 UsbDevice usbDevice = ...; var usbDeviceInfo = await DeviceInformation.CreateFromIdAsync( usbDevice.DeviceInformation.Id, new[] { "System.Devices.ContainerId" }); Guid usbContainerId = Guid.Parse(usbDeviceInfo.Properties["System.Devices.ContainerId"].ToString());
3. 判断是否为同一物理设备
只要比较两个Container ID是否相等即可:
if (hidContainerId == usbContainerId) { // 确认是同一物理设备 }
小提示:也可以用设备实例路径判断,但Container ID更可靠——即使设备插拔、驱动更新,Container ID通常保持不变,而设备实例路径可能会变化。
二、在UWP中获取USB字符串描述符
根据设备接口类型,有两种常用方法:
方法1:通过WinUSB接口获取(推荐,支持所有字符串描述符)
UsbDevice允许直接发送标准USB控制请求读取字符串描述符。比如读取产品字符串(索引对应设备描述符里的ProductStringIndex):
// 构造标准控制请求:获取字符串描述符 var controlSetup = new UsbControlSetupPacket( UsbControlDirection.In, // 数据输入(从设备到主机) UsbControlRequestType.Standard, // 标准请求类型 (byte)UsbStandardRequest.GetDescriptor, // 请求码:获取描述符 (ushort)((1 << 8) | usbDevice.DeviceDescriptor.ProductStringIndex), // 高字节=描述符类型(1=字符串),低字节=字符串索引 0x0409); // 语言ID,0x0409代表英文(可根据设备支持的语言调整) // 发送控制传输,缓冲区大小设为256(足够容纳大部分USB字符串) var transferResult = await usbDevice.SendControlInTransferAsync(controlSetup, 256); if (transferResult.Status == UsbTransferStatus.Completed) { // 字符串描述符是Unicode编码,转换为C#字符串 string productString = Encoding.Unicode.GetString(transferResult.Data).TrimEnd('\0'); }
如果要读取厂商字符串,把ProductStringIndex换成ManufacturerStringIndex即可;自定义字符串则替换为对应的索引值。
方法2:通过DeviceInformation读取常用字符串(HID设备适用)
HID API没有直接提供读取字符串描述符的方法,但可以通过DeviceInformation的内置属性获取厂商、产品名称等常用字符串——这些值就是从USB字符串描述符读取的:
var hidDeviceInfo = await DeviceInformation.CreateFromIdAsync( hidDevice.DeviceInformation.Id, new[] { "System.Devices.DeviceManufacturer", "System.Devices.DeviceProductName" }); string manufacturer = hidDeviceInfo.Properties["System.Devices.DeviceManufacturer"].ToString(); string productName = hidDeviceInfo.Properties["System.Devices.DeviceProductName"].ToString();
注意:这种方法只能获取系统预定义的几个字符串,无法读取自定义描述符,若需要自定义字符串,还是得通过WinUSB接口获取。
额外注意事项
- 确保UWP应用在
Package.appxmanifest中声明了对应设备功能:HID设备需声明DeviceCapability为humaninterfacedevice,WinUSB设备需声明usb功能并指定对应的VID/PID。 - 读取字符串描述符时,语言ID要和设备支持的一致,大部分设备支持0x0409(英文),若需其他语言,可先读取语言ID列表(字符串描述符索引0)获取设备支持的语言。
内容的提问来源于stack exchange,提问作者Damiendra Buwaneka

