udev distinguishes devices with the same USB pid vid

Problem phenomenon

module lsusb results dev
IMU USB Serial Port Module 10c4:ea60 Silicon Labs CP210x UART Bridge /dev/ttyUSB0
Chassis USB Serial Port Module 10c4:ea60 Silicon Labs CP210x UART Bridge /dev/ttyUSB1

1. When the device is restarted, there is a low probability that the ttyUSB{0,1} serial numbers of the two modules are exchanged, causing the program to fail to run after the system is restarted.
2. Think of distinguishing modules by USB pid:vid, but the two modules have the same uid:pid

Think of it

Distinguishing modules through finer-grained udev ATTRS attributes

Debugging and verification

Query imu usb module properties

1. Insert the IMU usb serial port module, add /sys/bus/usb/drivers/usb/7-1.1
2. Query usb ATTR attribute
udevadm info -a -p /sys/bus/usb/drivers/usb/7-1.1/

 looking at device '/devices/platform/usbdrd3_0/fc000000.usb/xhci-hcd.9.auto/usb7/7-1/7-1.1':
    KERNEL=="7-1.1"
    SUBSYSTEM=="usb"
    DRIVER=="usb"
    ATTR{devspec}=="(null)"
    ATTR{authorized}=="1"
    ATTR{speed}=="12"
    ATTR{quirks}=="0x0"
    ATTR{configuration}==""
    ATTR{devpath}=="1.1"
    ATTR{bNumConfigurations}=="1"
    ATTR{ltm_capable}=="no"
    ATTR{bMaxPower}=="100mA"
    ATTR{bDeviceSubClass}=="00"
    ATTR{rx_lanes}=="1"
    ATTR{idVendor}=="10c4"
    ATTR{bmAttributes}=="80"
    ATTR{maxchild}=="0"
    ATTR{bNumInterfaces}==" 1"
    ATTR{manufacturer}=="Silicon Labs"
    ATTR{busnum}=="7"
    ATTR{idProduct}=="ea60"
    ATTR{bMaxPacketSize0}=="64"
    ATTR{removable}=="unknown"
    ATTR{product}=="CP2102 USB to UART Bridge Controller"
    ATTR{urbnum}=="307803"
    ATTR{bDeviceProtocol}=="00"
    ATTR{bConfigurationValue}=="1"
    ATTR{bDeviceClass}=="00"
    ATTR{avoid_reset_quirk}=="0"
    ATTR{tx_lanes}=="1"
    ATTR{bcdDevice}=="0100"
    ATTR{devnum}=="40"
    ATTR{version}=="1.10"
    ATTR{serial}=="0001"

Query chassis usb module properties

1. Insert the IMU usb serial port module, add /sys/bus/usb/drivers/usb/7-1.2
2. Query usb ATTR attribute
udevadm info -a -p /sys/bus/usb/drivers/usb/7-1.2/

 looking at device '/devices/platform/usbdrd3_0/fc000000.usb/xhci-hcd.9.auto/usb7/7-1/7-1.2':
    KERNEL=="7-1.2"
    SUBSYSTEM=="usb"
    DRIVER=="usb"
    ATTR{urbnum}=="127201"
    ATTR{maxchild}=="0"
    ATTR{authorized}=="1"
    ATTR{bDeviceSubClass}=="00"
    ATTR{manufacturer}=="Silicon Labs"
    ATTR{bDeviceClass}=="00"
    ATTR{busnum}=="7"
    ATTR{bDeviceProtocol}=="00"
    ATTR{bConfigurationValue}=="1"
    ATTR{bmAttributes}=="80"
    ATTR{quirks}=="0x0"
    ATTR{ltm_capable}=="no"
    ATTR{version}==" 2.00"
    ATTR{bMaxPower}=="100mA"
    ATTR{removable}=="unknown"
    ATTR{rx_lanes}=="1"
    ATTR{tx_lanes}=="1"
    ATTR{devnum}=="38"
    ATTR{idVendor}=="10c4"
    ATTR{serial}=="6275b2d5040dec11ab81dccebd930c07"
    ATTR{product}=="CP2102N USB to UART Bridge Controller"
    ATTR{avoid_reset_quirk}=="0"
    ATTR{bNumInterfaces}==" 1"
    ATTR{bMaxPacketSize0}=="64"
    ATTR{configuration}==""
    ATTR{bcdDevice}=="0100"
    ATTR{speed}=="12"
    ATTR{devspec}=="(null)"
    ATTR{idProduct}=="ea60"
    ATTR{devpath}=="1.2"
    ATTR{bNumConfigurations}=="1"

