我正在尝试使用 udev 自动设置到 Intel RealSense D415 的符号链接。这是因为我在机器上使用多个摄像头,并且需要能够通过文件名可靠地引用它们(重新启动后不会更改)。
RealSense D415 在/dev
.我为前两个设备设置符号链接没有问题,但据我所知,除了 和KERNEL
属性之外,第一和第三个设备是相同的KERNELS
,如果首先插入另一个相机,这些属性可能会发生变化。
如何使用 udev 规则来区分这些?
输出sudo udevadm info -ap /devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.0/video4linux/video0
:
looking at device '/devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.0/video4linux/video0':
KERNEL=="video0"
SUBSYSTEM=="video4linux"
DRIVER==""
ATTR{dev_debug}=="0"
ATTR{index}=="0"
ATTR{name}=="Intel(R) RealSense(TM) 415: Int"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.0':
KERNELS=="2-1:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="uvcvideo"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="0e"
ATTRS{bInterfaceNumber}=="00"
ATTRS{bInterfaceProtocol}=="00"
ATTRS{bInterfaceSubClass}=="01"
ATTRS{bNumEndpoints}=="01"
ATTRS{iad_bFirstInterface}=="00"
ATTRS{iad_bFunctionClass}=="0e"
ATTRS{iad_bFunctionProtocol}=="00"
ATTRS{iad_bFunctionSubClass}=="03"
ATTRS{iad_bInterfaceCount}=="03"
ATTRS{interface}=="Intel(R) RealSense(TM) 415 Depth"
ATTRS{supports_autosuspend}=="1"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb2/2-1':
KERNELS=="2-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="ef"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="02"
ATTRS{bMaxPacketSize0}=="9"
ATTRS{bMaxPower}=="440mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 5"
ATTRS{bcdDevice}=="508f"
ATTRS{bmAttributes}=="c0"
ATTRS{busnum}=="2"
ATTRS{configuration}==""
ATTRS{devnum}=="2"
ATTRS{devpath}=="1"
ATTRS{idProduct}=="0ad3"
ATTRS{idVendor}=="8086"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Intel(R) RealSense(TM) 415"
ATTRS{maxchild}=="0"
ATTRS{product}=="Intel(R) RealSense(TM) 415"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="removable"
ATTRS{serial}=="736613021813"
ATTRS{speed}=="5000"
ATTRS{urbnum}=="56"
ATTRS{version}==" 3.10"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb2':
KERNELS=="usb2"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="03"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="9"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0415"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="2"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0003"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="yes"
ATTRS{manufacturer}=="Linux 4.15.0-36-generic xhci-hcd"
ATTRS{maxchild}=="10"
ATTRS{product}=="xHCI Host Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{serial}=="0000:00:14.0"
ATTRS{speed}=="5000"
ATTRS{urbnum}=="101"
ATTRS{version}==" 3.00"
looking at parent device '/devices/pci0000:00/0000:00:14.0':
KERNELS=="0000:00:14.0"
SUBSYSTEMS=="pci"
DRIVERS=="xhci_hcd"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0330"
ATTRS{consistent_dma_mask_bits}=="64"
ATTRS{d3cold_allowed}=="1"
ATTRS{dbc}=="disabled"
ATTRS{device}=="0xa2af"
ATTRS{dma_mask_bits}=="64"
ATTRS{driver_override}=="(null)"
ATTRS{enable}=="1"
ATTRS{irq}=="123"
ATTRS{local_cpulist}=="0-3"
ATTRS{local_cpus}=="f"
ATTRS{msi_bus}=="1"
ATTRS{numa_node}=="-1"
ATTRS{revision}=="0x00"
ATTRS{subsystem_device}=="0x310c"
ATTRS{subsystem_vendor}=="0x17aa"
ATTRS{vendor}=="0x8086"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
输出sudo udevadm info -ap /devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.3/video4linux/video2
:
looking at device '/devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.3/video4linux/video2':
KERNEL=="video2"
SUBSYSTEM=="video4linux"
DRIVER==""
ATTR{dev_debug}=="0"
ATTR{index}=="0"
ATTR{name}=="Intel(R) RealSense(TM) 415: Int"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1:1.3':
KERNELS=="2-1:1.3"
SUBSYSTEMS=="usb"
DRIVERS=="uvcvideo"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceClass}=="0e"
ATTRS{bInterfaceNumber}=="03"
ATTRS{bInterfaceProtocol}=="00"
ATTRS{bInterfaceSubClass}=="01"
ATTRS{bNumEndpoints}=="00"
ATTRS{iad_bFirstInterface}=="03"
ATTRS{iad_bFunctionClass}=="0e"
ATTRS{iad_bFunctionProtocol}=="00"
ATTRS{iad_bFunctionSubClass}=="03"
ATTRS{iad_bInterfaceCount}=="02"
ATTRS{interface}=="Intel(R) RealSense(TM) 415 RGB"
ATTRS{supports_autosuspend}=="1"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb2/2-1':
KERNELS=="2-1"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="ef"
ATTRS{bDeviceProtocol}=="01"
ATTRS{bDeviceSubClass}=="02"
ATTRS{bMaxPacketSize0}=="9"
ATTRS{bMaxPower}=="440mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 5"
ATTRS{bcdDevice}=="508f"
ATTRS{bmAttributes}=="c0"
ATTRS{busnum}=="2"
ATTRS{configuration}==""
ATTRS{devnum}=="2"
ATTRS{devpath}=="1"
ATTRS{idProduct}=="0ad3"
ATTRS{idVendor}=="8086"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Intel(R) RealSense(TM) 415"
ATTRS{maxchild}=="0"
ATTRS{product}=="Intel(R) RealSense(TM) 415"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="removable"
ATTRS{serial}=="736613021813"
ATTRS{speed}=="5000"
ATTRS{urbnum}=="56"
ATTRS{version}==" 3.10"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb2':
KERNELS=="usb2"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{authorized}=="1"
ATTRS{authorized_default}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{bDeviceProtocol}=="03"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPacketSize0}=="9"
ATTRS{bMaxPower}=="0mA"
ATTRS{bNumConfigurations}=="1"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bcdDevice}=="0415"
ATTRS{bmAttributes}=="e0"
ATTRS{busnum}=="2"
ATTRS{configuration}==""
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{idProduct}=="0003"
ATTRS{idVendor}=="1d6b"
ATTRS{interface_authorized_default}=="1"
ATTRS{ltm_capable}=="yes"
ATTRS{manufacturer}=="Linux 4.15.0-36-generic xhci-hcd"
ATTRS{maxchild}=="10"
ATTRS{product}=="xHCI Host Controller"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{serial}=="0000:00:14.0"
ATTRS{speed}=="5000"
ATTRS{urbnum}=="101"
ATTRS{version}==" 3.00"
looking at parent device '/devices/pci0000:00/0000:00:14.0':
KERNELS=="0000:00:14.0"
SUBSYSTEMS=="pci"
DRIVERS=="xhci_hcd"
ATTRS{broken_parity_status}=="0"
ATTRS{class}=="0x0c0330"
ATTRS{consistent_dma_mask_bits}=="64"
ATTRS{d3cold_allowed}=="1"
ATTRS{dbc}=="disabled"
ATTRS{device}=="0xa2af"
ATTRS{dma_mask_bits}=="64"
ATTRS{driver_override}=="(null)"
ATTRS{enable}=="1"
ATTRS{irq}=="123"
ATTRS{local_cpulist}=="0-3"
ATTRS{local_cpus}=="f"
ATTRS{msi_bus}=="1"
ATTRS{numa_node}=="-1"
ATTRS{revision}=="0x00"
ATTRS{subsystem_device}=="0x310c"
ATTRS{subsystem_vendor}=="0x17aa"
ATTRS{vendor}=="0x8086"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
答案1
这里似乎有一个区别因素:
ATTRS{interface}=="Intel(R) RealSense(TM) 415 Depth"
与
ATTRS{interface}=="Intel(R) RealSense(TM) 415 RGB"
为了区分多台相机,您可能需要这个:
ATTRS{serial}=="736613021813"
手册udev(7)
页说:
如果在单个规则中指定了与父设备匹配的多个密钥,则所有这些密钥必须在同一台父设备上匹配。
使接口可区分的属性位于父块中,使相机可区分的属性位于祖父母块中。因此,您必须使用多个规则行。
对于每个相机,应该有一组如下规则:
SUBSYSTEM=="video4linux", ATTRS{serial}!="736613021813", GOTO="not_first_camera"
SUBSYSTEM=="video4linux", KERNEL=="video*", ATTRS{interface}=="Intel(R) RealSense(TM) 415 Depth", SYMLINK+="cam1_depth"
SUBSYSTEM=="video4linux", KERNEL=="video*", ATTRS{interface}=="Intel(R) RealSense(TM) 415 RGB", SYMLINK+="cam1_rgb"
LABEL="not_first_camera"
如果相机序列号不匹配,第一条规则将绕过以下两条规则。这样,在第一条规则和与其关联的标签之间,我们可以确定我们正在谈论的相机的身份,并可以集中精力区分接口。
每个块应该有一个唯一的LABEL=
行和一个GOTO=
与唯一标签匹配的语句。当然,您可以SYMLINK
根据需要命名 s。
答案2
就我而言,我的 USB 集线器上有 4 个相同的摄像头。没有序列号。更糟糕的是,某些型号的相机在启动时显示为 video0..video3,而其他型号则显示为 video0..video6(每个相机两个)。我正在使用 fswebcam 拍照。如果摄像机占用两个视频编号,则只有一个可以工作。所以我收集的(相同)摄像机要么是视频 0-1-2-3,要么是视频 0-2-4-6
要识别工作视频编号,请运行循环 fswebcam -q - d /dev/videoX tpic.jpg - 其中 [X] 是 0-8 并记录哪些 X 值有效。
然后,对于每个有效的运行 udevadm info --attribute walk --name=/dev/videoX > a file
从文件中的大量输出(如上所列)中提取 (KERNEL==)[视频编号] 和 (KERNEL==)[USB 集线器端口地址] 字段。 KERNEL 和 KERNELS 之间的对应关系并不总是在重新启动后仍然存在 - 视频 0 的摄像机可能会变成视频 2 等等
因此,从提取的信息中制作一个列表,例如
内核==“video0”,子系统==“video4linux”,内核==“1-1.1.3:0”内核==“video1”,子系统==“video4linux”,内核==“1-1.1.1: 0"
ETC
最后对 KERNELS 字段上的列表进行排序,以便 KERNELS 编号(USB 集线器地址)始终位于列表中的同一位置
然后在排序列表中每行的末尾添加一个符号链接
内核==“video1”,子系统==“video4linux”,内核==“1-1.1.1:0”,SYMLINK+=“cam1”内核==“video0”,子系统==“video4linux”,内核==“ 1-1.1.3:0",SYMLINK+="cam2"
ETC
这会将摄像机编号(cam1-cam4 或任何您想要的名称)绑定到 USB 集线器端口并携带视频编号。
我写了一些 python 来完成这一切——大量的 os.system bash 调用。
一旦我有了一些有用的东西,我就失去了兴趣......如果有一种更简单的方法,那就很高兴知道。你也许可以用 bash 使用 grep 之类的东西来做到这一点