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
1830void 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
2037static 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+
3971bool 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+
74130INTERRUPT_HANDLER (mouse_interrupt )
75131void 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}
0 commit comments