linux下可直接读取/sys/bus/usb/devices/下各子目录的idvendor、idproduct等文本文件获取usb枚举信息,无需libusb或ioctl;需检查路径可读性,跳过权限不足或不存在的字段,注意厂商/产品字符串可能为空或含不可见字符。

Linux下读取/sys/bus/usb/devices/目录就能拿到枚举信息
USB设备被内核枚举后,会自动在/sys/bus/usb/devices/下生成以busnum-devnum(如1-1.2)命名的子目录,每个目录里包含idVendor、idProduct、manufacturer、product等文件。C++不需要调用libusb或ioctl就能直接读这些文本文件。
常见错误是直接opendir("/sys/bus/usb/devices")但忽略权限问题——普通用户可读,但某些字段(如bConfigurationValue)可能返回Permission denied,应跳过或静默处理。
- 遍历前先检查
/sys/bus/usb/devices是否存在且可读 - 对每个子目录,尝试读
idVendor和idProduct(十六进制字符串),失败则跳过 -
manufacturer和product可能为空或含不可见字符,建议用std::string::find_first_not_of(" ")清理
Windows上必须用SetupAPI + SetupDiGetClassDevs查USB设备
Windows不暴露类似Linux的sysfs路径,得走Win32 API。核心是调用SetupDiGetClassDevs传入GUID_DEVINTERFACE_USB_DEVICE,再用SetupDiEnumDeviceInterfaces和SetupDiGetDeviceInterfaceDetail逐个获取设备路径(如\?usb#vid_046d&pid_c52b#...)。
容易踩的坑:第一次调用SetupDiGetDeviceInterfaceDetail时传入NULL获取所需缓冲区大小,但很多人忘记检查GetLastError()是否为ERROR_INSUFFICIENT_BUFFER,导致后续读取失败;还有人误把设备路径当设备句柄直接CreateFile,其实那是用于后续DeviceIoControl的,不是打开设备本身。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 必须链接
setupapi.lib,否则链接报LNK2019: unresolved external symbol SetupDi* - 设备路径中的
VID_/PID_部分可正则提取,但注意大小写不敏感,且可能带&转义 - 若需厂商/产品字符串,得再调用
SetupDiGetDeviceRegistryProperty查SPDRP_MFG和SPDRP_FRIENDLYNAME,不是所有设备都填了这些值
libusb_get_device_list适合需要设备句柄或控制传输的场景
如果只是列设备,libusb比原生API重;但如果你后续要libusb_control_transfer发厂商请求,或者需要设备描述符(比如bNumConfigurations)、配置描述符细节,那必须用libusb。它跨平台,但底层仍依赖系统API封装。
关键点在于:libusb初始化后调用libusb_get_device_list返回的是libusb_device*指针数组,不是设备对象本身;真正读取描述符得用libusb_get_device_descriptor,而且这个函数不保证线程安全——多个线程同时调用同一设备指针可能崩溃。
- 调用
libusb_get_device_list前必须libusb_init(NULL),否则返回LIBUSB_ERROR_NO_BACKEND - 设备列表用完必须
libusb_free_device_list,否则内存泄漏(即使只读描述符也得free) - Linux下默认不支持非root用户访问USB设备,需udev规则(如
SUBSYSTEM=="usb", MODE="0664", GROUP="plugdev")
别混淆“设备节点”和“设备文件”:Linux的/dev/bus/usb/BBB/DDD不能直接fopen
有人看到/dev/bus/usb/001/002就以为能像普通文件一样fopen读取,结果fread返回0或EINVAL。这是USB设备节点,只能用ioctl(如USBDEVFS_CONTROL)通信,或者交给libusb处理。直接open它需要root权限,且读写行为未定义。
真正可安全fopen读取的,只有/sys下的那些只读文本文件;而/proc/bus/usb/在较新内核中已被移除,不要依赖。
- 试图
fread设备节点会触发内核拒绝,返回-1并设errno = EINVAL -
/dev/usb/目录(如果有)通常是hub节点,不是设备,内容无意义 - 如果真要从设备节点读原始数据,必须用
ioctl(fd, USBDEVFS_CONTROL, &ctrl)结构体,复杂度远超解析sysfs
/sys/bus/usb/devices/*/bDeviceClass这类字段可能因设备未完全初始化而暂时不存在,轮询时得加usleep(10000)再重试,而不是直接跳过。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










