udev rules for ttyUSB devices

In my particular case, there are two physical USB devices that are represented as TTY devices in the kernel: a Gobi2000 3G modem, and a 4-port USB-to-serial adapter. The modem is presented by two ttyUSB devices, and the USB-to-serial adapter adds four more. At the machine boot, these devices get assigned random numbers ttyUSB0 to ttyUSB5, and this assignment changes between reboots.

So, this needs udev rules which would assign symlinks to these devices, and the symlinks should remain valid between the reboots.

As there’s only one physical device of each type attached to the host, we can base our udev rules on idVendor and idProduct attributes. If you need to distinguish between multiple physical devices of the same type, you have to match serial numbers in your udev rules.

The next task is to distinguish between virtual TTY devices within the same physical device. The easiest way to perform this is to extract all available attributes for two devices and look at the difference between them:

udevadm info -a -n /dev/ttyUSB4 >x4
udevadm info -a -n /dev/ttyUSB5 >x5
diff -u x4 x5

The challenge with the 3G modem is that the two TTY devices are only differing in bInterfaceNumber attribute:

-    ATTRS{bInterfaceNumber}=="01"
+    ATTRS{bInterfaceNumber}=="02"

This attribute is derived during the device initialization and is not available for udev matching rules. Instead, there is environment variable ID_USB_INTERFACE_NUM which represents these values. The following commands help in identifying the needed match. The full device strings are taken from the output of “udevadm info” command:

udevadm test '/devices/pci0000:00/0000:00:13.0/usb3/3-1/3-1.3/3-1.3:1.1/ttyUSB4/tty/ttyUSB4' >z4
udevadm test '/devices/pci0000:00/0000:00:13.0/usb3/3-1/3-1.3/3-1.3:1.2/ttyUSB5/tty/ttyUSB5' >z5
diff -u z4 z

The output identifies clearly that ID_USB_INTERFACE_NUM is the variable that we can rely upon in fixing to a particular port inside the 3G modem.

Analogous comparison for the USB-to-Serial adapter shows that the ports are differing in “devpath” attribute.

So, we add the following udev rules:

cat >/etc/udev/rules.d/99-usb-serial.rules <<'EOT'
SUBSYSTEM=="tty", ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="251d", SYMLINK+="ttyGOBI%E{ID_USB_INTERFACE_NUM}"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="ttyFTDI%s{devpath}"
EOT

The “udevadm test” commands as specified above help in testing udev rules without the need to reboot the host.

After rebooting, we get the following devices with persistent names:

# ls -al /dev/tty* | grep USB
lrwxrwxrwx 1 root root          7 Jun 14 11:22 /dev/ttyFTDI1.1 -> ttyUSB0
lrwxrwxrwx 1 root root          7 Jun 14 11:22 /dev/ttyFTDI1.2 -> ttyUSB1
lrwxrwxrwx 1 root root          7 Jun 14 11:22 /dev/ttyFTDI1.3 -> ttyUSB2
lrwxrwxrwx 1 root root          7 Jun 14 11:22 /dev/ttyFTDI1.4 -> ttyUSB3
lrwxrwxrwx 1 root root          7 Jun 14 11:33 /dev/ttyGOBI01 -> ttyUSB4
lrwxrwxrwx 1 root root          7 Jun 14 11:35 /dev/ttyGOBI02 -> ttyUSB5
crw-rw---- 1 root dialout 188,  0 Jun 14 11:22 /dev/ttyUSB0
crw-rw---- 1 root dialout 188,  1 Jun 14 11:22 /dev/ttyUSB1
crw-rw---- 1 root dialout 188,  2 Jun 14 11:22 /dev/ttyUSB2
crw-rw---- 1 root dialout 188,  3 Jun 14 11:22 /dev/ttyUSB3
crw-rw---- 1 root dialout 188,  4 Jun 14 11:33 /dev/ttyUSB4
crw-rw---- 1 root dialout 188,  5 Jun 14 11:35 /dev/ttyUSB5

 

Advertisements

, ,

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: