strat9_kernel/arch/x86_64/
keyboard_us.rs1use super::io::inb;
7use spin::Mutex;
8
9const KEYBOARD_DATA_PORT: u16 = 0x60;
11
12pub struct KeyboardState {
14 pub left_shift: bool,
16 pub right_shift: bool,
18 pub caps_lock: bool,
20 pub ctrl: bool,
22 pub alt: bool,
24}
25
26impl KeyboardState {
27 pub const fn new() -> Self {
29 Self {
30 left_shift: false,
31 right_shift: false,
32 caps_lock: false,
33 ctrl: false,
34 alt: false,
35 }
36 }
37
38 pub fn shift_active(&self) -> bool {
40 self.left_shift || self.right_shift
41 }
42}
43
44pub static KEYBOARD: Mutex<KeyboardState> = Mutex::new(KeyboardState::new());
46
47static SCANCODE_TO_ASCII: [u8; 128] = {
49 let mut table = [0u8; 128];
50 table[0x01] = 0x1B; table[0x02] = b'1';
53 table[0x03] = b'2';
54 table[0x04] = b'3';
55 table[0x05] = b'4';
56 table[0x06] = b'5';
57 table[0x07] = b'6';
58 table[0x08] = b'7';
59 table[0x09] = b'8';
60 table[0x0A] = b'9';
61 table[0x0B] = b'0';
62 table[0x0C] = b'-';
63 table[0x0D] = b'=';
64 table[0x0E] = 0x08; table[0x0F] = b'\t';
67 table[0x10] = b'q';
68 table[0x11] = b'w';
69 table[0x12] = b'e';
70 table[0x13] = b'r';
71 table[0x14] = b't';
72 table[0x15] = b'y';
73 table[0x16] = b'u';
74 table[0x17] = b'i';
75 table[0x18] = b'o';
76 table[0x19] = b'p';
77 table[0x1A] = b'[';
78 table[0x1B] = b']';
79 table[0x1C] = b'\n'; table[0x1E] = b'a';
82 table[0x1F] = b's';
83 table[0x20] = b'd';
84 table[0x21] = b'f';
85 table[0x22] = b'g';
86 table[0x23] = b'h';
87 table[0x24] = b'j';
88 table[0x25] = b'k';
89 table[0x26] = b'l';
90 table[0x27] = b';';
91 table[0x28] = b'\'';
92 table[0x29] = b'`';
93 table[0x2B] = b'\\';
95 table[0x2C] = b'z';
96 table[0x2D] = b'x';
97 table[0x2E] = b'c';
98 table[0x2F] = b'v';
99 table[0x30] = b'b';
100 table[0x31] = b'n';
101 table[0x32] = b'm';
102 table[0x33] = b',';
103 table[0x34] = b'.';
104 table[0x35] = b'/';
105 table[0x39] = b' ';
107 table
108};
109
110static SCANCODE_TO_ASCII_SHIFT: [u8; 128] = {
112 let mut table = [0u8; 128];
113 table[0x01] = 0x1B;
114 table[0x02] = b'!';
115 table[0x03] = b'@';
116 table[0x04] = b'#';
117 table[0x05] = b'$';
118 table[0x06] = b'%';
119 table[0x07] = b'^';
120 table[0x08] = b'&';
121 table[0x09] = b'*';
122 table[0x0A] = b'(';
123 table[0x0B] = b')';
124 table[0x0C] = b'_';
125 table[0x0D] = b'+';
126 table[0x0E] = 0x08;
127 table[0x0F] = b'\t';
128 table[0x10] = b'Q';
129 table[0x11] = b'W';
130 table[0x12] = b'E';
131 table[0x13] = b'R';
132 table[0x14] = b'T';
133 table[0x15] = b'Y';
134 table[0x16] = b'U';
135 table[0x17] = b'I';
136 table[0x18] = b'O';
137 table[0x19] = b'P';
138 table[0x1A] = b'{';
139 table[0x1B] = b'}';
140 table[0x1C] = b'\n';
141 table[0x1E] = b'A';
142 table[0x1F] = b'S';
143 table[0x20] = b'D';
144 table[0x21] = b'F';
145 table[0x22] = b'G';
146 table[0x23] = b'H';
147 table[0x24] = b'J';
148 table[0x25] = b'K';
149 table[0x26] = b'L';
150 table[0x27] = b':';
151 table[0x28] = b'"';
152 table[0x29] = b'~';
153 table[0x2B] = b'|';
154 table[0x2C] = b'Z';
155 table[0x2D] = b'X';
156 table[0x2E] = b'C';
157 table[0x2F] = b'V';
158 table[0x30] = b'B';
159 table[0x31] = b'N';
160 table[0x32] = b'M';
161 table[0x33] = b'<';
162 table[0x34] = b'>';
163 table[0x35] = b'?';
164 table[0x39] = b' ';
165 table
166};
167
168pub fn handle_scancode() -> Option<u8> {
173 let scancode = unsafe { inb(KEYBOARD_DATA_PORT) };
174 handle_scancode_raw(scancode)
175}
176
177pub fn handle_scancode_raw(scancode: u8) -> Option<u8> {
179 let mut kbd = KEYBOARD.lock();
180
181 if scancode & 0x80 != 0 {
183 let released = scancode & 0x7F;
184 match released {
185 0x2A => kbd.left_shift = false,
186 0x36 => kbd.right_shift = false,
187 0x1D => kbd.ctrl = false,
188 0x38 => kbd.alt = false,
189 _ => {}
190 }
191 return None;
192 }
193
194 match scancode {
196 0x2A => {
197 kbd.left_shift = true;
198 return None;
199 }
200 0x36 => {
201 kbd.right_shift = true;
202 return None;
203 }
204 0x1D => {
205 kbd.ctrl = true;
206 return None;
207 }
208 0x38 => {
209 kbd.alt = true;
210 return None;
211 }
212 0x3A => {
213 kbd.caps_lock = !kbd.caps_lock;
214 return None;
215 }
216 _ => {}
217 }
218
219 if scancode < 128 {
221 let shift = kbd.shift_active();
222 let ch = if shift {
223 SCANCODE_TO_ASCII_SHIFT[scancode as usize]
224 } else {
225 SCANCODE_TO_ASCII[scancode as usize]
226 };
227
228 if kbd.caps_lock && ch.is_ascii_alphabetic() {
230 let ch = if shift {
231 ch.to_ascii_lowercase()
232 } else {
233 ch.to_ascii_uppercase()
234 };
235 if ch != 0 {
236 return Some(ch);
237 }
238 }
239
240 if ch != 0 {
241 return Some(ch);
242 }
243 }
244
245 None
246}