rustubs/machine/
keyctrl.rs1use self::super::key::*;
13use crate::arch::x86_64::is_int_enabled;
14use crate::io::*;
15use crate::machine::device_io::*;
16use crate::proc::sync::semaphore::{Semaphore, SleepSemaphore};
17use crate::proc::sync::IRQHandlerEpilogue;
18use crate::proc::sync::L3Sync;
19use alloc::collections::VecDeque;
20use bitflags::bitflags;
21use core::cmp::{Eq, PartialEq};
22use core::sync::atomic::AtomicU32;
23use core::sync::atomic::Ordering;
24
25#[cfg(target_arch = "x86_64")]
26use crate::arch::x86_64::interrupt::{pic_8259, pic_8259::PicDeviceInt as PD};
27
28use super::key::Modifiers;
29
30pub static KBCTL_GLOBAL: L3Sync<KeyboardController> =
34 L3Sync::new(KeyboardController::new());
35pub static KEY_BUFFER: SleepSemaphore<VecDeque<Key>> =
36 SleepSemaphore::new(VecDeque::new());
37
38pub struct KeyboardController {
39 keystate: KeyState,
40 gather: AtomicU32,
43 cport: IOPort,
44 dport: IOPort,
45}
46
47pub struct KeyboardDriver {}
50
51impl IRQHandlerEpilogue for KeyboardDriver {
52 unsafe fn do_prologue() {
53 debug_assert!(!is_int_enabled());
54 KBCTL_GLOBAL.l3_get_ref_mut().fetch_key();
55 }
56 unsafe fn do_epilogue() {
57 debug_assert!(is_int_enabled());
58 let k = KBCTL_GLOBAL.l3_get_ref_mut_unchecked().consume_key();
60 if let Some(key) = k {
61 KEY_BUFFER.v_unguarded(key);
66 }
67 }
68}
69
70struct KeyState {
71 modi: Modifiers, prefix: Prefix, scan: Option<u8>,
74}
75
76#[derive(Clone, Copy, Eq, PartialEq)]
77enum Prefix {
78 PREFIX1,
79 PREFIX2,
80 NONE, }
82
83impl Prefix {
84 fn try_from_u8(val: u8) -> Option<Prefix> {
85 match val {
86 Defs::C_PREFIX1 => Some(Self::PREFIX1),
87 Defs::C_PREFIX2 => Some(Self::PREFIX2),
88 _ => None,
89 }
90 }
91}
92
93impl KeyState {
94 pub const fn new() -> Self {
95 Self {
96 modi: Modifiers::NONE,
97 prefix: Prefix::NONE,
98 scan: None,
99 }
100 }
101
102 fn get_leds(&self) -> u8 { return self.modi.bits() & 0b111; }
103}
104
105impl KeyboardController {
106 pub const fn new() -> Self {
107 Self {
108 keystate: KeyState::new(),
109 cport: IOPort::new(Defs::CTRL),
110 dport: IOPort::new(Defs::DATA),
111 gather: AtomicU32::new(Key::NONE_KEY),
112 }
113 }
114
115 fn toggle_lock(&mut self, lock: Modifiers) {
117 self.keystate.modi.toggle(lock);
118 self.update_led();
119 }
120 fn update_led(&self) {
125 let leds = self.keystate.get_leds();
126 self.dport.outb(Cmd::SetLed as u8);
130 unsafe { self.__block_until_data_available() }
131 let reply = self.dport.inb();
133 if reply == Msg::ACK as u8 {
135 self.dport.outb(leds);
136 }
137 unsafe {
140 self.__block_until_data_available();
141 }
142 }
143
144 fn update_state(&mut self, code: u8) {
145 self.keystate.scan = Some(code);
147 if let Some(p) = Prefix::try_from_u8(code) {
148 self.keystate.prefix = p;
149 return;
150 }
151 if code & Defs::BREAK_BIT == 0 {
152 if self.press_event() {
153 self.decode_key();
154 }
155 } else {
156 self.release_event();
157 }
158 self.keystate.prefix = Prefix::NONE;
160 }
161 fn press_event(&mut self) -> bool {
163 let mut should_decode_ascii = false;
164 let code = self.keystate.scan.unwrap();
165 match code {
166 Defs::C_SHIFT_L | Defs::C_SHIFT_R => {
167 self.keystate.modi.insert(Modifiers::SHIFT)
168 }
169 Defs::C_ALT => match self.keystate.prefix {
170 Prefix::PREFIX1 => {
171 self.keystate.modi.insert(Modifiers::ALT_RIGHT)
172 }
173 _ => self.keystate.modi.insert(Modifiers::ALT_LEFT),
174 },
175 Defs::C_CTRL => match self.keystate.prefix {
176 Prefix::PREFIX1 => {
177 self.keystate.modi.insert(Modifiers::CTRL_RIGHT)
178 }
179 _ => self.keystate.modi.insert(Modifiers::CTRL_LEFT),
180 },
181 Defs::C_CAPSLOCK => self.toggle_lock(Modifiers::CAPSLOCK),
182 Defs::C_NUM_P => {
183 if !self.keystate.modi.contains(Modifiers::CTRL_LEFT) {
184 self.toggle_lock(Modifiers::NUMLOCK);
185 }
186 }
187 Defs::C_SCRLOCK => self.toggle_lock(Modifiers::SCROLL_LOCK),
188 Defs::C_DEL => {
189 if self
190 .keystate
191 .modi
192 .contains(Modifiers::CTRL_LEFT | Modifiers::ALT_LEFT)
193 {
194 unsafe {
195 self.reboot();
196 }
197 }
198 }
199 _ => {
200 should_decode_ascii = true;
201 }
202 }
203 should_decode_ascii
204 }
205
206 fn release_event(&mut self) {
207 let code = self.keystate.scan.unwrap() & !Defs::BREAK_BIT;
209 match code {
210 Defs::C_SHIFT_L | Defs::C_SHIFT_R => {
211 self.keystate.modi.remove(Modifiers::SHIFT)
212 }
213 Defs::C_ALT => match self.keystate.prefix {
214 Prefix::PREFIX1 => {
215 self.keystate.modi.remove(Modifiers::ALT_RIGHT)
216 }
217 _ => self.keystate.modi.remove(Modifiers::ALT_LEFT),
218 },
219 Defs::C_CTRL => match self.keystate.prefix {
220 Prefix::PREFIX1 => {
221 self.keystate.modi.remove(Modifiers::CTRL_RIGHT)
222 }
223 _ => self.keystate.modi.remove(Modifiers::CTRL_LEFT),
224 },
225 _ => {}
226 }
227 }
228
229 #[inline(always)]
230 fn read_status(&self) -> Option<StatusReg> {
231 Some(StatusReg::from_bits_truncate(self.cport.inb()))
233 }
234
235 fn fetch_key(&mut self) {
237 let was_masked = Self::is_int_masked();
239 if !was_masked {
240 Self::disable_keyboard_int();
241 }
242
243 let sr = self.read_status().unwrap();
245 if !sr.contains(StatusReg::OUTB) || sr.contains(StatusReg::AUXB) {
247 return;
248 }
249 self.update_state(self.dport.inb());
250 if !was_masked {
251 Self::enable_keyboard_int();
252 }
253 }
254
255 #[inline]
257 fn consume_key(&mut self) -> Option<Key> {
258 let res = self.gather.swap(Key::NONE_KEY, Ordering::Relaxed);
259 return Key::from_u32(res);
260 }
261
262 fn decode_key(&mut self) {
263 let s = self.keystate.scan.unwrap();
266 let c = s & !Defs::BREAK_BIT;
267 let m = self.keystate.modi;
268 let p = self.keystate.prefix;
269
270 if c == 53 && p == Prefix::PREFIX1 {
271 let k = Key { asc: b'/', modi: m, scan: s };
272 self.gather.store(k.to_u32(), Ordering::Relaxed);
273 return;
274 }
275
276 let asc = if m.contains(Modifiers::NUMLOCK)
277 && p == Prefix::NONE
278 && (71..=83).contains(&c)
279 {
280 ASC_NUM_TAB[c as usize - 71]
281 } else if m.contains(Modifiers::ALT_RIGHT) {
282 ALT_TAB[c as usize]
283 } else if m.contains(Modifiers::SHIFT) {
284 SHIFT_TAB[c as usize]
285 } else if m.contains(Modifiers::CAPSLOCK) {
286 if (16..=26).contains(&c)
287 || (30..=40).contains(&c)
288 || (44..=50).contains(&c)
289 {
290 SHIFT_TAB[c as usize]
291 } else {
292 NORMAL_TAB[c as usize]
293 }
294 } else {
295 NORMAL_TAB[c as usize]
296 };
297
298 let k = Key { asc, modi: m, scan: s };
299 self.gather.store(k.to_u32(), Ordering::Relaxed);
300 }
301
302 fn cycle_repeat_rate() {
303 todo!();
304 }
305
306 fn cycle_deley() {
307 todo!();
308 }
309
310 #[inline(always)]
311 unsafe fn __block_until_cmd_buffer_empty(&self) {
312 loop {
313 let s = self.read_status().unwrap();
314 if !s.contains(StatusReg::INB) {
315 break;
316 };
317 }
318 }
319
320 #[inline(always)]
322 unsafe fn __block_until_data_available(&self) {
323 loop {
324 let status = self.read_status().unwrap();
325 if status.contains(StatusReg::OUTB) {
326 break;
327 }
328 }
329 }
330}
331
332#[cfg(target_arch = "x86_64")]
334impl KeyboardController {
335 #[inline(always)]
336 fn disable_keyboard_int() { pic_8259::forbid(PD::KEYBOARD); }
337
338 #[inline(always)]
339 fn enable_keyboard_int() { pic_8259::allow(PD::KEYBOARD); }
340
341 #[inline(always)]
342 fn is_int_masked() -> bool { pic_8259::is_masked(PD::KEYBOARD) }
343}
344
345impl KeyboardController {
347 pub unsafe fn reboot(&self) {
348 println!("reboot...");
351 *(0x472 as *mut u16) = 0x1234;
352 self.__block_until_cmd_buffer_empty();
353 self.cport.outb(Cmd::CpuReset as u8);
354 }
355}
356
357enum Cmd {
358 SetLed = 0xed,
360 ScanCode = 0xf0, SetSpeed = 0xf3,
362 CpuReset = 0xfe,
363}
364
365bitflags! {
366#[derive(Debug)]
367struct StatusReg:u8 {
368 const NONE = 0;
369 const OUTB = 1 << 0; const INB = 1 << 1; const SYS = 1 << 2; const CMD_DATA = 1 << 3; const NOT_LOCKED = 1 << 4; const AUXB = 1 << 5; const TIMEOUT = 1 << 6; const PARITY_ERR = 1 << 7;
380}
381}
382
383enum Msg {
384 ACK = 0xfa,
385}
386
387struct Defs;
388impl Defs {
389 pub const CTRL: u16 = 0x64;
390 pub const DATA: u16 = 0x60;
391 pub const CPU_RESET: u8 = 0xfe;
392 pub const BREAK_BIT: u8 = 1 << 7;
393 pub const C_PREFIX1: u8 = 0xe0;
395 pub const C_PREFIX2: u8 = 0xe1;
396 pub const C_SHIFT_L: u8 = 0x2a;
397 pub const C_SHIFT_R: u8 = 0x36;
398 pub const C_ALT: u8 = 0x38;
399 pub const C_CTRL: u8 = 0x1d;
400 pub const C_CAPSLOCK: u8 = 0x3a;
401 pub const C_SCRLOCK: u8 = 0x46;
402 pub const C_NUM_P: u8 = 0x45; pub const C_F1: u8 = 0x3b;
404 pub const C_DEL: u8 = 0x53;
405 pub const C_UP: u8 = 0x48;
406 pub const C_DOWN: u8 = 0x50;
407 pub const C_LEFT: u8 = 0x4b;
408 pub const C_RIGHT: u8 = 0x4d;
409 pub const C_DIV: u8 = 0x8;
410}