xref: /DragonOS/kernel/src/driver/keyboard/ps2_keyboard.rs (revision 7b0ef10895108a0de5ff5ef3d2f93f40cf2e33a5)
1 use core::hint::spin_loop;
2 
3 use alloc::{
4     string::ToString,
5     sync::{Arc, Weak},
6 };
7 
8 use unified_init::macros::unified_init;
9 
10 use crate::{
11     arch::{io::PortIOArch, CurrentIrqArch, CurrentPortIOArch},
12     driver::{
13         base::device::device_number::{DeviceNumber, Major},
14         input::ps2_dev::Ps2StatusRegister,
15     },
16     exception::{
17         irqdata::IrqHandlerData,
18         irqdesc::{IrqHandleFlags, IrqHandler, IrqReturn},
19         manage::irq_manager,
20         InterruptArch, IrqNumber,
21     },
22     filesystem::{
23         devfs::{devfs_register, DevFS, DeviceINode},
24         vfs::{
25             core::generate_inode_id, file::FileMode, syscall::ModeType, FilePrivateData,
26             FileSystem, FileType, IndexNode, Metadata,
27         },
28     },
29     init::initcall::INITCALL_DEVICE,
30     libs::{
31         keyboard_parser::TypeOneFSM,
32         rwlock::RwLock,
33         spinlock::{SpinLock, SpinLockGuard},
34     },
35     time::PosixTimeSpec,
36 };
37 use system_error::SystemError;
38 
39 /// PS2键盘的中断向量号
40 const PS2_KEYBOARD_INTR_VECTOR: IrqNumber = IrqNumber::new(0x21);
41 
42 const PORT_PS2_KEYBOARD_DATA: u8 = 0x60;
43 const PORT_PS2_KEYBOARD_STATUS: u8 = 0x64;
44 const PORT_PS2_KEYBOARD_CONTROL: u8 = 0x64;
45 
46 /// 向键盘发送配置命令
47 const PS2_KEYBOARD_COMMAND_WRITE: u8 = 0x60;
48 
49 /// 读取键盘的配置值
50 #[allow(dead_code)]
51 const PS2_KEYBOARD_COMMAND_READ: u8 = 0x20;
52 /// 初始化键盘控制器的配置值
53 const PS2_KEYBOARD_PARAM_INIT: u8 = 0x47;
54 
55 #[derive(Debug)]
56 pub struct LockedPS2KeyBoardInode(RwLock<PS2KeyBoardInode>);
57 
58 lazy_static! {
59     static ref PS2_KEYBOARD_FSM: SpinLock<TypeOneFSM> = SpinLock::new(TypeOneFSM::new());
60 }
61 
62 #[derive(Debug)]
63 pub struct PS2KeyBoardInode {
64     /// uuid 暂时不知道有什么用(x
65     // uuid: Uuid,
66     /// 指向自身的弱引用
67     self_ref: Weak<LockedPS2KeyBoardInode>,
68     /// 指向inode所在的文件系统对象的指针
69     fs: Weak<DevFS>,
70     /// INode 元数据
71     metadata: Metadata,
72 }
73 
74 impl LockedPS2KeyBoardInode {
75     pub fn new() -> Arc<Self> {
76         let inode = PS2KeyBoardInode {
77             // uuid: Uuid::new_v5(),
78             self_ref: Weak::default(),
79             fs: Weak::default(),
80             metadata: Metadata {
81                 dev_id: 1,
82                 inode_id: generate_inode_id(),
83                 size: 0,
84                 blk_size: 0,
85                 blocks: 0,
86                 atime: PosixTimeSpec::default(),
87                 mtime: PosixTimeSpec::default(),
88                 ctime: PosixTimeSpec::default(),
89                 file_type: FileType::CharDevice, // 文件夹,block设备,char设备
90                 mode: ModeType::from_bits_truncate(0o666),
91                 nlinks: 1,
92                 uid: 0,
93                 gid: 0,
94                 raw_dev: DeviceNumber::new(Major::INPUT_MAJOR, 0), // 这里用来作为device number
95             },
96         };
97 
98         let result = Arc::new(LockedPS2KeyBoardInode(RwLock::new(inode)));
99         result.0.write().self_ref = Arc::downgrade(&result);
100 
101         return result;
102     }
103 }
104 
105 impl DeviceINode for LockedPS2KeyBoardInode {
106     fn set_fs(&self, fs: Weak<DevFS>) {
107         self.0.write().fs = fs;
108     }
109 }
110 
111 fn ps2_keyboard_register() {
112     devfs_register("ps2_keyboard", LockedPS2KeyBoardInode::new())
113         .expect("Failed to register ps/2 keyboard");
114 }
115 
116 impl IndexNode for LockedPS2KeyBoardInode {
117     fn read_at(
118         &self,
119         _offset: usize,
120         _len: usize,
121         _buf: &mut [u8],
122         _data: SpinLockGuard<FilePrivateData>,
123     ) -> Result<usize, SystemError> {
124         return Err(SystemError::ENOSYS);
125     }
126 
127     fn write_at(
128         &self,
129         _offset: usize,
130         _len: usize,
131         _buf: &[u8],
132         _data: SpinLockGuard<FilePrivateData>,
133     ) -> Result<usize, SystemError> {
134         return Err(SystemError::ENOSYS);
135     }
136 
137     fn open(
138         &self,
139         _data: SpinLockGuard<FilePrivateData>,
140         _mode: &FileMode,
141     ) -> Result<(), SystemError> {
142         return Ok(());
143     }
144 
145     fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> {
146         return Ok(());
147     }
148 
149     fn metadata(&self) -> Result<Metadata, SystemError> {
150         return Ok(self.0.read().metadata.clone());
151     }
152 
153     fn set_metadata(&self, metadata: &Metadata) -> Result<(), SystemError> {
154         let mut inode = self.0.write();
155         inode.metadata.atime = metadata.atime;
156         inode.metadata.mtime = metadata.mtime;
157         inode.metadata.ctime = metadata.ctime;
158         inode.metadata.mode = metadata.mode;
159         inode.metadata.uid = metadata.uid;
160         inode.metadata.gid = metadata.gid;
161 
162         return Ok(());
163     }
164 
165     fn fs(&self) -> alloc::sync::Arc<dyn FileSystem> {
166         return self.0.read().fs.upgrade().unwrap();
167     }
168 
169     fn as_any_ref(&self) -> &dyn core::any::Any {
170         self
171     }
172 
173     fn list(&self) -> Result<alloc::vec::Vec<alloc::string::String>, SystemError> {
174         return Err(SystemError::ENOSYS);
175     }
176 }
177 
178 #[derive(Debug)]
179 struct Ps2KeyboardIrqHandler;
180 
181 impl IrqHandler for Ps2KeyboardIrqHandler {
182     fn handle(
183         &self,
184         _irq: IrqNumber,
185         _static_data: Option<&dyn IrqHandlerData>,
186         _dev_id: Option<Arc<dyn IrqHandlerData>>,
187     ) -> Result<IrqReturn, SystemError> {
188         // 先检查状态寄存器,看看是否有数据
189         let mut fsm = PS2_KEYBOARD_FSM.lock();
190         let mut handled = false;
191         loop {
192             let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) };
193             let status = Ps2StatusRegister::from(status);
194             if status.outbuf_full() {
195                 let input = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) };
196                 fsm.parse(input);
197                 handled = true;
198             } else {
199                 break;
200             }
201         }
202         if handled {
203             Ok(IrqReturn::Handled)
204         } else {
205             Ok(IrqReturn::NotHandled)
206         }
207     }
208 }
209 
210 impl Ps2KeyboardIrqHandler {
211     const INTR_HANDLE_FLAGS: IrqHandleFlags =
212         IrqHandleFlags::from_bits_truncate(IrqHandleFlags::IRQF_TRIGGER_RISING.bits());
213 }
214 
215 /// 等待 PS/2 键盘的输入缓冲区为空
216 fn wait_ps2_keyboard_write() {
217     let mut status: Ps2StatusRegister;
218     loop {
219         status = Ps2StatusRegister::from(unsafe {
220             CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into())
221         });
222         if !status.inbuf_full() {
223             break;
224         }
225 
226         spin_loop();
227     }
228 }
229 
230 fn force_clear_input_buffer() {
231     loop {
232         let status = unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_STATUS.into()) };
233         let status = Ps2StatusRegister::from(status);
234         if status.outbuf_full() {
235             unsafe { CurrentPortIOArch::in8(PORT_PS2_KEYBOARD_DATA.into()) };
236         } else {
237             break;
238         }
239     }
240 }
241 
242 #[unified_init(INITCALL_DEVICE)]
243 fn ps2_keyboard_init() -> Result<(), SystemError> {
244     let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
245 
246     // 先读一下键盘的数据,防止由于在键盘初始化之前,由于按键被按下从而导致接收不到中断。
247     // 清空键盘缓冲区
248     force_clear_input_buffer();
249 
250     // ======== 初始化键盘控制器,写入配置值 =========
251     wait_ps2_keyboard_write();
252     unsafe {
253         CurrentPortIOArch::out8(PORT_PS2_KEYBOARD_CONTROL.into(), PS2_KEYBOARD_COMMAND_WRITE);
254         wait_ps2_keyboard_write();
255         CurrentPortIOArch::out8(PORT_PS2_KEYBOARD_DATA.into(), PS2_KEYBOARD_PARAM_INIT);
256         wait_ps2_keyboard_write();
257     }
258 
259     // 执行一百万次nop,等待键盘控制器把命令执行完毕
260     for _ in 0..1000000 {
261         spin_loop();
262     }
263 
264     irq_manager()
265         .request_irq(
266             PS2_KEYBOARD_INTR_VECTOR,
267             "ps2keyboard".to_string(),
268             &Ps2KeyboardIrqHandler,
269             Ps2KeyboardIrqHandler::INTR_HANDLE_FLAGS,
270             None,
271         )
272         .expect("Failed to request irq for ps2 keyboard");
273 
274     // 清空键盘缓冲区
275     force_clear_input_buffer();
276     drop(irq_guard);
277 
278     // 将设备挂载到devfs
279     ps2_keyboard_register();
280 
281     Ok(())
282 }
283