Writing an OS Kernel from Scratch | Keyboard — How Keystrokes Become Characters
Have you ever wondered about this process: you press a key → a character appears on screen. What does the OS experience in between? How do keyboard scan codes become scancodes? What’s the difference between USB HID and PS/2?
From the mechanical keyboard matrix to the Linux input subsystem, this article breaks down the complete “key to character” chain, giving you a debuggable map.
1. Keyboard Physical Layer: Matrix Scanning
A typical keyboard has an N×M row/column matrix, with each key being a switch at a matrix intersection.
Column 0 Column 1 Column 2 Column 3
│ │ │ │
Row 0 ──○─────────○─────────○─────────○ ← ESC, 1, 2, 3...
Row 1 ──○─────────○─────────○─────────○ ← Tab, Q, W, E, R...
Row 2 ──○─────────○─────────○─────────○ ← CapsLock, A, S, D, F...
...Scanning process:
- Keyboard controller drives Row 0 low, other Rows high
- Read Column levels to determine which Column has low level (pressed)
- Intersection determined → key coordinate (Row, Column) confirmed
- Look up table to convert (Row, Column) to Scan Code
PS/2 Scan Code Set 2 example:
- Press
A: keyboard sends0x1C - Press
Shift+A: first sends0x12(Left Shift Make), then0x1C - Release
A: sends0xF0+0x1C(Break Code)
# Linux: view current keyboard scan codes
$ showkey -s
# Press any key to see its scancode (decimal)
# Press ESC or wait 10 seconds to exit
# View keycode mapping
$ dumpkeys | head -20
keycode 1 = Escape
keycode 2 = one
keycode 3 = two2. PS/2 Protocol: Legacy Keyboard Communication
PS/2 keyboards use a simple synchronous serial protocol: 11 bits per frame (1 Start + 8 Data + 1 Parity + 1 Stop), clock provided by the keyboard (~10kHz).
Comments