Skip to content

Conversation

@jfischer-no
Copy link
Contributor

USBD_MAX_UDC_MSG configures the number of events coming from the UDC driver that the stack can keep. This can be filled very quickly if there would be multiple bus events for some reason, or function handlers of those events are blocked for long time. As a consequence, subsequent events could be dropped, and completed transfers not handled. To avoid it, we can store completed transfer requests in a slist and check it on every event.

Resolves: #74058

USBD_MAX_UDC_MSG configures the number of events coming from the UDC
driver that the stack can keep. This can be filled very quickly if there
would be multiple bus events for some reason, or function handlers of
those events are blocked for long time. As a consequence, subsequent
events could be dropped, and completed transfers not handled. To avoid
it, we can store completed transfer requests in a slist and check it on
every event.

Signed-off-by: Johann Fischer <[email protected]>
@sonarqubecloud
Copy link

/** Notification message recipient callback */
usbd_msg_cb_t msg_cb;
/** slist to keep endpoint events */
sys_slist_t ep_events;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sure it was probably considered, but if not, another option is to use sys_dlist_t. There is no additional cost in storage, and list elements can be removed efficiently from any point.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The events are processed in FIFO manner, so the advantage of "list elements can be removed efficiently from any point" doesn't seem necessary.

Comment on lines +167 to +170
if (event->type == UDC_EVT_EP_REQUEST) {
/* It has already been handled and cannot be another event type. */
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to keep the case UDC_EVT_EP_REQUEST under switch below, i.e.

case UDC_EVT_EP_REQUEST:
	/* It has already been handled */
	break;

Functionality wise this is equivalent to the if above, but it makes it clear that there is no omission in the switch.

{
int err = 0;

/* Always check if there is a completed transfer request. */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add note that this check is really a workaround for usbd_event_carrier() dropping messages on full queue, because otherwise the reason for unconditionally calling event_handler_ep_request() is not really obvious.

@nashif nashif merged commit 5137439 into zephyrproject-rtos:main Nov 21, 2025
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: USB Universal Serial Bus

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UDC events silently dropped on queue full lead to USB stack issues

4 participants