I have a device which connects through two different kernels when plugged in (e.g. /dev/ttyUSB0 and /dev/ttyUSB1. I'll dub one the config port and the other the data port, config always gets assigned the number one previous to data.
I'm trying to make a udev rule which symlinks the ports as well as differentiates between different devices, unfortunately it seems the distinguishing features are in one parent for data vs config, and in another parent for device vs device.
I'm not really sure how to take advantage of the config coming before data aspect. How would I go about doing so without hardcoding? Lets say the desired outcome is
/dev/device0_config
/dev/device0_data
/dev/device1_config
/dev/device1_data
attribute-walking one device results in the following for config and data respectively
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/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/ttyUSB1/tty/ttyUSB1':
KERNEL=="ttyUSB1"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/ttyUSB1':
KERNELS=="ttyUSB1"
SUBSYSTEMS=="usb-serial"
DRIVERS=="cp210x"
ATTRS{port_number}=="0"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0':
KERNELS=="3-2:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="cp210x"
ATTRS{supports_autosuspend}=="1"
ATTRS{bNumEndpoints}=="02"
ATTRS{bInterfaceProtocol}=="00"
ATTRS{bInterfaceSubClass}=="00"
ATTRS{bInterfaceClass}=="ff"
ATTRS{interface}=="Enhanced Com Port"
ATTRS{bInterfaceNumber}=="00"
ATTRS{authorized}=="1"
ATTRS{bAlternateSetting}==" 0"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2':
KERNELS=="3-2"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bConfigurationValue}=="1"
ATTRS{bNumConfigurations}=="1"
ATTRS{quirks}=="0x0"
ATTRS{devnum}=="9"
ATTRS{version}==" 2.00"
ATTRS{bcdDevice}=="0100"
ATTRS{bNumInterfaces}==" 2"
ATTRS{bDeviceProtocol}=="00"
ATTRS{speed}=="12"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{urbnum}=="22"
ATTRS{maxchild}=="0"
ATTRS{product}=="CP2105 Dual USB to UART Bridge Controller"
ATTRS{bmAttributes}=="80"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bMaxPower}=="100mA"
ATTRS{configuration}==""
ATTRS{idProduct}=="ea70"
ATTRS{idVendor}=="10c4"
ATTRS{ltm_capable}=="no"
ATTRS{busnum}=="3"
ATTRS{removable}=="removable"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{rx_lanes}=="1"
ATTRS{manufacturer}=="Silicon Labs"
ATTRS{authorized}=="1"
ATTRS{bDeviceClass}=="00"
ATTRS{serial}=="00E25BEB"
ATTRS{tx_lanes}=="1"
ATTRS{devpath}=="2"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3':
KERNELS=="usb3"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{speed}=="480"
ATTRS{bcdDevice}=="0515"
ATTRS{authorized_default}=="1"
ATTRS{busnum}=="3"
ATTRS{interface_authorized_default}=="1"
ATTRS{bConfigurationValue}=="1"
ATTRS{version}==" 2.00"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bmAttributes}=="e0"
ATTRS{bNumInterfaces}==" 1"
ATTRS{bNumConfigurations}=="1"
ATTRS{tx_lanes}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bDeviceClass}=="09"
ATTRS{maxchild}=="12"
ATTRS{bMaxPower}=="0mA"
ATTRS{product}=="xHCI Host Controller"
ATTRS{serial}=="0000:00:14.0"
ATTRS{bDeviceProtocol}=="01"
ATTRS{devnum}=="1"
ATTRS{configuration}==""
ATTRS{idVendor}=="1d6b"
ATTRS{devpath}=="0"
ATTRS{quirks}=="0x0"
ATTRS{urbnum}=="144"
ATTRS{removable}=="unknown"
ATTRS{bDeviceSubClass}=="00"
ATTRS{idProduct}=="0002"
ATTRS{authorized}=="1"
ATTRS{rx_lanes}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="Linux 5.15.0-58-generic xhci-hcd"
looking at parent device '/devices/pci0000:00/0000:00:14.0':
KERNELS=="0000:00:14.0"
SUBSYSTEMS=="pci"
DRIVERS=="xhci_hcd"
ATTRS{consistent_dma_mask_bits}=="64"
ATTRS{enable}=="1"
ATTRS{ari_enabled}=="0"
ATTRS{local_cpulist}=="0-7"
ATTRS{label}=="Onboard - Other"
ATTRS{dbc}=="disabled"
ATTRS{device}=="0xa0ed"
ATTRS{local_cpus}=="ff"
ATTRS{subsystem_device}=="0x3002"
ATTRS{irq}=="147"
ATTRS{vendor}=="0x8086"
ATTRS{power_state}=="D0"
ATTRS{d3cold_allowed}=="1"
ATTRS{class}=="0x0c0330"
ATTRS{index}=="6"
ATTRS{driver_override}=="(null)"
ATTRS{numa_node}=="-1"
ATTRS{dma_mask_bits}=="64"
ATTRS{msi_bus}=="1"
ATTRS{subsystem_vendor}=="0x8086"
ATTRS{broken_parity_status}=="0"
ATTRS{revision}=="0x20"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
ATTRS{waiting_for_supplier}=="0"
and
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/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.1/ttyUSB2/tty/ttyUSB2':
KERNEL=="ttyUSB2"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.1/ttyUSB2':
KERNELS=="ttyUSB2"
SUBSYSTEMS=="usb-serial"
DRIVERS=="cp210x"
ATTRS{port_number}=="0"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.1':
KERNELS=="3-2:1.1"
SUBSYSTEMS=="usb"
DRIVERS=="cp210x"
ATTRS{bNumEndpoints}=="02"
ATTRS{authorized}=="1"
ATTRS{bInterfaceProtocol}=="00"
ATTRS{bInterfaceNumber}=="01"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bInterfaceSubClass}=="00"
ATTRS{bAlternateSetting}==" 0"
ATTRS{interface}=="Standard Com Port"
ATTRS{supports_autosuspend}=="1"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2':
KERNELS=="3-2"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{devpath}=="2"
ATTRS{authorized}=="1"
ATTRS{manufacturer}=="Silicon Labs"
ATTRS{speed}=="12"
ATTRS{quirks}=="0x0"
ATTRS{bMaxPower}=="100mA"
ATTRS{bDeviceClass}=="00"
ATTRS{serial}=="00E25BEB"
ATTRS{removable}=="removable"
ATTRS{configuration}==""
ATTRS{bMaxPacketSize0}=="64"
ATTRS{ltm_capable}=="no"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bNumInterfaces}==" 2"
ATTRS{bcdDevice}=="0100"
ATTRS{busnum}=="3"
ATTRS{bmAttributes}=="80"
ATTRS{bNumConfigurations}=="1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bConfigurationValue}=="1"
ATTRS{product}=="CP2105 Dual USB to UART Bridge Controller"
ATTRS{urbnum}=="22"
ATTRS{maxchild}=="0"
ATTRS{bDeviceProtocol}=="00"
ATTRS{tx_lanes}=="1"
ATTRS{idVendor}=="10c4"
ATTRS{idProduct}=="ea70"
ATTRS{rx_lanes}=="1"
ATTRS{devnum}=="9"
ATTRS{version}==" 2.00"
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3':
KERNELS=="usb3"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bNumConfigurations}=="1"
ATTRS{bConfigurationValue}=="1"
ATTRS{product}=="xHCI Host Controller"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{bNumInterfaces}==" 1"
ATTRS{busnum}=="3"
ATTRS{version}==" 2.00"
ATTRS{tx_lanes}=="1"
ATTRS{idVendor}=="1d6b"
ATTRS{quirks}=="0x0"
ATTRS{removable}=="unknown"
ATTRS{authorized_default}=="1"
ATTRS{devnum}=="1"
ATTRS{devpath}=="0"
ATTRS{speed}=="480"
ATTRS{bcdDevice}=="0515"
ATTRS{urbnum}=="144"
ATTRS{rx_lanes}=="1"
ATTRS{bDeviceProtocol}=="01"
ATTRS{configuration}==""
ATTRS{serial}=="0000:00:14.0"
ATTRS{interface_authorized_default}=="1"
ATTRS{bDeviceClass}=="09"
ATTRS{maxchild}=="12"
ATTRS{manufacturer}=="Linux 5.15.0-58-generic xhci-hcd"
ATTRS{bmAttributes}=="e0"
ATTRS{idProduct}=="0002"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bMaxPower}=="0mA"
ATTRS{ltm_capable}=="no"
ATTRS{authorized}=="1"
looking at parent device '/devices/pci0000:00/0000:00:14.0':
KERNELS=="0000:00:14.0"
SUBSYSTEMS=="pci"
DRIVERS=="xhci_hcd"
ATTRS{dma_mask_bits}=="64"
ATTRS{broken_parity_status}=="0"
ATTRS{driver_override}=="(null)"
ATTRS{d3cold_allowed}=="1"
ATTRS{revision}=="0x20"
ATTRS{irq}=="147"
ATTRS{power_state}=="D0"
ATTRS{device}=="0xa0ed"
ATTRS{label}=="Onboard - Other"
ATTRS{dbc}=="disabled"
ATTRS{enable}=="1"
ATTRS{index}=="6"
ATTRS{local_cpulist}=="0-7"
ATTRS{subsystem_vendor}=="0x8086"
ATTRS{local_cpus}=="ff"
ATTRS{subsystem_device}=="0x3002"
ATTRS{msi_bus}=="1"
ATTRS{consistent_dma_mask_bits}=="64"
ATTRS{vendor}=="0x8086"
ATTRS{numa_node}=="-1"
ATTRS{class}=="0x0c0330"
ATTRS{ari_enabled}=="0"
looking at parent device '/devices/pci0000:00':
KERNELS=="pci0000:00"
SUBSYSTEMS==""
DRIVERS==""
ATTRS{waiting_for_supplier}=="0"
Note, for differentiating devices, I could use ATTRS{serial}==... from looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2':
ATTRS{bInterfaceNumber}=="00", whereas for the data device it is"01".looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2': KERNELS=="3-2". Which for config vs data is the same, as far as I can see.