aboutsummaryrefslogtreecommitdiffstats
path: root/os/hal/src/hal_usb.c
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2016-06-16 09:22:22 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2016-06-16 09:22:22 +0000
commitc3150eb13679314f8bfc02714ae0027dd1658002 (patch)
treeccb186462f6402db2fd8acded21d103519a58905 /os/hal/src/hal_usb.c
parent77a63206e770cb4a73abf3063ce381fa8de4705b (diff)
downloadChibiOS-c3150eb13679314f8bfc02714ae0027dd1658002.tar.gz
ChibiOS-c3150eb13679314f8bfc02714ae0027dd1658002.tar.bz2
ChibiOS-c3150eb13679314f8bfc02714ae0027dd1658002.zip
USB fixes.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@9628 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/src/hal_usb.c')
-rw-r--r--os/hal/src/hal_usb.c31
1 files changed, 21 insertions, 10 deletions
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);