diff options
author | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-06-16 09:22:22 +0000 |
---|---|---|
committer | Giovanni Di Sirio <gdisirio@gmail.com> | 2016-06-16 09:22:22 +0000 |
commit | c3150eb13679314f8bfc02714ae0027dd1658002 (patch) | |
tree | ccb186462f6402db2fd8acded21d103519a58905 /os/hal/src | |
parent | 77a63206e770cb4a73abf3063ce381fa8de4705b (diff) | |
download | ChibiOS-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')
-rw-r--r-- | os/hal/src/hal_serial_usb.c | 67 | ||||
-rw-r--r-- | os/hal/src/hal_usb.c | 31 |
2 files changed, 53 insertions, 45 deletions
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);
|