#include #include "panic.h" #include "util.h" static uint32_t *kbd_in_pointer; static uint32_t *kbd_out_pointer; #define KBD_BUFFER_LENGTH 1024 static uint32_t kbd_buffer[KBD_BUFFER_LENGTH]; static uint32_t mod_mask; enum { PS2_CMD = 0x64, PS2_DATA = 0x60 }; enum { PS2C_READ_CONFIG = 0x20, PS2C_WRITE_CONFIG = 0x60, PS2C_DISABLE = 0xad, PS2C_ENABLE = 0xae }; enum { PS2S_CODE_READY = 0x01 }; enum { PS2G_XT_COMPAT = 0x40 }; void init_kbd() { outb(PS2_CMD, PS2C_READ_CONFIG); uint8_t config = inb(PS2_DATA); outb(PS2_CMD, PS2C_WRITE_CONFIG); outb(PS2_DATA, config | PS2G_XT_COMPAT); kbd_in_pointer = kbd_buffer; kbd_out_pointer = kbd_buffer; mod_mask = 0; } uint32_t get_key_code() { if (kbd_in_pointer == kbd_out_pointer) return 0; uint32_t code = *kbd_out_pointer; if (++kbd_out_pointer == kbd_buffer + KBD_BUFFER_LENGTH) kbd_out_pointer = kbd_buffer; return code; } enum { MOD_LSHIFT = 0x00100, MOD_RSHIFT = 0x00200, MOD_CAPS = 0x00400, MOD_INSERT = 0x00800, MOD_NUMPAD = 0x01000, MOD_SCROLL = 0x02000, MOD_LALT = 0x04000, MOD_RALT = 0x08000, MOD_LCTRL = 0x10000, MOD_RCTRL = 0x20000, MOD_LMETA = 0x40000, MOD_RMETA = 0x80000 }; enum { CODE_CAPS = 0x80, CODE_INSERT, CODE_NUMPAD, CODE_SCROLL, CODE_LSHIFT, CODE_RSHIFT, CODE_LALT, CODE_RALT, CODE_LCTRL, CODE_RCTRL, CODE_LMETA, CODE_RMETA, /* 0x8c - 0x97 reserved */ /* 0x98 - 0x9f unassigned */ CODE_F1 = 0xa0, CODE_F2, CODE_F3, CODE_F4, CODE_F5, CODE_F6, CODE_F7, CODE_F8, CODE_F9, CODE_F10, CODE_F11, CODE_F12, /* 0xac - 0xaf unassigned */ CODE_NUM0 = 0xb0, CODE_NUM1, CODE_NUM2, CODE_NUM3, CODE_NUM4, CODE_NUM5, CODE_NUM6, CODE_NUM7, CODE_NUM8, CODE_NUM9, CODE_NTIMES, CODE_NPLUS, CODE_NENTER, CODE_NMINUS, CODE_NDOT, CODE_NSLASH, /* 0xc0 unassigned */ CODE_DELETE, CODE_HOME, CODE_END, CODE_PUP, CODE_PDOWN, CODE_UP, CODE_DOWN, CODE_LEFT, CODE_RIGHT, CODE_ESC, CODE_MENU, CODE_PAUSE, CODE_PRSCR, /* 0xce - 0xef unassigned */ CODE_END_LSHIFT = 0xf0, CODE_END_RSHIFT, CODE_END_LALT, CODE_END_RALT, CODE_END_LCTRL, CODE_END_RCTRL, CODE_END_LMETA, CODE_END_RMETA }; static const uint32_t mod_bits[] = { MOD_CAPS, MOD_INSERT, MOD_NUMPAD, MOD_SCROLL, MOD_LSHIFT, MOD_RSHIFT, MOD_LALT, MOD_RALT, MOD_LCTRL, MOD_RCTRL, MOD_LMETA, MOD_RMETA }; static const uint32_t *const unmod_bits = mod_bits + 4; //in these tables, 0x00 represents an unknown key, // and 0xff represents a key release. static const uint8_t codes[] = { 0, CODE_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', CODE_LCTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', CODE_LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', CODE_RSHIFT, CODE_NTIMES, CODE_LALT, ' ', CODE_CAPS, CODE_F1, CODE_F2, CODE_F3, CODE_F4, CODE_F5, CODE_F6, CODE_F7, CODE_F8, CODE_F9, CODE_F10, CODE_NUMPAD, CODE_SCROLL, CODE_NUM7, CODE_NUM8, CODE_NUM9, CODE_NMINUS, CODE_NUM4, CODE_NUM5, CODE_NUM6, CODE_NPLUS, CODE_NUM1, CODE_NUM2, CODE_NUM3, CODE_NUM0, CODE_NDOT, 0, 0, 0, CODE_F11, CODE_F12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, CODE_END_LCTRL, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, CODE_END_LSHIFT, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, CODE_END_RSHIFT, 0xff, CODE_END_LALT, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const uint8_t codes_e0[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CODE_NENTER, CODE_RCTRL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CODE_NSLASH, 0, 0, CODE_RALT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CODE_HOME, CODE_UP, CODE_PUP, 0, CODE_LEFT, 0, CODE_RIGHT, 0, CODE_END, CODE_DOWN, CODE_PDOWN, CODE_INSERT, CODE_DELETE, 0, 0, 0, 0, 0, 0, 0, CODE_LMETA, CODE_RMETA, CODE_MENU, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, CODE_END_RCTRL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0, 0, CODE_END_RALT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0, 0xff, 0, 0xff, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, CODE_END_LMETA, CODE_END_RMETA, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; void on_kbd_isr() { while (inb(PS2_CMD) & PS2S_CODE_READY) { uint8_t code = inb(PS2_DATA); if (code == 0xe1) { code = inb(PS2_DATA); if (code == 0x1d) { if (inb(PS2_DATA) != 0x45) code = 0; else code = CODE_PAUSE; } else if (code == 0x9d) { if (inb(PS2_DATA) != 0xc5) code = 0; else code = 0xff; } else code = 0; } else if (code == 0xe0) { code = inb(PS2_DATA); if (code == 0x2a) { if ((inb(PS2_DATA) != 0xe0) || (inb(PS2_DATA) != 0x37)) code = 0; else code = CODE_PRSCR; } else if (code == 0xb7) { if ((inb(PS2_DATA) != 0xe0) || (inb(PS2_DATA) != 0xaa)) code = 0; else code = 0xff; } else code = codes_e0[code]; } else code = codes[code]; if (!code) PANIC("Unknown scancode."); if (code < 0xf0) *kbd_in_pointer++ = mod_mask | code; if ((code >= 0x80) && (code <= 0x83)) mod_mask ^= mod_bits[code & 0x03]; else if ((code >= 0x84) && (code <= 0x8b)) mod_mask |= mod_bits[code & 0x0f]; else if (code >= 0xf0) mod_mask &= ~unmod_bits[code & 0x0f]; } }