# 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: ``` text 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)** ([USB Implementers Forum](https://usb.org/sites/default/files/hut1_21.pdf?utm_source=chatgpt.com)) 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](https://d1.amobbs.com/bbs_upload782111/files_47/ourdev_692986N5FAHU.pdf?utm_source=chatgpt.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](https://docs.kernel.org/input/input.html?utm_source=chatgpt.com)) 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: - **Linux input subsystem overview** ([Linux Kernel Documentation](https://docs.kernel.org/input/input.html?utm_source=chatgpt.com)) - **Input event types and codes (`event-codes.txt`)** ([Kernel.org](https://www.kernel.org/doc/Documentation/input/event-codes.txt?utm_source=chatgpt.com)) The **keycode definitions** (`KEY_L`, `KEY_LEFTMETA`, etc.) live in: - `include/uapi/linux/input-event-codes.h` in the kernel source Example mirror: ([GitHub](https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/input-event-codes.h?utm_source=chatgpt.com)) When `evtest` prints: ``` text 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** ([X.Org](https://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html?utm_source=chatgpt.com)) - **Arch Wiki: X keyboard extension** (good high-level intro) ([ArchWiki](https://wiki.archlinux.org/title/X_keyboard_extension?utm_source=chatgpt.com)) - A nice "practical" walkthrough of XKB concepts: [[https://medium.com/\[cite/t:@damko/a-simple-humble-but-comprehensive-guide-to-xkb-for-linux-6f1ad5e13450](https://medium.com/%5Bcite/t:@damko/a-simple-humble-but-comprehensive-guide-to-xkb-for-linux-6f1ad5e13450)](https://medium.com/@damko/a-simple-humble-but-comprehensive-guide-to-xkb-for-linux-6f1ad5e13450)\] ([Medium](https://medium.com/%40damko/a-simple-humble-but-comprehensive-guide-to-xkb-for-linux-6f1ad5e13450?utm_source=chatgpt.com)) 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: ``` ini 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: ([python-evdev.readthedocs.io](https://python-evdev.readthedocs.io/?utm_source=chatgpt.com)) - Linux input subsystem docs again: ([Linux Kernel Documentation](https://docs.kernel.org/driver-api/input.html?utm_source=chatgpt.com))