Fix Raspberry Pi USB Serial Path (From SiliconLab)
Question
Is there a way in Linux to fix the /dev/ttyUSBx assignment for a specific CP210x? When I have more than one plugged into a system, the /dev/ttyUSBx assignments get shuffled and this breaks scripts that I have written.
Answer
For starters, we need to understand that population of the /dev file system (devfs) in Linux is performed by the device manager. While there are many distributions of Linux covering mainframes to small embedded devices and everything in between, the most commonly used distributions, such as Debian, Ubuntu, Mint, Red Hat, Fedora, CentOS, Gentoo, and Arch all make use of the udev device manager.
One of udev's design goals is to dynamically create and remove /dev nodes as needed, a capability that is naturally a requirement for supporting plug-and-play device configuration. During boot time enumeration and any time a capable device is plugged in or removed, udev generates events, and these events can trigger the processing of rules.
The robust rules system in udev is one of its most powerful features. For example, a server with multiple network cards might be used to provide multiple streaming video feeds. If the server is brought down to replace a failed network adapter, the newly installed adapter might not be assigned the same network interface (e.g. eth1) on reboot, thus breaking a working firewall or port forwarding configuration. A properly written udev rule can fix this.
So, if a udev rule can be written to fix network interface assignments for different Ethernet cards in a server, it can certainly be used to assign a specific device node to a CP210x USB-to-serial bridge. In fact, the procedure is very similar to what is done with network interface cards.
First, we need to see which USB devices are plugged in with the lsusb command:
Notice, however, that there's not enough information here for us to determine which CP210x is which. We need a way to further query each CP210x, but, before we do that, we need to actually see which device nodes udev has already assigned. That's easy enough. We just need to list the contents of /dev and specifically look for ttyUSB nodes because this is the default name for USB-to-serial devices:
Finding more specific information about one of these CP210x bridges will take a bit of effort. We might need to scour the output of dmesg or one of the logs generated by various agents running under the Linux kernel to find more detailed information. Using lsusb in verbose mode is probably the most direct option, but the amount of data output, especially in a system with multiple USB devices, can be overwhelming. So, instead, we'll actually use one of udev's own administration tools to find what we need:
With this information handy, writing a specific udev rule to rename/renumber this particular CP210x bridge device is a simple matter. First, we need to edit (if it already exists) or create the file /etc/udev/rules.d/99-usb-serial.rules. Note that some on Linux distributions udev rules might reside in /etc/udev/rules (note the missing ".d"), so adjust the path accordingly. We'll then add the following line (make sure it is entered as a single line) to give the CP210x with the serial number attribute "00492F60" the device name ttySLAB0 each time it is plugged in:
SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{serial}=="00492F60", SYMLINK+="ttySLAB0"
Linux savvy readers might see this and say "Hey! You're not renaming ttyUSB0, you're only creating a symbolic link to it named ttySLAB0." Alas, this is correct. Current versions of the Linux kernel do not allow device nodes to be renamed and will output an error message like this...
...if the renaming option is used. This isn't ideal for purists who want to enforce fixed numbering of all CP210x bridges connected to a system and retain the customary ttyUSB device naming. It does, however, accomplish the desired goal of permitting scripts or other code written to communicate with a particular serial device connected to a CP210x to always access that device with the same name.
USB Bridges Knowledge Base Articles Interface