3

This is asked many a times before, but I haven't found any workable solution for my case. In my case, I have got two FTDI based USB <-> Serial converters from which I could not find any distinguishing feature to include in udev rules that I intend to write in order to identify them with a persistent name. The outputs of:

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

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

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-1':
    KERNELS=="3-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{devpath}=="1"
    ATTRS{idVendor}=="0403"
    ATTRS{speed}=="12"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="21"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="90mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="80"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="0"
    ATTRS{bcdDevice}=="0400"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{version}==" 1.10"
    ATTRS{urbnum}=="11"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="FTDI"
    ATTRS{removable}=="removable"
    ATTRS{idProduct}=="6001"
    ATTRS{bDeviceClass}=="00"
    ATTRS{product}=="USB <-> Serial"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3':
    KERNELS=="usb3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{devpath}=="0"
    ATTRS{idVendor}=="1d6b"
    ATTRS{speed}=="480"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{authorized_default}=="1"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="1"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="0mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="4"
    ATTRS{bcdDevice}=="0313"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{serial}=="0000:00:14.0"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="383"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Linux 3.13.0-32-generic xhci_hcd"
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="0002"
    ATTRS{bDeviceClass}=="09"
    ATTRS{product}=="xHCI Host Controller"

  looking at parent device '/devices/pci0000:00/0000:00:14.0':
    KERNELS=="0000:00:14.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="xhci_hcd"
    ATTRS{irq}=="40"
    ATTRS{subsystem_vendor}=="0x17aa"
    ATTRS{broken_parity_status}=="0"
    ATTRS{class}=="0x0c0330"
    ATTRS{enabled}=="1"
    ATTRS{consistent_dma_mask_bits}=="64"
    ATTRS{dma_mask_bits}=="64"
    ATTRS{local_cpus}=="ff"
    ATTRS{device}=="0x1e31"
    ATTRS{msi_bus}==""
    ATTRS{local_cpulist}=="0-7"
    ATTRS{vendor}=="0x8086"
    ATTRS{subsystem_device}=="0x3977"
    ATTRS{d3cold_allowed}=="1"

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

and same when done for ttyUSB1:

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

looking at device '/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/ttyUSB1':
    KERNEL=="ttyUSB1"
    SUBSYSTEM=="usb-serial"
    DRIVER=="ftdi_sio"
    ATTR{port_number}=="0"
    ATTR{latency_timer}=="1"

  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=="ftdi_sio"
    ATTRS{bInterfaceClass}=="ff"
    ATTRS{bInterfaceSubClass}=="ff"
    ATTRS{bInterfaceProtocol}=="ff"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{supports_autosuspend}=="1"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{interface}=="USB <-> Serial"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3/3-2':
    KERNELS=="3-2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{devpath}=="2"
    ATTRS{idVendor}=="0403"
    ATTRS{speed}=="12"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="22"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="90mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="80"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="0"
    ATTRS{bcdDevice}=="0400"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{version}==" 1.10"
    ATTRS{urbnum}=="11"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="FTDI"
    ATTRS{removable}=="removable"
    ATTRS{idProduct}=="6001"
    ATTRS{bDeviceClass}=="00"
    ATTRS{product}=="USB <-> Serial"

  looking at parent device '/devices/pci0000:00/0000:00:14.0/usb3':
    KERNELS=="usb3"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{devpath}=="0"
    ATTRS{idVendor}=="1d6b"
    ATTRS{speed}=="480"
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{authorized_default}=="1"
    ATTRS{busnum}=="3"
    ATTRS{devnum}=="1"
    ATTRS{configuration}==""
    ATTRS{bMaxPower}=="0mA"
    ATTRS{authorized}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{maxchild}=="4"
    ATTRS{bcdDevice}=="0313"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{serial}=="0000:00:14.0"
    ATTRS{version}==" 2.00"
    ATTRS{urbnum}=="383"
    ATTRS{ltm_capable}=="no"
    ATTRS{manufacturer}=="Linux 3.13.0-32-generic xhci_hcd"
    ATTRS{removable}=="unknown"
    ATTRS{idProduct}=="0002"
    ATTRS{bDeviceClass}=="09"
    ATTRS{product}=="xHCI Host Controller"

  looking at parent device '/devices/pci0000:00/0000:00:14.0':
    KERNELS=="0000:00:14.0"
    SUBSYSTEMS=="pci"
    DRIVERS=="xhci_hcd"
    ATTRS{irq}=="40"
    ATTRS{subsystem_vendor}=="0x17aa"
    ATTRS{broken_parity_status}=="0"
    ATTRS{class}=="0x0c0330"
    ATTRS{enabled}=="1"
    ATTRS{consistent_dma_mask_bits}=="64"
    ATTRS{dma_mask_bits}=="64"
    ATTRS{local_cpus}=="ff"
    ATTRS{device}=="0x1e31"
    ATTRS{msi_bus}==""
    ATTRS{local_cpulist}=="0-7"
    ATTRS{vendor}=="0x8086"
    ATTRS{subsystem_device}=="0x3977"
    ATTRS{d3cold_allowed}=="1"

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

I tried implementing the first solution @ How to distinguish between identical USB-to-serial adapters? by assigning KERNELS=="3-1" to ttyUSB0 and KERNELS=="3-2" to ttyUSB1, but it is not persistent and changes everytime I re-connect the devices. Moreover ATTRS{devnum} also keeps changing everytime, but it can be noted that they are always in sequence. So, can I use them to fix device names? I am not sure that same device will always be initialized with smaller or larger devnum.

Another option that I tried after following How to lock device id's to port addresses?, and did:

udevadm info /dev/ttyUSB0

