--- /dev/null
+#include <stdint.h>
+
+#include "kernel.h"
+#include "kbd.h"
+#include "interrupt.h"
+#include "tty.h"
+#include "pic.h"
+#include "ioport.h"
+
+static struct interrupt_handler keyboard;
+
+static unsigned char keymap[128] = {
+ 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
+ '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
+ 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
+ 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 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 unsigned char keymap_shift[128] = {
+ 0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\b',
+ '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n',
+ 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~',
+ 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 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 unsigned int kbd_state = 0;
+
+static unsigned char keyboard_decode(unsigned char scancode) {
+ if (scancode & 0x80) {
+ /* break */
+ scancode = scancode & 0x7F;
+ if (scancode == 0x2A || scancode == 0x36) {
+ /* left or right shift */
+ kbd_state = 0;
+ }
+ return 0;
+ } else {
+ if (scancode == 0x2A || scancode == 0x36) {
+ kbd_state = 1;
+ return 0;
+ }
+
+ if (kbd_state == 1) {
+ return keymap_shift[scancode];
+ } else {
+ return keymap[scancode];
+ }
+ }
+}
+
+static void keyboard_handler(struct interrupt_context *c, void *unused) {
+ unsigned char code;
+ unsigned char scancode;
+
+ scancode = inport8(0x60);
+
+ code = keyboard_decode(scancode);
+
+ /* TODO deliver to process with console open */
+ /* will need a notion of 'foreground' and 'background' processes */
+ /* might make sense to just hand it off to whatever terminal it is
+ * attached to
+ */
+ if(code) {
+ printk("%c", code);
+ }
+ code = scancode;
+}
+
+void init_keyboard() {
+ keyboard.handler = keyboard_handler;
+ keyboard.context = 0;
+
+ interrupt_add_handler(IRQ1, &keyboard);
+}