aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-09-08 12:28:44 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-09-08 12:28:44 +0000
commite5833b6a09786844ae09f389d768accec9678026 (patch)
tree879fb45694cc431f39098e05c9ae6c0e9cde8c0e
parentaa7557a5f206124dc232343be2010f7d9b82e267 (diff)
downloadChibiOS-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.h1
-rw-r--r--os/hal/src/serial_usb.c43
-rw-r--r--readme.txt3
-rw-r--r--testhal/STM32/STM32F7xx/USB_CDC/usbcfg.c6
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;