#include #include #include #ifdef __TESTING__ #include #include #endif #include #include bool is_shift_down = false; queue kb_cmd_queue; // current plan is to create a a multi d array // // // 16 entries each for each scan code... so // 0x01..0x0F (15)/ this is the top row, so esc - 1..0, etc // 0x10..0x1F (16) ... // 0x20..0x2F ... // these arrays will keep a 0/1 flag to see if these keys are pressed // as a stort of state machine // this will also let us tell multiple keys pressed // // another more simple version, which i could start with // // is do a Single character as currently pressed // and a bitflag we can mask for leftshift, leftctrl, right shift, right ctrl, alt, etc being pressed down // // // struct keyboard_state keyb_state; void init_kb(void) { #ifdef __TESTING__ puts("Initializing keyboard driver!"); #endif keyb_state.ready = false; keyb_state.waiting_for_commands = true; init_queue(&kb_cmd_queue); keyb_state.leds = 0; keyb_state.flags = 0; queue_kb_command(KEYB_CMD_ENABLE_SCANNING); queue_kb_command(KEYB_CMD_SET_TYPEMATIC); queue_kb_command(0x1F); queue_kb_command(KEYB_CMD_DO_SCAN_CODE); /** * TODO: look into this further, * this is setting scan code 2, but the scan code this results in (on my hardware) is scan code set 1 according to https://wiki.osdev.org/PS/2_Keyboard */ queue_kb_command(0x2); // lets use scan code set 1 send_kb_commands(); keyb_state.ready = true; keyb_state.waiting_for_commands = false; #ifdef __TESTING__ puts("Initialized keyboard driver!"); #endif } void queue_kb_command(uint8_t command) {enqueue(&kb_cmd_queue, command);} void send_kb_commands(void) { int i; uint8_t resp, cmd; while (!queue_is_empty(&kb_cmd_queue)) { cmd = queue_peek(&kb_cmd_queue); for (i = 0; i < KEYB_CMD_RETRIES; i++) { outb(KEYB_PORT, cmd); io_wait(); resp = inb(KEYB_PORT); io_wait(); switch(resp) { case KEYB_RESP_ACK: break; case KEYB_RESP_RESEND: continue; default: break; } } dequeue(&kb_cmd_queue); } } kb_key_code_t decode_scancode(uint8_t scancode) { switch (scancode) { case KEYB_RESP_ERR: case KEYB_RESP_SELF_TEST_PASSED: case KEYB_RESP_ECHO: case KEYB_RESP_ACK: case KEYB_RESP_SELF_TEST_FAILED: case KEYB_RESP_SELF_TEST_FAILED_TWO: case KEYB_RESP_RESEND: case KEYB_RESP_ERR_TWO: keyb_state.waiting_for_commands = false; return KEY_NONE; default: keyb_state.waiting_for_commands = false; return (kb_key_code_t) scancode; } } key_press_t do_keypress(kb_key_code_t keycode) { key_press_t packet; if (!keyb_state.ready || keycode == KEY_NONE) { packet.key_code = KEY_NONE; return packet; } if (keycode >= KEY_ESC_R) { packet.key_code = keycode - KEY_PRESS_RELEASE_DIFF; packet.release = true; } else { packet.key_code = keycode; packet.release = false; } switch (keycode) { case KEY_LEFT_SHIFT: keyb_state.flags |= (STATUS_FLAG_LSHIFT); break; case KEY_LEFT_SHIFT_R: keyb_state.flags &= ~(STATUS_FLAG_LSHIFT); break; case KEY_RIGHT_SHIFT: keyb_state.flags |= (STATUS_FLAG_RSHIFT); break; case KEY_RIGHT_SHIFT_R: keyb_state.flags &= ~(STATUS_FLAG_RSHIFT); break; case KEY_LEFT_CTRL: keyb_state.flags |= (STATUS_FLAG_CTRL); break; case KEY_LEFT_CTRL_R: keyb_state.flags &= ~(STATUS_FLAG_CTRL); break; case KEY_LEFT_ALT: keyb_state.flags |= (STATUS_FLAG_ALT); break; case KEY_LEFT_ALT_R: keyb_state.flags &= ~(STATUS_FLAG_ALT); break; case KEY_CAPSLOCK: keyb_state.flags ^= (STATUS_FLAG_CAPS_LOCK); keyb_state.leds ^= (KEYB_LED_CAP_LCK); queue_kb_command(KEYB_CMD_SET_LEDS); queue_kb_command(keyb_state.leds); break; case KEY_NUMLOCK: keyb_state.flags ^= (STATUS_FLAG_NUM_LOCK); keyb_state.leds ^= (KEYB_LED_NUM_LCK); queue_kb_command(KEYB_CMD_SET_LEDS); queue_kb_command(keyb_state.leds); break; case KEY_SCROLLLOCK: keyb_state.flags ^= (STATUS_FLAG_NUM_LOCK); keyb_state.leds ^= (KEYB_LED_SCRL_LCK); queue_kb_command(KEYB_CMD_SET_LEDS); queue_kb_command(keyb_state.leds); break; // case KEY_INSERT TODO: this shit baby default: break; } send_kb_commands(); packet.flags = keyb_state.flags; return packet; } /** * shift * ctrl * alt * caps * num * scroll */