1#![no_std]
4#![warn(missing_docs)]
5#![feature(const_fn_fn_ptr_basics)]
6
7use bitflags::bitflags;
8use x86_64::instructions::port::Port;
9
10const ADDRESS_PORT_ADDRESS: u16 = 0x64;
11const DATA_PORT_ADDRESS: u16 = 0x60;
12const GET_STATUS_BYTE: u8 = 0x20;
13const SET_STATUS_BYTE: u8 = 0x60;
14
15bitflags! {
16 #[derive(Default)]
18 pub struct MouseFlags: u8 {
19 const LEFT_BUTTON = 0b0000_0001;
21
22 const RIGHT_BUTTON = 0b0000_0010;
24
25 const MIDDLE_BUTTON = 0b0000_0100;
27
28 const ALWAYS_ONE = 0b0000_1000;
30
31 const X_SIGN = 0b0001_0000;
33
34 const Y_SIGN = 0b0010_0000;
36
37 const X_OVERFLOW = 0b0100_0000;
39
40 const Y_OVERFLOW = 0b1000_0000;
42 }
43}
44
45#[repr(u8)]
46enum Command {
47 EnablePacketStreaming = 0xF4,
48 SetDefaults = 0xF6,
49}
50
51#[derive(Debug)]
53pub struct Mouse {
54 command_port: Port<u8>,
55 data_port: Port<u8>,
56 current_packet: u8,
57 current_state: MouseState,
58 completed_state: MouseState,
59 on_complete: Option<fn(MouseState)>,
60}
61
62impl Default for Mouse {
63 fn default() -> Mouse {
64 Mouse::new()
65 }
66}
67
68#[derive(Debug, Copy, Clone, Default)]
70pub struct MouseState {
71 flags: MouseFlags,
72 x: i16,
73 y: i16,
74}
75
76impl MouseState {
77 pub const fn new() -> MouseState {
79 MouseState {
80 flags: MouseFlags::empty(),
81 x: 0,
82 y: 0,
83 }
84 }
85
86 pub fn left_button_down(&self) -> bool {
88 self.flags.contains(MouseFlags::LEFT_BUTTON)
89 }
90
91 pub fn left_button_up(&self) -> bool {
93 !self.flags.contains(MouseFlags::LEFT_BUTTON)
94 }
95
96 pub fn right_button_down(&self) -> bool {
98 self.flags.contains(MouseFlags::RIGHT_BUTTON)
99 }
100
101 pub fn right_button_up(&self) -> bool {
103 !self.flags.contains(MouseFlags::RIGHT_BUTTON)
104 }
105
106 pub fn x_moved(&self) -> bool {
108 self.x != 0
109 }
110
111 pub fn y_moved(&self) -> bool {
113 self.y != 0
114 }
115
116 pub fn moved(&self) -> bool {
118 self.x_moved() || self.y_moved()
119 }
120
121 pub fn get_x(&self) -> i16 {
123 self.x
124 }
125
126 pub fn get_y(&self) -> i16 {
128 self.y
129 }
130}
131
132impl Mouse {
133 pub const fn new() -> Mouse {
135 Mouse {
136 command_port: Port::new(ADDRESS_PORT_ADDRESS),
137 data_port: Port::new(DATA_PORT_ADDRESS),
138 current_packet: 0,
139 current_state: MouseState::new(),
140 completed_state: MouseState::new(),
141 on_complete: None,
142 }
143 }
144
145 pub fn get_state(&self) -> MouseState {
147 self.completed_state
148 }
149
150 pub fn init(&mut self) -> Result<(), &'static str> {
153 self.write_command_port(GET_STATUS_BYTE)?;
154 let status = self.read_data_port()? | 0x02;
155 self.write_command_port(SET_STATUS_BYTE)?;
156 self.write_data_port(status & 0xDF)?;
157 self.send_command(Command::SetDefaults)?;
158 self.send_command(Command::EnablePacketStreaming)?;
159 Ok(())
160 }
161
162 pub fn process_packet(&mut self, packet: u8) {
164 match self.current_packet {
165 0 => {
166 let flags = MouseFlags::from_bits_truncate(packet);
167 if !flags.contains(MouseFlags::ALWAYS_ONE) {
168 return;
169 }
170 self.current_state.flags = flags;
171 }
172 1 => self.process_x_movement(packet),
173 2 => {
174 self.process_y_movement(packet);
175 self.completed_state = self.current_state;
176 if let Some(on_complete) = self.on_complete {
177 on_complete(self.completed_state);
178 }
179 }
180 _ => unreachable!(),
181 }
182 self.current_packet = (self.current_packet + 1) % 3;
183 }
184
185 pub fn set_on_complete(&mut self, handler: fn(MouseState)) {
187 self.on_complete = Some(handler);
188 }
189
190 fn process_x_movement(&mut self, packet: u8) {
191 if !self.current_state.flags.contains(MouseFlags::X_OVERFLOW) {
192 self.current_state.x = if self.current_state.flags.contains(MouseFlags::X_SIGN) {
193 self.sign_extend(packet)
194 } else {
195 packet as i16
196 };
197 }
198 }
199
200 fn process_y_movement(&mut self, packet: u8) {
201 if !self.current_state.flags.contains(MouseFlags::Y_OVERFLOW) {
202 self.current_state.y = if self.current_state.flags.contains(MouseFlags::Y_SIGN) {
203 self.sign_extend(packet)
204 } else {
205 packet as i16
206 };
207 }
208 }
209
210 fn read_data_port(&mut self) -> Result<u8, &'static str> {
211 self.wait_for_read()?;
212 Ok(unsafe { self.data_port.read() })
213 }
214
215 fn send_command(&mut self, command: Command) -> Result<(), &'static str> {
216 self.write_command_port(0xD4)?;
217 self.write_data_port(command as u8)?;
218 if self.read_data_port()? != 0xFA {
219 return Err("mouse did not respond to the command");
220 }
221 Ok(())
222 }
223
224 fn sign_extend(&self, packet: u8) -> i16 {
225 ((packet as u16) | 0xFF00) as i16
226 }
227
228 fn write_command_port(&mut self, value: u8) -> Result<(), &'static str> {
229 self.wait_for_write()?;
230 unsafe {
231 self.command_port.write(value);
232 }
233 Ok(())
234 }
235
236 fn write_data_port(&mut self, value: u8) -> Result<(), &'static str> {
237 self.wait_for_write()?;
238 unsafe {
239 self.data_port.write(value);
240 }
241 Ok(())
242 }
243
244 fn wait_for_read(&mut self) -> Result<(), &'static str> {
245 let timeout = 100_000;
246 for _ in 0..timeout {
247 let value = unsafe { self.command_port.read() };
248 if (value & 0x1) == 0x1 {
249 return Ok(());
250 }
251 }
252 Err("wait for mouse read timeout")
253 }
254
255 fn wait_for_write(&mut self) -> Result<(), &'static str> {
256 let timeout = 100_000;
257 for _ in 0..timeout {
258 let value = unsafe { self.command_port.read() };
259 if (value & 0x2) == 0x0 {
260 return Ok(());
261 }
262 }
263 Err("wait for mouse write timeout")
264 }
265}
266
267#[cfg(test)]
268mod test {
269 use super::*;
270
271 const EMPTY_PACKET: u8 = 0;
272 const VALID_PACKET: u8 = MouseFlags::ALWAYS_ONE.bits();
273 const NEGATIVE_PACKET: u8 =
274 MouseFlags::ALWAYS_ONE.bits() | MouseFlags::X_SIGN.bits() | MouseFlags::Y_SIGN.bits();
275 const NEGATIVE_PACKET_WITH_OVERFLOW: u8 = MouseFlags::ALWAYS_ONE.bits()
276 | MouseFlags::X_SIGN.bits()
277 | MouseFlags::Y_SIGN.bits()
278 | MouseFlags::X_OVERFLOW.bits()
279 | MouseFlags::Y_OVERFLOW.bits();
280 const LEFT_MOUSE_BUTTON_DOWN_PACKET: u8 =
281 MouseFlags::ALWAYS_ONE.bits() | MouseFlags::LEFT_BUTTON.bits();
282 const RIGHT_MOUSE_BUTTON_DOWN_PACKET: u8 =
283 MouseFlags::ALWAYS_ONE.bits() | MouseFlags::RIGHT_BUTTON.bits();
284 const POSITIVE_X_PACKET: u8 = 0x5;
285 const POSITIVE_Y_PACKET: u8 = 0x8;
286 const NEGATIVE_X_PACKET: u8 = 0xD8;
287 const NEGATIVE_Y_PACKET: u8 = 0xD9;
288
289 #[test]
290 fn process_packets() {
291 let mut mouse = Mouse::new();
292
293 mouse.process_packet(VALID_PACKET);
294 assert_eq!(mouse.current_packet, 1);
295
296 mouse.process_packet(EMPTY_PACKET);
297 assert_eq!(mouse.current_packet, 2);
298
299 mouse.process_packet(EMPTY_PACKET);
300 assert_eq!(mouse.current_packet, 0);
301
302 let mouse_state = mouse.completed_state;
303 assert_eq!(mouse_state.flags, MouseFlags::ALWAYS_ONE);
304 assert_eq!(mouse_state.x, 0);
305 assert_eq!(mouse_state.y, 0);
306 }
307
308 #[test]
309 fn always_one_bit_not_set() {
310 let mut mouse = Mouse::new();
311 mouse.process_packet(EMPTY_PACKET);
312 assert_eq!(mouse.current_packet, 0);
313 }
314
315 #[test]
316 fn positive_movement() {
317 let mut mouse = Mouse::new();
318 mouse.process_packet(VALID_PACKET);
319 mouse.process_packet(POSITIVE_X_PACKET);
320 mouse.process_packet(POSITIVE_Y_PACKET);
321
322 let mouse_state = mouse.completed_state;
323 assert_eq!(mouse_state.x, POSITIVE_X_PACKET as i16);
324 assert_eq!(mouse_state.y, POSITIVE_Y_PACKET as i16);
325 }
326
327 #[test]
328 fn negative_movement() {
329 let mut mouse = Mouse::new();
330 mouse.process_packet(NEGATIVE_PACKET);
331 mouse.process_packet(NEGATIVE_X_PACKET);
332 mouse.process_packet(NEGATIVE_Y_PACKET);
333
334 let mouse_state = mouse.get_state();
335 assert_eq!(mouse_state.x, -40);
336 assert_eq!(mouse_state.y, -39);
337 }
338
339 #[test]
340 fn discard_overflow() {
341 let mut mouse = Mouse::new();
342 mouse.process_packet(VALID_PACKET);
343 mouse.process_packet(POSITIVE_X_PACKET);
344 mouse.process_packet(POSITIVE_Y_PACKET);
345
346 mouse.process_packet(NEGATIVE_PACKET_WITH_OVERFLOW);
347 mouse.process_packet(NEGATIVE_X_PACKET);
348 mouse.process_packet(NEGATIVE_Y_PACKET);
349
350 let mouse_state = mouse.completed_state;
351 assert_eq!(mouse_state.x, POSITIVE_X_PACKET as i16);
352 assert_eq!(mouse_state.y, POSITIVE_Y_PACKET as i16);
353 }
354
355 #[test]
356 fn left_mouse_button_down() {
357 let mut mouse = Mouse::new();
358 mouse.process_packet(LEFT_MOUSE_BUTTON_DOWN_PACKET);
359 assert_eq!(mouse.current_state.left_button_down(), true);
360 }
361
362 #[test]
363 fn left_mouse_button_up() {
364 let mut mouse = Mouse::new();
365 mouse.process_packet(VALID_PACKET);
366 assert_eq!(mouse.current_state.left_button_up(), true);
367 }
368
369 #[test]
370 fn right_mouse_button_down() {
371 let mut mouse = Mouse::new();
372 mouse.process_packet(RIGHT_MOUSE_BUTTON_DOWN_PACKET);
373 assert_eq!(mouse.current_state.right_button_down(), true);
374 }
375
376 #[test]
377 fn right_mouse_button_up() {
378 let mut mouse = Mouse::new();
379 mouse.process_packet(VALID_PACKET);
380 assert_eq!(mouse.current_state.right_button_up(), true);
381 }
382}