26

I have two different USB devices based on the same USB-RS232 chips. When I plug those in the USB they are mounted to /dev/ttyUSB0...3

My problem is how, inside a script, I can find out which one is on what tty?

Using lsusb I can differentiate them:

$> lsusb | grep 0403:f850
Bus 004 Device 002: ID 0403:f850 Future Technology Devices International, Ltd
$> lsusb | grep 0403:6001
Bus 004 Device 003: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC

And using dmesg I can tell where they were mounted:

$> dmesg | grep 'FTDI USB Serial Device converter now attached'
[36051.393350] usb 4-2: FTDI USB Serial Device converter now attached to ttyUSB1
[36061.823513] usb 4-1: FTDI USB Serial Device converter now attached to ttyUSB0

But "usb 4-1" does not seem to correspond to "Bus 004 Device 002".

Can I assume that "Bus 004 Device 001" will always be an "USB root hub" and thus dmesg will count from 1 onwards and lsusb from 2 onwards?

Or do you have another suggestion on how to correlate device ID to mount point (inside a script)?

I'm using Ubuntu 10.04 LTS.

Joe
  • 41,484
  • 20
  • 104
  • 125
gabriel_agm
  • 513
  • 1
  • 4
  • 14

3 Answers3

23

Find more info using sysfs:

$ ls /sys/bus/usb-serial/devices/ -ltrah

lrwxrwxrwx 1 root root 0 2012-02-07 22:17 ttyUSB0 -> ../../../devices/pci0000:00/0000:00:0f.4/usb2/2-2/2-2:1.0/ttyUSB0

$ ls -ltrad /sys//devices/pci0000:00/0000:00:0f.4/usb2/2-2/2-2:1.0/ttyUSB0
drwxr-xr-x 4 root root 0 2012-02-07 22:17 /sys//devices/pci0000:00/0000:00:0f.4/usb2/2-2/2-2:1.0/ttyUSB0

$ ls -ltrad /dev/ttyUSB0 
crw-rw---- 1 root dialout 188, 0 2012-02-01 00:17 /dev/ttyUSB0

Of course, the linked devices/... node contains a lot of information

Adding information based on the OP's comment:

The device number keeps growing if devices are removed/inserted. lsusb -t can be used to correlate the device numbers with usb bus/port.

Then, 'lsusb -d devID' can determine what device is on which port. Finally 'ls /sys/bus/usb-serial/devices/ -ltrah' will list (by bus/port) where it was mounted.

Not very convenient, but it 'works'

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Nice, that cleaner than dmesg, and shows the current state instead of all connection/disconnection history. I guess the ordering on the device numbers can be safely assumed to be the same on sysfs and lsusb - in case the bus number is not enough to differantiate. – gabriel_agm Feb 07 '12 at 21:29
  • The device number keeps growing if devices are removed/inserted - but 'lsusb -t' allows me to correlate device numbers with usb bus/port. Then, using 'lsusb -d devID' I can find what device is on which port - and finally with 'ls /sys/bus/usb-serial/devices/ -ltrah' I can find by bus/port where it was mounted. Creepy. – gabriel_agm Feb 08 '12 at 14:05
  • @gabriel_agm: incorporated your valuable experience in the answer for future visitors – sehe Feb 08 '12 at 14:42
  • 1
    I am trying to do this for a mobile phone. But on my Ubuntu 11.10 system, there is no `/sys/bus/usb-serial/`. There *is* `/sys/bus/usb/devices/`. – Craig McQueen May 08 '12 at 23:02
  • @CraigMcQueen the OP was specifically asking about USB-to-Serial convertors (that emulate a RS232 tty-type interface) – sehe May 08 '12 at 23:53
  • The mobile phone makes two serial interfaces, `/dev/ttyACM0` and `/dev/ttyACM1`, so it's a similar case. The first one is used for AT commands to the phone; the second one, I'm not sure. – Craig McQueen May 08 '12 at 23:58
  • @Sehe: what do you mean by "OP"? – m-ric Sep 25 '12 at 21:28
  • @m-ric OP means "Original Poster" or "Original Post" on the [SE] family of sites (and in many user groups) – sehe Sep 25 '12 at 21:33
15

You can use udev to assign a stable symbolic link to each FTDI dongle. Use device and vendor to match the type, and then the serial number for the specific device. Then use the symbolic link in the script.

I named my dongles ttyFTDI0 etc., and wrote the numbers on the dongles with a marker:

$ cat /etc/udev/ftdi.rules 
SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="FTDEN97D", SYMLINK+="ttyFTDI0"
SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A600b30P", SYMLINK+="ttyFTDI1"
SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A600bexU", SYMLINK+="ttyFTDI2"
SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="FTFMSA54", SYMLINK+="ttyFTDI3"
SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="FTFMUW4A", SYMLINK+="ttyFTDI4"
starblue
  • 55,348
  • 14
  • 97
  • 151
1

This one-liner udev rule will give a fixed name (e.g. /dev/ttyUSB_A9YL5BJJ) based on serial number for any device with vendor/product ids as given.

Put this into a udev rules file e.g. /etc/udev/rules.d/60-ftdi-serial-names.rules

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ENV{ID_SERIAL_SHORT}=="?*", SYMLINK+="ttyUSB_%E{ID_SERIAL_SHORT}"