164 lines
3.5 KiB
C
164 lines
3.5 KiB
C
/*
|
|
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");
|
|
}
|
|
|
|
|
|
|
|
|