From b77c53ae99a888371230429f174ce739db7b0366 Mon Sep 17 00:00:00 2001 From: xamidev Date: Wed, 18 Mar 2026 13:07:26 +0100 Subject: [PATCH] Keyboard buffer + getline --- docs/MANUAL.md | 27 +++++++++++++-- include/config.h | 3 ++ include/io/kbd/ps2.h | 5 +++ src/idt/idt.c | 2 +- src/io/kbd/ps2.c | 80 +++++++++++++++++++++++++++++++++++++++++++ src/kmain.c | 12 +++++-- src/sched/scheduler.c | 4 +-- 7 files changed, 125 insertions(+), 8 deletions(-) diff --git a/docs/MANUAL.md b/docs/MANUAL.md index 34195e4..35ac2c5 100644 --- a/docs/MANUAL.md +++ b/docs/MANUAL.md @@ -2,9 +2,30 @@ # Table of Contents -- nothing (yet). +- [Overview](#i-overview) + - [Supported Hardware](#a-supported-hardware) + - [Features](#b-features) +- [Kernel architecture](#ii-kernel-architecture) + - [Boot process](#a-boot-process) + - [Memory management](#b-memory-management) + - [Scheduling](#c-scheduling) + - [Input/output](#d-inputoutput) +- [Syscall table](#iii-syscall-table) -## I. Kernel architecture +## I. Overview + +## a. Supported Hardware + +The recommended hardware to run PepperOS is the following: + +- UEFI/BIOS +- Any x86 processor, 64-bits only +- PS/2 Keyboard +- Minimum 128MB of memory + +## b. Features + +## II. Kernel architecture ### a. Boot process @@ -14,6 +35,6 @@ ### d. Input/Output -## II. Syscall table +## III. Syscall table Not yet implemented. \ No newline at end of file diff --git a/include/config.h b/include/config.h index 8cab072..5c3dbc5 100644 --- a/include/config.h +++ b/include/config.h @@ -39,6 +39,9 @@ /* term */ #define TERM_HISTORY_MAX_LINES 256 +/* kbd */ +#define KBD_BUFFER_MAX 256 + /* time */ #define TIMER_FREQUENCY 1000 diff --git a/include/io/kbd/ps2.h b/include/io/kbd/ps2.h index c9aed30..55c12b5 100644 --- a/include/io/kbd/ps2.h +++ b/include/io/kbd/ps2.h @@ -7,7 +7,12 @@ #ifndef PS2_H #define PS2_H +#include + void keyboard_handler(void); +char keyboard_getchar(); +int keyboard_putchar(char c); +int keyboard_getline(char* output, size_t size); #define SHIFT_PRESSED_BIT 0b00000001 #define ALT_PRESSED_BIT 0b00000010 diff --git a/src/idt/idt.c b/src/idt/idt.c index 51b0eca..c101d05 100644 --- a/src/idt/idt.c +++ b/src/idt/idt.c @@ -258,7 +258,7 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context) case 33: // Keyboard Interrupt keyboard_handler(); - process_create("keyboard-initiated", kbdproc_main, NULL); // DEBUG + //process_create("keyboard-initiated", kbdproc_main, NULL); // DEBUG outb(0x20, 0x20); break; diff --git a/src/io/kbd/ps2.c b/src/io/kbd/ps2.c index e47d8a8..d36403a 100644 --- a/src/io/kbd/ps2.c +++ b/src/io/kbd/ps2.c @@ -4,6 +4,7 @@ * @license GPL-3.0-only */ +#include "config.h" #include #include #include @@ -18,6 +19,11 @@ uint8_t key_status = 0b00000000; unsigned char* keymap; unsigned char* keymap_shifted; +// Keyboard buffer +char keyboard_buffer[KBD_BUFFER_MAX] = {0}; +int write_index = 0; +int read_index = 0; + extern struct init_status init; unsigned char kbdus[128] = @@ -214,6 +220,7 @@ void keyboard_handler() } // Should probably have a keyboard buffer here... instead of this _putchar(c); + keyboard_putchar(c); } } } @@ -221,6 +228,79 @@ void keyboard_handler() } } +/* + * keyboard_getchar - Get a character from keyboard + * + * This function reads one character from the keyboard buffer. + * If the keyboard buffer is empty, it will block until a key + * is pressed. + * + * Return: + * - character from keyboard buffer + */ +char keyboard_getchar() +{ + while (read_index == write_index); // Empty buffer + + char c = keyboard_buffer[read_index]; + read_index = (read_index+1) % KBD_BUFFER_MAX; + return c; +} + +/* + * keyboard_putchar - Puts a character in the keyboard buffer + * @c: character to add + * + * This function is used in the keyboard handler to add new + * characters to the keyboard buffer. + * + * Return: + * %-1 - keyboard buffer is full + * %0 - operation completed successfully + */ +int keyboard_putchar(char c) +{ + if ((write_index+1) % KBD_BUFFER_MAX == read_index) { + // Full buffer + return -1; + } + + keyboard_buffer[write_index] = c; + write_index = (write_index+1) % KBD_BUFFER_MAX; + return 0; +} + +/* + * keyboard_getline - Gets a line of input from keyboard + * @output: Output string + * @size: Size of output string + * + * Read a line of characters from the keyboard, until the + * buffer fills or a newline character is read. + * The output string is NULL-terminated. + * + * Return: + * - the number of characters read + */ +int keyboard_getline(char* output, size_t size) +{ + char c; + size_t index = 0; + + // Read until Enter is pressed + while ((c = keyboard_getchar()) != 0x0A) { + if (index == size-1) { + output[index] = c; + output[index+1] = '\0'; + return index; + } + output[index] = c; + index++; + } + output[index+1] = '\0'; + return index; +} + /* * keyboard_init - Keyboard initialization * @layout: Desired layout diff --git a/src/kmain.c b/src/kmain.c index 37daa7f..139a515 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -68,7 +68,7 @@ struct process_t* idle_proc; // Never gets executed although pedicel is scheduled? void pedicel_main(void* arg) { - printf("\n\nWelcome to PepperOS! Pedicel speaking.\r\nNothing left to do, let's go idle!"); + printf("\n\nWelcome to PepperOS! Pedicel speaking.\r\nNothing left to do, let's go idle!\r\n"); } void idle_main(void* arg) @@ -78,6 +78,14 @@ void idle_main(void* arg) } } +void thing_main(void* arg) +{ + printf("What's your name, pal? "); + char name[10]; + keyboard_getline(name, 10); + printf("\r\n{%s} is such a nice name!\r\n", name); +} + extern uintptr_t kheap_start; /* @@ -118,7 +126,7 @@ void kmain() process_init(); idle_proc = process_create("idle", (void*)idle_main, 0); struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0); - + process_create("thing", thing_main, NULL); process_display_list(processes_list); scheduler_init(); diff --git a/src/sched/scheduler.c b/src/sched/scheduler.c index 932bcf2..3e98632 100644 --- a/src/sched/scheduler.c +++ b/src/sched/scheduler.c @@ -69,10 +69,10 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context) } } - DEBUG("current_process={pid=%u, name='%s', root_page_table[virt]=%p}", current_process->pid, current_process->name, current_process->root_page_table); + //DEBUG("current_process={pid=%u, name='%s', root_page_table[virt]=%p}", current_process->pid, current_process->name, current_process->root_page_table); load_cr3(VIRT_TO_PHYS((uint64_t)current_process->root_page_table)); - DEBUG("Loaded process PML4 into CR3"); + //DEBUG("Loaded process PML4 into CR3"); return current_process->context; } \ No newline at end of file