summaryrefslogtreecommitdiff
path: root/src/device
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2026-08-13 16:57:33 +0700
committerGitHub <[email protected]>2026-08-13 16:57:33 +0700
commit53fef28335181fd6b4c8fb2ac65fdacf44659492 (patch)
treeacb6dead21113cc3b5d909dad9a5e5e93118fc35 /src/device
parentdc3927fd293126d6f2b835153155ba7830f5707f (diff)
parent91fbbd192ca9539221d3dc096f00ce77836a5d3d (diff)
Merge pull request #3817 from hathach/claude/usbd-setup-queue-leak
usbd: fix queued-setup counter leak when the event queue is full
Diffstat (limited to 'src/device')
-rw-r--r--src/device/usbd.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 5471e132d..f5c3046d6 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -642,6 +642,8 @@ static void configuration_reset(uint8_t rhport) {
static void usbd_reset(uint8_t rhport) {
configuration_reset(rhport);
+ // discard any pre-reset SETUP still counted: a stale count skips post-reset SETUPs
+ _usbd_queued_setup = 0;
}
bool tud_task_event_ready(void) {
@@ -1473,8 +1475,18 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr)
break;
}
- if (send) {
- queue_event(event, in_isr);
+ if (send && !queue_event(event, in_isr)) {
+ // event dropped by a full queue: undo state that would otherwise wedge permanently
+ if (event->event_id == DCD_EVENT_SETUP_RECEIVED) {
+ // undo the increment, else every later SETUP is skipped as "other SETUP in queue"
+ // and EP0 is deaf until re-init
+ _usbd_queued_setup--;
+ } else if (event->event_id == DCD_EVENT_XFER_COMPLETE) {
+ // clear busy + claimed, else the endpoint can never be claimed or re-armed again
+ uint8_t const epnum = tu_edpt_number(event->xfer_complete.ep_addr);
+ uint8_t const ep_dir = tu_edpt_dir(event->xfer_complete.ep_addr);
+ _usbd_dev.ep_status[epnum][ep_dir] &= (uint8_t) ~(TU_EDPT_STATE_BUSY | TU_EDPT_STATE_CLAIMED);
+ }
}
}