Correctly implement main termios commands.

This commit is contained in:
Enrico Fraccaroli (Galfurian)
2022-01-14 09:13:00 -05:00
parent 455c555223
commit df1c5352c4
5 changed files with 187 additions and 57 deletions
+11 -4
View File
@@ -28,10 +28,17 @@ void keyboard_disable();
/// @brief Leds handler.
void keyboard_update_leds();
/// @brief Get a char from the buffer.
/// @details It loops until there is something new to read.
/// @return The read character.
int keyboard_getc();
/// @brief Gets and removes a char from the back of the buffer.
/// @return The extracted character.
int keyboard_pop_back();
/// @brief Gets a char from the back of the buffer.
/// @return The read character.
int keyboard_back();
/// @brief Gets a char from the front of the buffer.
/// @return The read character.
int keyboard_front();
/// @brief Initializes the keyboard drivers.
/// @return 0 on success, 1 on error.
+3
View File
@@ -5,6 +5,7 @@
#pragma once
#include "drivers/keyboard/keyboard.h"
#include "bits/termios-struct.h"
#include "system/signal.h"
#include "devices/fpu.h"
@@ -150,6 +151,8 @@ typedef struct task_struct {
/// Process-wise terminal options.
termios_t termios;
/// Buffer for managing inputs from keyboard.
fs_rb_scancode_t keyboard_rb;
//==== Future work =========================================================
// - task's attributes:
+79 -43
View File
@@ -33,6 +33,8 @@ static uint8_t ledstate = 0;
static uint32_t kflags = 0;
/// Where we store the keypress.
fs_rb_scancode_t scancodes;
/// Spinlock to protect access to the scancode buffer.
spinlock_t scancodes_lock;
#define KBD_LEFT_SHIFT (1 << 0) ///< Flag which identifies the left shift.
#define KBD_RIGHT_SHIFT (1 << 1) ///< Flag which identifies the right shift.
@@ -69,6 +71,51 @@ static inline bool_t get_keypad_number(int scancode)
return -1;
}
static inline void keyboard_push_front(int c)
{
if (c >= 0) {
spinlock_lock(&scancodes_lock);
fs_rb_scancode_push_front(&scancodes, c);
spinlock_unlock(&scancodes_lock);
}
}
int keyboard_pop_back()
{
int c;
spinlock_lock(&scancodes_lock);
if (!fs_rb_scancode_empty(&scancodes))
c = fs_rb_scancode_pop_back(&scancodes);
else
c = -1;
spinlock_unlock(&scancodes_lock);
return c;
}
int keyboard_back()
{
int c;
spinlock_lock(&scancodes_lock);
if (!fs_rb_scancode_empty(&scancodes))
c = fs_rb_scancode_back(&scancodes);
else
c = -1;
spinlock_unlock(&scancodes_lock);
return c;
}
int keyboard_front()
{
int c = -1;
spinlock_lock(&scancodes_lock);
if (!fs_rb_scancode_empty(&scancodes))
c = fs_rb_scancode_front(&scancodes);
else
c = -1;
spinlock_unlock(&scancodes_lock);
return c;
}
void keyboard_isr(pt_regs *f)
{
unsigned int scancode;
@@ -102,11 +149,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);
fs_rb_scancode_push(&scancodes, scancode << 16u);
keyboard_push_front(scancode << 16u);
pr_debug("Press(KBD_LEFT_ALT)\n");
} else if (scancode == KEY_RIGHT_ALT) {
bitmask_set_assign(kflags, KBD_RIGHT_ALT);
fs_rb_scancode_push(&scancodes, scancode << 16u);
keyboard_push_front(scancode << 16u);
pr_debug("Press(KBD_RIGHT_ALT)\n");
} else if (scancode == (KEY_LEFT_SHIFT | CODE_BREAK)) {
bitmask_clear_assign(kflags, KBD_LEFT_SHIFT);
@@ -139,50 +186,50 @@ void keyboard_isr(pt_regs *f)
keyboard_update_leds();
pr_debug("Toggle(KBD_SCROLL_LOCK)\n");
} else if (scancode == KEY_BACKSPACE) {
fs_rb_scancode_push(&scancodes, '\b');
keyboard_push_front('\b');
pr_debug("Press(KEY_BACKSPACE)\n");
} else if (scancode == KEY_DELETE) {
fs_rb_scancode_push(&scancodes, 127);
keyboard_push_front(127);
pr_debug("Press(KEY_DELETE)\n");
} else if ((scancode == KEY_ENTER) || (scancode == KEY_KP_RETURN)) {
fs_rb_scancode_push(&scancodes, '\n');
keyboard_push_front('\n');
pr_debug("Press(KEY_ENTER)\n");
} else if ((scancode == KEY_PAGE_UP) || (keypad_fun_number == 9)) {
fs_rb_scancode_push(&scancodes, scancode);
keyboard_push_front(scancode);
pr_debug("Press(KEY_PAGE_UP)\n");
} else if ((scancode == KEY_PAGE_DOWN) || (keypad_fun_number == 2)) {
fs_rb_scancode_push(&scancodes, scancode);
keyboard_push_front(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");
fs_rb_scancode_push(&scancodes, '\033');
fs_rb_scancode_push(&scancodes, '[');
fs_rb_scancode_push(&scancodes, 'A');
keyboard_push_front('\033');
keyboard_push_front('[');
keyboard_push_front('A');
} else if ((scancode == KEY_DOWN_ARROW) || (keypad_fun_number == 2)) {
pr_debug("Press(KEY_DOWN_ARROW)\n");
fs_rb_scancode_push(&scancodes, '\033');
fs_rb_scancode_push(&scancodes, '[');
fs_rb_scancode_push(&scancodes, 'B');
keyboard_push_front('\033');
keyboard_push_front('[');
keyboard_push_front('B');
} else if ((scancode == KEY_RIGHT_ARROW) || (keypad_fun_number == 6)) {
pr_debug("Press(KEY_RIGHT_ARROW)\n");
fs_rb_scancode_push(&scancodes, '\033');
fs_rb_scancode_push(&scancodes, '[');
fs_rb_scancode_push(&scancodes, 'C');
keyboard_push_front('\033');
keyboard_push_front('[');
keyboard_push_front('C');
} else if ((scancode == KEY_LEFT_ARROW) || (keypad_fun_number == 4)) {
pr_debug("Press(KEY_LEFT_ARROW)\n");
fs_rb_scancode_push(&scancodes, '\033');
fs_rb_scancode_push(&scancodes, '[');
fs_rb_scancode_push(&scancodes, 'D');
keyboard_push_front('\033');
keyboard_push_front('[');
keyboard_push_front('D');
} else if ((scancode == KEY_HOME) || (keypad_fun_number == 7)) {
pr_debug("Press(KEY_HOME)\n");
fs_rb_scancode_push(&scancodes, '\033');
fs_rb_scancode_push(&scancodes, '[');
fs_rb_scancode_push(&scancodes, 'H');
keyboard_push_front('\033');
keyboard_push_front('[');
keyboard_push_front('H');
} else if ((scancode == KEY_END) || (keypad_fun_number == 1)) {
pr_debug("Press(KEY_END)\n");
fs_rb_scancode_push(&scancodes, '\033');
fs_rb_scancode_push(&scancodes, '[');
fs_rb_scancode_push(&scancodes, 'F');
keyboard_push_front('\033');
keyboard_push_front('[');
keyboard_push_front('F');
} else if (scancode == KEY_ESCAPE) {
// Nothing to do.
} else if (keypad_fun_number == 5) {
@@ -191,25 +238,17 @@ void keyboard_isr(pt_regs *f)
// Get the current keymap.
const keymap_t *keymap = get_keymap(scancode);
// Get the specific keymap.
#if 0
pr_debug("%04x '%c' (%04x) '%c' (%04x) '%c' (%04x) '%c' (%04x))\n",
scancode,
((0x00ff & keymap->normal) >= 32) ? keymap->normal : ' ', keymap->normal,
((0x00ff & keymap->shift) >= 32) ? keymap->shift : ' ', keymap->shift,
((0x00ff & keymap->ctrl) >= 32) ? keymap->ctrl : ' ', keymap->ctrl,
((0x00ff & keymap->alt) >= 32) ? keymap->alt : ' ', keymap->alt);
#endif
int character = 0;
if (!bitmask_check(kflags, KBD_LEFT_SHIFT | KBD_RIGHT_SHIFT) != !bitmask_check(kflags, KBD_CAPS_LOCK)) {
fs_rb_scancode_push(&scancodes, keymap->shift);
keyboard_push_front(keymap->shift);
} else if ((get_keymap_type() == KEYMAP_IT) && bitmask_check(kflags, KBD_RIGHT_ALT) && (bitmask_check(kflags, KBD_LEFT_SHIFT | KBD_RIGHT_SHIFT))) {
fs_rb_scancode_push(&scancodes, keymap->alt);
keyboard_push_front(keymap->alt);
} else if (bitmask_check(kflags, KBD_RIGHT_ALT)) {
fs_rb_scancode_push(&scancodes, keymap->alt);
keyboard_push_front(keymap->alt);
} else if (bitmask_check(kflags, KBD_LEFT_CONTROL | KBD_RIGHT_CONTROL)) {
fs_rb_scancode_push(&scancodes, keymap->ctrl);
keyboard_push_front(keymap->ctrl);
} else {
fs_rb_scancode_push(&scancodes, keymap->normal);
keyboard_push_front(keymap->normal);
}
}
pic8259_send_eoi(IRQ_KEYBOARD);
@@ -237,15 +276,12 @@ void keyboard_disable()
outportb(0x60, 0xF5);
}
int keyboard_getc()
{
return fs_rb_scancode_pop(&scancodes);
}
int keyboard_initialize()
{
// Initialize the ring-buffer for the scancodes.
fs_rb_scancode_init(&scancodes);
// Initialize the spinlock.
spinlock_init(&scancodes_lock);
// Initialize the keymaps.
init_keymaps();
// Install the IRQ.
+92 -10
View File
@@ -24,13 +24,101 @@
#include "ctype.h"
#include "process/scheduler.h"
void print_rb(fs_rb_scancode_t *rb)
{
if (!fs_rb_scancode_empty(rb)) {
for (unsigned i = rb->read; (i < rb->write) && (i < rb->size); ++i) {
pr_debug("%c", rb->buffer[i]);
}
pr_debug("\n");
}
}
static ssize_t procv_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyte)
{
if (buf == NULL) {
// Stop if the buffer is invalid.
if (buf == NULL)
return -1;
// Get the currently running process.
task_struct *process = scheduler_get_current_process();
// Get a pointer to its ketboard ring-buffer.
fs_rb_scancode_t *rb = &process->keyboard_rb;
// If we are in canonical mode, and the last inserted element is a newline,
// we pop the buffer until it's empty.
if (bitmask_check(process->termios.c_lflag, ICANON) && (fs_rb_scancode_front(rb) == '\n')) {
*((char *)buf) = fs_rb_scancode_pop_back(rb) & 0x00FF;
return 1;
}
// Once we have dealt with the canonical mode, get the characgter.
int c = keyboard_pop_back();
// Check that it's a valid caracter.
if (c < 0)
return 0;
c &= 0x00FF;
// Add the character to the buffer.
fs_rb_scancode_push_front(rb, c);
// If echo is activated, output the character to video.
if (bitmask_check(process->termios.c_lflag, ECHO)) {
if (iscntrl(c)) {
if (isalpha('A' + (c - 1)) && (c != '\n')) {
video_putc('^');
video_putc('A' + (c - 1));
}
} else {
video_putc(c);
}
}
if (bitmask_check(process->termios.c_lflag, ISIG)) {
if (iscntrl(c)) {
if (c == 0x03) {
sys_kill(process->pid, SIGTERM);
} else if (c == 0x1A) {
sys_kill(process->pid, SIGSTOP);
}
}
}
// If we are NOT in canonical mode, we can send the character back to user
// right away.
if (!bitmask_check(process->termios.c_lflag, ICANON)) {
*((char *)buf) = fs_rb_scancode_pop_back(rb) & 0x00FF;
return 1;
}
#if 0
// The last inserted character.
int back_c = keyboard_back();
if (back_c < 0)
return 0;
// The first inserted character.
int front_c = keyboard_front();
pr_debug("'%c' (%3d %04x) [F: '%c' (%04x)]\n", back_c, back_c, back_c, front_c, front_c);
// Echo the character to video.
if (bitmask_check(process->termios.c_lflag, ECHO)) {
video_putc(back_c & 0x00FF);
}
// If we have the canonical input active, we should not return characters,
// until we receive a newline.
if ((bitmask_check(process->termios.c_lflag, ICANON) && (front_c == '\n')) ||
!bitmask_check(process->termios.c_lflag, ICANON)) {
*((char *)buf) = keyboard_pop_back() & 0x00FF;
return 1;
}
#endif
#if 0
// Read the character from the keyboard.
int c = keyboard_getc();
int c = keyboard_getc(false) & 0x00FF;
if (c < 0)
return 0;
if (c == KEY_PAGE_UP) {
@@ -40,19 +128,13 @@ 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();
// Echo the character to video.
if (bitmask_check(process->termios.c_lflag, ECHO)) {
video_putc(c & 0x00FF);
}
// Return the character.
//if (!bitmask_check(process->termios.c_lflag, ICANON)) {
*((char *)buf) = c & 0x00FF;
//}
}
return 1;
#endif
return 0;
}
static ssize_t procv_write(vfs_file_t *file, const void *buf, off_t offset, size_t nbyte)
+2
View File
@@ -236,6 +236,8 @@ static inline task_struct *__alloc_task(task_struct *source, task_struct *parent
.c_oflag = 0,
.c_iflag = 0
};
// Initialize the ringbuffer.
fs_rb_scancode_init(&proc->keyboard_rb);
return proc;
}