Disable ICANON for now. Use standardized fixed-size ring buffer inside the keyboard drivers.

This commit is contained in:
Enrico Fraccaroli
2022-01-12 13:41:44 +01:00
parent 4a29a27204
commit d19e1845f8
5 changed files with 102 additions and 145 deletions
+15 -16
View File
@@ -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.
};
//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.
+41 -39
View File
@@ -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__
+2
View File
@@ -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.
+38 -83
View File
@@ -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.
+6 -7
View File
@@ -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;
}