strat9_kernel/vfs/
input_scheme.rs1use crate::syscall::error::SyscallError;
13use alloc::{string::String, vec, vec::Vec};
14use core::sync::atomic::{AtomicU64, Ordering};
15
16use super::scheme::{
17 finalize_pseudo_stat, DirEntry, FileFlags, FileStat, OpenFlags, OpenResult, Scheme, DEV_INPUT,
18};
19
20static NEXT_ID: AtomicU64 = AtomicU64::new(1);
21
22const KBD_FILE_ID: u64 = 1;
24const MOUSE_FILE_ID: u64 = 2;
25
26pub struct InputScheme;
27
28impl InputScheme {
29 pub fn new() -> Self {
30 InputScheme
31 }
32}
33
34impl Scheme for InputScheme {
35 fn open(&self, path: &str, _flags: OpenFlags) -> Result<OpenResult, SyscallError> {
36 let file_id = match path {
37 "kbd" | "keyboard" => KBD_FILE_ID,
38 "mouse" => MOUSE_FILE_ID,
39 "" | "/" => {
40 return Ok(OpenResult {
41 file_id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
42 size: None,
43 flags: FileFlags::DIRECTORY,
44 });
45 }
46 _ => return Err(SyscallError::NotFound),
47 };
48
49 Ok(OpenResult {
50 file_id,
51 size: None,
52 flags: FileFlags::DEVICE,
53 })
54 }
55
56 fn read(&self, file_id: u64, _offset: u64, buf: &mut [u8]) -> Result<usize, SyscallError> {
61 match file_id {
62 KBD_FILE_ID => {
63 let mut count = 0;
64 for slot in buf.iter_mut() {
65 match crate::arch::x86_64::keyboard::read_char() {
66 Some(ch) => {
67 *slot = ch;
68 count += 1;
69 }
70 None => break,
71 }
72 }
73 Ok(count)
74 }
75 MOUSE_FILE_ID => {
76 let mut count = 0;
78 while count + 7 <= buf.len() {
79 match crate::arch::x86_64::mouse::read_event() {
80 Some(ev) => {
81 buf[count] = ev.dx as u8;
82 buf[count + 1] = (ev.dx >> 8) as u8;
83 buf[count + 2] = ev.dy as u8;
84 buf[count + 3] = (ev.dy >> 8) as u8;
85 buf[count + 4] = ev.dz as u8;
86 buf[count + 5] = (ev.left as u8)
87 | ((ev.right as u8) << 1)
88 | ((ev.middle as u8) << 2);
89 buf[count + 6] = 0; count += 7;
91 }
92 None => break,
93 }
94 }
95 Ok(count)
96 }
97 _ => Err(SyscallError::BadHandle),
98 }
99 }
100
101 fn write(&self, _file_id: u64, _offset: u64, _buf: &[u8]) -> Result<usize, SyscallError> {
102 Err(SyscallError::PermissionDenied) }
104
105 fn close(&self, _file_id: u64) -> Result<(), SyscallError> {
106 Ok(())
107 }
108
109 fn stat(&self, file_id: u64) -> Result<FileStat, SyscallError> {
110 let (mode, size) = match file_id {
111 KBD_FILE_ID => (0o020000 | 0o444, 0u64), MOUSE_FILE_ID => (0o020000 | 0o444, 0u64),
113 _ => (0o040555, 0u64), };
115 Ok(finalize_pseudo_stat(
116 FileStat {
117 st_ino: file_id,
118 st_mode: mode,
119 st_nlink: 1,
120 st_size: size,
121 st_blksize: 1,
122 st_blocks: 0,
123 ..FileStat::zeroed()
124 },
125 DEV_INPUT,
126 0,
127 ))
128 }
129
130 fn readdir(&self, file_id: u64) -> Result<Vec<DirEntry>, SyscallError> {
131 if file_id != 0 {
132 return Err(SyscallError::InvalidArgument);
133 }
134 Ok(vec![
135 DirEntry {
136 ino: KBD_FILE_ID,
137 file_type: super::scheme::DT_CHR,
138 name: String::from("kbd"),
139 },
140 DirEntry {
141 ino: MOUSE_FILE_ID,
142 file_type: super::scheme::DT_CHR,
143 name: String::from("mouse"),
144 },
145 ])
146 }
147}