diff options
| author | hathach <[email protected]> | 2025-12-13 14:56:15 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2025-12-13 14:56:15 +0700 |
| commit | 80886fb32a9610d863246726950ffefeb2ffb21b (patch) | |
| tree | 8914ea1e2702d6ebf8e8346ca4641a402e91b321 /src/host | |
| parent | 7a4af1e9b833d334cca8fa98bc200d4738cb6b82 (diff) | |
| parent | 3a4d02ba9f150b74df08384d16fac124a7c27485 (diff) | |
Merge branch 'refs/heads/master' into hcd_fsdev
Diffstat (limited to 'src/host')
| -rw-r--r-- | src/host/hub.c | 14 | ||||
| -rw-r--r-- | src/host/hub.h | 12 | ||||
| -rw-r--r-- | src/host/usbh.c | 101 | ||||
| -rw-r--r-- | src/host/usbh_pvt.h | 17 |
4 files changed, 58 insertions, 86 deletions
diff --git a/src/host/hub.c b/src/host/hub.c index 0b172a596..3baaff30f 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -218,27 +218,27 @@ bool hub_deinit(void) { return true; } -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { +uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && - 0 == itf_desc->bInterfaceSubClass); - TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); // not support multiple TT yet + 0 == itf_desc->bInterfaceSubClass, 0); + TU_VERIFY(itf_desc->bInterfaceProtocol <= 1, 0); // not support multiple TT yet - uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); - TU_ASSERT(drv_len <= max_len); + const uint16_t drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); + TU_ASSERT(drv_len <= max_len, 0); // Interrupt Status endpoint tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); + TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep), 0); hub_interface_t* p_hub = get_hub_itf(dev_addr); p_hub->itf_num = itf_desc->bInterfaceNumber; p_hub->ep_in = desc_ep->bEndpointAddress; - return true; + return drv_len; } void hub_close(uint8_t dev_addr) { diff --git a/src/host/hub.h b/src/host/hub.h index 3587f0ee3..d9750f8a5 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -206,12 +206,12 @@ bool hub_clear_feature(uint8_t hub_addr, uint8_t feature, tuh_xfer_cb_t complete //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -bool hub_init (void); -bool hub_deinit (void); -bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); -bool hub_set_config (uint8_t daddr, uint8_t itf_num); -bool hub_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); -void hub_close (uint8_t dev_addr); +bool hub_init(void); +bool hub_deinit(void); +uint16_t hub_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); +bool hub_set_config(uint8_t daddr, uint8_t itf_num); +bool hub_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +void hub_close(uint8_t dev_addr); #ifdef __cplusplus } diff --git a/src/host/usbh.c b/src/host/usbh.c index 734024771..5b14a15cb 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1066,7 +1066,14 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { } bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const* desc_ep) { - TU_ASSERT(tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr), true)); + // HACK: some device incorrectly always report 512 bulk regardless of link speed, overwrite descriptor to force 64 + if (desc_ep->bmAttributes.xfer == TUSB_XFER_BULK && tu_edpt_packet_size(desc_ep) > 64 && + tuh_speed_get(dev_addr) == TUSB_SPEED_FULL) { + TU_LOG1(" WARN: EP max packet size is 512 in fullspeed, force to 64\r\n"); + tusb_desc_endpoint_t *hacked_ep = (tusb_desc_endpoint_t *)(uintptr_t)desc_ep; + hacked_ep->wMaxPacketSize = tu_htole16(64); + } + TU_ASSERT(tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr))); return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, desc_ep); } @@ -1815,85 +1822,51 @@ static bool enum_parse_configuration_desc(uint8_t dev_addr, tusb_desc_configurat TU_LOG_USBH("Parsing Configuration descriptor (wTotalLength = %u)\r\n", total_len); // parse each interfaces - while( p_desc < desc_end ) { - if ( 0 == tu_desc_len(p_desc) ) { + while (tu_desc_in_bounds(p_desc, desc_end)) { + if (0 == tu_desc_len(p_desc)) { // A zero length descriptor indicates that the device is off spec (e.g. wrong wTotalLength). // Parsed interfaces should still be usable TU_LOG_USBH("Encountered a zero-length descriptor after %" PRIu32 " bytes\r\n", (uint32_t)p_desc - (uint32_t)desc_cfg); break; } - uint8_t assoc_itf_count = 1; - - // Class will always starts with Interface Association (if any) and then Interface descriptor - if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) ) { - tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc; - assoc_itf_count = desc_iad->bInterfaceCount; - - p_desc = tu_desc_next(p_desc); // next to Interface - - // IAD's first interface number and class should match with opened interface - //TU_ASSERT(desc_iad->bFirstInterface == desc_itf->bInterfaceNumber && - // desc_iad->bFunctionClass == desc_itf->bInterfaceClass); + // skip if not interface + if (TUSB_DESC_INTERFACE != tu_desc_type(p_desc)) { + p_desc = tu_desc_next(p_desc); + continue; } + const tusb_desc_interface_t *desc_itf = (const tusb_desc_interface_t *)p_desc; - TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) ); - tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc; - -#if CFG_TUH_MIDI - // MIDI has 2 interfaces (Audio Control v1 + MIDIStreaming) but does not have IAD - // manually force associated count = 2 - if (1 == assoc_itf_count && - TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) { - assoc_itf_count = 2; - } -#endif - -#if CFG_TUH_CDC - // Some legacy CDC device does not use IAD but rather use device class as hint to combine 2 interfaces - // manually force associated count = 2 - if (1 == assoc_itf_count && - TUSB_CLASS_CDC == desc_itf->bInterfaceClass && - CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == desc_itf->bInterfaceSubClass) { - assoc_itf_count = 2; - } -#endif - - uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) (desc_end-p_desc)); - TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); + // uint16_t const drv_len = tu_desc_get_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) + // (desc_end-p_desc)); TU_ASSERT(drv_len >= sizeof(tusb_desc_interface_t)); // Find driver for this interface - for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { - usbh_class_driver_t const * driver = get_driver(drv_id); - if (driver && driver->open(dev->bus_info.rhport, dev_addr, desc_itf, drv_len) ) { - // open successfully - TU_LOG_USBH(" %s opened\r\n", driver->name); + const uint16_t remaining_len = (uint16_t)(desc_end - p_desc); + uint8_t drv_id; + for (drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { + const usbh_class_driver_t *driver = get_driver(drv_id); + if (driver) { + const uint16_t drv_len = driver->open(dev->bus_info.rhport, dev_addr, desc_itf, remaining_len); + if ((sizeof(tusb_desc_interface_t) <= drv_len) && (drv_len <= remaining_len)) { + // open successfully + TU_LOG_USBH(" %s opened\r\n", driver->name); - // bind (associated) interfaces to found driver - for(uint8_t i=0; i<assoc_itf_count; i++) { - uint8_t const itf_num = desc_itf->bInterfaceNumber+i; + // bind found driver to all interfaces and endpoint within drv_len + tu_bind_driver_to_ep_itf(drv_id, dev->ep2drv, dev->itf2drv, CFG_TUH_INTERFACE_MAX, p_desc, drv_len); - // Interface number must not be used already - TU_ASSERT( TUSB_INDEX_INVALID_8 == dev->itf2drv[itf_num] ); - dev->itf2drv[itf_num] = drv_id; + p_desc += drv_len; // next Interface + break; // exit driver find loop } - - // bind all endpoints to found driver - tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id); - - break; // exit driver find loop - } - - if (drv_id == TOTAL_DRIVER_COUNT - 1) { - TU_LOG_USBH("[%u:%u] Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", - dev->bus_info.rhport, dev_addr, desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); } } - // next Interface or IAD descriptor - p_desc += drv_len; + // no driver found + if (drv_id == TOTAL_DRIVER_COUNT) { + p_desc = tu_desc_next(p_desc); // skip this interface + TU_LOG_USBH("[%u:%u] Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n", + dev->bus_info.rhport, dev_addr, desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, + desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol); + } } return true; diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index d722bb7e8..57428e3c5 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -44,16 +44,15 @@ //--------------------------------------------------------------------+ // Class Driver API //--------------------------------------------------------------------+ - typedef struct { - char const* name; - bool (* const init )(void); - bool (* const deinit )(void); - bool (* const open )(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const * itf_desc, uint16_t max_len); - bool (* const set_config )(uint8_t dev_addr, uint8_t itf_num); - bool (* const xfer_cb )(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); - void (* const close )(uint8_t dev_addr); -} usbh_class_driver_t; + const char *name; + bool (*const init)(void); + bool (*const deinit)(void); + uint16_t (*const open)(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *itf_desc, uint16_t max_len); + bool (*const set_config)(uint8_t dev_addr, uint8_t itf_num); + bool (*const xfer_cb)(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); + void (*const close)(uint8_t dev_addr); + } usbh_class_driver_t; // Invoked when initializing host stack to get additional class drivers. // Can be implemented by application to extend/overwrite class driver support. |
