good_os_framework/drivers/
mouse.rs

1use bitflags::bitflags;
2use spin::{Lazy, Mutex};
3use x86_64::instructions::port::Port;
4
5const PORT_READ_TRY_TIMES: u16 = 10_000;
6
7pub static MOUSE: Lazy<Mutex<Mouse>> = Lazy::new(|| Mutex::new(Mouse::new()));
8
9pub fn init() {
10    let mut mouse = MOUSE.lock();
11    match mouse.init() {
12        Ok(_) => {
13            mouse.set_complete_handler(mouse_complete_handler);
14            log::debug!("Mouse Type: {:?}", mouse.mouse_type);
15            log::info!("Mouse initialized successfully!");
16        }
17        Err(err) => log::error!("Failed to initialize mouse: {}", err),
18    }
19}
20
21fn mouse_complete_handler(_mouse_state: MouseState) {
22    //crate::println!("{:?}", mouse_state);
23}
24
25bitflags! {
26    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
27    struct MouseFlags: u8 {
28        const LEFT_BUTTON = 0b0000_0001;
29        const RIGHT_BUTTON = 0b0000_0010;
30        const MIDDLE_BUTTON = 0b0000_0100;
31        const ALWAYS_ONE = 0b0000_1000;
32        const X_SIGN = 0b0001_0000;
33        const Y_SIGN = 0b0010_0000;
34        const X_OVERFLOW = 0b0100_0000;
35        const Y_OVERFLOW = 0b1000_0000;
36    }
37}
38
39#[derive(Debug, Copy, Clone)]
40enum MouseAdditionalFlags {
41    FirstButton = 0b0100_0001,
42    SecondButton = 0b0111_1111,
43    ScrollUp = 0b0000_0001,
44    ScrollDown = 0b0000_1111,
45    None,
46}
47
48#[derive(Debug)]
49enum MouseType {
50    Standard,
51    OnlyScroll,
52    FiveButton,
53}
54
55#[derive(Debug)]
56pub struct Mouse {
57    command_port: Port<u8>,
58    data_port: Port<u8>,
59    current_packet_index: u16,
60    current_state: MouseState,
61    mouse_type: MouseType,
62    complete_handler: Option<fn(MouseState)>,
63}
64
65#[derive(Debug, Copy, Clone)]
66pub struct MouseState {
67    flags: MouseFlags,
68    additional_flags: MouseAdditionalFlags,
69    move_x: i16,
70    move_y: i16,
71}
72
73impl MouseState {
74    pub const fn new() -> MouseState {
75        MouseState {
76            flags: MouseFlags::empty(),
77            additional_flags: MouseAdditionalFlags::None,
78            move_x: 0,
79            move_y: 0,
80        }
81    }
82}
83
84impl Mouse {
85    pub const fn new() -> Mouse {
86        Mouse {
87            command_port: Port::new(0x64),
88            data_port: Port::new(0x60),
89            current_packet_index: 0,
90            current_state: MouseState::new(),
91            mouse_type: MouseType::Standard,
92            complete_handler: None,
93        }
94    }
95
96    pub fn init(&mut self) -> Result<(), &'static str> {
97        unsafe {
98            self.enable_packet_streaming()?
99                .enable_scroll_wheel()?
100                .enable_additional_button()?;
101        }
102        Ok(())
103    }
104
105    pub fn process_packet(&mut self, packet: u8) {
106        let modulo = match self.mouse_type {
107            MouseType::Standard => 3,
108            _ => 4,
109        };
110        match self.current_packet_index % modulo {
111            0 => {
112                let flags = MouseFlags::from_bits_truncate(packet);
113                if !flags.contains(MouseFlags::ALWAYS_ONE) {
114                    return;
115                }
116                self.current_state.flags = flags;
117            }
118            1 => {
119                if !self.current_state.flags.contains(MouseFlags::X_OVERFLOW) {
120                    self.current_state.move_x = packet as i16;
121                    if self.current_state.flags.contains(MouseFlags::X_SIGN) {
122                        self.current_state.move_x = ((packet as u16) | 0xFF00) as i16;
123                    }
124                }
125            }
126            2 => {
127                if !self.current_state.flags.contains(MouseFlags::Y_OVERFLOW) {
128                    self.current_state.move_y = packet as i16;
129                    if self.current_state.flags.contains(MouseFlags::Y_SIGN) {
130                        self.current_state.move_y = ((packet as u16) | 0xFF00) as i16;
131                    }
132                }
133            }
134            3 => {
135                self.current_state.additional_flags = match packet {
136                    0b0100_0001 => MouseAdditionalFlags::FirstButton,
137                    0b0111_1111 => MouseAdditionalFlags::SecondButton,
138                    0b0000_0001 => MouseAdditionalFlags::ScrollUp,
139                    // First is for OnlyScroll and second is for FiveButton
140                    0b1111_1111 => MouseAdditionalFlags::ScrollDown,
141                    0b0000_1111 => MouseAdditionalFlags::ScrollDown,
142                    _ => MouseAdditionalFlags::None,
143                };
144            }
145            _ => unreachable!(),
146        }
147        if self.current_packet_index % modulo == modulo - 1 {
148            if self.complete_handler.is_some() {
149                (self.complete_handler.unwrap())(self.current_state);
150            }
151        }
152        self.current_packet_index += 1;
153        self.current_packet_index %= modulo;
154    }
155
156    pub fn set_complete_handler(&mut self, handler: fn(MouseState)) {
157        self.complete_handler = Some(handler);
158    }
159
160    unsafe fn enable_packet_streaming(&mut self) -> Result<&mut Self, &'static str> {
161        Ok(self.send_command(0xf4 as u8)?)
162    }
163
164    unsafe fn enable_scroll_wheel(&mut self) -> Result<&mut Self, &'static str> {
165        self.send_command(0xf3)?.send_command(200)?;
166        self.send_command(0xf3)?.send_command(100)?;
167        self.send_command(0xf3)?.send_command(80)?;
168        self.send_command(0xf2 as u8)?;
169        if self.read_data_port()? == 0x3 {
170            self.mouse_type = MouseType::OnlyScroll;
171        }
172        Ok(self)
173    }
174
175    unsafe fn enable_additional_button(&mut self) -> Result<&mut Self, &'static str> {
176        self.send_command(0xf3)?.send_command(200)?;
177        self.send_command(0xf3)?.send_command(200)?;
178        self.send_command(0xf3)?.send_command(80)?;
179        self.send_command(0xf2 as u8)?;
180        if self.read_data_port()? == 0x4 {
181            self.mouse_type = MouseType::FiveButton;
182        }
183        Ok(self)
184    }
185
186    unsafe fn send_command(&mut self, command: u8) -> Result<&mut Self, &'static str> {
187        self.write_command_port(0xd4)?;
188        self.write_data_port(command)?;
189        for _ in 0..PORT_READ_TRY_TIMES {
190            if self.read_data_port()? == 0xfa {
191                return Ok(self);
192            }
193        }
194        Err("Did not receive ack response from mouse!")
195    }
196
197    unsafe fn read_data_port(&mut self) -> Result<u8, &'static str> {
198        self.wait_for_read()?;
199        Ok(self.data_port.read())
200    }
201
202    unsafe fn write_command_port(&mut self, value: u8) -> Result<(), &'static str> {
203        self.wait_for_write()?;
204        Ok(self.command_port.write(value))
205    }
206
207    unsafe fn write_data_port(&mut self, value: u8) -> Result<(), &'static str> {
208        self.wait_for_write()?;
209        Ok(self.data_port.write(value))
210    }
211
212    unsafe fn wait_for_read(&mut self) -> Result<(), &'static str> {
213        for _ in 0..PORT_READ_TRY_TIMES {
214            if self.command_port.read() & 0x1 == 1 {
215                return Ok(());
216            }
217        }
218        Err("Tried too many times to wait command port to be ready to read!")
219    }
220
221    unsafe fn wait_for_write(&mut self) -> Result<(), &'static str> {
222        for _ in 0..PORT_READ_TRY_TIMES {
223            if self.command_port.read() & 0x2 == 0 {
224                return Ok(());
225            }
226        }
227        Err("Tried too many times to wait command port to be ready to write!")
228    }
229}