mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-29 13:48:21 +00:00
input: add new evdev subsystem
Co-authored-by: Matheus <matheusuky@gmail.com>
This commit is contained in:
+161
-31
@@ -5,16 +5,31 @@
|
||||
#include <kernel/term.h>
|
||||
#include <kernel/devfs.h>
|
||||
#include <errno.h>
|
||||
#include <kernel/keyboard.h>
|
||||
#include <termios.h>
|
||||
#include <kernel/poll.h>
|
||||
#include <kernel/tty.h>
|
||||
#include <kernel/init.h>
|
||||
|
||||
static spinlock_t input_buffer_lock = SPINLOCK_INIT_VALUE;
|
||||
static ringbuffer_t input_buffer;
|
||||
static semaphore_t input_sem;
|
||||
|
||||
static mutex_t writemutex;
|
||||
static thread_t *thread;
|
||||
static tty_t *tty;
|
||||
|
||||
static size_t console_ttywrite(void *internal, char *str, size_t count) {
|
||||
return console_write(str, count);
|
||||
}
|
||||
|
||||
void console_putc(char c) {
|
||||
if (c == '\n') {
|
||||
console_write("\r\n", 2);
|
||||
} else {
|
||||
console_write(&c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t console_write(char *str, size_t count) {
|
||||
MUTEX_ACQUIRE(&writemutex);
|
||||
|
||||
@@ -24,15 +39,17 @@ size_t console_write(char *str, size_t count) {
|
||||
return count;
|
||||
}
|
||||
|
||||
size_t console_ttywrite(void *internal, char *str, size_t count) {
|
||||
return console_write(str, count);
|
||||
}
|
||||
void console_process_events(input_event_t *events, int count) {
|
||||
long ipl = spinlock_acquire_raise_ipl(&input_buffer_lock, IPL_INPUT);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (events[i].type != INPUT_EV_KEY || events[i].code >= INPUT_KEY_BTN_LEFT)
|
||||
continue;
|
||||
|
||||
void console_putc(char c) {
|
||||
if (c == '\n')
|
||||
console_write("\n\r", 2);
|
||||
else
|
||||
console_write(&c, 1);
|
||||
size_t written = ringbuffer_write(&input_buffer, &events[i], sizeof(input_event_t));
|
||||
if (written == sizeof(input_event_t))
|
||||
semaphore_signal(&input_sem);
|
||||
}
|
||||
spinlock_release_lower_ipl(&input_buffer_lock, ipl);
|
||||
}
|
||||
|
||||
// taken from https://en.wikipedia.org/wiki/ANSI_escape_code#Terminal_input_sequences
|
||||
@@ -49,55 +66,165 @@ void console_putc(char c) {
|
||||
#define RIGHT_STR "\e[C"
|
||||
#define LEFT_STR "\e[D"
|
||||
|
||||
static const char key_to_ascii_normal[] = {
|
||||
[INPUT_KEY_ESC] = '\e', [INPUT_KEY_1] = '1',
|
||||
[INPUT_KEY_2] = '2', [INPUT_KEY_3] = '3',
|
||||
[INPUT_KEY_4] = '4', [INPUT_KEY_5] = '5',
|
||||
[INPUT_KEY_6] = '6', [INPUT_KEY_7] = '7',
|
||||
[INPUT_KEY_8] = '8', [INPUT_KEY_9] = '9',
|
||||
[INPUT_KEY_0] = '0', [INPUT_KEY_MINUS] = '-',
|
||||
[INPUT_KEY_EQUAL] = '=', [INPUT_KEY_BACKSPACE] = '\b',
|
||||
[INPUT_KEY_TAB] = '\t', [INPUT_KEY_Q] = 'q',
|
||||
[INPUT_KEY_W] = 'w', [INPUT_KEY_E] = 'e',
|
||||
[INPUT_KEY_R] = 'r', [INPUT_KEY_T] = 't',
|
||||
[INPUT_KEY_Y] = 'y', [INPUT_KEY_U] = 'u',
|
||||
[INPUT_KEY_I] = 'i', [INPUT_KEY_O] = 'o',
|
||||
[INPUT_KEY_P] = 'p', [INPUT_KEY_LEFTBRACE] = '[',
|
||||
[INPUT_KEY_RIGHTBRACE] = ']', [INPUT_KEY_ENTER] = '\r',
|
||||
[INPUT_KEY_A] = 'a', [INPUT_KEY_S] = 's',
|
||||
[INPUT_KEY_D] = 'd', [INPUT_KEY_F] = 'f',
|
||||
[INPUT_KEY_G] = 'g', [INPUT_KEY_H] = 'h',
|
||||
[INPUT_KEY_J] = 'j', [INPUT_KEY_K] = 'k',
|
||||
[INPUT_KEY_L] = 'l', [INPUT_KEY_SEMICOLON] = ';',
|
||||
[INPUT_KEY_APOSTROPHE] = '\'', [INPUT_KEY_GRAVE] = '`',
|
||||
[INPUT_KEY_BACKSLASH] = '\\', [INPUT_KEY_Z] = 'z',
|
||||
[INPUT_KEY_X] = 'x', [INPUT_KEY_C] = 'c',
|
||||
[INPUT_KEY_V] = 'v', [INPUT_KEY_B] = 'b',
|
||||
[INPUT_KEY_N] = 'n', [INPUT_KEY_M] = 'm',
|
||||
[INPUT_KEY_COMMA] = ',', [INPUT_KEY_DOT] = '.',
|
||||
[INPUT_KEY_SLASH] = '/', [INPUT_KEY_KPASTERISK] = '*',
|
||||
[INPUT_KEY_SPACE] = ' ', [INPUT_KEY_KP7] = '7',
|
||||
[INPUT_KEY_KP8] = '8', [INPUT_KEY_KP9] = '9',
|
||||
[INPUT_KEY_KPMINUS] = '-', [INPUT_KEY_KP4] = '4',
|
||||
[INPUT_KEY_KP5] = '5', [INPUT_KEY_KP6] = '6',
|
||||
[INPUT_KEY_KPPLUS] = '+', [INPUT_KEY_KP1] = '1',
|
||||
[INPUT_KEY_KP2] = '2', [INPUT_KEY_KP3] = '3',
|
||||
[INPUT_KEY_KP0] = '0', [INPUT_KEY_KPDOT] = '.',
|
||||
[INPUT_KEY_KPENTER] = '\r', [INPUT_KEY_KPSLASH] = '/',
|
||||
};
|
||||
|
||||
static const char key_to_ascii_shift[] = {
|
||||
[INPUT_KEY_ESC] = '\e', [INPUT_KEY_1] = '!',
|
||||
[INPUT_KEY_2] = '@', [INPUT_KEY_3] = '#',
|
||||
[INPUT_KEY_4] = '$', [INPUT_KEY_5] = '%',
|
||||
[INPUT_KEY_6] = '^', [INPUT_KEY_7] = '&',
|
||||
[INPUT_KEY_8] = '*', [INPUT_KEY_9] = '(',
|
||||
[INPUT_KEY_0] = ')', [INPUT_KEY_MINUS] = '_',
|
||||
[INPUT_KEY_EQUAL] = '+', [INPUT_KEY_BACKSPACE] = '\b',
|
||||
[INPUT_KEY_TAB] = '\t', [INPUT_KEY_Q] = 'Q',
|
||||
[INPUT_KEY_W] = 'W', [INPUT_KEY_E] = 'E',
|
||||
[INPUT_KEY_R] = 'R', [INPUT_KEY_T] = 'T',
|
||||
[INPUT_KEY_Y] = 'Y', [INPUT_KEY_U] = 'U',
|
||||
[INPUT_KEY_I] = 'I', [INPUT_KEY_O] = 'O',
|
||||
[INPUT_KEY_P] = 'P', [INPUT_KEY_LEFTBRACE] = '{',
|
||||
[INPUT_KEY_RIGHTBRACE] = '}', [INPUT_KEY_ENTER] = '\r',
|
||||
[INPUT_KEY_A] = 'A', [INPUT_KEY_S] = 'S',
|
||||
[INPUT_KEY_D] = 'D', [INPUT_KEY_F] = 'F',
|
||||
[INPUT_KEY_G] = 'G', [INPUT_KEY_H] = 'H',
|
||||
[INPUT_KEY_J] = 'J', [INPUT_KEY_K] = 'K',
|
||||
[INPUT_KEY_L] = 'L', [INPUT_KEY_SEMICOLON] = ':',
|
||||
[INPUT_KEY_APOSTROPHE] = '"', [INPUT_KEY_GRAVE] = '~',
|
||||
[INPUT_KEY_BACKSLASH] = '|', [INPUT_KEY_Z] = 'Z',
|
||||
[INPUT_KEY_X] = 'X', [INPUT_KEY_C] = 'C',
|
||||
[INPUT_KEY_V] = 'V', [INPUT_KEY_B] = 'B',
|
||||
[INPUT_KEY_N] = 'N', [INPUT_KEY_M] = 'M',
|
||||
[INPUT_KEY_COMMA] = '<', [INPUT_KEY_DOT] = '>',
|
||||
[INPUT_KEY_SLASH] = '?', [INPUT_KEY_KPASTERISK] = '*',
|
||||
[INPUT_KEY_SPACE] = ' ', [INPUT_KEY_KP7] = '7',
|
||||
[INPUT_KEY_KP8] = '8', [INPUT_KEY_KP9] = '9',
|
||||
[INPUT_KEY_KPMINUS] = '-', [INPUT_KEY_KP4] = '4',
|
||||
[INPUT_KEY_KP5] = '5', [INPUT_KEY_KP6] = '6',
|
||||
[INPUT_KEY_KPPLUS] = '+', [INPUT_KEY_KP1] = '1',
|
||||
[INPUT_KEY_KP2] = '2', [INPUT_KEY_KP3] = '3',
|
||||
[INPUT_KEY_KP0] = '0', [INPUT_KEY_KPDOT] = '.',
|
||||
[INPUT_KEY_KPENTER] = '\r', [INPUT_KEY_KPSLASH] = '/',
|
||||
};
|
||||
|
||||
static void consolethread() {
|
||||
bool left_ctrl = false;
|
||||
bool right_ctrl = false;
|
||||
bool left_shift = false;
|
||||
bool right_shift = false;
|
||||
|
||||
for (;;) {
|
||||
kbpacket_t packet;
|
||||
keyboard_wait(keyboard_console, &packet);
|
||||
if (packet.flags & KBPACKET_FLAGS_RELEASED)
|
||||
semaphore_wait(&input_sem, false);
|
||||
__assert(RINGBUFFER_DATACOUNT(&input_buffer) >= sizeof(input_event_t));
|
||||
|
||||
input_event_t ev;
|
||||
__assert(ringbuffer_read(&input_buffer, &ev, sizeof(input_event_t)) == sizeof(input_event_t));
|
||||
|
||||
if (ev.code == INPUT_KEY_LEFTCTRL) {
|
||||
left_ctrl = ev.value != 0;
|
||||
continue;
|
||||
} else if (ev.code == INPUT_KEY_RIGHTCTRL) {
|
||||
right_ctrl = ev.value != 0;
|
||||
continue;
|
||||
} else if (ev.code == INPUT_KEY_LEFTSHIFT) {
|
||||
left_shift = ev.value != 0;
|
||||
continue;
|
||||
} else if (ev.code == INPUT_KEY_RIGHTSHIFT) {
|
||||
right_shift = ev.value != 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ctrl = left_ctrl || right_ctrl;
|
||||
bool shift = left_shift || right_shift;
|
||||
|
||||
// we only care about key presses, not releases
|
||||
if (ev.value == 0)
|
||||
continue;
|
||||
|
||||
if (packet.ascii) {
|
||||
// control characters
|
||||
if (packet.flags & (KBPACKET_FLAGS_LEFTCTRL | KBPACKET_FLAGS_RIGHTCTRL)) {
|
||||
if (!((packet.ascii >= 'a' && packet.ascii <= 'z') || (packet.ascii >= 'A' && packet.ascii <= '\\')))
|
||||
char ascii = 0;
|
||||
if (shift) {
|
||||
if (ev.code < sizeof(key_to_ascii_shift))
|
||||
ascii = key_to_ascii_shift[ev.code];
|
||||
} else {
|
||||
if (ev.code < sizeof(key_to_ascii_normal))
|
||||
ascii = key_to_ascii_normal[ev.code];
|
||||
}
|
||||
|
||||
if (ascii != 0) {
|
||||
if (ctrl) {
|
||||
// control characters
|
||||
if (!((ascii >= 'a' && ascii <= 'z') || (ascii >= 'A' && ascii <= '\\')))
|
||||
continue;
|
||||
|
||||
packet.ascii = packet.ascii >= 'a' ? packet.ascii - 0x60 : packet.ascii - 0x40;
|
||||
ascii = ascii >= 'a' ? ascii - 0x60 : ascii - 0x40;
|
||||
}
|
||||
|
||||
tty_process(tty, packet.ascii);
|
||||
tty_process(tty, ascii);
|
||||
} else {
|
||||
// no ascii for key but we can send in a escape sequence for it
|
||||
char *target = NULL;
|
||||
switch (packet.keycode) {
|
||||
case KEYCODE_HOME:
|
||||
switch (ev.code) {
|
||||
case INPUT_KEY_HOME:
|
||||
target = HOME_STR;
|
||||
break;
|
||||
case KEYCODE_INSERT:
|
||||
case INPUT_KEY_INSERT:
|
||||
target = INSERT_STR;
|
||||
break;
|
||||
case KEYCODE_DELETE:
|
||||
case INPUT_KEY_DELETE:
|
||||
target = DELETE_STR;
|
||||
break;
|
||||
case KEYCODE_END:
|
||||
case INPUT_KEY_END:
|
||||
target = END_STR;
|
||||
break;
|
||||
case KEYCODE_PAGEUP:
|
||||
case INPUT_KEY_PAGEUP:
|
||||
target = PGUP_STR;
|
||||
break;
|
||||
case KEYCODE_PAGEDOWN:
|
||||
case INPUT_KEY_PAGEDOWN:
|
||||
target = PGDN_STR;
|
||||
break;
|
||||
case KEYCODE_UP:
|
||||
case INPUT_KEY_UP:
|
||||
target = UP_STR;
|
||||
break;
|
||||
case KEYCODE_DOWN:
|
||||
case INPUT_KEY_DOWN:
|
||||
target = DOWN_STR;
|
||||
break;
|
||||
case KEYCODE_RIGHT:
|
||||
case INPUT_KEY_RIGHT:
|
||||
target = RIGHT_STR;
|
||||
break;
|
||||
case KEYCODE_LEFT:
|
||||
case INPUT_KEY_LEFT:
|
||||
target = LEFT_STR;
|
||||
break;
|
||||
default:
|
||||
@@ -112,6 +239,9 @@ static void consolethread() {
|
||||
}
|
||||
|
||||
void console_init() {
|
||||
SEMAPHORE_INIT(&input_sem, 0);
|
||||
ringbuffer_init(&input_buffer, 128 * sizeof(input_event_t));
|
||||
|
||||
MUTEX_INIT(&writemutex);
|
||||
|
||||
thread = sched_newthread(consolethread, PAGE_SIZE * 16, 0, NULL, NULL);
|
||||
@@ -127,8 +257,8 @@ void console_init() {
|
||||
tty->winsize.ws_row = y;
|
||||
tty->winsize.ws_xpixel = fbx;
|
||||
tty->winsize.ws_ypixel = fby;
|
||||
|
||||
|
||||
logging_sethook(console_putc);
|
||||
}
|
||||
|
||||
INIT_ROUTINE_DEFINE(console, INIT_ROUTINE_FLAGS_NONE, console_init, scheduler, keyboard);
|
||||
INIT_ROUTINE_DEFINE(console, INIT_ROUTINE_FLAGS_NONE, console_init, scheduler);
|
||||
|
||||
Reference in New Issue
Block a user