xref: /DragonOS/kernel/src/libs/keyboard_parser.rs (revision 6d345b774223b0daaf0ee629c7fb595a1912a9e2)
1 use alloc::sync::Arc;
2 
3 use crate::driver::tty::tty_device::TtyDevice;
4 
5 #[allow(dead_code)]
6 pub const NUM_SCAN_CODES: u8 = 0x80;
7 #[allow(dead_code)]
8 pub const TYPE1_KEYCODE_MAP_TABLE_COLS: u8 = 2;
9 
10 #[allow(dead_code)]
11 pub const TYPE1_KEYCODE_FLAG_BREAK: u8 = 0x80; // 用于判断按键是否被按下
12 
13 /// 标志状态
14 #[repr(u8)]
15 #[derive(Debug, PartialEq, Eq)]
16 #[allow(dead_code)]
17 pub enum KeyFlag {
18     NoneFlag = 0 as u8,
19     PauseBreak = 1 as u8,
20     PrintScreenPress = 2 as u8,
21     PrintScreenRelease = 4 as u8,
22     OtherKey = 8 as u8, // 除了上面两个按键以外的功能按键(不包括下面的第三类按键)
23 }
24 
25 /// @brief A FSM to parse type one keyboard scan code
26 #[derive(Debug)]
27 #[allow(dead_code)]
28 pub struct TypeOneFSM {
29     status: ScanCodeStatus,
30     current_state: TypeOneFSMState,
31     tty: Arc<TtyDevice>,
32 }
33 
34 impl TypeOneFSM {
35     #[allow(dead_code)]
36     pub fn new(tty: Arc<TtyDevice>) -> Self {
37         Self {
38             status: ScanCodeStatus::new(),
39             current_state: TypeOneFSMState::Start,
40             tty,
41         }
42     }
43 
44     /// @brief 解析扫描码
45     #[allow(dead_code)]
46     pub fn parse(&mut self, scancode: u8) -> TypeOneFSMState {
47         self.current_state = self
48             .current_state
49             .parse(scancode, &mut self.status, &self.tty);
50         self.current_state
51     }
52 }
53 
54 /// @brief 第一类扫描码状态机的状态
55 #[derive(Debug, Copy, Clone)]
56 pub enum TypeOneFSMState {
57     /// 起始状态
58     Start,
59     /// PauseBreak 第n个扫描码
60     PauseBreak(u8),
61     /// 多扫描码功能键起始状态
62     Func0,
63     /// 第三类扫描码或字符
64     Type3,
65 
66     PrtscPress(u8),
67     PrtscRelease(u8),
68 }
69 
70 impl TypeOneFSMState {
71     /// @brief 状态机总控程序
72     fn parse(
73         &self,
74         scancode: u8,
75         scancode_status: &mut ScanCodeStatus,
76         tty: &Arc<TtyDevice>,
77     ) -> TypeOneFSMState {
78         // kdebug!("the code is {:#x}\n", scancode);
79         match self {
80             TypeOneFSMState::Start => {
81                 return self.handle_start(scancode, scancode_status, tty);
82             }
83             TypeOneFSMState::PauseBreak(n) => {
84                 return self.handle_pause_break(*n, scancode_status, tty);
85             }
86             TypeOneFSMState::Func0 => {
87                 return self.handle_func0(scancode, scancode_status, tty);
88             }
89             TypeOneFSMState::Type3 => {
90                 return self.handle_type3(scancode, scancode_status, tty);
91             }
92             TypeOneFSMState::PrtscPress(n) => {
93                 return self.handle_prtsc_press(*n, scancode_status, tty)
94             }
95             TypeOneFSMState::PrtscRelease(n) => {
96                 return self.handle_prtsc_release(*n, scancode_status, tty)
97             }
98         }
99     }
100 
101     /// @brief 处理起始状态
102     fn handle_start(
103         &self,
104         scancode: u8,
105         scancode_status: &mut ScanCodeStatus,
106         tty: &Arc<TtyDevice>,
107     ) -> TypeOneFSMState {
108         //kdebug!("in handle_start the code is {:#x}\n",scancode);
109         match scancode {
110             0xe1 => {
111                 return TypeOneFSMState::PauseBreak(1);
112             }
113             0xe0 => {
114                 return TypeOneFSMState::Func0;
115             }
116             _ => {
117                 //kdebug!("in _d the code is {:#x}\n",scancode);
118                 return TypeOneFSMState::Type3.handle_type3(scancode, scancode_status, tty);
119             }
120         }
121     }
122 
123     /// @brief 处理PauseBreak状态
124     fn handle_pause_break(
125         &self,
126         scancode: u8,
127         scancode_status: &mut ScanCodeStatus,
128         tty: &Arc<TtyDevice>,
129     ) -> TypeOneFSMState {
130         static PAUSE_BREAK_SCAN_CODE: [u8; 6] = [0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5];
131         let i = match self {
132             TypeOneFSMState::PauseBreak(i) => *i,
133             _ => {
134                 return self.handle_type3(scancode, scancode_status, tty);
135             }
136         };
137         if scancode != PAUSE_BREAK_SCAN_CODE[i as usize] {
138             return self.handle_type3(scancode, scancode_status, tty);
139         } else {
140             if i == 5 {
141                 // 所有Pause Break扫描码都被清除
142                 return TypeOneFSMState::Start;
143             } else {
144                 return TypeOneFSMState::PauseBreak(i + 1);
145             }
146         }
147     }
148 
149     fn handle_func0(
150         &self,
151         scancode: u8,
152         scancode_status: &mut ScanCodeStatus,
153         tty: &Arc<TtyDevice>,
154     ) -> TypeOneFSMState {
155         //0xE0
156         match scancode {
157             0x2a => {
158                 return TypeOneFSMState::PrtscPress(2);
159             }
160             0xb7 => {
161                 return TypeOneFSMState::PrtscRelease(2);
162             }
163             0x1d => {
164                 // 按下右边的ctrl
165                 scancode_status.ctrl_r = true;
166             }
167             0x9d => {
168                 // 松开右边的ctrl
169                 scancode_status.ctrl_r = false;
170             }
171             0x38 => {
172                 // 按下右边的alt
173                 scancode_status.alt_r = true;
174             }
175             0xb8 => {
176                 // 松开右边的alt
177                 scancode_status.alt_r = false;
178             }
179             0x5b => {
180                 scancode_status.gui_l = true;
181             }
182             0xdb => {
183                 scancode_status.gui_l = false;
184             }
185             0x5c => {
186                 scancode_status.gui_r = true;
187             }
188             0xdc => {
189                 scancode_status.gui_r = false;
190             }
191             0x5d => {
192                 scancode_status.apps = true;
193             }
194             0xdd => {
195                 scancode_status.apps = false;
196             }
197             0x52 => {
198                 scancode_status.insert = true;
199             }
200             0xd2 => {
201                 scancode_status.insert = false;
202             }
203             0x47 => {
204                 scancode_status.home = true;
205             }
206             0xc7 => {
207                 scancode_status.home = false;
208             }
209             0x49 => {
210                 scancode_status.pgup = true;
211             }
212             0xc9 => {
213                 scancode_status.pgup = false;
214             }
215             0x53 => {
216                 scancode_status.del = true;
217                 Self::emit(tty, 127);
218             }
219             0xd3 => {
220                 scancode_status.del = false;
221             }
222             0x4f => {
223                 scancode_status.end = true;
224             }
225             0xcf => {
226                 scancode_status.end = false;
227             }
228             0x51 => {
229                 scancode_status.pgdn = true;
230             }
231             0xd1 => {
232                 scancode_status.pgdn = false;
233             }
234             0x48 => {
235                 scancode_status.arrow_u = true;
236                 Self::emit(tty, 224);
237                 Self::emit(tty, 72);
238             }
239             0xc8 => {
240                 scancode_status.arrow_u = false;
241             }
242             0x4b => {
243                 scancode_status.arrow_l = true;
244                 Self::emit(tty, 224);
245                 Self::emit(tty, 75);
246             }
247             0xcb => {
248                 scancode_status.arrow_l = false;
249             }
250             0x50 => {
251                 scancode_status.arrow_d = true;
252                 Self::emit(tty, 224);
253                 Self::emit(tty, 80);
254             }
255             0xd0 => {
256                 scancode_status.arrow_d = false;
257             }
258             0x4d => {
259                 scancode_status.arrow_r = true;
260                 Self::emit(tty, 224);
261                 Self::emit(tty, 77);
262             }
263             0xcd => {
264                 scancode_status.arrow_r = false;
265             }
266 
267             0x35 => {
268                 // 数字小键盘的 / 符号
269                 scancode_status.kp_forward_slash = true;
270 
271                 let ch = '/' as u8;
272                 Self::emit(tty, ch);
273             }
274             0xb5 => {
275                 scancode_status.kp_forward_slash = false;
276             }
277             0x1c => {
278                 scancode_status.kp_enter = true;
279                 Self::emit(tty, '\n' as u8);
280             }
281             0x9c => {
282                 scancode_status.kp_enter = false;
283             }
284             _ => {
285                 return TypeOneFSMState::Start;
286             }
287         }
288         return TypeOneFSMState::Start;
289     }
290 
291     fn handle_type3(
292         &self,
293         scancode: u8,
294         scancode_status: &mut ScanCodeStatus,
295         tty: &Arc<TtyDevice>,
296     ) -> TypeOneFSMState {
297         // 判断按键是被按下还是抬起
298         let flag_make = if (scancode & (TYPE1_KEYCODE_FLAG_BREAK as u8)) > 0 {
299             false //up
300         } else {
301             true //down
302         };
303 
304         // 计算扫描码位于码表的第几行
305         let mut col: bool = false;
306         let index = scancode & 0x7f;
307 
308         //kdebug!("in type3 ch is {:#x}\n",ch);
309         let mut key = KeyFlag::OtherKey; // 可视字符
310 
311         match index {
312             0x2a => {
313                 scancode_status.shift_l = flag_make;
314                 key = KeyFlag::NoneFlag;
315             }
316             0x36 => {
317                 scancode_status.shift_r = flag_make;
318                 key = KeyFlag::NoneFlag;
319             }
320             0x1d => {
321                 scancode_status.ctrl_l = flag_make;
322                 key = KeyFlag::NoneFlag;
323             }
324             0x38 => {
325                 scancode_status.alt_r = flag_make;
326                 key = KeyFlag::NoneFlag;
327             }
328             0x3A => {
329                 if scancode_status.caps_lock {
330                     scancode_status.caps_lock = !flag_make;
331                 }
332                 //if caps_lock: true, flag_make: true => cap_lock: false
333                 else {
334                     scancode_status.caps_lock = flag_make;
335                 } //else false => cap_lock: true
336                 key = KeyFlag::NoneFlag;
337             }
338             _ => {
339                 if flag_make == false {
340                     //kdebug!("in type3 ch is {:#x}\n",ch);
341                     key = KeyFlag::NoneFlag;
342                 }
343             }
344         }
345 
346         // shift被按下
347         if scancode_status.shift_l || scancode_status.shift_r {
348             col = true;
349         }
350 
351         if scancode_status.caps_lock {
352             if index >= 0x10 && index <= 0x19 {
353                 col = !col;
354             } else if index >= 0x1e && index <= 0x26 {
355                 col = !col;
356             } else if index >= 0x2c && index <= 0x32 {
357                 col = !col;
358             }
359         }
360 
361         let ch = TYPE1_KEY_CODE_MAPTABLE[col as usize + 2 * index as usize];
362 
363         if key != KeyFlag::NoneFlag {
364             Self::emit(tty, ch);
365         }
366         return TypeOneFSMState::Start;
367     }
368 
369     #[inline(always)]
370     fn emit(tty: &Arc<TtyDevice>, ch: u8) {
371         // 发送到tty
372         tty.input(&[ch]).ok();
373     }
374 
375     /// @brief 处理Prtsc按下事件
376     fn handle_prtsc_press(
377         &self,
378         scancode: u8,
379         scancode_status: &mut ScanCodeStatus,
380         tty: &Arc<TtyDevice>,
381     ) -> TypeOneFSMState {
382         static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0x2a, 0xe0, 0x37];
383         let i = match self {
384             TypeOneFSMState::PrtscPress(i) => *i,
385             _ => return TypeOneFSMState::Start, // 解析错误,返回起始状态
386         };
387         if i > 3 {
388             // 解析错误,返回起始状态
389             return TypeOneFSMState::Start;
390         }
391         if scancode != PRTSC_SCAN_CODE[i as usize] {
392             return self.handle_type3(scancode, scancode_status, tty);
393         } else {
394             if i == 3 {
395                 // 成功解析出PrtscPress
396                 return TypeOneFSMState::Start;
397             } else {
398                 // 继续解析
399                 return TypeOneFSMState::PrtscPress(i + 1);
400             }
401         }
402     }
403 
404     fn handle_prtsc_release(
405         &self,
406         scancode: u8,
407         scancode_status: &mut ScanCodeStatus,
408         tty: &Arc<TtyDevice>,
409     ) -> TypeOneFSMState {
410         static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0xb7, 0xe0, 0xaa];
411         let i = match self {
412             TypeOneFSMState::PrtscRelease(i) => *i,
413             _ => return TypeOneFSMState::Start, // 解析错误,返回起始状态
414         };
415         if i > 3 {
416             // 解析错误,返回起始状态
417             return TypeOneFSMState::Start;
418         }
419         if scancode != PRTSC_SCAN_CODE[i as usize] {
420             return self.handle_type3(scancode, scancode_status, tty);
421         } else {
422             if i == 3 {
423                 // 成功解析出PrtscRelease
424                 return TypeOneFSMState::Start;
425             } else {
426                 // 继续解析
427                 return TypeOneFSMState::PrtscRelease(i + 1);
428             }
429         }
430     }
431 }
432 
433 /// 按键状态
434 #[derive(Debug)]
435 #[allow(dead_code)]
436 pub struct ScanCodeStatus {
437     // Shift 按键
438     shift_l: bool,
439     shift_r: bool,
440     // Ctrl 按键
441     ctrl_l: bool,
442     ctrl_r: bool,
443     // Alt 按键
444     alt_l: bool,
445     alt_r: bool,
446     //
447     gui_l: bool,
448     gui_r: bool,
449     //
450     apps: bool,
451     insert: bool,
452     // page up/down
453     pgup: bool,
454     pgdn: bool,
455     del: bool,
456     home: bool,
457     end: bool,
458     arrow_u: bool,
459     arrow_l: bool,
460     arrow_d: bool,
461     arrow_r: bool,
462     // 斜杠
463     kp_forward_slash: bool,
464     // 回车
465     kp_enter: bool,
466     caps_lock: bool,
467 }
468 
469 impl ScanCodeStatus {
470     fn new() -> Self {
471         ScanCodeStatus {
472             shift_l: false,
473             shift_r: false,
474             ctrl_l: false,
475             ctrl_r: false,
476             alt_l: false,
477             alt_r: false,
478             gui_l: false,
479             gui_r: false,
480             apps: false,
481             insert: false,
482             pgup: false,
483             pgdn: false,
484             del: false,
485             home: false,
486             end: false,
487             arrow_u: false,
488             arrow_l: false,
489             arrow_d: false,
490             arrow_r: false,
491             kp_forward_slash: false,
492             kp_enter: false,
493             caps_lock: false,
494         }
495     }
496 }
497 
498 const TYPE1_KEY_CODE_MAPTABLE: [u8; 256] = [
499     /*0x00*/ 0, 0, /*0x01*/ 0, 0, // ESC
500     /*0x02*/ '1' as u8, '!' as u8, /*0x03*/ '2' as u8, '@' as u8,
501     /*0x04*/ '3' as u8, '#' as u8, /*0x05*/ '4' as u8, '$' as u8,
502     /*0x06*/ '5' as u8, '%' as u8, /*0x07*/ '6' as u8, '^' as u8,
503     /*0x08*/ '7' as u8, '&' as u8, /*0x09*/ '8' as u8, '*' as u8,
504     /*0x0a*/ '9' as u8, '(' as u8, /*0x0b*/ '0' as u8, ')' as u8,
505     /*0x0c*/ '-' as u8, '_' as u8, /*0x0d*/ '=' as u8, '+' as u8,
506     /*0x0e  \b */ 8 as u8, 8 as u8, // BACKSPACE
507     /*0x0f*/ '\t' as u8, '\t' as u8, // TAB
508     ////////////////////////character///////////////////////////
509     /*0x10*/ 'q' as u8,
510     'Q' as u8, /*0x11*/ 'w' as u8, 'W' as u8, /*0x12*/ 'e' as u8, 'E' as u8,
511     /*0x13*/ 'r' as u8, 'R' as u8, /*0x14*/ 't' as u8, 'T' as u8,
512     /*0x15*/ 'y' as u8, 'Y' as u8, /*0x16*/ 'u' as u8, 'U' as u8,
513     /*0x17*/ 'i' as u8, 'I' as u8, /*0x18*/ 'o' as u8, 'O' as u8,
514     /*0x19*/ 'p' as u8, 'P' as u8,
515     ////////////////////////character///////////////////////////
516 
517     /*0x1a*/ '[' as u8,
518     '{' as u8, /*0x1b*/ ']' as u8, '}' as u8, /*0x1c*/ '\n' as u8,
519     '\n' as u8, // ENTER
520     /*0x1d*/ 0x1d, 0x1d, // CTRL Left
521     ////////////////////////character///////////////////////////
522     /*0x1e*/ 'a' as u8,
523     'A' as u8, /*0x1f*/ 's' as u8, 'S' as u8, /*0x20*/ 'd' as u8, 'D' as u8,
524     /*0x21*/ 'f' as u8, 'F' as u8, /*0x22*/ 'g' as u8, 'G' as u8,
525     /*0x23*/ 'h' as u8, 'H' as u8, /*0x24*/ 'j' as u8, 'J' as u8,
526     /*0x25*/ 'k' as u8, 'K' as u8, /*0x26*/ 'l' as u8, 'L' as u8,
527     ////////////////////////character///////////////////////////
528 
529     /*0x27*/ ';' as u8,
530     ':' as u8, /*0x28*/ '\'' as u8, '"' as u8, /*0x29*/ '`' as u8, '~' as u8,
531     /*0x2a*/ 0x2a, 0x2a, // SHIFT Left
532     /*0x2b*/ '\\' as u8, '|' as u8,
533     ////////////////////////character///////////////////////////
534     /*0x2c*/ 'z' as u8,
535     'Z' as u8, /*0x2d*/ 'x' as u8, 'X' as u8, /*0x2e*/ 'c' as u8, 'C' as u8,
536     /*0x2f*/ 'v' as u8, 'V' as u8, /*0x30*/ 'b' as u8, 'B' as u8,
537     /*0x31*/ 'n' as u8, 'N' as u8, /*0x32*/ 'm' as u8, 'M' as u8,
538     ////////////////////////character///////////////////////////
539 
540     /*0x33*/ ',' as u8,
541     '<' as u8, /*0x34*/ '.' as u8, '>' as u8, /*0x35*/ '/' as u8, '?' as u8,
542     /*0x36*/ 0x36, 0x36, // SHIFT Right
543     /*0x37*/ '*' as u8, '*' as u8, /*0x38*/ 0x38, 0x38, // ALT Left
544     /*0x39*/ ' ' as u8, ' ' as u8, /*0x3a*/ 0, 0, // CAPS LOCK
545     /*0x3b*/ 0, 0, // F1
546     /*0x3c*/ 0, 0, // F2
547     /*0x3d*/ 0, 0, // F3
548     /*0x3e*/ 0, 0, // F4
549     /*0x3f*/ 0, 0, // F5
550     /*0x40*/ 0, 0, // F6
551     /*0x41*/ 0, 0, // F7
552     /*0x42*/ 0, 0, // F8
553     /*0x43*/ 0, 0, // F9
554     /*0x44*/ 0, 0, // F10
555     /*0x45*/ 0, 0, // NUM LOCK
556     /*0x46*/ 0, 0, // SCROLL LOCK
557     /*0x47*/ '7' as u8, 0, /*PAD HONE*/
558     /*0x48*/ '8' as u8, 0, /*PAD UP*/
559     /*0x49*/ '9' as u8, 0, /*PAD PAGEUP*/
560     /*0x4a*/ '-' as u8, 0, /*PAD MINUS*/
561     /*0x4b*/ '4' as u8, 0, /*PAD LEFT*/
562     /*0x4c*/ '5' as u8, 0, /*PAD MID*/
563     /*0x4d*/ '6' as u8, 0, /*PAD RIGHT*/
564     /*0x4e*/ '+' as u8, 0, /*PAD PLUS*/
565     /*0x4f*/ '1' as u8, 0, /*PAD END*/
566     /*0x50*/ '2' as u8, 0, /*PAD DOWN*/
567     /*0x51*/ '3' as u8, 0, /*PAD PAGEDOWN*/
568     /*0x52*/ '0' as u8, 0, /*PAD INS*/
569     /*0x53*/ '.' as u8, 0, /*PAD DOT*/
570     /*0x54*/ 0, 0, /*0x55*/ 0, 0, /*0x56*/ 0, 0, /*0x57*/ 0, 0, // F11
571     /*0x58*/ 0, 0, // F12
572     /*0x59*/ 0, 0, /*0x5a*/ 0, 0, /*0x5b*/ 0, 0, /*0x5c*/ 0, 0,
573     /*0x5d*/ 0, 0, /*0x5e*/ 0, 0, /*0x5f*/ 0, 0, /*0x60*/ 0, 0,
574     /*0x61*/ 0, 0, /*0x62*/ 0, 0, /*0x63*/ 0, 0, /*0x64*/ 0, 0,
575     /*0x65*/ 0, 0, /*0x66*/ 0, 0, /*0x67*/ 0, 0, /*0x68*/ 0, 0,
576     /*0x69*/ 0, 0, /*0x6a*/ 0, 0, /*0x6b*/ 0, 0, /*0x6c*/ 0, 0,
577     /*0x6d*/ 0, 0, /*0x6e*/ 0, 0, /*0x6f*/ 0, 0, /*0x70*/ 0, 0,
578     /*0x71*/ 0, 0, /*0x72*/ 0, 0, /*0x73*/ 0, 0, /*0x74*/ 0, 0,
579     /*0x75*/ 0, 0, /*0x76*/ 0, 0, /*0x77*/ 0, 0, /*0x78*/ 0, 0,
580     /*0x79*/ 0, 0, /*0x7a*/ 0, 0, /*0x7b*/ 0, 0, /*0x7c*/ 0, 0,
581     /*0x7d*/ 0, 0, /*0x7e*/ 0, 0, /*0x7f*/ 0, 0,
582 ];
583