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_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 (;;) {

View file

@ -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 };
};

View file

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