mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
Proper USB system + moved into userspace
This commit is contained in:
parent
3392b56aab
commit
8e805938a1
20 changed files with 735 additions and 232 deletions
18
Makefile
18
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 $@)
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
#include <stdbool.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
117
src/usb/uhci.c
117
src/usb/uhci.c
|
|
@ -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 <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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 $@
|
||||
|
||||
|
|
|
|||
164
src/userland/usb/driver.c
Normal file
164
src/userland/usb/driver.c
Normal file
|
|
@ -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 <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
37
src/userland/usb/driver.h
Normal file
37
src/userland/usb/driver.h
Normal file
|
|
@ -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 <stdbool.h>
|
||||
|
||||
#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
|
||||
|
|
@ -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 <string.h>
|
||||
|
||||
extern void serial_write(const char *str);
|
||||
#include <stdio.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
69
src/userland/usb/logitech_b110.c
Normal file
69
src/userland/usb/logitech_b110.c
Normal file
|
|
@ -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 <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -4,15 +4,17 @@
|
|||
#ifndef LOGITECH_B110_H
|
||||
#define LOGITECH_B110_H
|
||||
|
||||
#include "hid.h"
|
||||
#include <stdint.h>
|
||||
#include "usb.h"
|
||||
#include "driver.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#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
|
||||
74
src/userland/usb/syscall.h
Normal file
74
src/userland/usb/syscall.h
Normal file
|
|
@ -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 <stdint.h>
|
||||
|
||||
#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
|
||||
213
src/userland/usb/uhci.c
Normal file
213
src/userland/usb/uhci.c
Normal file
|
|
@ -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 <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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 <string.h>
|
||||
|
||||
extern void serial_write(const char *str);
|
||||
extern void serial_write_hex(uint64_t n);
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
src/userland/usb/usb_driver_main.c
Normal file
40
src/userland/usb/usb_driver_main.c
Normal file
|
|
@ -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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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;
|
||||
}
|
||||
Loading…
Reference in a new issue