EXSYS USB-to-serial Adapter and stable device names

EXSYS provides multi serial-port adapters connected over USB. I recently ordered the 8-port device EX-1338HMV. From a hardware perspective, the device is made very solid, ready for industrial use. The connectors, USB as well as power, are secured by additional screws, so tensions on the cables should be an issue.

As soon as I connected the USB cable, the serial ports worked without using any external power adapter, however depending how much the connected device actually draw, external power might be needed.

The device has FTDI chips inside, which was the reason I opted for this solution. FTDI chips have a good reputation in providing high quality USB-to-serial adapters with high accuracy. The FTDI chips are connected through two internal USB hubs, as can be shown using lsusb:

/: Bus 03.Port 1: Dev 1,, Driver=xhci_hcd/4p, 480M
   |__ Port 1: Dev 14, If 0,, Driver=hub/7p, 480M
   |__ Port 1: Dev 15, If 0, Specific Class, Driver=ftdi_sio, 12M
   |__ Port 2: Dev 16, If 0, Specific Class, Driver=ftdi_sio, 12M
   |__ Port 3: Dev 17, If 0, Specific Class, Driver=ftdi_sio, 12M
   |__ Port 4: Dev 18, If 0, Specific Class, Driver=ftdi_sio, 12M
   |__ Port 5: Dev 19, If 0, Specific Class, Driver=ftdi_sio, 12M
   |__ Port 6: Dev 20, If 0, Specific Class, Driver=ftdi_sio, 12M
   |__ Port 7: Dev 21, If 0,, Driver=hub/4p, 480M
       |__ Port 1: Dev 22, If 0, Specific Class, Driver=ftdi_sio, 12M
       |__ Port 2: Dev 23, If 0, Specific Class, Driver=ftdi_sio, 12M

One of the problems using USB-to-serial adapter is the assignation of device names: By default, a newly plugged-in device gets the next free device under /dev/ttyUSB. FTDI chips have serial numbers, so one can distinguish the individual FTDI chips in a reliable manor. By default, udev already makes use of this and creates stable symlinks under /dev/serial/by-id/:

ls /dev/serial/by-id/usb*
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A501YIJX-if00-port0
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A501YIJY-if00-port0
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A501YIJZ-if00-port0
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A501YIK0-if00-port0
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A501YIK1-if00-port0
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A501YIK2-if00-port0
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A501YIK3-if00-port0
/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A501YIK4-if00-port0

As you can see, the serial numbers are all in a row. However, those do not align to the labeled serial port number on the device. Using sysfs one can figure out the serial numbers by bus number. However, I prefer to use the serial number rather than the the bus location, since the latter might change when one uses a different USB port.

$ cat /sys/bus/usb/devices/3-1/3-1.1/serial
A501YIK2

In the end, my udev rule in the file /etc/udev/rules.d/90-exsys.rules look like this:

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A501YIK2", SYMLINK+="ttyEXSYS1"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A501YIK1", SYMLINK+="ttyEXSYS2"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A501YIJZ", SYMLINK+="ttyEXSYS3"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A501YIJX", SYMLINK+="ttyEXSYS4"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A501YIJY", SYMLINK+="ttyEXSYS5"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A501YIK0", SYMLINK+="ttyEXSYS6"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A501YIK3", SYMLINK+="ttyEXSYS7"
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A501YIK4", SYMLINK+="ttyEXSYS8"

You can use this command in case the udev rules don’t get (re)loaded automatically:

$ sudo udevadm control --reload-rules

Leave a Comment