1

I'm using a USB <-> Serial box and would like to have a custom symlink for the serial ports.

Based on the output of udevadm I know each port has a different KERNELS value:

KERNELS=="1-3:1.0" (this is labeled as port 1 on the box)
KERNELS=="1-3:1.1" (port 2)
KERNELS=="1-3:1.2" (port 3)
KERNELS=="1-3:1.3" (port 4)

I tried the following rule:

ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", KERNELS=="1-3:1.3", SYMLINK+="my_port"

which did not work. If, however, I use KERNELS=="1-3" instead of KERNELS=="1-3:1.3", the symlink is created.

How can I rewrite the rule to be able to differentiate between the various serial ports?

 $ udevadm info --path=/sys/bus/usb-serial/devices/ttyUSB19 --attribute-walk

  looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.3/ttyUSB19':
    KERNEL=="ttyUSB19"
    SUBSYSTEM=="usb-serial"
    DRIVER=="ftdi_sio"
    ATTR{latency_timer}=="16"
    ATTR{port_number}=="0"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.3':
    KERNELS=="1-3:1.3"
    SUBSYSTEMS=="usb"
    DRIVERS=="ftdi_sio"
    ATTRS{authorized}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceClass}=="ff"
    ATTRS{bInterfaceNumber}=="03"
    ATTRS{bInterfaceProtocol}=="ff"
    ATTRS{bInterfaceSubClass}=="ff"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{interface}=="USB <-> Serial Cable"
    ATTRS{supports_autosuspend}=="1"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-3':
    KERNELS=="1-3"
    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}==" 4"
    ATTRS{bcdDevice}=="0800"
    ATTRS{bmAttributes}=="80"
    ATTRS{busnum}=="1"
    ATTRS{configuration}==""
    ATTRS{devnum}=="65"
    ATTRS{devpath}=="3"
    ATTRS{idProduct}=="6011"
    ATTRS{idVendor}=="0403"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="FTDI"
    [...]
2
  • At KERNELS=="1-3", you probably get a symlink to the raw USB device instead of the tty. You need to match on SUBSYSTEM=="usb-serial" (or whatever subsystem actually produces the tty). This question is a duplicate, and has been asked before in several variants, but I don't have the time to find the old question(s) right now.
    – dirkt
    Jun 6, 2018 at 11:50
  • @dirkt I am aware of that. But matching with subsystem is not enough because all the serial ports have the same, "1-3". I was suspecting that the colon is the source of trouble: why does it work for "1-3" but not for "1-3:1.3"?
    – Sparkler
    Jun 6, 2018 at 12:37

1 Answer 1

3

Bootstrap

  • You can not math for KERNEL when writing a rule for a USB device as @dirkt wrote.
  • And unfortunately, the device is not well-populated at "looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-3/1-3:1.3/ttyUSB19'" for a proper match (as you can see in your question).
  • But the udev and the other rules before of yours can help! The udevadm info will print the raw device info, however, the udevadm monitor -u -p prints the populated version:

    udevadm monitor --help
    
    ...
    -p --property                            Print the event properties
    -k --kernel                              Print kernel uevents
    -u --udev                                Print udev events
    -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem
    

Solution

Get parameters

  1. Pull out your device
  2. run the udevadm monitor -kups usb command for getting fully-populated events
  3. connect it for getting logs

Write rule

You have two choices:

  1. Write rule based on the original KERNEL event:

    ACTION=="add", SUBSYSTEM=="usb-serial", ENV{DEVTYPE}=="usb_device", \
      ENV{PRODUCT}=="403/6011/0", SYMLINK+="my_port"
    
  2. Write rule based on the extended UDEV event:

    ACTION=="add", SUBSYSTEM=="usb-serial", ENV{DEVTYPE}=="usb_device", \
      ENV{ID_VENDOR_ID}=="0403", ENV{ID_MODEL_ID}=="6011", SYMLINK+="my_port"
    

Test rule

You should test your rule to avoid unwanted behavior before production (e.g. a too broad condition => multiple matches => multiple runs)

  1. Grab the device path from the output of the previous udevadm monitor run (e.g.: usb1/1-3 in your case)
  2. Run the udevadm test for dry-run the udev rules:

    udevadm test --action=add /sys/bus/usb/devices/usb1/1-3
    

Apply changes & try

  1. Reload rules:

    udevadm control --reload
    
  2. Trigger USB device re-connection:

    udevadm trigger -v --action=add --subsystem-match /sys/bus/usb/devices/usb1/1-3
    

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .