Skip to content

Commit ecf22f0

Browse files
committed
Basic PS2 Mouse driver now functional
1 parent b14396f commit ecf22f0

File tree

5 files changed

+151
-14
lines changed

5 files changed

+151
-14
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* -------------------------------------------------------------------------------------------------
3+
* Megha Operating System V2 - x86, PC Kernel - PS/2 Devices
4+
* -------------------------------------------------------------------------------------------------
5+
*/
6+
7+
#pragma once
8+
9+
#include <types.h>
10+
11+
#define PS2_MOUSE_CMD_GET_ID (0xF2)
12+
#define PS2_MOUSE_CMD_STATUS_REQ (0xE9)
13+
#define PS2_MOUSE_CMD_SET_SAMPLE_RATE (0xF3)
14+
#define PS2_MOUSE_CMD_GET_MOUSE_PACKET (0xEB)
15+
#define PS2_MOUSE_CMD_ENTER_REMOTE_MODE (0xF0)
16+
#define PS2_MOUSE_CMD_ENTER_STREAM_MODE (0xEA)
17+
18+
#define PS2_MOUSE_PACKET_BYTE0_LEFT_BTN_MASK (1 << 0)
19+
#define PS2_MOUSE_PACKET_BYTE0_RIGHT_BTN_MASK (1 << 1)
20+
#define PS2_MOUSE_PACKET_BYTE0_MID_BTN_MASK (1 << 2)
21+
#define PS2_MOUSE_PACKET_BYTE0_X_SIGN_BTN_MASK (1 << 4)
22+
#define PS2_MOUSE_PACKET_BYTE0_Y_SIGN_BTN_MASK (1 << 5)
23+
#define PS2_MOUSE_PACKET_BYTE0_X_OVERFLOW_BTN_MASK (1 << 6)
24+
#define PS2_MOUSE_PACKET_BYTE0_Y_OVERFLOW_BTN_MASK (1 << 7)
25+
26+
#define PS2_MOUSE_STATE_BYTE_0_RIGHT_BTN_MASK (1 << 0)
27+
#define PS2_MOUSE_STATE_BYTE_0_MID_BTN_MASK (1 << 1)
28+
#define PS2_MOUSE_STATE_BYTE_0_LEFT_BTN_MASK (1 << 2)
29+
#define PS2_MOUSE_STATE_BYTE_0_SCALE_2x1_ENABLED_MASK (1 << 4)
30+
#define PS2_MOUSE_STATE_BYTE_0_DATA_REPORTING_ENABLED_MASK (1 << 5)
31+
#define PS2_MOUSE_STATE_BYTE_0_REMOTE_MODE_ENABLED (1 << 6)
32+
33+
typedef struct MousePositionData {
34+
INT x;
35+
INT y;
36+
bool left_button;
37+
bool right_button;
38+
bool middle_button;
39+
} MousePositionData;
40+
41+
bool ps2mouse_init();
42+
bool ps2kb_init();
43+
MousePositionData mouse_get_packet();

include/x86/config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636

3737
#define CONFIG_HANDLES_ARRAY_ITEM_COUNT (1000) /* Number of objects stored in handles array */
3838

39+
#define CONFIG_PS2_MOUSE_SAMPLE_RATE (40)
40+
3941
/** Derived Configs
4042
* SHOULD NOT BE EDITTED MANUALLY */
4143
#define CONFIG_PAGE_FRAME_SIZE_BITS (31U - CONFIG_PAGE_SIZE_BITS)

src/kernel/drivers/x86/pc/8042_ps2.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,6 @@ bool ps2_configuration (U8 enabled, U8 disabled, U8* original_config)
112112
RETURN_ERROR (ERROR_PASSTHROUGH, false);
113113
}
114114

