#include "drivers/input/input.h" #include "mp/spinlock.h" #include "libk/stdio.h" #include "fs/vfs.h" #include #include "mm/memory.h" #include "libk/string.h" #include #include "libk/debug.h" /* ------------------------------------------------------------------ * * Event ring-buffer * ------------------------------------------------------------------ */ #define INPUT_BUF_SIZE 512 #define CONSOLE_BUF_SIZE 256 static char s_console_buf[CONSOLE_BUF_SIZE]; static size_t s_console_rpos = 0; static size_t s_console_wpos = 0; static input_event_t s_buf[INPUT_BUF_SIZE]; static size_t s_rpos = 0; static size_t s_wpos = 0; static spinlock_t s_lock = SPINLOCK_INIT; /* Called from IRQ context */ void input_push_char(char c) { uint64_t flags; spinlock_acquire_irqsave(&s_lock, &flags); size_t next = (s_console_wpos + 1) % CONSOLE_BUF_SIZE; if (next != s_console_rpos) { /* drop if full */ s_console_buf[s_console_wpos] = c; s_console_wpos = next; } spinlock_release_irqrestore(&s_lock, flags); } int input_read_console(void *buf, size_t len) { uint8_t *p = buf; size_t count = 0; uint64_t flags; spinlock_acquire_irqsave(&s_lock, &flags); while (count < len && s_console_rpos != s_console_wpos) { p[count++] = s_console_buf[s_console_rpos]; s_console_rpos = (s_console_rpos + 1) % CONSOLE_BUF_SIZE; } spinlock_release_irqrestore(&s_lock, flags); return (int)count; } static void push_event(const input_event_t *ev) { spinlock_acquire_or_wait(&s_lock); size_t next = (s_wpos + 1) % INPUT_BUF_SIZE; if (next != s_rpos) { /* drop if full */ s_buf[s_wpos] = *ev; s_wpos = next; } spinlock_drop(&s_lock); } bool input_poll(input_event_t *out) { spinlock_acquire_or_wait(&s_lock); if (s_rpos == s_wpos) { spinlock_drop(&s_lock); return false; } *out = s_buf[s_rpos]; s_rpos = (s_rpos + 1) % INPUT_BUF_SIZE; spinlock_drop(&s_lock); return true; } bool input_has_event(void) { spinlock_acquire_or_wait(&s_lock); bool has = (s_rpos != s_wpos); spinlock_drop(&s_lock); return has; } /* ------------------------------------------------------------------ * * Driver-facing helpers * ------------------------------------------------------------------ */ void input_push_key(uint8_t scancode, char ascii, bool pressed) { input_event_t ev = { .type = INPUT_EV_KEY, .key = { .scancode = scancode, .ascii = ascii, .pressed = pressed }, }; push_event(&ev); } void input_push_mouse_rel(int16_t dx, int16_t dy) { input_event_t ev = { .type = INPUT_EV_MOUSE_REL, .rel = { dx, dy } }; push_event(&ev); } void input_push_mouse_btn(uint8_t button, bool pressed) { input_event_t ev = { .type = INPUT_EV_MOUSE_BTN, .btn = { .button = button, .pressed = pressed }, }; push_event(&ev); } void input_push_mouse_wheel(int8_t delta) { input_event_t ev = { .type = INPUT_EV_MOUSE_WHEEL, .wheel = { delta } }; push_event(&ev); } static int dev_input_read(void *buf, size_t len) { size_t count = 0; while (count + sizeof(input_event_t) <= len) { input_event_t ev; if (!input_poll(&ev)) break; memcpy((uint8_t*)buf + count, &ev, sizeof(ev)); count += sizeof(ev); } return (int)count; } static int dev_input_write(const void *buf, size_t len) { (void)buf; (void)len; return -1; /* read-only */ } void input_register_devnodes(void) { VFS_RegisterCharDev("/dev/input/event0", dev_input_read, dev_input_write); } void input_init(void) { input_register_devnodes(); kprintf("input: subsystem initialized\n"); }