Espresso 0.0.2a
This commit is contained in:
@ -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 it’s 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user