kernel/devices/keyboard_mouse/
mouse.rs

1use 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
49/// Number of events that can be buffered before being overwritten
50const MOUSE_BUFFER_SIZE: usize = 1024;
51
52// PS/2 mouse interrupt
53pub 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        // enable the mouse
73        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        // magic to transition to mouse id 3
79        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        // magic to transition to mouse id 4
87        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            // overflow, ignore the data
114            return;
115        }
116
117        // combine the data for the main buttons plus the 4th/5th if available
118        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}