
You can find the USB devices by ls /dev/*USB*
pi@raspberrypi:~ $ ls /dev/*USB*
/dev/ttyUSB0 /dev/ttyUSB1
pi@raspberrypi:~ $
and more information by lsusb
or dmesg | grep ttyUSB
.
pi@raspberrypi:~ $ lsusb
Bus 002 Device 003: ID 05e3:0626 Genesys Logic, Inc.
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 006: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Bus 001 Device 005: ID 046d:c534 Logitech, Inc. Unifying Receiver
Bus 001 Device 004: ID 05e3:0610 Genesys Logic, Inc. 4-port hub
Bus 001 Device 003: ID 1a86:7523 QinHeng Electronics HL-340 USB-Serial adapter
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
pi@raspberrypi:~ $
pi@raspberrypi:~ $
pi@raspberrypi:~ $ dmesg | grep ttyUSB
[ 5.284638] usb 1-1.3: ch341-uart converter now attached to ttyUSB0
[ 5.312424] usb 1-1.4: FTDI USB Serial Device converter now attached to ttyUSB1
But sometimes, you may want to use the /dev/ path to descript your USB, such as selecting the serial port in NodeRed.
Procedure of assigning fixed name
- Finding unique attributes for your USB devices
- Creating udev rules for your applications
- Creating match keys and assignment keys to bind the USB devices to your desired name.
- Applying rules
Finding unique attributes of USB devices
Using udevadm info [options] [devpath|file|unit…]
to check the details of the USB devices. -a
option stands for --attribute-walk
.
pi@raspberrypi:/etc/udev/rules.d $ udevadm info -a /dev/ttyUSB0
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/ttyUSB0/tty/ttyUSB0':
KERNEL=="ttyUSB0"
SUBSYSTEM=="tty"
DRIVER==""
looking at parent device '/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0/ttyUSB0':
KERNELS=="ttyUSB0"
SUBSYSTEMS=="usb-serial"
DRIVERS=="ch341-uart"
ATTRS{port_number}=="0"
looking at parent device '/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3/1-1.3:1.0':
KERNELS=="1-1.3:1.0"
SUBSYSTEMS=="usb"
DRIVERS=="ch341"
ATTRS{bNumEndpoints}=="03"
ATTRS{bInterfaceProtocol}=="02"
ATTRS{bInterfaceSubClass}=="01"
ATTRS{bInterfaceClass}=="ff"
ATTRS{bAlternateSetting}==" 0"
ATTRS{bInterfaceNumber}=="00"
ATTRS{supports_autosuspend}=="1"
ATTRS{authorized}=="1"
looking at parent device '/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.3':
KERNELS=="1-1.3"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{bcdDevice}=="0264"
ATTRS{busnum}=="1"
ATTRS{authorized}=="1"
ATTRS{bDeviceProtocol}=="00"
ATTRS{urbnum}=="31"
ATTRS{bConfigurationValue}=="1"
ATTRS{bDeviceClass}=="ff"
ATTRS{devspec}=="(null)"
ATTRS{bMaxPower}=="98mA"
ATTRS{idProduct}=="7523"
ATTRS{rx_lanes}=="1"
ATTRS{tx_lanes}=="1"
ATTRS{product}=="USB Serial"
ATTRS{bNumInterfaces}==" 1"
ATTRS{avoid_reset_quirk}=="0"
ATTRS{bDeviceSubClass}=="00"
ATTRS{speed}=="12"
ATTRS{removable}=="unknown"
ATTRS{bNumConfigurations}=="1"
ATTRS{configuration}==""
ATTRS{devpath}=="1.3"
ATTRS{quirks}=="0x0"
ATTRS{bMaxPacketSize0}=="8"
ATTRS{bmAttributes}=="80"
ATTRS{ltm_capable}=="no"
ATTRS{version}==" 1.10"
ATTRS{devnum}=="65"
ATTRS{maxchild}=="0"
ATTRS{idVendor}=="1a86"
...
...
...
Some unique attributes are ” idProduct”, “idVendor”. Make sure you are searching these attributes under the corresponding Port, in my case, usb1/1-1/1-1.3. Repeat the udevadm info
command and search for attributes for the other devices. Remember to change the /dev/ttyUSB0 to /dev/ttyUSB1 or else only plug a single device at a time.
To understand more about USB ports, please visit Extra readings down below.
Creating udev rules
Linux stores file-like device nodes in /dev directory. Each node points to a part of a system or device, no matter it exists or not. Because the /dev directories contain every device that may exits in the system, it may be very large and become difficult to manage.
udev plays an important role to manage /dev directories by providing a path forward, by matching information provided by sysfs and rules provided by users.
udev files should be kept in /etc/udev/rules.d
directories and with a .rules
suffix. Files in /etc/udev/rules.d are parsed in lexical order. In general, you want your rule file to be parsed first, so it is suggested that /etc/udev/rules.d/10-local.rules
is a good choice.
sudo touch /etc/udev/rules.d/10-local.rules
to create a rule file.
In a rules file, lines starting with “#” are treated as comments. Every other non-blank line is a rule. Rules cannot span multiple lines.
To learn more about udev, you may man udev
man udevadm
or visit http://www.reactivated.net/writing_udev_rules.html#udevinfo
Writing rules
Each line of rule should contain at least one match key and at least one assignment to construct a key-value pair. When all match keys are fulfilled, the rule will apply and the action of assignment will be performed.
Do not insert any line breaks in the rules, udev will see your one rule as multiple rules. And here are my rules to assign a new name for the 2 USB devices. Just add the following lines in your 10-local.rules
file.
SUBSYSTEM=="tty", ATTRS{idProduct}=="7523", ATTRS{idVendor}=="1a86", SYMLINK+="ttyUSB_HL-340_device"
SUBSYSTEM=="tty", ATTRS{idProduct}=="6001", ATTRS{idVendor}=="0403", SYMLINK+="ttyUSB_FT232_device"
SUBSYSTEM will match against the subsystem of the device.
SYMLINK is the alternative name(s) you want to assign to the USB device. This will not change or hide the original name but only provide an alternative name to link to the device.
Besides an exact matching of strings, you could also use shell-style pattern matching, such as *, ? and [].
Applying rules
Run udevadm trigger
to apply the new rules.
sudo udevadm trigger
To check the result.
pi@raspberrypi:/etc/udev/rules.d $ ls -l /dev/ttyUSB*
crw-rw---- 1 root dialout 188, 0 Dec 3 12:05 /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 1 Dec 3 12:05 /dev/ttyUSB1
lrwxrwxrwx 1 root root 7 Dec 3 12:05 /dev/ttyUSB_FT232_device -> ttyUSB1
lrwxrwxrwx 1 root root 7 Dec 3 12:05 /dev/ttyUSB_HL-340_device -> ttyUSB0
If you know the top-level device path, you can use udevadm test to show the action. Or else, just use
pi@raspberrypi:/etc/udev/rules.d $ udevadm test -a -p $(udevadm info -q path -n /dev/ttyUSB_FT232_device)
Serial port name in Node-red
Now you can specify the USB you are pointing to in Node-red rather than guessing which is ttyUSB0 and ttyUSB1.

———————-This is separator———————–
Extra readings
You may use lsusb -t
to explore what devices are connected to your pi. The following corresponds to no USB device connected.
pi@raspberrypi:~ $ lsusb -t
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
And the following corresponds to 4 USB devices connected. Dev 31 is a wireless mouse and keyboard. All devices are via USB2.0.

pi@raspberrypi:~ $ lsusb -t
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 1: Dev 27, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
|__ Port 2: Dev 31, If 0, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 2: Dev 31, If 1, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 3: Dev 26, If 0, Class=Vendor Specific Class, Driver=ftdi_sio, 12M
|__ Port 4: Dev 30, If 0, Class=Hub, Driver=hub/4p, 480M

If you have a USB hub, then those connected devices will be under the hub port. In my case, the hub is connected to Port 3.

pi@raspberrypi:~ $ lsusb -t
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 3: Dev 36, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 1: Dev 37, If 0, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 1: Dev 37, If 1, Class=Human Interface Device, Driver=usbhid, 12M
|__ Port 2: Dev 41, If 0, Class=Vendor Specific Class, Driver=ftdi_sio, 12M
|__ Port 3: Dev 42, If 0, Class=Vendor Specific Class, Driver=ch341, 12M
If you have USB 3.0 devices, they will be using Bus 02. In my case, both the USB hub and USB flash drive support USB 3.0.

pi@raspberrypi:~ $ lsusb -t
/: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M
|__ Port 1: Dev 13, If 0, Class=Hub, Driver=hub/4p, 5000M
|__ Port 4: Dev 14, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
/: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/1p, 480M
|__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M
|__ Port 1: Dev 56, If 0, Class=Hub, Driver=hub/4p, 480M
The number after the word ‘usb’ in dmesg
is actually the USB Bus and Port. In my case, the ch341-uart converter is under bus 1, port 1.3. In similar manner, usb 3.0 devices will be usb 2-X.X.
[161104.469392] usb 1-1.3: ch341-uart converter now attached to ttyUSB1