Home

Awesome

pc-keyboard

A simple driver for handling PC keyboards, with both Scancode Set 1 (when running on a PC) and Scancode Set 2 support (when reading a PS/2 keyboard output directly).

Supports:

NameNo. KeysDescriptionLink
Us104Key101/104North American standard EnglishWikipedia
Uk105Key102/105United Kingdom standard EnglishWikipedia
Azerty102/105Typically used in French localesWikipedia
De105Key102/105German layoutWikipedia
FiSe105Key102/105Finnish/Swedish layoutWikipedia
No105Key102/105Norwegian layoutWikipedia
Jis109Key106/109JIS 109-key layout (Latin chars only)Wikipedia
Colemak101/104A keyboard layout designed to make typing more efficient and comfortableWikipedia
Dvorak104Key101/104The more 'ergonomic' alternative to QWERTYWikipedia
DVP104Key101/104Dvorak for ProgrammersWikipedia

101/104 keys is ANSI layout (wide Enter key) and 102/105 keys is ISO layout (tall Enter key). The difference between 101 and 104 (and between 102 and 105) comes from the two Windows keys and the Menu key that were added when Windows 95 came out. JIS keyboards have extra keys, added by making the space-bar and backspace keys shorter.

Usage

There are three basic steps to handling keyboard input. Your application may bypass some of these.

There is also Keyboard which combines the above three functions into a single object.

See the examples folder for more details.

Documentation

Keycodes

This crate uses symbolic keycodes to abstract over Scancode Set 1 and Scancode Set 2. They represented by the KeyCode enum. The scancodes can come from one of three supported keyboards: 102/105 key ISO, 101/104 key ANSI and 106/109-key JIS.

102/105 key ISO

This is the mapping of KeyCode to a 102/105-key ISO keyboard:

┌────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐   ┌────┬────┬────┐
│Esc │  │ F1 │ F2 │ F3 │ F4 │  │ F5 │ F6 │ F7 │ F8 │  │ F9 │F10 │F11 │F12 │   │PrSc│Scrl│PBrk│
└────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘   └────┴────┴────┘

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐  ┌────┬────┬────┐  ┌────┬────┬────┬────┐
│Oem8│Key1│Key2│Key3│Key4│Key5│Key6│Key7│Key8│Key9│Key0│Oem─│Oem+│Backspace│  │Inse│Home│PgUp│  │NumL│Num/│Num*│Num─│
├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤  ├────┼────┼────┤  ├────┼────┼────┼────┤
│ Tab │ Q  │ W  │ E  │ R  │ T  │ Y  │ U  │ I  │ O  │ P  │Oem4│Oem6│ Enter  │  │Dele│End │PgDo│  │Num7│Num8│Num9│    │
├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐       │  └────┴────┴────┘  ├────┼────┼────┤Num+│
│CapsLo│ A  │ S  │ D  │ F  │ G  │ H  │ J  │ K  │ L  │Oem1│Oem3│Oem7│       │                    │Num4│Num5│Num6│    │
├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤       ┌────┐       ├────┼────┼────┼────┤
│LShf│Oem5│ Z  │ X  │ C  │ V  │ B  │ N  │ M  │OemC│OemP│Oem2│   RShift     │       │ Up │       │Num1│Num2│Num3│    │
├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┴────┴┬──────┬──────┤  ┌────┼────┼────┐  ├────┴────┼────┤Num │
│LCtrl│LWin │ Alt │       Space                  │AltGr│RWin │ Menu │RCtrl │  │Left│Down│Righ│  │Num0     │NumP│Ente│
└─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘  └────┴────┴────┘  └─────────┴────┴────┘

The 102-key is missing LWin, RWin, and Menu.

101/104 key ANSI

This is the mapping of KeyCode to a 101/104-key ANSI keyboard:

┌────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐   ┌────┬────┬────┐
│Esc │  │ F1 │ F2 │ F3 │ F4 │  │ F5 │ F6 │ F7 │ F8 │  │ F9 │F10 │F11 │F12 │   │PrSc│Scrl│PBrk│
└────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘   └────┴────┴────┘

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐  ┌────┬────┬────┐  ┌────┬────┬────┬────┐
│Oem8│Key1│Key2│Key3│Key4│Key5│Key6│Key7│Key8│Key9│Key0│Oem─│Oem+│Backspace│  │Inse│Home│PgUp│  │NumL│Num/│Num*│Num─│
├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤  ├────+────+────┤  ├────┼────┼────┼────┤
│ Tab │ Q  │ W  │ E  │ R  │ T  │ Y  │ U  │ I  │ O  │ P  │Oem4│Oem6│  Oem5  │  │Dele│End │PgDo│  │Num7│Num8│Num9│    │
├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤  └────┴────┴────┘  ├────┼────┼────┤Num+│
│CapsLo│ A  │ S  │ D  │ F  │ G  │ H  │ J  │ K  │ L  │Oem1│Oem3│   Enter    │                    │Num4│Num5│Num6│    │
├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤       ┌────┐       ├────┼────┼────┼────┤
│ LShift  │ Z  │ X  │ C  │ V  │ B  │ N  │ M  │OemC│OemP│Oem2│   RShift     │       │ Up │       │Num1│Num2│Num3│    │
├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┴────┴┬──────┬──────┤  ┌────┼────┼────┐  ├────┴────┼────┤Num │
│LCtrl│LWin │ Alt │       Space                  │AltGr│RWin │ Menu │RCtrl │  │Left│Down│Righ│  │Num0     │NumP│Ente│
└─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘  └────┴────┴────┘  └─────────┴────┴────┘

Note that the Oem7 key is missing on the 104-key ANSI keyboard.

The 101-key is also missing LWin, RWin, and Menu.

106/109 key JIS

This is the mapping of KeyCode to a 106/109-key JIS keyboard:

┌────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐   ┌────┬────┬────┐
│Esc │  │ F1 │ F2 │ F3 │ F4 │  │ F5 │ F6 │ F7 │ F8 │  │ F9 │F10 │F11 │F12 │   │PrSc│Scrl│PBrk│
└────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘   └────┴────┴────┘

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐  ┌────┬────┬────┐  ┌────┬────┬────┬────┐
│Oem8│Key1│Key2│Key3│Key4│Key5│Key6│Key7│Key8│Key9│Key0│Oem─│Oem+│Om13│BkSp│  │Inse│Home│PgUp│  │NumL│Num/│Num*│Num─│
├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤  ├────┼────┼────┤  ├────┼────┼────┼────┤
│ Tab │ Q  │ W  │ E  │ R  │ T  │ Y  │ U  │ I  │ O  │ P  │Oem4│Oem6│ Enter  │  │Dele│End │PgDo│  │Num7│Num8│Num9│    │
├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐       │  └────┴────┴────┘  ├────┼────┼────┤Num+│
│CapsLo│ A  │ S  │ D  │ F  │ G  │ H  │ J  │ K  │ L  │Oem1│Oem3│Oem7│       │                    │Num4│Num5│Num6│    │
├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤       ┌────┐       ├────┼────┼────┼────┤
│LShift   │ Z  │ X  │ C  │ V  │ B  │ N  │ M  │OemC│OemP│Oem2│Oem12 │RShift │       │ Up │       │Num1│Num2│Num3│    │
├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬────┬──────┤  ┌────┼────┼────┐  ├────┴────┼────┤Num │
│LCtrl│LWin │LAlt │Oem9 │ Space Bar           │Oem10│Oem11│RWin│Menu│RCtrl │  │Left│Down│Righ│  │Num0     │NumP│Ente│
└─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘  └────┴────┴────┘  └─────────┴────┴────┘

Note that the Oem5 is missing on the 109-key JIS layout, but Oem9 (Muhenkan), Oem10 (Henkan/Zenkouho), Oem11 (Hiragana/Katakana), Oem12 (Backslash) and Oem13 (¥) are added.

The 106-key is also missing LWin, RWin, and Menu.

Conversion Table

Scancode Set 1 and Scancode Set 2 can be losslessly converted. Indeed, this is what the i8042 keyboard controller in your PC does - it takes Scancode Set 2 from the keyboard and provides Scancode Set 1 to the Operating System. This allowed them to change the keyboard design without breaking compatibility with any MS-DOS applications that read raw scancodes from the keyboard.

This table shows the correspondence between our symbolic KeyCode, Scancode Set 1 and Scancode Set 2. We may extend this in the future to also handle USB HID Scancodes. Any codes prefixed 0xE0 or 0xE1 are extended multi-byte scancodes. Typically these are keys that were not on the IBM PC and PC/XT keyboards so they they were added in such a way that if you ignored the 0xE0, you got a reasonable result anyway. For example ArrowLeft is 0xE04B in Scancode Set 1 because Numpad4 is 0x4B and that was the left-arrow key on an IBM PC or PC/XT.