P: /devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/ttyUSB0/tty/ttyUSB0
N: ttyUSB0
S: serial/by-id/usb-FTDI_USB__-__Serial-if00-port0
S: serial/by-path/pci-0000:00:14.0-usb-0:1:1.0-port0
E: DEVLINKS=/dev/serial/by-id/usb-FTDI_USB__-__Serial-if00-port0 /dev/serial/by-path/pci-0000:00:14.0-usb-0:1:1.0-port0
E: DEVNAME=/dev/ttyUSB0
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/ttyUSB0/tty/ttyUSB0
E: ID_BUS=usb
E: ID_MM_CANDIDATE=1
E: ID_MODEL=USB__-__Serial
E: ID_MODEL_ENC=USB\x20\x3c-\x3e\x20Serial
E: ID_MODEL_FROM_DATABASE=FT232 USB-Serial (UART) IC
E: ID_MODEL_ID=6001
E: ID_PATH=pci-0000:00:14.0-usb-0:1:1.0
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_1_1_0
E: ID_REVISION=0400
E: ID_SERIAL=FTDI_USB__-__Serial
E: ID_TYPE=generic
E: ID_USB_DRIVER=ftdi_sio
E: ID_USB_INTERFACES=:ffffff:
E: ID_USB_INTERFACE_NUM=00
E: ID_VENDOR=FTDI
E: ID_VENDOR_ENC=FTDI
E: ID_VENDOR_FROM_DATABASE=Future Technology Devices International, Ltd
E: ID_VENDOR_ID=0403
E: MAJOR=188
E: MINOR=0
E: SUBSYSTEM=tty
E: USEC_INITIALIZED=8719192

and then:

udevadm info /dev/ttyUSB1

P: /devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/ttyUSB1/tty/ttyUSB1
N: ttyUSB1
S: serial/by-id/usb-FTDI_USB__-__Serial-if00-port0
S: serial/by-path/pci-0000:00:14.0-usb-0:2:1.0-port0
E: DEVLINKS=/dev/serial/by-id/usb-FTDI_USB__-__Serial-if00-port0 /dev/serial/by-path/pci-0000:00:14.0-usb-0:2:1.0-port0
E: DEVNAME=/dev/ttyUSB1
E: DEVPATH=/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/ttyUSB1/tty/ttyUSB1
E: ID_BUS=usb
E: ID_MM_CANDIDATE=1
E: ID_MODEL=USB__-__Serial
E: ID_MODEL_ENC=USB\x20\x3c-\x3e\x20Serial
E: ID_MODEL_FROM_DATABASE=FT232 USB-Serial (UART) IC
E: ID_MODEL_ID=6001
E: ID_PATH=pci-0000:00:14.0-usb-0:2:1.0
E: ID_PATH_TAG=pci-0000_00_14_0-usb-0_2_1_0
E: ID_REVISION=0400
E: ID_SERIAL=FTDI_USB__-__Serial
E: ID_TYPE=generic
E: ID_USB_DRIVER=ftdi_sio
E: ID_USB_INTERFACES=:ffffff:
E: ID_USB_INTERFACE_NUM=00
E: ID_VENDOR=FTDI
E: ID_VENDOR_ENC=FTDI
E: ID_VENDOR_FROM_DATABASE=Future Technology Devices International, Ltd
E: ID_VENDOR_ID=0403
E: MAJOR=188
E: MINOR=1
E: SUBSYSTEM=tty
E: USEC_INITIALIZED=79099407

and then wrote udev rule in the file as 44-my-devices.rules located at /etc/udev/rules.d/: SUBSYSTEM=="tty", ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:1:1.0", SYMLINK+="ttyUSBMotor1"

SUBSYSTEM=="tty", ENV{ID_PATH}=="pci-0000:00:14.0-usb-0:2:1.0", SYMLINK+="ttyUSBMotor2"

I also copied it to /lib/udev/rules.d/ and then reloaded the rules as:

sudo udevadm control --reload-rules

sudo /etc/init.d/udev restart

But nothing did happen. I think I am making some mistake here, as this should work. The hardware associated always remains the same, and the rule must work. I have tried restarting the pc as well, but to no effect.

  • You could perhaps write a script that detects when they are connected and assigns them a name... – Daniel Nov 17 '15 at 4:26
  • But what should be the identification parameter? As I want to address the devices/ports in a C program, so there is a need to have a persistent name and for that a differentiating param. Moreover, there is no sequence as to when they would be connected. Writing such a script to assign names upon connection would also leave them to have different names at different times. – Ashish Sharma Nov 17 '15 at 4:32
  • It appears that this line: S: serial/by-path/pci-0000:00:14.0-usb-0:2:1.0-port0 differs from S: serial/by-path/pci-0000:00:14.0-usb-0:1:1.0-port0. You could use that to differentiate, assuming it doesn't change. – Daniel Nov 17 '15 at 14:29
  • Yes @Daniel, did somewhat the same thing by adding ENV{ID_PATH} for both of them in udev rules, as I have updated in answer. – Ashish Sharma Nov 18 '15 at 5:20
0

Well, using the physical path to the port is working for me, as I would keep the devices connected all the times, so attaching a device with a particular port and using this to identify one of two same devices is good approach to have. One thing to be noted is that, I had to rename my udev rules file in /etc/udev/rules.d to my-devices.rules from 44-my-devices.rules as pointed out in the README file as:

If the ordering of files in this directory are not important to you,
it's recommended that you simply name your files "descriptive-name.rules"
such that they are processed AFTER all numbered rules in both this
directory and /lib/udev/rules.d and thus override anything set there.

This seems to have worked for me, and I am able to duplicate the ports with user-understandable persistent names.

$ ls /dev/ttyUSB*
/dev/ttyUSB0  /dev/ttyUSB1  /dev/ttyUSBMotor1  /dev/ttyUSBMotor2

Hope it would help someone else like me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.