Files
vault/Technical/Linux/Keyboard.md
Zaine Arch 9645ee23b0
Some checks failed
Build Quartz Notes / build (push) Failing after 21s
update
2026-06-10 20:00:45 +01:00

6.3 KiB
Raw Blame History

Keyboard inputs

This all comes from the fact that a "key press" isn't one thing — it's a stack of specs and translations from keyboard hardware → USB/HID → Linux kernel → userspace (XKB/Wayland) → Hyprland binds.

1. Big picture: what happens when you press a key?

When you hit a key (like your "lock" key), roughly this happens:

Physical switch on keyboard
        ↓
Keyboard firmware → USB HID "usage" (e.g. 0x07:0xE3 = Left GUI)
        ↓
Linux kernel input subsystem (evdev) → KEY_LEFTMETA (code 125)
        ↓
libinput / xkbcommon → keysyms (like Super_L, L, etc.)
        ↓
Hyprland → your `bind = SUPER, L, exec, ...`

The "topic" we've been poking at is basically understanding each layer in that stack.


2. USB HID: where 700e3 comes from

Modern USB keyboards follow the USB HID (Human Interface Device) specification. This spec defines Usage Tables: numerical codes for things like keys, buttons, axes, etc.

  • The keyboard page is Usage Page 0x07 (Keyboard/Keypad).

  • In your evtest output, MSC_SCAN value 700e3 means:

    • 0x07 (Keyboard page)
    • 0xE3 (Left GUI / "Windows/Super" key)

You can see the official tables here (PDF):

If you scroll to the Keyboard/Keypad Page (0x07) section, it lists all the key usages: A, B, C, modifiers, function keys, etc. There's also a standalone Keyboard/Keypad-page extract people mirror, like this PDF snippet: (d1.amobbs.com)

So:

  • 700e3 = Page 0x07, Usage 0xE3Keyboard Left GUI
  • 7000f = Page 0x07, Usage 0x0FKeyboard L key

That's how we knew your lock key was sending Super + L.


3. Linux input subsystem: EV_MSC, EV_KEY, KEY_LEFTMETA

Linux has a dedicated input subsystem in the kernel (drivers/input, drivers/hid etc.) that takes those HID usages and turns them into a unified stream of input events. (Linux Kernel Documentation)

Key ideas:

  • Devices expose /dev/input/eventX nodes.

  • Each event is a struct with:

    • type (e.g. =EVKEY=, EV_MSC, EV_REL, EV_SYN)
    • code (e.g. =KEYL=, KEY_LEFTMETA)
    • value (pressed = 1, released = 0, repeat = 2)

Docs worth bookmarking:

The keycode definitions (KEY_L, KEY_LEFTMETA, etc.) live in:

When evtest prints:

type 4 (EV_MSC), code 4 (MSC_SCAN), value 700e3
type 1 (EV_KEY), code 125 (KEY_LEFTMETA), value 0

that means:

  • EV_MSC / MSC_SCAN → "Here is the raw hardware scancode" (from USB HID).
  • EV_KEY / KEY_LEFTMETA → "Linux mapped that scancode to logical key LEFTMETA".

4. XKB / xkbcommon: mapping to actual characters & modifiers

Above the kernel, you've got an extra mapping layer that says:

For keycode N, with this layout, when Shift is held, produce this character/symbol.

On X11 this is handled by XKB (X Keyboard Extension); on Wayland compositors (including Hyprland) the same ideas are implemented via xkbcommon.

Docs:

Hyprland, Sway, etc. all use libinput + xkbcommon under the hood to interpret those keycodes and translate them into keysyms and modifiers.


5. Hyprland / your config: where the bindings fit in

Hyprland sits at the top of this stack:

  • It listens to the input events (via libinput).
  • It sees keysyms/modifiers (e.g. =Super=, L).
  • It matches them against your config:
bind = SUPER, L, exec, hyprlock

So your keyboard's "lock" key:

  1. Firmware sends HID usages 0xE3 (Left GUI) and 0x0F (L).
  2. Linux maps them to KEY_LEFTMETA (125) and KEY_L (38).
  3. xkbcommon maps that to Super + L.
  4. Hyprland says: "Ah, SUPER+L → run hyprlock".

The "topic" you stumbled into is just peeling back each abstraction layer.


6. Handy tools & libraries if you want to go deeper