summaryrefslogtreecommitdiff
path: root/src/device/usbd.c
diff options
context:
space:
mode:
authorhathach <[email protected]>2025-09-15 16:45:41 +0700
committerhathach <[email protected]>2025-09-15 16:45:41 +0700
commit8e34ba9cf6bdcabe2c9eb73ae1aafec38d0ec46d (patch)
tree58c2426146aa5d413706a62521ab6e2cb740b170 /src/device/usbd.c
parent802819d271314298ea5a786a37ec6a1e65ef31d6 (diff)
parentfeef534921446e1a3ded54a0c46191fe1709bdb4 (diff)
Merge branch 'master' into fork/ennebi/mtp
Diffstat (limited to 'src/device/usbd.c')
-rw-r--r--src/device/usbd.c112
1 files changed, 87 insertions, 25 deletions
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 8f50d815f..8620c3b6f 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -163,6 +163,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = cdcd_open,
.control_xfer_cb = cdcd_control_xfer_cb,
.xfer_cb = cdcd_xfer_cb,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -176,6 +177,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = mscd_open,
.control_xfer_cb = mscd_control_xfer_cb,
.xfer_cb = mscd_xfer_cb,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -189,6 +191,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = hidd_open,
.control_xfer_cb = hidd_control_xfer_cb,
.xfer_cb = hidd_xfer_cb,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -202,6 +205,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = audiod_open,
.control_xfer_cb = audiod_control_xfer_cb,
.xfer_cb = audiod_xfer_cb,
+ .xfer_isr = audiod_xfer_isr,
.sof = audiod_sof_isr
},
#endif
@@ -215,6 +219,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = videod_open,
.control_xfer_cb = videod_control_xfer_cb,
.xfer_cb = videod_xfer_cb,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -228,6 +233,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.reset = midid_reset,
.control_xfer_cb = midid_control_xfer_cb,
.xfer_cb = midid_xfer_cb,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -241,6 +247,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = vendord_open,
.control_xfer_cb = tud_vendor_control_xfer_cb,
.xfer_cb = vendord_xfer_cb,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -254,6 +261,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = usbtmcd_open_cb,
.control_xfer_cb = usbtmcd_control_xfer_cb,
.xfer_cb = usbtmcd_xfer_cb,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -267,6 +275,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = dfu_rtd_open,
.control_xfer_cb = dfu_rtd_control_xfer_cb,
.xfer_cb = NULL,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -280,6 +289,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = dfu_moded_open,
.control_xfer_cb = dfu_moded_control_xfer_cb,
.xfer_cb = NULL,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -293,7 +303,8 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = netd_open,
.control_xfer_cb = netd_control_xfer_cb,
.xfer_cb = netd_xfer_cb,
- .sof = NULL,
+ .xfer_isr = NULL,
+ .sof = NULL,
},
#endif
@@ -306,6 +317,7 @@ tu_static usbd_class_driver_t const _usbd_driver[] = {
.open = btd_open,
.control_xfer_cb = btd_control_xfer_cb,
.xfer_cb = btd_xfer_cb,
+ .xfer_isr = NULL,
.sof = NULL
},
#endif
@@ -330,38 +342,37 @@ enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) };
tu_static usbd_class_driver_t const * _app_driver = NULL;
tu_static uint8_t _app_driver_count = 0;
-#define TOTAL_DRIVER_COUNT (_app_driver_count + BUILTIN_DRIVER_COUNT)
+#define TOTAL_DRIVER_COUNT ((uint8_t) (_app_driver_count + BUILTIN_DRIVER_COUNT))
// virtually joins built-in and application drivers together.
// Application is positioned first to allow overwriting built-in ones.
TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8_t drvid) {
- usbd_class_driver_t const * driver = NULL;
- if ( drvid < _app_driver_count ) {
+ usbd_class_driver_t const *driver = NULL;
+ if (drvid < _app_driver_count) {
// Application drivers
driver = &_app_driver[drvid];
- } else if ( drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0 ){
+ } else if (drvid < TOTAL_DRIVER_COUNT && BUILTIN_DRIVER_COUNT > 0) {
driver = &_usbd_driver[drvid - _app_driver_count];
}
return driver;
}
-
//--------------------------------------------------------------------+
// DCD Event
//--------------------------------------------------------------------+
-
enum { RHPORT_INVALID = 0xFFu };
tu_static uint8_t _usbd_rhport = RHPORT_INVALID;
-// Event queue
-// usbd_int_set() is used as mutex in OS NONE config
+static OSAL_SPINLOCK_DEF(_usbd_spin, usbd_int_set);
+
+// Event queue: usbd_int_set() is used as mutex in OS NONE config
OSAL_QUEUE_DEF(usbd_int_set, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t);
-tu_static osal_queue_t _usbd_q;
+static osal_queue_t _usbd_q;
// Mutex for claiming endpoint
#if OSAL_MUTEX_REQUIRED
- tu_static osal_mutex_def_t _ubsd_mutexdef;
- tu_static osal_mutex_t _usbd_mutex;
+ static osal_mutex_def_t _ubsd_mutexdef;
+ static osal_mutex_t _usbd_mutex;
#else
#define _usbd_mutex NULL
#endif
@@ -477,17 +488,36 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
return true; // skip if already initialized
}
TU_ASSERT(rh_init);
-
- TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport,
- rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full");
+#if CFG_TUSB_DEBUG >= CFG_TUD_LOG_LEVEL
+ char const* speed_str = 0;
+ switch (rh_init->speed) {
+ case TUSB_SPEED_HIGH:
+ speed_str = "High";
+ break;
+ case TUSB_SPEED_FULL:
+ speed_str = "Full";
+ break;
+ case TUSB_SPEED_LOW:
+ speed_str = "Low";
+ break;
+ case TUSB_SPEED_AUTO:
+ speed_str = "Auto";
+ break;
+ default:
+ break;
+ }
+ TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport, speed_str);
TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t));
TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t));
TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t));
TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_edpt_stream_t));
+#endif
tu_varclr(&_usbd_dev);
_usbd_queued_setup = 0;
+ osal_spin_init(&_usbd_spin);
+
#if OSAL_MUTEX_REQUIRED
// Init device mutex
_usbd_mutex = osal_mutex_create(&_ubsd_mutexdef);
@@ -501,6 +531,7 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
// Get application driver if available
if (usbd_app_driver_get_cb) {
_app_driver = usbd_app_driver_get_cb(&_app_driver_count);
+ TU_ASSERT(_app_driver_count + BUILTIN_DRIVER_COUNT <= UINT8_MAX);
}
// Init class drivers
@@ -574,8 +605,7 @@ static void usbd_reset(uint8_t rhport) {
}
bool tud_task_event_ready(void) {
- // Skip if stack is not initialized
- if (!tud_inited()) return false;
+ TU_VERIFY(tud_inited()); // Skip if stack is not initialized
return !osal_queue_empty(_usbd_q);
}
@@ -697,7 +727,9 @@ 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) event.func_call.func(event.func_call.param);
+ if (event.func_call.func) {
+ event.func_call.func(event.func_call.param);
+ }
break;
case DCD_EVENT_SOF:
@@ -714,7 +746,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO
// return if there is no more events, for application to run other background
- if (osal_queue_empty(_usbd_q)) return;
+ if (osal_queue_empty(_usbd_q)) { return; }
#endif
}
}
@@ -1240,6 +1272,32 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr)
send = true;
break;
+ case DCD_EVENT_XFER_COMPLETE: {
+ // Invoke the class callback associated with the endpoint address
+ uint8_t const ep_addr = event->xfer_complete.ep_addr;
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const ep_dir = tu_edpt_dir(ep_addr);
+
+ send = true;
+ if(epnum > 0) {
+ usbd_class_driver_t const* driver = get_driver(_usbd_dev.ep2drv[epnum][ep_dir]);
+
+ if (driver && driver->xfer_isr) {
+ _usbd_dev.ep_status[epnum][ep_dir].busy = 0;
+ _usbd_dev.ep_status[epnum][ep_dir].claimed = 0;
+
+ send = !driver->xfer_isr(event->rhport, ep_addr, (xfer_result_t) event->xfer_complete.result, event->xfer_complete.len);
+
+ // xfer_isr() is deferred to xfer_cb(), revert busy/claimed status
+ if (send) {
+ _usbd_dev.ep_status[epnum][ep_dir].busy = 1;
+ _usbd_dev.ep_status[epnum][ep_dir].claimed = 1;
+ }
+ }
+ }
+ break;
+ }
+
default:
send = true;
break;
@@ -1254,17 +1312,21 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr)
// USBD API For Class Driver
//--------------------------------------------------------------------+
-void usbd_int_set(bool enabled)
-{
- if (enabled)
- {
+void usbd_int_set(bool enabled) {
+ if (enabled) {
dcd_int_enable(_usbd_rhport);
- }else
- {
+ } else {
dcd_int_disable(_usbd_rhport);
}
}
+void usbd_spin_lock(bool in_isr) {
+ osal_spin_lock(&_usbd_spin, in_isr);
+}
+void usbd_spin_unlock(bool in_isr) {
+ osal_spin_unlock(&_usbd_spin, in_isr);
+}
+
// Parse consecutive endpoint descriptors (IN & OUT)
bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in)
{