Symbolic KeyScancode Set 1Scancode Set 2
Escape0x010x76
F10x3B0x05
F20x3C0x06
F30x3D0x04
F40x3E0x0C
F50x3F0x03
F60x400x0B
F70x410x83
F80x420x0A
F90x430x01
F100x440x09
F110x570x78
F120x580x07
PrintScreen0xE0370xE07C
SysRq0x540x7F
ScrollLock0x460x7E
PauseBreak----
-----
Oem80x290x0E
Key10x020x16
Key20x030x1E
Key30x040x26
Key40x050x25
Key50x060x2E
Key60x070x36
Key70x080x3D
Key80x090x3E
Key90x0A0x46
Key00x0B0x45
OemMinus0x0C0x4E
OemPlus0x0D0x55
Backspace0x0E0x66
Insert0xE0520xE070
Home0xE0470xE06C
PageUp0xE0490xE07D
NumpadLock0x450x77
NumpadDivide0xE0350xE04A
NumpadMultiply0x370x7C
NumpadSubtract0x4A0x7B
-----
Tab0x0F0x0D
Q0x100x15
W0x110x1D
E0x120x24
R0x130x2D
T0x140x2C
Y0x150x35
U0x160x3C
I0x170x43
O0x180x44
P0x190x4D
Oem40x1A0x54
Oem60x1B0x5B
Oem50x560x61
Oem70x2B0x5D
Delete0xE0530xE071
End0xE04F0xE069
PageDown0xE0510xE07A
Numpad70x470x6C
Numpad80x480x75
Numpad90x490x7D
NumpadAdd0x4E0x79
-----
CapsLock0x3A0x58
A0x1E0x1C
S0x1F0x1B
D0x200x23
F0x210x2B
G0x220x34
H0x230x33
J0x240x3B
K0x250x42
L0x260x4B
Oem10x270x4C
Oem30x280x52
Return0x1C0x5A
Numpad40x4B0x6B
Numpad50x4C0x73
Numpad60x4D0x74
-----
LShift0x2A0x12
Z0x2C0x1A
X0x2D0x22
C0x2E0x21
V0x2F0x2A
B0x300x32
N0x310x31
M0x320x3A
OemComma0x330x41
OemPeriod0x340x49
Oem20x350x4A
RShift0x360x59
ArrowUp0xE0480xE075
Numpad10x4F0x69
Numpad20x500x72
Numpad30x510x7A
NumpadEnter0xE01C0xE075
-----
LControl0x1D0x14
LWin0xE05B0xE01F
LAlt0x380x11
Spacebar0x390x29
RAltGr0xE0380xE011
RWin0xE05C0xE027
Apps0xE05C0xE02F
RControl0xE01D0xE014
ArrowLeft0xE04B0xE06B
ArrowDown0xE0500xE072
ArrowRight0xE04D0xE074
Numpad00x520x70
NumpadPeriod0x530x71
-----
Oem90x7B0x67
Oem100x790x64
Oem110x700x13
Oem120x730x51
Oem130x7D0x6A
-----
PrevTrack0xE0100xE015
NextTrack0xE0190xE04D
Mute0xE0200xE023
Calculator0xE0210xE02B
Play0xE0220xE034
Stop0xE0240xE03B
VolumeDown0xE02E0xE021
VolumeUp0xE0300xE032
WWWHome0xE0320xE03A
TooManyKeys--0x00
PowerOnTestOk--0xAA
RControl20xE11D0xE114
RAlt20xE02A0xE012

Note 1: PauseBreak does not have a scancode because it's something we infer from a sequence of other keypresses (NumLock with RControl2 held).

Note 2: SysReq doesn't have a key on the diagram, because the scancode is only generated when you do Alt + PrintScreen.

Minimum Supported Rust Version (MSRV)

This crate is guaranteed to compile on stable Rust 1.61 and up. It might compile with older versions but that may change in any new patch release.

Changelog

There is a changelog in CHANGELOG.md.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you shall be licensed as above, without any additional terms or conditions.

Code of Conduct

Contribution to this crate is organized under the terms of the Rust Code of Conduct, the maintainer of this crate, the Rust Embedded Community, promises to intervene to uphold that code of conduct.