diff options
| author | hathach <[email protected]> | 2026-08-12 22:36:49 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-08-12 22:41:17 +0700 |
| commit | a0249ada9096365697340031a7b4a285beb18a2b (patch) | |
| tree | a860c416a256718d4e2a5ef0c623bbc32fa0977b /src | |
| parent | 32530d8f4b6cd6d6f7a7df7e6358856c7ebc4f5e (diff) | |
usbd: don't leak the queued-setup counter when the event queue is full
A SETUP arriving while the event queue is full is silently dropped by
queue_event(), but _usbd_queued_setup has already been incremented. The
leaked count makes the event handler skip every subsequent SETUP
("Skipped since there is other SETUP in queue") forever: EP0 stays deaf
until tud_init() while the device otherwise looks alive - enumerated,
endpoints armed. Undo the increment when the enqueue fails.
Unit test: fill the queue so a SETUP is dropped, then verify the next
SETUP still completes a GET_DESCRIPTOR control transfer.
Diffstat (limited to 'src')
| -rw-r--r-- | src/device/usbd.c | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/src/device/usbd.c b/src/device/usbd.c index 5471e132d..b77b766dd 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1473,8 +1473,10 @@ 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->event_id == DCD_EVENT_SETUP_RECEIVED) { + // dropped by a full queue: undo the increment, else every later SETUP is skipped as + // "other SETUP in queue" and EP0 is deaf until re-init + _usbd_queued_setup--; } } |
