Kernel: Add support for the PS/2 mouse wheel if detected.

This commit is contained in:
Andreas Kling 2019-05-13 19:48:14 +02:00
parent 852d648912
commit dae8eb6454
Notes: sideshowbarker 2024-07-19 14:09:24 +09:00
3 changed files with 78 additions and 17 deletions

View file

@ -10,6 +10,11 @@
#define I8042_MOUSE_BUFFER 0x20 #define I8042_MOUSE_BUFFER 0x20
#define I8042_KEYBOARD_BUFFER 0x00 #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 //#define PS2MOUSE_DEBUG
static PS2MouseDevice* s_the; static PS2MouseDevice* s_the;
@ -40,6 +45,21 @@ void PS2MouseDevice::handle_irq()
byte data = IO::in8(I8042_BUFFER); byte data = IO::in8(I8042_BUFFER);
m_data[m_data_state] = data; 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) { switch (m_data_state) {
case 0: case 0:
if (!(data & 0x08)) { if (!(data & 0x08)) {
@ -52,17 +72,15 @@ void PS2MouseDevice::handle_irq()
++m_data_state; ++m_data_state;
break; break;
case 2: case 2:
m_data_state = 0; if (m_has_wheel) {
#ifdef PS2MOUSE_DEBUG ++m_data_state;
dbgprintf("PS2Mouse: %d, %d %s %s (buffered: %u)\n", break;
m_data[1], }
m_data[2], commit_packet();
(m_data[0] & 1) ? "Left" : "", break;
(m_data[0] & 2) ? "Right" : "", case 3:
m_queue.size() ASSERT(m_has_wheel);
); commit_packet();
#endif
parse_data_packet();
break; break;
} }
} }
@ -72,6 +90,9 @@ void PS2MouseDevice::parse_data_packet()
{ {
int x = m_data[1]; int x = m_data[1];
int y = m_data[2]; 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 x_overflow = m_data[0] & 0x40;
bool y_overflow = m_data[0] & 0x80; bool y_overflow = m_data[0] & 0x80;
bool x_sign = m_data[0] & 0x10; bool x_sign = m_data[0] & 0x10;
@ -87,7 +108,9 @@ void PS2MouseDevice::parse_data_packet()
MousePacket packet; MousePacket packet;
packet.dx = x; packet.dx = x;
packet.dy = y; packet.dy = y;
packet.dz = z;
packet.buttons = m_data[0] & 0x07; packet.buttons = m_data[0] & 0x07;
m_queue.enqueue(packet); m_queue.enqueue(packet);
} }
@ -119,17 +142,52 @@ void PS2MouseDevice::initialize()
// Set default settings. // Set default settings.
mouse_write(0xf6); mouse_write(0xf6);
byte ack1 = mouse_read(); expect_ack();
ASSERT(ack1 == 0xfa);
// Enable. // Enable.
mouse_write(0xf4); mouse_write(0xf4);
byte ack2 = mouse_read(); expect_ack();
ASSERT(ack2 == 0xfa);
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(); enable_irq();
} }
void PS2MouseDevice::expect_ack()
{
byte data = mouse_read();
ASSERT(data == I8042_ACK);
}
void PS2MouseDevice::prepare_for_input() void PS2MouseDevice::prepare_for_input()
{ {
for (;;) { for (;;) {

View file

@ -33,8 +33,10 @@ private:
void wait_then_write(byte port, byte data); void wait_then_write(byte port, byte data);
byte wait_then_read(byte port); byte wait_then_read(byte port);
void parse_data_packet(); void parse_data_packet();
void expect_ack();
CircularQueue<MousePacket, 100> m_queue; CircularQueue<MousePacket, 100> m_queue;
byte m_data_state { 0 }; byte m_data_state { 0 };
byte m_data[3]; byte m_data[4];
bool m_has_wheel { false };
}; };

View file

@ -3,5 +3,6 @@
struct MousePacket { struct MousePacket {
int dx { 0 }; int dx { 0 };
int dy { 0 }; int dy { 0 };
byte buttons; int dz { 0 };
byte buttons { 0 };
}; };