summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/Devices/PS2MouseDevice.cpp88
-rw-r--r--Kernel/Devices/PS2MouseDevice.h4
-rw-r--r--Kernel/MousePacket.h3
3 files changed, 78 insertions, 17 deletions
diff --git a/Kernel/Devices/PS2MouseDevice.cpp b/Kernel/Devices/PS2MouseDevice.cpp
index 0af6ca4010..c7d8ff54f5 100644
--- a/Kernel/Devices/PS2MouseDevice.cpp
+++ b/Kernel/Devices/PS2MouseDevice.cpp
@@ -10,6 +10,11 @@
#define I8042_MOUSE_BUFFER 0x20
#define I8042_KEYBOARD_BUFFER 0x00
+#define PS2MOUSE_GET_DEVICE_ID 0xF2
+#define PS2MOUSE_SET_SAMPLE_RATE 0xF3
+
+#define PS2MOUSE_INTELLIMOUSE_ID 0x03
+
//#define PS2MOUSE_DEBUG
static PS2MouseDevice* s_the;
@@ -40,6 +45,21 @@ void PS2MouseDevice::handle_irq()
byte data = IO::in8(I8042_BUFFER);
m_data[m_data_state] = data;
+
+ auto commit_packet = [&] {
+ m_data_state = 0;
+#ifdef PS2MOUSE_DEBUG
+ dbgprintf("PS2Mouse: %d, %d %s %s (buffered: %u)\n",
+ m_data[1],
+ m_data[2],
+ (m_data[0] & 1) ? "Left" : "",
+ (m_data[0] & 2) ? "Right" : "",
+ m_queue.size()
+ );
+#endif
+ parse_data_packet();
+ };
+
switch (m_data_state) {
case 0:
if (!(data & 0x08)) {
@@ -52,17 +72,15 @@ void PS2MouseDevice::handle_irq()
++m_data_state;
break;
case 2:
- m_data_state = 0;
-#ifdef PS2MOUSE_DEBUG
- dbgprintf("PS2Mouse: %d, %d %s %s (buffered: %u)\n",
- m_data[1],
- m_data[2],
- (m_data[0] & 1) ? "Left" : "",
- (m_data[0] & 2) ? "Right" : "",
- m_queue.size()
- );
-#endif
- parse_data_packet();
+ if (m_has_wheel) {
+ ++m_data_state;
+ break;
+ }
+ commit_packet();
+ break;
+ case 3:
+ ASSERT(m_has_wheel);
+ commit_packet();
break;
}
}
@@ -72,6 +90,9 @@ void PS2MouseDevice::parse_data_packet()
{
int x = m_data[1];
int y = m_data[2];
+ int z = 0;
+ if (m_has_wheel)
+ z = (char)m_data[3];
bool x_overflow = m_data[0] & 0x40;
bool y_overflow = m_data[0] & 0x80;
bool x_sign = m_data[0] & 0x10;
@@ -87,7 +108,9 @@ void PS2MouseDevice::parse_data_packet()
MousePacket packet;
packet.dx = x;
packet.dy = y;
+ packet.dz = z;
packet.buttons = m_data[0] & 0x07;
+
m_queue.enqueue(packet);
}
@@ -119,17 +142,52 @@ void PS2MouseDevice::initialize()
// Set default settings.
mouse_write(0xf6);
- byte ack1 = mouse_read();
- ASSERT(ack1 == 0xfa);
+ expect_ack();
// Enable.
mouse_write(0xf4);
- byte ack2 = mouse_read();
- ASSERT(ack2 == 0xfa);
+ expect_ack();
+
+ mouse_write(PS2MOUSE_GET_DEVICE_ID);
+ expect_ack();
+ byte device_id = mouse_read();
+
+ if (device_id != PS2MOUSE_INTELLIMOUSE_ID) {
+ // 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();
+ }
+
+ if (device_id == PS2MOUSE_INTELLIMOUSE_ID) {
+ m_has_wheel = true;
+ kprintf("PS2MouseDevice: Mouse wheel enabled!\n");
+ } else {
+ kprintf("PS2MouseDevice: No mouse wheel detected!\n");
+ }
enable_irq();
}
+void PS2MouseDevice::expect_ack()
+{
+ byte data = mouse_read();
+ ASSERT(data == I8042_ACK);
+}
+
void PS2MouseDevice::prepare_for_input()
{
for (;;) {
diff --git a/Kernel/Devices/PS2MouseDevice.h b/Kernel/Devices/PS2MouseDevice.h
index a3e4eef698..6a04ab672c 100644
--- a/Kernel/Devices/PS2MouseDevice.h
+++ b/Kernel/Devices/PS2MouseDevice.h
@@ -33,8 +33,10 @@ private:
void wait_then_write(byte port, byte data);
byte wait_then_read(byte port);
void parse_data_packet();
+ void expect_ack();
CircularQueue<MousePacket, 100> m_queue;
byte m_data_state { 0 };
- byte m_data[3];
+ byte m_data[4];
+ bool m_has_wheel { false };
};
diff --git a/Kernel/MousePacket.h b/Kernel/MousePacket.h
index ad0513ff35..26d03f4988 100644
--- a/Kernel/MousePacket.h
+++ b/Kernel/MousePacket.h
@@ -3,5 +3,6 @@
struct MousePacket {
int dx { 0 };
int dy { 0 };
- byte buttons;
+ int dz { 0 };
+ byte buttons { 0 };
};