From 8e805938a139ccd25ff1ea251ccb529b2174804e Mon Sep 17 00:00:00 2001 From: rwusmm Date: Mon, 11 May 2026 20:58:38 +0300 Subject: [PATCH] Proper USB system + moved into userspace --- Makefile | 18 +-- src/core/main.c | 7 - src/dev/ps2.c | 3 - src/sys/syscall.c | 90 +++++++++++ src/sys/syscall.h | 11 ++ src/usb/logitech_b110.c | 46 ------ src/usb/uhci.c | 117 -------------- src/userland/Makefile | 21 ++- src/userland/usb/driver.c | 164 +++++++++++++++++++ src/userland/usb/driver.h | 37 +++++ src/{ => userland}/usb/hid.c | 12 +- src/{ => userland}/usb/hid.h | 0 src/userland/usb/logitech_b110.c | 69 ++++++++ src/{ => userland}/usb/logitech_b110.h | 10 +- src/userland/usb/syscall.h | 74 +++++++++ src/userland/usb/uhci.c | 213 +++++++++++++++++++++++++ src/{ => userland}/usb/uhci.h | 0 src/{ => userland}/usb/usb.c | 35 ++-- src/{ => userland}/usb/usb.h | 0 src/userland/usb/usb_driver_main.c | 40 +++++ 20 files changed, 735 insertions(+), 232 deletions(-) delete mode 100644 src/usb/logitech_b110.c delete mode 100644 src/usb/uhci.c create mode 100644 src/userland/usb/driver.c create mode 100644 src/userland/usb/driver.h rename src/{ => userland}/usb/hid.c (92%) rename src/{ => userland}/usb/hid.h (100%) create mode 100644 src/userland/usb/logitech_b110.c rename src/{ => userland}/usb/logitech_b110.h (66%) create mode 100644 src/userland/usb/syscall.h create mode 100644 src/userland/usb/uhci.c rename src/{ => userland}/usb/uhci.h (100%) rename src/{ => userland}/usb/usb.c (81%) rename src/{ => userland}/usb/usb.h (100%) create mode 100644 src/userland/usb/usb_driver_main.c diff --git a/Makefile b/Makefile index af07e16..554d7cd 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,6 @@ C_SOURCES = $(wildcard $(SRC_DIR)/core/*.c) \ $(wildcard $(SRC_DIR)/net/nic/*.c) \ $(wildcard $(SRC_DIR)/fs/*.c) \ $(wildcard $(SRC_DIR)/wm/*.c) \ - $(wildcard $(SRC_DIR)/usb/*.c) \ $(wildcard $(SRC_DIR)/net/third_party/lwip/core/*.c) \ $(wildcard $(SRC_DIR)/net/third_party/lwip/core/ipv4/*.c) \ $(SRC_DIR)/net/third_party/lwip/netif/ethernet.c \ @@ -63,7 +62,6 @@ OBJ_FILES = $(patsubst $(SRC_DIR)/core/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_D $(patsubst $(SRC_DIR)/net/nic/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/net/nic/*.c)) \ $(patsubst $(SRC_DIR)/fs/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/fs/*.c)) \ $(patsubst $(SRC_DIR)/wm/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/wm/*.c)) \ - $(patsubst $(SRC_DIR)/usb/%.c, $(BUILD_DIR)/%.o, $(wildcard $(SRC_DIR)/usb/*.c)) \ $(patsubst $(SRC_DIR)/net/third_party/lwip/%.c, $(BUILD_DIR)/lwip/%.o, $(filter $(SRC_DIR)/net/third_party/lwip/%.c, $(C_SOURCES))) \ $(patsubst $(SRC_DIR)/arch/%.asm, $(BUILD_DIR)/%.o, $(ASM_SOURCES)) @@ -74,7 +72,7 @@ CFLAGS = -g -O2 -pipe -Wall -Wextra -std=gnu11 -ffreestanding \ -I$(SRC_DIR)/sys -I$(SRC_DIR)/mem -I$(SRC_DIR)/dev \ -I$(SRC_DIR)/drivers \ -I$(SRC_DIR)/net -I$(SRC_DIR)/net/nic -I$(SRC_DIR)/fs \ - -I$(SRC_DIR)/wm -I$(SRC_DIR)/input -I$(SRC_DIR)/usb + -I$(SRC_DIR)/wm -I$(SRC_DIR)/input LDFLAGS = -m elf_x86_64 -nostdlib -static -pie --no-dynamic-linker \ -z text -z max-page-size=0x1000 -T linker.ld @@ -86,11 +84,7 @@ LIMINE_URL_BASE = https://github.com/limine-bootloader/limine/raw/v$(LIMINE_VERS HOST_OS := $(shell uname -s 2>/dev/null || echo Windows) -<<<<<<< HEAD -.PHONY: all clean run run-hd limine-setup run-windows run-mac run-linux run-hd-mac run-hd-windows run-hd-linux -======= .PHONY: all clean run run-hd limine-setup run-windows run-mac run-linux run-hd-mac run-hd-windows run-hd-linux unsafe ->>>>>>> 335d1c8 (Add new VGA fix and USB system) all: $(call PRINT_STEP,STARTING BOREDOS BUILD) @@ -181,16 +175,6 @@ $(BUILD_DIR)/%.o: $(SRC_DIR)/wm/%.c | $(BUILD_DIR) limine-setup mkdir -p $(dir $@) $(CC) $(CFLAGS) -c $< -o $@ -$(BUILD_DIR)/%.o: $(SRC_DIR)/usb/%.c | $(BUILD_DIR) limine-setup - @printf "$(YELLOW)[CC]$(RESET)[usb] $< -> $@" - mkdir -p $(dir $@) - $(CC) $(CFLAGS) -c $< -o $@ - -$(BUILD_DIR)/uhci.o: $(SRC_DIR)/usb/uhci.c | $(BUILD_DIR) limine-setup - @printf "$(YELLOW)[CC]$(RESET)[usb] $< -> $@" - mkdir -p $(dir $@) - $(CC) $(CFLAGS) -c $< -o $@ - $(BUILD_DIR)/lwip/%.o: $(SRC_DIR)/net/third_party/lwip/%.c | $(BUILD_DIR) limine-setup @printf "$(YELLOW)[CC]$(RESET)[lwIP] $< -> $@" mkdir -p $(dir $@) diff --git a/src/core/main.c b/src/core/main.c index 9784e45..866858b 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -36,9 +36,6 @@ #include "input/keymap.h" #include "input/keyboard.h" #include "../drivers/acpi.h" -#include "../usb/usb.h" -#include "../usb/hid.h" -#include "../usb/logitech_b110.h" extern void sysfs_init_subsystems(void); @@ -502,10 +499,6 @@ void kmain(void) { ps2_init(); asm("sti"); - usb_init(); - usb_enumerate_devices(); - usb_hid_init(); - keymap_init(); serial_write("[INIT] Keymap initialized"); diff --git a/src/dev/ps2.c b/src/dev/ps2.c index 2ba5085..aca0b95 100644 --- a/src/dev/ps2.c +++ b/src/dev/ps2.c @@ -10,7 +10,6 @@ #include #include "input/keyboard.h" #include "input/keymap.h" -#include "../usb/logitech_b110.h" extern void serial_print(const char *s); extern void serial_print_hex(uint64_t n); @@ -152,7 +151,6 @@ uint64_t mouse_handler(registers_t *regs) { if (!(status & 0x20)) { outb(0x20, 0x20); outb(0xA0, 0x20); - logitech_b110_poll(); return (uint64_t)regs; } @@ -188,7 +186,6 @@ uint64_t mouse_handler(registers_t *regs) { outb(0x20, 0x20); outb(0xA0, 0x20); - logitech_b110_poll(); return (uint64_t)regs; } diff --git a/src/sys/syscall.c b/src/sys/syscall.c index 7ad9ad2..423757e 100644 --- a/src/sys/syscall.c +++ b/src/sys/syscall.c @@ -2388,6 +2388,85 @@ static uint64_t sys_cmd_disk_replace_kernel(const syscall_args_t *args) { return 0; } +static uint64_t sys_cmd_pci_read_config(const syscall_args_t *args) { + uint8_t bus = (uint8_t)args->arg2; + uint8_t device = (uint8_t)args->arg3; + uint8_t function = (uint8_t)args->arg4; + uint8_t offset = (uint8_t)args->arg5; + extern uint32_t pci_read_config(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset); + return pci_read_config(bus, device, function, offset); +} + +static uint64_t sys_cmd_pci_write_config(const syscall_args_t *args) { + uint8_t bus = (uint8_t)args->arg2; + uint8_t device = (uint8_t)args->arg3; + uint8_t function = (uint8_t)args->arg4; + uint8_t offset = (uint8_t)args->arg5; + uint32_t value = 0; + extern void pci_write_config(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value); + pci_write_config(bus, device, function, offset, value); + return 0; +} + +static uint64_t sys_cmd_io_inb(const syscall_args_t *args) { + uint16_t port = (uint16_t)args->arg2; + return inb(port); +} + +static uint64_t sys_cmd_io_outb(const syscall_args_t *args) { + uint16_t port = (uint16_t)args->arg2; + uint8_t value = (uint8_t)args->arg3; + outb(port, value); + return 0; +} + +static uint64_t sys_cmd_io_inw(const syscall_args_t *args) { + uint16_t port = (uint16_t)args->arg2; + return inw(port); +} + +static uint64_t sys_cmd_io_outw(const syscall_args_t *args) { + uint16_t port = (uint16_t)args->arg2; + uint16_t value = (uint16_t)args->arg3; + outw(port, value); + return 0; +} + +static uint64_t sys_cmd_io_inl(const syscall_args_t *args) { + uint16_t port = (uint16_t)args->arg2; + return inl(port); +} + +static uint64_t sys_cmd_io_outl(const syscall_args_t *args) { + uint16_t port = (uint16_t)args->arg2; + uint32_t value = (uint32_t)args->arg3; + outl(port, value); + return 0; +} + +static uint64_t sys_cmd_mem_map_phys(const syscall_args_t *args) { + uint64_t phys_addr = args->arg2; + uint64_t size = args->arg3; + extern uint64_t p2v(uint64_t phys); + (void)size; + return p2v(phys_addr); +} + +static uint64_t sys_cmd_mem_unmap(const syscall_args_t *args) { + (void)args; + return 0; +} + +static uint64_t sys_cmd_wm_handle_mouse(const syscall_args_t *args) { + int dx = (int)args->arg2; + int dy = (int)args->arg3; + uint8_t buttons = (uint8_t)args->arg4; + int wheel = (int)args->arg5; + extern void wm_handle_mouse(int dx, int dy, uint8_t buttons, int wheel); + wm_handle_mouse(dx, dy, buttons, wheel); + return 0; +} + #define SYS_CMD_TABLE_SIZE 110 static const syscall_handler_fn sys_cmd_table[SYS_CMD_TABLE_SIZE] = { [SYSTEM_CMD_SET_BG_COLOR] = sys_cmd_set_bg_color, @@ -2467,6 +2546,17 @@ static const syscall_handler_fn sys_cmd_table[SYS_CMD_TABLE_SIZE] = { [SYSTEM_CMD_DISK_RESCAN] = sys_cmd_disk_rescan, [SYSTEM_CMD_DISK_REPLACE_KERNEL] = sys_cmd_disk_replace_kernel, [SYSTEM_CMD_DISK_SYNC] = sys_cmd_disk_sync, + [SYSTEM_CMD_PCI_READ_CONFIG] = sys_cmd_pci_read_config, + [SYSTEM_CMD_PCI_WRITE_CONFIG] = sys_cmd_pci_write_config, + [SYSTEM_CMD_IO_INB] = sys_cmd_io_inb, + [SYSTEM_CMD_IO_OUTB] = sys_cmd_io_outb, + [SYSTEM_CMD_IO_INW] = sys_cmd_io_inw, + [SYSTEM_CMD_IO_OUTW] = sys_cmd_io_outw, + [SYSTEM_CMD_IO_INL] = sys_cmd_io_inl, + [SYSTEM_CMD_IO_OUTL] = sys_cmd_io_outl, + [SYSTEM_CMD_MEM_MAP_PHYS] = sys_cmd_mem_map_phys, + [SYSTEM_CMD_MEM_UNMAP] = sys_cmd_mem_unmap, + [SYSTEM_CMD_WM_HANDLE_MOUSE] = sys_cmd_wm_handle_mouse, }; static uint64_t handle_sys_write(const syscall_args_t *args) { diff --git a/src/sys/syscall.h b/src/sys/syscall.h index 5ef981b..68d8708 100644 --- a/src/sys/syscall.h +++ b/src/sys/syscall.h @@ -123,6 +123,17 @@ typedef struct { #define SYSTEM_CMD_SIGPENDING 75 #define SYSTEM_CMD_GET_ELF_METADATA 76 #define SYSTEM_CMD_GET_ELF_PRIMARY_IMAGE 77 +#define SYSTEM_CMD_PCI_READ_CONFIG 78 +#define SYSTEM_CMD_PCI_WRITE_CONFIG 79 +#define SYSTEM_CMD_IO_INB 80 +#define SYSTEM_CMD_IO_OUTB 81 +#define SYSTEM_CMD_IO_INW 82 +#define SYSTEM_CMD_IO_OUTW 83 +#define SYSTEM_CMD_IO_INL 84 +#define SYSTEM_CMD_IO_OUTL 85 +#define SYSTEM_CMD_MEM_MAP_PHYS 86 +#define SYSTEM_CMD_MEM_UNMAP 87 +#define SYSTEM_CMD_WM_HANDLE_MOUSE 88 void syscall_init(void); uint64_t syscall_handler_c(registers_t *regs); diff --git a/src/usb/logitech_b110.c b/src/usb/logitech_b110.c deleted file mode 100644 index 6c25cfe..0000000 --- a/src/usb/logitech_b110.c +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) 2023-2026 Chris (boreddevnl) -// This software is released under the GNU General Public License v3.0. See LICENSE file for details. -// This header needs to maintain in this file it has in it, as per the GPL license terms. -#include "logitech_b110.h" -#include "../core/io.h" - -extern void serial_write(const char *str); -extern void wm_handle_mouse(int dx, int dy, int buttons, int wheel); - -static usb_device_t b110_device; -static bool b110_initialized = false; - -bool logitech_b110_probe(usb_device_t *dev) { - if (dev->vendor_id == LOGITECH_VID && dev->product_id == LOGITECH_B110_PID) { - serial_write("[B110] Logitech B110 mouse detected\n"); - return true; - } - return false; -} - -bool logitech_b110_init(usb_device_t *dev) { - if (!logitech_b110_probe(dev)) return false; - - b110_device = *dev; - b110_initialized = hid_init_mouse(dev); - - if (b110_initialized) { - serial_write("[LT-B110] Mouse USB driver initialized\n"); - } - - return b110_initialized; -} - -void logitech_b110_poll(void) { - if (!b110_initialized) return; - - hid_mouse_report_t report; - if (hid_mouse_get_report(&b110_device, &report) > 0) { - int buttons = 0; - if (report.buttons & 0x01) buttons |= 0x01; - if (report.buttons & 0x02) buttons |= 0x02; - if (report.buttons & 0x04) buttons |= 0x04; - - wm_handle_mouse(report.x, report.y, buttons, report.wheel); - } -} diff --git a/src/usb/uhci.c b/src/usb/uhci.c deleted file mode 100644 index 19bf42a..0000000 --- a/src/usb/uhci.c +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) 2023-2026 Chris (boreddevnl) -// This software is released under the GNU General Public License v3.0. See LICENSE file for details. -// This header needs to maintain in this file it has in it, as per the GPL license terms. -#include "uhci.h" -#include "../core/io.h" -#include "../core/platform.h" -#include "../mem/memory_manager.h" -#include "../dev/pci.h" -#include - -extern void serial_write(const char *str); -extern void serial_write_hex(uint64_t n); - -static uhci_hc_t uhci_controller; -static uint8_t *frame_list; -static uhci_qh_t *qh_pool; -static uhci_td_t *td_pool; - -#define FRAME_LIST_SIZE 1024 -#define POOL_SIZE 64 - -bool uhci_init(usb_hc_t *hc) { - serial_write("[UHCI] Initializing UHCI controller\n"); - - uint32_t bar = hc->bar0 & 0xFFFFFFF0; - if (bar == 0) { - serial_write("[UHCI] Invalid BAR0\n"); - return false; - } - - uhci_controller.base = (uint8_t *)p2v(bar); - uhci_controller.regs = (uhci_regs_t *)uhci_controller.base; - - uint16_t cmd = inw((uint32_t)&uhci_controller.regs->cmd); - outw((uint32_t)&uhci_controller.regs->cmd, cmd & ~UHCI_CMD_RUN); - - for (volatile int i = 0; i < 10000; i++); - - outw((uint32_t)&uhci_controller.regs->cmd, cmd | UHCI_CMD_HCRESET); - - for (volatile int i = 0; i < 10000; i++); - - frame_list = (uint8_t *)kmalloc(FRAME_LIST_SIZE * 4); - if (!frame_list) { - serial_write("[UHCI] Failed to allocate frame list\n"); - return false; - } - - memset(frame_list, 0, FRAME_LIST_SIZE * 4); - - qh_pool = (uhci_qh_t *)kmalloc(sizeof(uhci_qh_t) * POOL_SIZE); - td_pool = (uhci_td_t *)kmalloc(sizeof(uhci_td_t) * POOL_SIZE); - - if (!qh_pool || !td_pool) { - serial_write("[UHCI] Failed to allocate pools\n"); - return false; - } - - memset(qh_pool, 0, sizeof(uhci_qh_t) * POOL_SIZE); - memset(td_pool, 0, sizeof(uhci_td_t) * POOL_SIZE); - - uint32_t frame_list_phys = v2p((uint64_t)frame_list); - outl((uint32_t)&uhci_controller.regs->frame_base, frame_list_phys); - - outw((uint32_t)&uhci_controller.regs->cmd, UHCI_CMD_RUN | UHCI_CMD_MAXP); - - uint16_t port1 = inw((uint32_t)&uhci_controller.regs->port1); - if (port1 & UHCI_PORT_CCS) { - serial_write("[UHCI] Device detected on port 1\n"); - outw((uint32_t)&uhci_controller.regs->port1, port1 | UHCI_PORT_PED); - } - - uint16_t port2 = inw((uint32_t)&uhci_controller.regs->port2); - if (port2 & UHCI_PORT_CCS) { - serial_write("[UHCI] Device detected on port 2\n"); - outw((uint32_t)&uhci_controller.regs->port2, port2 | UHCI_PORT_PED); - } - - uhci_controller.initialized = true; - serial_write("[UHCI] Initialization complete\n"); - return true; -} - -void uhci_reset_port(usb_hc_t *hc, int port) { - (void)hc; - uhci_hc_t *controller = &uhci_controller; - uint16_t port_reg = (port == 1) ? (uint32_t)&controller->regs->port1 : (uint32_t)&controller->regs->port2; - - uint16_t status = inw(port_reg); - outw(port_reg, status | UHCI_PORT_PR); - - for (volatile int i = 0; i < 10000; i++); - - status = inw(port_reg); - outw(port_reg, status & ~UHCI_PORT_PR); - - for (volatile int i = 0; i < 10000; i++); - - status = inw(port_reg); - outw(port_reg, status | UHCI_PORT_PED); -} - -int uhci_control_transfer(usb_hc_t *hc, usb_setup_packet_t *setup, void *data, uint16_t len) { - (void)hc; - (void)setup; - (void)data; - (void)len; - return -1; -} - -int uhci_interrupt_in(usb_hc_t *hc, uint8_t endpoint, void *data, uint16_t len) { - (void)hc; - (void)endpoint; - (void)data; - (void)len; - return -1; -} diff --git a/src/userland/Makefile b/src/userland/Makefile index 80150c3..5b67d32 100644 --- a/src/userland/Makefile +++ b/src/userland/Makefile @@ -13,7 +13,7 @@ APP_METADATA_TOOL = ../../tools/gen_userland_note.sh APP_ICON_SOURCE_DIR = ../images/icons/colloid APP_METADATA_SOURCE_DOOM = games/doom/doomgeneric_boredos.c APP_METADATA_SOURCE_LUA = cli/third_party/lua/boredos_onelua.c -APP_SOURCE_DIRS = . cli gui sys games net cli/third_party +APP_SOURCE_DIRS = . cli gui sys games net cli/third_party usb define app_source_for $(if $(filter doom,$1),$(APP_METADATA_SOURCE_DOOM),$(if $(filter lua,$1),$(APP_METADATA_SOURCE_LUA),$(if $(filter tcc,$1),cli/third_party/tcc/tcc.c,$(firstword $(foreach d,$(APP_SOURCE_DIRS),$(wildcard $(d)/$1.c)))))) @@ -22,11 +22,11 @@ endef LIBC_SOURCES = $(wildcard libc/*.c) LIBC_OBJS = $(patsubst libc/%.c, $(BIN_DIR)/%.o, $(LIBC_SOURCES)) $(BIN_DIR)/crt0.o $(BIN_DIR)/libwidget.o $(BIN_DIR)/stb_image.o -VPATH = cli gui sys games libc net cli/third_party -vpath %.c cli gui sys games libc net cli/third_party +VPATH = cli gui sys games libc net cli/third_party usb +vpath %.c cli gui sys games libc net cli/third_party usb -APP_SOURCES_FULL = $(wildcard cli/*.c gui/*.c sys/*.c games/*.c *.c net/*.c cli/third_party/*.c) -APP_SOURCES = $(filter-out stb_image.c, $(APP_SOURCES_FULL)) +APP_SOURCES_FULL = $(wildcard cli/*.c gui/*.c sys/*.c games/*.c *.c net/*.c cli/third_party/*.c usb/*.c) +APP_SOURCES = $(filter-out stb_image.c usb_driver_main.c usb.c uhci.c hid.c logitech_b110.c driver.c syscall.h, $(APP_SOURCES_FULL)) APP_ELFS = $(patsubst %.c, $(BIN_DIR)/%.elf, $(notdir $(APP_SOURCES))) APP_NAMES = $(sort $(basename $(notdir $(APP_SOURCES))) doom lua) APP_NOTE_CSOURCES = $(patsubst %, $(BIN_DIR)/%.note.c, $(APP_NAMES)) @@ -35,10 +35,13 @@ APP_NOTE_OBJS = $(patsubst %, $(BIN_DIR)/%.note.o, $(APP_NAMES)) DOOM_SOURCES = $(wildcard games/doom/*.c) DOOM_OBJS = $(patsubst games/doom/%.c, $(BIN_DIR)/%.o, $(DOOM_SOURCES)) +USB_SOURCES = $(wildcard usb/*.c) +USB_OBJS = $(patsubst usb/%.c, $(BIN_DIR)/%.o, $(USB_SOURCES)) + LUA_DIR = cli/third_party/lua LUA_CFLAGS = -std=gnu11 -ffreestanding -O2 -fno-stack-protector -fno-stack-check -fno-lto -fno-pie -m64 -march=x86-64 -mno-red-zone -isystem $(LUA_DIR)/sysinclude -I. -Ilibc -I$(LUA_DIR) -DLUA_USE_C89 -Wno-conversion -Wno-sign-conversion -Wno-double-promotion -Wno-unused-parameter -Wno-missing-declarations -Wno-shadow -Wno-undef -Wno-redundant-decls -Wno-old-style-definition -Wno-missing-prototypes -Wno-implicit-fallthrough -Wno-type-limits -all: $(BIN_DIR) $(APP_ELFS) $(BIN_DIR)/doom.elf $(BIN_DIR)/lua.elf $(BIN_DIR)/tcc.elf $(BIN_DIR)/empty.o +all: $(BIN_DIR) $(APP_ELFS) $(BIN_DIR)/doom.elf $(BIN_DIR)/lua.elf $(BIN_DIR)/tcc.elf $(BIN_DIR)/usb_driver_main.elf $(BIN_DIR)/empty.o $(BIN_DIR): mkdir -p $(BIN_DIR) @@ -92,9 +95,15 @@ $(BIN_DIR)/screenshot.elf: $(LIBC_OBJS) $(BIN_DIR)/screenshot.o $(BIN_DIR)/scree $(BIN_DIR)/%.o: games/doom/%.c | $(BIN_DIR) $(CC) $(CFLAGS) -Wno-error -DBOREDOS -Igames/doom -c $< -o $@ +$(BIN_DIR)/%.o: usb/%.c | $(BIN_DIR) + $(CC) $(CFLAGS) -Iusb -c $< -o $@ + $(BIN_DIR)/doom.elf: $(LIBC_OBJS) $(DOOM_OBJS) $(BIN_DIR)/doom.note.o $(LD) $(LDFLAGS) $^ -o $@ +$(BIN_DIR)/usb_driver_main.elf: $(LIBC_OBJS) $(USB_OBJS) + $(LD) $(LDFLAGS) $^ -o $@ + $(BIN_DIR)/%.elf: $(LIBC_OBJS) $(BIN_DIR)/%.o $(BIN_DIR)/%.note.o $(LD) $(LDFLAGS) $^ -o $@ diff --git a/src/userland/usb/driver.c b/src/userland/usb/driver.c new file mode 100644 index 0000000..ab207d6 --- /dev/null +++ b/src/userland/usb/driver.c @@ -0,0 +1,164 @@ +// Copyright (c) 2023-2026 Chris (boreddevnl) +// This software is released under the GNU General Public License v3.0. See LICENSE file for details. +// This header needs to maintain in this file it has in it, as per the GPL license terms. +#include "driver.h" +#include +#include + +static usb_driver_t *driver_registry[MAX_DRIVERS]; +static int driver_count = 0; +static driver_instance_t active_instances[MAX_DRIVERS]; +static int instance_count = 0; + +void driver_manager_init(void) { + memset(driver_registry, 0, sizeof(driver_registry)); + memset(active_instances, 0, sizeof(active_instances)); + driver_count = 0; + instance_count = 0; +} + +int driver_register(usb_driver_t *driver) { + if (!driver || driver_count >= MAX_DRIVERS) return -1; + + for (int i = 0; i < driver_count; i++) { + if (driver_registry[i]->vendor_id == driver->vendor_id && + driver_registry[i]->product_id == driver->product_id) { + return -1; + } + } + + driver_registry[driver_count++] = driver; + driver->loaded = false; + return 0; +} + +int driver_unregister(usb_driver_t *driver) { + if (!driver) return -1; + + for (int i = 0; i < driver_count; i++) { + if (driver_registry[i] == driver) { + for (int j = i; j < driver_count - 1; j++) { + driver_registry[j] = driver_registry[j + 1]; + } + driver_count--; + driver->loaded = false; + return 0; + } + } + + return -1; +} + +int driver_load_for_device(usb_device_t *dev) { + if (!dev) return -1; + + for (int i = 0; i < driver_count; i++) { + usb_driver_t *driver = driver_registry[i]; + + if (driver->vendor_id == dev->vendor_id && + driver->product_id == dev->product_id) { + + if (instance_count >= MAX_DRIVERS) return -1; + + if (driver->probe && !driver->probe(dev)) { + continue; + } + + if (driver->init && driver->init(dev) != 0) { + continue; + } + + active_instances[instance_count].device = *dev; + active_instances[instance_count].driver = driver; + active_instances[instance_count].active = true; + instance_count++; + + driver->loaded = true; + printf("[DRIVER] Loaded %s for VID:PID %04X:%04X\n", + driver->name, dev->vendor_id, dev->product_id); + return 0; + } + } + + return -1; +} + +void driver_unload_for_device(usb_device_t *dev) { + if (!dev) return; + + for (int i = 0; i < instance_count; i++) { + if (active_instances[i].active && + active_instances[i].device.vendor_id == dev->vendor_id && + active_instances[i].device.product_id == dev->product_id) { + + if (active_instances[i].driver->deinit) { + active_instances[i].driver->deinit(dev); + } + + active_instances[i].driver->loaded = false; + active_instances[i].active = false; + + for (int j = i; j < instance_count - 1; j++) { + active_instances[j] = active_instances[j + 1]; + } + instance_count--; + + printf("[DRIVER] Unloaded driver for VID:PID %04X:%04X\n", + dev->vendor_id, dev->product_id); + return; + } + } +} + +void driver_hotplug_poll(void) { + extern int usb_get_device_count(void); + extern usb_device_t* usb_get_device(int index); + + int current_count = usb_get_device_count(); + + for (int i = 0; i < current_count; i++) { + usb_device_t *dev = usb_get_device(i); + if (!dev) continue; + + bool found = false; + for (int j = 0; j < instance_count; j++) { + if (active_instances[j].active && + active_instances[j].device.vendor_id == dev->vendor_id && + active_instances[j].device.product_id == dev->product_id) { + found = true; + break; + } + } + + if (!found && !dev->initialized) { + driver_load_for_device(dev); + dev->initialized = true; + } + } + + for (int i = 0; i < instance_count; i++) { + bool still_present = false; + for (int j = 0; j < current_count; j++) { + usb_device_t *dev = usb_get_device(j); + if (dev && + active_instances[i].device.vendor_id == dev->vendor_id && + active_instances[i].device.product_id == dev->product_id) { + still_present = true; + break; + } + } + + if (!still_present) { + driver_unload_for_device(&active_instances[i].device); + i--; + } + } +} + +void driver_poll_all(void) { + for (int i = 0; i < instance_count; i++) { + if (active_instances[i].active && active_instances[i].driver->poll) { + active_instances[i].driver->poll(&active_instances[i].device); + } + } +} diff --git a/src/userland/usb/driver.h b/src/userland/usb/driver.h new file mode 100644 index 0000000..31a15ff --- /dev/null +++ b/src/userland/usb/driver.h @@ -0,0 +1,37 @@ +// Copyright (c) 2023-2026 Chris (boreddevnl) +// This software is released under the GNU General Public License v3.0. See LICENSE file for details. +// This header needs to maintain in this file it has in it, as per the GPL license terms. +#ifndef DRIVER_H +#define DRIVER_H + +#include "usb.h" +#include + +#define MAX_DRIVERS 16 + +typedef struct { + uint16_t vendor_id; + uint16_t product_id; + char name[64]; + bool (*probe)(usb_device_t *dev); + int (*init)(usb_device_t *dev); + void (*deinit)(usb_device_t *dev); + int (*poll)(usb_device_t *dev); + bool loaded; +} usb_driver_t; + +typedef struct { + usb_device_t device; + usb_driver_t *driver; + bool active; +} driver_instance_t; + +void driver_manager_init(void); +int driver_register(usb_driver_t *driver); +int driver_unregister(usb_driver_t *driver); +int driver_load_for_device(usb_device_t *dev); +void driver_unload_for_device(usb_device_t *dev); +void driver_hotplug_poll(void); +void driver_poll_all(void); + +#endif diff --git a/src/usb/hid.c b/src/userland/usb/hid.c similarity index 92% rename from src/usb/hid.c rename to src/userland/usb/hid.c index e1e1d7e..0bd445a 100644 --- a/src/usb/hid.c +++ b/src/userland/usb/hid.c @@ -3,10 +3,8 @@ // This header needs to maintain in this file it has in it, as per the GPL license terms. #include "hid.h" #include "logitech_b110.h" -#include "../core/io.h" #include - -extern void serial_write(const char *str); +#include static usb_device_t hid_mouse_devices[8]; static int hid_mouse_count = 0; @@ -85,7 +83,7 @@ bool hid_init_mouse(usb_device_t *dev) { hid_mouse_devices[hid_mouse_count++] = *dev; dev->initialized = true; - serial_write("[HID] Mouse initialized\n"); + printf("[HID] Mouse initialized\n"); return true; } @@ -106,7 +104,7 @@ int hid_mouse_get_report(usb_device_t *dev, hid_mouse_report_t *report) { } void usb_hid_init(void) { - serial_write("[HID] Initializing HID subsystem\n"); + printf("[HID] Initializing HID subsystem\n"); int device_count = usb_get_device_count(); @@ -114,10 +112,10 @@ void usb_hid_init(void) { usb_device_t *dev = usb_get_device(i); if (dev && dev->device_class == USB_CLASS_HID) { - serial_write("[HID] Found HID device\n"); + printf("[HID] Found HID device\n"); if (logitech_b110_probe(dev)) { - serial_write("[HID] Initializing LT-B110\n"); + printf("[HID] Initializing Logitech B110\n"); logitech_b110_init(dev); } } diff --git a/src/usb/hid.h b/src/userland/usb/hid.h similarity index 100% rename from src/usb/hid.h rename to src/userland/usb/hid.h diff --git a/src/userland/usb/logitech_b110.c b/src/userland/usb/logitech_b110.c new file mode 100644 index 0000000..a55a5a5 --- /dev/null +++ b/src/userland/usb/logitech_b110.c @@ -0,0 +1,69 @@ +// Copyright (c) 2023-2026 Chris (boreddevnl) +// This software is released under the GNU General Public License v3.0. See LICENSE file for details. +// This header needs to maintain in this file it has in it, as per the GPL license terms. +#include "logitech_b110.h" +#include "hid.h" +#include "syscall.h" +#include +#include + +static bool b110_initialized = false; + +bool logitech_b110_probe(usb_device_t *dev) { + if (!dev) return false; + + if (dev->vendor_id == LOGITECH_VID && dev->product_id == LOGITECH_B110_PID) { + return true; + } + + return false; +} + +int logitech_b110_init(usb_device_t *dev) { + if (!dev) return -1; + + b110_initialized = hid_init_mouse(dev); + + if (b110_initialized) { + printf("[B110] Mouse USB driver initialized\n"); + } + + return b110_initialized ? 0 : -1; +} + +void logitech_b110_deinit(usb_device_t *dev) { + (void)dev; + b110_initialized = false; + printf("[B110] Mouse USB driver deinitialized\n"); +} + +int logitech_b110_poll(usb_device_t *dev) { + if (!b110_initialized || !dev) return -1; + + uint8_t buffer[8]; + int len = usb_interrupt_in(dev, dev->endpoint_in, buffer, sizeof(buffer)); + + if (len > 0) { + hid_mouse_report_t report; + hid_parse_mouse_report(buffer, len, &report); + + wm_handle_mouse(report.x, report.y, report.buttons, report.wheel); + } + + return len; +} + +static usb_driver_t logitech_b110_driver = { + .vendor_id = LOGITECH_VID, + .product_id = LOGITECH_B110_PID, + .name = "Logitech B110", + .probe = logitech_b110_probe, + .init = logitech_b110_init, + .deinit = logitech_b110_deinit, + .poll = logitech_b110_poll, + .loaded = false +}; + +usb_driver_t* logitech_b110_get_driver(void) { + return &logitech_b110_driver; +} diff --git a/src/usb/logitech_b110.h b/src/userland/usb/logitech_b110.h similarity index 66% rename from src/usb/logitech_b110.h rename to src/userland/usb/logitech_b110.h index 6294928..ae507bf 100644 --- a/src/usb/logitech_b110.h +++ b/src/userland/usb/logitech_b110.h @@ -4,15 +4,17 @@ #ifndef LOGITECH_B110_H #define LOGITECH_B110_H -#include "hid.h" -#include +#include "usb.h" +#include "driver.h" #include #define LOGITECH_VID 0x046D #define LOGITECH_B110_PID 0xC05A bool logitech_b110_probe(usb_device_t *dev); -bool logitech_b110_init(usb_device_t *dev); -void logitech_b110_poll(void); +int logitech_b110_init(usb_device_t *dev); +void logitech_b110_deinit(usb_device_t *dev); +int logitech_b110_poll(usb_device_t *dev); +usb_driver_t* logitech_b110_get_driver(void); #endif diff --git a/src/userland/usb/syscall.h b/src/userland/usb/syscall.h new file mode 100644 index 0000000..a3d7762 --- /dev/null +++ b/src/userland/usb/syscall.h @@ -0,0 +1,74 @@ +// Copyright (c) 2023-2026 Chris (boreddevnl) +// This software is released under the GNU General Public License v3.0. See LICENSE file for details. +// This header needs to maintain in this file it has in it, as per the GPL license terms. +#ifndef SYSCALL_H +#define SYSCALL_H + +#include + +#define SYSTEM_CMD_PCI_READ_CONFIG 78 +#define SYSTEM_CMD_PCI_WRITE_CONFIG 79 +#define SYSTEM_CMD_IO_INB 80 +#define SYSTEM_CMD_IO_OUTB 81 +#define SYSTEM_CMD_IO_INW 82 +#define SYSTEM_CMD_IO_OUTW 83 +#define SYSTEM_CMD_IO_INL 84 +#define SYSTEM_CMD_IO_OUTL 85 +#define SYSTEM_CMD_MEM_MAP_PHYS 86 +#define SYSTEM_CMD_MEM_UNMAP 87 +#define SYSTEM_CMD_WM_HANDLE_MOUSE 88 + +static inline uint64_t syscall(uint64_t num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5) { + uint64_t ret; + asm volatile ("syscall" + : "=a"(ret) + : "a"(num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(arg4), "r"(arg5) + : "rcx", "r11", "memory"); + return ret; +} + +static inline uint32_t pci_read_config(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) { + return syscall(SYSTEM_CMD_PCI_READ_CONFIG, 0, bus, device, function, offset); +} + +static inline void pci_write_config(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value) { + syscall(SYSTEM_CMD_PCI_WRITE_CONFIG, 0, bus, device, function, offset); +} + +static inline uint8_t inb(uint16_t port) { + return syscall(SYSTEM_CMD_IO_INB, 0, port, 0, 0, 0); +} + +static inline void outb(uint16_t port, uint8_t value) { + syscall(SYSTEM_CMD_IO_OUTB, 0, port, value, 0, 0); +} + +static inline uint16_t inw(uint16_t port) { + return syscall(SYSTEM_CMD_IO_INW, 0, port, 0, 0, 0); +} + +static inline void outw(uint16_t port, uint16_t value) { + syscall(SYSTEM_CMD_IO_OUTW, 0, port, value, 0, 0); +} + +static inline uint32_t inl(uint16_t port) { + return syscall(SYSTEM_CMD_IO_INL, 0, port, 0, 0, 0); +} + +static inline void outl(uint16_t port, uint32_t value) { + syscall(SYSTEM_CMD_IO_OUTL, 0, port, value, 0, 0); +} + +static inline uint64_t p2v(uint64_t phys) { + return syscall(SYSTEM_CMD_MEM_MAP_PHYS, 0, phys, 0, 0, 0); +} + +static inline void mem_unmap(uint64_t virt) { + syscall(SYSTEM_CMD_MEM_UNMAP, 0, virt, 0, 0, 0); +} + +static inline void wm_handle_mouse(int dx, int dy, uint8_t buttons, int wheel) { + syscall(SYSTEM_CMD_WM_HANDLE_MOUSE, 0, dx, dy, buttons, wheel); +} + +#endif diff --git a/src/userland/usb/uhci.c b/src/userland/usb/uhci.c new file mode 100644 index 0000000..2e8cea0 --- /dev/null +++ b/src/userland/usb/uhci.c @@ -0,0 +1,213 @@ +// Copyright (c) 2023-2026 Chris (boreddevnl) +// This software is released under the GNU General Public License v3.0. See LICENSE file for details. +// This header needs to maintain in this file it has in it, as per the GPL license terms. +#include "uhci.h" +#include "syscall.h" +#include +#include +#include + +static uhci_hc_t uhci_controller; +static uint8_t *frame_list; +static uhci_qh_t *qh_pool; +static uhci_td_t *td_pool; +static int td_idx = 0; + +#define FRAME_LIST_SIZE 1024 +#define POOL_SIZE 64 + +bool uhci_init(usb_hc_t *hc) { + serial_write("[UHCI] Initializing UHCI controller\n"); + + uint32_t bar = hc->bar0 & 0xFFFFFFF0; + if (bar == 0) { + serial_write("[UHCI] Invalid BAR0\n"); + return false; + } + + uhci_controller.base = (uint8_t *)p2v(bar); + uhci_controller.regs = (uhci_regs_t *)uhci_controller.base; + + uint16_t cmd = inw((uint32_t)&uhci_controller.regs->cmd); + outw((uint32_t)&uhci_controller.regs->cmd, cmd & ~UHCI_CMD_RUN); + + for (volatile int i = 0; i < 10000; i++); + + outw((uint32_t)&uhci_controller.regs->cmd, cmd | UHCI_CMD_HCRESET); + + for (volatile int i = 0; i < 10000; i++); + + frame_list = (uint8_t *)malloc(FRAME_LIST_SIZE * 4); + if (!frame_list) { + printf("[UHCI] Failed to allocate frame list\n"); + return false; + } + + memset(frame_list, 0, FRAME_LIST_SIZE * 4); + + qh_pool = (uhci_qh_t *)malloc(sizeof(uhci_qh_t) * POOL_SIZE); + td_pool = (uhci_td_t *)malloc(sizeof(uhci_td_t) * POOL_SIZE); + + if (!qh_pool || !td_pool) { + printf("[UHCI] Failed to allocate pools\n"); + return false; + } + + memset(qh_pool, 0, sizeof(uhci_qh_t) * POOL_SIZE); + memset(td_pool, 0, sizeof(uhci_td_t) * POOL_SIZE); + + for (int i = 0; i < FRAME_LIST_SIZE; i++) { + frame_list[i * 4 + 0] = 0x01; + frame_list[i * 4 + 1] = 0x00; + frame_list[i * 4 + 2] = 0x00; + frame_list[i * 4 + 3] = 0x00; + } + + uint32_t frame_list_phys = p2v((uint64_t)frame_list); + outl((uint32_t)&uhci_controller.regs->frame_base, frame_list_phys); + + outw((uint32_t)&uhci_controller.regs->cmd, UHCI_CMD_RUN | UHCI_CMD_MAXP); + + uint16_t port1 = inw((uint32_t)&uhci_controller.regs->port1); + if (port1 & UHCI_PORT_CCS) { + printf("[UHCI] Device detected on port 1\n"); + outw((uint32_t)&uhci_controller.regs->port1, port1 | UHCI_PORT_PED); + } + + uint16_t port2 = inw((uint32_t)&uhci_controller.regs->port2); + if (port2 & UHCI_PORT_CCS) { + printf("[UHCI] Device detected on port 2\n"); + outw((uint32_t)&uhci_controller.regs->port2, port2 | UHCI_PORT_PED); + } + + uhci_controller.initialized = true; + printf("[UHCI] Initialization complete\n"); + return true; +} + +void uhci_reset_port(usb_hc_t *hc, int port) { + (void)hc; + uhci_hc_t *controller = &uhci_controller; + uint16_t port_reg = (port == 1) ? (uint32_t)&controller->regs->port1 : (uint32_t)&controller->regs->port2; + + uint16_t status = inw(port_reg); + outw(port_reg, status | UHCI_PORT_PR); + + for (volatile int i = 0; i < 10000; i++); + + status = inw(port_reg); + outw(port_reg, status & ~UHCI_PORT_PR); + + for (volatile int i = 0; i < 10000; i++); + + status = inw(port_reg); + outw(port_reg, status | UHCI_PORT_PED); +} + +int uhci_control_transfer(usb_hc_t *hc, usb_setup_packet_t *setup, void *data, uint16_t len) { + (void)hc; + if (!uhci_controller.initialized) return -1; + + uhci_td_t *td_setup = &td_pool[td_idx++ % POOL_SIZE]; + uhci_td_t *td_data = (len > 0) ? &td_pool[td_idx++ % POOL_SIZE] : NULL; + uhci_td_t *td_status = &td_pool[td_idx++ % POOL_SIZE]; + + uint8_t *setup_buf = (uint8_t *)kmalloc(8); + if (!setup_buf) return -1; + + setup_buf[0] = setup->bmRequestType; + setup_buf[1] = setup->bRequest; + setup_buf[2] = setup->wValue & 0xFF; + setup_buf[3] = (setup->wValue >> 8) & 0xFF; + setup_buf[4] = setup->wIndex & 0xFF; + setup_buf[5] = (setup->wIndex >> 8) & 0xFF; + setup_buf[6] = setup->wLength & 0xFF; + setup_buf[7] = (setup->wLength >> 8) & 0xFF; + + memset(td_setup, 0, sizeof(uhci_td_t)); + td_setup->link = (td_data) ? (p2v((uint64_t)td_data) | 0x4) : (p2v((uint64_t)td_status) | 0x4); + td_setup->status = 0x00800000 | ((7 & 0x7FF) << 21); + td_setup->buffer = p2v((uint64_t)setup_buf); + + if (td_data && len > 0) { + memset(td_data, 0, sizeof(uhci_td_t)); + td_data->link = p2v((uint64_t)td_status) | 0x4; + td_data->status = 0x00800000 | ((len & 0x7FF) << 21); + td_data->buffer = p2v((uint64_t)data); + } + + memset(td_status, 0, sizeof(uhci_td_t)); + td_status->link = 0x00000001; + td_status->status = 0x00800000; + + uhci_qh_t *qh = &qh_pool[0]; + memset(qh, 0, sizeof(uhci_qh_t)); + qh->element_link = p2v((uint64_t)td_setup) | 0x4; + qh->link = 0x00000001; + + uint32_t qh_phys = p2v((uint64_t)qh); + frame_list[0] = qh_phys & 0xFF; + frame_list[1] = (qh_phys >> 8) & 0xFF; + frame_list[2] = (qh_phys >> 16) & 0xFF; + frame_list[3] = (qh_phys >> 24) & 0xFF; + + outw((uint32_t)&uhci_controller.regs->cmd, inw((uint32_t)&uhci_controller.regs->cmd) | UHCI_CMD_MAXP); + + for (volatile int i = 0; i < 100000; i++); + + uint32_t status = td_status->status; + + frame_list[0] = 0x01; + frame_list[1] = 0x00; + frame_list[2] = 0x00; + frame_list[3] = 0x00; + + if (status & 0x80000000) { + free(setup_buf); + return len; + } + + free(setup_buf); + return -1; +} + +int uhci_interrupt_in(usb_hc_t *hc, uint8_t endpoint, void *data, uint16_t len) { + (void)hc; + (void)endpoint; + if (!uhci_controller.initialized) return -1; + + uhci_td_t *td = &td_pool[td_idx++ % POOL_SIZE]; + + memset(td, 0, sizeof(uhci_td_t)); + td->link = 0x00000001; + td->status = 0x00800000 | ((len & 0x7FF) << 21) | (0x69 << 16); + td->buffer = p2v((uint64_t)data); + + uhci_qh_t *qh = &qh_pool[1]; + memset(qh, 0, sizeof(uhci_qh_t)); + qh->element_link = p2v((uint64_t)td) | 0x4; + qh->link = 0x00000001; + + uint32_t qh_phys = p2v((uint64_t)qh); + frame_list[0] = qh_phys & 0xFF; + frame_list[1] = (qh_phys >> 8) & 0xFF; + frame_list[2] = (qh_phys >> 16) & 0xFF; + frame_list[3] = (qh_phys >> 24) & 0xFF; + + outw((uint32_t)&uhci_controller.regs->cmd, inw((uint32_t)&uhci_controller.regs->cmd) | UHCI_CMD_MAXP); + + for (volatile int i = 0; i < 50000; i++); + + uint32_t status = td->status; + + frame_list[0] = 0x01; + frame_list[1] = 0x00; + frame_list[2] = 0x00; + frame_list[3] = 0x00; + + if (status & 0x80000000) { + return len; + } + + return -1; +} diff --git a/src/usb/uhci.h b/src/userland/usb/uhci.h similarity index 100% rename from src/usb/uhci.h rename to src/userland/usb/uhci.h diff --git a/src/usb/usb.c b/src/userland/usb/usb.c similarity index 81% rename from src/usb/usb.c rename to src/userland/usb/usb.c index b7b9449..23870e0 100644 --- a/src/usb/usb.c +++ b/src/userland/usb/usb.c @@ -3,13 +3,10 @@ // This header needs to maintain in any file it has in it, as per the GPL license terms. #include "usb.h" #include "uhci.h" -#include "../dev/pci.h" -#include "../core/io.h" -#include "../mem/memory_manager.h" +#include "syscall.h" #include - -extern void serial_write(const char *str); -extern void serial_write_hex(uint64_t n); +#include +#include static usb_hc_t usb_controllers[8]; static int usb_controller_count = 0; @@ -17,10 +14,6 @@ static usb_device_t usb_devices[USB_MAX_DEVICES]; static int usb_device_count = 0; static uint8_t device_address_counter = 1; -extern uint32_t pci_read_config(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset); -extern void pci_write_config(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value); -extern int pci_find_device_by_class(uint8_t class_code, uint8_t subclass, pci_device_t *dev); - usb_hc_type_t usb_detect_controller(usb_hc_t *hc) { uint32_t class_code = pci_read_config(hc->bus, hc->device, hc->function, 0x08) >> 24; uint32_t prog_if = pci_read_config(hc->bus, hc->device, hc->function, 0x09) & 0xFF; @@ -36,7 +29,7 @@ usb_hc_type_t usb_detect_controller(usb_hc_t *hc) { } void usb_init(void) { - serial_write("[USB] Initializing USB stack...\n"); + printf("[USB] Initializing USB stack...\n"); int idx = 0; @@ -65,13 +58,11 @@ void usb_init(void) { else if (type == USB_HC_EHCI) type_str = "EHCI"; else if (type == USB_HC_XHCI) type_str = "XHCI"; - serial_write("[USB] Found controller: "); - serial_write(type_str); - serial_write("\n"); + printf("[USB] Found controller: %s\n", type_str); if (type == USB_HC_UHCI) { if (uhci_init(&usb_controllers[idx])) { - serial_write("[USB] UHCI initialized\n"); + printf("[USB] UHCI initialized\n"); } } @@ -82,9 +73,7 @@ void usb_init(void) { } usb_controller_count = idx; - serial_write("[USB] Total controllers found: "); - serial_write_hex(usb_controller_count); - serial_write("\n"); + printf("[USB] Total controllers found: %d\n", usb_controller_count); } bool usb_enumerate_device(usb_device_t *dev) { @@ -151,10 +140,10 @@ int usb_interrupt_in(usb_device_t *dev, uint8_t endpoint, void *data, uint16_t l } void usb_enumerate_devices(void) { - serial_write("[USB] Starting device enumeration\n"); + printf("[USB] Starting device enumeration\n"); if (usb_controller_count == 0) { - serial_write("[USB] No controllers available\n"); + printf("[USB] No controllers available\n"); return; } @@ -163,11 +152,7 @@ void usb_enumerate_devices(void) { memset(&dev, 0, sizeof(usb_device_t)); if (usb_enumerate_device(&dev)) { - serial_write("[USB] Device enumerated: VID="); - serial_write_hex(dev.vendor_id); - serial_write(" PID="); - serial_write_hex(dev.product_id); - serial_write("\n"); + printf("[USB] Device enumerated: VID=%04X PID=%04X\n", dev.vendor_id, dev.product_id); } } } diff --git a/src/usb/usb.h b/src/userland/usb/usb.h similarity index 100% rename from src/usb/usb.h rename to src/userland/usb/usb.h diff --git a/src/userland/usb/usb_driver_main.c b/src/userland/usb/usb_driver_main.c new file mode 100644 index 0000000..4008a3e --- /dev/null +++ b/src/userland/usb/usb_driver_main.c @@ -0,0 +1,40 @@ +// Copyright (c) 2023-2026 Chris (boreddevnl) +// This software is released under the GNU General Public License v3.0. See LICENSE file for details. +// This header needs to maintain in this file it has in it, as per the GPL license terms. +#include "usb.h" +#include "driver.h" +#include "logitech_b110.h" +#include +#include + +extern void wm_handle_mouse(int dx, int dy, uint8_t buttons, int wheel); + +int main(int argc, char **argv) { + (void)argc; + (void)argv; + + printf("[USB] Starting userspace USB driver\n"); + + driver_manager_init(); + + printf("[USB] Initializing USB stack\n"); + usb_init(); + + printf("[USB] Enumerating devices\n"); + usb_enumerate_devices(); + + printf("[USB] Registering drivers\n"); + driver_register(logitech_b110_get_driver()); + + printf("[USB] Loading drivers for detected devices\n"); + driver_hotplug_poll(); + + printf("[USB] Entering main loop\n"); + while (1) { + driver_hotplug_poll(); + driver_poll_all(); + usleep(10000); + } + + return 0; +}