]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: /dev/kbd raw scancode device for game input (DOOM)
authorTulio A M Mendes <[email protected]>
Thu, 12 Feb 2026 07:32:51 +0000 (04:32 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 02:44:55 +0000 (23:44 -0300)
Added raw scancode ring buffer to the keyboard driver. The HAL
keyboard layer now fires a second callback with the unprocessed
scancode byte (both key-press and key-release events).

- hal/keyboard.h: added hal_keyboard_scan_cb_t and setter
- hal/x86/keyboard.c: fires g_scan_cb before ASCII translation
- drivers/keyboard.c: raw scancode buffer + /dev/kbd device node
  registered via devfs (non-blocking read returns raw scancodes)
- init.c: calls keyboard_register_devfs() after devfs is mounted

DOOM can now open /dev/kbd and read raw PS/2 scancodes to detect
key press/release events without TTY line buffering.

include/hal/keyboard.h
include/keyboard.h
src/drivers/keyboard.c
src/hal/x86/keyboard.c
src/kernel/init.c

index 0a7cca27a220373ec5942af364fe79a29325924d..9f76378100a9031b75a621371a3167d2275237d7 100644 (file)
 #ifndef HAL_KEYBOARD_H
 #define HAL_KEYBOARD_H
 
+#include <stdint.h>
+
 typedef void (*hal_keyboard_char_cb_t)(char c);
+typedef void (*hal_keyboard_scan_cb_t)(uint8_t scancode);
 
 void hal_keyboard_init(hal_keyboard_char_cb_t cb);
+void hal_keyboard_set_scancode_cb(hal_keyboard_scan_cb_t cb);
 
 #endif
index 585e2b197a84a0c0727ecaabee9217fcb5ae5348..fdc76d743912c35ea313b1e3d65908e00016e31e 100644 (file)
@@ -16,6 +16,7 @@
 typedef void (*keyboard_callback_t)(char);
 
 void keyboard_init(void);
+void keyboard_register_devfs(void);
 void keyboard_set_callback(keyboard_callback_t callback);
 
 int keyboard_read_nonblock(char* out, uint32_t max_len);
index f9501f8790eb65b7b4f9a6daeba2e51dd55b4873..b0a194ec1b2b702d4eb84a05bd65801f1c977346 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include "keyboard.h"
+#include "devfs.h"
 #include "uart_console.h"
 #include <stddef.h>
 
@@ -55,13 +56,65 @@ static void hal_kbd_bridge(char c) {
     }
 }
 
+/* --- Raw scancode ring buffer for /dev/kbd --- */
+
+#define SCAN_BUF_SIZE 256
+static volatile uint32_t scan_head = 0;
+static volatile uint32_t scan_tail = 0;
+static uint8_t scan_buf[SCAN_BUF_SIZE];
+static spinlock_t scan_lock = {0};
+
+static void scan_push(uint8_t sc) {
+    uint32_t next = (scan_head + 1U) % SCAN_BUF_SIZE;
+    if (next == scan_tail) {
+        scan_tail = (scan_tail + 1U) % SCAN_BUF_SIZE;
+    }
+    scan_buf[scan_head] = sc;
+    scan_head = next;
+}
+
+static void hal_scan_bridge(uint8_t scancode) {
+    uintptr_t flags = spin_lock_irqsave(&scan_lock);
+    scan_push(scancode);
+    spin_unlock_irqrestore(&scan_lock, flags);
+}
+
+static uint32_t kbd_dev_read(fs_node_t* node, uint32_t offset, uint32_t size, uint8_t* buffer) {
+    (void)node; (void)offset;
+    if (!buffer || size == 0) return 0;
+
+    uintptr_t flags = spin_lock_irqsave(&scan_lock);
+    uint32_t count = 0;
+    while (count < size && scan_tail != scan_head) {
+        buffer[count++] = scan_buf[scan_tail];
+        scan_tail = (scan_tail + 1U) % SCAN_BUF_SIZE;
+    }
+    spin_unlock_irqrestore(&scan_lock, flags);
+    return count;
+}
+
+static fs_node_t g_dev_kbd_node;
+
 void keyboard_init(void) {
     uart_print("[KBD] Initializing Keyboard Driver...\n");
     spinlock_init(&kbd_lock);
+    spinlock_init(&scan_lock);
     kbd_head = 0;
     kbd_tail = 0;
+    scan_head = 0;
+    scan_tail = 0;
     kbd_waiter = NULL;
     hal_keyboard_init(hal_kbd_bridge);
+    hal_keyboard_set_scancode_cb(hal_scan_bridge);
+}
+
+void keyboard_register_devfs(void) {
+    memset(&g_dev_kbd_node, 0, sizeof(g_dev_kbd_node));
+    strcpy(g_dev_kbd_node.name, "kbd");
+    g_dev_kbd_node.flags = FS_CHARDEVICE;
+    g_dev_kbd_node.inode = 21;
+    g_dev_kbd_node.read = &kbd_dev_read;
+    devfs_register_device(&g_dev_kbd_node);
 }
 
 void keyboard_set_callback(keyboard_callback_t callback) {
index e9415e1a193b724ac819b225ad169bf4eee67987..6931e2a7b269dffcfd83d41f8048c42fcd1b3319 100644 (file)
@@ -14,6 +14,7 @@
 #include "io.h"
 
 static hal_keyboard_char_cb_t g_cb = 0;
+static hal_keyboard_scan_cb_t g_scan_cb = 0;
 
 static char scancode_map[128] = {
     0,  27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
@@ -60,6 +61,11 @@ static void kbd_irq(struct registers* regs) {
     if (status & 0x01) {
         uint8_t scancode = inb(0x60);
 
+        /* Raw scancode callback (key press and release) */
+        if (g_scan_cb) {
+            g_scan_cb(scancode);
+        }
+
         if (!(scancode & 0x80)) {
             if (scancode < 128) {
                 char c = scancode_map[scancode];
@@ -75,8 +81,16 @@ void hal_keyboard_init(hal_keyboard_char_cb_t cb) {
     g_cb = cb;
     register_interrupt_handler(33, kbd_irq);
 }
+
+void hal_keyboard_set_scancode_cb(hal_keyboard_scan_cb_t cb) {
+    g_scan_cb = cb;
+}
 #else
 void hal_keyboard_init(hal_keyboard_char_cb_t cb) {
     (void)cb;
 }
+
+void hal_keyboard_set_scancode_cb(hal_keyboard_scan_cb_t cb) {
+    (void)cb;
+}
 #endif
index e1cc2feff1b59b2c562e276ad45e5f2da7983582..2179241498749afc70269185bfd2a8cbbb3668ac 100644 (file)
@@ -95,6 +95,7 @@ int init_start(const struct boot_info* bi) {
     }
 
     vbe_register_devfs();
+    keyboard_register_devfs();
 
     fs_node_t* persist = persistfs_create_root();
     if (persist) {