115-
kearly_println ("Config read: %x", config);
116-
117115
// Return the read config if point is not NULL
118116
if (original_config != NULL) {
119117
*original_config = config;
@@ -123,8 +121,6 @@ bool ps2_configuration (U8 enabled, U8 disabled, U8* original_config)
123121
config &= (U8) ~(disabled);
124122
config |= (enabled);
125123

126-
kearly_println ("Config written: %x", config);
127-
128124
// Write back the modified config
129125
if (!ps2_wait_write (PS2_CMD_PORT, PS2_CMD_WRITE_CONFIGURATION_BYTE)) {
130126
RETURN_ERROR (ERROR_PASSTHROUGH, false);

src/kernel/drivers/x86/pc/ps2mouse.c

Lines changed: 98 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,34 @@
55
*/
66

77
#include <drivers/x86/pc/8042_ps2.h>
8-
#include <kassert.h>
9-
#include <stdbool.h>
108
#include <kerror.h>
119
#include <drivers/x86/pc/8259_pic.h>
1210
#include <x86/idt.h>
1311
#include <x86/interrupt.h>
1412
#include <x86/gdt.h>
15-
#include <x86/io.h>
1613
#include <utils.h>
14+
#include <drivers/x86/pc/ps2_devices.h>
15+
16+
typedef struct MousePacket {
17+
INT byte_index;
18+
U8 b0;
19+
U8 b1;
20+
U8 b2;
21+
} MousePacket;
22+
23+
typedef struct MouseStatus {
24+
U8 id;
25+
U8 status;
26+
U8 resolution;
27+
U8 sample_rate;
28+
} MouseStatus;
1729

1830
void mouse_interrupt_asm_handler();
31+
static bool ismouse();
32+
static MouseStatus get_mouse_state();
33+
34+
static MousePositionData mouse_position = { 0 };
35+
static MouseStatus mouse_status_original = { 0 };
1936

2037
static bool ismouse()
2138
{
@@ -36,6 +53,21 @@ static bool ismouse()
3653
return true;
3754
}
3855

56+
static MouseStatus get_mouse_state()
57+
{
58+
MouseStatus status = { 0 };
59+
60+
ps2_write_device_cmd (PS2_SECOND_DEVICE, PS2_MOUSE_CMD_GET_ID);
61+
ps2_wait_read (PS2_DATA_PORT, &status.id);
62+
63+
ps2_write_device_cmd (PS2_SECOND_DEVICE, PS2_MOUSE_CMD_STATUS_REQ);
64+
ps2_wait_read (PS2_DATA_PORT, &status.status);
65+
ps2_wait_read (PS2_DATA_PORT, &status.resolution);
66+
ps2_wait_read (PS2_DATA_PORT, &status.sample_rate);
67+
68+
return status;
69+
}
70+
3971
bool ps2mouse_init()
4072
{
4173
FUNC_ENTRY();
@@ -53,11 +85,30 @@ bool ps2mouse_init()
5385
RETURN_ERROR (ERROR_PASSTHROUGH, false);
5486
}
5587

56-
// Interrupt when keys are pressed
88+
// Set sample rate
89+
if (!ps2_write_device_cmd (PS2_SECOND_DEVICE, PS2_MOUSE_CMD_SET_SAMPLE_RATE)) {
90+
RETURN_ERROR (ERROR_PASSTHROUGH, false);
91+
}
92+
if (!ps2_write_device_cmd (PS2_SECOND_DEVICE, CONFIG_PS2_MOUSE_SAMPLE_RATE)) {
93+
RETURN_ERROR (ERROR_PASSTHROUGH, false);
94+
}
95+
96+
// Enable scanning by the device
5797
if (!ps2_write_device_cmd (PS2_SECOND_DEVICE, PS2_DEV_CMD_ENABLE_SCANNING)) {
5898
RETURN_ERROR (ERROR_PASSTHROUGH, false);
5999
}
60100

101+
// Check if mouse status is as per settings set previously
102+
mouse_status_original = get_mouse_state();
103+
104+
if (mouse_status_original.sample_rate != CONFIG_PS2_MOUSE_SAMPLE_RATE ||
105+
!BIT_ISSET (mouse_status_original.status,
106+
PS2_MOUSE_STATE_BYTE_0_DATA_REPORTING_ENABLED_MASK) ||
107+
BIT_ISSET (mouse_status_original.status, PS2_MOUSE_STATE_BYTE_0_REMOTE_MODE_ENABLED)) {
108+
// Device state is not as per expected.
109+
RETURN_ERROR (ERR_DEVICE_INIT_FAILED, false);
110+
}
111+
61112
// Setup PS2 configuration to enable interrupts from port 2
62113
ps2_configuration (PS2_CONFIG_SECOND_PORT_INTERRUPT_ENABLE, 0, NULL);
63114

@@ -71,15 +122,52 @@ bool ps2mouse_init()
71122
return true;
72123
}
73124

125+
MousePositionData mouse_get_packet()
126+
{
127+
return mouse_position;
128+
}
129+
74130
INTERRUPT_HANDLER (mouse_interrupt)
75131
void mouse_interrupt_handler (InterruptFrame* frame)
76132
{
77133
(void)frame;
78-
#if defined(DEBUG) && defined(PORT_E9_ENABLED)
79-
U8 data1, data2, data3 = 0;
80-
data1 = (U8)ps2_no_wait_read (PS2_DATA_PORT);
81-
data2 = (U8)ps2_no_wait_read (PS2_DATA_PORT);
82-
INFO ("Mouse handler: %x, %x, %x", data1, data2, data3);
83-
#endif
134+
135+
static MousePacket mpacket = { 0 };
136+
137+
U8 data;
138+
if (ps2_wait_read (PS2_DATA_PORT, &data)) {
139+
switch (mpacket.byte_index) {
140+
case 0:
141+
mpacket.b0 = data;
142+
break;
143+
case 1:
144+
mpacket.b1 = data;
145+
break;
146+
case 2:
147+
mpacket.b2 = data;
148+
149+
INFO ("Mouse packet: %x %x %x", mpacket.b0, mpacket.b1, mpacket.b2);
150+
151+
// Discard whole packet is overflow is set
152+
if (!BIT_ISSET (mpacket.b0, PS2_MOUSE_PACKET_BYTE0_X_OVERFLOW_BTN_MASK) &&
153+
!BIT_ISSET (mpacket.b0, PS2_MOUSE_PACKET_BYTE0_Y_OVERFLOW_BTN_MASK)) {
154+
mouse_position.x += mpacket.b1 - ((mpacket.b0 << 4) & 0x100);
155+
mouse_position.y += mpacket.b2 - ((mpacket.b0 << 3) & 0x100);
156+
mouse_position.left_button = BIT_ISSET (mpacket.b0,
157+
PS2_MOUSE_PACKET_BYTE0_LEFT_BTN_MASK);
158+
mouse_position.right_button = BIT_ISSET (mpacket.b0,
159+
PS2_MOUSE_PACKET_BYTE0_RIGHT_BTN_MASK);
160+
mouse_position.middle_button = BIT_ISSET (mpacket.b0,
161+
PS2_MOUSE_PACKET_BYTE0_MID_BTN_MASK);
162+
} else {
163+
WARN ("PS2: Mouse overflow detected.");
164+
}
165+
break;
166+
default:
167+
FATAL_BUG();
168+
}
169+
mpacket.byte_index = (mpacket.byte_index + 1) % 3;
170+
}
171+
84172
pic_send_eoi (PIC_IRQ_PS2_MOUSE);
85173
}

src/kernel/x86/kernel.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include <vmm.h>
4040
#include <drivers/x86/pc/8259_pic.h>
4141
#include <drivers/x86/pc/8254_pit.h>
42+
#include <drivers/x86/pc/8042_ps2.h>
43+
#include <drivers/x86/pc/ps2_devices.h>
4244
#ifdef GRAPHICS_MODE_ENABLED
4345
#include <kgraphics.h>
4446
#include <compositor.h>
@@ -173,6 +175,12 @@ void kernel_main ()
173175
__asm__ volatile ("cpuid;":"+eax"(eax):"eax"(0));
174176
kearly_println ("CPUID [EAX=0]: %x", eax);
175177

178+
ps2_init();
179+
180+
if (!ps2mouse_init()) {
181+
k_panic ("PS2 Mouse initialization falied");
182+
}
183+
176184
run_root_process();
177185
k_halt();
178186
}

0 commit comments

Comments
 (0)