kernel/devices/keyboard_mouse/
keyboard.rs1use core::sync::atomic::{AtomicU8, Ordering};
2
3use blinkcast::alloc::{Receiver as BlinkcastReceiver, Sender as BlinkcastSender};
4use kernel_user_link::keyboard::{modifier, Key, KeyType};
5
6use super::ps2::Ps2;
7
8const KEYBOARD_BUFFER_SIZE: usize = 256;
11
12const KEY_PRESSED: u8 = 1 << 7;
13
14pub const KEYBOARD_INT_NUM: u8 = 1;
16
17pub type KeyboardReader = BlinkcastReceiver<Key>;
18
19pub struct Keyboard {
20 active_modifiers: AtomicU8,
21 active_toggles: AtomicU8,
22 ps2: Ps2,
23
24 sender: BlinkcastSender<Key>,
25}
26
27impl Keyboard {
28 pub fn new(ps2: Ps2) -> Keyboard {
29 let sender = BlinkcastSender::new(KEYBOARD_BUFFER_SIZE);
30 Keyboard {
31 active_modifiers: AtomicU8::new(0),
32 active_toggles: AtomicU8::new(0),
33 ps2,
34 sender,
35 }
36 }
37
38 pub fn new_receiver(&self) -> KeyboardReader {
39 self.sender.new_receiver()
40 }
41
42 fn modifiers(&self) -> u8 {
43 let modifiers_only = self.active_modifiers.load(Ordering::Relaxed)
45 & !(modifier::CAPS_LOCK | modifier::NUM_LOCK | modifier::SCROLL_LOCK);
46
47 modifiers_only | self.active_toggles.load(Ordering::Relaxed)
48 }
49
50 pub fn handle_keyboard_data(&self) {
51 if !self.ps2.has_data() {
52 return;
53 }
54
55 let data = self.ps2.read_data();
56
57 if data == 0xE0 {
58 let data = self.ps2.read_data();
60 let pressed = data & KEY_PRESSED == 0;
61 let Some(key) = key_type_from_device(data | 0x80) else {
62 return;
64 };
65
66 self.sender.send(Key {
67 pressed,
68 modifiers: self.modifiers(),
69 key_type: key,
70 });
71 }
72
73 let pressed = data & KEY_PRESSED == 0;
74 let data = data & !KEY_PRESSED; if let Some(modifier_key) = get_modifier(data) {
76 if pressed {
77 self.active_modifiers
78 .fetch_or(modifier_key, Ordering::Relaxed);
79 } else {
80 self.active_modifiers
81 .fetch_and(!modifier_key, Ordering::Relaxed);
82 }
83 } else if let Some(toggle_key) = get_toggle(data) {
84 let should_toggle =
86 pressed && self.active_modifiers.load(Ordering::Relaxed) & toggle_key == 0;
87 if should_toggle {
88 self.active_toggles.fetch_xor(toggle_key, Ordering::Relaxed);
89 }
90
91 if pressed {
93 self.active_modifiers
94 .fetch_or(toggle_key, Ordering::Relaxed);
95 } else {
96 self.active_modifiers
97 .fetch_and(!toggle_key, Ordering::Relaxed);
98 }
99 }
100 let Some(key_type) = key_type_from_device(data) else {
102 return;
104 };
105
106 self.sender.send(Key {
107 pressed,
108 modifiers: self.modifiers(),
109 key_type,
110 })
111 }
112}
113
114fn key_type_from_device(value: u8) -> Option<KeyType> {
116 if value & 0x80 == 0 {
117 if value <= KeyType::F12 as u8 {
118 let k = unsafe { core::mem::transmute::<u8, KeyType>(value) };
122 if k == KeyType::_None1
123 || k == KeyType::_None2
124 || k == KeyType::_None3
125 || k == KeyType::_None4
126 {
127 return None;
128 }
129
130 Some(k)
131 } else {
132 None
134 }
135 } else {
136 let key = value & !0x80;
138
139 match key {
141 0x10 => Some(KeyType::MultimediaPreviousTrack),
142 0x19 => Some(KeyType::MultimediaNextTrack),
143 0x1C => Some(KeyType::KeypadEnter),
144 0x1D => Some(KeyType::RightCtrl),
145 0x20 => Some(KeyType::MultimediaMute),
146 0x21 => Some(KeyType::Calculator),
147 0x22 => Some(KeyType::MultimediaPlayPause),
148 0x24 => Some(KeyType::MultimediaStop),
149 0x2E => Some(KeyType::VolumeDown),
150 0x30 => Some(KeyType::VolumeUp),
151 0x32 => Some(KeyType::WWWHome),
152 0x35 => Some(KeyType::KeypadSlash),
153 0x38 => Some(KeyType::RightAlt),
154 0x47 => Some(KeyType::Home),
155 0x48 => Some(KeyType::UpArrow),
156 0x49 => Some(KeyType::PageUp),
157 0x4B => Some(KeyType::LeftArrow),
158 0x4D => Some(KeyType::RightArrow),
159 0x4F => Some(KeyType::End),
160 0x50 => Some(KeyType::DownArrow),
161 0x51 => Some(KeyType::PageDown),
162 0x52 => Some(KeyType::Insert),
163 0x53 => Some(KeyType::Delete),
164 0x5B => Some(KeyType::LeftGUI),
165 0x5C => Some(KeyType::RightGUI),
166 0x5D => Some(KeyType::Application),
167 0x5E => Some(KeyType::Power),
168 0x5F => Some(KeyType::Sleep),
169 0x63 => Some(KeyType::Wake),
170 0x65 => Some(KeyType::WWWSearch),
171 0x66 => Some(KeyType::WWWFavorites),
172 0x67 => Some(KeyType::WWWRefresh),
173 0x68 => Some(KeyType::WWWStop),
174 0x69 => Some(KeyType::WWWForward),
175 0x6A => Some(KeyType::WWWBack),
176 0x6B => Some(KeyType::MyComputer),
177 0x6C => Some(KeyType::Email),
178 0x6D => Some(KeyType::MultimediaSelect),
179 _ => None,
180 }
181 }
182}
183
184const fn get_modifier(key: u8) -> Option<u8> {
185 match key {
186 0x2A => Some(modifier::SHIFT),
187 0x36 => Some(modifier::SHIFT),
188 0x1D => Some(modifier::CTRL),
189 0x38 => Some(modifier::ALT),
190 _ => None,
191 }
192}
193
194const fn get_toggle(key: u8) -> Option<u8> {
195 match key {
196 0x3A => Some(modifier::CAPS_LOCK),
197 0x45 => Some(modifier::NUM_LOCK),
198 0x46 => Some(modifier::SCROLL_LOCK),
199 _ => None,
200 }
201}