Browse Source

Kernel: Detect 5-button PS/2 mouse if present :^)

The detection works very similarly to how we detect a mouse wheel, just
another magical sequence of "set sample rate" requests to the mouse
followed by an ID check.
Andreas Kling 5 years ago
parent
commit
c5882d3a18
3 changed files with 47 additions and 19 deletions
  1. 42 19
      Kernel/Devices/PS2MouseDevice.cpp
  2. 3 0
      Kernel/Devices/PS2MouseDevice.h
  3. 2 0
      Kernel/MousePacket.h

+ 42 - 19
Kernel/Devices/PS2MouseDevice.cpp

@@ -52,6 +52,7 @@ namespace Kernel {
 #define PS2MOUSE_RESET 0xFF
 #define PS2MOUSE_RESET 0xFF
 
 
 #define PS2MOUSE_INTELLIMOUSE_ID 0x03
 #define PS2MOUSE_INTELLIMOUSE_ID 0x03
+#define PS2MOUSE_INTELLIMOUSE_EXPLORER_ID 0x04
 
 
 //#define PS2MOUSE_DEBUG
 //#define PS2MOUSE_DEBUG
 
 
@@ -151,6 +152,14 @@ void PS2MouseDevice::parse_data_packet()
     packet.y = y;
     packet.y = y;
     packet.z = z;
     packet.z = z;
     packet.buttons = m_data[0] & 0x07;
     packet.buttons = m_data[0] & 0x07;
+
+    if (m_has_five_buttons) {
+        if (m_data[3] & 0x10)
+            packet.buttons |= MousePacket::BackButton;
+        if (m_data[3] & 0x20)
+            packet.buttons |= MousePacket::ForwardButton;
+    }
+
     packet.is_relative = true;
     packet.is_relative = true;
 #ifdef PS2MOUSE_DEBUG
 #ifdef PS2MOUSE_DEBUG
     dbg() << "PS2 Relative Mouse: Buttons " << String::format("%x", packet.buttons);
     dbg() << "PS2 Relative Mouse: Buttons " << String::format("%x", packet.buttons);
@@ -201,6 +210,21 @@ void PS2MouseDevice::check_device_presence()
     }
     }
 }
 }
 
 
+u8 PS2MouseDevice::get_device_id()
+{
+    mouse_write(PS2MOUSE_GET_DEVICE_ID);
+    expect_ack();
+    return mouse_read();
+}
+
+void PS2MouseDevice::set_sample_rate(u8 rate)
+{
+    mouse_write(PS2MOUSE_SET_SAMPLE_RATE);
+    expect_ack();
+    mouse_write(rate);
+    expect_ack();
+}
+
 void PS2MouseDevice::initialize_device()
 void PS2MouseDevice::initialize_device()
 {
 {
     if (!m_device_present)
     if (!m_device_present)
@@ -223,28 +247,14 @@ void PS2MouseDevice::initialize_device()
     mouse_write(PS2MOUSE_ENABLE_PACKET_STREAMING);
     mouse_write(PS2MOUSE_ENABLE_PACKET_STREAMING);
     expect_ack();
     expect_ack();
 
 
-    mouse_write(PS2MOUSE_GET_DEVICE_ID);
-    expect_ack();
-    u8 device_id = mouse_read();
+    u8 device_id = get_device_id();
 
 
     if (device_id != PS2MOUSE_INTELLIMOUSE_ID) {
     if (device_id != PS2MOUSE_INTELLIMOUSE_ID) {
         // Send magical wheel initiation sequence.
         // Send magical wheel initiation sequence.
-        mouse_write(PS2MOUSE_SET_SAMPLE_RATE);
-        expect_ack();
-        mouse_write(200);
-        expect_ack();
-        mouse_write(PS2MOUSE_SET_SAMPLE_RATE);
-        expect_ack();
-        mouse_write(100);
-        expect_ack();
-        mouse_write(PS2MOUSE_SET_SAMPLE_RATE);
-        expect_ack();
-        mouse_write(80);
-        expect_ack();
-
-        mouse_write(PS2MOUSE_GET_DEVICE_ID);
-        expect_ack();
-        device_id = mouse_read();
+        set_sample_rate(200);
+        set_sample_rate(100);
+        set_sample_rate(80);
+        device_id = get_device_id();
     }
     }
 
 
     if (device_id == PS2MOUSE_INTELLIMOUSE_ID) {
     if (device_id == PS2MOUSE_INTELLIMOUSE_ID) {
@@ -254,6 +264,19 @@ void PS2MouseDevice::initialize_device()
         klog() << "PS2MouseDevice: No mouse wheel detected!";
         klog() << "PS2MouseDevice: No mouse wheel detected!";
     }
     }
 
 
+    if (device_id == PS2MOUSE_INTELLIMOUSE_ID) {
+        // Try to enable 5 buttons as well!
+        set_sample_rate(200);
+        set_sample_rate(200);
+        set_sample_rate(80);
+        device_id = get_device_id();
+    }
+
+    if (device_id == PS2MOUSE_INTELLIMOUSE_EXPLORER_ID) {
+        m_has_five_buttons = true;
+        klog() << "PS2MouseDevice: 5 buttons enabled!";
+    }
+
     enable_irq();
     enable_irq();
 }
 }
 
 

+ 3 - 0
Kernel/Devices/PS2MouseDevice.h

@@ -68,12 +68,15 @@ private:
     u8 wait_then_read(u8 port);
     u8 wait_then_read(u8 port);
     void parse_data_packet();
     void parse_data_packet();
     void expect_ack();
     void expect_ack();
+    void set_sample_rate(u8);
+    u8 get_device_id();
 
 
     bool m_device_present { false };
     bool m_device_present { false };
     CircularQueue<MousePacket, 100> m_queue;
     CircularQueue<MousePacket, 100> m_queue;
     u8 m_data_state { 0 };
     u8 m_data_state { 0 };
     u8 m_data[4];
     u8 m_data[4];
     bool m_has_wheel { false };
     bool m_has_wheel { false };
+    bool m_has_five_buttons { false };
 };
 };
 
 
 }
 }

+ 2 - 0
Kernel/MousePacket.h

@@ -37,6 +37,8 @@ struct MousePacket {
         LeftButton = 0x01,
         LeftButton = 0x01,
         RightButton = 0x02,
         RightButton = 0x02,
         MiddleButton = 0x04,
         MiddleButton = 0x04,
+        BackButton = 0x08,
+        ForwardButton = 0x10,
     };
     };
 
 
     unsigned char buttons { 0 };
     unsigned char buttons { 0 };