Skip to main content

proka_kernel/drivers/input/
keyboard.rs

1extern crate alloc;
2use crate::drivers::{CharDevice, Device, DeviceError, DeviceInner, DeviceType, SharedDeviceOps};
3use alloc::string::String;
4use alloc::sync::Arc;
5use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard as PcKeyboard, ScancodeSet1};
6use spin::Mutex;
7
8const BUFFER_SIZE: usize = 128;
9
10pub struct KeyboardInner {
11    pc_keyboard: PcKeyboard<layouts::Us104Key, ScancodeSet1>,
12    enabled: bool,
13    buffer: [char; BUFFER_SIZE],
14    head: usize,
15    tail: usize,
16}
17
18pub struct Keyboard {
19    inner: Mutex<KeyboardInner>,
20    name: String,
21}
22
23impl Default for Keyboard {
24    fn default() -> Self {
25        Self {
26            inner: Mutex::new(KeyboardInner {
27                pc_keyboard: PcKeyboard::new(
28                    ScancodeSet1::new(),
29                    layouts::Us104Key,
30                    HandleControl::Ignore,
31                ),
32                enabled: true,
33                buffer: ['\0'; BUFFER_SIZE],
34                head: 0,
35                tail: 0,
36            }),
37            name: String::from("keyboard"),
38        }
39    }
40}
41
42impl Keyboard {
43    pub fn new() -> Self {
44        Self::default()
45    }
46
47    pub fn set_enabled(&self, enabled: bool) {
48        x86_64::instructions::interrupts::without_interrupts(|| {
49            self.inner.lock().enabled = enabled;
50        });
51    }
52
53    pub fn is_enabled(&self) -> bool {
54        x86_64::instructions::interrupts::without_interrupts(|| self.inner.lock().enabled)
55    }
56
57    pub fn handle_scancode(&self, scancode: u8) {
58        let mut inner = self.inner.lock();
59        if !inner.enabled {
60            return;
61        }
62
63        if let Ok(Some(key_event)) = inner.pc_keyboard.add_byte(scancode) {
64            if let Some(key) = inner.pc_keyboard.process_keyevent(key_event) {
65                match key {
66                    DecodedKey::Unicode(character) => {
67                        let tail = inner.tail;
68                        let next_tail = (tail + 1) % BUFFER_SIZE;
69                        if next_tail != inner.head {
70                            inner.buffer[tail] = character;
71                            inner.tail = next_tail;
72                        }
73                    }
74                    DecodedKey::RawKey(_) => {}
75                }
76            }
77        }
78    }
79
80    pub fn create_device() -> Device {
81        Device::new_auto_assign(KEYBOARD.name.clone(), DeviceInner::Char(KEYBOARD.clone()))
82    }
83}
84
85impl SharedDeviceOps for Keyboard {
86    fn name(&self) -> &str {
87        &self.name
88    }
89
90    fn device_type(&self) -> DeviceType {
91        DeviceType::Char
92    }
93
94    fn open(&self) -> Result<(), DeviceError> {
95        Ok(())
96    }
97
98    fn close(&self) -> Result<(), DeviceError> {
99        Ok(())
100    }
101
102    fn ioctl(&self, _cmd: u64, _arg: u64) -> Result<u64, DeviceError> {
103        Err(DeviceError::NotSupported)
104    }
105}
106
107impl CharDevice for Keyboard {
108    fn read(&self, buf: &mut [u8]) -> Result<usize, DeviceError> {
109        x86_64::instructions::interrupts::without_interrupts(|| {
110            let mut inner = self.inner.lock();
111            let mut read_count = 0;
112
113            while read_count < buf.len() && inner.head != inner.tail {
114                let c = inner.buffer[inner.head];
115                inner.head = (inner.head + 1) % BUFFER_SIZE;
116
117                let mut char_buf = [0u8; 4];
118                let char_str = c.encode_utf8(&mut char_buf);
119                let bytes = char_str.as_bytes();
120
121                if read_count + bytes.len() <= buf.len() {
122                    buf[read_count..read_count + bytes.len()].copy_from_slice(bytes);
123                    read_count += bytes.len();
124                } else {
125                    inner.head = (inner.head + BUFFER_SIZE - 1) % BUFFER_SIZE;
126                    break;
127                }
128            }
129
130            if read_count == 0 && !buf.is_empty() {
131                Err(DeviceError::WouldBlock)
132            } else {
133                Ok(read_count)
134            }
135        })
136    }
137
138    fn write(&self, _buf: &[u8]) -> Result<usize, DeviceError> {
139        Err(DeviceError::NotSupported)
140    }
141
142    fn has_data(&self) -> bool {
143        x86_64::instructions::interrupts::without_interrupts(|| {
144            let inner = self.inner.lock();
145            inner.head != inner.tail
146        })
147    }
148}
149
150lazy_static::lazy_static! {
151    pub static ref KEYBOARD: Arc<Keyboard> = Arc::new(Keyboard::new());
152}