/* 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"); }