Libusb无法获取USB设备序列号的技术求助
问题分析与解决方案
首先,你遇到的iSerialNumber返回0的问题,核心原因是设备描述符中的iSerialNumber只是字符串描述符的索引,并非实际的序列号字符串。返回0通常有两种情况:要么设备本身未配置序列号(部分低成本USB设备会这样),要么你没有打开设备并读取对应字符串描述符的权限。
先看你的代码,你在printdev函数里仅获取了设备描述符,但完全没尝试打开设备去读取序列号字符串。接下来我会一步步帮你修正问题:
1. 读取序列号的正确流程
要获取USB设备的序列号,必须完成以下两步:
- 打开匹配的USB设备,获取设备句柄
- 通过
libusb_get_string_descriptor_ascii函数,利用iSerialNumber索引读取实际的字符串内容
2. 代码修正示例
在你匹配到目标设备的代码块中,添加以下逻辑(同时修正一个隐藏的逻辑错误):
if((vID == 5946) && (pID == 8661)) { // 注意!你之前用了位与&,这里必须改成逻辑与&& accuPID = pID; accuVID = vID; // 新增:打开设备获取句柄 libusb_device_handle *dev_handle = nullptr; int r = libusb_open(dev, &dev_handle); if(r == LIBUSB_SUCCESS) { char serial_buf[256] = {0}; if(desc.iSerialNumber != 0) { // 先判断索引是否有效 // 读取ASCII格式的序列号字符串 r = libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, (unsigned char*)serial_buf, sizeof(serial_buf)); if(r > 0) { accuSerial = std::string(serial_buf); write_text_to_log_file("序列号获取成功:" + accuSerial); } else { write_text_to_log_file("读取序列号失败,错误码:" + std::to_string(r)); accuSerial = "读取失败"; } } else { write_text_to_log_file("设备未配置序列号(iSerialNumber为0)"); accuSerial = "无序列号"; } libusb_close(dev_handle); // 记得关闭设备句柄,避免资源泄漏 } else { write_text_to_log_file("打开设备失败,错误码:" + std::to_string(r)); accuSerial = "打开设备失败"; } accuChekFound = TRUE; usbFound = TRUE; }
3. Windows平台额外注意事项
在Windows下,libusb需要设备使用WinUSB驱动才能正常访问。如果你的设备当前用的是厂商自定义驱动,必须用工具(比如Zadig)将驱动替换为WinUSB,否则会出现权限不足、无法打开设备的问题。
4. 替代库推荐
如果你觉得libusb在Windows下的驱动配置太繁琐,可以考虑这些方案:
- Windows原生SetupAPI:无需第三方库,直接调用系统API,通过
SetupDiGetClassDevs、SetupDiGetDeviceRegistryProperty等函数读取设备注册表中的序列号信息,无需打开设备即可获取。 - Qt QUsb扩展库:专为Qt环境封装的USB库,底层基于libusb或Windows原生API,API风格更贴合Qt开发习惯,使用更简洁。
- WinUSB API:微软官方的USB用户态API,专门适配WinUSB驱动的设备,功能强大,适合需要深度控制USB设备的场景。
内容的提问来源于stack exchange,提问作者RGarland
相关产品推荐
相关产品推荐

