126 lines
5.9 KiB
C
126 lines
5.9 KiB
C
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include "../panic.h"
|
|
#include "../interrupt/pic.h"
|
|
#include <string.h>
|
|
#include <sys.h>
|
|
|
|
#include "ps2ctrl.h"
|
|
#include "ps2kb.h"
|
|
#include "keycodes.h"
|
|
|
|
#define BUFFER_LEN 16
|
|
|
|
#define KEYCODE_ARRAY_LEN 0x84
|
|
|
|
static uint8_t scancodes[] = {
|
|
// 00/08 01/09 02/0A 03/0B 04/0C 05/0D 06/0E 07/0F
|
|
/*00*/ KEY_NONE, KEY_F9, KEY_NONE, KEY_F5, KEY_F3, KEY_F1, KEY_F2, KEY_F12,
|
|
/*08*/ KEY_NONE, KEY_F10, KEY_F8, KEY_F6, KEY_F4, KEY_TAB, KEY_BACKTICK, KEY_NONE,
|
|
/*10*/ KEY_NONE, KEY_L_ALT, KEY_L_SHIFT, KEY_NONE, KEY_L_CTRL, KEY_Q, KEY_1, KEY_NONE,
|
|
/*18*/ KEY_NONE, KEY_NONE, KEY_Z, KEY_S, KEY_A, KEY_W, KEY_2, KEY_NONE,
|
|
/*20*/ KEY_NONE, KEY_C, KEY_X, KEY_D, KEY_E, KEY_4, KEY_3, KEY_NONE,
|
|
/*28*/ KEY_NONE, KEY_SPACE, KEY_V, KEY_F, KEY_T, KEY_R, KEY_5, KEY_NONE,
|
|
/*30*/ KEY_NONE, KEY_N, KEY_B, KEY_H, KEY_G, KEY_Y, KEY_6, KEY_NONE,
|
|
/*38*/ KEY_NONE, KEY_NONE, KEY_M, KEY_J, KEY_U, KEY_7, KEY_8, KEY_NONE,
|
|
/*40*/ KEY_NONE, KEY_COMMA, KEY_K, KEY_I, KEY_O, KEY_0, KEY_9, KEY_NONE,
|
|
/*48*/ KEY_NONE, KEY_PERIOD, KEY_SLASH, KEY_L, KEY_SEMICOLON, KEY_P, KEY_MINUS, KEY_NONE,
|
|
/*50*/ KEY_NONE, KEY_NONE, KEY_QUOTE, KEY_NONE, KEY_L_BRACE, KEY_EQUAL, KEY_NONE, KEY_NONE,
|
|
/*58*/ KEY_CAPS_LOCK, KEY_R_SHIFT, KEY_ENTER, KEY_R_BRACE, KEY_NONE, KEY_BACKSLASH, KEY_NONE, KEY_NONE,
|
|
/*60*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_BACKSPACE, KEY_NONE,
|
|
/*68*/ KEY_NONE, KEY_NP_1, KEY_NONE, KEY_NP_4, KEY_NP_7, KEY_NONE, KEY_NONE, KEY_NONE,
|
|
/*70*/ KEY_NP_0, KEY_NP_PERIOD, KEY_NP_2, KEY_NP_5, KEY_NP_6, KEY_NP_8, KEY_ESCAPE, KEY_NUM_LOCK,
|
|
/*78*/ KEY_F11, KEY_NP_PLUS, KEY_NP_3, KEY_NP_MINUS, KEY_NP_ASTERISK, KEY_NP_9, KEY_SCROLL_LOCK, KEY_NONE,
|
|
/*80*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_F7,
|
|
};
|
|
static uint8_t scancodes_ext[] = {
|
|
// 00/08 01/09 02/0A 03/0B 04/0C 05/0D 06/0E 07/0F
|
|
/*00*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
|
/*08*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
|
/*10*/ KEY_UNKNOWN, KEY_R_ALT, KEY_PRINT_SCREEN, KEY_NONE, KEY_R_CTRL, KEY_UNKNOWN, KEY_NONE, KEY_NONE,
|
|
/*18*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_L_META,
|
|
/*20*/ KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_R_META,
|
|
/*28*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_MENU,
|
|
/*30*/ KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_UNKNOWN,
|
|
/*38*/ KEY_UNKNOWN, KEY_NONE, KEY_UNKNOWN, KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN,
|
|
/*40*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
|
/*48*/ KEY_UNKNOWN, KEY_NONE, KEY_NP_SLASH, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE, KEY_NONE,
|
|
/*50*/ KEY_UNKNOWN, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
|
/*58*/ KEY_NONE, KEY_NONE, KEY_NP_ENTER, KEY_NONE, KEY_NONE, KEY_NONE, KEY_UNKNOWN, KEY_NONE,
|
|
/*60*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
|
/*68*/ KEY_NONE, KEY_END, KEY_NONE, KEY_LEFT, KEY_HOME, KEY_NONE, KEY_NONE, KEY_NONE,
|
|
/*70*/ KEY_INSERT, KEY_DELETE, KEY_DOWN, KEY_NONE, KEY_RIGHT, KEY_UP, KEY_NONE, KEY_NONE,
|
|
/*78*/ KEY_NONE, KEY_NONE, KEY_PAGE_DOWN, KEY_NONE, KEY_NONE, KEY_PAGE_UP, KEY_NONE, KEY_NONE,
|
|
/*80*/ KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
|
|
};
|
|
|
|
static struct Keycode last_keycode;
|
|
|
|
static bool is_init = false;
|
|
static bool state_keyup = false;
|
|
static bool state_ext = false;
|
|
|
|
void ps2kb_init(void) {
|
|
is_init = false;
|
|
pic_mask(1);
|
|
|
|
uint8_t result;
|
|
|
|
ps2ctrl_out_data(0xFF);
|
|
result = ps2ctrl_in();
|
|
if(result != 0xFA) {
|
|
panic("Failed to reset PS/2 keyboard: expected 0xFA, got 0x%X\n", result);
|
|
}
|
|
result = ps2ctrl_in();
|
|
if(result != 0xAA) {
|
|
panic("Failed to reset PS/2 keyboard: expected 0xAA, got 0x%X\n", result);
|
|
}
|
|
|
|
ps2ctrl_out_data(0xF4);
|
|
result = ps2ctrl_in();
|
|
if(result != 0xFA) {
|
|
panic("Failed to enable PS/2 keyboard: expected 0xFA, got 0x%X\n", result);
|
|
}
|
|
|
|
pic_unmask(1);
|
|
is_init = true;
|
|
}
|
|
|
|
void ps2kb_recv(void) {
|
|
if(!ps2ctrl_is_init() || !is_init) {
|
|
inb(0x60);
|
|
return;
|
|
}
|
|
uint8_t code = ps2ctrl_in();
|
|
if (code == 0x00 || code == 0x0F) {
|
|
last_keycode.key = KEY_NONE;
|
|
last_keycode.flags = KC_FLAG_ERROR;
|
|
} else if(code == 0xF0) {
|
|
state_keyup = true;
|
|
} else if(code == 0xE0) {
|
|
state_ext = true;
|
|
} else if(code <= KEYCODE_ARRAY_LEN) {
|
|
uint8_t *scancode_table = state_ext ? scancodes_ext : scancodes;
|
|
uint8_t keycode = scancode_table[code];
|
|
if(keycode != KEY_NONE) {
|
|
last_keycode.key = keycode;
|
|
last_keycode.flags = state_keyup ? KC_FLAG_KEY_UP : KC_FLAG_KEY_DOWN;
|
|
}
|
|
state_keyup = false;
|
|
state_ext = false;
|
|
}
|
|
}
|
|
|
|
struct Keycode ps2kb_get(void) {
|
|
struct Keycode code;
|
|
if(is_init) {
|
|
code = last_keycode;
|
|
} else {
|
|
code.key = KEY_NONE;
|
|
code.flags = KC_FLAG_ERROR;
|
|
}
|
|
last_keycode.key = KEY_NONE;
|
|
last_keycode.flags = 0;
|
|
return code;
|
|
}
|