1#[derive(Debug, Clone, Copy)]
2pub struct KeyEvent {
3 pub keycode: u8,
4 pub pressed: bool,
5}
6
7use core::sync::atomic::{AtomicU8, Ordering};
8
9static MODIFIER_STATE: AtomicU8 = AtomicU8::new(0);
14
15pub const MOD_SHIFT: u8 = 1 << 0;
16pub const MOD_CTRL: u8 = 1 << 1;
17pub const MOD_ALT: u8 = 1 << 2;
18pub const MOD_META: u8 = 1 << 3;
19
20pub fn modifier_state() -> u8 {
22 MODIFIER_STATE.load(Ordering::Relaxed)
23}
24
25pub fn shift_down() -> bool {
27 modifier_state() & MOD_SHIFT != 0
28}
29pub fn ctrl_down() -> bool {
30 modifier_state() & MOD_CTRL != 0
31}
32pub fn alt_down() -> bool {
33 modifier_state() & MOD_ALT != 0
34}
35pub fn meta_down() -> bool {
36 modifier_state() & MOD_META != 0
37}
38
39fn set_modifier(bit: u8, pressed: bool) {
41 let cur = MODIFIER_STATE.load(Ordering::Relaxed);
42 let next = if pressed { cur | bit } else { cur & !bit };
43 MODIFIER_STATE.store(next, Ordering::Relaxed);
44}
45
46pub const KC_KILL_LINE: u8 = 0x5A;
50
51#[derive(Debug, Clone, Copy, PartialEq, Eq)]
52pub enum KeyboardLayout {
53 Us,
54 Jis,
55}
56
57impl KeyboardLayout {
58 pub const fn name(self) -> &'static str {
59 match self {
60 Self::Us => "US",
61 Self::Jis => "JIS",
62 }
63 }
64
65 pub fn parse(name: &str) -> Option<Self> {
66 if name.eq_ignore_ascii_case("us") {
67 Some(Self::Us)
68 } else if name.eq_ignore_ascii_case("js")
69 || name.eq_ignore_ascii_case("jis")
70 || name.eq_ignore_ascii_case("jp")
71 {
72 Some(Self::Jis)
73 } else {
74 None
75 }
76 }
77}
78
79pub struct Keyboard {
80 pub shift_pressed: bool,
81 pub ctrl_pressed: bool,
82 pub alt_pressed: bool,
83 layout: KeyboardLayout,
84 logical_map: [u8; 128],
85}
86
87impl Default for Keyboard {
88 fn default() -> Self {
89 Self::new()
90 }
91}
92
93impl Keyboard {
94 pub const fn new() -> Self {
95 Self {
96 shift_pressed: false,
97 ctrl_pressed: false,
98 alt_pressed: false,
99 layout: KeyboardLayout::Jis,
100 logical_map: [0; 128],
101 }
102 }
103
104 pub fn set_layout(&mut self, layout: KeyboardLayout) {
105 self.layout = layout;
106 }
107
108 pub const fn layout(&self) -> KeyboardLayout {
109 self.layout
110 }
111
112 pub fn decode(&mut self, code: u8) -> Option<KeyEvent> {
114 let pressed = (code & 0x80) == 0;
116 let phys_keycode = code & 0x7F;
117
118 if phys_keycode >= 128 {
119 return None;
120 }
121
122 let mut keycode = phys_keycode;
123
124 if pressed {
125 if keycode == 0x3A && crate::kernel::config::get_config().swap_caps_ctrl {
127 keycode = 0x1D;
128 }
129
130 if self.ctrl_pressed {
132 if let Some(c) = alpha_char(keycode, self.shift_pressed) {
133 match c.to_ascii_lowercase() {
134 'p' => keycode = 0x48, 'n' => keycode = 0x50, 'b' => keycode = 0x4B, 'f' => keycode = 0x4D, 'a' => keycode = 0x47, 'e' => keycode = 0x4F, 'h' => keycode = 0x0E, 'd' => keycode = 0x53, 'k' => keycode = KC_KILL_LINE, _ => {}
144 }
145 }
146 }
147
148 self.logical_map[phys_keycode as usize] = keycode;
150 } else {
151 let mapped = self.logical_map[phys_keycode as usize];
153 if mapped != 0 {
154 keycode = mapped;
155 self.logical_map[phys_keycode as usize] = 0;
156 } else {
157 if keycode == 0x3A && crate::kernel::config::get_config().swap_caps_ctrl {
158 keycode = 0x1D;
159 }
160 }
161 }
162
163 match keycode {
165 0x2A | 0x36 => {
166 self.shift_pressed = pressed;
168 set_modifier(MOD_SHIFT, pressed);
169 }
170 0x1D => {
171 self.ctrl_pressed = pressed;
173 set_modifier(MOD_CTRL, pressed);
174 }
175 0x38 => {
176 self.alt_pressed = pressed;
178 set_modifier(MOD_ALT, pressed);
179 }
180 _ => {}
181 }
182
183 Some(KeyEvent { keycode, pressed })
184 }
185
186 pub fn get_ascii(&self, keycode: u8) -> Option<char> {
188 if let Some(letter) = alpha_char(keycode, self.shift_pressed) {
189 return Some(letter);
190 }
191
192 let layout = crate::kernel::config::get_config().keyboard_layout;
193 match layout {
194 KeyboardLayout::Us => us_ascii(keycode, self.shift_pressed),
195 KeyboardLayout::Jis => jis_ascii(keycode, self.shift_pressed),
196 }
197 }
198}
199
200pub fn ascii_to_scancode(c: char, layout: KeyboardLayout) -> Option<(u8, bool)> {
206 match c {
208 '\n' | '\r' => return Some((0x1C, false)), '\x08' | '\x7f' => return Some((0x0E, false)), '\t' => return Some((0x0F, false)),
211 '' => return Some((0x01, false)),
216 _ => {}
217 }
218 for kc in 0u8..0x80 {
219 for &shift in &[false, true] {
220 if alpha_char(kc, shift) == Some(c) {
221 return Some((kc, shift));
222 }
223 let mapped = match layout {
224 KeyboardLayout::Us => us_ascii(kc, shift),
225 KeyboardLayout::Jis => jis_ascii(kc, shift),
226 };
227 if mapped == Some(c) {
228 return Some((kc, shift));
229 }
230 }
231 }
232 None
233}
234
235fn alpha_char(keycode: u8, shift_pressed: bool) -> Option<char> {
236 let c = match keycode {
237 0x1E => {
238 if shift_pressed {
239 'A'
240 } else {
241 'a'
242 }
243 }
244 0x30 => {
245 if shift_pressed {
246 'B'
247 } else {
248 'b'
249 }
250 }
251 0x2E => {
252 if shift_pressed {
253 'C'
254 } else {
255 'c'
256 }
257 }
258 0x20 => {
259 if shift_pressed {
260 'D'
261 } else {
262 'd'
263 }
264 }
265 0x12 => {
266 if shift_pressed {
267 'E'
268 } else {
269 'e'
270 }
271 }
272 0x21 => {
273 if shift_pressed {
274 'F'
275 } else {
276 'f'
277 }
278 }
279 0x22 => {
280 if shift_pressed {
281 'G'
282 } else {
283 'g'
284 }
285 }
286 0x23 => {
287 if shift_pressed {
288 'H'
289 } else {
290 'h'
291 }
292 }
293 0x17 => {
294 if shift_pressed {
295 'I'
296 } else {
297 'i'
298 }
299 }
300 0x24 => {
301 if shift_pressed {
302 'J'
303 } else {
304 'j'
305 }
306 }
307 0x25 => {
308 if shift_pressed {
309 'K'
310 } else {
311 'k'
312 }
313 }
314 0x26 => {
315 if shift_pressed {
316 'L'
317 } else {
318 'l'
319 }
320 }
321 0x32 => {
322 if shift_pressed {
323 'M'
324 } else {
325 'm'
326 }
327 }
328 0x31 => {
329 if shift_pressed {
330 'N'
331 } else {
332 'n'
333 }
334 }
335 0x18 => {
336 if shift_pressed {
337 'O'
338 } else {
339 'o'
340 }
341 }
342 0x19 => {
343 if shift_pressed {
344 'P'
345 } else {
346 'p'
347 }
348 }
349 0x10 => {
350 if shift_pressed {
351 'Q'
352 } else {
353 'q'
354 }
355 }
356 0x13 => {
357 if shift_pressed {
358 'R'
359 } else {
360 'r'
361 }
362 }
363 0x1F => {
364 if shift_pressed {
365 'S'
366 } else {
367 's'
368 }
369 }
370 0x14 => {
371 if shift_pressed {
372 'T'
373 } else {
374 't'
375 }
376 }
377 0x16 => {
378 if shift_pressed {
379 'U'
380 } else {
381 'u'
382 }
383 }
384 0x2F => {
385 if shift_pressed {
386 'V'
387 } else {
388 'v'
389 }
390 }
391 0x11 => {
392 if shift_pressed {
393 'W'
394 } else {
395 'w'
396 }
397 }
398 0x2D => {
399 if shift_pressed {
400 'X'
401 } else {
402 'x'
403 }
404 }
405 0x15 => {
406 if shift_pressed {
407 'Y'
408 } else {
409 'y'
410 }
411 }
412 0x2C => {
413 if shift_pressed {
414 'Z'
415 } else {
416 'z'
417 }
418 }
419 _ => return None,
420 };
421 Some(c)
422}
423
424fn us_ascii(keycode: u8, shift_pressed: bool) -> Option<char> {
425 let c = match keycode {
426 0x02 => {
427 if shift_pressed {
428 '!'
429 } else {
430 '1'
431 }
432 }
433 0x03 => {
434 if shift_pressed {
435 '@'
436 } else {
437 '2'
438 }
439 }
440 0x04 => {
441 if shift_pressed {
442 '#'
443 } else {
444 '3'
445 }
446 }
447 0x05 => {
448 if shift_pressed {
449 '$'
450 } else {
451 '4'
452 }
453 }
454 0x06 => {
455 if shift_pressed {
456 '%'
457 } else {
458 '5'
459 }
460 }
461 0x07 => {
462 if shift_pressed {
463 '^'
464 } else {
465 '6'
466 }
467 }
468 0x08 => {
469 if shift_pressed {
470 '&'
471 } else {
472 '7'
473 }
474 }
475 0x09 => {
476 if shift_pressed {
477 '*'
478 } else {
479 '8'
480 }
481 }
482 0x0A => {
483 if shift_pressed {
484 '('
485 } else {
486 '9'
487 }
488 }
489 0x0B => {
490 if shift_pressed {
491 ')'
492 } else {
493 '0'
494 }
495 }
496 0x0C => {
497 if shift_pressed {
498 '_'
499 } else {
500 '-'
501 }
502 }
503 0x0D => {
504 if shift_pressed {
505 '+'
506 } else {
507 '='
508 }
509 }
510 0x0E => '\x08',
511 0x0F => '\t',
512 0x1A => {
513 if shift_pressed {
514 '{'
515 } else {
516 '['
517 }
518 }
519 0x1B => {
520 if shift_pressed {
521 '}'
522 } else {
523 ']'
524 }
525 }
526 0x27 => {
527 if shift_pressed {
528 ':'
529 } else {
530 ';'
531 }
532 }
533 0x28 => {
534 if shift_pressed {
535 '"'
536 } else {
537 '\''
538 }
539 }
540 0x29 => {
541 if shift_pressed {
542 '~'
543 } else {
544 '`'
545 }
546 }
547 0x2B => {
548 if shift_pressed {
549 '|'
550 } else {
551 '\\'
552 }
553 }
554 0x33 => {
555 if shift_pressed {
556 '<'
557 } else {
558 ','
559 }
560 }
561 0x34 => {
562 if shift_pressed {
563 '>'
564 } else {
565 '.'
566 }
567 }
568 0x35 => {
569 if shift_pressed {
570 '?'
571 } else {
572 '/'
573 }
574 }
575 0x39 => ' ',
576 0x1C => '\n',
577 _ => return None,
578 };
579 Some(c)
580}
581
582fn jis_ascii(keycode: u8, shift_pressed: bool) -> Option<char> {
583 let c = match keycode {
584 0x02 => {
585 if shift_pressed {
586 '!'
587 } else {
588 '1'
589 }
590 }
591 0x03 => {
592 if shift_pressed {
593 '"'
594 } else {
595 '2'
596 }
597 }
598 0x04 => {
599 if shift_pressed {
600 '#'
601 } else {
602 '3'
603 }
604 }
605 0x05 => {
606 if shift_pressed {
607 '$'
608 } else {
609 '4'
610 }
611 }
612 0x06 => {
613 if shift_pressed {
614 '%'
615 } else {
616 '5'
617 }
618 }
619 0x07 => {
620 if shift_pressed {
621 '&'
622 } else {
623 '6'
624 }
625 }
626 0x08 => {
627 if shift_pressed {
628 '\''
629 } else {
630 '7'
631 }
632 }
633 0x09 => {
634 if shift_pressed {
635 '('
636 } else {
637 '8'
638 }
639 }
640 0x0A => {
641 if shift_pressed {
642 ')'
643 } else {
644 '9'
645 }
646 }
647 0x0B => {
649 if shift_pressed {
650 ')'
651 } else {
652 '0'
653 }
654 }
655 0x0C => {
656 if shift_pressed {
657 '='
658 } else {
659 '-'
660 }
661 }
662 0x0D => {
663 if shift_pressed {
664 '~'
665 } else {
666 '^'
667 }
668 }
669 0x0E => '\x08',
670 0x0F => '\t',
671 0x1A => {
672 if shift_pressed {
673 '`'
674 } else {
675 '@'
676 }
677 }
678 0x1B => {
679 if shift_pressed {
680 '{'
681 } else {
682 '['
683 }
684 }
685 0x27 => {
686 if shift_pressed {
687 '+'
688 } else {
689 ';'
690 }
691 }
692 0x28 => {
693 if shift_pressed {
694 '*'
695 } else {
696 ':'
697 }
698 }
699 0x29 => return None,
700 0x2B => {
701 if shift_pressed {
702 '}'
703 } else {
704 ']'
705 }
706 }
707 0x33 => {
708 if shift_pressed {
709 '<'
710 } else {
711 ','
712 }
713 }
714 0x34 => {
715 if shift_pressed {
716 '>'
717 } else {
718 '.'
719 }
720 }
721 0x35 => {
722 if shift_pressed {
723 '?'
724 } else {
725 '/'
726 }
727 }
728 0x39 => ' ',
729 0x1C => '\n',
730 0x73 => {
731 if shift_pressed {
732 '_'
733 } else {
734 '\\'
735 }
736 }
737 0x7D => {
738 if shift_pressed {
739 '|'
740 } else {
741 '\\'
742 }
743 }
744 _ => return None,
745 };
746 Some(c)
747}