summaryrefslogtreecommitdiff
path: root/src/drivers/hdi/ps2/keyboard.c
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-07-20 09:31:30 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-07-20 09:31:30 +0200
commit7eae4edb86fc65b2e99bf81757aeb00392d8a60d (patch)
tree2ee5c92be2ca55dcd30dc3e9632bcfa4dfd9a095 /src/drivers/hdi/ps2/keyboard.c
parent43fcc1ca57149c5a87502f0c23a2c85e4d28264a (diff)
downloadabaos-7eae4edb86fc65b2e99bf81757aeb00392d8a60d.tar.gz
abaos-7eae4edb86fc65b2e99bf81757aeb00392d8a60d.tar.bz2
added a virtual keyboard driver interface, made the PS/2 keyboard a specialization of it
Diffstat (limited to 'src/drivers/hdi/ps2/keyboard.c')
-rw-r--r--src/drivers/hdi/ps2/keyboard.c331
1 files changed, 0 insertions, 331 deletions
diff --git a/src/drivers/hdi/ps2/keyboard.c b/src/drivers/hdi/ps2/keyboard.c
deleted file mode 100644
index 9c5a246..0000000
--- a/src/drivers/hdi/ps2/keyboard.c
+++ /dev/null
@@ -1,331 +0,0 @@
-#include "keyboard.h"
-#include "stdio.h"
-
-// status register on command port (read)
-#define STATUS_REG_OUTPUT_BUF_FULL 0x01
-#define STATUS_REG_INPUT_BUF_FULL 0x02
-
-// generic PS/2 commands
-#define COMMAND_GET_STATE 0x20
-#define COMMAND_SET_STATE 0x60
-#define COMMAND_DISABLE_PORT1 0xAD
-#define COMMAND_ENABLE_PORT1 0xAE
-
-// status control register flags
-#define STATUS_CONTROL_CONFIG_ENABLE_IRQ_PORT1 0x01
-#define STATUS_CONTROL_CONFIG_CLOCK_PORT1 0x10
-
-// keyboard specific commands, PSAUX1
-#define KBD_COMMAND_SET_LEDS 0xED
-#define KBD_SET_SCANCODE 0xF0
-#define KBD_ACTIVATE 0xF4
-
-// keyboard LED status codes
-#define KBD_LED_SCROLL_LOCK_ON 0x01
-#define KBD_LED_NUM_LOCK_ON 0x02
-#define KBD_LED_CAPS_LOCK_ON 0x04
-#define KBD_LED_ALL_OFF 0x00
-#define KBD_LED_ALL_ON KBD_LED_SCROLL_LOCK_ON | KBD_LED_NUM_LOCK_ON | KBD_LED_CAPS_LOCK_ON
-
-// keyboard scan codes
-#define KBD_SCANCODE_1 0x01
-#define KBD_SCANCODE_2 0x02
-#define KBD_SCANCODE_3 0x03
-
-#undef DEBUG
-
-static uint8_t read_data( keyboard_t *keyboard )
-{
- while( ( port8_read( &keyboard->command_port ) & STATUS_REG_OUTPUT_BUF_FULL ) == 0 ) { }
- return port8_read( &keyboard->data_port );
-}
-
-static void send_command( keyboard_t *keyboard, uint8_t command )
-{
- while( port8_read( &keyboard->command_port ) & STATUS_REG_INPUT_BUF_FULL ) { }
- port8_write( &keyboard->command_port, command );
-}
-
-static void write_data( keyboard_t *keyboard, uint8_t data )
-{
- while( port8_read( &keyboard->command_port ) & STATUS_REG_INPUT_BUF_FULL ) { }
- port8_write( &keyboard->data_port, data );
-}
-
-/*
-static void read_ack( keyboard_t *keyboard )
-{
- uint8_t data = read_data( keyboard );
- if( data == 0xFA ) {
- return;
- } else {
- kernel_warn( "ERR PS/2 keyboard: acknoledgment failed 0x%X\n", data );
- }
-}
-*/
-
-static keyboard_vtable_t const keyboard_vtable = {
- {
- keyboard_activate,
- keyboard_deactivate,
- keyboard_deinit,
- keyboard_print_info
- }
-};
-
-void keyboard_init( keyboard_t *keyboard, keyboard_event_handler_t handler, interrupt_t *interrupt, void *context )
-{
- memset( keyboard, 0, sizeof( keyboard_t ) );
-
- driver_init( (driver_t *)keyboard, DRIVER_TYPE_KEYBOARD, interrupt, context );
-
- port8_init( &keyboard->command_port, 0x64 );
- port8_init( &keyboard->data_port, 0x60 );
-
- keyboard->shift = false;
- keyboard->handler = handler;
-
- ((driver_t *)keyboard)->vtable = (driver_vtable_t *)&keyboard_vtable;
-}
-
-void keyboard_activate( void *obj )
-{
- puts( "Activating driver for PS/2 keyboard.." );
-
- driver_t *driver = obj;
- keyboard_t *keyboard = obj;
-
- // first switch off port 1
- send_command( keyboard, COMMAND_DISABLE_PORT1 );
-
- // consume character pressed before executing the kernel
- while( port8_read( &keyboard->command_port ) & STATUS_REG_OUTPUT_BUF_FULL ) {
- port8_read( &keyboard->data_port );
- }
-
- // enable interrupts for port 1
- send_command( keyboard, COMMAND_GET_STATE );
- uint8_t status = read_data( keyboard );
- status |= STATUS_CONTROL_CONFIG_ENABLE_IRQ_PORT1;
- status &= ~STATUS_CONTROL_CONFIG_CLOCK_PORT1;
- send_command( keyboard, COMMAND_SET_STATE );
- write_data( keyboard, status );
-
- // disable all LEDs on keyboard
- //~ send_command( keyboard, KBD_COMMAND_SET_LEDS );
- //~ write_data( keyboard, KBD_LED_ALL_ON );
-
- // set scan code
- //~ send_command( keyboard, KBD_SET_SCANCODE );
- //~ write_data( keyboard, KBD_SCANCODE_2 );
-
- // activate keyboard
- //send_command( keyboard, KBD_ACTIVATE );
- //read_ack( keyboard );
-
- interrupt_handler_init( &keyboard->interrupt_handler, IRQ_BASE + 0x01, driver->interrupt, keyboard_handle_interrupt, obj );
- interrupts_register_interrupt_handler( keyboard->interrupt_handler );
-
- // enable port 1
- send_command( keyboard, COMMAND_ENABLE_PORT1 );
-}
-
-void keyboard_deactivate( void *obj )
-{
- puts( "Deactivating driver for PS/2 keyboard.." );
-
- keyboard_t *keyboard = obj;
-
- send_command( keyboard, COMMAND_DISABLE_PORT1 );
-}
-
-void keyboard_deinit( void *obj )
-{
- // nothing to do
-}
-
-typedef enum {
- KEYCODE_UNKNOWN,
- KEYCODE_ASCII_CHAR,
- KEYCODE_ESC
-} keycode_type_t;
-
-typedef struct {
- keycode_type_t type;
- char c;
-} keycode_t;
-
-typedef enum {
- SCANCODE_SET_NORMAL = 0,
- SCANCODE_SET_SHIFT = 1,
- SCANCODE_SET_E0 = 2,
- SCANCODE_SET_E1 = 3
-} scancode_set_t;
-
-// TODO: here come the translations to other keyboard layouts,
-// assumming a QWERTY US keyboard here..
-static char scancode_map[4][128] = {
- {
- 0, 0, '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', '-', '=', '\b', 0,
- 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
- 'o', 'p', '[', ']', '\n', 0, 'a', 's',
- 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
- '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
- 'b', 'n', 'm', ',', '.', '/', 0, 0,
- 0, ' ', 0, 0, 0, 0, 0, 0,
- 0, 0, 0 , 0 , 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0 , 0 , 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0 , 0 , 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0 , 0 , 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- },
- {
- 0, 0, '!', '@', '#', '$', '%', '^',
- '&', '*', '(', ')', '_', '+', 0, 0,
- 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',
- 'O', 'P', '{', '}', '\n', 0, 'A', 'S',
- 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
- '"', '~', 0, '|', 'Z', 'X', 'C', 'V',
- 'B', 'N', 'M', '<', '>', '?', 0, 0,
- 0, ' ', 0, 0, 0, 0, 0, 0,
- 0, 0, 0 , 0 , 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0 , 0 , 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0 , 0 , 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0 , 0 , 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- },
- {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- },
- {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0
- }
-};
-
-#define SCAN_CODE_ESC 0x01
-
-static keycode_t scancode_to_keycode( scancode_set_t set, uint8_t scan_code )
-{
- keycode_t key_code;
- key_code.type = KEYCODE_UNKNOWN;
-
- key_code.c = scancode_map[set][scan_code];
- if( key_code.c > 0 ) {
- key_code.type = KEYCODE_ASCII_CHAR;
- }
-
- if( scan_code == SCAN_CODE_ESC ) {
- key_code.type = KEYCODE_ESC;
- }
-
- return key_code;
-}
-
-#define SCAN_CODE_BREAK_CODE 0x80
-#define SCAN_CODE_LEFT_SHIFT 0x2A
-#define SCAN_CODE_RIGHT_SHIFT 0x36
-
-uint32_t keyboard_handle_interrupt( interrupt_handler_t *handler, uint32_t esp )
-{
- keyboard_t *keyboard = (keyboard_t *)handler->driver;
-
- // we can only wake up on IRQ1 because we don't send commands
- // after initialization
- uint8_t scan_code = port8_read( &keyboard->data_port );
-
- // we get break code when the high bit is set, so the
- // the key is released
- bool break_code = false;
- if( scan_code & SCAN_CODE_BREAK_CODE ) {
- break_code = true;
- }
-
- scan_code &= ~SCAN_CODE_BREAK_CODE;
-
- if( scan_code == SCAN_CODE_LEFT_SHIFT ||
- scan_code == SCAN_CODE_RIGHT_SHIFT ) {
- if( break_code ) {
- keyboard->shift = false;
- } else {
- keyboard->shift = true;
- }
- }
-
- scancode_set_t code_set = SCANCODE_SET_NORMAL;
- if( keyboard->shift ) {
- code_set = SCANCODE_SET_SHIFT;
- }
-
- keycode_t key_code = scancode_to_keycode( code_set, scan_code );
-
-#ifdef DEBUG
- printf( "KBD SCAN:0x%X S:%d B:%d S:%d T:0x%X '%c' 0x%X\n",
- scan_code, code_set, break_code, keyboard->shift,
- key_code.type, key_code.c, key_code.c );
-#endif
-
- keyboard_event_t event;
- if( break_code ) {
- event.type = KEYBOARD_EVENT_TYPE_KEY_RELEASED;
- } else {
- event.type = KEYBOARD_EVENT_TYPE_KEY_PRESSED;
- }
- event.modifiers = 0;
- if( keyboard->shift ) {
- event.modifiers |= KEYBOARD_MODIFIER_SHIFT;
- }
- // TODO: for control, alt, meta, etc.
- event.key = KEYBOARD_KEY_UNKNOWN;
- if( key_code.type == KEYCODE_ASCII_CHAR ) {
- event.key = KEYBOARD_KEY_ASCII;
- event.ascii_key = key_code.c;
- } else if( key_code.type == KEYCODE_ESC ) {
- event.key = KEYBOARD_KEY_ESC;
- }
-
- keyboard->handler( &event, keyboard->base.context );
-
- return esp;
-}
-
-void keyboard_print_info( void *obj )
-{
- puts( "PS/2 keyboard driver" );
-}