summaryrefslogtreecommitdiff
path: root/kernel/interrupts.cpp
diff options
context:
space:
mode:
authorBenji Dial <benji@benjidial.net>2024-01-27 23:14:29 -0500
committerBenji Dial <benji@benjidial.net>2024-01-27 23:14:29 -0500
commita8a80d326de9550b2a25b1255a2093ab43219ede (patch)
treed42a800f735caf93679d1728e2d5f20004db3b65 /kernel/interrupts.cpp
parent7199e74aa22e592a3b77bdd81f735edca5470596 (diff)
downloadhilbert-os-a8a80d326de9550b2a25b1255a2093ab43219ede.tar.gz
keyboard input
Diffstat (limited to 'kernel/interrupts.cpp')
-rw-r--r--kernel/interrupts.cpp111
1 files changed, 108 insertions, 3 deletions
diff --git a/kernel/interrupts.cpp b/kernel/interrupts.cpp
index 1a95f22..cd57c4f 100644
--- a/kernel/interrupts.cpp
+++ b/kernel/interrupts.cpp
@@ -1,4 +1,6 @@
#include <hilbert/kernel/terminal.hpp>
+#include <hilbert/kernel/input.hpp>
+#include <hilbert/kernel/panic.hpp>
using namespace hilbert::kernel;
@@ -34,7 +36,7 @@ struct [[gnu::packed]] exception_info_t {
extern exception_info_t exception_info;
-const char *exception_types[] = {
+static const char *exception_types[] = {
"division error",
"",
"non-maskable interrupt",
@@ -53,7 +55,7 @@ const char *exception_types[] = {
""
};
-const char *flag_names[] = {
+static const char *flag_names[] = {
" cf",
"",
" pf",
@@ -72,7 +74,7 @@ const char *flag_names[] = {
" md"
};
-void print_line(const char *r1, const char *r2, uint64_t r1v, uint64_t r2v) {
+static void print_line(const char *r1, const char *r2, uint64_t r1v, uint64_t r2v) {
terminal::put_string_sz("\n ");
terminal::put_string_sz(r1);
terminal::put_string_sz(": 0x");
@@ -123,3 +125,106 @@ extern "C" [[noreturn]] void print_exception() {
asm ("hlt");
}
+
+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);
+
+ 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;
+ }
+
+}