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