Correctly implement main termios commands.
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user