summaryrefslogtreecommitdiff
path: root/src/device/usbd.c
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-11-18 09:36:16 +0700
committerhathach <[email protected]>2025-11-18 09:36:16 +0700
commit98f7b0c7ba03fd770616195a6312e1bb65e5155f (patch)
tree6dce3fafc3794fd3cd1f13bd0cc04bfb84989e24 /src/device/usbd.c
parentbeea882c6bcee352b5ff69446aef9fc43237bab0 (diff)
parent66c84528f67c0eedc23d25221500d820e702d93f (diff)
Merge branch 'master' into fork/HiFiPhile/dwc2_iso_incomp
Diffstat (limited to 'src/device/usbd.c')
-rw-r--r--src/device/usbd.c148
1 files changed, 85 insertions, 63 deletions
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 339ccf4b4..cf96f050d 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -352,9 +352,13 @@ TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8
if (drvid < _app_driver_count) {
// Application drivers
driver = &_app_driver[drvid];
- } else if (drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0) {
- driver = &_usbd_driver[drvid - _app_driver_count];
+ } else{
+ drvid -= _app_driver_count;
+ if (drvid < BUILTIN_DRIVER_COUNT) {
+ driver = &_usbd_driver[drvid];
+ }
}
+
return driver;
}
@@ -572,7 +576,7 @@ bool tud_deinit(uint8_t rhport) {
// Deinit device controller driver
dcd_int_disable(rhport);
dcd_disconnect(rhport);
- dcd_deinit(rhport);
+ TU_VERIFY(dcd_deinit(rhport));
// Deinit class drivers
for (uint8_t i = 0; i < TOTAL_DRIVER_COUNT; i++) {
@@ -594,7 +598,6 @@ bool tud_deinit(uint8_t rhport) {
#endif
_usbd_rhport = RHPORT_INVALID;
-
return true;
}
@@ -606,8 +609,8 @@ static void configuration_reset(uint8_t rhport) {
}
tu_varclr(&_usbd_dev);
- memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping
- memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping
+ (void) memset(_usbd_dev.itf2drv, DRVID_INVALID, sizeof(_usbd_dev.itf2drv)); // invalid mapping
+ (void) memset(_usbd_dev.ep2drv, DRVID_INVALID, sizeof(_usbd_dev.ep2drv)); // invalid mapping
}
static void usbd_reset(uint8_t rhport) {
@@ -638,12 +641,16 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
(void) in_isr; // not implemented yet
// Skip if stack is not initialized
- if (!tud_inited()) return;
+ if (!tud_inited()) {
+ return;
+ }
// Loop until there is no more events in the queue
while (1) {
dcd_event_t event;
- if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) return;
+ if (!osal_queue_receive(_usbd_q, &event, timeout_ms)) {
+ return;
+ }
#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
if (event.event_id == DCD_EVENT_SETUP_RECEIVED) TU_LOG_USBD("\r\n"); // extra line for setup
@@ -667,7 +674,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
TU_ASSERT(_usbd_queued_setup > 0,);
_usbd_queued_setup--;
TU_LOG_BUF(CFG_TUD_LOG_LEVEL, &event.setup_received, 8);
- if (_usbd_queued_setup) {
+ if (_usbd_queued_setup != 0) {
TU_LOG_USBD(" Skipped since there is other SETUP in queue\r\n");
break;
}
@@ -703,8 +710,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
_usbd_dev.ep_status[epnum][ep_dir].claimed = 0;
if (0 == epnum) {
- usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result,
- event.xfer_complete.len);
+ usbd_control_xfer_cb(event.rhport, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
} else {
usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]);
TU_ASSERT(driver,);
@@ -738,7 +744,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
case USBD_EVENT_FUNC_CALL:
TU_LOG_USBD("\r\n");
- if (event.func_call.func) {
+ if (event.func_call.func != NULL) {
event.func_call.func(event.func_call.param);
}
break;
@@ -792,7 +798,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
}
#endif
- switch ( p_request->bmRequestType_bit.recipient ) {
+ switch (p_request->bmRequestType_bit.recipient) { //-V2520
//------------- Device Requests e.g in enumeration -------------//
case TUSB_REQ_RCPT_DEVICE:
if ( TUSB_REQ_TYPE_CLASS == p_request->bmRequestType_bit.type ) {
@@ -806,13 +812,13 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
return invoke_class_control(rhport, driver, p_request);
}
- if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) {
+ if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) {
// Non-standard request is not supported
TU_BREAKPOINT();
return false;
}
- switch ( p_request->bRequest ) {
+ switch (p_request->bRequest) { //-V2520
case TUSB_REQ_SET_ADDRESS:
// Depending on mcu, status phase could be sent either before or after changing device address,
// or even require stack to not response with status at all
@@ -834,18 +840,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// Only process if new configure is different
if (_usbd_dev.cfg_num != cfg_num) {
- if ( _usbd_dev.cfg_num ) {
+ if (_usbd_dev.cfg_num != 0) {
// already configured: need to clear all endpoints and driver first
TU_LOG_USBD(" Clear current Configuration (%u) before switching\r\n", _usbd_dev.cfg_num);
- // disable SOF
dcd_sof_enable(rhport, false);
-
- // close all non-control endpoints, cancel all pending transfers if any
dcd_edpt_close_all(rhport);
// close all drivers and current configured state except bus speed
- uint8_t const speed = _usbd_dev.speed;
+ const uint8_t speed = _usbd_dev.speed;
configuration_reset(rhport);
_usbd_dev.speed = speed; // restore speed
@@ -853,18 +856,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
_usbd_dev.cfg_num = cfg_num;
- // Handle the new configuration and execute the corresponding callback
- if ( cfg_num ) {
- // switch to new configuration if not zero
+ // Handle the new configuration
+ if (cfg_num == 0) {
+ tud_umount_cb();
+ } else {
if (!process_set_config(rhport, cfg_num)) {
- TU_MESS_FAILED();
- TU_BREAKPOINT();
_usbd_dev.cfg_num = 0;
- return false;
+ TU_ASSERT(false);
}
tud_mount_cb();
- } else {
- tud_umount_cb();
}
}
@@ -873,17 +873,17 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
break;
case TUSB_REQ_GET_DESCRIPTOR:
- TU_VERIFY( process_get_descriptor(rhport, p_request) );
+ TU_VERIFY(process_get_descriptor(rhport, p_request));
break;
case TUSB_REQ_SET_FEATURE:
- switch(p_request->wValue) {
+ switch(p_request->wValue) { //-V2520
case TUSB_REQ_FEATURE_REMOTE_WAKEUP:
TU_LOG_USBD(" Enable Remote Wakeup\r\n");
// Host may enable remote wake up before suspending especially HID device
_usbd_dev.remote_wakeup_en = true;
tud_control_status(rhport, p_request);
- break;
+ break;
#if CFG_TUD_TEST_MODE
case TUSB_REQ_FEATURE_TEST_MODE: {
@@ -897,7 +897,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
tud_control_status(rhport, p_request);
break;
}
- #endif /* CFG_TUD_TEST_MODE */
+ #endif
// Stall unsupported feature selector
default: return false;
@@ -907,13 +907,12 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
case TUSB_REQ_CLEAR_FEATURE:
// Only support remote wakeup for device feature
TU_VERIFY(TUSB_REQ_FEATURE_REMOTE_WAKEUP == p_request->wValue);
-
TU_LOG_USBD(" Disable Remote Wakeup\r\n");
// Host may disable remote wake up after resuming
_usbd_dev.remote_wakeup_en = false;
tud_control_status(rhport, p_request);
- break;
+ break;
case TUSB_REQ_GET_STATUS: {
// Device status bit mask
@@ -939,24 +938,24 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
// all requests to Interface (STD or Class) is forwarded to class driver.
// notable requests are: GET HID REPORT DESCRIPTOR, SET_INTERFACE, GET_INTERFACE
- if ( !invoke_class_control(rhport, driver, p_request) ) {
+ if (!invoke_class_control(rhport, driver, p_request)) {
// For GET_INTERFACE and SET_INTERFACE, it is mandatory to respond even if the class
// driver doesn't use alternate settings or implement this
TU_VERIFY(TUSB_REQ_TYPE_STANDARD == p_request->bmRequestType_bit.type);
- switch(p_request->bRequest) {
- case TUSB_REQ_GET_INTERFACE:
- case TUSB_REQ_SET_INTERFACE:
- // Clear complete callback if driver set since it can also stall the request.
- usbd_control_set_complete_callback(NULL);
+ // Clear complete callback if driver set since it can also stall the request.
+ usbd_control_set_complete_callback(NULL);
- if (TUSB_REQ_GET_INTERFACE == p_request->bRequest) {
- uint8_t alternate = 0;
- tud_control_xfer(rhport, p_request, &alternate, 1);
- }else {
- tud_control_status(rhport, p_request);
- }
- break;
+ switch (p_request->bRequest) { //-V2520
+ case TUSB_REQ_GET_INTERFACE: {
+ uint8_t alternate = 0;
+ tud_control_xfer(rhport, p_request, &alternate, 1);
+ break;
+ }
+
+ case TUSB_REQ_SET_INTERFACE:
+ tud_control_status(rhport, p_request);
+ break;
default: return false;
}
@@ -973,15 +972,15 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
TU_ASSERT(ep_num < TU_ARRAY_SIZE(_usbd_dev.ep2drv) );
usbd_class_driver_t const * driver = get_driver(_usbd_dev.ep2drv[ep_num][ep_dir]);
- if ( TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type ) {
+ if (TUSB_REQ_TYPE_STANDARD != p_request->bmRequestType_bit.type) {
// Forward class request to its driver
TU_VERIFY(driver);
return invoke_class_control(rhport, driver, p_request);
} else {
// Handle STD request to endpoint
- switch ( p_request->bRequest ) {
+ switch (p_request->bRequest) { //-V2520
case TUSB_REQ_GET_STATUS: {
- uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001 : 0x0000;
+ uint16_t status = usbd_edpt_stalled(rhport, ep_addr) ? 0x0001u : 0x0000u;
tud_control_xfer(rhport, p_request, &status, 2);
}
break;
@@ -996,7 +995,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
}
}
- if (driver) {
+ if (driver != NULL) {
// Some classes such as USBTMC needs to clear/re-init its buffer when receiving CLEAR_FEATURE request
// We will also forward std request targeted endpoint to class drivers as well
@@ -1006,7 +1005,9 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
usbd_control_set_complete_callback(NULL);
// skip ZLP status if driver already did that
- if ( !_usbd_dev.ep_status[0][TUSB_DIR_IN].busy ) tud_control_status(rhport, p_request);
+ if (!_usbd_dev.ep_status[0][TUSB_DIR_IN].busy) {
+ tud_control_status(rhport, p_request);
+ }
}
}
break;
@@ -1017,8 +1018,8 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const
return false;
}
}
+ break;
}
- break;
// Unknown recipient
default:
@@ -1081,10 +1082,11 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
// Some drivers use 2 or more interfaces but may not have IAD e.g MIDI (always) or
// BTH (even CDC) with class in device descriptor (single interface)
- if ( assoc_itf_count == 1)
- {
+ if (assoc_itf_count == 1) {
#if CFG_TUD_CDC
- if ( driver->open == cdcd_open ) assoc_itf_count = 2;
+ if ( driver->open == cdcd_open ) {
+ assoc_itf_count = 2;
+ }
#endif
#if CFG_TUD_MIDI
@@ -1101,6 +1103,28 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
#if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT
if ( driver->open == btd_open ) assoc_itf_count = 2;
#endif
+
+ #if CFG_TUD_AUDIO
+ if (driver->open == audiod_open) {
+ // UAC1 device doesn't have IAD, needs to read AS interface count from CS AC descriptor
+ if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
+ AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass &&
+ AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) {
+ uint8_t const* p = tu_desc_next(p_desc);
+ uint8_t const* const itf_end = p_desc + remaining_len;
+ while (p < itf_end) {
+ if (TUSB_DESC_CS_INTERFACE == tu_desc_type(p) &&
+ AUDIO10_CS_AC_INTERFACE_HEADER == ((audio10_desc_cs_ac_interface_1_t const *) p)->bDescriptorSubType) {
+ audio10_desc_cs_ac_interface_1_t const * p_header = (audio10_desc_cs_ac_interface_1_t const *) p;
+ // AC + AS interfaces
+ assoc_itf_count = p_header->bInCollection + 1;
+ break;
+ }
+ p = tu_desc_next(p);
+ }
+ }
+ }
+ #endif
}
// bind (associated) interfaces to found driver
@@ -1136,8 +1160,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
tusb_desc_type_t const desc_type = (tusb_desc_type_t) tu_u16_high(p_request->wValue);
uint8_t const desc_index = tu_u16_low( p_request->wValue );
- switch(desc_type)
- {
+ switch(desc_type) { //-V2520
case TUSB_DESC_DEVICE: {
TU_LOG_USBD(" Device\r\n");
@@ -1165,7 +1188,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
// requested by host if USB > 2.0 ( i.e 2.1 or 3.x )
uintptr_t desc_bos = (uintptr_t) tud_descriptor_bos_cb();
- TU_VERIFY(desc_bos);
+ TU_VERIFY(desc_bos != 0);
// Use offsetof to avoid pointer to the odd/misaligned address
uint16_t const total_len = tu_le16toh( tu_unaligned_read16((const void*) (desc_bos + offsetof(tusb_desc_bos_t, wTotalLength))) );
@@ -1181,12 +1204,12 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
if ( desc_type == TUSB_DESC_CONFIGURATION ) {
TU_LOG_USBD(" Configuration[%u]\r\n", desc_index);
desc_config = (uintptr_t) tud_descriptor_configuration_cb(desc_index);
- TU_ASSERT(desc_config);
+ TU_ASSERT(desc_config != 0);
}else {
// Host only request this after getting Device Qualifier descriptor
TU_LOG_USBD(" Other Speed Configuration\r\n");
desc_config = (uintptr_t) tud_descriptor_other_speed_configuration_cb(desc_index);
- TU_VERIFY(desc_config);
+ TU_VERIFY(desc_config != 0);
}
// Use offsetof to avoid pointer to the odd/misaligned address
@@ -1196,8 +1219,7 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const
}
// break; // unreachable
- case TUSB_DESC_STRING:
- {
+ case TUSB_DESC_STRING: {
TU_LOG_USBD(" String[%u]\r\n", desc_index);
// String Descriptor always uses the desc set from user