#![cfg_attr(not(test), no_std)]
#[cfg(not(test))]
use core::marker::PhantomData;
#[cfg(test)]
use std::marker::PhantomData;
mod scancodes;
pub use crate::scancodes::{ScancodeSet1, ScancodeSet2};
#[derive(Debug)]
pub struct Keyboard<T, S>
where
T: KeyboardLayout,
S: ScancodeSet,
{
register: u16,
num_bits: u8,
decode_state: DecodeState,
handle_ctrl: HandleControl,
modifiers: Modifiers,
_layout: PhantomData<T>,
_set: PhantomData<S>,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Error {
BadStartBit,
BadStopBit,
ParityError,
UnknownKeyCode,
#[doc(hidden)]
InvalidState,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord)]
pub enum KeyCode {
AltLeft,
AltRight,
ArrowDown,
ArrowLeft,
ArrowRight,
ArrowUp,
BackSlash,
Backspace,
BackTick,
BracketSquareLeft,
BracketSquareRight,
CapsLock,
Comma,
ControlLeft,
ControlRight,
Delete,
End,
Enter,
Escape,
Equals,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
Fullstop,
Home,
Insert,
Key1,
Key2,
Key3,
Key4,
Key5,
Key6,
Key7,
Key8,
Key9,
Key0,
Menus,
Minus,
Numpad0,
Numpad1,
Numpad2,
Numpad3,
Numpad4,
Numpad5,
Numpad6,
Numpad7,
Numpad8,
Numpad9,
NumpadEnter,
NumpadLock,
NumpadSlash,
NumpadStar,
NumpadMinus,
NumpadPeriod,
NumpadPlus,
PageDown,
PageUp,
PauseBreak,
PrintScreen,
ScrollLock,
SemiColon,
ShiftLeft,
ShiftRight,
Slash,
Spacebar,
Tab,
Quote,
WindowsLeft,
WindowsRight,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
HashTilde,
PrevTrack,
NextTrack,
Mute,
Calculator,
Play,
Stop,
VolumeDown,
VolumeUp,
WWWHome,
PowerOnTestOk,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum KeyState {
Up,
Down,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum HandleControl {
MapLettersToUnicode,
Ignore,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct KeyEvent {
pub code: KeyCode,
pub state: KeyState,
}
pub trait KeyboardLayout {
fn map_keycode(
keycode: KeyCode,
modifiers: &Modifiers,
handle_ctrl: HandleControl,
) -> DecodedKey;
}
pub trait ScancodeSet {
fn advance_state(state: &mut DecodeState, code: u8) -> Result<Option<KeyEvent>, Error>;
fn map_scancode(code: u8) -> Result<KeyCode, Error>;
fn map_extended_scancode(code: u8) -> Result<KeyCode, Error>;
}
#[derive(Debug)]
pub struct Modifiers {
pub lshift: bool,
pub rshift: bool,
pub lctrl: bool,
pub rctrl: bool,
pub numlock: bool,
pub capslock: bool,
pub alt_gr: bool,
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum DecodedKey {
RawKey(KeyCode),
Unicode(char),
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum DecodeState {
Start,
Extended,
Release,
ExtendedRelease,
}
const KEYCODE_BITS: u8 = 11;
const EXTENDED_KEY_CODE: u8 = 0xE0;
const KEY_RELEASE_CODE: u8 = 0xF0;
impl<T, S> Keyboard<T, S>
where
T: KeyboardLayout,
S: ScancodeSet,
{
pub fn new(_layout: T, _set: S, handle_ctrl: HandleControl) -> Keyboard<T, S> {
Keyboard {
register: 0,
num_bits: 0,
decode_state: DecodeState::Start,
handle_ctrl,
modifiers: Modifiers {
lshift: false,
rshift: false,
lctrl: false,
rctrl: false,
numlock: true,
capslock: false,
alt_gr: false,
},
_layout: PhantomData,
_set: PhantomData,
}
}
pub fn set_ctrl_handling(&mut self, new_value: HandleControl) {
self.handle_ctrl = new_value;
}
pub fn get_ctrl_handling(&self) -> HandleControl {
self.handle_ctrl
}
pub fn clear(&mut self) {
self.register = 0;
self.num_bits = 0;
self.decode_state = DecodeState::Start;
}
pub fn add_word(&mut self, word: u16) -> Result<Option<KeyEvent>, Error> {
let byte = Self::check_word(word)?;
self.add_byte(byte)
}
pub fn add_byte(&mut self, byte: u8) -> Result<Option<KeyEvent>, Error> {
let r = S::advance_state(&mut self.decode_state, byte);
r
}
pub fn add_bit(&mut self, bit: bool) -> Result<Option<KeyEvent>, Error> {
self.register |= (bit as u16) << self.num_bits;
self.num_bits += 1;
if self.num_bits == KEYCODE_BITS {
let word = self.register;
self.register = 0;
self.num_bits = 0;
self.add_word(word)
} else {
Ok(None)
}
}
pub fn process_keyevent(&mut self, ev: KeyEvent) -> Option<DecodedKey> {
match ev {
KeyEvent {
code: KeyCode::ShiftLeft,
state: KeyState::Down,
} => {
self.modifiers.lshift = true;
None
}
KeyEvent {
code: KeyCode::ShiftRight,
state: KeyState::Down,
} => {
self.modifiers.rshift = true;
None
}
KeyEvent {
code: KeyCode::ShiftLeft,
state: KeyState::Up,
} => {
self.modifiers.lshift = false;
None
}
KeyEvent {
code: KeyCode::ShiftRight,
state: KeyState::Up,
} => {
self.modifiers.rshift = false;
None
}
KeyEvent {
code: KeyCode::CapsLock,
state: KeyState::Down,
} => {
self.modifiers.capslock = !self.modifiers.capslock;
None
}
KeyEvent {
code: KeyCode::NumpadLock,
state: KeyState::Down,
} => {
self.modifiers.numlock = !self.modifiers.numlock;
None
}
KeyEvent {
code: KeyCode::ControlLeft,
state: KeyState::Down,
} => {
self.modifiers.lctrl = true;
None
}
KeyEvent {
code: KeyCode::ControlLeft,
state: KeyState::Up,
} => {
self.modifiers.lctrl = false;
None
}
KeyEvent {
code: KeyCode::ControlRight,
state: KeyState::Down,
} => {
self.modifiers.rctrl = true;
None
}
KeyEvent {
code: KeyCode::ControlRight,
state: KeyState::Up,
} => {
self.modifiers.rctrl = false;
None
}
KeyEvent {
code: KeyCode::AltRight,
state: KeyState::Down,
} => {
self.modifiers.alt_gr = true;
None
}
KeyEvent {
code: KeyCode::AltRight,
state: KeyState::Up,
} => {
self.modifiers.alt_gr = false;
None
}
KeyEvent {
code: c,
state: KeyState::Down,
} => Some(T::map_keycode(c, &self.modifiers, self.handle_ctrl)),
_ => None,
}
}
fn get_bit(word: u16, offset: usize) -> bool {
((word >> offset) & 0x0001) != 0
}
fn has_even_number_bits(data: u8) -> bool {
(data.count_ones() % 2) == 0
}
fn check_word(word: u16) -> Result<u8, Error> {
let start_bit = Self::get_bit(word, 0);
let parity_bit = Self::get_bit(word, 9);
let stop_bit = Self::get_bit(word, 10);
let data = ((word >> 1) & 0xFF) as u8;
if start_bit {
return Err(Error::BadStartBit);
}
if !stop_bit {
return Err(Error::BadStopBit);
}
let need_parity = Self::has_even_number_bits(data);
if need_parity != parity_bit {
return Err(Error::ParityError);
}
Ok(data)
}
}
impl KeyEvent {
pub fn new(code: KeyCode, state: KeyState) -> KeyEvent {
KeyEvent { code, state }
}
}
impl Modifiers {
pub fn is_shifted(&self) -> bool {
(self.lshift | self.rshift)
}
pub fn is_ctrl(&self) -> bool {
(self.lctrl | self.rctrl)
}
pub fn is_caps(&self) -> bool {
(self.lshift | self.rshift) ^ self.capslock
}
}
pub mod layouts;
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_f9() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(
k.add_bit(true),
Ok(Some(KeyEvent::new(KeyCode::F9, KeyState::Down)))
);
}
#[test]
fn test_f9_word() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(
k.add_word(0x0402),
Ok(Some(KeyEvent::new(KeyCode::F9, KeyState::Down)))
);
}
#[test]
fn test_f9_byte() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(
k.add_byte(0x01),
Ok(Some(KeyEvent::new(KeyCode::F9, KeyState::Down)))
);
}
#[test]
fn test_keyup_keydown() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(
k.add_byte(0x01),
Ok(Some(KeyEvent::new(KeyCode::F9, KeyState::Down)))
);
assert_eq!(
k.add_byte(0x01),
Ok(Some(KeyEvent::new(KeyCode::F9, KeyState::Down)))
);
assert_eq!(k.add_byte(0xF0), Ok(None));
assert_eq!(
k.add_byte(0x01),
Ok(Some(KeyEvent::new(KeyCode::F9, KeyState::Up)))
);
}
#[test]
fn test_f5() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(
k.add_bit(true),
Ok(Some(KeyEvent::new(KeyCode::F5, KeyState::Down)))
);
}
#[test]
fn test_f5_up() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(false), Ok(None));
assert_eq!(k.add_bit(true), Ok(None));
assert_eq!(
k.add_bit(true),
Ok(Some(KeyEvent::new(KeyCode::F5, KeyState::Up)))
);
}
#[test]
fn test_shift() {
let mut k = Keyboard::new(
layouts::Uk105Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ShiftLeft, KeyState::Down)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Down)),
Some(DecodedKey::Unicode('A'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ShiftLeft, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Down)),
Some(DecodedKey::Unicode('a'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ShiftRight, KeyState::Down)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Down)),
Some(DecodedKey::Unicode('A'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ShiftRight, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::CapsLock, KeyState::Down)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::CapsLock, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::X, KeyState::Down)),
Some(DecodedKey::Unicode('X'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::X, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ShiftRight, KeyState::Down)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Down)),
Some(DecodedKey::Unicode('a'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ShiftRight, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::Key1, KeyState::Down)),
Some(DecodedKey::Unicode('1'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::Key1, KeyState::Up)),
None
);
}
#[test]
fn test_ctrl() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Down)),
Some(DecodedKey::Unicode('a'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ControlLeft, KeyState::Down)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Down)),
Some(DecodedKey::Unicode('\u{0001}'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ControlLeft, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Down)),
Some(DecodedKey::Unicode('a'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ControlRight, KeyState::Down)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Down)),
Some(DecodedKey::Unicode('\u{0001}'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::ControlRight, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Up)),
None
);
}
#[test]
fn test_numlock() {
let mut k = Keyboard::new(
layouts::Uk105Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::Numpad0, KeyState::Down)),
Some(DecodedKey::Unicode('0'))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::Numpad0, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::NumpadLock, KeyState::Down)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::NumpadLock, KeyState::Up)),
None
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::Numpad0, KeyState::Down)),
Some(DecodedKey::RawKey(KeyCode::Insert))
);
assert_eq!(
k.process_keyevent(KeyEvent::new(KeyCode::Numpad0, KeyState::Up)),
None
);
}
#[test]
fn validate_scancodes() {
let mut codes = Vec::new();
let mut errs = Vec::new();
for code in 0x00..=0x7F {
let r = ScancodeSet1::map_scancode(code);
match r {
Ok(c) => codes.push(c),
Err(_) => errs.push(code),
}
}
codes.sort();
println!("{:?}", codes);
assert_eq!(codes.len(), 85);
assert_eq!(errs.len(), 43);
let mut codes = Vec::new();
let mut errs = Vec::new();
for code in 0x00..=0xFF {
let r = ScancodeSet2::map_scancode(code);
match r {
Ok(c) => codes.push(c),
Err(_) => errs.push(code),
}
}
codes.sort();
println!("{:?}", codes);
assert_eq!(codes.len(), 87);
assert_eq!(errs.len(), 169);
}
#[test]
fn test_set_1_down_up_down() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet1,
HandleControl::MapLettersToUnicode,
);
assert_eq!(
k.add_byte(0x1e),
Ok(Some(KeyEvent::new(KeyCode::A, KeyState::Down)))
);
assert_eq!(
k.add_byte(0x9e),
Ok(Some(KeyEvent::new(KeyCode::A, KeyState::Up)))
);
assert_eq!(
k.add_byte(0x1f),
Ok(Some(KeyEvent::new(KeyCode::S, KeyState::Down)))
);
}
#[test]
fn test_set_1_ext_down_up_down() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet1,
HandleControl::MapLettersToUnicode,
);
assert_eq!(k.add_byte(0xe0), Ok(None));
assert_eq!(
k.add_byte(0x1c),
Ok(Some(KeyEvent::new(KeyCode::NumpadEnter, KeyState::Down)))
);
assert_eq!(k.add_byte(0xe0), Ok(None));
assert_eq!(
k.add_byte(0x9c),
Ok(Some(KeyEvent::new(KeyCode::NumpadEnter, KeyState::Up)))
);
}
#[test]
fn test_set_2_down_up() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(
k.add_byte(0x29),
Ok(Some(KeyEvent::new(KeyCode::Spacebar, KeyState::Down)))
);
assert_eq!(k.add_byte(0xF0), Ok(None));
assert_eq!(
k.add_byte(0x29),
Ok(Some(KeyEvent::new(KeyCode::Spacebar, KeyState::Up)))
);
assert_eq!(
k.add_byte(0x29),
Ok(Some(KeyEvent::new(KeyCode::Spacebar, KeyState::Down)))
);
assert_eq!(k.add_byte(0xF0), Ok(None));
assert_eq!(
k.add_byte(0x29),
Ok(Some(KeyEvent::new(KeyCode::Spacebar, KeyState::Up)))
);
assert_eq!(
k.add_byte(0x29),
Ok(Some(KeyEvent::new(KeyCode::Spacebar, KeyState::Down)))
);
assert_eq!(k.add_byte(0xF0), Ok(None));
assert_eq!(
k.add_byte(0x29),
Ok(Some(KeyEvent::new(KeyCode::Spacebar, KeyState::Up)))
);
}
#[test]
fn test_set_2_ext_down_up() {
let mut k = Keyboard::new(
layouts::Us104Key,
ScancodeSet2,
HandleControl::MapLettersToUnicode,
);
assert_eq!(k.add_byte(0xE0), Ok(None));
assert_eq!(
k.add_byte(0x6C),
Ok(Some(KeyEvent::new(KeyCode::Home, KeyState::Down)))
);
assert_eq!(k.add_byte(0xE0), Ok(None));
assert_eq!(k.add_byte(0xF0), Ok(None));
assert_eq!(
k.add_byte(0x6C),
Ok(Some(KeyEvent::new(KeyCode::Home, KeyState::Up)))
);
}
}