diff options
author | Giovanni Di Sirio <gdisirio@gmail.com> | 2015-09-08 12:28:44 +0000 |
---|---|---|
committer | Giovanni Di Sirio <gdisirio@gmail.com> | 2015-09-08 12:28:44 +0000 |
commit | e5833b6a09786844ae09f389d768accec9678026 (patch) | |
tree | 879fb45694cc431f39098e05c9ae6c0e9cde8c0e | |
parent | aa7557a5f206124dc232343be2010f7d9b82e267 (diff) | |
download | ChibiOS-e5833b6a09786844ae09f389d768accec9678026.tar.gz ChibiOS-e5833b6a09786844ae09f389d768accec9678026.tar.bz2 ChibiOS-e5833b6a09786844ae09f389d768accec9678026.zip |
Disconnect handling in SDU driver.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8287 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r-- | os/hal/include/serial_usb.h | 1 | ||||
-rw-r--r-- | os/hal/src/serial_usb.c | 43 | ||||
-rw-r--r-- | readme.txt | 3 | ||||
-rw-r--r-- | testhal/STM32/STM32F7xx/USB_CDC/usbcfg.c | 6 |
4 files changed, 51 insertions, 2 deletions
diff --git a/os/hal/include/serial_usb.h b/os/hal/include/serial_usb.h index abf6313d0..22e873ea1 100644 --- a/os/hal/include/serial_usb.h +++ b/os/hal/include/serial_usb.h @@ -247,6 +247,7 @@ extern "C" { void sduObjectInit(SerialUSBDriver *sdup);
void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config);
void sduStop(SerialUSBDriver *sdup);
+ void sduDisconnectI(SerialUSBDriver *sdup);
void sduConfigureHookI(SerialUSBDriver *sdup);
bool sduRequestsHook(USBDriver *usbp);
void sduDataTransmitted(USBDriver *usbp, usbep_t ep);
diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index dc0e803a8..c32a17376 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -56,43 +56,67 @@ static cdc_linecoding_t linecoding = { static size_t write(void *ip, const uint8_t *bp, size_t n) {
+ if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
+ return 0;
+
return oqWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp,
n, TIME_INFINITE);
}
static size_t read(void *ip, uint8_t *bp, size_t n) {
+ if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
+ return 0;
+
return iqReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp,
n, TIME_INFINITE);
}
static msg_t put(void *ip, uint8_t b) {
+ if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
+ return MSG_RESET;
+
return oqPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, TIME_INFINITE);
}
static msg_t get(void *ip) {
+ if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
+ return MSG_RESET;
+
return iqGetTimeout(&((SerialUSBDriver *)ip)->iqueue, TIME_INFINITE);
}
static msg_t putt(void *ip, uint8_t b, systime_t timeout) {
+ if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
+ return MSG_RESET;
+
return oqPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, timeout);
}
static msg_t gett(void *ip, systime_t timeout) {
+ if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
+ return MSG_RESET;
+
return iqGetTimeout(&((SerialUSBDriver *)ip)->iqueue, timeout);
}
static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) {
+ if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
+ return 0;
+
return oqWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, n, timeout);
}
static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) {
+ if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
+ return 0;
+
return iqReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, timeout);
}
@@ -252,12 +276,27 @@ void sduStop(SerialUSBDriver *sdup) { }
sdup->state = SDU_STOP;
+ /* Enforces a disconnection.*/
+ sduDisconnectI(sdup);
+ osalOsRescheduleS();
+ osalSysUnlock();
+}
+
+/**
+ * @brief USB device disconnection handler.
+ * @note If this function is not called from an ISR then an explicit call
+ * to @p osalOsRescheduleS() in necessary afterward.
+ *
+ * @param[in] sdup pointer to a @p SerialUSBDriver object
+ *
+ * @iclass
+ */
+void sduDisconnectI(SerialUSBDriver *sdup) {
+
/* Queues reset in order to signal the driver stop to the application.*/
chnAddFlagsI(sdup, CHN_DISCONNECTED);
iqResetI(&sdup->iqueue);
iqResetI(&sdup->oqueue);
- osalOsRescheduleS();
- osalSysUnlock();
}
/**
diff --git a/readme.txt b/readme.txt index 576aeecf5..6d3ba394b 100644 --- a/readme.txt +++ b/readme.txt @@ -73,6 +73,9 @@ *****************************************************************************
*** 3.1.0 ***
+- HAL: Modified the serial-USB driver to reject write/read attempts if the
+ underlying USB is not in active state. In case of disconnection the
+ SDU driver broadcasts a CHN_DISCONNECTED event.
- HAL: Modified the USB driver to have a separate USB_SUSPENDED state, this
allows the application to detect if the USB is communicating or if
it is disconnected or powered down.
diff --git a/testhal/STM32/STM32F7xx/USB_CDC/usbcfg.c b/testhal/STM32/STM32F7xx/USB_CDC/usbcfg.c index 73ada5cc0..968fd6724 100644 --- a/testhal/STM32/STM32F7xx/USB_CDC/usbcfg.c +++ b/testhal/STM32/STM32F7xx/USB_CDC/usbcfg.c @@ -284,6 +284,12 @@ static void usb_event(USBDriver *usbp, usbevent_t event) { chSysUnlockFromISR();
return;
case USB_EVENT_SUSPEND:
+ chSysLockFromISR();
+
+ /* Disconnection event on suspend.*/
+ sduDisconnectI(&SDU2);
+
+ chSysUnlockFromISR();
return;
case USB_EVENT_WAKEUP:
return;
|