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,
}