kernel/devices/keyboard_mouse/
mouse.rs1use super::ps2::Ps2;
2
3use blinkcast::alloc::{Receiver as BlinkcastReceiver, Sender as BlinkcastSender};
4use kernel_user_link::mouse::{MouseEvent, ScrollType};
5use tracing::warn;
6
7#[allow(dead_code)]
8pub mod scaling {
9 pub const PER_SEC_10: u8 = 10;
10 pub const PER_SEC_20: u8 = 20;
11 pub const PER_SEC_40: u8 = 40;
12 pub const PER_SEC_60: u8 = 60;
13 pub const PER_SEC_80: u8 = 80;
14 pub const PER_SEC_100: u8 = 100;
15 pub const PER_SEC_200: u8 = 200;
16}
17
18#[allow(dead_code)]
19pub mod resolution {
20 pub const PIXEL_PER_MM_1: u8 = 0;
21 pub const PIXEL_PER_MM_2: u8 = 1;
22 pub const PIXEL_PER_MM_4: u8 = 2;
23 pub const PIXEL_PER_MM_8: u8 = 3;
24}
25
26#[allow(dead_code)]
27mod commands {
28 pub const MOUSE_PREFIX: u8 = 0xD4;
29
30 pub const MOUSE_RESET: u8 = 0xFF;
31 pub const MOUSE_ENABLE_STREAMING: u8 = 0xF4;
32 pub const MOUSE_DISABLE_STREAMING: u8 = 0xF5;
33 pub const MOUSE_SET_DEFAULTS: u8 = 0xF6;
34 pub const MOUSE_SET_SAMPLE_RATE: u8 = 0xF3;
35 pub const MOUSE_GET_DEVICE_ID: u8 = 0xF2;
36 pub const MOUSE_REQUEST_SINGLE_PACKET: u8 = 0xEB;
37 pub const MOUSE_STATUS_REQUEST: u8 = 0xE9;
38
39 pub const SYSTEM_RESET: u8 = 0xFE;
40}
41
42mod packet {
43 pub const Y_OVERFLOW: u8 = 1 << 7;
44 pub const X_OVERFLOW: u8 = 1 << 6;
45 pub const Y_SIGN: u8 = 1 << 5;
46 pub const X_SIGN: u8 = 1 << 4;
47}
48
49const MOUSE_BUFFER_SIZE: usize = 1024;
51
52pub const MOUSE_INT_NUM: u8 = 12;
54
55pub type MouseReader = BlinkcastReceiver<MouseEvent>;
56
57pub struct Mouse {
58 ps2: Ps2,
59 has_extra_byte: bool,
60 sender: BlinkcastSender<MouseEvent>,
61}
62
63#[allow(dead_code)]
64impl Mouse {
65 pub fn new(ps2: Ps2) -> Mouse {
66 let mut device = Mouse {
67 ps2,
68 has_extra_byte: false,
69 sender: BlinkcastSender::new(MOUSE_BUFFER_SIZE),
70 };
71
72 device.reset();
74 let mut mouse_id = device.get_id();
75 device.write_command(commands::MOUSE_SET_DEFAULTS, None);
76 device.write_command(commands::MOUSE_ENABLE_STREAMING, None);
77
78 if mouse_id != 3 {
80 device.write_command(commands::MOUSE_SET_SAMPLE_RATE, Some(scaling::PER_SEC_200));
81 device.write_command(commands::MOUSE_SET_SAMPLE_RATE, Some(scaling::PER_SEC_100));
82 device.write_command(commands::MOUSE_SET_SAMPLE_RATE, Some(scaling::PER_SEC_80));
83 mouse_id = device.get_id();
84 }
85
86 if mouse_id == 3 {
88 device.write_command(commands::MOUSE_SET_SAMPLE_RATE, Some(scaling::PER_SEC_200));
89 device.write_command(commands::MOUSE_SET_SAMPLE_RATE, Some(scaling::PER_SEC_200));
90 device.write_command(commands::MOUSE_SET_SAMPLE_RATE, Some(scaling::PER_SEC_80));
91 mouse_id = device.get_id();
92 }
93
94 if mouse_id == 3 || mouse_id == 4 {
95 device.has_extra_byte = true;
96 }
97
98 device
99 }
100
101 pub fn new_receiver(&self) -> MouseReader {
102 self.sender.new_receiver()
103 }
104
105 pub fn handle_mouse_data(&self) {
106 let mut data = [0; 4];
107 let read_len = if self.has_extra_byte { 4 } else { 3 };
108 for d in data.iter_mut().take(read_len) {
109 *d = self.ps2.read_data();
110 }
111
112 if data[0] & packet::X_OVERFLOW != 0 || data[0] & packet::Y_OVERFLOW != 0 {
113 return;
115 }
116
117 let buttons = data[0] & 0b111 | ((data[3] >> 4) & 0b11) << 3;
119 let mut x = data[1] as u16;
120 let mut y = data[2] as u16;
121
122 if data[0] & packet::X_SIGN != 0 {
123 x |= 0xFF00;
124 }
125 if data[0] & packet::Y_SIGN != 0 {
126 y |= 0xFF00;
127 }
128
129 let x = x as i16;
130 let y = y as i16;
131
132 let scroll_type = match data[3] & 0b1111 {
133 1 => ScrollType::VerticalUp,
134 0xF => ScrollType::VerticalDown,
135 2 => ScrollType::HorizontalRight,
136 0xE => ScrollType::HorizontalNegative,
137 _ => ScrollType::None,
138 };
139
140 let event = MouseEvent {
141 x,
142 y,
143 buttons,
144 scroll_type,
145 };
146
147 self.sender.send(event);
148 }
149
150 fn reset(&self) {
151 self.ps2.write_prefix(commands::MOUSE_PREFIX);
152 self.ps2.write_command_data(commands::MOUSE_RESET).unwrap();
153 loop {
154 let data = self.ps2.wait_read_data();
155 if data != 0xAA && data != 0xFA {
156 panic!("failed to reset mouse: {:#X}", data);
157 }
158 if data == 0xAA {
159 break;
160 }
161 }
162 }
163
164 fn write_command(&self, command: u8, extra: Option<u8>) {
165 self.ps2.write_prefix(commands::MOUSE_PREFIX);
166 self.ps2.write_command_data(command).unwrap();
167
168 if let Some(extra) = extra {
169 self.ps2.write_prefix(commands::MOUSE_PREFIX);
170 if self.ps2.write_command_data(extra).is_none() {
171 warn!("command {:#X} extra {:#X} failed", command, extra);
172 }
173 }
174 }
175
176 fn get_id(&self) -> u8 {
177 self.write_command(commands::MOUSE_GET_DEVICE_ID, None);
178 self.ps2.wait_read_data()
179 }
180
181 #[allow(dead_code)]
182 fn get_status(&self) -> [u8; 3] {
183 self.write_command(commands::MOUSE_STATUS_REQUEST, None);
184 let mut status = [0; 3];
185 self.ps2.wait_read_data_slice(&mut status);
186 status
187 }
188}