Как создать правило udev для двух устройств с одинаковым идентификатором производителя, идентификатором продукта и серийным номером?

Вопрос или проблема

У меня есть два лидаров. И в моем коде мне нужно указать порт лидара: ttyUSB0/ttyUSB1 и т.д.

У меня есть правило udev. (/etc/udev/rules.d/rplidar.rules)
rplidar.rules

# установить правило udev, сделать device_port фиксированным для rplidar
#
KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="rplidar"

Сделав это, я могу просто вызвать port=rplidar в своем коде. Но сейчас у меня есть два rplidar с одинаковыми idVendor и idProduct, как я могу их различать и создать дополнительное правило для второго лидара?

Когда я подключал только одно устройство, вот как я это делал

$ udevadm info -a -n /ttyUSB0
Udevadm info начинается с устройства, указанного по devpath, а затем
идет вверх по цепочке родительских устройств. Он печатает для каждого устройства,
найденного все возможные атрибуты в формате ключей правил udev.
Правило для совпадения может быть составлено из атрибутов устройства
и атрибутов от одного родительского устройства.

  смотрим на устройство '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.1/1-1.1:1.0/ttyUSB0/tty/ttyUSB0':
    KERNEL=="ttyUSB0"
    SUBSYSTEM=="tty"
    DRIVER==""

  смотрим на родительское устройство '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.1/1-1.1:1.0/ttyUSB0':
    KERNELS=="ttyUSB0"
    SUBSYSTEMS=="usb-serial"
    DRIVERS=="cp210x"
    ATTRS{port_number}=="0"

  смотрим на родительское устройство '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.1/1-1.1:1.0':
    KERNELS=="1-1.1:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="cp210x"
    ATTRS{authorized}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceClass}=="ff"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bInterfaceProtocol}=="00"
    ATTRS{bInterfaceSubClass}=="00"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{interface}=="CP2102 USB to UART Bridge Controller"
    ATTRS{supports_autosuspend}=="1"

  смотрим на родительское устройство '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.1':
    KERNELS=="1-1.1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="100mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bcdDevice}=="0100"
    ATTRS{bmAttributes}=="80"
    ATTRS{busnum}=="1"
    ATTRS{configuration}==""
    ATTRS{devnum}=="28"
    ATTRS{devpath}=="1.1"
    ATTRS{idProduct}=="ea60"
    ATTRS{idVendor}=="10c4"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Silicon Labs"
    ATTRS{maxchild}=="0"
    ATTRS{product}=="CP2102 USB to UART Bridge Controller"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{serial}=="0001"
    ATTRS{speed}=="12"
    ATTRS{urbnum}=="17"
    ATTRS{version}==" 1.10"

  смотрим на родительское устройство '/devices/pci0000:00/0000:00:14.0/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceProtocol}=="02"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="0mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bcdDevice}=="0286"
    ATTRS{bmAttributes}=="e0"
    ATTRS{busnum}=="1"
    ATTRS{configuration}==""
    ATTRS{devnum}=="13"
    ATTRS{devpath}=="1"
    ATTRS{idProduct}=="2744"
    ATTRS{idVendor}=="0424"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Microchip Tech"
    ATTRS{maxchild}=="4"
    ATTRS{product}=="USB2744"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="removable"
    ATTRS{speed}=="480"
    ATTRS{urbnum}=="331"
    ATTRS{version}==" 2.10"

  смотрим на родительское устройство '/devices/pci0000:00/0000:00:14.0/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{authorized}=="1"
    ATTRS{authorized_default}=="1"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{bMaxPower}=="0mA"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bcdDevice}=="0413"
    ATTRS{bmAttributes}=="e0"
    ATTRS{busnum}=="1"
    ATTRS{configuration}==""
    ATTRS{devnum}=="1"
    ATTRS{devpath}=="0"
    ATTRS{idProduct}=="0002"
    ATTRS{idVendor}=="1d6b"
    ATTRS{interface_authorized_default}=="1"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Linux 4.13.0-38-generic xhci-hcd"
    ATTRS{maxchild}=="16"
    ATTRS{product}=="xHCI Host Controller"
    ATTRS{quirks}=="0x0"
    ATTRS{removable}=="unknown"
    ATTRS{serial}=="0000:00:14.0"
    ATTRS{speed}=="480"
    ATTRS{urbnum}=="75264"
    ATTRS{version}==" 2.00"

  смотрим на родительское устройство '/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{device}=="0xa12f"
    ATTRS{dma_mask_bits}=="64"
    ATTRS{driver_override}=="(null)"
    ATTRS{enable}=="1"
    ATTRS{irq}=="126"
    ATTRS{local_cpulist}=="0-7"
    ATTRS{local_cpus}=="ff"
    ATTRS{msi_bus}=="1"
    ATTRS{numa_node}=="-1"
    ATTRS{revision}=="0x31"
    ATTRS{subsystem_device}=="0x201f"
    ATTRS{subsystem_vendor}=="0x1043"
    ATTRS{vendor}=="0x8086"

  смотрим на родительское устройство '/devices/pci0000:00':
    KERNELS=="pci0000:00"
    SUBSYSTEMS==""
    DRIVERS==""

