diff --git a/kernel/keyboard.c b/kernel/keyboard.c new file mode 100644 index 0000000..da2e8b0 --- /dev/null +++ b/kernel/keyboard.c @@ -0,0 +1,163 @@ +/* +Copyright (C) 2015-2019 The University of Notre Dame +This software is distributed under the GNU General Public License. +See the file LICENSE for details. +*/ + +#include "console.h" +#include "ioports.h" +#include "interrupt.h" +#include "kernel/ascii.h" +#include "kernelcore.h" +#include "event_queue.h" + +#define KEYBOARD_PORT 0x60 + +#define KEYMAP_SHIFT 1 +#define KEYMAP_ALT 2 +#define KEYMAP_CTRL 3 +#define KEYMAP_CAPSLOCK 4 +#define KEYMAP_NUMLOCK 5 +#define KEYMAP_ALPHA 6 +#define KEYMAP_NUMPAD 8 +#define KEYMAP_ALTGR 9 + +/* sent before certain keys such as up, down, left, or right. */ +#define KEYCODE_EXTRA (uint8_t)0xE0 +#define KEYCODE_UP (uint8_t)0x48 +#define KEYCODE_DOWN (uint8_t)0x42 +#define KEYCODE_LEFT (uint8_t)0x4B +#define KEYCODE_RIGHT (uint8_t)0x4D + +#define BUFFER_SIZE 256 + +struct keymap { + char normal; + char shifted; + char ctrled; + char special; +}; + +static struct keymap keymap[] = { +#include "keymap.de.pc.c" +}; + +static int shift_mode = 0; +static int alt_mode = 0; +static int altgr_mode = 0; +static int ctrl_mode = 0; +static int capslock_mode = 0; +static int numlock_mode = 0; + +static void keyboard_interrupt_l2( uint8_t code ) +{ + int direction; + int event; + + if(code & 0x80) { + direction = 0; + event = EVENT_KEY_UP; + code = code & 0x7f; + } else { + direction = 1; + event = EVENT_KEY_DOWN; + } + + struct keymap *k = &keymap[code]; + if(k->special == KEYMAP_SHIFT) { + shift_mode = direction; + } else if(k->special == KEYMAP_ALT) { + alt_mode = direction; + } else if(k->special == KEYMAP_ALTGR) { + // @blab+ ALTGR hack + altgr_mode = direction; + } else if(k->special == KEYMAP_CTRL) { + ctrl_mode = direction; + } else if(k->special == KEYMAP_CAPSLOCK) { + if(direction == 0) capslock_mode = !capslock_mode; + } else if(k->special == KEYMAP_NUMLOCK) { + if(direction == 0) numlock_mode = !numlock_mode; + } else { + if(direction && ctrl_mode && alt_mode && k->normal == ASCII_DEL) { + reboot(); + } else if(capslock_mode) { + if(k->special==KEYMAP_ALPHA && !shift_mode) { + event_queue_post_root(event,k->shifted,0,0); + } else { + event_queue_post_root(event,k->normal,0,0); + } + } else if(numlock_mode) { + if(k->special==KEYMAP_NUMPAD && !shift_mode) { + event_queue_post_root(event,k->shifted,0,0); + } else { + event_queue_post_root(event,k->normal,0,0); + } + } else if(shift_mode) { + event_queue_post_root(event,k->shifted,0,0); + } else if(ctrl_mode) { + event_queue_post_root(event,k->ctrled,0,0); + } else if(altgr_mode) { + // @blab+ ALTGR hack + event_queue_post_root(event,k->special,0,0); + } else { + event_queue_post_root(event,k->normal,0,0); + } + } +} + +static int expect_extra = 0; + +static void keyboard_interrupt(int i, int intr_code) +{ + uint8_t code = inb(KEYBOARD_PORT); + uint8_t c = KEY_INVALID; + + // printf("[%x]",code); + + if(code == KEYCODE_EXTRA) { + expect_extra = 1; + return; + } else if(expect_extra) { + expect_extra = 0; + switch(code) { + // @blab+ ALTGR hack + case 0x38: + case 0xb8: + // keymap: use next reserved row (normally nulled) + // {KEY_INVALID, KEY_INVALID, KEY_INVALID, KEYMAP_ALT},# + // .. + // {KEY_INVALID, KEY_INVALID, KEY_INVALID, KEYMAP_ALTGR}, + c = code+3; + break; + case KEYCODE_UP: + c = KEY_UP; + break; + case KEYCODE_DOWN: + c = KEY_DOWN; + break; + case KEYCODE_LEFT: + c = KEY_LEFT; + break; + case KEYCODE_RIGHT: + c = KEY_RIGHT; + break; + default: + return; + } + } else { + c = code; + } + + keyboard_interrupt_l2(c); +} + +void keyboard_init() +{ + interrupt_register(33, keyboard_interrupt); + interrupt_enable(33); + printf("keyboard: ready\n"); +} + + + +