summaryrefslogtreecommitdiff
path: root/src/kernel/kbd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/kbd.c')
-rw-r--r--src/kernel/kbd.c410
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
+}