Tag Archive for: udev

A udev rule lets WebHID apps reach your mouse without sudo. Here’s the whole setup — wired, wireless, and Bluetooth.

TL;DR — drop this in /etc/udev/rules.d/70-webhid.rules, reload, replug. It covers every HID device on the machine:

KERNEL=="hidraw*", SUBSYSTEM=="hidraw", TAG+="uaccess"

Why your browser can’t see your mouse

Web apps that configure mice — button remapping, DPI, RGB, macros — talk to the device through WebHID, which reads /dev/hidraw* directly.

Out of the box, Linux hands those nodes to root:root with mode 0600. Your browser runs as your normal user, so it can’t open them. The app either shows no devices or only works when the browser is launched as root.

Running the browser with sudo “works”, but it’s the wrong fix. The right fix is a udev rule that grants your logged-in user access to that one device.

What you’ll need

  • A Chromium-based browser — Chrome, Chromium, Brave, Edge, Vivaldi, Opera. Firefox’s WebHID support is partial and unreliable.
  • Terminal access with sudo.
  • Your mouse connected via at least one transport.

Applies to Ubuntu, TUXEDO OS, Pop!_OS, Debian, Linux Mint, and other systemd-based distros.

Step 1 — Identify your device

The matching style differs per transport, so use only the section you need.

Wired or USB dongle

lsusb

Find your mouse in the list:

Bus 001 Device 005: ID 046d:c52b Logitech, Inc. Unifying Receiver

Your IDs are 046d (vendor) and c52b (product). Note them in lowercase — udev is case-sensitive.

Bluetooth

bluetoothctl devices

Map hidraw nodes to devices

Run this with the device connected. It tells you which node belongs to which device:

for h in /sys/class/hidraw/hidraw*; do
  echo "== ${h##*/}"
  cat "$h/device/uevent"
done

For Bluetooth, also walk the parent chain:

udevadm info -a -n /dev/hidrawN

Bluetooth trap: BT HID devices usually have no idVendor/idProduct attributes. A USB-style rule silently never matches them. Look for HID_ID / HID_UNIQ in the uevent output and the parent’s KERNELS name in the udevadm walk — that’s your identifier.

Step 2 — Create the udev rule

sudo nano /etc/udev/rules.d/70-webhid.rules

Each line is independent, so include every transport your mouse supports.

USB — wired or dongle

# USB
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="c52b", TAG+="uaccess"

Use ATTRS (plural) — the IDs live on the parent USB device, so ATTR alone won’t match.

Bluetooth / BLE

Match the parent’s kernel name. The .* absorbs a per-connection counter that changes on every reconnect:

# Bluetooth / BLE
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", KERNELS=="0005:3151:402C.*", TAG+="uaccess"

Or match the stable HID identity from the uevent output:

KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ENV{HID_ID}=="0005:00003151:0000402C", TAG+="uaccess"

Why two different styles? The USB device exposes vendor/product attributes; the Bluetooth device genuinely doesn’t. Don’t “fix” one to look like the other — it will stop working.

Step 3 — Apply the rule

sudo udevadm control --reload-rules
sudo udevadm trigger

Then physically unplug and replug the mouse, or toggle Bluetooth off and on. Existing nodes keep their old permissions until the device re-enumerates.

Step 4 — Verify it worked

for f in /dev/hidraw*; do echo "== $f"; getfacl -c "$f"; done

You want a line like this on the right node:

user:yourname:rw-

That’s the uaccess ACL. Now fully restart your browser and reload the app.

You can dry-run the rule before trusting it:

udevadm test /sys/class/hidraw/hidrawN

Troubleshooting

SymptomCauseFix
Rule never matchesUppercase hex in IDsUse lowercase: 046d, not 046D
Rule never matchesFile in /lib/udev/rules.d/Move to /etc/udev/rules.d/
USB rule never matchesUsed ATTR not ATTRSUse ATTRS — IDs are on the parent device
BT rule never matchesMatched idVendor, absent on BTUse KERNELS or ENV{HID_ID}
BT rule breaks on reconnectHard-coded the .NNNN suffixGlob it: 0005:3151:402C.*
Nothing happensDidn’t replug the deviceReplug, or toggle Bluetooth
No ACL after repluguaccess needs a local sessionUse MODE="0660", GROUP="plugdev"
Works only under sudoRule isn’t matchingRecheck IDs against udevadm info -a
Firefox can’t see itPartial WebHID supportUse Chrome/Chromium/Brave/Edge
Snap browser can’t see itSnap confinementsnap connect firefox:joystick

Watch udev process rules live:

sudo udevadm control --log-priority=debug
sudo udevadm monitor --udev --subsystem-match=hidraw

Browser-side errors: open chrome://device-log.

Bluetooth caveat

Many mice expose fewer HID collections over Bluetooth than over USB — the vendor config interface is often USB-only. If the app connects over Bluetooth but finds no settings to change, that’s the firmware, not your rule. Test over USB to confirm.

Why not just run the browser as root?

sudo chrome works, but your browser profile, cache, and keyring can end up root-owned and cause confusing problems later. uaccess is scoped to one device and one logged-in user, with no side effects.

Security

uaccess grants your user read/write on the device node. The broad KERNEL=="hidraw*" rule does that for all HID devices. Neither grants root. To narrow it, keep the specific VID/PID or HID_ID match instead.

Uninstall

sudo rm /etc/udev/rules.d/70-webhid.rules
sudo udevadm control --reload-rules
sudo udevadm trigger

Then replug the device.

Quick reference

# List USB devices
lsusb

# Map hidraw nodes to devices
for h in /sys/class/hidraw/hidraw*; do echo "== ${h##*/}"; cat "$h/device/uevent"; done

# Full attribute walk for a node
udevadm info -a -n /dev/hidrawN

# Apply rules
sudo udevadm control --reload-rules
sudo udevadm trigger

# Verify ACLs
getfacl -c /dev/hidrawN