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_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 (;;) {
|
||||||
|
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue