b28a6bcf29
Signed-off-by: kaguya3311 <kaguya3311@national.shitposting.agency>
150 lines
3.7 KiB
C
150 lines
3.7 KiB
C
#include "drivers/input/input.h"
|
|
#include "mp/spinlock.h"
|
|
#include "libk/stdio.h"
|
|
#include "fs/vfs.h"
|
|
#include <stddef.h>
|
|
#include "mm/memory.h"
|
|
#include "libk/string.h"
|
|
#include <stddef.h>
|
|
#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");
|
|
} |