Browse Source

feat: improved keyboard event handling

greatbridf 3 năm trước cách đây
mục cha
commit
1be69f0785

+ 4 - 1
CMakeLists.txt

@@ -42,10 +42,12 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         src/kernel/stdio.c
                         src/kernel/mem.c
                         src/kernel/vga.c
-                        src/kernel/hw/keyboard.c
+                        src/kernel/hw/keyboard.cpp
+                        src/kernel/event/event.cpp
                         src/types/buffer.c
                         include/asm/boot.h
                         include/asm/port_io.h
+                        include/kernel/event/event.h
                         include/kernel/errno.h
                         include/kernel/interrupt.h
                         include/kernel/stdio.h
@@ -53,6 +55,7 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/kernel/vga.h
                         include/kernel/hw/keyboard.h
                         include/kernel/input/keycodes.h
+                        include/kernel/input/input_event.h
                         include/types/buffer.h
                         include/types/types.h
                         include/types/size.h

+ 16 - 0
include/kernel/event/event.h

@@ -0,0 +1,16 @@
+#pragma once
+
+#include <kernel/input/input_event.h>
+#include <types/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void commit_input_event(struct input_event* evt);
+
+void dispatch_event(void);
+
+#ifdef __cplusplus
+}
+#endif

+ 4 - 0
include/kernel/hw/keyboard.h

@@ -6,4 +6,8 @@ int32_t keyboard_has_data(void);
 
 void process_keyboard_data(void);
 
+#ifdef __cplusplus
+extern "C" void handle_keyboard_interrupt(void);
+#else
 void handle_keyboard_interrupt(void);
+#endif

+ 17 - 0
include/kernel/input/input_event.h

@@ -0,0 +1,17 @@
+#pragma once
+
+#include <types/types.h>
+
+// keyboard event code
+#define KEY_DOWN 0
+#define KEY_UP 1
+
+struct input_event {
+    enum input_event_type {
+        KEYBOARD,
+    };
+
+    enum input_event_type type;
+    uint32_t code;
+    uint32_t data;
+};

+ 35 - 0
src/kernel/event/event.cpp

@@ -0,0 +1,35 @@
+#include "kernel/vga.h"
+#include <asm/port_io.h>
+#include <kernel/event/event.h>
+#include <kernel/input/input_event.h>
+#include <kernel/stdio.h>
+#include <types/list.hpp>
+
+static ::types::list<::input_event> _input_event_queue {};
+
+namespace event {
+::types::list<::input_event>& input_event_queue(void)
+{
+    return _input_event_queue;
+}
+} // namespace event
+
+void commit_input_event(struct input_event* evt)
+{
+    event::input_event_queue().push_back(*evt);
+}
+
+void dispatch_event(void)
+{
+    char buf[1024];
+    auto& input_event_queue = event::input_event_queue();
+
+    while (!input_event_queue.empty()) {
+        for (auto iter = input_event_queue.begin(); iter != input_event_queue.end(); ++iter) {
+            const auto& item = *iter;
+            snprintf(buf, 1024, "input event: type%x, data%x, code%x\n", item.type, item.data, item.code);
+            vga_printk(buf, 0x0fu);
+            input_event_queue.erase(iter);
+        }
+    }
+}

+ 0 - 47
src/kernel/hw/keyboard.c

@@ -1,47 +0,0 @@
-#include <asm/port_io.h>
-#include <kernel/hw/keyboard.h>
-#include <kernel/stdio.h>
-#include <kernel/vga.h>
-#include <types/types.h>
-
-#define KEYBOARD_SCAN_CODE_BUFFER_SIZE (256)
-static char keyboard_scan_code_buf[KEYBOARD_SCAN_CODE_BUFFER_SIZE];
-static struct ring_buffer* p_scan_code_buf = 0;
-
-void handle_keyboard_interrupt(void)
-{
-    static struct ring_buffer
-        s_scan_code_buf
-        = MAKE_RING_BUFFER(keyboard_scan_code_buf, KEYBOARD_SCAN_CODE_BUFFER_SIZE);
-    if (p_scan_code_buf == 0)
-        p_scan_code_buf = &s_scan_code_buf;
-
-    char c = 0x00;
-    c = (char)asm_inb(PORT_KEYDATA);
-
-    ring_buffer_write(p_scan_code_buf, c);
-}
-
-int32_t keyboard_has_data(void)
-{
-    // uninitialized
-    if (p_scan_code_buf == 0)
-        return 0;
-    return !ring_buffer_empty(p_scan_code_buf);
-}
-
-void process_keyboard_data(void)
-{
-    char buf[128] = { 0 };
-    while (keyboard_has_data()) {
-        // as scan codes may be greater than 127
-        // so we use unsigned char here to prevent
-        // the compiler from automatically filling
-        // 1's in front of the scan codes and cause
-        // codes like '9e' show like 'ffffff9e'
-        unsigned char c;
-        c = ring_buffer_read(p_scan_code_buf);
-        snprintf(buf, 128, "%x", c);
-    }
-    vga_printk(buf, 0x0fu);
-}

+ 30 - 0
src/kernel/hw/keyboard.cpp

@@ -0,0 +1,30 @@
+#include <asm/port_io.h>
+#include <kernel/event/event.h>
+#include <kernel/hw/keyboard.h>
+#include <kernel/input/input_event.h>
+
+extern "C" void
+handle_keyboard_interrupt(void)
+{
+    input_event evt {
+        .type = input_event::input_event_type::KEYBOARD,
+        .code = KEY_DOWN,
+        .data = 0
+    };
+
+    uint8_t keycode = asm_inb(PORT_KEYDATA);
+    if (keycode >= 0xd8) {
+        // TODO: report not_supported event
+        return;
+    }
+
+    // key release
+    if (keycode >= 0x80) {
+        evt.code = KEY_UP;
+        keycode -= 0x80;
+    }
+
+    evt.data = keycode;
+
+    commit_input_event(&evt);
+}

+ 3 - 3
src/kernel_main.c

@@ -2,6 +2,7 @@
 
 #include <asm/boot.h>
 #include <asm/port_io.h>
+#include <kernel/event/event.h>
 #include <kernel/hw/keyboard.h>
 #include <kernel/interrupt.h>
 #include <kernel/mem.h>
@@ -70,9 +71,8 @@ void kernel_main(void)
         // disable interrupt
         asm_cli();
 
-        if (keyboard_has_data()) {
-            process_keyboard_data();
-        }
+        dispatch_event();
+
         asm_sti();
         asm_hlt();
     }