How to distinguish between identical USB-to-serial adapters?

is there any way I can write a udev rule that fixes the name of each adapter based on which physical port on the hub the adapter is plugged into?

Yes there is, as it turns out. Consider the last portion of the device hierarchy shown in the second example above:

looking at parent device '/devices/pci0000:00/0000:00:1d.7/usb1/1-4/1-4.5': KERNELS=="1-4.5"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{configuration}==""
ATTRS{bNumInterfaces}==" 1"
ATTRS{bConfigurationValue}=="1"
ATTRS{bmAttributes}=="80"
ATTRS{bMaxPower}=="100mA"
ATTRS{urbnum}=="69"
ATTRS{idVendor}=="067b"
ATTRS{idProduct}=="2303"
ATTRS{bcdDevice}=="0300"
ATTRS{bDeviceClass}=="00"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bNumConfigurations}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{speed}=="12"
ATTRS{busnum}=="1"
ATTRS{devnum}=="7" ATTRS{version}==" 1.10" ATTRS{maxchild}=="0" ATTRS{quirks}=="0x0"
ATTRS{authorized}=="1"
ATTRS{manufacturer}=="Prolific Technology Inc."
ATTRS{product}=="USB-Serial Controller"

The name given to this device by the kernel (KERNELS=="1-4.5") indicates that this device is plugged into the fifth port of a hub connected to port four on bus 1 (see this FAQ for more information on how to decode the sysfs usb device hierarchy). With some help from this guide to writing udev rules I came up with the following set of udev rules for my USB-to-serial-port converters:

KERNEL=="ttyUSB*", KERNELS=="1-8.1.5", NAME="ttyUSB0"
KERNEL=="ttyUSB*", KERNELS=="1-8.1.6", NAME="ttyUSB1"
KERNEL=="ttyUSB*", KERNELS=="1-8.1.1", NAME="ttyUSB2"
KERNEL=="ttyUSB*", KERNELS=="1-8.1.2", NAME="ttyUSB3"

These rules have one obvious disadvantage: they assume that all USB-to-serial converters will be plugged into the same hub ("1-8.1.*"). If a USB to serial converter was plugged into another USB port it could be assigned the name "ttyUSB0" which would conflict with the naming scheme described above. However, since I leave all of the converters plugged into the hub I can live with this constraint.


Although it would not help in this specific case, some adapters are assigned unique serial ids:

udevadm info -a -n /dev/ttyUSB1 | grep '{serial}'

An example adapter serial id:

  ATTRS{serial}=="A6008isP"`

and udev rules would then contain:

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A6008isP", SYMLINK+="arduino"

Source


Have you looked at the contents of /dev/serial/by-id/? In a similar situation each device was assigned a unique persistent ID there (I'll admit don't know what it actually represents).