diff options
Diffstat (limited to 'src/kernel/kbd.c')
-rw-r--r-- | src/kernel/kbd.c | 410 |
1 files changed, 157 insertions, 253 deletions
diff --git a/src/kernel/kbd.c b/src/kernel/kbd.c index 8808b74..29c0350 100644 --- a/src/kernel/kbd.c +++ b/src/kernel/kbd.c @@ -1,14 +1,14 @@ #include <stdint.h> + +#include "window.h" +#include "drive.h" #include "panic.h" +#include "pmap.h" #include "util.h" +#include "kbd.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; +#define SCANTAB_DIR "sys/scantabs" +#define LAYOUT_HARDCODE_TMP "qwerty" enum { PS2_CMD = 0x64, @@ -30,274 +30,178 @@ 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; -} +static uint32_t n_scantabs; -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 -}; +static struct scantab_info { + uint8_t *scantab; + uint8_t prefix_length; + uint8_t prefix[256]; +} *scantabs; 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 = 0xc1, - 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 + ST_ILLEGAL, + ST_SUBTABLE, + ST_FLIP, + ST_SKIP }; -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 -}; +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); -static const uint32_t *const unmod_bits = mod_bits + 4; + //TODO: get layout from some config file + file_id_t stf = drives->get_file(drives, SCANTAB_DIR "/" LAYOUT_HARDCODE_TMP ".sct"); -//in these tables, 0x00 represents an unknown key, -// and 0xff represents a key release. + fmcpy(&n_scantabs, drives, stf, 0, 4); + scantabs = allocate_kernel_pages((sizeof(struct scantab_info) * n_scantabs - 1) / 4096 + 1); + uint32_t fi = 0x10; + void *st_data = allocate_kernel_pages((n_scantabs - 1) / 8 + 1); -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, + for (uint32_t n = 0; n < n_scantabs; ++n) { + uint32_t data_sector; + fmcpy(&data_sector, drives, stf, fi, 4); + drives->load_sector(drives, stf, data_sector, st_data + 512 * n); + scantabs[n].scantab = st_data + 512 * n; - 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 -}; + uint8_t pl; + fmcpy(&pl, drives, stf, fi + 4, 1); + scantabs[n].prefix_length = pl; + fmcpy(scantabs[n].prefix, drives, stf, fi + 5, pl); -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, + fi += 5 + pl; + if (fi & 0xf) + fi = (fi & ~0xf) + 0x10; + } - 0, 0, 0, 0, 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 -}; + drives->free_file(drives, stf); +} -#include "log.h" -uint8_t get_code_byte() { +static inline uint8_t get_next_code_byte() { for (uint32_t spin = 0; spin < 10000000; ++spin) ; return inb(PS2_DATA); } +static enum key_modifiers_t keymods = 0; + void on_kbd_isr() { +//logf(LOG_INFO, "on_kbd_isr()"); while (inb(PS2_CMD) & PS2S_CODE_READY) { - //char nbuf[11]; - uint8_t code = get_code_byte(); - //logsz("code: 0x"); - //u8_hex(code, nbuf); - //logsz(nbuf); - if (code == 0xe1) { - code = get_code_byte(); - //logsz(" 0x"); - //u8_hex(code, nbuf); - //logsz(nbuf); - if (code == 0x1d) { - if (get_code_byte() != 0x45) - code = 0; - else - code = CODE_PAUSE; - } - else if (code == 0x9d) { - if (get_code_byte() != 0xc5) - code = 0; - else - code = 0xff; - } - else - code = 0; + uint8_t code[256]; + uint8_t code_i = 0; + sub_table: + code[code_i] = get_next_code_byte(); + const uint8_t *table; + for (uint32_t i = 0; i < n_scantabs; ++i) { + if (scantabs[i].prefix_length != code_i) + continue; + for (uint8_t j = 0; j < code_i; ++j) + if (scantabs[i].prefix[j] != code[j]) + goto next_table; + table = scantabs[i].scantab; + goto got_table; + next_table:; } - else if (code == 0xe0) { - code = get_code_byte(); - //logsz(" 0x"); - //u8_hex(code, nbuf); - //logsz(nbuf); - if (code == 0x2a) { - if ((get_code_byte() != 0xe0) || - (get_code_byte() != 0x37)) - code = 0; - else - code = CODE_PRSCR; - } - else if (code == 0xb7) { - if ((get_code_byte() != 0xe0) || - (get_code_byte() != 0xaa)) - code = 0; - else - code = 0xff; - } - else - code = codes_e0[code]; + PANIC("Couldn't find scantable"); + + got_table:; + bool is_up = false; + flipped_table:; + uint8_t entry = table[code[code_i]]; + switch (entry) { + case ST_ILLEGAL: + PANIC("Illegal scancode encountered"); + case ST_SUBTABLE: + ++code_i; + goto sub_table; + case ST_FLIP: + if (is_up) + PANIC("Recursive flip in scantable"); + table += 0x100; + is_up = true; + goto flipped_table; + case ST_SKIP: + continue; } - else - code = codes[code]; - //logch('\n'); - - if (!code) - PANIC("Unknown scancode."); + switch ((enum key_id_t)entry) { + case KEY_LEFT_SHIFT: + if (is_up) + keymods &= ~LSHIFT; + else + keymods |= LSHIFT; + break; + case KEY_RIGHT_SHIFT: + if (is_up) + keymods &= ~RSHIFT; + else + keymods |= RSHIFT; + break; + case KEY_LEFT_CONTROL: + if (is_up) + keymods &= ~LCTRL; + else + keymods |= LCTRL; + break; + case KEY_RIGHT_CONTROL: + if (is_up) + keymods &= ~RCTRL; + else + keymods |= RCTRL; + break; + case KEY_LEFT_ALT: + if (is_up) + keymods &= ~LALT; + else + keymods |= LALT; + break; + case KEY_RIGHT_ALT: + if (is_up) + keymods &= ~RALT; + else + keymods |= RALT; + break; + case KEY_LEFT_WIN: + if (is_up) + keymods &= ~LWIN; + else + keymods |= LWIN; + break; + case KEY_RIGHT_WIN: + if (is_up) + keymods &= ~RWIN; + else + keymods |= RWIN; + break; + case KEY_CAPS_LOCK: + if (!is_up) + keymods ^= CAPS; + break; + case KEY_NUM_LOCK: + if (!is_up) + keymods ^= NUM; + break; + case KEY_SCROLL_LOCK: + if (!is_up) + keymods ^= SCROLL; + break; + case KEY_INSERT: + if (!is_up) + keymods ^= INSERT; + break; + default: + break; + } - 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]; + on_action((struct window_action){ + .action_type = is_up ? KEY_UP : KEY_DOWN, + .as_key = (struct key_packet){ + .key_id = entry, + .modifiers = keymods + } + }); } -}
\ No newline at end of file +} |