linux - 为什么我有多个产品和供应商 ID?

标签 linux usb udev

目标: 我正在尝试将 4 个 RFID 读取器连接到 Pi,并且需要区分每个读取器的端口。

我做了什么: 我输入lsusb进入终端,只插入一个读卡器。它返回:

Bus 001 Device 004: ID 0c27:232a RFIDeas, Inc

这是我的读者。 所以我的供应商 ID 应该是 0c27我的产品 ID 应该是 232a 现在我需要序列号,因为我的所有读者都显示相同的供应商和产品 ID。

我的设备位于端口 ttyACM0 ,因此在终端中我搜索序列属性并通过输入以下内容来验证我的产品 ID 和供应商 ID:

udevadm info --name=ttyACM0 --attribute-walk | grep -i "serial" -e "product" -e "vendor"

这将返回:

ATTRS{idProduct}=="232a"
ATTRS{idVendor}=="0c27"
ATTRS{product}=="USB Serial"
ATTRS{idProduct}=="9514"
ATTRS{idVendor}=="0424"
ATTRS{idProduct}=="0002"
ATTRS{idVendor}=="1d6b"
ATTRS{product}=="DWC OTG Controller"
ATTRS{serial}=="3f980000.usb"

问题: 返回 3 个产品 ID 和 3 个供应商 ID。而只有一个序列号返回。

问题:

  1. 当仅连接一台设备时,为什么会返回 3 个产品 ID 和 3 个供应商 ID?

  2. 我应该在 udev 规则中使用哪些来创建持久设备名称?

如果我遗漏了某些内容,请告诉我,以便我更新问题。

编辑: 我已使用首先提到的产品 ID 和供应商 ID 成功创建了 udev 规则:

SUBSYSTEM=="tty", ATTRS{idVendor}=="0c27", ATTRS{idProduct}=="232a", SYMLINK+="reader1"

这会创建一个有效的 udev 规则,但是当我添加序列号 # ATTRS{serial}=="3f980000.usb" 时它停止工作。我需要一个唯一的标识符。

最佳答案

虽然从您的角度来看,您只是将一个设备插入计算机,但 Linux 内核对正在发生的情况有更复杂的看法。内核跟踪设备的层次结构,每个设备都有自己的属性、驱动程序和子设备。层次结构的根通常是代表 CPU 的某种根设备,然后连接(可能间接)到 USB Controller 设备,USB Controller 设备连接到“根集线器”,然后连接到您插入的物理 USB 设备,而该物理 USB 设备又可能具有用于 USB 设备公开的每个功能/接口(interface)的子设备。

您可以运行man udevadm详细了解该命令的作用。它说:

   -a, --attribute-walk
       Print all sysfs properties of the specified device that can be used
       in udev rules to match the specified device. It prints all devices
       along the chain, up to the root of sysfs that can be used in udev
       rules.

因此存在这样的设备链,从 ttyACM0(USB 设备的一个函数)开始,向上到达物理 USB 设备,然后是根集线器,然后是 USB Controller ,直到到达层次结构的根。 --attribute-walk选项沿着该链向上走,并打印出沿途每个设备的属性。

您正在将该命令的输出通过管道传输到 grep所以你没有看到完整的输出,这可能是你感到困惑的原因。该命令的完整输出实际上信息量很大:它打印出一个很好的段落来解释它的作用,并且当它从打印一个设备的属性切换到打印其父设备的属性时,有一些有用的句子可以让情况变得清晰。以下是我在检查 Raspberry Pi 上的 USB 设备时得到的一些输出:

$ udevadm info --name=sda2 --attribute-walk

Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.

  looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host0/target0:0:0/0:0:0:0/block/sda/sda2':
    KERNEL=="sda2"
    SUBSYSTEM=="block"
    [snip]

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host0/target0:0:0/0:0:0:0/block/sda':
    KERNELS=="sda"
    SUBSYSTEMS=="block"
    [snip]

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0/host0/target0:0:0':
    KERNELS=="target0:0:0"
    SUBSYSTEMS=="scsi"
    [snip]

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1/1-1.2.1:1.0':
    KERNELS=="1-1.2.1:1.0"
    SUBSYSTEMS=="usb"
    [snip]

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1':
    KERNELS=="1-1.2.1"
    SUBSYSTEMS=="usb"
    [snip]

  [... and so on, up to the root device]

不幸的是,从你的 udevadm 的输出来看命令,您的 RFID 适配器似乎没有 USB 序列号,因此将其与相同型号的其他设备区分开可能会很棘手。要确认它没有序列号,我建议您运行 lsusb -v -d 0c27:232a | grep iSerial 。如果 iSerial 之后的数字为0,表示没有序列号。

我建议查看 Linux 在 /dev/serial/by-id 中为您创建的符号链接(symbolic link)。 ;也许这些符号链接(symbolic link)的名称中有足够的详细信息,因此您无需创建新的 udev 规则。 (提示:运行 ls -lR /dev/serial/by-id 。)

如果您仍然需要更多帮助来查找或创建稳定的符号链接(symbolic link),我认为您应该插入所有四个 RFID 读取器,然后发布每个命令的完整输出:

ls -lR /dev/serial/by-id
ls /dev/ttyACM*
udevadm info --name=ttyACM0 --attribute-walk

关于linux - 为什么我有多个产品和供应商 ID?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52847664/

相关文章:

linux - 使用unix脚本发布一条一条地显示和删除记录

Linux命令: How to move files from a directory to another with waiting a few seconds

android - adb 安装命令不起作用

c - 具有多个读取操作、ioctl 或 fops 的 Linux USB 驱动程序?

类型固定但没有 USB 硬盘的 C# getdrives?

shell - 将参数从 udev 规则文件传递给 shell 脚本

linux - 启动时自动挂载独立分区时 systemd/udev 依赖失败

c++ - 在使用 Qt 制作的 GUI 上按下按钮时启动 shell 脚本

linux - 为什么在 Linux 中 spin_lock 和 spin_unlock 之间的中断被禁用?

linux - ttyusb udev 按硬件端口命名