Raspberry Pi – KERNELS Path for USB Device Connected to HUB

raspberry piraspbianttyusbudev

I'm creating udev rules to map my USB devices (ttyUSB*) to the USB ports where they are connected. The usual way to do so is looking at the output of:

udevadm info --name=/dev/ttyUSB0 --attribute-walk

Here my output (I removed the ATTRS lines not meaningful):

looking at device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5.6/1-1.5.6:1.0/ttyUSB0/tty/ttyUSB0':
    KERNEL=="ttyUSB0"
    SUBSYSTEM=="tty"
    DRIVER==""

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5.6/1-1.5.6:1.0/ttyUSB0':
    KERNELS=="ttyUSB0"
    SUBSYSTEMS=="usb-serial"
    DRIVERS=="ftdi_sio"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5.6/1-1.5.6:1.0':
    KERNELS=="1-1.5.6:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="ftdi_sio"
    ATTRS{interface}=="USB-RS485 Cable"
    ATTRS{supports_autosuspend}=="1"

    looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5/1-1.5.6':
    KERNELS=="1-1.5.6"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{idProduct}=="6001"
    ATTRS{idVendor}=="0403"
    ATTRS{manufacturer}=="FTDI"
    ATTRS{product}=="USB-RS485 Cable"
    ATTRS{serial}=="FTY48GF2"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5':
    KERNELS=="1-1.5"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{product}=="USB 2.0 Hub [MTT]"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"

  looking at parent device '/devices/platform/soc/3f980000.usb/usb1':
    KERNELS=="usb1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{manufacturer}=="Linux 4.9.41-v7+ dwc_otg_hcd"
    ATTRS{product}=="DWC OTG Controller"

  looking at parent device '/devices/platform/soc/3f980000.usb':
    KERNELS=="3f980000.usb"
    SUBSYSTEMS=="platform"
    DRIVERS=="dwc_otg"

  looking at parent device '/devices/platform/soc':
    KERNELS=="soc"
    SUBSYSTEMS=="platform"
    DRIVERS==""

  looking at parent device '/devices/platform':
    KERNELS=="platform"
    SUBSYSTEMS==""
    DRIVERS==""

Here the connection: Raspberry Pi -> USB HUB -> FTDI dongle.
My rule is the following:

$ cat /etc/udev/rules.d/99-usb.rules 
KERNEL=="1-1.5.6", SUBSYSTEM=="usb", SYMLINK+="rs485"

but:

# ls -l /dev/rs485 
lrwxrwxrwx 1 root root 15 Oct  4 07:04 /dev/rs485 -> bus/usb/001/009

I was expecting the symlink should be created to /dev/ttyUSB0.
Now, I understand my dongle is at that usb position from:

$ lsusb
Bus 001 Device 006: ID 046d:c062 Logitech, Inc. M-UAS144 [LS1 Laser Mouse]
Bus 001 Device 009: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
...

but of course it IS NOT the serial port (i.e. I cannot echo to it).
Trying to use 1-1.5.6:1.0 as KERNEL key doesn't work – no symlink created.

What value should I use?

Best Answer

If you look at man udev, KERNELS searches the device path, while KERNEL matches the device itself, and SUBSYSTEM represents the part of the kernel generating the event. When your USB dongle is plugged in, several udev events are created, as parts of the kernel discover the device and react according.

You want your rule to trigger on the action for the device itself (SUBSYSTEM=="tty", because you want a link for /dev/ttyUSB0), but with SUBSYSTEMS=="usb", it triggers when the USB device itself is discovered, not when the driver for the USB device is started. That's why you get a link to the USB device as seen from the USB subsystem, bus/usb/001/009o.

So what you need is

KERNELS=="1-1.5.6", SUBSYSTEM=="tty", SYMLINK+="rs485"

(note the S and the tty).

Related Question