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
//! Abstractions for the keyboard driver.
#![allow(unused)]
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> {
todo!("BSB A1")
}
/// 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) {
todo!("BSB A6")
}
/// Wait for the next key press
pub fn pop(&mut self, scheduler: &mut Scheduler) -> char {
todo!("BSB A6")
}
}
/// 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,
}