Disconnect handling in SDU driver.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8287 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2015-09-08 12:28:44 +00:00
parent aa7557a5f2
commit e5833b6a09
4 changed files with 51 additions and 2 deletions

View File

@ -247,6 +247,7 @@ extern "C" {
void sduObjectInit(SerialUSBDriver *sdup); void sduObjectInit(SerialUSBDriver *sdup);
void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config); void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config);
void sduStop(SerialUSBDriver *sdup); void sduStop(SerialUSBDriver *sdup);
void sduDisconnectI(SerialUSBDriver *sdup);
void sduConfigureHookI(SerialUSBDriver *sdup); void sduConfigureHookI(SerialUSBDriver *sdup);
bool sduRequestsHook(USBDriver *usbp); bool sduRequestsHook(USBDriver *usbp);
void sduDataTransmitted(USBDriver *usbp, usbep_t ep); void sduDataTransmitted(USBDriver *usbp, usbep_t ep);

View File

@ -56,43 +56,67 @@ static cdc_linecoding_t linecoding = {
static size_t write(void *ip, const uint8_t *bp, size_t n) { 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, return oqWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp,
n, TIME_INFINITE); n, TIME_INFINITE);
} }
static size_t read(void *ip, uint8_t *bp, size_t n) { 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, return iqReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp,
n, TIME_INFINITE); n, TIME_INFINITE);
} }
static msg_t put(void *ip, uint8_t b) { 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); return oqPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, TIME_INFINITE);
} }
static msg_t get(void *ip) { static msg_t get(void *ip) {
if (usbGetDriverStateI(((SerialUSBDriver *)ip)->config->usbp) != USB_ACTIVE)
return MSG_RESET;
return iqGetTimeout(&((SerialUSBDriver *)ip)->iqueue, TIME_INFINITE); return iqGetTimeout(&((SerialUSBDriver *)ip)->iqueue, TIME_INFINITE);
} }
static msg_t putt(void *ip, uint8_t b, systime_t timeout) { 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); return oqPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, timeout);
} }
static msg_t gett(void *ip, systime_t 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); return iqGetTimeout(&((SerialUSBDriver *)ip)->iqueue, timeout);
} }
static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t 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); return oqWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, n, timeout);
} }
static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t 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); return iqReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, timeout);
} }
@ -252,12 +276,27 @@ void sduStop(SerialUSBDriver *sdup) {
} }
sdup->state = SDU_STOP; 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.*/ /* Queues reset in order to signal the driver stop to the application.*/
chnAddFlagsI(sdup, CHN_DISCONNECTED); chnAddFlagsI(sdup, CHN_DISCONNECTED);
iqResetI(&sdup->iqueue); iqResetI(&sdup->iqueue);
iqResetI(&sdup->oqueue); iqResetI(&sdup->oqueue);
osalOsRescheduleS();
osalSysUnlock();
} }
/** /**

View File

@ -73,6 +73,9 @@
***************************************************************************** *****************************************************************************
*** 3.1.0 *** *** 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 - 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 allows the application to detect if the USB is communicating or if
it is disconnected or powered down. it is disconnected or powered down.

View File

@ -284,6 +284,12 @@ static void usb_event(USBDriver *usbp, usbevent_t event) {
chSysUnlockFromISR(); chSysUnlockFromISR();
return; return;
case USB_EVENT_SUSPEND: case USB_EVENT_SUSPEND:
chSysLockFromISR();
/* Disconnection event on suspend.*/
sduDisconnectI(&SDU2);
chSysUnlockFromISR();
return; return;
case USB_EVENT_WAKEUP: case USB_EVENT_WAKEUP:
return; return;