From c3150eb13679314f8bfc02714ae0027dd1658002 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Thu, 16 Jun 2016 09:22:22 +0000 Subject: USB fixes. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9628 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/hal_usb.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'os/hal/src/hal_usb.c') diff --git a/os/hal/src/hal_usb.c b/os/hal/src/hal_usb.c index d6d5b6606..c10bf0d56 100644 --- a/os/hal/src/hal_usb.c +++ b/os/hal/src/hal_usb.c @@ -144,12 +144,20 @@ static bool default_handler(USBDriver *usbp) { /* Handling configuration selection from the host.*/ usbp->configuration = usbp->setup[2]; if (usbp->configuration == 0U) { - usbp->state = USB_SELECTED; + if (usbp->state == USB_ACTIVE) { + chSysLockFromISR (); + usbDisableEndpointsI(usbp); + chSysUnlockFromISR (); + usbp->state = USB_SELECTED; + _usb_isr_invoke_event_cb(usbp, USB_EVENT_UNCONFIGURED); + } } else { - usbp->state = USB_ACTIVE; + if (usbp->state != USB_ACTIVE) { + usbp->state = USB_ACTIVE; + _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED); + } } - _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED); usbSetupTransfer(usbp, NULL, 0, NULL); return true; case (uint32_t)USB_RTYPE_RECIPIENT_INTERFACE | ((uint32_t)USB_REQ_GET_STATUS << 8): @@ -318,8 +326,8 @@ void usbStop(USBDriver *usbp) { osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) || (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE) || (usbp->state == USB_SUSPENDED), - "invalid state"); + usb_lld_stop(usbp); usbp->config = NULL; usbp->state = USB_STOP; @@ -396,10 +404,11 @@ void usbDisableEndpointsI(USBDriver *usbp) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); - osalDbgAssert(usbp->state == USB_SELECTED, "invalid state"); + osalDbgAssert(usbp->state == USB_ACTIVE, "invalid state"); + + usbp->transmitting &= 1U; + usbp->receiving &= 1U; - usbp->transmitting &= ~1U; - usbp->receiving &= ~1U; for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { #if USB_USE_WAIT == TRUE /* Signaling the event to threads waiting on endpoints.*/ @@ -679,9 +688,11 @@ void _usb_reset(USBDriver *usbp) { * @notapi */ void _usb_suspend(USBDriver *usbp) { + /* No state change, suspend always returns to previous state. */ /* State transition.*/ - usbp->state = USB_SUSPENDED; + usbp->saved_state = usbp->state; + usbp->state = USB_SUSPENDED; /* Notification of suspend event.*/ _usb_isr_invoke_event_cb(usbp, USB_EVENT_SUSPEND); @@ -718,8 +729,8 @@ void _usb_suspend(USBDriver *usbp) { */ void _usb_wakeup(USBDriver *usbp) { - /* State transition.*/ - usbp->state = USB_ACTIVE; + /* State transition, returning to the previous state.*/ + usbp->state = usbp->saved_state; /* Notification of suspend event.*/ _usb_isr_invoke_event_cb(usbp, USB_EVENT_WAKEUP); -- cgit v1.2.3