Accessing Serial Devices on Linux w/o sudo

Motivation

If you're using a USB serial device like an FTDI USB UART serial converter on Linux, you'll need root permission to use the device by default, which can be annoying to remember every time you need to use the device.

Some distributions support a plugdev group which permits users in the group to access such devices without root permissions. However, the permissions here are broad, and it may be more desirable to limit users to specific devices.

A udev rule is one method to permit access on a more granular level. This guide details how to configure such a rule. For more information, see this article.

Instructions

1. Identify the device

Run ls /dev/. The device will show up as a /dev/ttyACMx or /dev/ttyUSBx, where x is some positive number.

If there are multiple ttyACM and/or ttyUSB devices visible, run the following command then unplug and re-plug in the USB device. This will output information on USB device initialization, generally including the USB serial device TTY file.

sudo dmesg -w | grep "usb"

For example, here is the output from my system. Note the last line of the output where it lists the USB serial device TTY file as ttyUSB1:

$ sudo dmesg | grep "usb"
[21.944277] usb 1-4: USB disconnect, device number 6
[21.637095] usb 1-4: new full-speed USB device number 7 using xhci_hcd
[21.764180] usb 1-4: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.64
[21.764184] usb 1-4: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[21.764186] usb 1-4: Product: USB Serial
[21.766670] usb 1-4: ch341-uart converter now attached to ttyUSB1

2. Get the device model ID and vendor ID

Run the udevadm info command to get the USB device model and vendor ID (also visible in the dmesg command in the previous instruction).

For example, the following outputs the model and vendor ID of the /dev/ttyUSB1 device.

$ udevadm info /dev/ttyUSB1 | grep -e ID_VENDOR_ID -e ID_MODEL_ID
E: ID_VENDOR_ID=0403
E: ID_MODEL_ID=6015

3. Create the udev rule

With root permissions (e.g. sudo), create a new udev rule file in /etc/udev/rules.d/, for example 80-usb-serial.rules. The number prefix is important here for order of udev rule execution, the lower the prefix the higher the priority.

Then in your preferred editor, add the below line, substituting in the model and vendor ID you found in the previous step.

# Contents of udev rule
SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="0403", ENV{ID_MODEL_ID}="6015", MODE="0666"

If you'd like to give your device a more meaningful name or you have multiple devices which cause the name to change on subsequent, configure the rule with a symlink as follows.

# Creates a udev rule for the device which symlinks the tty file to '/dev/ttyUART'
SUBSYSTEM=="tty", ENV{ID_VENDOR_ID}=="0403", ENV{ID_MODEL_ID}="6015", SYMLINK+="ttyUART", MODE="0666"

NOTE: When multiple USB serial devices with the same model and vendor ID are added, udev will match on all of them and overwrite the symlink each time. The end result is only the last device matched will be symlinked, and this is not determinat. To alleviate this, add additional matching information to the udev rule. The command udevadm info will prove useful for this. See man 7 udevadm for more info.

4. Verify the udev rule

Using the udevadm test command, simulate the application of udev rules to your desired USB serial device. You'll also need the /sys/ device path, but you can get this with the udevadm info command.

Substituting in your device's /dev/ path, run the following command. Look for a line which contains 'MODE' and optionally a line that contains 'LINK', if you configured a symlink for your device. These are visible in the command:

$ sudo udevadm test $(udevadm info --query=path --name=/dev/ttyUSB0) 2>&1 | grep "80-usb-serial.rules"
Reading rules file: /etc/udev/rules.d/80-usb-serial.rules
ttyUSB0: /etc/udev/rules.d/80-usb-serial.rules:7 MODE 0666
ttyUSB0: /etc/udev/rules.d/80-usb-serial.rules:7 LINK 'ttyUART'

5. Reload udev rules

run the following command to now permit non-root users to access the device.

sudo udevadm control --reload && sudo udevadm trigger

To provide more context, the udevadm control --reload command reloads the rules for new events while udevadm trigger replays kernel events so that your newly-loaded rule applies to events which have already occured. No need to unplug and replug your device!

References