rstubs/device/keyboard.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
//! Abstractions for the keyboard driver.
use arraydeque::{ArrayDeque, Wrapping};
use bitfield_struct::bitfield;
use pc_keyboard::layouts::Us104Key;
use pc_keyboard::{DecodedKey, HandleControl, KeyCode, KeyState, ScancodeSet1};
use crate::arch::io::Port;
use crate::threading::{Scheduler, Semaphore};
/// Access status (read) and command (write) registers.
const CTRL: Port<u8> = Port::new(0x64);
/// Access PS/2 device keyboard output (read) and input (write) buffers.
const DATA: Port<u8> = Port::new(0x60);
/// Keyboard driver, that initializes the keyboard and parses keycodes.
pub struct PS2Controller {
/// Keyboard layout. You choose another layout, like DE.
inner: pc_keyboard::Keyboard<Us104Key, ScancodeSet1>,
ctrl: bool,
alt: bool,
}
impl PS2Controller {
/// Constructs the keyboard driver
pub const fn new() -> Self {
Self {
inner: pc_keyboard::Keyboard::new(
ScancodeSet1::new(),
Us104Key,
HandleControl::MapLettersToUnicode,
),
ctrl: false,
alt: false,
}
}
/// Initialize the keyboar controller
pub fn init(&mut self) {
self.set_repeat_rate(0, 0);
// clear buffer
while self.event().is_some() {}
}
/// Configure the repeat rate of the keyboard
pub fn set_repeat_rate(&mut self, speed: u8, delay: u8) {
if speed <= 31 && delay <= 3 {
self.send_cmd(0xf3, delay << 4 | speed);
}
}
/// Read a key from the keyboard and parse it using the internal keyboard decoder.
///
/// This function also reboots the system if ctrl+alt+del is pressed
pub fn event(&mut self) -> Option<DecodedKey> {
let status = unsafe { Status(CTRL.read()) };
if status.has_output() {
let scan = unsafe { DATA.read() };
if !status.is_mouse() {
let event = self.inner.add_byte(scan).ok()??;
// Check for reboot shortcut
if event.code == KeyCode::LControl {
self.ctrl = event.state == KeyState::Down;
} else if event.code == KeyCode::LAlt {
self.alt = event.state == KeyState::Down;
} else if event.code == KeyCode::Delete && self.ctrl && self.alt {
println!("Rebooting...");
self.reboot();
}
return self.inner.process_keyevent(event);
}
}
None
}
/// Send a command or data to a connected PS/2 device
fn send_cmd(&mut self, cmd: u8, data: u8) {
unsafe {
while Status(CTRL.read()).input_pending() {}
CTRL.write(cmd);
CTRL.write(data);
}
}
/// Yes on x86 the keyboard can reboot the system
pub fn reboot(&mut self) {
self.send_cmd(0xfe, 0);
}
}
/// Buffers key presses.
///
/// This has to be protected by the [Guard][crate::interrupts::guard::Guard].
pub struct KeyBuffer {
sema: Semaphore,
buf: ArrayDeque<char, 16, Wrapping>,
}
impl KeyBuffer {
pub const fn new() -> Self {
Self {
sema: Semaphore::new(0),
buf: ArrayDeque::new(),
}
}
/// Push a key into the buffer
pub fn push(&mut self, scheduler: &mut Scheduler, key: char) {
self.buf.push_back(key);
self.sema.signal(scheduler);
}
/// Wait for the next key press
pub fn pop(&mut self, scheduler: &mut Scheduler) -> char {
self.sema.wait(scheduler);
self.buf.pop_front().unwrap()
}
}
/// Flags in the PS/2 controller status register
#[bitfield(u8)]
struct Status {
/// Output buffer non-empty?
has_output: bool,
/// Is input buffer full?
input_pending: bool,
/// Set on soft reset, cleared on power up
system_flag: bool,
/// Is command Byte? (otherwise data)
is_command: bool,
__: bool,
/// Mouse output has data
is_mouse: bool,
timeout_err: bool,
parity_err: bool,
}