From d19e1845f8f21b2ddb657f645e5b96991f7ee172 Mon Sep 17 00:00:00 2001 From: Enrico Fraccaroli Date: Wed, 12 Jan 2022 13:41:44 +0100 Subject: [PATCH] Disable ICANON for now. Use standardized fixed-size ring buffer inside the keyboard drivers. --- libc/inc/bits/termios-struct.h | 31 +++---- libc/inc/ring_buffer.h | 80 ++++++++-------- mentos/inc/drivers/keyboard/keyboard.h | 2 + mentos/src/drivers/keyboard/keyboard.c | 121 ++++++++----------------- mentos/src/io/proc_video.c | 13 ++- 5 files changed, 102 insertions(+), 145 deletions(-) diff --git a/libc/inc/bits/termios-struct.h b/libc/inc/bits/termios-struct.h index 694c3a0..134550a 100644 --- a/libc/inc/bits/termios-struct.h +++ b/libc/inc/bits/termios-struct.h @@ -26,19 +26,18 @@ typedef struct termios { speed_t c_ospeed; ///< output speed } termios_t; -/// @brief These flags generally control higher-level aspects of input processing than the input -/// modes flags described in Input Modes, such as echoing, signals, and the choice of canonical -/// or noncanonical input. -enum { - ISIG = 000001U, ///< Controls whether the INTR, QUIT, and SUSP characters are recognized. - ICANON = 000002U, ///< Enables canonical input processing mode. - ECHO = 000010U, ///< Echo input characters. - ECHOE = 000020U, ///< If ICANON is set, the ERASE character erases the preceding character. - ECHOK = 000040U, ///< If ICANON is set, the KILL character erases the current line. - ECHONL = 000100U, ///< If ICANON is set, echo the NL character even if ECHO is not set. - NOFLSH = 000200U, ///< Do not clear in/out queues when receiving INTR, QUIT, and SUSP. - TOSTOP = 000400U, ///< Allows SIGTTOU signals generated by background processes. - ECHOCTL = 001000U, ///< If this and ECHO are set, control characters with ‘^’ are echoed. - ECHOKE = 004000U, ///< If ICANON is set, KILL is echoed by erasing each character on the line. - IEXTEN = 100000U, ///< Enables implementation-defined input processing. -}; \ No newline at end of file +//These flags generally control higher-level aspects of input processing than +// the input modes flags described in Input Modes, such as echoing, signals, and +// the choice of canonical or noncanonical input. + +#define ISIG 0x00000080 ///< Controls whether the INTR, QUIT, and SUSP characters are recognized. +#define ICANON 0x00000100 ///< Enables canonical input processing mode. +#define ECHO 0x00000008 ///< Echo input characters. +#define ECHOE 0x00000002 ///< If ICANON is set, the ERASE character erases the preceding character. +#define ECHOK 0x00000004 ///< If ICANON is set, the KILL character erases the current line. +#define ECHONL 0x00000010 ///< If ICANON is set, echo the NL character even if ECHO is not set. +#define NOFLSH 0x80000000 ///< Do not clear in/out queues when receiving INTR, QUIT, and SUSP. +#define TOSTOP 0x00400000 ///< Allows SIGTTOU signals generated by background processes. +#define ECHOCTL 0x00000040 ///< If this and ECHO are set, control characters with ‘^’ are echoed. +#define ECHOKE 0x00000001 ///< If ICANON is set, KILL is echoed by erasing each character on the line. +#define IEXTEN 0x00000400 ///< Enables implementation-defined input processing. \ No newline at end of file diff --git a/libc/inc/ring_buffer.h b/libc/inc/ring_buffer.h index 50acb34..8af9bf0 100644 --- a/libc/inc/ring_buffer.h +++ b/libc/inc/ring_buffer.h @@ -5,45 +5,47 @@ #pragma once -#define DECLARE_FS_RING_BUFFER(type, name, length, init) \ - typedef struct rb_##name##_t { \ - unsigned size, read, write; \ - type buffer[length]; \ - } rb_##name##_t; \ - static inline void init_rb_##name(rb_##name##_t *rb) \ - { \ - rb->size = length; \ - rb->read = rb->write = 0; \ - memset(rb->buffer, init, sizeof(type) * length); \ - } \ - static inline void free_rb_##name(rb_##name##_t *rb) \ - { \ - kfree(rb->buffer); \ - } \ - static inline unsigned step_rb_##name(rb_##name##_t *rb, unsigned index) \ - { \ - return (index == (rb->size - 1)) ? 0 : index + 1; \ - } \ - static inline void push_rb_##name(rb_##name##_t *rb, type item) \ - { \ - if (step_rb_##name(rb, rb->write) == rb->read) \ - rb->read = step_rb_##name(rb, rb->read); \ - rb->buffer[rb->write] = item; \ - rb->write = step_rb_##name(rb, rb->write); \ - } \ - static inline type pop_rb_##name(rb_##name##_t *rb) \ - { \ - type item = init; \ - if (rb->write != rb->read) { \ - item = rb->buffer[rb->read]; \ - rb->read = step_rb_##name(rb, rb->read); \ - } \ - return item; \ - } \ - static inline void get_rb_##name(rb_##name##_t *rb, unsigned index, type *item) \ - { \ - if (index < rb->size) \ - *item = rb->buffer[index]; \ +#define DECLARE_FIXED_SIZE_RING_BUFFER(type, name, length, init) \ + typedef struct fs_rb_##name##_t { \ + unsigned size, read, write; \ + type buffer[length]; \ + } fs_rb_##name##_t; \ + static inline void fs_rb_##name##_init(fs_rb_##name##_t *rb) \ + { \ + rb->size = length; \ + rb->read = rb->write = 0; \ + char *dst = (char *)rb->buffer; \ + long num = sizeof(type) * length; \ + while (num--) *dst++ = (char)(init & 0xFF); \ + } \ + static inline unsigned fs_rb_##name##_step(fs_rb_##name##_t *rb, unsigned index) \ + { \ + return (index == (rb->size - 1)) ? 0 : index + 1; \ + } \ + static inline void fs_rb_##name##_push(fs_rb_##name##_t *rb, type item) \ + { \ + if (fs_rb_##name##_step(rb, rb->write) == rb->read) \ + rb->read = fs_rb_##name##_step(rb, rb->read); \ + rb->buffer[rb->write] = item; \ + rb->write = fs_rb_##name##_step(rb, rb->write); \ + } \ + static inline type fs_rb_##name##_empty(fs_rb_##name##_t *rb) \ + { \ + return rb->write == rb->read; \ + } \ + static inline type fs_rb_##name##_pop(fs_rb_##name##_t *rb) \ + { \ + type item = init; \ + if (rb->write != rb->read) { \ + item = rb->buffer[rb->read]; \ + rb->read = fs_rb_##name##_step(rb, rb->read); \ + } \ + return item; \ + } \ + static inline void fs_rb_##name##_get(fs_rb_##name##_t *rb, unsigned index, type *item) \ + { \ + if (index < rb->size) \ + *item = rb->buffer[index]; \ } #ifdef __KERNEL__ diff --git a/mentos/inc/drivers/keyboard/keyboard.h b/mentos/inc/drivers/keyboard/keyboard.h index 17fbd8c..4835208 100644 --- a/mentos/inc/drivers/keyboard/keyboard.h +++ b/mentos/inc/drivers/keyboard/keyboard.h @@ -10,8 +10,10 @@ #pragma once +#include "ring_buffer.h" #include "kernel.h" +DECLARE_FIXED_SIZE_RING_BUFFER(int, scancode, 256, -1) /// @brief The interrupt service routine of the keyboard. /// @param f The interrupt stack frame. diff --git a/mentos/src/drivers/keyboard/keyboard.c b/mentos/src/drivers/keyboard/keyboard.c index c39b63c..9b7f5d8 100644 --- a/mentos/src/drivers/keyboard/keyboard.c +++ b/mentos/src/drivers/keyboard/keyboard.c @@ -27,22 +27,12 @@ #include "ring_buffer.h" #include "string.h" -/// The dimension of the circular buffer used to store video history. -#define BUFSIZE 256 - -/// A macro from Ivan to update buffer indexes. -#define STEP(x) (((x) == BUFSIZE - 1) ? 0 : ((x) + 1)) - -/// Circular Buffer where the pressed keys are stored. -static int circular_buffer[BUFSIZE] = { 0 }; -/// Index inside the buffer... -static long buf_r = 0; -/// Index inside the buffer... -static long buf_w = 0; /// Tracks the state of the leds. static uint8_t ledstate = 0; /// The flags concerning the keyboard. static uint32_t kflags = 0; +/// Where we store the keypress. +fs_rb_scancode_t scancodes; #define KBD_LEFT_SHIFT (1 << 0) ///< Flag which identifies the left shift. #define KBD_RIGHT_SHIFT (1 << 1) ///< Flag which identifies the right shift. @@ -54,28 +44,6 @@ static uint32_t kflags = 0; #define KBD_LEFT_ALT (1 << 7) ///< Flag which identifies the left alt. #define KBD_RIGHT_ALT (1 << 8) ///< Flag which identifies the right alt. -static inline void push_character(int c) -{ - // Update buffer. - if (STEP(buf_w) == buf_r) { - buf_r = STEP(buf_r); - } - - circular_buffer[buf_w] = c & 0x00FF; - - buf_w = STEP(buf_w); -} - -static inline int read_character() -{ - int c = -1; - if (buf_r != buf_w) { - c = circular_buffer[buf_r]; - buf_r = STEP(buf_r); - } - return c; -} - static inline bool_t get_keypad_number(int scancode) { if (scancode == KEY_KP0) @@ -134,11 +102,11 @@ void keyboard_isr(pt_regs *f) pr_debug("Press(KBD_RIGHT_CONTROL)\n"); } else if (scancode == KEY_LEFT_ALT) { bitmask_set_assign(kflags, KBD_LEFT_ALT); - push_character(scancode << 16u); + fs_rb_scancode_push(&scancodes, scancode << 16u); pr_debug("Press(KBD_LEFT_ALT)\n"); } else if (scancode == KEY_RIGHT_ALT) { bitmask_set_assign(kflags, KBD_RIGHT_ALT); - push_character(scancode << 16u); + fs_rb_scancode_push(&scancodes, scancode << 16u); pr_debug("Press(KBD_RIGHT_ALT)\n"); } else if (scancode == (KEY_LEFT_SHIFT | CODE_BREAK)) { bitmask_clear_assign(kflags, KBD_LEFT_SHIFT); @@ -171,52 +139,54 @@ void keyboard_isr(pt_regs *f) keyboard_update_leds(); pr_debug("Toggle(KBD_SCROLL_LOCK)\n"); } else if (scancode == KEY_BACKSPACE) { - push_character('\b'); + fs_rb_scancode_push(&scancodes, '\b'); pr_debug("Press(KEY_BACKSPACE)\n"); } else if (scancode == KEY_DELETE) { - push_character(127); + fs_rb_scancode_push(&scancodes, 127); pr_debug("Press(KEY_DELETE)\n"); } else if ((scancode == KEY_ENTER) || (scancode == KEY_KP_RETURN)) { - push_character('\n'); + fs_rb_scancode_push(&scancodes, '\n'); pr_debug("Press(KEY_ENTER)\n"); } else if ((scancode == KEY_PAGE_UP) || (keypad_fun_number == 9)) { - push_character(scancode); + fs_rb_scancode_push(&scancodes, scancode); pr_debug("Press(KEY_PAGE_UP)\n"); } else if ((scancode == KEY_PAGE_DOWN) || (keypad_fun_number == 2)) { - push_character(scancode); + fs_rb_scancode_push(&scancodes, scancode); pr_debug("Press(KEY_PAGE_DOWN)\n"); } else if ((scancode == KEY_UP_ARROW) || (keypad_fun_number == 8)) { pr_debug("Press(KEY_UP_ARROW)\n"); - push_character('\033'); - push_character('['); - push_character('A'); + fs_rb_scancode_push(&scancodes, '\033'); + fs_rb_scancode_push(&scancodes, '['); + fs_rb_scancode_push(&scancodes, 'A'); } else if ((scancode == KEY_DOWN_ARROW) || (keypad_fun_number == 2)) { pr_debug("Press(KEY_DOWN_ARROW)\n"); - push_character('\033'); - push_character('['); - push_character('B'); + fs_rb_scancode_push(&scancodes, '\033'); + fs_rb_scancode_push(&scancodes, '['); + fs_rb_scancode_push(&scancodes, 'B'); } else if ((scancode == KEY_RIGHT_ARROW) || (keypad_fun_number == 6)) { pr_debug("Press(KEY_RIGHT_ARROW)\n"); - push_character('\033'); - push_character('['); - push_character('C'); + fs_rb_scancode_push(&scancodes, '\033'); + fs_rb_scancode_push(&scancodes, '['); + fs_rb_scancode_push(&scancodes, 'C'); } else if ((scancode == KEY_LEFT_ARROW) || (keypad_fun_number == 4)) { pr_debug("Press(KEY_LEFT_ARROW)\n"); - push_character('\033'); - push_character('['); - push_character('D'); + fs_rb_scancode_push(&scancodes, '\033'); + fs_rb_scancode_push(&scancodes, '['); + fs_rb_scancode_push(&scancodes, 'D'); } else if ((scancode == KEY_HOME) || (keypad_fun_number == 7)) { pr_debug("Press(KEY_HOME)\n"); - push_character('\033'); - push_character('['); - push_character('H'); + fs_rb_scancode_push(&scancodes, '\033'); + fs_rb_scancode_push(&scancodes, '['); + fs_rb_scancode_push(&scancodes, 'H'); } else if ((scancode == KEY_END) || (keypad_fun_number == 1)) { pr_debug("Press(KEY_END)\n"); - push_character('\033'); - push_character('['); - push_character('F'); + fs_rb_scancode_push(&scancodes, '\033'); + fs_rb_scancode_push(&scancodes, '['); + fs_rb_scancode_push(&scancodes, 'F'); } else if (scancode == KEY_ESCAPE) { // Nothing to do. + } else if (keypad_fun_number == 5) { + // Nothing to do. } else if (!(scancode & CODE_BREAK)) { // Get the current keymap. const keymap_t *keymap = get_keymap(scancode); @@ -231,33 +201,16 @@ void keyboard_isr(pt_regs *f) #endif int character = 0; if (!bitmask_check(kflags, KBD_LEFT_SHIFT | KBD_RIGHT_SHIFT) != !bitmask_check(kflags, KBD_CAPS_LOCK)) { - push_character(keymap->shift); + fs_rb_scancode_push(&scancodes, keymap->shift); } else if ((get_keymap_type() == KEYMAP_IT) && bitmask_check(kflags, KBD_RIGHT_ALT) && (bitmask_check(kflags, KBD_LEFT_SHIFT | KBD_RIGHT_SHIFT))) { - push_character(keymap->alt); + fs_rb_scancode_push(&scancodes, keymap->alt); } else if (bitmask_check(kflags, KBD_RIGHT_ALT)) { - push_character(keymap->alt); - } else if (get_keypad_number(scancode) && bitmask_check(kflags, KBD_NUM_LOCK)) { - push_character(keymap->normal); + fs_rb_scancode_push(&scancodes, keymap->alt); + } else if (bitmask_check(kflags, KBD_LEFT_CONTROL | KBD_RIGHT_CONTROL)) { + fs_rb_scancode_push(&scancodes, keymap->ctrl); } else { - push_character(keymap->normal); + fs_rb_scancode_push(&scancodes, keymap->normal); } - // Parse the key. - /* - else if () { - character = keymap->alt[scancode]; - } - // We have failed to retrieve the character. - if (character <= 0) { - break; - } - if (bitmask_check(kflags, KBD_LEFT_CONTROL | KBD_RIGHT_CONTROL)) { - push_character('\033'); - push_character('^'); - character = toupper(character); - } - // Update buffer. - push_character(character); - */ } pic8259_send_eoi(IRQ_KEYBOARD); } @@ -286,11 +239,13 @@ void keyboard_disable() int keyboard_getc() { - return read_character(); + return fs_rb_scancode_pop(&scancodes); } int keyboard_initialize() { + // Initialize the ring-buffer for the scancodes. + fs_rb_scancode_init(&scancodes); // Initialize the keymaps. init_keymaps(); // Install the IRQ. diff --git a/mentos/src/io/proc_video.c b/mentos/src/io/proc_video.c index 786cd04..6122d5b 100644 --- a/mentos/src/io/proc_video.c +++ b/mentos/src/io/proc_video.c @@ -40,18 +40,17 @@ static ssize_t procv_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyt video_shift_one_page_up(); return 0; } else { + pr_debug("'%c' (0x%04x)\n", c, c); // Get the currently running process. task_struct *process = scheduler_get_current_process(); - // Return the character. - *((char *)buf) = c & 0x00FF; + // Echo the character to video. if (bitmask_check(process->termios.c_lflag, ECHO)) { - if ((c == '\b') && - (!bitmask_check(process->termios.c_lflag, ICANON) || !bitmask_check(process->termios.c_lflag, ECHOE))) { - return 1; - } - // Echo the character to video. video_putc(c & 0x00FF); } + // Return the character. + //if (!bitmask_check(process->termios.c_lflag, ICANON)) { + *((char *)buf) = c & 0x00FF; + //} } return 1; }