Linux USB设备驱动中,VID(Vendor ID) 和 PID(Product ID) 是核心标识符,用于唯一识别USB设备厂商及具体产品型号。“Vendor” 通常翻译为 “供应商”“厂商”,指提供产品、服务或技术的个人、公司或组织。在不同领域(尤其是商业、技术、工程领域),Vendor ID 是一个由标准化组织(如 USB-IF)分配的唯一编号,用于标识硬件设备的生产厂商,确保系统(如操作系统)能识别设备的制造商,进而加载对应的驱动或配置。以下是深度技术解析:
一、VID/PID的本质与功能
1. 定义
标识符 | 长度 | 分配方 | 作用 |
---|---|---|---|
VID | 16-bit | USB-IF官方授权 | 标识设备制造商(如Intel: 0x8086) |
PID | 16-bit | 厂商自行分配 | 标识具体产品型号(如Arduino: 0x0043) |
2. 核心功能
-
设备识别:内核通过VID/PID匹配对应驱动
-
驱动绑定:避免多个驱动竞争同一设备
-
热插拔管理:
udev
规则依赖VID/PID创建设备节点 -
权限控制:
/etc/udev/rules.d
中基于VID/PID设置设备访问权限
三、源码级工作流程分析
1. 驱动注册关键代码(drivers/usb/core/driver.c)
c
struct usb_driver my_driver = { .name = "my_usb_drv", .id_table = my_usb_ids, // 重点:VID/PID匹配表 .probe = my_probe, .disconnect = my_disconnect, }; static struct usb_device_id my_usb_ids[] = { { USB_DEVICE(0x1234, 0x5678) }, // VID=0x1234, PID=0x5678 { } // 终止项 }; MODULE_DEVICE_TABLE(usb, my_usb_ids);
-
USB_DEVICE宏:将VID/PID组合为32位匹配键(
match_flags | (vid<<16) | pid
)
2. 内核设备匹配流程
3. 匹配函数源码(drivers/usb/core/driver.c)
c
static int usb_device_match(struct device *dev, struct device_driver *drv) { struct usb_interface *intf; struct usb_driver *usb_drv = to_usb_driver(drv); // 关键匹配逻辑 if (usb_match_id(dev, usb_drv->id_table)) return 1; return 0; }
三、设备树(Device Tree)中的VID/PID应用
1. 设备树覆盖场景
当标准USB枚举无法满足需求时(如定制硬件),需在设备树中显式定义:
dts
// arch/arm/boot/dts/myboard.dts &usb1 { status = "okay"; custom_device@1 { compatible = "vendor,custom-device"; reg = <1>; // 设备地址 vendor-id = <0x1234>; // VID product-id = <0x5678>; // PID // 附加参数 max-power = <500>; // mA }; };
2. 驱动解析设备树(示例)
c
static int my_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; u32 vid, pid; // 从设备树节点提取VID/PID of_property_read_u32(dev->of_node, "vendor-id", &vid); of_property_read_u32(dev->of_node, "product-id", &pid); // 注册USB设备 struct usb_device *udev = usb_get_dev_by_vid_pid(vid, pid); ... }
四、VID/PID的高级应用场景
1. 多设备复合驱动
c
static struct usb_device_id multi_ids[] = { { USB_DEVICE(0x1234, 0x1111) }, // 型号A { USB_DEVICE(0x1234, 0x2222) }, // 型号B { USB_DEVICE_INTERFACE_CLASS(0x1234, 0x3333, 0xFF) }, // 特定接口类 { } };
-
USB_DEVICE_INTERFACE_CLASS:同时匹配接口类/子类/协议
2. 动态PID支持
某些设备通过固件切换PID:
bash
# 通过sysfs动态修改PID echo 0x5678 > /sys/bus/usb/devices/1-1/idProduct
3. udev规则示例(权限控制)
bash
# /etc/udev/rules.d/99-mydevice.rules SUBSYSTEM=="usb", ATTR{idVendor}=="1234", ATTR{idProduct}=="5678", MODE="0666"
五、调试技巧与工具
1. 查看设备VID/PID
bash
lsusb -v | grep -E "idVendor|idProduct" # 输出示例: # idVendor 0x1234 Vendor Inc. # idProduct 0x5678 SuperDevice
2. 内核调试信息
启用CONFIG_USB_DEBUG
后:
dmesg
[ +0.000153] usb 1-1: New USB device found, idVendor=1234, idProduct=5678
3. 设备树查看
bash
dtc -I fs /sys/firmware/devicetree/base | grep vendor-id
六、设计注意事项
-
冲突避免
-
新设备VID需向USB-IF申请($5000费用)
-
临时开发可使用测试VID:
0xAAAA
~0xAF00
-
-
设备树覆盖优先级
内核实际匹配顺序:plaintext
设备树定义 > 模块id_table > 内置驱动id_table
-
热插拔延迟优化
在设备树中预定义VID/PID可减少枚举时间300ms以上
总结
VID/PID在Linux USB生态中扮演着设备身份证角色:
-
驱动绑定:通过
struct usb_device_id
实现精准匹配 -
设备树集成:解决非标准硬件枚举问题
-
权限管理:为
udev
提供硬件级标识依据
深入理解其机制,是开发稳定USB设备驱动的关键前提。