Linux下USB设备通信:如何获取正确的设备路径?
正确获取USB HID设备通信路径的方法
你打开的/dev/bus/usb/001/078是USB设备的原始控制节点,仅能用于执行USB总线级别的操作(比如读取设备描述符、配置描述符),无法直接进行HID报告的收发。对于需要通过USB报告通信的设备(通常为HID类设备),你需要找到对应的HID设备节点,比如/dev/hidrawX或/dev/input/eventX,具体取决于设备的功能类型。
步骤1:确认设备的USB类别
通过lsusb命令查看设备的Class字段,若显示为Human Interface Device(HID类,代码03),则目标节点属于hidraw或input子系统。
步骤2:用udev获取正确的通信节点路径
调整udev枚举逻辑,匹配hidraw或input子系统而非usb子系统:
针对hidraw节点(最适合HID报告收发,无需处理输入事件协议):
- 设置匹配子系统为
hidraw:udev_enumerate_add_match_subsystem(enumerate, "hidraw") - 添加vendor和product ID的匹配:
udev_enumerate_add_match_property(enumerate, "ID_VENDOR_ID", "你的vendor ID(小写十六进制)"); udev_enumerate_add_match_property(enumerate, "ID_MODEL_ID", "你的product ID(小写十六进制)"); - 枚举设备后,从udev设备对象中读取
DEVNAME属性,即为通信路径(例如/dev/hidraw0)
- 设置匹配子系统为
针对input节点(若设备作为输入设备,如键盘、鼠标类):
- 设置匹配子系统为
input:udev_enumerate_add_match_subsystem(enumerate, "input") - 同样匹配
ID_VENDOR_ID和ID_MODEL_ID,然后读取DEVNAME属性(例如/dev/input/event10)
- 设置匹配子系统为
步骤3:验证与通信
- 打开hidraw节点时,使用
O_RDWR标志即可,直接用read()和write()收发HID报告。注意:若设备使用带报告ID的格式,发送数据的第一个字节需为报告ID,接收数据的第一个字节也会是报告ID。 - 权限处理:默认情况下普通用户可能无访问hidraw/input节点的权限,可通过两种方式解决:
- 将当前用户加入
plugdev或input组:sudo usermod -aG plugdev $USER - 创建udev规则文件(如
/etc/udev/rules.d/99-your-device.rules),设置节点权限:SUBSYSTEM=="hidraw", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="yyyy", MODE="0666"
- 将当前用户加入
代码示例(简化版)
struct udev *udev = udev_new(); struct udev_enumerate *enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "hidraw"); udev_enumerate_add_match_property(enumerate, "ID_VENDOR_ID", "1234"); udev_enumerate_add_match_property(enumerate, "ID_MODEL_ID", "5678"); udev_enumerate_scan_devices(enumerate); struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate); struct udev_list_entry *entry; udev_list_entry_foreach(entry, devices) { const char *path = udev_list_entry_get_name(entry); struct udev_device *dev = udev_device_new_from_syspath(udev, path); const char *devnode = udev_device_get_devnode(dev); if (devnode) { printf("通信路径:%s\n", devnode); // 此处可打开devnode进行通信 } udev_device_unref(dev); } udev_enumerate_unref(enumerate); udev_unref(udev);
内容的提问来源于stack exchange,提问作者valdo
相关产品推荐
相关产品推荐