Compare attribute differences

#chassis
-- ATTR{product}=="CP2102 USB to UART Bridge Controller"
-- ATTR{devpath}==" 1.2"

#imu
 + + ATTR{version}==" 2.00"
 + + ATTR{product}=="CP2102N USB to UART Bridge Controller"

Writing rules

/etc/udev/rules.d/900-myself-dev.rules

KERNEL=="ttyUSB*", ACTION=="add", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{version} ==" 2.00",ATTRS{product}=="CP2102N USB to UART Bridge Controller", MODE:="0666", SYMLINK + ="ttyImu"
KERNEL=="ttyUSB*", ACTION=="add", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{version}==\ " 1.10",ATTRS{product}=="CP2102 USB to UART Bridge Controller", MODE:="0666", SYMLINK + ="ttyChaisses"

Verify Verification:
Plugging and unplugging the USB does not take effect

Debug udev method

Method 1: Unplug the USB, open udev log

udevadm control --log-priority=debug #Set log level
journalctl -f #Query udev service log

May 15 15:56:15 orangepi5 systemd-udevd[21823]: ttyUSB0: Processing device (SEQNUM=5744, ACTION=bind)
May 15 15:56:15 orangepi5 systemd-udevd[21823]: ttyUSB0: /etc/udev/rules.d/900-myself-dev.rules:3 MODE 0666
May 15 15:56:15 orangepi5 systemd-udevd[21823]: ttyUSB0: /etc/udev/rules.d/900-myself-dev.rules:3 RUN ‘/etc/ruichi/udev-test.sh’
May 15 15:56:15 orangepi5 systemd-udevd[21823]: ttyUSB0: Running command “/etc/myself/udev-test.sh”
May 15 15:56:15 orangepi5 systemd-udevd[21823]: ttyUSB0: Starting ‘/etc/myself/udev-test.sh’

It can be seen from the udev log that the 900-myself-dev.rules rule is triggered and the corresponding /dev/ttyImu device is enumerated

Method 2: udevadm test simulation

udevadm test /sys/bus/usb/drivers/usb/7-1.2/

Reading rules file: /etc/udev/rules.d/900-ruichi-dev.rules
Invalid inotify descriptor.
DEVPATH=/devices/platform/usbdrd3_0/fc000000.usb/xhci-hcd.9.auto/usb7/7-1/7-1.2
DEVNAME=/dev/bus/usb/007/038
DEVTYPE=usb_device
DRIVER=usb
PRODUCT=10c4/ea60/100
TYPE=0/0/0
BUSNUM=007
DEVNUM=038
MAJOR=189
MINOR=805
ACTION=add
SUBSYSTEM=usb
ID_VENDOR=Silicon_Labs
ID_VENDOR_ENC=Silicon\x20Labs
ID_VENDOR_ID=10c4
ID_MODEL=CP2102N_USB_to_UART_Bridge_Controller
ID_MODEL_ENC=CP2102N\x20USB\x20to\x20UART\x20Bridge\x20Controller
ID_MODEL_ID=ea60
ID_REVISION=0100
ID_SERIAL=Silicon_Labs_CP2102N_USB_to_UART_Bridge_Controller_6275b2d5040dec11ab81dccebd930c07
ID_SERIAL_SHORT=6275b2d5040dec11ab81dccebd930c07
ID_BUS=usb
ID_USB_INTERFACES=:ff0000:
ID_VENDOR_FROM_DATABASE=Silicon Labs
ID_MODEL_FROM_DATABASE=CP210x UART Bridge
REALTEK_NIC_MODE=1
USEC_INITIALIZED=9888901551
Unload module index
Unloaded link configuration context.

Result:
It doesn’t take effect, I don’t know if it is a path, and there is a problem with the command usage.

Solution for rules not taking effect: restart udev

udevadm control --reload-rules #Reload rules
systemctl restart udev.service #restart udev service

result:
Enumeration succeeded

/dev/ttyUSB0 /dev/ttyChaisses
/dev/ttyUSB1 /dev/ttyImu

Update record

1. Update the rules rules
1.1 ACTION==“bind” – ACTION==“add”
1.2 Remove ACTION==”bind”, and the actual measurement will also take effect