#include #include #include 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::input_queue->insert({ .keyboard = current_flags | key, .is_mouse = false}); 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]; static 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; } } static uint8_t mouse_packet_so_far[3]; static uint8_t mouse_packet_so_far_len = 0; extern "C" void on_mouse_interrupt(uint8_t byte) { if (mouse_packet_so_far_len == 0 && byte == 0xfa) //dirty hack return; mouse_packet_so_far[mouse_packet_so_far_len++] = byte; if (mouse_packet_so_far_len < 3) return; mouse_packet_so_far_len = 0; int16_t x_change = mouse_packet_so_far[1]; int16_t y_change = -(int16_t)mouse_packet_so_far[2]; if (mouse_packet_so_far[0] & 0x10) x_change -= 0x100; if (mouse_packet_so_far[0] & 0x20) y_change += 0x100; input::input_packet packet = { .mouse = { .x_change = x_change, .y_change = y_change, .buttons = (input::buttons_t)(mouse_packet_so_far[0] & 7) }, .is_mouse = true }; if (input::input_queue->count > 0 && input::input_queue->last_inserted().is_mouse && input::input_queue->last_inserted().mouse.buttons == packet.mouse.buttons) { input::input_queue->last_inserted().mouse.x_change = packet.mouse.x_change; input::input_queue->last_inserted().mouse.y_change = packet.mouse.y_change; } else input::input_queue->insert(packet); input::got_input(); }