ps2.c (4756B)
1 #include <stdbool.h> 2 #include <stdint.h> 3 #include <arch/x86/io.h> 4 #include "keyboard.h" 5 6 // Mapping table from scancode set 2 standard keys (not multimedia) 7 // to the key codes 8 static enum keyboard_key s2_keycodes[256] = { 9 KEY_UNUSED, KEY_F9, KEY_UNUSED, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12, 10 KEY_UNUSED, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_BACKTICK, KEY_UNUSED, 11 KEY_UNUSED, KEY_ALT, KEY_LSHIFT, KEY_UNUSED, KEY_LCTRL, KEY_Q, KEY_1, KEY_UNUSED, 12 KEY_UNUSED, KEY_UNUSED, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_UNUSED, 13 KEY_UNUSED, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_UNUSED, 14 KEY_UNUSED, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_UNUSED, 15 KEY_UNUSED, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_UNUSED, 16 KEY_UNUSED, KEY_UNUSED, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_UNUSED, 17 KEY_UNUSED, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_UNUSED, 18 KEY_UNUSED, KEY_DOT, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_UNUSED, 19 KEY_UNUSED, KEY_UNUSED, KEY_APOSTROPHE, KEY_UNUSED, KEY_LSQ_BRACKET, KEY_EQUALS, KEY_UNUSED, KEY_UNUSED, 20 KEY_CAPSLOCK, KEY_RSHIFT, KEY_ENTER, KEY_RSQ_BRACKET, KEY_UNUSED, KEY_BACKSLASH, KEY_UNUSED, KEY_UNUSED, 21 KEY_UNUSED, KEY_UNUSED, KEY_BACKSPACE, KEY_UNUSED, KEY_UNUSED, KEY_1_KP, KEY_UNUSED, KEY_4_KP, 22 KEY_7_KP, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_0_KP, KEY_DOT_KP, KEY_2_KP, KEY_5_KP, 23 KEY_6_KP, KEY_8_KP, KEY_ESC, KEY_NUMLOCK, KEY_F11, KEY_PLUS_KP, KEY_3_KP, KEY_MINUS_KP, 24 KEY_TIMES_KP, KEY_9_KP, KEY_SCROLLLOCK, KEY_UNUSED, KEY_UNUSED, KEY_UNUSED, KEY_F7 25 }; 26 27 // All possible states for our keycode finite state machine 28 static void fsm_start(uint8_t); 29 static void fsm_release(uint8_t); 30 static void fsm_multimedia(uint8_t); 31 static void fsm_multimedia_release(uint8_t); 32 static void fsm_print_1(uint8_t); 33 static void fsm_print_2(uint8_t); 34 static void kbd_wait_outbuf(); 35 static void set_scancode(uint8_t); 36 37 38 // FSM: Keep track of the current state of the state machine 39 static void (*current_state)(uint8_t) = fsm_start; 40 41 // The state machine start states for each scancode set 42 // TODO: Currently scancode set 1 and 3 are missing and will trigger 43 // a fault interrupt 44 static void (*scancode_state_starts[3])(uint8_t) = { 0x0, fsm_start, 0x0 }; 45 46 void keyboard_init() { 47 set_scancode(2); 48 } 49 50 void keyboard_irq_handler() { 51 uint8_t scancode; 52 53 kbd_wait_outbuf(); 54 scancode = inb(0x60); 55 current_state(scancode); 56 } 57 58 // Methods for waiting for keyboard 59 static void kbd_wait_outbuf() { 60 // TODO: Can we add some idle loops or is kbd controller so fast? 61 uint8_t status; 62 do { 63 status = inb(0x64); 64 } while ((status & 0x1) == 0); 65 } 66 67 static void kbd_wait_inbuf() { 68 // TODO: Can we add some idle loops or is kbd controller so fast? 69 uint8_t status; 70 do { 71 status = inb(0x64); 72 } while ((status & 0x2) != 0); 73 } 74 75 static void set_scancode(uint8_t scancode_nr) { 76 if (scancode_nr < 1 || scancode_nr > 3) 77 return; 78 79 outb(0x60, 0xf0); 80 kbd_wait_inbuf(); 81 outb(0x60, scancode_nr); 82 kbd_wait_inbuf(); 83 84 // disable translation 85 outb(0x64, 0x20); 86 kbd_wait_outbuf(); 87 uint8_t status = inb(0x60); 88 89 kbd_wait_inbuf(); 90 outb(0x64, 0x60); 91 kbd_wait_inbuf(); 92 outb(0x60, status & 0x3f); 93 94 current_state = scancode_state_starts[scancode_nr - 1]; 95 } 96 97 // FSM function implementation 98 // These functions read scancodes and jump to correct next function 99 static void fsm_start(uint8_t byte) { 100 if (byte == 0xe0) { 101 current_state = fsm_multimedia; 102 } else if (byte == 0xf0) { 103 current_state = fsm_release; 104 } else { 105 if (s2_keycodes[byte] != KEY_UNUSED) { 106 keyboard_fire_event(s2_keycodes[byte], false); 107 } 108 } 109 } 110 111 static void fsm_multimedia(uint8_t byte) { 112 if (byte == 0xf0) { 113 current_state = fsm_multimedia_release; 114 } else if (byte == 0x12) { 115 current_state = fsm_print_1; 116 } else { 117 // TODO: multimedia key byte pressed 118 current_state = fsm_start; 119 } 120 } 121 122 static void fsm_release(uint8_t byte) { 123 if (s2_keycodes[byte] != KEY_UNUSED) { 124 keyboard_fire_event(s2_keycodes[byte], true); 125 } 126 127 current_state = fsm_start; 128 } 129 130 static void fsm_multimedia_release(uint8_t byte) { 131 char *vidmem = (char*) 0xb8000; 132 vidmem[0] = 'x'; 133 // TODO: Multimedia key byte released 134 current_state = fsm_start; 135 } 136 137 static void fsm_print_1(uint8_t byte) { 138 if (byte == 0xe0) { 139 current_state = fsm_print_2; 140 } else { 141 // TODO: Failure 142 } 143 } 144 145 static void fsm_print_2(uint8_t byte) { 146 if (byte == 0x7c) { 147 // TODO key = PRINT pressed 148 current_state = fsm_start; 149 } else { 150 // TODO: Failure 151 } 152 }