From 49c1bad935c7e2cd9f4c11788855613121626119 Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sun, 18 Jan 2026 16:20:43 -0800 Subject: [PATCH 01/10] Create hid.h Adding base HID device support for early HID standards 1.0 --- kernel/hid.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 kernel/hid.h diff --git a/kernel/hid.h b/kernel/hid.h new file mode 100644 index 0000000..68029ae --- /dev/null +++ b/kernel/hid.h @@ -0,0 +1,46 @@ +#ifndef HID_H +#define HID_H + +#include +#include + +// HID Report types +#define HID_REPORT_INPUT 0x01 +#define HID_REPORT_OUTPUT 0x02 +#define HID_REPORT_FEATURE 0x03 + +// HID usage page constants (USB HID) +#define HID_USAGE_PAGE_GENERIC 0x01 +#define HID_USAGE_KEYBOARD 0x06 +#define HID_USAGE_MOUSE 0x02 + +// HID keyboard and mouse data +typedef struct { + uint8_t modifier; // Modifier keys (shift, ctrl, alt, etc.) + uint8_t reserved; // Reserved byte + uint8_t keycodes[6]; // Keycodes for keys pressed +} keyboard_hid_report_t; + +typedef struct { + uint8_t buttons; // Mouse buttons (bitwise: 0x01 = left, 0x02 = right, 0x04 = middle) + int8_t x; // X axis movement + int8_t y; // Y axis movement + int8_t wheel; // Mouse wheel +} mouse_hid_report_t; + +// Initialize the HID subsystem +void hid_init(void); + +// Process an incoming HID report +void hid_process_report(uint8_t* report, uint8_t length); + +// Process HID keyboard report +void hid_process_keyboard_report(const keyboard_hid_report_t* report); + +// Process HID mouse report +void hid_process_mouse_report(const mouse_hid_report_t* report); + +// USB HID report descriptor parsing +bool hid_parse_descriptor(uint8_t* descriptor, uint32_t length); + +#endif // HID_H From cca6aafd65e22d482a4db162aafc6974c5bd6b64 Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sun, 18 Jan 2026 16:21:45 -0800 Subject: [PATCH 02/10] Create hid.c Add bass HID implementation --- kernel/hid.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 kernel/hid.c diff --git a/kernel/hid.c b/kernel/hid.c new file mode 100644 index 0000000..5192d01 --- /dev/null +++ b/kernel/hid.c @@ -0,0 +1,66 @@ +#include "hid.h" +#include "usb.h" +#include "mouse.h" +#include "keyboard.h" +#include "print.h" +#include +#include + +// Global variables +static bool hid_initialized = false; + +void hid_init(void) { + if (hid_initialized) return; + hid_initialized = true; + + // Initialize keyboard and mouse HID handling + keyboard_init(); + // Assume USB mouse has been initialized and is connected. + usb_hid_init(); // Initializes USB HID for both keyboard and mouse +} + +void hid_process_report(uint8_t* report, uint8_t length) { + // Process the HID report based on its type + if (length == 8) { // Assuming a standard 8-byte report for HID keyboard + keyboard_hid_report_t* k_report = (keyboard_hid_report_t*) report; + hid_process_keyboard_report(k_report); + } else if (length == 3) { // Assuming a standard 3-byte report for HID mouse + mouse_hid_report_t* m_report = (mouse_hid_report_t*) report; + hid_process_mouse_report(m_report); + } +} + +// Handle HID keyboard report +void hid_process_keyboard_report(const keyboard_hid_report_t* report) { + // Iterate over the keycodes and process key presses + for (int i = 0; i < 6; i++) { + uint8_t keycode = report->keycodes[i]; + if (keycode != 0) { + char key = scancode_map[keycode]; + if (key) { + keyboard_buffer_add(key); + } + } + } +} + +// Handle HID mouse report +void hid_process_mouse_report(const mouse_hid_report_t* report) { + // Process mouse movement and button clicks + mouse_data.x += report->x; + mouse_data.y += report->y; + mouse_data.left_button = (report->buttons & 0x01) != 0; + mouse_data.right_button = (report->buttons & 0x02) != 0; + + // Print mouse movement for debugging + print_hex(mouse_data.x, 1, 1); + print_hex(mouse_data.y, 1, 1); + print_hex(report->buttons, 1, 1); +} + +// Parse the HID descriptor (for parsing USB HID device descriptors) +bool hid_parse_descriptor(uint8_t* descriptor, uint32_t length) { + // HID descriptors are defined in the USB HID specification, we'll need to parse them here. + // For now, just return true assuming we have a valid descriptor. + return true; +} From 4c7de228f9792a17edcc64b5422c0fcafa14f5c9 Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sat, 24 Jan 2026 22:13:32 -0800 Subject: [PATCH 03/10] Update keyboard.c remove static --- kernel/keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/keyboard.c b/kernel/keyboard.c index 8d83d8e..4984dc9 100644 --- a/kernel/keyboard.c +++ b/kernel/keyboard.c @@ -13,7 +13,7 @@ static uint8_t buffer_count = 0; static uint8_t buffer_index = 0; // Basic US QWERTY keymap (scancode to ASCII) -static const char scancode_map[128] = { +const char scancode_map[128] = { 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', // 0x00 - 0x09 '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', // 0x0A - 0x13 't', 'y', 'z', 'u', 'i', 'o', 'p', '[', ']', '\n', // 0x14 - 0x1D From 5a664c6e31079daa10205c95bffd3f604390daaa Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sat, 24 Jan 2026 22:14:37 -0800 Subject: [PATCH 04/10] Update keyboard.h Add a extern const for the scancode map --- kernel/keyboard.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/keyboard.h b/kernel/keyboard.h index 4f269ed..46cef82 100644 --- a/kernel/keyboard.h +++ b/kernel/keyboard.h @@ -3,5 +3,6 @@ void keyboard_init(void); char keyboard_get_char(void); // Blocking read from buffer +extern const char scancode_map[128]; #endif From a08648eff55a8d7d2e09c6268c968362af75f0a2 Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sat, 24 Jan 2026 22:21:44 -0800 Subject: [PATCH 05/10] Update keyboard.h fixing missing includes and definition --- kernel/keyboard.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/keyboard.h b/kernel/keyboard.h index 46cef82..f60ee49 100644 --- a/kernel/keyboard.h +++ b/kernel/keyboard.h @@ -1,7 +1,10 @@ #ifndef KEYBOARD_H #define KEYBOARD_H +#include + void keyboard_init(void); +void keyboard_buffer_add(char c); char keyboard_get_char(void); // Blocking read from buffer extern const char scancode_map[128]; From 18801a742f5bb130905b77ed76504ae67d2f83fc Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sat, 24 Jan 2026 22:31:50 -0800 Subject: [PATCH 06/10] Update keyboard.c Fix missing definitions so theres nothing that would break the build --- kernel/keyboard.c | 97 ++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 35 deletions(-) diff --git a/kernel/keyboard.c b/kernel/keyboard.c index 4984dc9..4e34d72 100644 --- a/kernel/keyboard.c +++ b/kernel/keyboard.c @@ -2,64 +2,91 @@ #include "io.h" #include "isr.h" #include "terminal.h" +#include #define KEYBOARD_DATA_PORT 0x60 #define KEY_BUFFER_SIZE 256 -static char key_buffer[KEY_BUFFER_SIZE]; -static uint8_t buffer_head = 0; // Write position (interrupt) -static uint8_t buffer_tail = 0; // Read position (get_char) -static uint8_t buffer_count = 0; -static uint8_t buffer_index = 0; +// Use volatile so the compiler knows these change inside interrupts +static volatile char key_buffer[KEY_BUFFER_SIZE]; +static volatile uint8_t buffer_head = 0; +static volatile uint8_t buffer_tail = 0; +static volatile uint8_t buffer_count = 0; -// Basic US QWERTY keymap (scancode to ASCII) +// Exported map: Removed 'static' so hid.c can reference it if needed const char scancode_map[128] = { - 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', // 0x00 - 0x09 - '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', // 0x0A - 0x13 - 't', 'y', 'z', 'u', 'i', 'o', 'p', '[', ']', '\n', // 0x14 - 0x1D - 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', // 0x1E - 0x27 - ';', '\'', '`', 0, '\\', 'x', 'c', 'v', 'b', // 0x28 - 0x31 - 'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, // 0x32 - 0x3B - // rest can be filled as needed + 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', + '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', + 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', + 'm', ',', '.', '/', 0, '*', 0, ' ', 0 }; -// Interrupt handler for IRQ1 -void keyboard_callback(void) { - uint8_t scancode = inb(KEYBOARD_DATA_PORT); - - if (scancode & 0x80) return; // Ignore key release - - char c = scancode_map[scancode]; +/** + * Shared function used by both PS/2 (callback) and USB (hid.c) + * This fixes the "undefined reference to keyboard_buffer_add" error. + */ +void keyboard_buffer_add(char c) { if (!c) return; uint8_t next_head = (buffer_head + 1) % KEY_BUFFER_SIZE; - // Drop key if buffer full - if (next_head == buffer_tail) return; + // If buffer is full, we must drop the key + if (next_head == buffer_tail) { + return; + } key_buffer[buffer_head] = c; buffer_head = next_head; buffer_count++; + // Echo to terminal terminal_putchar(c); } -void keyboard_init() { - register_interrupt_handler(33, keyboard_callback); // IRQ1 = int 33 (0x21) +/** + * Hardware Interrupt Handler for PS/2 + */ +void keyboard_callback(void) { + uint8_t scancode = inb(KEYBOARD_DATA_PORT); + + // Ignore break codes (key release) + if (scancode & 0x80) return; + + char c = scancode_map[scancode]; + keyboard_buffer_add(c); } -// Blocking read (returns one char) +void keyboard_init(void) { + buffer_head = 0; + buffer_tail = 0; + buffer_count = 0; + // IRQ1 is usually mapped to IDT entry 33 + register_interrupt_handler(33, keyboard_callback); +} + +/** + * Blocking read with a safe HLT to prevent CPU 100% usage + */ char keyboard_get_char(void) { - while (buffer_count == 0) { - __asm__ __volatile__("hlt"); // Better than busy loop - } - char c; - __asm__ __volatile__("cli"); - c = key_buffer[buffer_tail]; - buffer_tail = (buffer_tail + 1) % KEY_BUFFER_SIZE; - buffer_count--; - __asm__ __volatile__("sti"); - return c; + while (1) { + __asm__ __volatile__("cli"); // Disable interrupts to check buffer_count safely + + if (buffer_count > 0) { + c = key_buffer[buffer_tail]; + buffer_tail = (buffer_tail + 1) % KEY_BUFFER_SIZE; + buffer_count--; + __asm__ __volatile__("sti"); // Re-enable interrupts after reading + return c; + } + + /* * IMPORTANT: 'sti' followed by 'hlt' is guaranteed by x86 + * to execute 'hlt' BEFORE the next interrupt can trigger. + * This prevents the race condition hang. + */ + __asm__ __volatile__("sti; hlt"); + } } From f9e281a7aec47c661b7a8ce39e02ae3901b5d4d0 Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sat, 24 Jan 2026 22:46:03 -0800 Subject: [PATCH 07/10] Update mouse.c Make mouse_data non static --- kernel/mouse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/mouse.c b/kernel/mouse.c index 8d6ece6..c03e014 100644 --- a/kernel/mouse.c +++ b/kernel/mouse.c @@ -5,7 +5,7 @@ #include // Mouse buffer -static mouse_data_t mouse_data; +mouse_data_t mouse_data; // Read USB mouse data mouse_data_t usb_read_mouse(void) { From 745deeddde56c167f46df7385cb622f66946496e Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sat, 24 Jan 2026 22:49:07 -0800 Subject: [PATCH 08/10] Update mouse.h Fixes static --- kernel/mouse.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/mouse.h b/kernel/mouse.h index 96a4f85..d8ec913 100644 --- a/kernel/mouse.h +++ b/kernel/mouse.h @@ -12,6 +12,8 @@ typedef struct { bool right_button; } mouse_data_t; +extern mouse_data_t mouse_data; + // Function declarations for USB 1.x HID mouse support bool usb_mouse_init(void); bool usb_mouse_detected(void); From 1037ba4f548283bb7eb1adc22a9fb9c563a3c004 Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sun, 25 Jan 2026 08:24:43 -0800 Subject: [PATCH 09/10] Update keyboard.h fixed typo in header include --- kernel/keyboard.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/keyboard.h b/kernel/keyboard.h index f60ee49..86e6bde 100644 --- a/kernel/keyboard.h +++ b/kernel/keyboard.h @@ -1,11 +1,12 @@ #ifndef KEYBOARD_H #define KEYBOARD_H -#include +#include void keyboard_init(void); void keyboard_buffer_add(char c); -char keyboard_get_char(void); // Blocking read from buffer -extern const char scancode_map[128]; +char keyboard_get_char(void); + +extern const char scancode_map[128]; #endif From 6c69b5fd6a2b47930ae28f757b754985efbcb9c0 Mon Sep 17 00:00:00 2001 From: Gregory Bowne Date: Sun, 25 Jan 2026 08:45:45 -0800 Subject: [PATCH 10/10] Update hid.c Fixing print_hex error --- kernel/hid.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/kernel/hid.c b/kernel/hid.c index 5192d01..45578f2 100644 --- a/kernel/hid.c +++ b/kernel/hid.c @@ -51,11 +51,10 @@ void hid_process_mouse_report(const mouse_hid_report_t* report) { mouse_data.y += report->y; mouse_data.left_button = (report->buttons & 0x01) != 0; mouse_data.right_button = (report->buttons & 0x02) != 0; - - // Print mouse movement for debugging - print_hex(mouse_data.x, 1, 1); - print_hex(mouse_data.y, 1, 1); - print_hex(report->buttons, 1, 1); + + print_hex((uint32_t)mouse_data.x, 1, 1); + print_hex((uint32_t)mouse_data.y, 1, 1); + print_hex((uint32_t)report->buttons, 1, 1); } // Parse the HID descriptor (for parsing USB HID device descriptors)