diff --git a/src/kernel/hid-keyboard.c b/src/kernel/hid-keyboard.c index db87654..0952eda 100644 --- a/src/kernel/hid-keyboard.c +++ b/src/kernel/hid-keyboard.c @@ -170,6 +170,7 @@ static uint64_t stream_read(__attribute__((unused)) stream_t *self, uint64_t max } buffer_length -= size; buffer_offset = (buffer_offset + size) % BUFFER_SIZE; + return size; } diff --git a/src/kernel/usb.c b/src/kernel/usb.c index b410444..7c99284 100644 --- a/src/kernel/usb.c +++ b/src/kernel/usb.c @@ -35,6 +35,8 @@ typedef struct __attribute__((packed)) { #define USB_SETUP_RECIPIENT_OTHER 3 #define USB_SETUP_GET_DESCRIPTOR 0x06 +#define USB_SETUP_SET_CONFIGURATION 0x09 +#define USB_SETUP_SET_IDLE 0x0A #define USB_SETUP_SET_PROTOCOL 0x0B #define USB_SETUP_DESCRIPTOR_TYPE_R(s) BITS_R((s)->w_value, 15, 8) @@ -52,11 +54,6 @@ typedef struct __attribute__((packed)) { #define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02 #define USB_DESCRIPTOR_TYPE_INTERFACE 0x04 #define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05 -#define USB_DESCRIPTOR_TYPE_HID 0x21 - -#define USB_INTERFACE_HID_KEYBOARD_CLASS 0x3 -#define USB_INTERFACE_HID_KEYBOARD_SUBCLASS 0x1 -#define USB_INTERFACE_HID_KEYBOARD_PROTOCOL 0x1 typedef struct __attribute__((packed)) { usb_descriptor_base_t base; @@ -176,7 +173,6 @@ void usb_enumerate(stream_t *out) { } xhci_slot_t slot = xhci_attach(port); - if (slot == (xhci_slot_t)-1) { continue; } @@ -206,7 +202,6 @@ xhci_port_t usb_find_by_interface(uint8_t class, uint8_t subclass, uint8_t proto } xhci_slot_t slot = xhci_attach(port); - if (slot == (xhci_slot_t)-1) { continue; } @@ -239,6 +234,14 @@ xhci_endpoint_t usb_open_endpoint(xhci_slot_t slot, uint8_t type, uint16_t max_p scan_device(slot, &device, &configuration, &interface, &endpoint); usb_setup_t setup; + memory_set(0, sizeof(setup), &setup); + USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D); + USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_STANDARD); + USB_SETUP_RECIPIENT_W(&setup, USB_SETUP_RECIPIENT_DEVICE); + setup.b_request = USB_SETUP_SET_CONFIGURATION; + setup.w_value = configuration.configuration_value; + xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0); + memory_set(0, sizeof(setup), &setup); USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D); USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_CLASS); @@ -246,9 +249,16 @@ xhci_endpoint_t usb_open_endpoint(xhci_slot_t slot, uint8_t type, uint16_t max_p setup.b_request = USB_SETUP_SET_PROTOCOL; xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0); + memory_set(0, sizeof(setup), &setup); + USB_SETUP_DIRECTION_W(&setup, USB_SETUP_DIRECTION_H2D); + USB_SETUP_TYPE_W(&setup, USB_SETUP_TYPE_CLASS); + USB_SETUP_RECIPIENT_W(&setup, USB_SETUP_RECIPIENT_INTERFACE); + setup.b_request = USB_SETUP_SET_IDLE; + xhci_control_transfer(slot, *(uint64_t *)&setup, NUL, 0); + ASSERT(endpoint.max_packet_size == max_packet_size, "usb_open_endpoint: Unexpected max packet size."); - return xhci_open_endpoint(slot, endpoint.endpoint_address, type, endpoint.max_packet_size, endpoint.interval); + return xhci_open_endpoint(slot, endpoint.endpoint_address, type, endpoint.max_packet_size, 7); } uint16_t usb_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t max, void *to) { diff --git a/src/kernel/xhci.c b/src/kernel/xhci.c index d73db2b..f1e648c 100644 --- a/src/kernel/xhci.c +++ b/src/kernel/xhci.c @@ -1,12 +1,12 @@ #include "src/kernel/xhci.h" #include "src/kernel/log.h" +#include "src/kernel/memory.h" #include "src/kernel/panic.h" #include "src/kernel/pci.h" #include "src/kernel/stream.h" #include "src/lib/layout.h" #include "src/lib/memory.h" #include "src/lib/util.h" -#include #define XHCI_PCI_CLASS 0x0C #define XHCI_PCI_SUBCLASS 0x03 @@ -29,6 +29,7 @@ typedef volatile struct __attribute__((packed)) { #define XHCI_CAP_REGS_MAX_INTRS(c) BITS_R((c)->hcsparams1, 18, 8) #define XHCI_CAP_REGS_MAX_PORTS(c) BITS_R((c)->hcsparams1, 31, 24) #define XHCI_CAP_REGS_MAX_ERSTS(c) BITS_R((c)->hcsparams2, 7, 4) +#define XHCI_CAP_REGS_MAX_SCRATCHPAD_BUFFERS(c) (BITS_R((c)->hcsparams2, 31, 27) << 5 | BITS_R((c)->hcsparams2, 4, 0)) typedef volatile struct __attribute__((packed)) { uint32_t usbcmd; @@ -96,6 +97,8 @@ static xhci_db_regs *db_regs; #define MAX_SLOTS 32 +static void *scratchpads[32]; + static void *dcbaa[MAX_SLOTS + 1] __attribute__((aligned(PAGE_SIZE))); typedef struct __attribute__((packed)) { @@ -408,6 +411,13 @@ void xhci_init() { RING_WRAP(cmd); XHCI_TRB_CYCLE_W(&cmd_r[RING_LENGTH], cmd_r_cycle); + LOG_LN_INFO("Setting up scratchpad buffers..."); + ASSERT(XHCI_CAP_REGS_MAX_SCRATCHPAD_BUFFERS(cap_regs) <= sizeof(scratchpads), "Too many scratchpad buffers expected."); + for (uint32_t i = 0; i < XHCI_CAP_REGS_MAX_SCRATCHPAD_BUFFERS(cap_regs); i++) { + scratchpads[i] = memory_page_allocate(); + } + dcbaa[0] = VIRT_TO_PHYS(scratchpads); + LOG_LN_INFO("Configuring controller..."); XHCI_OP_REGS_MAX_SLOTS_EN_W(op_regs, MAX_SLOTS); op_regs->dcbaap = (uint64_t)VIRT_TO_PHYS(dcbaa); @@ -475,13 +485,17 @@ xhci_slot_t xhci_attach(xhci_port_t port) { RING_WRAP(tsf); LOG_LN_STEP("Resetting device..."); + LOG_VAL_TRACE(port_regs[port].portsc, "%x"); + port_regs[port].portsc = (port_regs[port].portsc & ~(uint32_t)0x00FE0000) | 0x00FE0000; + LOG_VAL_TRACE(port_regs[port].portsc, "%x"); port_regs[port].portsc = (port_regs[port].portsc & ~(uint32_t)0x00FE0000) | (1 << 4); + LOG_VAL_TRACE(port_regs[port].portsc, "%x"); while (XHCI_PORT_REGS_PR_R(&port_regs[port])) ; - LOG_VAL_TRACE(&port_regs[port].portsc, "%x"); + LOG_VAL_TRACE(port_regs[port].portsc, "%x"); while (!XHCI_PORT_REGS_PED(&port_regs[port]) && XHCI_PORT_REGS_PLL(&port_regs[port]) != 0) ; - LOG_VAL_TRACE(&port_regs[port].portsc, "%x"); + LOG_VAL_TRACE(port_regs[port].portsc, "%x"); LOG_LN_STEP("Enabling a slot..."); xhci_trb_t cmd_es; @@ -612,10 +626,17 @@ uint16_t xhci_read_endpoint(xhci_slot_t slot, xhci_endpoint_t endpoint, uint16_t LOG_LN_STEP("Received transfer event, returning..."); ep_processed_events++; + LOG_VAL_TRACE(cmp->parameter, "%lx"); + LOG_VAL_TRACE(cmp->status, "%x"); + LOG_VAL_TRACE(cmp->control, "%x"); + xhci_trb_t *cmd = PHYS_TO_VIRT(cmp->parameter); uint16_t size = max < cmd->status ? max : (uint16_t)cmd->status; memory_copy(PHYS_TO_VIRT(cmd->parameter), size, to); + LOG_VAL_TRACE(size, "%d"); + LOG_VAL_TRACE(*(uint64_t *)to, "%lx"); + transferred = size; }