xref: /DragonOS/kernel/src/libs/keyboard_parser.rs (revision 52da9a59374752b4d01907b052135a0d317781dd)
1*52da9a59SGnoCiYeH use core::sync::atomic::Ordering;
2*52da9a59SGnoCiYeH 
320e3152eSlogin use alloc::sync::Arc;
420e3152eSlogin 
5*52da9a59SGnoCiYeH use crate::driver::tty::{
6*52da9a59SGnoCiYeH     tty_port::{TtyPort, TTY_PORTS},
7*52da9a59SGnoCiYeH     virtual_terminal::virtual_console::CURRENT_VCNUM,
8*52da9a59SGnoCiYeH };
95fb12ce4SGou Ngai 
105fb12ce4SGou Ngai #[allow(dead_code)]
115fb12ce4SGou Ngai pub const NUM_SCAN_CODES: u8 = 0x80;
125fb12ce4SGou Ngai #[allow(dead_code)]
135fb12ce4SGou Ngai pub const TYPE1_KEYCODE_MAP_TABLE_COLS: u8 = 2;
145fb12ce4SGou Ngai 
155fb12ce4SGou Ngai #[allow(dead_code)]
165fb12ce4SGou Ngai pub const TYPE1_KEYCODE_FLAG_BREAK: u8 = 0x80; // 用于判断按键是否被按下
175fb12ce4SGou Ngai 
185fb12ce4SGou Ngai /// 标志状态
195fb12ce4SGou Ngai #[repr(u8)]
205fb12ce4SGou Ngai #[derive(Debug, PartialEq, Eq)]
215fb12ce4SGou Ngai #[allow(dead_code)]
225fb12ce4SGou Ngai pub enum KeyFlag {
235fb12ce4SGou Ngai     NoneFlag = 0 as u8,
245fb12ce4SGou Ngai     PauseBreak = 1 as u8,
255fb12ce4SGou Ngai     PrintScreenPress = 2 as u8,
265fb12ce4SGou Ngai     PrintScreenRelease = 4 as u8,
275fb12ce4SGou Ngai     OtherKey = 8 as u8, // 除了上面两个按键以外的功能按键(不包括下面的第三类按键)
285fb12ce4SGou Ngai }
295fb12ce4SGou Ngai 
305fb12ce4SGou Ngai /// @brief A FSM to parse type one keyboard scan code
315fb12ce4SGou Ngai #[derive(Debug)]
325fb12ce4SGou Ngai #[allow(dead_code)]
335fb12ce4SGou Ngai pub struct TypeOneFSM {
345fb12ce4SGou Ngai     status: ScanCodeStatus,
355fb12ce4SGou Ngai     current_state: TypeOneFSMState,
365fb12ce4SGou Ngai }
375fb12ce4SGou Ngai 
385fb12ce4SGou Ngai impl TypeOneFSM {
395fb12ce4SGou Ngai     #[allow(dead_code)]
40*52da9a59SGnoCiYeH     pub fn new() -> Self {
415fb12ce4SGou Ngai         Self {
425fb12ce4SGou Ngai             status: ScanCodeStatus::new(),
435fb12ce4SGou Ngai             current_state: TypeOneFSMState::Start,
445fb12ce4SGou Ngai         }
455fb12ce4SGou Ngai     }
465fb12ce4SGou Ngai 
475fb12ce4SGou Ngai     /// @brief 解析扫描码
485fb12ce4SGou Ngai     #[allow(dead_code)]
495fb12ce4SGou Ngai     pub fn parse(&mut self, scancode: u8) -> TypeOneFSMState {
50*52da9a59SGnoCiYeH         self.current_state = self.current_state.parse(scancode, &mut self.status);
515fb12ce4SGou Ngai         self.current_state
525fb12ce4SGou Ngai     }
535fb12ce4SGou Ngai }
545fb12ce4SGou Ngai 
555fb12ce4SGou Ngai /// @brief 第一类扫描码状态机的状态
565fb12ce4SGou Ngai #[derive(Debug, Copy, Clone)]
575fb12ce4SGou Ngai pub enum TypeOneFSMState {
585fb12ce4SGou Ngai     /// 起始状态
595fb12ce4SGou Ngai     Start,
605fb12ce4SGou Ngai     /// PauseBreak 第n个扫描码
615fb12ce4SGou Ngai     PauseBreak(u8),
625fb12ce4SGou Ngai     /// 多扫描码功能键起始状态
635fb12ce4SGou Ngai     Func0,
645fb12ce4SGou Ngai     /// 第三类扫描码或字符
655fb12ce4SGou Ngai     Type3,
665fb12ce4SGou Ngai 
675fb12ce4SGou Ngai     PrtscPress(u8),
685fb12ce4SGou Ngai     PrtscRelease(u8),
695fb12ce4SGou Ngai }
705fb12ce4SGou Ngai 
715fb12ce4SGou Ngai impl TypeOneFSMState {
725fb12ce4SGou Ngai     /// @brief 状态机总控程序
73*52da9a59SGnoCiYeH     fn parse(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
745fb12ce4SGou Ngai         // kdebug!("the code is {:#x}\n", scancode);
755fb12ce4SGou Ngai         match self {
765fb12ce4SGou Ngai             TypeOneFSMState::Start => {
77*52da9a59SGnoCiYeH                 return self.handle_start(scancode, scancode_status);
785fb12ce4SGou Ngai             }
795fb12ce4SGou Ngai             TypeOneFSMState::PauseBreak(n) => {
80*52da9a59SGnoCiYeH                 return self.handle_pause_break(*n, scancode_status);
815fb12ce4SGou Ngai             }
825fb12ce4SGou Ngai             TypeOneFSMState::Func0 => {
83*52da9a59SGnoCiYeH                 return self.handle_func0(scancode, scancode_status);
845fb12ce4SGou Ngai             }
855fb12ce4SGou Ngai             TypeOneFSMState::Type3 => {
86*52da9a59SGnoCiYeH                 return self.handle_type3(scancode, scancode_status);
875fb12ce4SGou Ngai             }
88*52da9a59SGnoCiYeH             TypeOneFSMState::PrtscPress(n) => return self.handle_prtsc_press(*n, scancode_status),
895fb12ce4SGou Ngai             TypeOneFSMState::PrtscRelease(n) => {
90*52da9a59SGnoCiYeH                 return self.handle_prtsc_release(*n, scancode_status)
915fb12ce4SGou Ngai             }
925fb12ce4SGou Ngai         }
935fb12ce4SGou Ngai     }
945fb12ce4SGou Ngai 
955fb12ce4SGou Ngai     /// @brief 处理起始状态
96*52da9a59SGnoCiYeH     fn handle_start(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
975fb12ce4SGou Ngai         //kdebug!("in handle_start the code is {:#x}\n",scancode);
985fb12ce4SGou Ngai         match scancode {
995fb12ce4SGou Ngai             0xe1 => {
1005fb12ce4SGou Ngai                 return TypeOneFSMState::PauseBreak(1);
1015fb12ce4SGou Ngai             }
1025fb12ce4SGou Ngai             0xe0 => {
1035fb12ce4SGou Ngai                 return TypeOneFSMState::Func0;
1045fb12ce4SGou Ngai             }
1055fb12ce4SGou Ngai             _ => {
1065fb12ce4SGou Ngai                 //kdebug!("in _d the code is {:#x}\n",scancode);
107*52da9a59SGnoCiYeH                 return TypeOneFSMState::Type3.handle_type3(scancode, scancode_status);
1085fb12ce4SGou Ngai             }
1095fb12ce4SGou Ngai         }
1105fb12ce4SGou Ngai     }
1115fb12ce4SGou Ngai 
1125fb12ce4SGou Ngai     /// @brief 处理PauseBreak状态
1135fb12ce4SGou Ngai     fn handle_pause_break(
1145fb12ce4SGou Ngai         &self,
1155fb12ce4SGou Ngai         scancode: u8,
1165fb12ce4SGou Ngai         scancode_status: &mut ScanCodeStatus,
1175fb12ce4SGou Ngai     ) -> TypeOneFSMState {
1185fb12ce4SGou Ngai         static PAUSE_BREAK_SCAN_CODE: [u8; 6] = [0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5];
1195fb12ce4SGou Ngai         let i = match self {
1205fb12ce4SGou Ngai             TypeOneFSMState::PauseBreak(i) => *i,
1215fb12ce4SGou Ngai             _ => {
122*52da9a59SGnoCiYeH                 return self.handle_type3(scancode, scancode_status);
1235fb12ce4SGou Ngai             }
1245fb12ce4SGou Ngai         };
1255fb12ce4SGou Ngai         if scancode != PAUSE_BREAK_SCAN_CODE[i as usize] {
126*52da9a59SGnoCiYeH             return self.handle_type3(scancode, scancode_status);
1275fb12ce4SGou Ngai         } else {
1285fb12ce4SGou Ngai             if i == 5 {
1295fb12ce4SGou Ngai                 // 所有Pause Break扫描码都被清除
1305fb12ce4SGou Ngai                 return TypeOneFSMState::Start;
1315fb12ce4SGou Ngai             } else {
1325fb12ce4SGou Ngai                 return TypeOneFSMState::PauseBreak(i + 1);
1335fb12ce4SGou Ngai             }
1345fb12ce4SGou Ngai         }
1355fb12ce4SGou Ngai     }
1365fb12ce4SGou Ngai 
137*52da9a59SGnoCiYeH     fn handle_func0(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
1385fb12ce4SGou Ngai         //0xE0
1395fb12ce4SGou Ngai         match scancode {
1405fb12ce4SGou Ngai             0x2a => {
1415fb12ce4SGou Ngai                 return TypeOneFSMState::PrtscPress(2);
1425fb12ce4SGou Ngai             }
1435fb12ce4SGou Ngai             0xb7 => {
1445fb12ce4SGou Ngai                 return TypeOneFSMState::PrtscRelease(2);
1455fb12ce4SGou Ngai             }
1465fb12ce4SGou Ngai             0x1d => {
1475fb12ce4SGou Ngai                 // 按下右边的ctrl
1485fb12ce4SGou Ngai                 scancode_status.ctrl_r = true;
1495fb12ce4SGou Ngai             }
1505fb12ce4SGou Ngai             0x9d => {
1515fb12ce4SGou Ngai                 // 松开右边的ctrl
1525fb12ce4SGou Ngai                 scancode_status.ctrl_r = false;
1535fb12ce4SGou Ngai             }
1545fb12ce4SGou Ngai             0x38 => {
1555fb12ce4SGou Ngai                 // 按下右边的alt
1565fb12ce4SGou Ngai                 scancode_status.alt_r = true;
1575fb12ce4SGou Ngai             }
1585fb12ce4SGou Ngai             0xb8 => {
1595fb12ce4SGou Ngai                 // 松开右边的alt
1605fb12ce4SGou Ngai                 scancode_status.alt_r = false;
1615fb12ce4SGou Ngai             }
1625fb12ce4SGou Ngai             0x5b => {
1635fb12ce4SGou Ngai                 scancode_status.gui_l = true;
1645fb12ce4SGou Ngai             }
1655fb12ce4SGou Ngai             0xdb => {
1665fb12ce4SGou Ngai                 scancode_status.gui_l = false;
1675fb12ce4SGou Ngai             }
1685fb12ce4SGou Ngai             0x5c => {
1695fb12ce4SGou Ngai                 scancode_status.gui_r = true;
1705fb12ce4SGou Ngai             }
1715fb12ce4SGou Ngai             0xdc => {
1725fb12ce4SGou Ngai                 scancode_status.gui_r = false;
1735fb12ce4SGou Ngai             }
1745fb12ce4SGou Ngai             0x5d => {
1755fb12ce4SGou Ngai                 scancode_status.apps = true;
1765fb12ce4SGou Ngai             }
1775fb12ce4SGou Ngai             0xdd => {
1785fb12ce4SGou Ngai                 scancode_status.apps = false;
1795fb12ce4SGou Ngai             }
1805fb12ce4SGou Ngai             0x52 => {
1815fb12ce4SGou Ngai                 scancode_status.insert = true;
1825fb12ce4SGou Ngai             }
1835fb12ce4SGou Ngai             0xd2 => {
1845fb12ce4SGou Ngai                 scancode_status.insert = false;
1855fb12ce4SGou Ngai             }
1865fb12ce4SGou Ngai             0x47 => {
1875fb12ce4SGou Ngai                 scancode_status.home = true;
1885fb12ce4SGou Ngai             }
1895fb12ce4SGou Ngai             0xc7 => {
1905fb12ce4SGou Ngai                 scancode_status.home = false;
1915fb12ce4SGou Ngai             }
1925fb12ce4SGou Ngai             0x49 => {
1935fb12ce4SGou Ngai                 scancode_status.pgup = true;
1945fb12ce4SGou Ngai             }
1955fb12ce4SGou Ngai             0xc9 => {
1965fb12ce4SGou Ngai                 scancode_status.pgup = false;
1975fb12ce4SGou Ngai             }
1985fb12ce4SGou Ngai             0x53 => {
1995fb12ce4SGou Ngai                 scancode_status.del = true;
200*52da9a59SGnoCiYeH                 Self::emit(127);
2015fb12ce4SGou Ngai             }
2025fb12ce4SGou Ngai             0xd3 => {
2035fb12ce4SGou Ngai                 scancode_status.del = false;
2045fb12ce4SGou Ngai             }
2055fb12ce4SGou Ngai             0x4f => {
2065fb12ce4SGou Ngai                 scancode_status.end = true;
2075fb12ce4SGou Ngai             }
2085fb12ce4SGou Ngai             0xcf => {
2095fb12ce4SGou Ngai                 scancode_status.end = false;
2105fb12ce4SGou Ngai             }
2115fb12ce4SGou Ngai             0x51 => {
2125fb12ce4SGou Ngai                 scancode_status.pgdn = true;
2135fb12ce4SGou Ngai             }
2145fb12ce4SGou Ngai             0xd1 => {
2155fb12ce4SGou Ngai                 scancode_status.pgdn = false;
2165fb12ce4SGou Ngai             }
2175fb12ce4SGou Ngai             0x48 => {
2185fb12ce4SGou Ngai                 scancode_status.arrow_u = true;
219*52da9a59SGnoCiYeH                 Self::emit(224);
220*52da9a59SGnoCiYeH                 Self::emit(72);
2215fb12ce4SGou Ngai             }
2225fb12ce4SGou Ngai             0xc8 => {
2235fb12ce4SGou Ngai                 scancode_status.arrow_u = false;
2245fb12ce4SGou Ngai             }
2255fb12ce4SGou Ngai             0x4b => {
2265fb12ce4SGou Ngai                 scancode_status.arrow_l = true;
227*52da9a59SGnoCiYeH                 Self::emit(224);
228*52da9a59SGnoCiYeH                 Self::emit(75);
2295fb12ce4SGou Ngai             }
2305fb12ce4SGou Ngai             0xcb => {
2315fb12ce4SGou Ngai                 scancode_status.arrow_l = false;
2325fb12ce4SGou Ngai             }
2335fb12ce4SGou Ngai             0x50 => {
2345fb12ce4SGou Ngai                 scancode_status.arrow_d = true;
235*52da9a59SGnoCiYeH                 Self::emit(224);
236*52da9a59SGnoCiYeH                 Self::emit(80);
2375fb12ce4SGou Ngai             }
2385fb12ce4SGou Ngai             0xd0 => {
2395fb12ce4SGou Ngai                 scancode_status.arrow_d = false;
2405fb12ce4SGou Ngai             }
2415fb12ce4SGou Ngai             0x4d => {
2425fb12ce4SGou Ngai                 scancode_status.arrow_r = true;
243*52da9a59SGnoCiYeH                 Self::emit(224);
244*52da9a59SGnoCiYeH                 Self::emit(77);
2455fb12ce4SGou Ngai             }
2465fb12ce4SGou Ngai             0xcd => {
2475fb12ce4SGou Ngai                 scancode_status.arrow_r = false;
2485fb12ce4SGou Ngai             }
2495fb12ce4SGou Ngai 
2505fb12ce4SGou Ngai             0x35 => {
2515fb12ce4SGou Ngai                 // 数字小键盘的 / 符号
2525fb12ce4SGou Ngai                 scancode_status.kp_forward_slash = true;
2535fb12ce4SGou Ngai 
2545fb12ce4SGou Ngai                 let ch = '/' as u8;
255*52da9a59SGnoCiYeH                 Self::emit(ch);
2565fb12ce4SGou Ngai             }
2575fb12ce4SGou Ngai             0xb5 => {
2585fb12ce4SGou Ngai                 scancode_status.kp_forward_slash = false;
2595fb12ce4SGou Ngai             }
2605fb12ce4SGou Ngai             0x1c => {
2615fb12ce4SGou Ngai                 scancode_status.kp_enter = true;
262*52da9a59SGnoCiYeH                 Self::emit('\n' as u8);
2635fb12ce4SGou Ngai             }
2645fb12ce4SGou Ngai             0x9c => {
2655fb12ce4SGou Ngai                 scancode_status.kp_enter = false;
2665fb12ce4SGou Ngai             }
2675fb12ce4SGou Ngai             _ => {
2685fb12ce4SGou Ngai                 return TypeOneFSMState::Start;
2695fb12ce4SGou Ngai             }
2705fb12ce4SGou Ngai         }
2715fb12ce4SGou Ngai         return TypeOneFSMState::Start;
2725fb12ce4SGou Ngai     }
2735fb12ce4SGou Ngai 
274*52da9a59SGnoCiYeH     fn handle_type3(&self, scancode: u8, scancode_status: &mut ScanCodeStatus) -> TypeOneFSMState {
2755fb12ce4SGou Ngai         // 判断按键是被按下还是抬起
2765fb12ce4SGou Ngai         let flag_make = if (scancode & (TYPE1_KEYCODE_FLAG_BREAK as u8)) > 0 {
277d7b31a96SGou Ngai             false //up
2785fb12ce4SGou Ngai         } else {
279d7b31a96SGou Ngai             true //down
2805fb12ce4SGou Ngai         };
2815fb12ce4SGou Ngai 
2825fb12ce4SGou Ngai         // 计算扫描码位于码表的第几行
283d7b31a96SGou Ngai         let mut col: bool = false;
2845fb12ce4SGou Ngai         let index = scancode & 0x7f;
2855fb12ce4SGou Ngai 
2865fb12ce4SGou Ngai         //kdebug!("in type3 ch is {:#x}\n",ch);
2875fb12ce4SGou Ngai         let mut key = KeyFlag::OtherKey; // 可视字符
2885fb12ce4SGou Ngai 
2895fb12ce4SGou Ngai         match index {
2905fb12ce4SGou Ngai             0x2a => {
2915fb12ce4SGou Ngai                 scancode_status.shift_l = flag_make;
2925fb12ce4SGou Ngai                 key = KeyFlag::NoneFlag;
2935fb12ce4SGou Ngai             }
2945fb12ce4SGou Ngai             0x36 => {
2955fb12ce4SGou Ngai                 scancode_status.shift_r = flag_make;
2965fb12ce4SGou Ngai                 key = KeyFlag::NoneFlag;
2975fb12ce4SGou Ngai             }
2985fb12ce4SGou Ngai             0x1d => {
2995fb12ce4SGou Ngai                 scancode_status.ctrl_l = flag_make;
3005fb12ce4SGou Ngai                 key = KeyFlag::NoneFlag;
3015fb12ce4SGou Ngai             }
3025fb12ce4SGou Ngai             0x38 => {
303d7b31a96SGou Ngai                 scancode_status.alt_r = flag_make;
304d7b31a96SGou Ngai                 key = KeyFlag::NoneFlag;
305d7b31a96SGou Ngai             }
306d7b31a96SGou Ngai             0x3A => {
307d7b31a96SGou Ngai                 if scancode_status.caps_lock {
308d7b31a96SGou Ngai                     scancode_status.caps_lock = !flag_make;
309d7b31a96SGou Ngai                 }
310d7b31a96SGou Ngai                 //if caps_lock: true, flag_make: true => cap_lock: false
311d7b31a96SGou Ngai                 else {
312d7b31a96SGou Ngai                     scancode_status.caps_lock = flag_make;
313d7b31a96SGou Ngai                 } //else false => cap_lock: true
3145fb12ce4SGou Ngai                 key = KeyFlag::NoneFlag;
3155fb12ce4SGou Ngai             }
3165fb12ce4SGou Ngai             _ => {
3175fb12ce4SGou Ngai                 if flag_make == false {
3185fb12ce4SGou Ngai                     // kdebug!("in type3 ch is {:#x}\n",ch);
3195fb12ce4SGou Ngai                     key = KeyFlag::NoneFlag;
3205fb12ce4SGou Ngai                 }
3215fb12ce4SGou Ngai             }
3225fb12ce4SGou Ngai         }
3235fb12ce4SGou Ngai 
324d7b31a96SGou Ngai         // shift被按下
325d7b31a96SGou Ngai         if scancode_status.shift_l || scancode_status.shift_r {
326d7b31a96SGou Ngai             col = true;
327d7b31a96SGou Ngai         }
328d7b31a96SGou Ngai 
329d7b31a96SGou Ngai         if scancode_status.caps_lock {
330d7b31a96SGou Ngai             if index >= 0x10 && index <= 0x19 {
331d7b31a96SGou Ngai                 col = !col;
332d7b31a96SGou Ngai             } else if index >= 0x1e && index <= 0x26 {
333d7b31a96SGou Ngai                 col = !col;
334d7b31a96SGou Ngai             } else if index >= 0x2c && index <= 0x32 {
335d7b31a96SGou Ngai                 col = !col;
336d7b31a96SGou Ngai             }
337d7b31a96SGou Ngai         }
338d7b31a96SGou Ngai 
339*52da9a59SGnoCiYeH         let mut ch = TYPE1_KEY_CODE_MAPTABLE[col as usize + 2 * index as usize];
3405fb12ce4SGou Ngai         if key != KeyFlag::NoneFlag {
34101bd5258SLoGin             // kdebug!("EMIT: ch is '{}', keyflag is {:?}\n", ch as char, key);
342*52da9a59SGnoCiYeH             if scancode_status.ctrl_l || scancode_status.ctrl_r {
343*52da9a59SGnoCiYeH                 ch = Self::to_ctrl(ch);
344*52da9a59SGnoCiYeH             }
345*52da9a59SGnoCiYeH             Self::emit(ch);
3465fb12ce4SGou Ngai         }
3475fb12ce4SGou Ngai         return TypeOneFSMState::Start;
3485fb12ce4SGou Ngai     }
3495fb12ce4SGou Ngai 
350*52da9a59SGnoCiYeH     #[inline]
351*52da9a59SGnoCiYeH     fn to_ctrl(ch: u8) -> u8 {
352*52da9a59SGnoCiYeH         return match ch as char {
353*52da9a59SGnoCiYeH             'a'..='z' => ch - 0x40,
354*52da9a59SGnoCiYeH             'A'..='Z' => ch - 0x40,
355*52da9a59SGnoCiYeH             '@'..='_' => ch - 0x40,
356*52da9a59SGnoCiYeH             _ => ch,
357*52da9a59SGnoCiYeH         };
358*52da9a59SGnoCiYeH     }
359*52da9a59SGnoCiYeH 
36020e3152eSlogin     #[inline(always)]
361*52da9a59SGnoCiYeH     fn emit(ch: u8) {
36220e3152eSlogin         // 发送到tty
363*52da9a59SGnoCiYeH         let _ = Self::current_port().receive_buf(&[ch], &[], 1);
364*52da9a59SGnoCiYeH     }
365*52da9a59SGnoCiYeH 
366*52da9a59SGnoCiYeH     #[inline]
367*52da9a59SGnoCiYeH     fn current_port() -> Arc<dyn TtyPort> {
368*52da9a59SGnoCiYeH         TTY_PORTS[CURRENT_VCNUM.load(Ordering::SeqCst) as usize].clone()
3695fb12ce4SGou Ngai     }
3705fb12ce4SGou Ngai 
3715fb12ce4SGou Ngai     /// @brief 处理Prtsc按下事件
3725fb12ce4SGou Ngai     fn handle_prtsc_press(
3735fb12ce4SGou Ngai         &self,
3745fb12ce4SGou Ngai         scancode: u8,
3755fb12ce4SGou Ngai         scancode_status: &mut ScanCodeStatus,
3765fb12ce4SGou Ngai     ) -> TypeOneFSMState {
3775fb12ce4SGou Ngai         static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0x2a, 0xe0, 0x37];
3785fb12ce4SGou Ngai         let i = match self {
3795fb12ce4SGou Ngai             TypeOneFSMState::PrtscPress(i) => *i,
3805fb12ce4SGou Ngai             _ => return TypeOneFSMState::Start, // 解析错误,返回起始状态
3815fb12ce4SGou Ngai         };
3825fb12ce4SGou Ngai         if i > 3 {
3835fb12ce4SGou Ngai             // 解析错误,返回起始状态
3845fb12ce4SGou Ngai             return TypeOneFSMState::Start;
3855fb12ce4SGou Ngai         }
3865fb12ce4SGou Ngai         if scancode != PRTSC_SCAN_CODE[i as usize] {
387*52da9a59SGnoCiYeH             return self.handle_type3(scancode, scancode_status);
3885fb12ce4SGou Ngai         } else {
3895fb12ce4SGou Ngai             if i == 3 {
3905fb12ce4SGou Ngai                 // 成功解析出PrtscPress
3915fb12ce4SGou Ngai                 return TypeOneFSMState::Start;
3925fb12ce4SGou Ngai             } else {
3935fb12ce4SGou Ngai                 // 继续解析
3945fb12ce4SGou Ngai                 return TypeOneFSMState::PrtscPress(i + 1);
3955fb12ce4SGou Ngai             }
3965fb12ce4SGou Ngai         }
3975fb12ce4SGou Ngai     }
3985fb12ce4SGou Ngai 
3995fb12ce4SGou Ngai     fn handle_prtsc_release(
4005fb12ce4SGou Ngai         &self,
4015fb12ce4SGou Ngai         scancode: u8,
4025fb12ce4SGou Ngai         scancode_status: &mut ScanCodeStatus,
4035fb12ce4SGou Ngai     ) -> TypeOneFSMState {
4045fb12ce4SGou Ngai         static PRTSC_SCAN_CODE: [u8; 4] = [0xe0, 0xb7, 0xe0, 0xaa];
4055fb12ce4SGou Ngai         let i = match self {
4065fb12ce4SGou Ngai             TypeOneFSMState::PrtscRelease(i) => *i,
4075fb12ce4SGou Ngai             _ => return TypeOneFSMState::Start, // 解析错误,返回起始状态
4085fb12ce4SGou Ngai         };
4095fb12ce4SGou Ngai         if i > 3 {
4105fb12ce4SGou Ngai             // 解析错误,返回起始状态
4115fb12ce4SGou Ngai             return TypeOneFSMState::Start;
4125fb12ce4SGou Ngai         }
4135fb12ce4SGou Ngai         if scancode != PRTSC_SCAN_CODE[i as usize] {
414*52da9a59SGnoCiYeH             return self.handle_type3(scancode, scancode_status);
4155fb12ce4SGou Ngai         } else {
4165fb12ce4SGou Ngai             if i == 3 {
4175fb12ce4SGou Ngai                 // 成功解析出PrtscRelease
4185fb12ce4SGou Ngai                 return TypeOneFSMState::Start;
4195fb12ce4SGou Ngai             } else {
4205fb12ce4SGou Ngai                 // 继续解析
4215fb12ce4SGou Ngai                 return TypeOneFSMState::PrtscRelease(i + 1);
4225fb12ce4SGou Ngai             }
4235fb12ce4SGou Ngai         }
4245fb12ce4SGou Ngai     }
4255fb12ce4SGou Ngai }
4265fb12ce4SGou Ngai 
4275fb12ce4SGou Ngai /// 按键状态
4285fb12ce4SGou Ngai #[derive(Debug)]
429d7b31a96SGou Ngai #[allow(dead_code)]
4305fb12ce4SGou Ngai pub struct ScanCodeStatus {
4315fb12ce4SGou Ngai     // Shift 按键
4325fb12ce4SGou Ngai     shift_l: bool,
4335fb12ce4SGou Ngai     shift_r: bool,
4345fb12ce4SGou Ngai     // Ctrl 按键
4355fb12ce4SGou Ngai     ctrl_l: bool,
4365fb12ce4SGou Ngai     ctrl_r: bool,
4375fb12ce4SGou Ngai     // Alt 按键
4385fb12ce4SGou Ngai     alt_l: bool,
4395fb12ce4SGou Ngai     alt_r: bool,
4405fb12ce4SGou Ngai     //
4415fb12ce4SGou Ngai     gui_l: bool,
4425fb12ce4SGou Ngai     gui_r: bool,
4435fb12ce4SGou Ngai     //
4445fb12ce4SGou Ngai     apps: bool,
4455fb12ce4SGou Ngai     insert: bool,
4465fb12ce4SGou Ngai     // page up/down
4475fb12ce4SGou Ngai     pgup: bool,
4485fb12ce4SGou Ngai     pgdn: bool,
4495fb12ce4SGou Ngai     del: bool,
4505fb12ce4SGou Ngai     home: bool,
4515fb12ce4SGou Ngai     end: bool,
4525fb12ce4SGou Ngai     arrow_u: bool,
4535fb12ce4SGou Ngai     arrow_l: bool,
4545fb12ce4SGou Ngai     arrow_d: bool,
4555fb12ce4SGou Ngai     arrow_r: bool,
4565fb12ce4SGou Ngai     // 斜杠
4575fb12ce4SGou Ngai     kp_forward_slash: bool,
4585fb12ce4SGou Ngai     // 回车
4595fb12ce4SGou Ngai     kp_enter: bool,
460d7b31a96SGou Ngai     caps_lock: bool,
4615fb12ce4SGou Ngai }
4625fb12ce4SGou Ngai 
4635fb12ce4SGou Ngai impl ScanCodeStatus {
4645fb12ce4SGou Ngai     fn new() -> Self {
4655fb12ce4SGou Ngai         ScanCodeStatus {
4665fb12ce4SGou Ngai             shift_l: false,
4675fb12ce4SGou Ngai             shift_r: false,
4685fb12ce4SGou Ngai             ctrl_l: false,
4695fb12ce4SGou Ngai             ctrl_r: false,
4705fb12ce4SGou Ngai             alt_l: false,
4715fb12ce4SGou Ngai             alt_r: false,
4725fb12ce4SGou Ngai             gui_l: false,
4735fb12ce4SGou Ngai             gui_r: false,
4745fb12ce4SGou Ngai             apps: false,
4755fb12ce4SGou Ngai             insert: false,
4765fb12ce4SGou Ngai             pgup: false,
4775fb12ce4SGou Ngai             pgdn: false,
4785fb12ce4SGou Ngai             del: false,
4795fb12ce4SGou Ngai             home: false,
4805fb12ce4SGou Ngai             end: false,
4815fb12ce4SGou Ngai             arrow_u: false,
4825fb12ce4SGou Ngai             arrow_l: false,
4835fb12ce4SGou Ngai             arrow_d: false,
4845fb12ce4SGou Ngai             arrow_r: false,
4855fb12ce4SGou Ngai             kp_forward_slash: false,
4865fb12ce4SGou Ngai             kp_enter: false,
487d7b31a96SGou Ngai             caps_lock: false,
4885fb12ce4SGou Ngai         }
4895fb12ce4SGou Ngai     }
4905fb12ce4SGou Ngai }
4915fb12ce4SGou Ngai 
4925fb12ce4SGou Ngai const TYPE1_KEY_CODE_MAPTABLE: [u8; 256] = [
4935fb12ce4SGou Ngai     /*0x00*/ 0, 0, /*0x01*/ 0, 0, // ESC
4945fb12ce4SGou Ngai     /*0x02*/ '1' as u8, '!' as u8, /*0x03*/ '2' as u8, '@' as u8,
4955fb12ce4SGou Ngai     /*0x04*/ '3' as u8, '#' as u8, /*0x05*/ '4' as u8, '$' as u8,
4965fb12ce4SGou Ngai     /*0x06*/ '5' as u8, '%' as u8, /*0x07*/ '6' as u8, '^' as u8,
4975fb12ce4SGou Ngai     /*0x08*/ '7' as u8, '&' as u8, /*0x09*/ '8' as u8, '*' as u8,
4985fb12ce4SGou Ngai     /*0x0a*/ '9' as u8, '(' as u8, /*0x0b*/ '0' as u8, ')' as u8,
4995fb12ce4SGou Ngai     /*0x0c*/ '-' as u8, '_' as u8, /*0x0d*/ '=' as u8, '+' as u8,
50020e3152eSlogin     /*0x0e  \b */ 8 as u8, 8 as u8, // BACKSPACE
5015fb12ce4SGou Ngai     /*0x0f*/ '\t' as u8, '\t' as u8, // TAB
502d7b31a96SGou Ngai     ////////////////////////character///////////////////////////
503d7b31a96SGou Ngai     /*0x10*/ 'q' as u8,
504d7b31a96SGou Ngai     'Q' as u8, /*0x11*/ 'w' as u8, 'W' as u8, /*0x12*/ 'e' as u8, 'E' as u8,
505d7b31a96SGou Ngai     /*0x13*/ 'r' as u8, 'R' as u8, /*0x14*/ 't' as u8, 'T' as u8,
506d7b31a96SGou Ngai     /*0x15*/ 'y' as u8, 'Y' as u8, /*0x16*/ 'u' as u8, 'U' as u8,
507d7b31a96SGou Ngai     /*0x17*/ 'i' as u8, 'I' as u8, /*0x18*/ 'o' as u8, 'O' as u8,
508d7b31a96SGou Ngai     /*0x19*/ 'p' as u8, 'P' as u8,
509d7b31a96SGou Ngai     ////////////////////////character///////////////////////////
510d7b31a96SGou Ngai 
511d7b31a96SGou Ngai     /*0x1a*/ '[' as u8,
512d7b31a96SGou Ngai     '{' as u8, /*0x1b*/ ']' as u8, '}' as u8, /*0x1c*/ '\n' as u8,
513d7b31a96SGou Ngai     '\n' as u8, // ENTER
5145fb12ce4SGou Ngai     /*0x1d*/ 0x1d, 0x1d, // CTRL Left
515d7b31a96SGou Ngai     ////////////////////////character///////////////////////////
516d7b31a96SGou Ngai     /*0x1e*/ 'a' as u8,
517d7b31a96SGou Ngai     'A' as u8, /*0x1f*/ 's' as u8, 'S' as u8, /*0x20*/ 'd' as u8, 'D' as u8,
518d7b31a96SGou Ngai     /*0x21*/ 'f' as u8, 'F' as u8, /*0x22*/ 'g' as u8, 'G' as u8,
519d7b31a96SGou Ngai     /*0x23*/ 'h' as u8, 'H' as u8, /*0x24*/ 'j' as u8, 'J' as u8,
520d7b31a96SGou Ngai     /*0x25*/ 'k' as u8, 'K' as u8, /*0x26*/ 'l' as u8, 'L' as u8,
521d7b31a96SGou Ngai     ////////////////////////character///////////////////////////
522d7b31a96SGou Ngai 
523d7b31a96SGou Ngai     /*0x27*/ ';' as u8,
524d7b31a96SGou Ngai     ':' as u8, /*0x28*/ '\'' as u8, '"' as u8, /*0x29*/ '`' as u8, '~' as u8,
525d7b31a96SGou Ngai     /*0x2a*/ 0x2a, 0x2a, // SHIFT Left
526d7b31a96SGou Ngai     /*0x2b*/ '\\' as u8, '|' as u8,
527d7b31a96SGou Ngai     ////////////////////////character///////////////////////////
528d7b31a96SGou Ngai     /*0x2c*/ 'z' as u8,
529d7b31a96SGou Ngai     'Z' as u8, /*0x2d*/ 'x' as u8, 'X' as u8, /*0x2e*/ 'c' as u8, 'C' as u8,
5305fb12ce4SGou Ngai     /*0x2f*/ 'v' as u8, 'V' as u8, /*0x30*/ 'b' as u8, 'B' as u8,
5315fb12ce4SGou Ngai     /*0x31*/ 'n' as u8, 'N' as u8, /*0x32*/ 'm' as u8, 'M' as u8,
532d7b31a96SGou Ngai     ////////////////////////character///////////////////////////
533d7b31a96SGou Ngai 
534d7b31a96SGou Ngai     /*0x33*/ ',' as u8,
535d7b31a96SGou Ngai     '<' as u8, /*0x34*/ '.' as u8, '>' as u8, /*0x35*/ '/' as u8, '?' as u8,
536d7b31a96SGou Ngai     /*0x36*/ 0x36, 0x36, // SHIFT Right
5375fb12ce4SGou Ngai     /*0x37*/ '*' as u8, '*' as u8, /*0x38*/ 0x38, 0x38, // ALT Left
5385fb12ce4SGou Ngai     /*0x39*/ ' ' as u8, ' ' as u8, /*0x3a*/ 0, 0, // CAPS LOCK
5395fb12ce4SGou Ngai     /*0x3b*/ 0, 0, // F1
5405fb12ce4SGou Ngai     /*0x3c*/ 0, 0, // F2
5415fb12ce4SGou Ngai     /*0x3d*/ 0, 0, // F3
5425fb12ce4SGou Ngai     /*0x3e*/ 0, 0, // F4
5435fb12ce4SGou Ngai     /*0x3f*/ 0, 0, // F5
5445fb12ce4SGou Ngai     /*0x40*/ 0, 0, // F6
5455fb12ce4SGou Ngai     /*0x41*/ 0, 0, // F7
5465fb12ce4SGou Ngai     /*0x42*/ 0, 0, // F8
5475fb12ce4SGou Ngai     /*0x43*/ 0, 0, // F9
5485fb12ce4SGou Ngai     /*0x44*/ 0, 0, // F10
5495fb12ce4SGou Ngai     /*0x45*/ 0, 0, // NUM LOCK
5505fb12ce4SGou Ngai     /*0x46*/ 0, 0, // SCROLL LOCK
5515fb12ce4SGou Ngai     /*0x47*/ '7' as u8, 0, /*PAD HONE*/
5525fb12ce4SGou Ngai     /*0x48*/ '8' as u8, 0, /*PAD UP*/
5535fb12ce4SGou Ngai     /*0x49*/ '9' as u8, 0, /*PAD PAGEUP*/
5545fb12ce4SGou Ngai     /*0x4a*/ '-' as u8, 0, /*PAD MINUS*/
5555fb12ce4SGou Ngai     /*0x4b*/ '4' as u8, 0, /*PAD LEFT*/
5565fb12ce4SGou Ngai     /*0x4c*/ '5' as u8, 0, /*PAD MID*/
5575fb12ce4SGou Ngai     /*0x4d*/ '6' as u8, 0, /*PAD RIGHT*/
5585fb12ce4SGou Ngai     /*0x4e*/ '+' as u8, 0, /*PAD PLUS*/
5595fb12ce4SGou Ngai     /*0x4f*/ '1' as u8, 0, /*PAD END*/
5605fb12ce4SGou Ngai     /*0x50*/ '2' as u8, 0, /*PAD DOWN*/
5615fb12ce4SGou Ngai     /*0x51*/ '3' as u8, 0, /*PAD PAGEDOWN*/
5625fb12ce4SGou Ngai     /*0x52*/ '0' as u8, 0, /*PAD INS*/
5635fb12ce4SGou Ngai     /*0x53*/ '.' as u8, 0, /*PAD DOT*/
5645fb12ce4SGou Ngai     /*0x54*/ 0, 0, /*0x55*/ 0, 0, /*0x56*/ 0, 0, /*0x57*/ 0, 0, // F11
5655fb12ce4SGou Ngai     /*0x58*/ 0, 0, // F12
5665fb12ce4SGou Ngai     /*0x59*/ 0, 0, /*0x5a*/ 0, 0, /*0x5b*/ 0, 0, /*0x5c*/ 0, 0,
5675fb12ce4SGou Ngai     /*0x5d*/ 0, 0, /*0x5e*/ 0, 0, /*0x5f*/ 0, 0, /*0x60*/ 0, 0,
5685fb12ce4SGou Ngai     /*0x61*/ 0, 0, /*0x62*/ 0, 0, /*0x63*/ 0, 0, /*0x64*/ 0, 0,
5695fb12ce4SGou Ngai     /*0x65*/ 0, 0, /*0x66*/ 0, 0, /*0x67*/ 0, 0, /*0x68*/ 0, 0,
5705fb12ce4SGou Ngai     /*0x69*/ 0, 0, /*0x6a*/ 0, 0, /*0x6b*/ 0, 0, /*0x6c*/ 0, 0,
5715fb12ce4SGou Ngai     /*0x6d*/ 0, 0, /*0x6e*/ 0, 0, /*0x6f*/ 0, 0, /*0x70*/ 0, 0,
5725fb12ce4SGou Ngai     /*0x71*/ 0, 0, /*0x72*/ 0, 0, /*0x73*/ 0, 0, /*0x74*/ 0, 0,
5735fb12ce4SGou Ngai     /*0x75*/ 0, 0, /*0x76*/ 0, 0, /*0x77*/ 0, 0, /*0x78*/ 0, 0,
5745fb12ce4SGou Ngai     /*0x79*/ 0, 0, /*0x7a*/ 0, 0, /*0x7b*/ 0, 0, /*0x7c*/ 0, 0,
5755fb12ce4SGou Ngai     /*0x7d*/ 0, 0, /*0x7e*/ 0, 0, /*0x7f*/ 0, 0,
5765fb12ce4SGou Ngai ];
577