-
Notifications
You must be signed in to change notification settings - Fork 0
USB Rule Files for Ubuntu
Thanks @Yuki
Scenario:
multiple USB devices plugged via hub to a host (Linux OS based), multiple services/programs interacting with TTY running on top (e.g. GPSd) Problem:
At boot TTY are randomly assigned to devices causing depending services/programs instabilities. They could indeed fail to start because of different TTY configurations.
Solution:
Assign un-mutable TTY names to USB devices by creating symbolic links of physical devices Configure then services/programs to point to these symbolic TTYs
Therefore, the short answer is: customize udev
rules.
udev
allows a Linux system to use consistent names for devices such as removable drives and printers,
which in turn allows users to experience predictable behavior when devices are added or removed from the system.
In synthesis, it represents Linux dynamic device manager.
udev
consists of:
- a configuration file
/etc/udev/udev.conf
, - permission files, and
- rules files
Rules files are used to determine the TTY used for removable drives currently available in the system. Every line within rule files defines how a specific device attribute is mapped to a dedicated device file.
The default udev
rules file is /etc/udev/rules.d/50-udev.rules
and should not be modified by a user.
To create new rules, add a new file in the same directory (/etc/udev/rules.d/
) keeping in mind the following conventions:
- All rules files must have a filename that ends with the
.rules
extension - Files are read in ascending order
Therefore, to create a customized file read before the default one, just type for example /etc/udev/rules.d/49-my.rules
.
Execute lsusb
to see all the currently detected USB devices printed out with an essential amount of info.
$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:8000 Intel Corp.
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 002 Device 002: ID 2109:2812
Bus 002 Device 003: ID 1a40:0101 Terminus Technology Inc. Hub
Bus 003 Device 002: ID 2109:0812
Bus 002 Device 004: ID 1546:01a8 U-Blox AG
Bus 002 Device 005: ID 2341:8036 Arduino SA Leonardo (CDC ACM, HID)
Bus 002 Device 006: ID 12d1:14db Huawei Technologies Co., Ltd. E353/E3131
Bus 002 Device 007: ID 0529:0001 Aladdin Knowledge Systems HASP v0.06
In this case, two USB devices are connected via hub to the host:
- a USB GPS Receiver U-Blox AG, and
- an Arduino platform
This means, they could be connected to either the device /dev/ttyACM0
or /dev/ttyACM1
(randomly selected).
Besides, their services require a static configuration of the expected TTY.
Therefore, a solution here is creating a customized udev
rule assigning the U-Blox device to a symbolic /dev/ttyGPS
.
Execute udevadm info -a -p $(udevadm info -q path -n /dev/ttyACM0)
to increase the verbosity of the USB details.
The output will look like the one reported below:
looking at device '/devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3.2/2-3.2:1.0/tty/ttyACM0':
KERNEL=="ttyACM0"
SUBSYSTEM=="tty"
DRIVER==""
[...]
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3.2':
KERNELS=="2-3.2"
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{configuration}==""
ATTRS{bNumInterfaces}==" 2"
ATTRS{bConfigurationValue}=="1"
ATTRS{bmAttributes}=="c0"
ATTRS{bMaxPower}=="100mA"
ATTRS{urbnum}=="40406"
ATTRS{idVendor}=="1546"
ATTRS{idProduct}=="01a8"
ATTRS{bcdDevice}=="0201"
ATTRS{bDeviceClass}=="02"
ATTRS{bDeviceSubClass}=="00"
ATTRS{bDeviceProtocol}=="00"
ATTRS{bNumConfigurations}=="1"
ATTRS{bMaxPacketSize0}=="64"
ATTRS{speed}=="12"
ATTRS{busnum}=="2"
ATTRS{devnum}=="4"
ATTRS{version}==" 1.10"
ATTRS{maxchild}=="0"
ATTRS{quirks}=="0x0"
ATTRS{authorized}=="1"
ATTRS{ltm_capable}=="no"
ATTRS{manufacturer}=="u-blox AG - www.u-blox.com"
ATTRS{product}=="u-blox GNSS receiver"
[...]
So, what you need to do eventually is:
- get KERNELS info for your hardware setup.
udevadm info -a -n /dev/ttyUSB0 | grep '{serial}'
- Update the rule file like:
KERNEL=="ttyUSB*", ATTRS{serial}=="AU6FBYET", SYMLINK+="ft_sensor1" MODE="0666"
KERNEL=="ttyUSB*", ATTRS{serial}=="AU684C7U", SYMLINK+="ft_sensor2" MODE="0666"
KERNEL=="ttyUSB*", ATTRS{serial}=="AU5KEDBG", SYMLINK+="ft_sensor3" MODE="0666"
KERNEL=="ttyUSB*", ATTRS{serial}=="BFT-SP-R1", SYMLINK+="ft_sensor4" MODE="0666"
- see if the rule is updated by running: Then, reconnect sensors and connect them again to PC.
sudo udevadm control --reload-rules.
- Now, if everything went correctly you can connect your device and type in your terminal:
ls /dev/ft_sensor3
to see if you successfully created a symlink. Since it’s a symbolic link you will be able to access both /dev/ttyUSB4 and /dev/ft_sensor4 but they will point to the same device.
- If you try to access the USB from python and if you get an error that says 'permission denied' then add
MODE="0666"
to the line of USB, you want to provide access always rule file. This make the permission to rw-rw-rw, but default is rw-rw-r