sos

[unmaintained] experimenting with low level OS development
Log | Files | Refs | README | LICENSE

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 }