From f95c36128325fa52687be20b93fa719ebf0b08d9 Mon Sep 17 00:00:00 2001 From: "Enrico Fraccaroli (Galfurian)" Date: Wed, 19 Jan 2022 22:50:45 -0500 Subject: [PATCH] Complete the implementation of ECHO, ECHOE, ICANON. --- libc/inc/ring_buffer.h | 22 ++++---- mentos/src/drivers/keyboard/keyboard.c | 4 +- mentos/src/io/proc_video.c | 74 ++++++++++++++++++++------ 3 files changed, 73 insertions(+), 27 deletions(-) diff --git a/libc/inc/ring_buffer.h b/libc/inc/ring_buffer.h index ee018ce..0abd0b0 100644 --- a/libc/inc/ring_buffer.h +++ b/libc/inc/ring_buffer.h @@ -42,6 +42,13 @@ } \ return item; \ } \ + static inline type fs_rb_##name##_pop_front(fs_rb_##name##_t *rb) \ + { \ + if (fs_rb_##name##_empty(rb)) \ + return init; \ + rb->write = (rb->write > 0) ? rb->write - 1 : rb->size - 1; \ + return rb->buffer[rb->write]; \ + } \ static inline type fs_rb_##name##_get(fs_rb_##name##_t *rb, unsigned index) \ { \ if (index < rb->size) \ @@ -50,18 +57,15 @@ } \ static inline type fs_rb_##name##_back(fs_rb_##name##_t *rb) \ { \ - if (!fs_rb_##name##_empty(rb)) \ - return rb->buffer[rb->read]; \ - return init; \ + if (fs_rb_##name##_empty(rb)) \ + return init; \ + return rb->buffer[rb->read]; \ } \ static inline type fs_rb_##name##_front(fs_rb_##name##_t *rb) \ { \ - if (!fs_rb_##name##_empty(rb)) { \ - if (rb->write > 0) \ - return rb->buffer[rb->write - 1]; \ - return rb->buffer[rb->size - 1]; \ - } \ - return init; \ + if (fs_rb_##name##_empty(rb)) \ + return init; \ + return rb->buffer[(rb->write > 0) ? rb->write - 1 : rb->size - 1]; \ } #ifdef __KERNEL__ diff --git a/mentos/src/drivers/keyboard/keyboard.c b/mentos/src/drivers/keyboard/keyboard.c index 5c649d5..cb90534 100644 --- a/mentos/src/drivers/keyboard/keyboard.c +++ b/mentos/src/drivers/keyboard/keyboard.c @@ -10,7 +10,7 @@ /// Change the header. #define __DEBUG_HEADER__ "[KEYBRD]" /// Set the log level. -#define __DEBUG_LEVEL__ LOGLEVEL_DEBUG +#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE #include "drivers/keyboard/keyboard.h" @@ -189,7 +189,7 @@ void keyboard_isr(pt_regs *f) keyboard_push_front('\b'); pr_debug("Press(KEY_BACKSPACE)\n"); } else if (scancode == KEY_DELETE) { - keyboard_push_front(127); + keyboard_push_front(0x7F); pr_debug("Press(KEY_DELETE)\n"); } else if ((scancode == KEY_ENTER) || (scancode == KEY_KP_RETURN)) { keyboard_push_front('\n'); diff --git a/mentos/src/io/proc_video.c b/mentos/src/io/proc_video.c index b9a583e..9849f98 100644 --- a/mentos/src/io/proc_video.c +++ b/mentos/src/io/proc_video.c @@ -44,35 +44,77 @@ static ssize_t procv_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyt task_struct *process = scheduler_get_current_process(); // Get a pointer to its ketboard ring-buffer. fs_rb_scancode_t *rb = &process->keyboard_rb; + // Pre-check the flags. + bool_t flg_icanon = bitmask_check(process->termios.c_lflag, ICANON) == ICANON; + bool_t flg_echoe = bitmask_check(process->termios.c_lflag, ECHOE) == ECHOE; + bool_t flg_echo = bitmask_check(process->termios.c_lflag, ECHO) == ECHO; + bool_t flg_isig = bitmask_check(process->termios.c_lflag, ISIG) == ISIG; // 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')) { + if (!fs_rb_scancode_empty(rb) && (!flg_icanon || (flg_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. + // Once we have dealt with the canonical mode, get the character. int c = keyboard_pop_back(); + // Check that it's a valid caracter. if (c < 0) return 0; + + // Keep only the character not the scancode. c &= 0x00FF; - // Add the character to the buffer. - fs_rb_scancode_push_front(rb, c); + + // We just received backspace. + if (c == '\b') { + // If !ECHOE and ECHO, We need to show the the `^?` string. + if (!flg_echoe && flg_echo) { + video_puts("^?"); + } + + // If we are in canonical mode, we pop the previous character. + if (flg_icanon) { + // Pop the previous character in buffer. + fs_rb_scancode_pop_front(rb); + // Delete the previous character on video. + if (flg_echoe) + video_putc(c); + } else { + // Add the character to the buffer. + fs_rb_scancode_push_front(rb, 0x7F); + // Return the character. + *((char *)buf) = fs_rb_scancode_pop_back(rb) & 0x00FF; + return 1; + } + return 0; + } else if (c == 0x7f) { + if (flg_echo) { + video_puts("^[[3~"); + } + // Add the character to the buffer. + fs_rb_scancode_push_front(rb, '\033'); + fs_rb_scancode_push_front(rb, '['); + fs_rb_scancode_push_front(rb, '3'); + fs_rb_scancode_push_front(rb, '~'); + return 0; + } else { + // 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)); - } + if (flg_echo) { + if (iscntrl(c) && (isalpha('A' + (c - 1)) && (c != '\n') && (c != '\b'))) { + video_putc('^'); + video_putc('A' + (c - 1)); } else { video_putc(c); } } - if (bitmask_check(process->termios.c_lflag, ISIG)) { + if (flg_isig) { if (iscntrl(c)) { if (c == 0x03) { sys_kill(process->pid, SIGTERM); @@ -84,7 +126,7 @@ static ssize_t procv_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyt // 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)) { + if (!flg_icanon) { *((char *)buf) = fs_rb_scancode_pop_back(rb) & 0x00FF; return 1; } @@ -103,14 +145,14 @@ static ssize_t procv_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyt 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)) { + if (flg_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)) { + if ((flg_icanon && (front_c == '\n')) || + !flg_icanon) { *((char *)buf) = keyboard_pop_back() & 0x00FF; return 1; } @@ -129,7 +171,7 @@ static ssize_t procv_read(vfs_file_t *file, char *buf, off_t offset, size_t nbyt return 0; } else { // Echo the character to video. - if (bitmask_check(process->termios.c_lflag, ECHO)) { + if (flg_echo) { video_putc(c & 0x00FF); } }