mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
Kernel: Add support for the PS/2 mouse wheel if detected.
This commit is contained in:
parent
852d648912
commit
dae8eb6454
Notes:
sideshowbarker
2024-07-19 14:09:24 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/dae8eb6454d
3 changed files with 78 additions and 17 deletions
|
@ -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 (;;) {
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
@ -3,5 +3,6 @@
|
|||
struct MousePacket {
|
||||
int dx { 0 };
|
||||
int dy { 0 };
|
||||
byte buttons;
|
||||
int dz { 0 };
|
||||
byte buttons { 0 };
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue