udev Input Device Permissions: How to Pin dialout and plugdev

To pin udev permissions for USB serial/HID, drop a rule under /etc/udev/rules.d/, match the USB parent with ATTRS{idVendor} / ATTRS{idProduct} (and serial when possible), then set GROUP="dialout", MODE="0660", and SYMLINK+="…". On Debian/Ubuntu, serial nodes default to the dialout group.

This article covers USB serial/HID groups and symlinks only—not a general udev primer.

Where do the rules live?

One-line answer: User rules go in /etc/udev/rules.d/99-….rules; add yourself to dialout (and your distro’s plugdev/replacement group if needed) and re-login.

Flow:

  1. Plug in and list nodes: ls -l /dev/ttyUSB* /dev/ttyACM* (HID: /dev/hidraw*).
  2. sudo usermod -aG dialout "$USER" then log out/in.
  3. Write a rule, e.g. FTDI-style serial:
# /etc/udev/rules.d/99-usb-serial.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", \
  ATTRS{serial}=="A1B2C3D4", GROUP="dialout", MODE="0660", SYMLINK+="myboard"

HID sketch (replace with measured IDs):

KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678", \
  GROUP="plugdev", MODE="0660", SYMLINK+="myhid"

systemd defaults already assign many tty* nodes to dialout. Custom rules mainly add a stable name and VID/PID lock-in. Ubuntu-style plugdev appears in desktop USB guides; systemd discussions often prefer uaccess or system groups over long-term plugdev dependence. For board serial, dialout + a logged-in session remains the common path.

If /dev/serial/by-id/… already exists, pointing the app there also avoids enumeration-order churn.

How does ATTR matching work?

One-line answer: Walk parents with udevadm info -a -n /dev/ttyUSB0, then combine ATTRS{…} that live on the same parent. Matching is case-sensitive.

udevadm info -a -n /dev/ttyUSB0 | grep -E 'ATTRS\{(idVendor|idProduct|serial|manufacturer|product)\}'

Tips:

  • ATTR{…} is the device itself; ATTRS{…} walks parents. VID/PID usually sit on the USB parent.
  • All ATTRS keys in one rule must be satisfied by one parent device—do not mix ancestors.
  • Hex values are often lowercase (0403); avoid case/whitespace mismatches.
  • Add ATTRS{serial} when identical dongles share a VID/PID.
  • Match the tty (SUBSYSTEM=="tty") for serial apps; a symlink on the raw USB device alone may not be the node your tool opens.

How do you verify with udevadm?

One-line answer: control --reload-rules, trigger, then info / test to confirm GROUP, SYMLINK, and access.

sudo udevadm control --reload-rules
sudo udevadm trigger --subsystem-match=tty
sudo udevadm trigger -n /dev/ttyUSB0

udevadm info -n /dev/ttyUSB0 | grep -E 'DEVNAME|DEVLINKS|ID_VENDOR|ID_MODEL|ID_SERIAL'
ls -l /dev/myboard /dev/ttyUSB0
sudo udevadm test /sys/class/tty/ttyUSB0 2>&1 | tail -n 40

Checks:

  • ls -l shows the intended group
  • /dev/myboard points at the expected tty
  • Unprivileged open works after re-login
  • If not: groups, rule filename/syntax (== vs =), VID/PID typos

Wrap-up

Pin USB serial/HID access with /etc/udev/rules.d + dialout membership → ② ATTRS VID/PID(/serial) → ③ udevadm reload/trigger/test. Focus on group, symlink, and verification so board paths stay stable.

Sources