diff --git a/firmware/export/usb.h b/firmware/export/usb.h index 35d525e304..13271652f9 100644 --- a/firmware/export/usb.h +++ b/firmware/export/usb.h @@ -240,6 +240,8 @@ void usb_set_mode(int mode); /* USB driver call this function to notify that a transfer has completed */ void usb_signal_transfer_completion( struct usb_transfer_completion_event_data *event_data); +/* Clear all signaled transfer completion events from event queue */ +void usb_clear_pending_transfer_completion_events(void); /* notify the USB code that some important event has occurred which influences the * USB state (like USB_NOTIFY_SET_ADDR). USB drivers should call usb_core_notify_* * functions and not this function. */ diff --git a/firmware/usb.c b/firmware/usb.c index df87919892..7f4c61a573 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -305,6 +305,13 @@ void usb_signal_transfer_completion( queue_post(&usb_queue, USB_TRANSFER_COMPLETION, (intptr_t)event_data); } +void usb_clear_pending_transfer_completion_events(void) +{ + while (queue_peek_ex(&usb_queue, NULL, + 1 | QPEEK_REMOVE_EVENTS, + QPEEK_FILTER1(USB_TRANSFER_COMPLETION))); +} + void usb_signal_notify(long id, intptr_t data) { queue_post(&usb_queue, id, data); diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c index 4cf4e1b137..3f2aff4310 100644 --- a/firmware/usbstack/usb_core.c +++ b/firmware/usbstack/usb_core.c @@ -863,9 +863,14 @@ static int usb_core_do_set_config(uint8_t new_config) } } init_deinit_endpoints(usb_config - 1, false); + + /* clear any pending transfer completions, + * because they are depend on contents of ep_data */ + usb_clear_pending_transfer_completion_events(); + /* reset endpoint states */ + memset(ep_data, 0, sizeof(ep_data)); } - memset(ep_data, 0, sizeof(ep_data)); usb_config = new_config; usb_state = usb_config == 0 ? ADDRESS : CONFIGURED;