Updated: 2025-12-28 Sun 19:48

# keyboard

planted: 2025-11-22 last tended to: 2025-12-28

## 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):

- HID Usage Tables (includes Keyboard/Keypad page 0x07) https://usb.org/sites/default/files/hut1_21.pdf (USB Implementers Forum)

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 `0xE3` → Keyboard Left GUI
- `7000f` = Page `0x07`, Usage `0x0F` → Keyboard 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. `EV_KEY`, `EV_MSC`, `EV_REL`, `EV_SYN`)
  - `code` (e.g. `KEY_L`, `KEY_LEFTMETA`)
  - `value` (pressed = 1, released = 0, repeat = 2)

Docs worth bookmarking:

- Linux input subsystem overview https://docs.kernel.org/input/input.html (Linux Kernel Documentation)
- Input event types and codes (`event-codes.txt`) https://www.kernel.org/doc/Documentation/input/event-codes.txt (Kernel.org)

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

- `include/uapi/linux/input-event-codes.h` in the kernel source Example mirror: https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/input-event-codes.h (GitHub)

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:

- X Keyboard Extension (XKB) protocol spec https://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html (X.Org)
- Arch Wiki: X keyboard extension (good high-level intro) https://wiki.archlinux.org/title/X_keyboard_extension (ArchWiki)
- A nice “practical” walkthrough of XKB concepts: https://medium.com/[cite/t:@damko/a-simple-humble-but-comprehensive-guide-to-xkb-for-linux-6f1ad5e13450] (Medium)

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

- `evtest`, `libinput debug-events`, `showkey` → To watch what your keyboard is actually sending.
- Python-evdev – Python bindings to read `/dev/input/event*` yourself: https://python-evdev.readthedocs.io/ (python-evdev.readthedocs.io)
- Linux input subsystem docs again: https://docs.kernel.org/driver-api/input.html (Linux Kernel Documentation)

Backlinks

- linuxmoc