Linux USB设备驱动中的VID和PID详解——linux驱动源码工作分析

Linux USB设备驱动中,VID(Vendor ID) 和 PID(Product ID) 是核心标识符,用于唯一识别USB设备厂商及具体产品型号。“Vendor” 通常翻译为 “供应商”“厂商”,指提供产品、服务或技术的个人、公司或组织。在不同领域(尤其是商业、技术、工程领域),Vendor ID 是一个由标准化组织(如 USB-IF)分配的唯一编号,用于标识硬件设备的生产厂商,确保系统(如操作系统)能识别设备的制造商,进而加载对应的驱动或配置。以下是深度技术解析:


一、VID/PID的本质与功能

1. 定义
标识符长度分配方作用
VID16-bitUSB-IF官方授权标识设备制造商(如Intel: 0x8086)
PID16-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

六、设计注意事项

  1. 冲突避免

    • 新设备VID需向USB-IF申请($5000费用)

    • 临时开发可使用测试VID:0xAAAA~0xAF00

  2. 设备树覆盖优先级
    内核实际匹配顺序:

    plaintext

    设备树定义 > 模块id_table > 内置驱动id_table
  3. 热插拔延迟优化
    在设备树中预定义VID/PID可减少枚举时间300ms以上


总结

VID/PID在Linux USB生态中扮演着设备身份证角色:

  • 驱动绑定:通过struct usb_device_id实现精准匹配

  • 设备树集成:解决非标准硬件枚举问题

  • 权限管理:为udev提供硬件级标识依据
    深入理解其机制,是开发稳定USB设备驱动的关键前提。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值