Espresso 0.0.2a

This commit is contained in:
2025-10-20 21:57:30 -05:00
parent 102d517097
commit ff6cba1164
59 changed files with 29272 additions and 773 deletions

View File

@ -2,7 +2,7 @@
#include <port_io.h>
#include <tty.h>
#include <stdlib.h>
#include <ksymtab.h>
#include <drivers/ps2_keyboard.h>
@ -29,6 +29,8 @@
#define KEYBOARD_IRQ 1
#define RETURN_STI() do { _sti_asm(); return; } while (0)
bool ps2keyboard_initialized = false;
/* State for shift key */
@ -41,14 +43,25 @@ static bool capslock_pressed = false;
static bool extended = false;
static bool is_new_char = false;
static bool is_new_key = false;
static bool is_new_key = false;
static bool gets_called = false;
static volatile bool gets_finished = false;
volatile unsigned char current_char;
volatile char* current_string = NULL;
volatile char* current_string = NULL;
volatile char* gets_string = NULL;
volatile int32_t current_length = 0;
volatile int32_t capacity = 0;
volatile int32_t gets_length = 0;
volatile int32_t capacity = 0;
volatile int32_t gets_capacity = 0;
volatile uint16_t current_key;
volatile ps2_hook_t* hooks = NULL;
volatile int hook_count = 0;
extern void _cli_asm(void);
extern void _sti_asm(void);
static const char scancode_map[128] = {
0, 27, '1','2','3','4','5','6','7','8','9','0','-','=','\b', /* Backspace */
@ -69,15 +82,134 @@ static const char scancode_map[128] = {
void keyboard_init(void)
{
#ifdef _DEBUG
printf("[ PS/2 KBD ] Initializing the PS/2 keyboard...\n");
#endif
outb(0x64, 0xAE); /* Enable keyboard interface (often optional, but here for safety) */
hooks = (ps2_hook_t*) malloc(sizeof(ps2_hook_t) * hook_count);
ps2keyboard_initialized = true;
#ifdef _DEBUG
printf("[ PS/2 KBD ] PS/2 Keyboard initialized\n");
#endif
}
bool setup_hook(ps2_hook_t func)
{
_cli_asm();
ps2_hook_t* copy = malloc(sizeof(ps2_hook_t) * hook_count);
if (hook_count > 0 && copy == NULL)
{
return false;
}
if (hook_count > 0)
{
memcpy(copy, hooks, sizeof(ps2_hook_t) * hook_count);
}
free((void*) hooks);
hooks = malloc(sizeof(ps2_hook_t) * (hook_count + 1));
if (hooks == NULL)
{
return false;
}
if (hook_count > 0)
{
memcpy((void*) hooks, copy, sizeof(ps2_hook_t) * hook_count);
}
free(copy);
hooks[hook_count] = func;
hook_count++;
_sti_asm();
return true;
}
bool remove_hook(ps2_hook_t func)
{
_cli_asm();
int index = -1;
for (int i = 0; i < hook_count; i++)
{
if (hooks[i] == func)
{
index = i;
break;
}
}
if (index == -1)
{
return false;
}
for (int i = index; i < hook_count - 1; i++)
{
hooks[i] = hooks[i + 1];
}
hook_count--;
if (hook_count == 0)
{
free((void*) hooks);
hooks = NULL;
return false;
}
ps2_hook_t* smaller = malloc(sizeof(ps2_hook_t) * hook_count);
if (smaller == NULL)
{
return false;
}
memcpy(smaller, (void*) hooks, sizeof(ps2_hook_t) * hook_count);
free((void*) hooks);
hooks = smaller;
_sti_asm();
return true;
}
void call_hooks(char c)
{
_cli_asm();
if (hook_count == 0)
{
return;
}
for (int i = 0; i < hook_count; i++)
{
hooks[i](c);
}
_sti_asm();
}
char get_char(void)
{
/*
ASCII code 5 (Enquiry) is/was used in legacy systems meant for requesting a response from a remote terminal or device.
For example, one system might send ENQ (ASCII 5), and the receiver could reply with ACK (ASCII 6) to indicate its ready or still online.
For example, one system might send ENQ (ASCII 5), and the receiver could reply with ACK (ASCII 6) to indicate it's ready or still online.
In modern computing, ENQ is largely obsolete:
@ -87,16 +219,13 @@ char get_char(void)
- It may still appear in legacy systems, embedded devices, or proprietary serial protocols, but that's niche.
*/
char temp = 5;
if (is_new_char)
if (!is_new_char)
{
temp = current_char;
return 5;
}
is_new_char = false;
return temp;
return current_char;
}
uint16_t get_key(void)
@ -122,39 +251,184 @@ char* get_string(void)
return current_string;
}
static void append_char(char c)
char* kbd_gets(void)
{
gets_called = true;
gets_finished = false;
while (gets_finished != true)
{
sleep(1);
}
char* result = strdup(gets_string); /* Could be NULL, that is checked below */
free(gets_string);
gets_string = NULL;
gets_capacity = 0;
gets_length = 0;
gets_called = false;
return result == NULL ? "" : result;
}
void gets_append_char(unsigned char c)
{
_cli_asm();
if (!gets_string && gets_capacity > 0)
{
printf("[keyboard] ERROR: gets_string is NULL but capacity > 0!\n");
RETURN_STI();
}
if (c == KEY_ARROW_UP || c == KEY_ARROW_DOWN || c == KEY_ARROW_RIGHT || c == KEY_ARROW_LEFT)
{
gets_string[1] = '\0';
char tc = '\0';
switch (c)
{
case KEY_ARROW_UP:
tc = KEY_UP;
break;
case KEY_ARROW_DOWN:
tc = KEY_DOWN;
break;
case KEY_ARROW_RIGHT:
tc = KEY_RIGHT;
break;
case KEY_ARROW_LEFT:
tc = KEY_LEFT;
break;
default:
tc = '\0';
break;
}
gets_string[0] = tc;
gets_finished = true;
RETURN_STI();
}
else if (c == '\n')
{
/* The returned string must/will not have newlines in it, so we return here after setting gets_finished to 'true'. */
gets_finished = true;
printf("\n");
RETURN_STI();
}
else if (c == 27) /* ASCII escape, here it's used to cancel input. */
{
gets_finished = true;
gets_string[0] = '\0';
RETURN_STI();
}
else if (c == '\b')
{
if (gets_length < 1)
{
RETURN_STI();
}
gets_length--;
gets_string[gets_length] = '\0';
printf("\b \b");
RETURN_STI();
}
if ((gets_length) >= gets_capacity)
{
int new_capacity = (gets_capacity == 0) ? 64 : gets_capacity * 2;
char* new_str = (char*) malloc(new_capacity);
if (!new_str)
{
RETURN_STI();
}
if (gets_string)
{
for (int i = 0; i < gets_length; i++)
{
new_str[i] = gets_string[i];
}
new_str[gets_length] = '\0';
free(gets_string);
}
gets_string = new_str;
gets_capacity = new_capacity;
}
if (!gets_string)
{
RETURN_STI();
}
gets_string[gets_length] = (char) c;
gets_length++;
gets_string[gets_length] = '\0';
printf("%c", c);
RETURN_STI();
}
void append_char(char c)
{
_cli_asm();
if (current_length + 1 >= capacity)
{
/* Need more space (+1 for the null zero) */
int new_capacity = (capacity == 0) ? 16 : capacity * 2;
char* new_str = (char*)malloc(new_capacity);
if (!new_str) {
char* new_str = (char*) malloc(new_capacity);
if (!new_str)
{
printf("[keyboard] ERROR: malloc failed for new input buffer\n");
return;
}
if (current_string)
{
memcpy(new_str, current_string, current_length);
free(current_string);
}
if (!current_string)
{
return;
}
current_string = new_str;
capacity = new_capacity;
}
if (!current_string)
{
return;
}
current_string[current_length] = c;
current_length++;
current_string[current_length] = '\0'; /* Maintain null terminator */
current_string[current_length] = '\0';
_sti_asm();
}
static void free_current_string(void)
void free_current_string(void)
{
if (current_string)
{
@ -198,8 +472,8 @@ void keyboard_handler(void)
}
else
{
uint16_t c = (uint16_t)scancode_map[scancode];
if ((shift_pressed ^ capslock_pressed) && ((char)c >= 'a') && ((char)c <= 'z'))
uint16_t c = (uint16_t) scancode_map[scancode];
if ((shift_pressed ^ capslock_pressed) && ((char) c >= 'a') && ((char) c <= 'z'))
{
c -= 32; /* Convert to uppercase */
}
@ -208,11 +482,10 @@ void keyboard_handler(void)
c = (uint16_t) terminal_get_shifted((unsigned char) c);
}
/*if (scancode == 0x1C) {
printf("\n");
return;
}*/
if (hook_count > 0)
{
call_hooks(c);
}
if (extended)
{
@ -235,6 +508,13 @@ void keyboard_handler(void)
break;
}
if (gets_called)
{
gets_append_char(c);
return;
}
current_key = c;
is_new_key = true;
@ -242,20 +522,35 @@ void keyboard_handler(void)
return;
}
if (gets_called)
{
gets_append_char(c);
return;
}
if (c)
{
if (c != '\n')
{
append_char(c);
}
current_char = c;
is_new_char = true;
if (c == '\n')
{
/*append_char(c);
current_char = c;
is_new_char = true;*/
free_current_string();
}
append_char(c);
}
}
}