proka_kernel/drivers/input/
keyboard.rs1extern 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}