Files
org_roam/20251122223053-keyboard.org
2025-12-14 21:07:46 +00:00

204 lines
6.8 KiB
Org Mode
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
:PROPERTIES:
:ID: 0217f537-442a-4593-8c69-d481f0d1f2a8
:END:
#+title: keyboard
#+filetags: :hardware:linux:
* 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?
:PROPERTIES:
:CUSTOM_ID: big-picture-what-happens-when-you-press-a-key
:END:
When you hit a key (like your "lock" key), roughly this happens:
#+begin_src 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, ...`
#+end_src
The "topic" we've been poking at is basically *understanding each layer
in that stack*.
--------------
** 2. USB HID: where =700e3= comes from
:PROPERTIES:
:CUSTOM_ID: usb-hid-where-700e3-comes-from
:END:
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]]
([[https://usb.org/sites/default/files/hut1_21.pdf?utm_source=chatgpt.com][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:
([[https://d1.amobbs.com/bbs_upload782111/files_47/ourdev_692986N5FAHU.pdf?utm_source=chatgpt.com][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=
:PROPERTIES:
:CUSTOM_ID: linux-input-subsystem-ev_msc-ev_key-key_leftmeta
:END:
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*.
([[https://docs.kernel.org/input/input.html?utm_source=chatgpt.com][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]]
([[https://docs.kernel.org/input/input.html?utm_source=chatgpt.com][Linux
Kernel Documentation]])
- *Input event types and codes (=event-codes.txt=)*
[[https://www.kernel.org/doc/Documentation/input/event-codes.txt]]
([[https://www.kernel.org/doc/Documentation/input/event-codes.txt?utm_source=chatgpt.com][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]]
([[https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/linux/input-event-codes.h?utm_source=chatgpt.com][GitHub]])
When =evtest= prints:
#+begin_src text
type 4 (EV_MSC), code 4 (MSC_SCAN), value 700e3
type 1 (EV_KEY), code 125 (KEY_LEFTMETA), value 0
#+end_src
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
:PROPERTIES:
:CUSTOM_ID: xkb-xkbcommon-mapping-to-actual-characters-modifiers
:END:
Above the kernel, you've got an extra mapping layer that says:
#+begin_quote
For keycode N, with this layout, when Shift is held, produce this
character/symbol.
#+end_quote
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]]
([[https://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html?utm_source=chatgpt.com][X.Org]])
- *Arch Wiki: X keyboard extension* (good high-level intro)
[[https://wiki.archlinux.org/title/X_keyboard_extension]]
([[https://wiki.archlinux.org/title/X_keyboard_extension?utm_source=chatgpt.com][ArchWiki]])
- A nice "practical" walkthrough of XKB concepts:
[[https://medium.com/@damko/a-simple-humble-but-comprehensive-guide-to-xkb-for-linux-6f1ad5e13450][https://medium.com/[cite/t:@damko/a-simple-humble-but-comprehensive-guide-to-xkb-for-linux-6f1ad5e13450]]]
([[https://medium.com/%40damko/a-simple-humble-but-comprehensive-guide-to-xkb-for-linux-6f1ad5e13450?utm_source=chatgpt.com][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
:PROPERTIES:
:CUSTOM_ID: hyprland-your-config-where-the-bindings-fit-in
:END:
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:
#+begin_src ini
bind = SUPER, L, exec, hyprlock
#+end_src
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
:PROPERTIES:
:CUSTOM_ID: handy-tools-libraries-if-you-want-to-go-deeper
:END:
- =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/]]
([[https://python-evdev.readthedocs.io/?utm_source=chatgpt.com][python-evdev.readthedocs.io]])
- Linux input subsystem docs again:
[[https://docs.kernel.org/driver-api/input.html]]
([[https://docs.kernel.org/driver-api/input.html?utm_source=chatgpt.com][Linux
Kernel Documentation]])