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_serial_usb.c | 67 ++++++++++++++++++++++----------------------- os/hal/src/hal_usb.c | 31 ++++++++++++++------- 2 files changed, 53 insertions(+), 45 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/hal_serial_usb.c b/os/hal/src/hal_serial_usb.c index 7d4ed05a8..b97254fdd 100644 --- a/os/hal/src/hal_serial_usb.c +++ b/os/hal/src/hal_serial_usb.c @@ -50,6 +50,35 @@ static cdc_linecoding_t linecoding = { /* Driver local functions. */ /*===========================================================================*/ + +static bool sdu_start_receive(SerialUSBDriver *sdup) { + uint8_t *buf; + + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || + (sdup->state != SDU_READY)) { + return true; + } + + /* Checking if there is already a transaction ongoing on the endpoint.*/ + if (usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_in)) { + return true; + } + + /* Checking if there is a buffer ready for incoming data.*/ + buf = ibqGetEmptyBufferI(&sdup->ibqueue); + if (buf == NULL) { + return true; + } + + /* Buffer found, starting a new transaction.*/ + usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, + buf, SERIAL_USB_BUFFERS_SIZE); + + return false; +} + /* * Interface implementation. */ @@ -140,24 +169,7 @@ static const struct SerialUSBDriverVMT vmt = { */ static void ibnotify(io_buffers_queue_t *bqp) { SerialUSBDriver *sdup = bqGetLinkX(bqp); - - /* If the USB driver is not in the appropriate state then transactions - must not be started.*/ - if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || - (sdup->state != SDU_READY)) { - return; - } - - /* Checking if there is already a transaction ongoing on the endpoint.*/ - if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out)) { - /* Trying to get a free buffer.*/ - uint8_t *buf = ibqGetEmptyBufferI(&sdup->ibqueue); - if (buf != NULL) { - /* Buffer found, starting a new transaction.*/ - usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, - buf, SERIAL_USB_BUFFERS_SIZE); - } - } + (void) sdu_start_receive(sdup); } /** @@ -309,19 +321,11 @@ void sduDisconnectI(SerialUSBDriver *sdup) { * @iclass */ void sduConfigureHookI(SerialUSBDriver *sdup) { - uint8_t *buf; ibqResetI(&sdup->ibqueue); obqResetI(&sdup->obqueue); chnAddFlagsI(sdup, CHN_CONNECTED); - - /* Starts the first OUT transaction immediately.*/ - buf = ibqGetEmptyBufferI(&sdup->ibqueue); - - osalDbgAssert(buf != NULL, "no free buffer"); - - usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, - buf, SERIAL_USB_BUFFERS_SIZE); + (void) sdu_start_receive(sdup); } /** @@ -457,9 +461,7 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { * @param[in] ep OUT endpoint number */ void sduDataReceived(USBDriver *usbp, usbep_t ep) { - uint8_t *buf; SerialUSBDriver *sdup = usbp->out_params[ep - 1U]; - if (sdup == NULL) { return; } @@ -477,12 +479,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { /* The endpoint cannot be busy, we are in the context of the callback, so a packet is in the buffer for sure. Trying to get a free buffer for the next transaction.*/ - buf = ibqGetEmptyBufferI(&sdup->ibqueue); - if (buf != NULL) { - /* Buffer found, starting a new transaction.*/ - usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, - buf, SERIAL_USB_BUFFERS_SIZE); - } + sdu_start_receive(sdup); osalSysUnlockFromISR(); } 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