152 lines
3.5 KiB
C++
152 lines
3.5 KiB
C++
#include <hilbert/kernel/input.hpp>
|
|
#include <hilbert/kernel/panic.hpp>
|
|
|
|
using namespace hilbert::kernel;
|
|
|
|
struct [[gnu::packed]] exception_info_t {
|
|
|
|
uint64_t rax;
|
|
uint64_t rbx;
|
|
uint64_t rcx;
|
|
uint64_t rdx;
|
|
uint64_t rdi;
|
|
uint64_t rsi;
|
|
uint64_t rbp;
|
|
uint64_t rsp;
|
|
uint64_t r8;
|
|
uint64_t r9;
|
|
uint64_t r10;
|
|
uint64_t r11;
|
|
uint64_t r12;
|
|
uint64_t r13;
|
|
uint64_t r14;
|
|
uint64_t r15;
|
|
|
|
uint64_t cr2;
|
|
uint64_t cr3;
|
|
uint64_t rip;
|
|
uint64_t rflags;
|
|
|
|
uint64_t error;
|
|
uint8_t has_error;//0 or 1
|
|
uint8_t exception_number;
|
|
|
|
};
|
|
|
|
extern exception_info_t exception_info;
|
|
|
|
extern "C" [[noreturn]] void print_exception() {
|
|
|
|
//so exception_info's type is known by gdb
|
|
exception_info_t the_exception_info = exception_info;
|
|
(void)the_exception_info;
|
|
|
|
//TODO: log exception, and recover if possible.
|
|
|
|
panic(0xba40bb);
|
|
|
|
}
|
|
|
|
static uint32_t current_flags = 0;
|
|
|
|
#define SETBIT(field, bit, cond) \
|
|
field = (cond) ? (field | (bit)) : (field & ~(bit));
|
|
|
|
static void got_key(uint32_t key) {
|
|
|
|
input::key_queue->insert(current_flags | key);
|
|
input::got_input();
|
|
|
|
if (key == (input::BREAK | 0x77))
|
|
current_flags ^= input::NUM_LOCK;
|
|
|
|
else if (key == (input::BREAK | 0x58))
|
|
current_flags ^= input::CAPS_LOCK;
|
|
|
|
else if ((key & 0xff) == 0xa7)
|
|
SETBIT(current_flags, input::RIGHT_WIN, !(key & input::BREAK))
|
|
|
|
else if ((key & 0xff) == 0x9f)
|
|
SETBIT(current_flags, input::LEFT_WIN, !(key & input::BREAK))
|
|
|
|
else if ((key & 0xff) == 0x91)
|
|
SETBIT(current_flags, input::RIGHT_ALT, !(key & input::BREAK))
|
|
|
|
else if ((key & 0xff) == 0x11)
|
|
SETBIT(current_flags, input::LEFT_ALT, !(key & input::BREAK))
|
|
|
|
else if ((key & 0xff) == 0x94)
|
|
SETBIT(current_flags, input::RIGHT_CTRL, !(key & input::BREAK))
|
|
|
|
else if ((key & 0xff) == 0x14)
|
|
SETBIT(current_flags, input::LEFT_CTRL, !(key & input::BREAK))
|
|
|
|
else if ((key & 0xff) == 0x59)
|
|
SETBIT(current_flags, input::RIGHT_SHIFT, !(key & input::BREAK))
|
|
|
|
else if ((key & 0xff) == 0x12)
|
|
SETBIT(current_flags, input::LEFT_SHIFT, !(key & input::BREAK))
|
|
|
|
}
|
|
|
|
static uint8_t key_so_far[8];
|
|
uint8_t key_so_far_len = 0;
|
|
|
|
extern "C" void on_keyboard_interrupt(uint8_t byte) {
|
|
|
|
key_so_far[key_so_far_len++] = byte;
|
|
|
|
if (key_so_far_len == 1) {
|
|
if (byte != 0xe0 && byte != 0xe1 && byte != 0xf0) {
|
|
got_key(byte);
|
|
key_so_far_len = 0;
|
|
}
|
|
}
|
|
|
|
else if (key_so_far_len == 2) {
|
|
if (key_so_far[0] == 0xe0 && byte != 0xf0 && byte != 0x12) {
|
|
got_key(byte | 0x80);
|
|
key_so_far_len = 0;
|
|
}
|
|
else if (key_so_far[0] == 0xf0) {
|
|
got_key(input::BREAK | byte);
|
|
key_so_far_len = 0;
|
|
}
|
|
}
|
|
|
|
else if (key_so_far_len == 3) {
|
|
if (key_so_far[0] == 0xe0 && key_so_far[1] == 0xf0 && byte != 0x7c) {
|
|
got_key(input::BREAK | byte | 0x80);
|
|
key_so_far_len = 0;
|
|
}
|
|
}
|
|
|
|
else if (key_so_far_len == 4) {
|
|
if (key_so_far[0] == 0xe0 && key_so_far[1] == 0x12 &&
|
|
key_so_far[2] == 0xe0 && byte == 0x7c) {
|
|
got_key(0xe0);
|
|
key_so_far_len = 0;
|
|
}
|
|
}
|
|
|
|
else if (key_so_far_len == 6) {
|
|
if (key_so_far[0] == 0xe0 && key_so_far[1] == 0xf0 &&
|
|
key_so_far[2] == 0x7c && key_so_far[3] == 0xe0 &&
|
|
key_so_far[4] == 0xf0 && byte == 0x12) {
|
|
got_key(input::BREAK | 0xe0);
|
|
key_so_far_len = 0;
|
|
}
|
|
}
|
|
|
|
else if (key_so_far_len == 8) {
|
|
if (key_so_far[0] == 0xe1 && key_so_far[1] == 0x14 &&
|
|
key_so_far[2] == 0x77 && key_so_far[3] == 0xe1 &&
|
|
key_so_far[2] == 0xf0 && key_so_far[3] == 0x14 &&
|
|
key_so_far[4] == 0xf0 && byte == 0x77) {
|
|
got_key(0xe1);
|
|
got_key(input::BREAK | 0xe1);
|
|
}
|
|
key_so_far_len = 0;
|
|
}
|
|
|
|
}
|