From ee3e51aa1624693217b1a4ae7bfb2730424c08f2 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Tue, 18 Jul 2017 21:23:22 +0200 Subject: added a virtual mouse driver interface, made the PS/2 mouse a specialization of it --- src/Makefile | 13 +- src/drivers/hdi/mouse.c | 65 ++++++++++ src/drivers/hdi/mouse.h | 55 +++++++++ src/drivers/hdi/ps2/mouse.c | 263 ----------------------------------------- src/drivers/hdi/ps2/mouse.h | 68 ----------- src/drivers/hdi/ps2/ps2mouse.c | 246 ++++++++++++++++++++++++++++++++++++++ src/drivers/hdi/ps2/ps2mouse.h | 35 ++++++ src/kernel/kernel.c | 13 +- 8 files changed, 416 insertions(+), 342 deletions(-) create mode 100644 src/drivers/hdi/mouse.c create mode 100644 src/drivers/hdi/mouse.h delete mode 100644 src/drivers/hdi/ps2/mouse.c delete mode 100644 src/drivers/hdi/ps2/mouse.h create mode 100644 src/drivers/hdi/ps2/ps2mouse.c create mode 100644 src/drivers/hdi/ps2/ps2mouse.h (limited to 'src') 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/mouse.h b/src/drivers/hdi/mouse.h new file mode 100644 index 0000000..90417f3 --- /dev/null +++ b/src/drivers/hdi/mouse.h @@ -0,0 +1,55 @@ +#ifndef MOUSE_H +#define MOUSE_H + +#include "driver.h" + +typedef enum { + MOUSE_EVENT_TYPE_BUTTON_UP, + MOUSE_EVENT_TYPE_BUTTON_DOWN, + MOUSE_EVENT_TYPE_MOVE +} mouse_event_type_t; + +typedef enum { + MOUSE_BUTTON_LEFT = 1, + MOUSE_BUTTON_RIGHT = 2, + MOUSE_BUTTON_MIDDLE = 3 +} mouse_button_t; + +typedef struct { + mouse_event_type_t type; + mouse_button_t button; + int32_t old_cursor_x; + int32_t old_cursor_y; + int32_t cursor_x; + int32_t cursor_y; +} mouse_event_t; + +typedef void (*mouse_event_handler_t)( mouse_event_t *event, void *context ); + +typedef struct { + driver_t base; + uint32_t res_x; + uint32_t res_y; + int32_t cursor_x; + int32_t cursor_y; + mouse_event_handler_t 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 ); +void mouse_activate( void *obj ); +void mouse_deactivate( void *obj ); +void mouse_deinit( void *obj ); +void mouse_print_info( void *obj ); + +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 ); + +#endif // MOUSE_H 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/mouse.h b/src/drivers/hdi/ps2/mouse.h deleted file mode 100644 index 1a00b5e..0000000 --- a/src/drivers/hdi/ps2/mouse.h +++ /dev/null @@ -1,68 +0,0 @@ -#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, - MOUSE_EVENT_TYPE_MOVE -} mouse_event_type_t; - -typedef enum { - MOUSE_BUTTON_LEFT = 1, - MOUSE_BUTTON_RIGHT = 2, - MOUSE_BUTTON_MIDDLE = 3 -} mouse_button_t; - -typedef struct { - mouse_event_type_t type; - mouse_button_t button; - int32_t old_cursor_x; - int32_t old_cursor_y; - int32_t cursor_x; - int32_t cursor_y; -} mouse_event_t; - -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; -} mouse_vtable_t; - -void mouse_init( mouse_t *mouse, mouse_event_handler_t handler, interrupt_t *interrupt, void *context ); -void mouse_activate( void *obj ); -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 ); - -uint32_t mouse_handle_interrupt( interrupt_handler_t *handler, uint32_t esp ); - -#endif // MOUSE_H 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; } } -- cgit v1.2.3-54-g00ecf