diff --git a/kernel/device/usb/usb.h b/kernel/device/usb/usb.h index 6b7a842..523d506 100644 --- a/kernel/device/usb/usb.h +++ b/kernel/device/usb/usb.h @@ -4,6 +4,21 @@ #include #include +/* descriptor types */ + +#define USB_DESC_DEVICE 1 +#define USB_DESC_CONFIG 2 +#define USB_DESC_STRING 3 +#define USB_DESC_IF 4 +#define USB_DESC_ENDPOINT 5 +#define USB_DESC_IF_POWER 8 +#define USB_DESC_OTG 9 +#define USB_DESC_DEBUG 10 +#define USB_DESC_IF_ASSOC 11 +#define USB_DESC_BOS 15 +#define USB_DESC_DEV_CAPABILITY 16 +#define USB_DESC_SS_USB_EP_COMP 48 + struct usb_desc_hdr { uint8_t length; uint8_t desc_type; diff --git a/kernel/device/usb/xhci.c b/kernel/device/usb/xhci.c index 83e9312..50523b4 100644 --- a/kernel/device/usb/xhci.c +++ b/kernel/device/usb/xhci.c @@ -885,6 +885,79 @@ static bool xhci_pdevice_setup_get_config (struct xhci* xhci, struct xhci_pdevic usb_config->total_length, usb_config->num_ifs, usb_config->config_value, usb_config->config, usb_config->attrs, usb_config->max_power); + pdevice->config_desc = *usb_config; + + pmm_free (response_buf_phys, 1); + return true; +} + +static bool xhci_pdevice_setup_get_config_full (struct xhci* xhci, struct xhci_pdevice* pdevice, + uint64_t* lockflags) { + struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + + uintptr_t response_buf_phys = pmm_alloc (1); + + void* response_buf = (void*)(response_buf_phys + (uintptr_t)hhdm->offset); + memset (response_buf, 0, PAGE_SIZE); + + bool ok = xhci_endpoint0_ctrl_in (xhci, pdevice, 0x80, 6, (2 << 8), 0, response_buf_phys, + pdevice->config_desc.total_length, lockflags); + + if (!ok) { + pmm_free (response_buf_phys, 1); + return false; + } + + uint8_t* ptr = (uint8_t*)response_buf; + uint8_t* end = ptr + pdevice->config_desc.total_length; + + while (ptr < end) { + struct usb_desc_hdr* hdr = (struct usb_desc_hdr*)ptr; + + if (hdr->length == 0) + break; + + switch (hdr->desc_type) { + case USB_DESC_CONFIG: { + struct xhci_pdevice_dconfig* dconfig = malloc (sizeof (*dconfig)); + memset (dconfig, 0, sizeof (*dconfig)); + dconfig->desc = *(struct usb_config_desc*)ptr; + list_append (pdevice->dconfigs, &dconfig->configs_link); + + DEBUG ( + "Found USB device config: total_len=%u num_ifs=%u, cfgval=%u cfg=%u attrs=%02x maxpow=%u\n", + dconfig->desc.total_length, dconfig->desc.num_ifs, dconfig->desc.config_value, + dconfig->desc.config, dconfig->desc.attrs, dconfig->desc.max_power); + } break; + case USB_DESC_IF: { + struct xhci_pdevice_dif* dif = malloc (sizeof (*dif)); + memset (dif, 0, sizeof (*dif)); + dif->desc = *(struct usb_if_desc*)ptr; + list_append (pdevice->difs, &dif->ifs_link); + + DEBUG ( + "Found USB device interface: ifnum=%u altsetting=%u eps=%u ifclass=%u ifsubclass=%u ifproto=%u if=%u\n", + dif->desc.if_num, dif->desc.alt_setting, dif->desc.num_endpoints, dif->desc.if_class, + dif->desc.if_subclass, dif->desc.if1); + } break; + case USB_DESC_ENDPOINT: { + struct xhci_pdevice_dendpoint* dendpoint = malloc (sizeof (*dendpoint)); + memset (dendpoint, 0, sizeof (*dendpoint)); + dendpoint->desc = *(struct usb_endpoint_desc*)ptr; + list_append (pdevice->dendpoints, &dendpoint->endpoints_link); + + DEBUG ("Found USB device endpoint: addr=%u attrs=%u maxpkt=%u intvl=%u\n", + dendpoint->desc.endpoint_addr, dendpoint->desc.attrs, dendpoint->desc.max_packet_size, + dendpoint->desc.interval); + } break; + default: + DEBUG ("Found unknown USB descriptor of type %u\n", hdr->desc_type); + break; + } + + ptr += hdr->length; + } + pmm_free (response_buf_phys, 1); return true; } @@ -900,10 +973,9 @@ static void xhci_poll_setup_devices (struct xhci* xhci, uint64_t* lockflags) { continue; xhci_pdevice_setup_addressing (xhci, pdevice, lockflags); - xhci_pdevice_setup_get_info (xhci, pdevice, lockflags); - xhci_pdevice_setup_get_config (xhci, pdevice, lockflags); + xhci_pdevice_setup_get_config_full (xhci, pdevice, lockflags); } } diff --git a/kernel/device/usb/xhci.h b/kernel/device/usb/xhci.h index a4099c9..a0af759 100644 --- a/kernel/device/usb/xhci.h +++ b/kernel/device/usb/xhci.h @@ -67,13 +67,33 @@ struct xhci_ring { uint8_t cycle_bit; }; +struct xhci_pdevice_dconfig { + struct usb_config_desc desc; + struct list_node_link configs_link; +}; + +struct xhci_pdevice_dif { + struct usb_if_desc desc; + struct list_node_link ifs_link; +}; + +struct xhci_pdevice_dendpoint { + struct usb_endpoint_desc desc; + struct list_node_link endpoints_link; +}; + struct xhci_pdevice { struct list_node_link pdevices_link; struct xhci_port* xhci_port; int slot_id; struct xhci_ring endpoint0_ring; + struct usb_device_desc device_desc; + struct usb_config_desc config_desc; + struct list_node_link* dconfigs; + struct list_node_link* difs; + struct list_node_link* dendpoints; }; struct xhci_port_status_change {