Вы можете использовать %n вот так

SYMLINK+="rplidar%n"

если вас устраивает нумерованное устройство, предоставленное ядром. Номер, который находится в %n, определяется ядром.

Возьмите программное обеспечение от siliconelab и измените параметры контроллера CP2102 USB to UART Bridge.
Сделать это довольно быстро, примерно за 5 минут.
Каждое устройство будет иметь свое собственное имя и серийный номер…

используемый exe: install_USBXpress_SDK.exe

Ответ или решение

Как создать правило udev для двух устройств с одинаковым идентификатором производителя, идентификатором продукта и серийным номером

Если у вас есть два лидара с одинаковыми идентификаторами производителя и продукта, но с разными серийными номерами, вы можете создать правила udev, которые помогут их различать и установить жесткие символические ссылки для доступа к каждому устройству. Рассмотрим подробно, как это сделать.

1. Анализ текущего правила udev

Ваша текущая настройка udev выглядит следующим образом:

KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="rplidar"

Это правило создает символическую ссылку rplidar для любого устройства с указанными идентификатором производителя и продуктом. Однако в случае двух идентичных устройств, ваше применение правила не сможет правильно выбрать соответствующее устройство.

2. Получение информации об устройствах

Используя команду:

$ udevadm info -a -n /dev/ttyUSB0

вы можете извлечь всю информацию об устройстве и его родителях. Вам нужно искать уникальные атрибуты, которые помогут отличить одно устройство от другого.

3. Создание уникальных правил

Одним из способов различения устройств является использование атрибута серийного номера, если ваши устройства его имеют, или настройка другого устройства через программное обеспечение, как вы уже упоминали.

Предположим, что вы можете изменить настройку устройства CP2102 USB до UART, чтобы у каждого устройства был уникальный серийный номер. В этом случае вы могли бы создать правила, подобные следующим:

# Правило для первого лидара
KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{serial}=="0001", MODE:="0777", SYMLINK+="rplidar1"

# Правило для второго лидара
KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{serial}=="0002", MODE:="0777", SYMLINK+="rplidar2"

4. Использование udev переменных для символьной ссылки

Если вы не можете изменить серийные номера, вы можете использовать переменную %n для создания динамически именуемой символической ссылки в зависимости от номера устройства. Это может выглядеть так:

KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="rplidar%n"

5. Применение изменений

После добавления правил в файл /etc/udev/rules.d/rplidar.rules, вам нужно перезагрузить служебные правила udev. Это можно сделать с помощью команд:

sudo udevadm control --reload-rules
sudo udevadm trigger

6. Проверка изменений

Подключите лида, после этого выполните команду ls -l /dev/rplidar* для проверки созданных символических ссылок. Вы должны увидеть что-то вроде:

lrwxrwxrwx 1 root root 7 Oct 21 12:30 /dev/rplidar1 -> ttyUSB0
lrwxrwxrwx 1 root root 7 Oct 21 12:30 /dev/rplidar2 -> ttyUSB1

Это позволит вашему коду использовать ссылки rplidar1 и rplidar2 для доступа к различным устройствам.

Заключение

Создание уникальных правил для устройств с одинаковыми идентификаторами может быть выполнено несколькими способами: изменением серийных номеров или использованием переменных udev. Важно правильно настроить уставшие атрибуты, чтобы обеспечить требуемую идентификацию.

Эти изменения помогут вам эффективно работать с несколькими устройствами, избегая конфликтов и создавая более надёжную систему для вашего проекта.

Оцените материал
Добавить комментарий

Капча загружается...