Merge pull request #99 from gbowne1/gbowne1-add-hid

Add HID support
This commit is contained in:
2026-01-26 12:18:04 -08:00
committed by GitHub
6 changed files with 183 additions and 38 deletions

65
kernel/hid.c Normal file
View File

@@ -0,0 +1,65 @@
#include "hid.h"
#include "usb.h"
#include "mouse.h"
#include "keyboard.h"
#include "print.h"
#include <stdint.h>
#include <stdbool.h>
// 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_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)
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;
}

46
kernel/hid.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef HID_H
#define HID_H
#include <stdint.h>
#include <stdbool.h>
// 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

View File

@@ -2,64 +2,91 @@
#include "io.h" #include "io.h"
#include "isr.h" #include "isr.h"
#include "terminal.h" #include "terminal.h"
#include <stddef.h>
#define KEYBOARD_DATA_PORT 0x60 #define KEYBOARD_DATA_PORT 0x60
#define KEY_BUFFER_SIZE 256 #define KEY_BUFFER_SIZE 256
static char key_buffer[KEY_BUFFER_SIZE]; // Use volatile so the compiler knows these change inside interrupts
static uint8_t buffer_head = 0; // Write position (interrupt) static volatile char key_buffer[KEY_BUFFER_SIZE];
static uint8_t buffer_tail = 0; // Read position (get_char) static volatile uint8_t buffer_head = 0;
static uint8_t buffer_count = 0; static volatile uint8_t buffer_tail = 0;
static uint8_t buffer_index = 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
static const char scancode_map[128] = { const char scancode_map[128] = {
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', // 0x00 - 0x09 0, 27, '1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', // 0x0A - 0x13 '9', '0', '-', '=', '\b', '\t', 'q', 'w', 'e', 'r',
't', 'y', 'z', 'u', 'i', 'o', 'p', '[', ']', '\n', // 0x14 - 0x1D 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0,
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', // 0x1E - 0x27 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
';', '\'', '`', 0, '\\', 'x', 'c', 'v', 'b', // 0x28 - 0x31 '\'', '`', 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n',
'n', 'm', ',', '.', '/', 0, '*', 0, ' ', 0, // 0x32 - 0x3B 'm', ',', '.', '/', 0, '*', 0, ' ', 0
// rest can be filled as needed
}; };
// Interrupt handler for IRQ1 /**
void keyboard_callback(void) { * Shared function used by both PS/2 (callback) and USB (hid.c)
uint8_t scancode = inb(KEYBOARD_DATA_PORT); * This fixes the "undefined reference to keyboard_buffer_add" error.
*/
if (scancode & 0x80) return; // Ignore key release void keyboard_buffer_add(char c) {
char c = scancode_map[scancode];
if (!c) return; if (!c) return;
uint8_t next_head = (buffer_head + 1) % KEY_BUFFER_SIZE; uint8_t next_head = (buffer_head + 1) % KEY_BUFFER_SIZE;
// Drop key if buffer full // If buffer is full, we must drop the key
if (next_head == buffer_tail) return; if (next_head == buffer_tail) {
return;
}
key_buffer[buffer_head] = c; key_buffer[buffer_head] = c;
buffer_head = next_head; buffer_head = next_head;
buffer_count++; buffer_count++;
// Echo to terminal
terminal_putchar(c); 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) { char keyboard_get_char(void) {
while (buffer_count == 0) {
__asm__ __volatile__("hlt"); // Better than busy loop
}
char c; 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");
}
} }

View File

@@ -1,7 +1,12 @@
#ifndef KEYBOARD_H #ifndef KEYBOARD_H
#define KEYBOARD_H #define KEYBOARD_H
#include <stdint.h>
void keyboard_init(void); void keyboard_init(void);
char keyboard_get_char(void); // Blocking read from buffer void keyboard_buffer_add(char c);
char keyboard_get_char(void);
extern const char scancode_map[128];
#endif #endif

View File

@@ -5,7 +5,7 @@
#include <stdbool.h> #include <stdbool.h>
// Mouse buffer // Mouse buffer
static mouse_data_t mouse_data; mouse_data_t mouse_data;
// Read USB mouse data // Read USB mouse data
mouse_data_t usb_read_mouse(void) { mouse_data_t usb_read_mouse(void) {

View File

@@ -12,6 +12,8 @@ typedef struct {
bool right_button; bool right_button;
} mouse_data_t; } mouse_data_t;
extern mouse_data_t mouse_data;
// Function declarations for USB 1.x HID mouse support // Function declarations for USB 1.x HID mouse support
bool usb_mouse_init(void); bool usb_mouse_init(void);
bool usb_mouse_detected(void); bool usb_mouse_detected(void);