diff --git a/src/device/usbd.c b/src/device/usbd.c index be85d77698..8e54a094c7 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -486,16 +486,40 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) { case DCD_EVENT_BUS_RESET: TU_LOG_USBD(": %s Speed\r\n", tu_str_speed[event.bus_reset.speed]); - usbd_reset(event.rhport); - _usbd_dev.speed = event.bus_reset.speed; - break; + TU_ATTR_FALLTHROUGH; case DCD_EVENT_UNPLUGGED: TU_LOG_USBD("\r\n"); + // Only inform application about the unmount if it was mounted before + if ( _usbd_dev.cfg_num ) + { + _usbd_dev.cfg_num = 0; + + // invoke callback + if (tud_umount_cb) tud_umount_cb(); + } + + // Inform application about a no longer valid suspend state + if ( _usbd_dev.suspended ) + { + _usbd_dev.suspended = 0; + + // invoke callback + if (tud_resume_cb) tud_resume_cb(); + } + + // Completely clear the current USB state usbd_reset(event.rhport); - // invoke callback - if (tud_umount_cb) tud_umount_cb(); + // Recover the intended bus speed + if (DCD_EVENT_BUS_RESET == event.event_id) + { + _usbd_dev.speed = event.bus_reset.speed; + } + else if (DCD_EVENT_UNPLUGGED == event.event_id) + { + _usbd_dev.speed = DCD_EVENT_INVALID; + } break; case DCD_EVENT_SETUP_RECEIVED: @@ -1069,17 +1093,20 @@ static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const //--------------------------------------------------------------------+ // DCD Event Handler //--------------------------------------------------------------------+ -TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) { - bool send = false; - switch (event->event_id) { - case DCD_EVENT_UNPLUGGED: - _usbd_dev.connected = 0; - _usbd_dev.addressed = 0; - _usbd_dev.cfg_num = 0; - _usbd_dev.suspended = 0; - send = true; - break; +TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const * event, bool in_isr) +{ + volatile static uint8_t last_event_id = DCD_EVENT_INVALID; + // Skip the useless repeating bus states + if (last_event_id == event->event_id && DCD_EVENT_UNPLUGGED <= event->event_id && DCD_EVENT_RESUME >= event->event_id) + { + return; + } + + last_event_id = event->event_id; + + switch (event->event_id) + { case DCD_EVENT_SUSPEND: // NOTE: When plugging/unplugging device, the D+/D- state are unstable and // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ). diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 3e15d51c66..2a597c89c8 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1078,6 +1078,8 @@ void dcd_int_handler(uint8_t rhport) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; bus_reset(rhport); + + dcd_event_bus_reset(rhport, TUSB_SPEED_INVALID, true); } if (int_status & GINTSTS_ENUMDNE) {