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

时间:2018-10-17 05:12:58

标签: 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"时,它将停止工作。我需要一个唯一的标识符。

2 个答案:

答案 0 :(得分:1)

从您的角度来看,您只是将一台设备插入计算机,而Linux内核对正在发生的事情有更复杂的了解。内核跟踪设备的层次结构,每个设备都有自己的属性,驱动程序和子设备。层次结构的根通常是代表您的CPU的某种根设备,然后将其(可能间接)连接到USB控制器设备,该设备又连接到“根集线器”,然后再将其连接到您的物理USB设备插入后,USB设备可能会为每个功能/接口配备子设备。

您可以运行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控制器,直到到达根目录为止。等级制。 --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中为您创建的符号链接;也许这些符号链接的名称中将有足够的详细信息,因此您无需创建新的udev规则。 (提示:运行ls -lR /dev/serial/by-id。)

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

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

答案 1 :(得分:0)

我能够通过输入以下内容来创建udev规则:

SUBSYSTEM=="tty", ATTRS{idVendor}=="1d6b", ATTRS{idProduct}=="0002", ATTRS{serial}=="3f980000.usb", SYMLINK+="reader1"

大卫·格雷森(David Grayson)在下面引用的答案解释了多个产品和供应商ID的原因。这就是导致我找到解决方案的原因。

  

从您的角度来看,您只是将一台设备插入计算机,而Linux内核对正在发生的事情有更复杂的了解。内核跟踪设备的层次结构,每个设备都有自己的属性,驱动程序和子设备。层次结构的根通常是代表您的CPU的某种根设备,然后将其(可能间接)连接到USB控制器设备,该设备又连接到“根集线器”,然后再将其连接到您的物理USB设备插入后,USB设备可能会为每个功能/接口配备子设备。

     

您可以运行man udevadm来了解有关命令功能的更多信息。它说:

     

-a,--attribute-walk          打印可以使用的指定设备的所有sysfs属性          在udev规则中匹配指定的设备。打印所有设备          沿着链,直到可以在udev中使用的sysfs的根          规则。   因此,存在这样的设备链,从ttyACM0(USB设备的功能)开始,一直到物理USB设备,再到根集线器,再到USB控制器,直到到达层次结构的根。 --attribute-walk选项沿该链向上移动,并沿途打印出每个设备的属性。

     

您正在将该命令的输出传递到grep中,因此您看不到完整的输出,这可能是您感到困惑的原因。该命令的完整输出实际上是非常有用的:它打印出一个漂亮的段落来说明其功能,并且当它从打印一个设备的属性切换到打印其父设备的属性时,有一些有用的句子可以使您清楚。这是我在Raspberry Pi上检查USB设备时得到的一些输出:

     

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

     

Udevadm信息从devpath指定的设备开始,然后沿父设备链向上移动。它会为找到的每个设备以udev规则键格式打印所有可能的属性。匹配的规则可以由设备的属性和单个父设备的属性组成。

     

查看设备'/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]

     

查看父设备'/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]

     

查看父设备'/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]

     

查看父设备'/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]

     

查看父设备'/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2.1':KERNELS ==“ 1-1.2.1” SUBSYSTEMS ==“ usb” [snip]

     

[...依此类推,直到根设备为止]“