A tweaked udev rules file

I’d been trying to get pulseaudio’s module-mmkbd-evdev to function with the keyboard; to cut a long story short that wants a predictable device path for the media keys and udev doesn’t offer one, so I wrote this to prevent any problems like that happening again.

This goes in /etc/udev/rules.d/99-kaleidoscope.rules, then run udevadm control --reload and… it’s easier just replugging the device than trying to manually poke udev to update, believe me :wink:

# Tag all subdevices in the USB tree with a stable identifier
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="230[01]", \
    TAG+="model01"

# Consumer Control, i.e. media keys (and things like KEY_SLEEP if you defined them)
TAG=="model01", ATTRS{name}=="* Consumer Control", KERNEL=="event*", \
    GROUP="plugdev", MODE="0640", SYMLINK+="model01/mmkbd"

# System Control: not exactly sure what this does, but here's how to ID it
TAG=="model01", ATTRS{name}=="* System Control", KERNEL=="event*", \
    GROUP="plugdev", MODE="0640", SYMLINK+="model01/sysctl"

# Serial port: create a symlink so it's easier to identify for programming
TAG=="model01", SUBSYSTEM=="tty", \
    SYMLINK+="model01/serial"

# The regular mouse movement Fn-keys (W↑ / A← / S→ / D↓ / FRV)
TAG=="model01", ENV{ID_INPUT_MOUSE}=="1", ATTRS{name}=="* Mouse", \
    SYMLINK+="model01/mousekeys"

# The “mouse grid” Fn-keys (T⏎ / G↖ / Tab↗ / B↙ / Esc↘)
TAG=="model01", ENV{ID_INPUT_MOUSE}=="1", ATTRS{name}!="* Mouse", \
    SYMLINK+="model01/mousegrid"

# The regular USB HID keyboard
TAG=="model01", ENV{ID_INPUT_KEYBOARD}=="1", \
    SYMLINK+="model01/keyboard"

That’ll give you a /dev/model01/ directory with properly named symlinks. It also makes the two Control input devices plugdev-readable, which I believe isn’t a risk since those don’t send typed text. Feel free to remove the permissions-twiddling if you don’t need it, I think most desktop distros do something fancy with ACLs to accomplish the same effect anyway…

(While I was doing this I also discovered ModemManager now knows not to mess with the keyboard, so if you had existing rules for that previously you can safely remove them now.)

1 Like

Thanks, this sounds extremely useful! So much so that I wonder if it’s worth trying to upstream it.

Also, what happens if I plug in two Model 01?

That’s a good question… I think you’ll just get symlinks pointing to whatever was plugged in last.

Is the USB serial field filled in correctly on these? (I’d imagine so)

In that case you’d be able to have something like this instead:

SUBSYSTEMS=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="230[01]", \
    TAG+="model01", ENV{M01_ID}="$attr{serial}"
#...
TAG=="model01", SUBSYSTEM=="tty", \
    SYMLINK+="model01/serial", SYMLINK+="model01/%E{M01_ID}-serial"

As far as I remember, it isn’t. It’s going to be the same for all Model01s.

Ah, that’s a shame. In that case ENV{M01_ID}="$id" (the USB port number) will have to do.