summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-07-18 21:23:22 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-07-18 21:23:22 +0200
commitee3e51aa1624693217b1a4ae7bfb2730424c08f2 (patch)
treebebd430417bad79c9cd1aa91f48d168f90795621
parent3a1570d0e6531e3f49e79bbbe4e24d6280e49b1a (diff)
downloadabaos-ee3e51aa1624693217b1a4ae7bfb2730424c08f2.tar.gz
abaos-ee3e51aa1624693217b1a4ae7bfb2730424c08f2.tar.bz2
added a virtual mouse driver interface, made the PS/2 mouse a specialization of it
-rw-r--r--src/Makefile13
-rw-r--r--src/drivers/hdi/mouse.c65
-rw-r--r--src/drivers/hdi/mouse.h (renamed from src/drivers/hdi/ps2/mouse.h)21
-rw-r--r--src/drivers/hdi/ps2/mouse.c263
-rw-r--r--src/drivers/hdi/ps2/ps2mouse.c246
-rw-r--r--src/drivers/hdi/ps2/ps2mouse.h35
-rw-r--r--src/kernel/kernel.c13
7 files changed, 365 insertions, 291 deletions
diff --git a/src/Makefile b/src/Makefile
index 013e895..5b67063 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -36,7 +36,7 @@ kernel.bin: kernel.elf
kernel.sym: kernel.elf
$(OBJCOPY) --only-keep-debug kernel.elf kernel.sym
-kernel.elf: kernel/entry.o kernel/kernel.o kernel/kernel_asm.o kernel/console.o kernel/vgatext.o kernel/serial.o kernel/memorymanagement.o kernel/tasks.o hardware/port.o hardware/port_asm.o hardware/interrupts.o hardware/interrupts_asm.o hardware/pci.o drivers/driver.o drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/mouse.o drivers/video/vga.o drivers/video/vga_font.o drivers/net/rtl8139.o gui/widget.o gui/composite_widget.o gui/window.o gui/desktop.o gui/text_widget.o libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o
+kernel.elf: kernel/entry.o kernel/kernel.o kernel/kernel_asm.o kernel/console.o kernel/vgatext.o kernel/serial.o kernel/memorymanagement.o kernel/tasks.o hardware/port.o hardware/port_asm.o hardware/interrupts.o hardware/interrupts_asm.o hardware/pci.o drivers/driver.o drivers/hdi/mouse.o drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/ps2mouse.o drivers/video/vga.o drivers/video/vga_font.o drivers/net/rtl8139.o gui/widget.o gui/composite_widget.o gui/window.o gui/desktop.o gui/text_widget.o libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o
$(LD) -o kernel.elf -N -n -Ttext 0x8800 -e kernel_entry --oformat elf32-i386 \
kernel/entry.o \
kernel/kernel.o kernel/kernel_asm.o \
@@ -45,8 +45,8 @@ kernel.elf: kernel/entry.o kernel/kernel.o kernel/kernel_asm.o kernel/console.o
hardware/port.o hardware/port_asm.o \
hardware/interrupts.o hardware/interrupts_asm.o \
hardware/pci.o \
- drivers/driver.o \
- drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/mouse.o \
+ drivers/driver.o drivers/hdi/mouse.o \
+ drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/ps2mouse.o \
drivers/video/vga.o drivers/video/vga_font.o \
drivers/net/rtl8139.o \
libc/string.o libc/stdlib.o libc/stdio.o libc/setjmp.o \
@@ -98,11 +98,14 @@ hardware/pci.o: hardware/pci.c hardware/pci.h
drivers/driver.o: drivers/driver.c drivers/driver.h
$(CC) $(CFLAGS) -c -o drivers/driver.o drivers/driver.c
+drivers/hdi/mouse.o: drivers/hdi/mouse.c drivers/hdi/mouse.h
+ $(CC) $(CFLAGS) -c -o drivers/hdi/mouse.o drivers/hdi/mouse.c
+
drivers/hdi/ps2/keyboard.o: drivers/hdi/ps2/keyboard.c drivers/hdi/ps2/keyboard.h
$(CC) $(CFLAGS) -c -o drivers/hdi/ps2/keyboard.o drivers/hdi/ps2/keyboard.c
-drivers/hdi/ps2/mouse.o: drivers/hdi/ps2/mouse.c drivers/hdi/ps2/mouse.h
- $(CC) $(CFLAGS) -c -o drivers/hdi/ps2/mouse.o drivers/hdi/ps2/mouse.c
+drivers/hdi/ps2/ps2mouse.o: drivers/hdi/ps2/ps2mouse.c drivers/hdi/ps2/ps2mouse.h
+ $(CC) $(CFLAGS) -c -o drivers/hdi/ps2/ps2mouse.o drivers/hdi/ps2/ps2mouse.c
drivers/video/vga.o: drivers/video/vga.c drivers/video/vga.h
$(CC) $(CFLAGS) -c -o drivers/video/vga.o drivers/video/vga.c
diff --git a/src/drivers/hdi/mouse.c b/src/drivers/hdi/mouse.c
new file mode 100644
index 0000000..85d4c82
--- /dev/null
+++ b/src/drivers/hdi/mouse.c
@@ -0,0 +1,65 @@
+#include "mouse.h"
+
+#include "string.h"
+#include "kernel.h"
+
+static mouse_vtable_t const mouse_vtable = {
+ {
+ mouse_activate,
+ mouse_deactivate,
+ mouse_deinit,
+ mouse_print_info
+ },
+ mouse_set_resolution,
+ mouse_set_position
+};
+
+void mouse_init( mouse_t *mouse, mouse_event_handler_t handler, interrupt_t *interrupt, void *context )
+{
+ memset( mouse, 0, sizeof( mouse_t ) );
+
+ driver_init( (driver_t *)mouse, DRIVER_TYPE_MOUSE, interrupt, context );
+
+ mouse->handler = handler;
+
+ ((driver_t *)mouse)->vtable = (driver_vtable_t *)&mouse_vtable;
+}
+
+void mouse_deinit( void *obj )
+{
+ // nothing to be done
+}
+
+void mouse_activate( void *obj )
+{
+ kernel_panic( "Activating generic mouse driver should not be called directly." );
+}
+
+void mouse_deactivate( void *obj )
+{
+ kernel_panic( "Deactivating generic mouse driver should not be called directly." );
+}
+
+void mouse_print_info( void *obj )
+{
+ kernel_panic( "Printing info of generic mouse driver should not be called directly." );
+}
+
+void mouse_set_resolution( void *obj, const uint32_t res_x, const uint32_t res_y )
+{
+ mouse_t *mouse = (mouse_t *)obj;
+
+ mouse->res_x = res_x;
+ mouse->res_y = res_y;
+ mouse->cursor_x = mouse->res_x / 2;
+ mouse->cursor_y = mouse->res_y / 2;
+}
+
+void mouse_set_position( void *obj, const uint32_t x, const uint32_t y )
+{
+ mouse_t *mouse = (mouse_t *)obj;
+
+ mouse->cursor_x = x;
+ mouse->cursor_y = y;
+}
+
diff --git a/src/drivers/hdi/ps2/mouse.h b/src/drivers/hdi/mouse.h
index 1a00b5e..90417f3 100644
--- a/src/drivers/hdi/ps2/mouse.h
+++ b/src/drivers/hdi/mouse.h
@@ -1,15 +1,8 @@
#ifndef MOUSE_H
#define MOUSE_H
-#include "string.h"
-
-#include "interrupts.h"
-#include "port.h"
-
#include "driver.h"
-#define MAX_NOF_MOUSE_PACKETS 5
-
typedef enum {
MOUSE_EVENT_TYPE_BUTTON_UP,
MOUSE_EVENT_TYPE_BUTTON_DOWN,
@@ -35,23 +28,17 @@ typedef void (*mouse_event_handler_t)( mouse_event_t *event, void *context );
typedef struct {
driver_t base;
- interrupt_t *interrupts;
- port8_t command_port;
- port8_t data_port;
- int nof_packets; // 3 or more mouse packets
- uint8_t buf[MAX_NOF_MOUSE_PACKETS];
- uint8_t buttons;
- uint8_t offset;
uint32_t res_x;
uint32_t res_y;
int32_t cursor_x;
int32_t cursor_y;
mouse_event_handler_t handler;
- interrupt_handler_t interrupt_handler;
} mouse_t;
typedef struct {
driver_vtable_t base;
+ void (*set_resolution)( void *obj, const uint32_t x, const uint32_t y );
+ void (*set_position)( void *obj, const uint32_t x, const uint32_t y );
} mouse_vtable_t;
void mouse_init( mouse_t *mouse, mouse_event_handler_t handler, interrupt_t *interrupt, void *context );
@@ -60,8 +47,8 @@ void mouse_deactivate( void *obj );
void mouse_deinit( void *obj );
void mouse_print_info( void *obj );
-void mouse_set_resolution( mouse_t *mouse, const uint32_t x, const uint32_t y );
-void mouse_set_position( mouse_t *mouse, const uint32_t x, const uint32_t y );
+void mouse_set_resolution( void *obj, const uint32_t x, const uint32_t y );
+void mouse_set_position( void *obj, const uint32_t x, const uint32_t y );
uint32_t mouse_handle_interrupt( interrupt_handler_t *handler, uint32_t esp );
diff --git a/src/drivers/hdi/ps2/mouse.c b/src/drivers/hdi/ps2/mouse.c
deleted file mode 100644
index 1afd8d2..0000000
--- a/src/drivers/hdi/ps2/mouse.c
+++ /dev/null
@@ -1,263 +0,0 @@
-#include "mouse.h"
-
-#include "stdio.h"
-
-// status register on command port (read)
-#define STATUS_REG_OUTPUT_BUF_FULL 0x01
-#define STATUS_REG_INPUT_BUF_FULL 0x02
-#define STATUS_REG_OUTPUT_BUF2_FULL 0x20
-
-// status control register flags
-#define STATUS_CONTROL_CONFIG_ENABLE_IRQ_PORT2 0x02
-#define STATUS_CONTROL_CONFIG_CLOCK_PORT2 0x20
-
-// generic PS/2 commands
-#define COMMAND_GET_STATE 0x20
-#define COMMAND_SET_STATE 0x60
-#define COMMAND_DISABLE_PORT2 0xA7
-#define COMMAND_ENABLE_PORT2 0xA8
-#define COMMAND_SEND_TO_PORT2 0xD4
-
-// mouse commands
-#define MOUSE_COMMAND_GET_DEVICE_ID 0xF2
-#define MOUSE_COMMAND_SET_SAMPLE_RATE 0xF3
-#define MOUSE_COMMAND_ENABLE_DATAREPORTING 0xF4
-#define MOUSE_COMMAND_SET_DEFAULTS 0xF6
-#define DEFAULT_NOF_PACKETS 3
-
-// mouse data packet one
-#define MOUSE_BYTE1_LEFT_BUTTON 0x01
-#define MOUSE_BYTE1_RIGHT_BUTTON 0x02
-#define MOUSE_BYTE1_MIDDLE_BUTTON 0x04
-#define MOUSE_BYTE1_ID_BIT 0x08
-#define MOUSE_BYTE1_X_SIGN 0x10
-#define MOUSE_BYTE1_Y_SIGN 0x20
-#define MOUSE_BYTE1_X_OVERFLOW 0x40
-#define MOUSE_BYTE1_Y_OVERFLOW 0x80
-
-#undef DEBUG
-
-static uint8_t read_data( mouse_t *mouse )
-{
- while( ( port8_read( &mouse->command_port ) & STATUS_REG_OUTPUT_BUF_FULL ) == 0 ) { }
- return port8_read( &mouse->data_port );
-}
-
-static void send_command( mouse_t *mouse, uint8_t command )
-{
- while( port8_read( &mouse->command_port ) & STATUS_REG_INPUT_BUF_FULL ) { }
- port8_write( &mouse->command_port, command );
-}
-
-static void write_data( mouse_t *mouse, uint8_t data )
-{
- while( port8_read( &mouse->command_port ) & STATUS_REG_INPUT_BUF_FULL ) { }
- port8_write( &mouse->data_port, data );
-}
-
-static void read_ack( mouse_t *mouse )
-{
- uint8_t data = read_data( mouse );
- if( data == 0xFA ) {
- return;
- } else {
- printf( "ERR PS/2 mouse: acknoledgment failed 0x%X\n", data );
- }
-}
-
-static void set_sample_rate( mouse_t *mouse, uint8_t samples )
-{
- send_command( mouse, COMMAND_SEND_TO_PORT2 );
- write_data( mouse, MOUSE_COMMAND_SET_SAMPLE_RATE );
- read_ack( mouse );
-
- send_command( mouse, COMMAND_SEND_TO_PORT2 );
- write_data( mouse, samples );
- read_ack( mouse );
-}
-
-static mouse_vtable_t const mouse_vtable = {
- {
- mouse_activate,
- mouse_deactivate,
- mouse_deinit,
- mouse_print_info
- }
-};
-
-void mouse_init( mouse_t *mouse, mouse_event_handler_t handler, interrupt_t *interrupt, void *context )
-{
- memset( mouse, 0, sizeof( mouse_t ) );
-
- driver_init( (driver_t *)mouse, DRIVER_TYPE_MOUSE, interrupt, context );
-
- // TODO: we should probe for wheel mouse and more than 3 packets
- mouse->nof_packets = DEFAULT_NOF_PACKETS;
-
- mouse->handler = handler;
-
- port8_init( &mouse->command_port, 0x64 );
- port8_init( &mouse->data_port, 0x60 );
-
- ((driver_t *)mouse)->vtable = (driver_vtable_t *)&mouse_vtable;
-}
-
-void mouse_activate( void *obj )
-{
- puts( "Activating driver for PS/2 mouse.." );
-
- driver_t *driver = obj;
- mouse_t *mouse = obj;
-
- // enable port 2
- send_command( mouse, COMMAND_ENABLE_PORT2 );
-
- // enable interrupts for port 2
- send_command( mouse, COMMAND_GET_STATE );
- uint8_t status = read_data( mouse );
- status |= STATUS_CONTROL_CONFIG_ENABLE_IRQ_PORT2;
- status &= ~STATUS_CONTROL_CONFIG_CLOCK_PORT2;
- send_command( mouse, COMMAND_SET_STATE );
- write_data( mouse, status );
-
- // detecting mouse wheel (and 4th data packet)
- set_sample_rate( mouse, 200 );
- set_sample_rate( mouse, 100 );
- set_sample_rate( mouse, 80 );
- send_command( mouse, COMMAND_SEND_TO_PORT2 );
- write_data( mouse, MOUSE_COMMAND_GET_DEVICE_ID );
- read_ack( mouse );
- uint8_t id = read_data( mouse );
- printf( "PS/2 mouse model id is 0x%X\n", id );
- if( id == 0x03 ) {
- mouse->nof_packets = 4;
- }
-
- // set mouse defaults
-// send_command( mouse, COMMAND_SEND_TO_PORT2 );
-// write_data( mouse, MOUSE_COMMAND_SET_DEFAULTS );
-
- interrupt_handler_init( &mouse->interrupt_handler, IRQ_BASE + 0x0C, driver->interrupt, mouse_handle_interrupt, obj );
- interrupts_register_interrupt_handler( mouse->interrupt_handler );
-
- // enable mouse on second port
- send_command( mouse, COMMAND_SEND_TO_PORT2 );
- write_data( mouse, MOUSE_COMMAND_ENABLE_DATAREPORTING );
- read_ack( mouse );
-}
-
-void mouse_deactivate( void *obj )
-{
- puts( "Dectivating driver for PS/2 mouse.." );
-
- mouse_t *mouse = obj;
-
- send_command( mouse, COMMAND_DISABLE_PORT2 );
-}
-
-void mouse_deinit( void *obj )
-{
- // nothing to do
-}
-
-uint32_t mouse_handle_interrupt( interrupt_handler_t *handler, uint32_t esp )
-{
- mouse_t *mouse = (mouse_t *)handler->driver;
-
- uint8_t status = port8_read( &mouse->command_port );
- if( !( status & STATUS_REG_OUTPUT_BUF2_FULL ) ) {
- return esp;
- }
-
- mouse->buf[mouse->offset] = port8_read( &mouse->data_port );
-
-#ifdef DEBUG
- printf( "MOUSE: %d 0x%X\n", mouse->offset, mouse->buf[mouse->offset] );
-#endif
-
- switch( mouse->offset ) {
- case 0:
- if( mouse->buf[0] & MOUSE_BYTE1_ID_BIT ) {
- for( int i = 0; i < 3; i++ ) {
- if( ( mouse->buf[0] & ( 0x01 << i ) ) != ( mouse->buttons & ( 0x01 << i ) ) ) {
- mouse_event_t event;
- event.button = i + 1;
- if( mouse->buttons & ( 0x01 << i ) ) {
- event.type = MOUSE_EVENT_TYPE_BUTTON_UP;
- } else {
- event.type = MOUSE_EVENT_TYPE_BUTTON_DOWN;
- }
- event.cursor_x = mouse->cursor_x;
- event.cursor_y = mouse->cursor_y;
- mouse->handler( &event, mouse->base.context );
- }
- }
- mouse->buttons = mouse->buf[0];
- }
- break;
-
- case 1:
- // delay evaluation of move events till second byte
- break;
-
- case 2:
- if( mouse->buf[1] !=0 || mouse->buf[2] != 0 ) {
-
- mouse_event_t event;
- event.type = MOUSE_EVENT_TYPE_MOVE;
- event.old_cursor_x = mouse->cursor_x;
- event.old_cursor_y = mouse->cursor_y;
-
- mouse->cursor_x += (int8_t)mouse->buf[1];
- mouse->cursor_y -= (int8_t)mouse->buf[2];
- if( mouse->cursor_x < 0 ) {
- mouse->cursor_x = 0;
- }
- if( mouse->cursor_x > mouse->res_x - 1 ) {
- mouse->cursor_x = mouse->res_x - 1;
- }
- if( mouse->cursor_y < 0 ) {
- mouse->cursor_y = 0;
- }
- if( mouse->cursor_y > mouse->res_y - 1 ) {
- mouse->cursor_y = mouse->res_y - 1;
- }
-
- event.cursor_x = mouse->cursor_x;
- event.cursor_y = mouse->cursor_y;
-
- mouse->handler( &event, mouse->base.context );
- }
-
- break;
-
- case 3:
- // TODO: read fourth data packet, but don't handle
- // it yet
- break;
- }
-
- // advance offset
- mouse->offset = ( mouse->offset + 1 ) % mouse->nof_packets;
-
- return esp;
-}
-
-void mouse_print_info( void *obj )
-{
- puts( "PS/2 mouse driver" );
-}
-
-void mouse_set_resolution( mouse_t *mouse, const uint32_t res_x, const uint32_t res_y )
-{
- mouse->res_x = res_x;
- mouse->res_y = res_y;
- mouse->cursor_x = mouse->res_x / 2;
- mouse->cursor_y = mouse->res_y / 2;
-}
-
-void mouse_set_position( mouse_t *mouse, const uint32_t x, const uint32_t y )
-{
- mouse->cursor_x = x;
- mouse->cursor_y = y;
-}
diff --git a/src/drivers/hdi/ps2/ps2mouse.c b/src/drivers/hdi/ps2/ps2mouse.c
new file mode 100644
index 0000000..9f0fcae
--- /dev/null
+++ b/src/drivers/hdi/ps2/ps2mouse.c
@@ -0,0 +1,246 @@
+#include "ps2mouse.h"
+
+#include "stdio.h"
+
+// status register on command port (read)
+#define STATUS_REG_OUTPUT_BUF_FULL 0x01
+#define STATUS_REG_INPUT_BUF_FULL 0x02
+#define STATUS_REG_OUTPUT_BUF2_FULL 0x20
+
+// status control register flags
+#define STATUS_CONTROL_CONFIG_ENABLE_IRQ_PORT2 0x02
+#define STATUS_CONTROL_CONFIG_CLOCK_PORT2 0x20
+
+// generic PS/2 commands
+#define COMMAND_GET_STATE 0x20
+#define COMMAND_SET_STATE 0x60
+#define COMMAND_DISABLE_PORT2 0xA7
+#define COMMAND_ENABLE_PORT2 0xA8
+#define COMMAND_SEND_TO_PORT2 0xD4
+
+// mouse commands
+#define MOUSE_COMMAND_GET_DEVICE_ID 0xF2
+#define MOUSE_COMMAND_SET_SAMPLE_RATE 0xF3
+#define MOUSE_COMMAND_ENABLE_DATAREPORTING 0xF4
+#define MOUSE_COMMAND_SET_DEFAULTS 0xF6
+#define DEFAULT_NOF_PACKETS 3
+
+// mouse data packet one
+#define MOUSE_BYTE1_LEFT_BUTTON 0x01
+#define MOUSE_BYTE1_RIGHT_BUTTON 0x02
+#define MOUSE_BYTE1_MIDDLE_BUTTON 0x04
+#define MOUSE_BYTE1_ID_BIT 0x08
+#define MOUSE_BYTE1_X_SIGN 0x10
+#define MOUSE_BYTE1_Y_SIGN 0x20
+#define MOUSE_BYTE1_X_OVERFLOW 0x40
+#define MOUSE_BYTE1_Y_OVERFLOW 0x80
+
+#undef DEBUG
+
+static uint8_t read_data( ps2mouse_t *ps2mouse )
+{
+ while( ( port8_read( &ps2mouse->command_port ) & STATUS_REG_OUTPUT_BUF_FULL ) == 0 ) { }
+ return port8_read( &ps2mouse->data_port );
+}
+
+static void send_command( ps2mouse_t *ps2mouse, uint8_t command )
+{
+ while( port8_read( &ps2mouse->command_port ) & STATUS_REG_INPUT_BUF_FULL ) { }
+ port8_write( &ps2mouse->command_port, command );
+}
+
+static void write_data( ps2mouse_t *ps2mouse, uint8_t data )
+{
+ while( port8_read( &ps2mouse->command_port ) & STATUS_REG_INPUT_BUF_FULL ) { }
+ port8_write( &ps2mouse->data_port, data );
+}
+
+static void read_ack( ps2mouse_t *ps2mouse )
+{
+ uint8_t data = read_data( ps2mouse );
+ if( data == 0xFA ) {
+ return;
+ } else {
+ printf( "ERR PS/2 mouse: acknoledgment failed 0x%X\n", data );
+ }
+}
+
+static void set_sample_rate( ps2mouse_t *ps2mouse, uint8_t samples )
+{
+ send_command( ps2mouse, COMMAND_SEND_TO_PORT2 );
+ write_data( ps2mouse, MOUSE_COMMAND_SET_SAMPLE_RATE );
+ read_ack( ps2mouse );
+
+ send_command( ps2mouse, COMMAND_SEND_TO_PORT2 );
+ write_data( ps2mouse, samples );
+ read_ack( ps2mouse );
+}
+
+static ps2mouse_vtable_t const ps2mouse_vtable = {
+ {
+ {
+ ps2mouse_activate,
+ ps2mouse_deactivate,
+ mouse_deinit,
+ ps2mouse_print_info
+ },
+ mouse_set_resolution,
+ mouse_set_position
+ }
+};
+
+void ps2mouse_init( ps2mouse_t *ps2mouse, mouse_event_handler_t handler, interrupt_t *interrupt, void *context )
+{
+ memset( ps2mouse, 0, sizeof( ps2mouse_t ) );
+
+ mouse_init( (mouse_t *)ps2mouse, handler, interrupt, context );
+
+ ps2mouse->nof_packets = DEFAULT_NOF_PACKETS;
+
+ port8_init( &ps2mouse->command_port, 0x64 );
+ port8_init( &ps2mouse->data_port, 0x60 );
+
+ ((driver_t *)ps2mouse)->vtable = (driver_vtable_t *)&ps2mouse_vtable;
+}
+
+void ps2mouse_activate( void *obj )
+{
+ puts( "Activating driver for PS/2 mouse.." );
+
+ driver_t *driver = obj;
+ ps2mouse_t *ps2mouse = obj;
+
+ // enable port 2
+ send_command( ps2mouse, COMMAND_ENABLE_PORT2 );
+
+ // enable interrupts for port 2
+ send_command( ps2mouse, COMMAND_GET_STATE );
+ uint8_t status = read_data( ps2mouse );
+ status |= STATUS_CONTROL_CONFIG_ENABLE_IRQ_PORT2;
+ status &= ~STATUS_CONTROL_CONFIG_CLOCK_PORT2;
+ send_command( ps2mouse, COMMAND_SET_STATE );
+ write_data( ps2mouse, status );
+
+ // detecting mouse wheel (and 4th data packet)
+ set_sample_rate( ps2mouse, 200 );
+ set_sample_rate( ps2mouse, 100 );
+ set_sample_rate( ps2mouse, 80 );
+ send_command( ps2mouse, COMMAND_SEND_TO_PORT2 );
+ write_data( ps2mouse, MOUSE_COMMAND_GET_DEVICE_ID );
+ read_ack( ps2mouse );
+ uint8_t id = read_data( ps2mouse );
+ printf( "PS/2 mouse model id is 0x%X\n", id );
+ if( id == 0x03 ) {
+ ps2mouse->nof_packets = 4;
+ }
+
+ // set mouse defaults
+// send_command( ps2mouse, COMMAND_SEND_TO_PORT2 );
+// write_data( ps2mouse, MOUSE_COMMAND_SET_DEFAULTS );
+
+ interrupt_handler_init( &ps2mouse->interrupt_handler, IRQ_BASE + 0x0C, driver->interrupt, ps2mouse_handle_interrupt, obj );
+ interrupts_register_interrupt_handler( ps2mouse->interrupt_handler );
+
+ // enable mouse on second port
+ send_command( ps2mouse, COMMAND_SEND_TO_PORT2 );
+ write_data( ps2mouse, MOUSE_COMMAND_ENABLE_DATAREPORTING );
+ read_ack( ps2mouse );
+}
+
+void ps2mouse_deactivate( void *obj )
+{
+ puts( "Dectivating driver for PS/2 mouse.." );
+
+ ps2mouse_t *ps2mouse = obj;
+
+ send_command( ps2mouse, COMMAND_DISABLE_PORT2 );
+}
+
+uint32_t ps2mouse_handle_interrupt( interrupt_handler_t *handler, uint32_t esp )
+{
+ ps2mouse_t *ps2mouse = (ps2mouse_t *)handler->driver;
+
+ uint8_t status = port8_read( &ps2mouse->command_port );
+ if( !( status & STATUS_REG_OUTPUT_BUF2_FULL ) ) {
+ return esp;
+ }
+
+ ps2mouse->buf[ps2mouse->offset] = port8_read( &ps2mouse->data_port );
+
+#ifdef DEBUG
+ printf( "PS2 MOUSE: %d 0x%X\n", ps2mouse->offset, ps2mouse->buf[ps2mouse->offset] );
+#endif
+
+ switch( ps2mouse->offset ) {
+ case 0:
+ if( ps2mouse->buf[0] & MOUSE_BYTE1_ID_BIT ) {
+ for( int i = 0; i < 3; i++ ) {
+ if( ( ps2mouse->buf[0] & ( 0x01 << i ) ) != ( ps2mouse->buttons & ( 0x01 << i ) ) ) {
+ mouse_event_t event;
+ event.button = i + 1;
+ if( ps2mouse->buttons & ( 0x01 << i ) ) {
+ event.type = MOUSE_EVENT_TYPE_BUTTON_UP;
+ } else {
+ event.type = MOUSE_EVENT_TYPE_BUTTON_DOWN;
+ }
+ event.cursor_x = ps2mouse->base.cursor_x;
+ event.cursor_y = ps2mouse->base.cursor_y;
+ ps2mouse->base.handler( &event, ps2mouse->base.base.context );
+ }
+ }
+ ps2mouse->buttons = ps2mouse->buf[0];
+ }
+ break;
+
+ case 1:
+ // delay evaluation of move events till second byte
+ break;
+
+ case 2:
+ if( ps2mouse->buf[1] !=0 || ps2mouse->buf[2] != 0 ) {
+
+ mouse_event_t event;
+ event.type = MOUSE_EVENT_TYPE_MOVE;
+ event.old_cursor_x = ps2mouse->base.cursor_x;
+ event.old_cursor_y = ps2mouse->base.cursor_y;
+
+ ps2mouse->base.cursor_x += (int8_t)ps2mouse->buf[1];
+ ps2mouse->base.cursor_y -= (int8_t)ps2mouse->buf[2];
+ if( ps2mouse->base.cursor_x < 0 ) {
+ ps2mouse->base.cursor_x = 0;
+ }
+ if( ps2mouse->base.cursor_x > ps2mouse->base.res_x - 1 ) {
+ ps2mouse->base.cursor_x = ps2mouse->base.res_x - 1;
+ }
+ if( ps2mouse->base.cursor_y < 0 ) {
+ ps2mouse->base.cursor_y = 0;
+ }
+ if( ps2mouse->base.cursor_y > ps2mouse->base.res_y - 1 ) {
+ ps2mouse->base.cursor_y = ps2mouse->base.res_y - 1;
+ }
+
+ event.cursor_x = ps2mouse->base.cursor_x;
+ event.cursor_y = ps2mouse->base.cursor_y;
+
+ ps2mouse->base.handler( &event, ps2mouse->base.base.context );
+ }
+
+ break;
+
+ case 3:
+ // TODO: read fourth data packet, but don't handle
+ // it yet
+ break;
+ }
+
+ // advance offset
+ ps2mouse->offset = ( ps2mouse->offset + 1 ) % ps2mouse->nof_packets;
+
+ return esp;
+}
+
+void ps2mouse_print_info( void *obj )
+{
+ puts( "PS/2 mouse driver" );
+}
+
diff --git a/src/drivers/hdi/ps2/ps2mouse.h b/src/drivers/hdi/ps2/ps2mouse.h
new file mode 100644
index 0000000..4c59089
--- /dev/null
+++ b/src/drivers/hdi/ps2/ps2mouse.h
@@ -0,0 +1,35 @@
+#ifndef PS2MOUSE_H
+#define PS2MOUSE_H
+
+#include "string.h"
+
+#include "interrupts.h"
+#include "port.h"
+
+#include "mouse.h"
+
+#define MAX_NOF_MOUSE_PACKETS 5
+
+typedef struct {
+ mouse_t base;
+ port8_t command_port;
+ port8_t data_port;
+ int nof_packets; // 3 or more mouse packets
+ uint8_t buf[MAX_NOF_MOUSE_PACKETS];
+ uint8_t buttons;
+ uint8_t offset;
+ interrupt_handler_t interrupt_handler;
+} ps2mouse_t;
+
+typedef struct {
+ mouse_vtable_t base;
+} ps2mouse_vtable_t;
+
+void ps2mouse_init( ps2mouse_t *mouse, mouse_event_handler_t handler, interrupt_t *interrupt, void *context );
+void ps2mouse_activate( void *obj );
+void ps2mouse_deactivate( void *obj );
+void ps2mouse_print_info( void *obj );
+
+uint32_t ps2mouse_handle_interrupt( interrupt_handler_t *handler, uint32_t esp );
+
+#endif // PS2MOUSE_H
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index d708850..4314ca8 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -12,7 +12,7 @@
#include "interrupts.h"
#include "driver.h"
#include "keyboard.h"
-#include "mouse.h"
+#include "ps2mouse.h"
#include "pci.h"
#include "memorymanagement.h"
@@ -133,9 +133,10 @@ void kernel_main( void )
keyboard_init( global_context.keyboard, &handle_keyboard_event, &interrupt, (void *)&global_context );
driver_manager_add_driver( &global_context.driver_manager, (driver_t *)global_context.keyboard );
- global_context.mouse = (mouse_t *)malloc( sizeof( mouse_t ) );
- mouse_init( global_context.mouse, &handle_mouse_event, &interrupt, (void *)&global_context );
- mouse_set_resolution( global_context.mouse, global_context.vga_text.res_x, global_context.vga_text.res_y );
+ global_context.mouse = (mouse_t *)malloc( sizeof( ps2mouse_t ) );
+ ps2mouse_init( (ps2mouse_t *)global_context.mouse, &handle_mouse_event, &interrupt, (void *)&global_context );
+ ((mouse_vtable_t *)(global_context.mouse->base.vtable))->set_resolution( global_context.mouse, global_context.vga_text.res_x, global_context.vga_text.res_y );
+
driver_manager_add_driver( &global_context.driver_manager, (driver_t *)global_context.mouse );
// dynamically detected and registered drivers
@@ -372,7 +373,7 @@ static void switch_to_graphics_mode( global_context_t *global_context )
text_widget_init( &global_context->widget3, (widget_t *)&global_context->window3, 1, 1, global_context->window3.base.base.w - 2, global_context->window3.base.base.h - 2, VGA_COLOR_RED, s );
((composite_widget_vtable_t *)global_context->window3.base.base.vtable)->add_child( (composite_widget_t *)&global_context->window3, (widget_t *)&global_context->widget3 );
- mouse_set_resolution( mouse, vga->mode.x, vga->mode.y );
+ ((mouse_vtable_t *)(mouse->base.vtable))->set_resolution( mouse, vga->mode.x, vga->mode.y );
// enable Z buffering
vga_use_z_buffer( global_context->vga, true );
@@ -391,7 +392,7 @@ static void switch_to_text_mode( global_context_t *global_context )
if( vga_set_mode( vga, vga_make_mode( VGA_MODE_TYPE_TEXT, 640, 480, 4 ) ) ) {
vga_text_set_cursor( vga_text, vga_text->cursor_x, vga_text->cursor_y );
- mouse_set_resolution( mouse, vga_text->res_x, vga_text->res_y );
+ ((mouse_vtable_t *)(mouse->base.vtable))->set_resolution( mouse, vga_text->res_x, vga_text->res_y );
global_context->mode = MODE_TEXT;
}
}