From 22781883e073a764779a36fe1a0b02baf8f946a0 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 30 Jan 2011 19:18:26 +0000 Subject: Merged the USB branch and made the needed adjustments, not tested yet. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2695 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 328 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 os/hal/src/serial_usb.c (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c new file mode 100644 index 000000000..62a901162 --- /dev/null +++ b/os/hal/src/serial_usb.c @@ -0,0 +1,328 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file serial_usb.c + * @brief Serial over USB Driver code. + * + * @addtogroup SERIAL_USB + * @{ + */ + +#include "ch.h" +#include "hal.h" + +#include "usb_cdc.h" + +#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/* + * Current Line Coding. + */ +static cdc_linecoding_t linecoding = { + {0x00, 0x96, 0x00, 0x00}, /* 38400. */ + LC_STOP_1, LC_PARITY_NONE, 8 +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/* + * Interface implementation. + */ + +static size_t writes(void *ip, const uint8_t *bp, size_t n) { + + return chOQWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, + n, TIME_INFINITE); +} + +static size_t reads(void *ip, uint8_t *bp, size_t n) { + + return chIQReadTimeout(&((SerialDriver *)ip)->iqueue, bp, + n, TIME_INFINITE); +} + +static bool_t putwouldblock(void *ip) { + + return chOQIsFullI(&((SerialDriver *)ip)->oqueue); +} + +static bool_t getwouldblock(void *ip) { + + return chIQIsEmptyI(&((SerialDriver *)ip)->iqueue); +} + +static msg_t putt(void *ip, uint8_t b, systime_t timeout) { + + return chOQPutTimeout(&((SerialDriver *)ip)->oqueue, b, timeout); +} + +static msg_t gett(void *ip, systime_t timeout) { + + return chIQGetTimeout(&((SerialDriver *)ip)->iqueue, timeout); +} + +static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t time) { + + return chOQWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, n, time); +} + +static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { + + return chIQReadTimeout(&((SerialDriver *)ip)->iqueue, bp, n, time); +} + +static ioflags_t getflags(void *ip) { + _ch_get_and_clear_flags_impl(ip); +} + +static const struct SerialUSBDriverVMT vmt = { + writes, reads, putwouldblock, getwouldblock, + putt, gett, writet, readt, + getflags +}; + +/** + * @brief Notification of data removed from the input queue. + */ +static void inotify(GenericQueue *qp) { + SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr; + size_t n; + + /* Writes to the input queue can only happen when the queue has been + emptied, then a whole packet is loaded in the queue.*/ + if (chIQIsEmptyI(&sdup->iqueue)) { + + n = usbReadI(sdup->config->usbp, sdup->config->data_available_ep, + sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); + if (n > 0) { + sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; + chSemSetCounterI(&sdup->iqueue.q_sem, n); + } + } +} + +/** + * @brief Notification of data inserted into the output queue. + */ +static void onotify(GenericQueue *qp) { + SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr; + size_t n; + + /* If there is any data in the output queue then it is sent within a + single packet and the queue is emptied.*/ + n = usbWriteI(sdup->config->usbp, sdup->config->data_request_ep, + sdup->oqueue.q_buffer, chOQGetFullI(&sdup->oqueue)); + if (n > 0) { + sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; + chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); + } +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Serial Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void sduInit(void) { +} + +/** + * @brief Initializes a generic full duplex driver object. + * @details The HW dependent part of the initialization has to be performed + * outside, usually in the hardware initialization code. + * + * @param[out] sdup pointer to a @p SerialUSBDriver structure + * @param[in] inotify pointer to a callback function that is invoked when + * some data is read from the Queue. The value can be + * @p NULL. + * @param[in] onotify pointer to a callback function that is invoked when + * some data is written in the Queue. The value can be + * @p NULL. + * + * @init + */ +void sduObjectInit(SerialUSBDriver *sdup) { + + sdup->vmt = &vmt; + chEvtInit(&sdup->event); + sdup->flags = IO_NO_ERROR; + sdup->state = SDU_STOP; + chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify); + chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify); + /* This is a dirty trick but those pointers are never used because queues + are accessed in block mode from the low level.*/ + sdup->iqueue.q_wrptr = (uint8_t *)sdup; + sdup->oqueue.q_rdptr = (uint8_t *)sdup; +} + +/** + * @brief Configures and starts the driver. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * @param[in] config the serial over USB driver configuration + * + * @api + */ +void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { + + chDbgCheck(sdup != NULL, "sduStart"); + + chSysLock(); + chDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), + "sduStart(), #1", + "invalid state"); + sdup->config = config; + usbStart(config->usbp, &config->usb_config); + config->usbp->usb_param = sdup; + sdup->state = SDU_READY; + chSysUnlock(); +} + +/** + * @brief Stops the driver. + * @details Any thread waiting on the driver's queues will be awakened with + * the message @p Q_RESET. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * + * @api + */ +void sduStop(SerialUSBDriver *sdup) { + + chDbgCheck(sdup != NULL, "sdStop"); + + chSysLock(); + chDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), + "sduStop(), #1", + "invalid state"); + usbStop(sdup->config->usbp); + sdup->state = SDU_STOP; + chSysUnlock(); +} + +/** + * @brief Default requests hook. + * @details Applications wanting to use the Serial over USB driver can use + * this function as requests hook in the USB configuration. + * The following requests are emulated: + * - CDC_GET_LINE_CODING. + * - CDC_SET_LINE_CODING. + * - CDC_SET_CONTROL_LINE_STATE. + * . + */ +bool_t sduRequestsHook(USBDriver *usbp) { + + if ((usbp->usb_setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { + switch (usbp->usb_setup[1]) { + case CDC_GET_LINE_CODING: + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); + return TRUE; + case CDC_SET_LINE_CODING: + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); + return TRUE; + case CDC_SET_CONTROL_LINE_STATE: + /* Nothing to do, there are no control lines.*/ + usbSetupTransfer(usbp, NULL, 0, NULL); + return TRUE; + default: + return FALSE; + } + } + return FALSE; +} + +/** + * @brief Default data request callback. + * @details The application must use this function as callback for the IN + * data endpoint. + */ +void sduDataRequest(USBDriver *usbp, usbep_t ep) { + SerialUSBDriver *sdup = usbp->usb_param; + size_t n; + + chSysLockFromIsr(); + /* If there is any data in the output queue then it is sent within a + single packet and the queue is emptied.*/ + n = chOQGetFullI(&sdup->oqueue); + if (n > 0) { + n = usbWriteI(usbp, ep, sdup->oqueue.q_buffer, n); + if (n > 0) { + sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; + chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); + chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); + } + } + chSysUnlockFromIsr(); +} + +/** + * @brief Default data available callback. + * @details The application must use this function as callback for the OUT + * data endpoint. + */ +void sduDataAvailable(USBDriver *usbp, usbep_t ep) { + SerialUSBDriver *sdup = usbp->usb_param; + + chSysLockFromIsr(); + /* Writes to the input queue can only happen when the queue has been + emptied, then a whole packet is loaded in the queue.*/ + if (chIQIsEmptyI(&sdup->iqueue)) { + size_t n; + + n = usbReadI(usbp, ep, sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); + if (n > 0) { + sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; + chSemSetCounterI(&sdup->iqueue.q_sem, n); + chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + } + } + chSysUnlockFromIsr(); +} + +/** + * @brief Default data received callback. + * @details The application must use this function as callback for the IN + * interrupt endpoint. + */ +void sduInterruptRequest(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + (void)ep; +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ -- cgit v1.2.3 From 100573d2c30750a50c3dfd9f3e7a051dcc987724 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 6 Feb 2011 13:51:08 +0000 Subject: Serial over USB changes, work in progress, the USB demo is not buildable. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2717 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 62a901162..60976eca2 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -206,7 +206,7 @@ void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { "invalid state"); sdup->config = config; usbStart(config->usbp, &config->usb_config); - config->usbp->usb_param = sdup; + config->usbp->param = sdup; sdup->state = SDU_READY; chSysUnlock(); } @@ -245,17 +245,17 @@ void sduStop(SerialUSBDriver *sdup) { */ bool_t sduRequestsHook(USBDriver *usbp) { - if ((usbp->usb_setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { - switch (usbp->usb_setup[1]) { + if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { + switch (usbp->setup[1]) { case CDC_GET_LINE_CODING: - usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding)); return TRUE; case CDC_SET_LINE_CODING: - usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding)); return TRUE; case CDC_SET_CONTROL_LINE_STATE: /* Nothing to do, there are no control lines.*/ - usbSetupTransfer(usbp, NULL, 0, NULL); + usbSetupTransfer(usbp, NULL, 0); return TRUE; default: return FALSE; @@ -265,12 +265,12 @@ bool_t sduRequestsHook(USBDriver *usbp) { } /** - * @brief Default data request callback. + * @brief Default data transmitted callback. * @details The application must use this function as callback for the IN * data endpoint. */ -void sduDataRequest(USBDriver *usbp, usbep_t ep) { - SerialUSBDriver *sdup = usbp->usb_param; +void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { + SerialUSBDriver *sdup = usbp->param; size_t n; chSysLockFromIsr(); @@ -289,12 +289,12 @@ void sduDataRequest(USBDriver *usbp, usbep_t ep) { } /** - * @brief Default data available callback. + * @brief Default data received callback. * @details The application must use this function as callback for the OUT * data endpoint. */ -void sduDataAvailable(USBDriver *usbp, usbep_t ep) { - SerialUSBDriver *sdup = usbp->usb_param; +void sduDataReceived(USBDriver *usbp, usbep_t ep) { + SerialUSBDriver *sdup = usbp->param; chSysLockFromIsr(); /* Writes to the input queue can only happen when the queue has been @@ -317,7 +317,7 @@ void sduDataAvailable(USBDriver *usbp, usbep_t ep) { * @details The application must use this function as callback for the IN * interrupt endpoint. */ -void sduInterruptRequest(USBDriver *usbp, usbep_t ep) { +void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep) { (void)usbp; (void)ep; -- cgit v1.2.3 From 77934792d53efe99678286bab123c42c546478a7 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 9 Feb 2011 16:36:49 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2722 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 60976eca2..29aec2650 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -119,9 +119,9 @@ static void inotify(GenericQueue *qp) { emptied, then a whole packet is loaded in the queue.*/ if (chIQIsEmptyI(&sdup->iqueue)) { - n = usbReadI(sdup->config->usbp, sdup->config->data_available_ep, - sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); - if (n > 0) { + n = usbReadPacketI(sdup->config->usbp, sdup->config->data_available_ep, + sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); + if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; chSemSetCounterI(&sdup->iqueue.q_sem, n); } @@ -137,9 +137,9 @@ static void onotify(GenericQueue *qp) { /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ - n = usbWriteI(sdup->config->usbp, sdup->config->data_request_ep, - sdup->oqueue.q_buffer, chOQGetFullI(&sdup->oqueue)); - if (n > 0) { + n = usbWritePacketI(sdup->config->usbp, sdup->config->data_request_ep, + sdup->oqueue.q_buffer, chOQGetFullI(&sdup->oqueue)); + if (n != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); } @@ -278,8 +278,8 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { single packet and the queue is emptied.*/ n = chOQGetFullI(&sdup->oqueue); if (n > 0) { - n = usbWriteI(usbp, ep, sdup->oqueue.q_buffer, n); - if (n > 0) { + n = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n); + if (n != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); @@ -302,8 +302,9 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { if (chIQIsEmptyI(&sdup->iqueue)) { size_t n; - n = usbReadI(usbp, ep, sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); - if (n > 0) { + n = usbReadPacketI(usbp, ep, sdup->iqueue.q_buffer, + SERIAL_USB_BUFFERS_SIZE); + if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; chSemSetCounterI(&sdup->iqueue.q_sem, n); chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); -- cgit v1.2.3 From bbc2b91e9c2b438c97a2412b862f58a914d72394 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 9 Feb 2011 20:51:32 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2726 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 29aec2650..430218edb 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -124,6 +124,7 @@ static void inotify(GenericQueue *qp) { if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; chSemSetCounterI(&sdup->iqueue.q_sem, n); + chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); } } } @@ -142,6 +143,7 @@ static void onotify(GenericQueue *qp) { if (n != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); + chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); } } -- cgit v1.2.3 From d749ecc10a40b21a22b3e7ab14ff9861fabe4685 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 12 Feb 2011 11:54:15 +0000 Subject: RAM optimization to the USB driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2732 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 430218edb..b17669c04 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -124,7 +124,7 @@ static void inotify(GenericQueue *qp) { if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; chSemSetCounterI(&sdup->iqueue.q_sem, n); - chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); +// chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); } } } @@ -143,7 +143,7 @@ static void onotify(GenericQueue *qp) { if (n != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); - chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); +// chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); } } -- cgit v1.2.3 From 95d128420a70587ce2845df383ed9b6a165e58dc Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 12 Feb 2011 18:59:34 +0000 Subject: Fixed a problem in the USB-CDC demo. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2733 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index b17669c04..430218edb 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -124,7 +124,7 @@ static void inotify(GenericQueue *qp) { if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; chSemSetCounterI(&sdup->iqueue.q_sem, n); -// chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); } } } @@ -143,7 +143,7 @@ static void onotify(GenericQueue *qp) { if (n != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); -// chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); + chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); } } -- cgit v1.2.3 From 2c15c4864f33c3c71c58e54494561eff1b291a0f Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 14 Feb 2011 19:37:40 +0000 Subject: More improvements in the USB driver model. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2738 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 430218edb..83f1c93ff 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -250,14 +250,14 @@ bool_t sduRequestsHook(USBDriver *usbp) { if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { switch (usbp->setup[1]) { case CDC_GET_LINE_CODING: - usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding)); + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); return TRUE; case CDC_SET_LINE_CODING: - usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding)); + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); return TRUE; case CDC_SET_CONTROL_LINE_STATE: /* Nothing to do, there are no control lines.*/ - usbSetupTransfer(usbp, NULL, 0); + usbSetupTransfer(usbp, NULL, 0, NULL); return TRUE; default: return FALSE; -- cgit v1.2.3 From eed6999aaf3a4579121b5e70d3a84ef620f896eb Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 1 Mar 2011 13:49:53 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2784 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 83f1c93ff..0393ad141 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -167,12 +167,6 @@ void sduInit(void) { * outside, usually in the hardware initialization code. * * @param[out] sdup pointer to a @p SerialUSBDriver structure - * @param[in] inotify pointer to a callback function that is invoked when - * some data is read from the Queue. The value can be - * @p NULL. - * @param[in] onotify pointer to a callback function that is invoked when - * some data is written in the Queue. The value can be - * @p NULL. * * @init */ @@ -244,6 +238,11 @@ void sduStop(SerialUSBDriver *sdup) { * - CDC_SET_LINE_CODING. * - CDC_SET_CONTROL_LINE_STATE. * . + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The hook status. + * @retval TRUE Message handled internally. + * @retval FALSE Message not handled. */ bool_t sduRequestsHook(USBDriver *usbp) { @@ -270,6 +269,9 @@ bool_t sduRequestsHook(USBDriver *usbp) { * @brief Default data transmitted callback. * @details The application must use this function as callback for the IN * data endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number */ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { SerialUSBDriver *sdup = usbp->param; @@ -294,6 +296,9 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { * @brief Default data received callback. * @details The application must use this function as callback for the OUT * data endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number */ void sduDataReceived(USBDriver *usbp, usbep_t ep) { SerialUSBDriver *sdup = usbp->param; @@ -319,6 +324,9 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { * @brief Default data received callback. * @details The application must use this function as callback for the IN * interrupt endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number */ void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep) { -- cgit v1.2.3 From ebaac50aa4daa939814b783b1239073e3170860f Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 8 Mar 2011 21:09:14 +0000 Subject: Improvements to the Serial over USB driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2810 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 0393ad141..6ed5d324c 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -119,7 +119,7 @@ static void inotify(GenericQueue *qp) { emptied, then a whole packet is loaded in the queue.*/ if (chIQIsEmptyI(&sdup->iqueue)) { - n = usbReadPacketI(sdup->config->usbp, sdup->config->data_available_ep, + n = usbReadPacketI(sdup->config->usbp, DATA_AVAILABLE_EP, sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; @@ -138,7 +138,7 @@ static void onotify(GenericQueue *qp) { /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ - n = usbWritePacketI(sdup->config->usbp, sdup->config->data_request_ep, + n = usbWritePacketI(sdup->config->usbp, DATA_REQUEST_EP, sdup->oqueue.q_buffer, chOQGetFullI(&sdup->oqueue)); if (n != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; -- cgit v1.2.3 From e7e79a6ccb4f3e320b2b8b7bad1b14d65218641d Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 18 Mar 2011 18:38:08 +0000 Subject: License updated. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2827 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 6ed5d324c..b6ad10c13 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -1,5 +1,6 @@ /* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011 Giovanni Di Sirio. This file is part of ChibiOS/RT. -- cgit v1.2.3 From de877486efb49378065f769ff423eef19ceb12e6 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 9 Apr 2011 15:10:15 +0000 Subject: Fixed bug 3276379. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2872 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index b6ad10c13..bc2c39426 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -59,44 +59,44 @@ static cdc_linecoding_t linecoding = { static size_t writes(void *ip, const uint8_t *bp, size_t n) { - return chOQWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, + return chOQWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, n, TIME_INFINITE); } static size_t reads(void *ip, uint8_t *bp, size_t n) { - return chIQReadTimeout(&((SerialDriver *)ip)->iqueue, bp, + return chIQReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, TIME_INFINITE); } static bool_t putwouldblock(void *ip) { - return chOQIsFullI(&((SerialDriver *)ip)->oqueue); + return chOQIsFullI(&((SerialUSBDriver *)ip)->oqueue); } static bool_t getwouldblock(void *ip) { - return chIQIsEmptyI(&((SerialDriver *)ip)->iqueue); + return chIQIsEmptyI(&((SerialUSBDriver *)ip)->iqueue); } static msg_t putt(void *ip, uint8_t b, systime_t timeout) { - return chOQPutTimeout(&((SerialDriver *)ip)->oqueue, b, timeout); + return chOQPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, timeout); } static msg_t gett(void *ip, systime_t timeout) { - return chIQGetTimeout(&((SerialDriver *)ip)->iqueue, timeout); + return chIQGetTimeout(&((SerialUSBDriver *)ip)->iqueue, timeout); } static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t time) { - return chOQWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, n, time); + return chOQWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, n, time); } static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { - return chIQReadTimeout(&((SerialDriver *)ip)->iqueue, bp, n, time); + return chIQReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, time); } static ioflags_t getflags(void *ip) { @@ -124,7 +124,7 @@ static void inotify(GenericQueue *qp) { sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - chSemSetCounterI(&sdup->iqueue.q_sem, n); + chSemAddCounterI(&sdup->iqueue.q_sem, n); chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); } } @@ -135,15 +135,16 @@ static void inotify(GenericQueue *qp) { */ static void onotify(GenericQueue *qp) { SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr; - size_t n; + size_t w, n; /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ - n = usbWritePacketI(sdup->config->usbp, DATA_REQUEST_EP, - sdup->oqueue.q_buffer, chOQGetFullI(&sdup->oqueue)); - if (n != USB_ENDPOINT_BUSY) { + n = chOQGetFullI(&sdup->oqueue); + w = usbWritePacketI(sdup->config->usbp, DATA_REQUEST_EP, + sdup->oqueue.q_buffer, n); + if (w != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); + chSemAddCounterI(&sdup->oqueue.q_sem, n); chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); } } @@ -276,17 +277,17 @@ bool_t sduRequestsHook(USBDriver *usbp) { */ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { SerialUSBDriver *sdup = usbp->param; - size_t n; + size_t n, w; chSysLockFromIsr(); /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ n = chOQGetFullI(&sdup->oqueue); if (n > 0) { - n = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n); - if (n != USB_ENDPOINT_BUSY) { + w = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n); + if (w != USB_ENDPOINT_BUSY) { sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - chSemSetCounterI(&sdup->oqueue.q_sem, SERIAL_USB_BUFFERS_SIZE); + chSemAddCounterI(&sdup->oqueue.q_sem, n); chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); } } @@ -314,7 +315,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { SERIAL_USB_BUFFERS_SIZE); if (n != USB_ENDPOINT_BUSY) { sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - chSemSetCounterI(&sdup->iqueue.q_sem, n); + chSemAddCounterI(&sdup->iqueue.q_sem, n); chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); } } -- cgit v1.2.3 From 3cfb4077fb27e9ab51bc33d67def962ae68f26c7 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 20 May 2011 07:29:52 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2982 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index bc2c39426..7fecd5f30 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -123,9 +123,12 @@ static void inotify(GenericQueue *qp) { n = usbReadPacketI(sdup->config->usbp, DATA_AVAILABLE_EP, sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); if (n != USB_ENDPOINT_BUSY) { - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - chSemAddCounterI(&sdup->iqueue.q_sem, n); chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; + sdup->iqueue.q_counter = n; + if (notempty(&sdup->iqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; + chSchRescheduleS(); } } } @@ -143,9 +146,12 @@ static void onotify(GenericQueue *qp) { w = usbWritePacketI(sdup->config->usbp, DATA_REQUEST_EP, sdup->oqueue.q_buffer, n); if (w != USB_ENDPOINT_BUSY) { - sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - chSemAddCounterI(&sdup->oqueue.q_sem, n); chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); + sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; + sdup->oqueue.q_counter = n; + if (notempty(&sdup->oqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; + chSchRescheduleS(); } } @@ -286,9 +292,11 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { if (n > 0) { w = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n); if (w != USB_ENDPOINT_BUSY) { - sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - chSemAddCounterI(&sdup->oqueue.q_sem, n); chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); + sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; + sdup->oqueue.q_counter = n; + if (notempty(&sdup->oqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; } } chSysUnlockFromIsr(); @@ -314,9 +322,11 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { n = usbReadPacketI(usbp, ep, sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); if (n != USB_ENDPOINT_BUSY) { - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - chSemAddCounterI(&sdup->iqueue.q_sem, n); chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; + sdup->iqueue.q_counter = n; + if (notempty(&sdup->iqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } } chSysUnlockFromIsr(); -- cgit v1.2.3 From f4ec81ae144ef2ae7ddd9a0e56082970420c0464 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 20 May 2011 12:46:24 +0000 Subject: USB CDC functionality restored, more improvements to the I/O queues. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2983 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 7fecd5f30..3f53d7df0 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -126,9 +126,8 @@ static void inotify(GenericQueue *qp) { chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; sdup->iqueue.q_counter = n; - if (notempty(&sdup->iqueue.q_waiting)) + while (notempty(&sdup->iqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; - chSchRescheduleS(); } } } @@ -148,10 +147,9 @@ static void onotify(GenericQueue *qp) { if (w != USB_ENDPOINT_BUSY) { chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - sdup->oqueue.q_counter = n; - if (notempty(&sdup->oqueue.q_waiting)) + sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); + while (notempty(&sdup->oqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; - chSchRescheduleS(); } } @@ -294,8 +292,8 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { if (w != USB_ENDPOINT_BUSY) { chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - sdup->oqueue.q_counter = n; - if (notempty(&sdup->oqueue.q_waiting)) + sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); + while (notempty(&sdup->oqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; } } @@ -325,7 +323,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; sdup->iqueue.q_counter = n; - if (notempty(&sdup->iqueue.q_waiting)) + while (notempty(&sdup->iqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } } -- cgit v1.2.3 From fe0093f795b6c88db8f12e2f7e45e11355fc3340 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 26 Aug 2011 13:47:22 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3254 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 3f53d7df0..d9c25ecdf 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -33,6 +33,10 @@ #if HAL_USE_SERIAL_USB || defined(__DOXYGEN__) +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ -- cgit v1.2.3 From 339cbbd60e7c45bb21758cdfe264e8e1c78d4fd5 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 28 Aug 2011 12:55:02 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3260 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index d9c25ecdf..237d8e027 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -124,7 +124,7 @@ static void inotify(GenericQueue *qp) { emptied, then a whole packet is loaded in the queue.*/ if (chIQIsEmptyI(&sdup->iqueue)) { - n = usbReadPacketI(sdup->config->usbp, DATA_AVAILABLE_EP, + n = usbReadPacketI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP, sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); if (n != USB_ENDPOINT_BUSY) { chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); @@ -146,7 +146,7 @@ static void onotify(GenericQueue *qp) { /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ n = chOQGetFullI(&sdup->oqueue); - w = usbWritePacketI(sdup->config->usbp, DATA_REQUEST_EP, + w = usbWritePacketI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP, sdup->oqueue.q_buffer, n); if (w != USB_ENDPOINT_BUSY) { chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); @@ -211,10 +211,10 @@ void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { "sduStart(), #1", "invalid state"); sdup->config = config; - usbStart(config->usbp, &config->usb_config); config->usbp->param = sdup; sdup->state = SDU_READY; chSysUnlock(); + usbStart(config->usbp, &config->usb_config); } /** -- cgit v1.2.3 From 76f8d18aaf60c6d916a799ba3d8b09815da979b2 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 28 Aug 2011 12:57:21 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3261 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 237d8e027..16822502a 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -234,9 +234,9 @@ void sduStop(SerialUSBDriver *sdup) { chDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), "sduStop(), #1", "invalid state"); - usbStop(sdup->config->usbp); sdup->state = SDU_STOP; chSysUnlock(); + usbStop(sdup->config->usbp); } /** -- cgit v1.2.3 From 309b1e411426e8d36d9a552ef2870da3db912a80 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 23 Oct 2011 11:39:45 +0000 Subject: Improvements to the USB driver, first phase. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3449 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 91 +++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 34 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 16822502a..ea434b197 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -118,21 +118,26 @@ static const struct SerialUSBDriverVMT vmt = { */ static void inotify(GenericQueue *qp) { SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr; - size_t n; /* Writes to the input queue can only happen when the queue has been emptied, then a whole packet is loaded in the queue.*/ - if (chIQIsEmptyI(&sdup->iqueue)) { - - n = usbReadPacketI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP, - sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); - if (n != USB_ENDPOINT_BUSY) { - chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - sdup->iqueue.q_counter = n; - while (notempty(&sdup->iqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; - } + if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) && + chIQIsEmptyI(&sdup->iqueue)) { + chSysUnlock(); + + /* Unlocked to make the potentially long read operation preemptable.*/ + size_t n = usbReadPacketBuffer(sdup->config->usbp, + USB_CDC_DATA_AVAILABLE_EP, + sdup->iqueue.q_buffer, + SERIAL_USB_BUFFERS_SIZE); + + chSysLock(); + usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP); + chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; + sdup->iqueue.q_counter = n; + while (notempty(&sdup->iqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } } @@ -141,14 +146,20 @@ static void inotify(GenericQueue *qp) { */ static void onotify(GenericQueue *qp) { SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr; - size_t w, n; + size_t n; /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ n = chOQGetFullI(&sdup->oqueue); - w = usbWritePacketI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP, - sdup->oqueue.q_buffer, n); - if (w != USB_ENDPOINT_BUSY) { + if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP)) { + chSysUnlock(); + + /* Unlocked to make the potentially long write operation preemptable.*/ + usbWritePacketBuffer(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP, + sdup->oqueue.q_buffer, n); + + chSysLock(); + usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP); chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); @@ -285,21 +296,27 @@ bool_t sduRequestsHook(USBDriver *usbp) { */ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { SerialUSBDriver *sdup = usbp->param; - size_t n, w; + size_t n; chSysLockFromIsr(); /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ n = chOQGetFullI(&sdup->oqueue); if (n > 0) { - w = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n); - if (w != USB_ENDPOINT_BUSY) { - chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); - sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); - while (notempty(&sdup->oqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; - } + /* The endpoint cannot be busy, we are in the context of the callback, + so it is safe to transmit without a check.*/ + chSysUnlockFromIsr(); + + /* Unlocked to make the potentially long write operation preemptable.*/ + usbWritePacketBuffer(usbp, ep, sdup->oqueue.q_buffer, n); + + chSysLockFromIsr(); + usbStartTransmitI(usbp, ep); + chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); + sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; + sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); + while (notempty(&sdup->oqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; } chSysUnlockFromIsr(); } @@ -319,17 +336,23 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { /* Writes to the input queue can only happen when the queue has been emptied, then a whole packet is loaded in the queue.*/ if (chIQIsEmptyI(&sdup->iqueue)) { + /* The endpoint cannot be busy, we are in the context of the callback, + so a packet is in the buffer for sure.*/ size_t n; - n = usbReadPacketI(usbp, ep, sdup->iqueue.q_buffer, - SERIAL_USB_BUFFERS_SIZE); - if (n != USB_ENDPOINT_BUSY) { - chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - sdup->iqueue.q_counter = n; - while (notempty(&sdup->iqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; - } + chSysUnlockFromIsr(); + + /* Unlocked to make the potentially long write operation preemptable.*/ + n = usbReadPacketBuffer(usbp, ep, sdup->iqueue.q_buffer, + SERIAL_USB_BUFFERS_SIZE); + + chSysLockFromIsr(); + usbStartReceiveI(usbp, ep); + chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; + sdup->iqueue.q_counter = n; + while (notempty(&sdup->iqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } chSysUnlockFromIsr(); } -- cgit v1.2.3 From de5dcbba856524599a8f06d3a9bdbf1b01db44c2 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 21 Jan 2012 14:29:42 +0000 Subject: License text updated with new year. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3846 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index ea434b197..f007e7bdd 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -1,6 +1,6 @@ /* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011 Giovanni Di Sirio. + 2011,2012 Giovanni Di Sirio. This file is part of ChibiOS/RT. -- cgit v1.2.3 From d0a2e55ed0cf97be924ebbdae2497fd77bfac5b6 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 8 May 2012 17:09:20 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4175 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index f007e7bdd..52c57c800 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -103,7 +103,7 @@ static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { return chIQReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, time); } -static ioflags_t getflags(void *ip) { +static chnflags_t getflags(void *ip) { _ch_get_and_clear_flags_impl(ip); } @@ -133,7 +133,7 @@ static void inotify(GenericQueue *qp) { chSysLock(); usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP); - chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; sdup->iqueue.q_counter = n; while (notempty(&sdup->iqueue.q_waiting)) @@ -160,7 +160,7 @@ static void onotify(GenericQueue *qp) { chSysLock(); usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP); - chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); + chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); while (notempty(&sdup->oqueue.q_waiting)) @@ -195,7 +195,7 @@ void sduObjectInit(SerialUSBDriver *sdup) { sdup->vmt = &vmt; chEvtInit(&sdup->event); - sdup->flags = IO_NO_ERROR; + sdup->flags = CHN_NO_ERROR; sdup->state = SDU_STOP; chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify); chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify); @@ -312,7 +312,7 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { chSysLockFromIsr(); usbStartTransmitI(usbp, ep); - chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); + chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); while (notempty(&sdup->oqueue.q_waiting)) @@ -348,7 +348,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { chSysLockFromIsr(); usbStartReceiveI(usbp, ep); - chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; sdup->iqueue.q_counter = n; while (notempty(&sdup->iqueue.q_waiting)) -- cgit v1.2.3 From ac2e9f7ffc14db090a75086a9a0469b0a90fdb90 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 29 May 2012 16:36:10 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4246 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 52c57c800..2c7a37b4d 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -104,7 +104,7 @@ static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { } static chnflags_t getflags(void *ip) { - _ch_get_and_clear_flags_impl(ip); + _chn_get_and_clear_flags_impl(ip); } static const struct SerialUSBDriverVMT vmt = { -- cgit v1.2.3 From c762926b68f6a6c7f1e71b8acf9b1dd29d6e481f Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 10 Jun 2012 16:31:03 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4265 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 2c7a37b4d..7f1658812 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -119,6 +119,7 @@ static const struct SerialUSBDriverVMT vmt = { static void inotify(GenericQueue *qp) { SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr; +#if 0 /* Writes to the input queue can only happen when the queue has been emptied, then a whole packet is loaded in the queue.*/ if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) && @@ -139,6 +140,7 @@ static void inotify(GenericQueue *qp) { while (notempty(&sdup->iqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } +#endif } /** @@ -148,6 +150,7 @@ static void onotify(GenericQueue *qp) { SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr; size_t n; +#if 0 /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ n = chOQGetFullI(&sdup->oqueue); @@ -166,6 +169,7 @@ static void onotify(GenericQueue *qp) { while (notempty(&sdup->oqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; } +#endif } /*===========================================================================*/ @@ -298,6 +302,7 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { SerialUSBDriver *sdup = usbp->param; size_t n; +#if 0 chSysLockFromIsr(); /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ @@ -319,6 +324,7 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; } chSysUnlockFromIsr(); +#endif } /** @@ -332,6 +338,7 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { void sduDataReceived(USBDriver *usbp, usbep_t ep) { SerialUSBDriver *sdup = usbp->param; +#if 0 chSysLockFromIsr(); /* Writes to the input queue can only happen when the queue has been emptied, then a whole packet is loaded in the queue.*/ @@ -355,6 +362,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } chSysUnlockFromIsr(); +#endif } /** -- cgit v1.2.3 From d094e348c5d1a3785289c69c5185bbaca1257de8 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 11 Jun 2012 16:54:35 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4266 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 115 ++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 68 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 7f1658812..5fec52a68 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -117,59 +117,47 @@ static const struct SerialUSBDriverVMT vmt = { * @brief Notification of data removed from the input queue. */ static void inotify(GenericQueue *qp) { - SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr; + size_t n, maxsize; + SerialUSBDriver *sdup = chQGetLink(qp); -#if 0 - /* Writes to the input queue can only happen when the queue has been - emptied, then a whole packet is loaded in the queue.*/ + /* If there is in the queue enough space to hold at least one packet and + a transaction is not yet started then a new transaction is started for + the available space.*/ + maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize; if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) && - chIQIsEmptyI(&sdup->iqueue)) { + ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize)) { chSysUnlock(); - /* Unlocked to make the potentially long read operation preemptable.*/ - size_t n = usbReadPacketBuffer(sdup->config->usbp, - USB_CDC_DATA_AVAILABLE_EP, - sdup->iqueue.q_buffer, - SERIAL_USB_BUFFERS_SIZE); + n = (n / maxsize) * maxsize; + usbPrepareQueuedReceive(sdup->config->usbp, + USB_CDC_DATA_AVAILABLE_EP, + &sdup->iqueue, n); chSysLock(); usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP); - chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - sdup->iqueue.q_counter = n; - while (notempty(&sdup->iqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } -#endif } /** * @brief Notification of data inserted into the output queue. */ static void onotify(GenericQueue *qp) { - SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr; size_t n; + SerialUSBDriver *sdup = chQGetLink(qp); -#if 0 - /* If there is any data in the output queue then it is sent within a - single packet and the queue is emptied.*/ - n = chOQGetFullI(&sdup->oqueue); - if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP)) { + /* If there is not an ongoing transaction and the output queue contains + data then a new transaction is started.*/ + if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) && + ((n = chOQGetFullI(&sdup->oqueue)) > 0)) { chSysUnlock(); - /* Unlocked to make the potentially long write operation preemptable.*/ - usbWritePacketBuffer(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP, - sdup->oqueue.q_buffer, n); + usbPrepareQueuedTransmit(sdup->config->usbp, + USB_CDC_DATA_REQUEST_EP, + &sdup->oqueue, n); chSysLock(); usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP); - chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); - sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); - while (notempty(&sdup->oqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; } -#endif } /*===========================================================================*/ @@ -201,12 +189,8 @@ void sduObjectInit(SerialUSBDriver *sdup) { chEvtInit(&sdup->event); sdup->flags = CHN_NO_ERROR; sdup->state = SDU_STOP; - chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify); - chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify); - /* This is a dirty trick but those pointers are never used because queues - are accessed in block mode from the low level.*/ - sdup->iqueue.q_wrptr = (uint8_t *)sdup; - sdup->oqueue.q_rdptr = (uint8_t *)sdup; + chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify, sdup); + chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify, sdup); } /** @@ -299,32 +283,28 @@ bool_t sduRequestsHook(USBDriver *usbp) { * @param[in] ep endpoint number */ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { - SerialUSBDriver *sdup = usbp->param; size_t n; + SerialUSBDriver *sdup = usbp->param; + + (void)ep; -#if 0 + chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); chSysLockFromIsr(); - /* If there is any data in the output queue then it is sent within a - single packet and the queue is emptied.*/ - n = chOQGetFullI(&sdup->oqueue); - if (n > 0) { + + if ((n = chOQGetFullI(&sdup->oqueue)) > 0) { /* The endpoint cannot be busy, we are in the context of the callback, so it is safe to transmit without a check.*/ chSysUnlockFromIsr(); - /* Unlocked to make the potentially long write operation preemptable.*/ - usbWritePacketBuffer(usbp, ep, sdup->oqueue.q_buffer, n); + usbPrepareQueuedTransmit(sdup->config->usbp, + USB_CDC_DATA_REQUEST_EP, + &sdup->oqueue, n); chSysLockFromIsr(); - usbStartTransmitI(usbp, ep); - chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); - sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); - while (notempty(&sdup->oqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; + usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP); } + chSysUnlockFromIsr(); -#endif } /** @@ -336,33 +316,32 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { * @param[in] ep endpoint number */ void sduDataReceived(USBDriver *usbp, usbep_t ep) { + size_t n, maxsize; SerialUSBDriver *sdup = usbp->param; -#if 0 + (void)ep; + + chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); chSysLockFromIsr(); - /* Writes to the input queue can only happen when the queue has been - emptied, then a whole packet is loaded in the queue.*/ - if (chIQIsEmptyI(&sdup->iqueue)) { + + /* Writes to the input queue can only happen when there is enough space + to hold at least one packet.*/ + maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize; + if ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize) { /* The endpoint cannot be busy, we are in the context of the callback, so a packet is in the buffer for sure.*/ - size_t n; - chSysUnlockFromIsr(); - /* Unlocked to make the potentially long write operation preemptable.*/ - n = usbReadPacketBuffer(usbp, ep, sdup->iqueue.q_buffer, - SERIAL_USB_BUFFERS_SIZE); + n = (n / maxsize) * maxsize; + usbPrepareQueuedReceive(sdup->config->usbp, + USB_CDC_DATA_AVAILABLE_EP, + &sdup->iqueue, n); chSysLockFromIsr(); - usbStartReceiveI(usbp, ep); - chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - sdup->iqueue.q_counter = n; - while (notempty(&sdup->iqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; + usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP); } + chSysUnlockFromIsr(); -#endif } /** -- cgit v1.2.3 From 41eb1a7e7ec33ee7abd62fa954be6b995d6e9707 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 11 Jun 2012 19:43:14 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4271 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 5fec52a68..52be6e975 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -288,8 +288,8 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { (void)ep; - chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); chSysLockFromIsr(); + chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); if ((n = chOQGetFullI(&sdup->oqueue)) > 0) { /* The endpoint cannot be busy, we are in the context of the callback, @@ -321,8 +321,8 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { (void)ep; - chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); chSysLockFromIsr(); + chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); /* Writes to the input queue can only happen when there is enough space to hold at least one packet.*/ -- cgit v1.2.3 From f620f29e0a803ed942134ac8a801d5204cebe034 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 13 Jun 2012 16:13:00 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4273 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 52be6e975..2b02ae02f 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -120,6 +120,11 @@ static void inotify(GenericQueue *qp) { size_t n, maxsize; SerialUSBDriver *sdup = chQGetLink(qp); + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if (usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) + return; + /* If there is in the queue enough space to hold at least one packet and a transaction is not yet started then a new transaction is started for the available space.*/ @@ -145,6 +150,11 @@ static void onotify(GenericQueue *qp) { size_t n; SerialUSBDriver *sdup = chQGetLink(qp); + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if (usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) + return; + /* If there is not an ongoing transaction and the output queue contains data then a new transaction is started.*/ if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) && @@ -238,6 +248,22 @@ void sduStop(SerialUSBDriver *sdup) { usbStop(sdup->config->usbp); } +/** + * @brief USB device configured handler. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @iclass + */ +void sduConfigureHookI(USBDriver *usbp) { + SerialUSBDriver *sdup = usbp->param; + + sdup->flags = CHN_NO_ERROR; + chIQResetI(&sdup->iqueue); + chOQResetI(&sdup->oqueue); + chnAddFlagsI(sdup, CHN_CONNECTED); +} + /** * @brief Default requests hook. * @details Applications wanting to use the Serial over USB driver can use -- cgit v1.2.3 From 9057c6c72be213bb7f07929e2ddd1ab1e942a1de Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 18 Jun 2012 16:22:34 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4294 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 2b02ae02f..466b65b0a 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -73,14 +73,14 @@ static size_t reads(void *ip, uint8_t *bp, size_t n) { n, TIME_INFINITE); } -static bool_t putwouldblock(void *ip) { +static msg_t put(void *ip, uint8_t b) { - return chOQIsFullI(&((SerialUSBDriver *)ip)->oqueue); + return chOQPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, TIME_INFINITE); } -static bool_t getwouldblock(void *ip) { +static msg_t get(void *ip) { - return chIQIsEmptyI(&((SerialUSBDriver *)ip)->iqueue); + return chIQGetTimeout(&((SerialUSBDriver *)ip)->iqueue, TIME_INFINITE); } static msg_t putt(void *ip, uint8_t b, systime_t timeout) { @@ -108,7 +108,7 @@ static chnflags_t getflags(void *ip) { } static const struct SerialUSBDriverVMT vmt = { - writes, reads, putwouldblock, getwouldblock, + writes, reads, put, get, putt, gett, writet, readt, getflags }; -- cgit v1.2.3 From 6af0806da3d9df7ea9f6410a74ad8c864926bd7f Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 20 Jun 2012 08:39:04 +0000 Subject: Fixed bugs 3536522 and 3536523. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4309 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 466b65b0a..c3e9ae184 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -61,13 +61,13 @@ static cdc_linecoding_t linecoding = { * Interface implementation. */ -static size_t writes(void *ip, const uint8_t *bp, size_t n) { +static size_t write(void *ip, const uint8_t *bp, size_t n) { return chOQWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, n, TIME_INFINITE); } -static size_t reads(void *ip, uint8_t *bp, size_t n) { +static size_t read(void *ip, uint8_t *bp, size_t n) { return chIQReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, TIME_INFINITE); @@ -108,7 +108,7 @@ static chnflags_t getflags(void *ip) { } static const struct SerialUSBDriverVMT vmt = { - writes, reads, put, get, + write, read, put, get, putt, gett, writet, readt, getflags }; -- cgit v1.2.3 From ec9736a27d1572f1a8357cae3dd56470f00af974 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 2 Jul 2012 18:47:09 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4388 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index c3e9ae184..fc082b56b 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -322,12 +322,12 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { so it is safe to transmit without a check.*/ chSysUnlockFromIsr(); - usbPrepareQueuedTransmit(sdup->config->usbp, + usbPrepareQueuedTransmit(usbp, USB_CDC_DATA_REQUEST_EP, &sdup->oqueue, n); chSysLockFromIsr(); - usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP); + usbStartTransmitI(usbp, USB_CDC_DATA_REQUEST_EP); } chSysUnlockFromIsr(); @@ -352,19 +352,19 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { /* Writes to the input queue can only happen when there is enough space to hold at least one packet.*/ - maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize; + maxsize = usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize; if ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize) { /* The endpoint cannot be busy, we are in the context of the callback, so a packet is in the buffer for sure.*/ chSysUnlockFromIsr(); n = (n / maxsize) * maxsize; - usbPrepareQueuedReceive(sdup->config->usbp, + usbPrepareQueuedReceive(usbp, USB_CDC_DATA_AVAILABLE_EP, &sdup->iqueue, n); chSysLockFromIsr(); - usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP); + usbStartReceiveI(usbp, USB_CDC_DATA_AVAILABLE_EP); } chSysUnlockFromIsr(); -- cgit v1.2.3 From e372aabda9da9309671e058839d668ec38c7e8c1 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 17 Aug 2012 12:40:48 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4575 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index fc082b56b..f05c341fc 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -223,7 +223,6 @@ void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { config->usbp->param = sdup; sdup->state = SDU_READY; chSysUnlock(); - usbStart(config->usbp, &config->usb_config); } /** @@ -245,7 +244,6 @@ void sduStop(SerialUSBDriver *sdup) { "invalid state"); sdup->state = SDU_STOP; chSysUnlock(); - usbStop(sdup->config->usbp); } /** @@ -322,12 +320,23 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { so it is safe to transmit without a check.*/ chSysUnlockFromIsr(); - usbPrepareQueuedTransmit(usbp, - USB_CDC_DATA_REQUEST_EP, - &sdup->oqueue, n); + usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, n); + + chSysLockFromIsr(); + usbStartTransmitI(usbp, ep); + } + else if (!(usbp->epc[ep]->in_state->txsize & + (usbp->epc[ep]->in_maxsize - 1))) { + /* Transmit zero sized packet in case the last one has maximum allowed + size. Otherwise the recipient may expect more data coming soon and + not return buffered data to app. See section 5.8.3 Bulk Transfer + Packet Size Constraints of the USB Specification document.*/ + chSysUnlockFromIsr(); + + usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, 0); chSysLockFromIsr(); - usbStartTransmitI(usbp, USB_CDC_DATA_REQUEST_EP); + usbStartTransmitI(usbp, ep); } chSysUnlockFromIsr(); -- cgit v1.2.3 From aedb7fddf11a5c5fad8b1a7a15d22534f145c763 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 17 Aug 2012 12:43:40 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4576 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index f05c341fc..9b36be413 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -368,12 +368,10 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { chSysUnlockFromIsr(); n = (n / maxsize) * maxsize; - usbPrepareQueuedReceive(usbp, - USB_CDC_DATA_AVAILABLE_EP, - &sdup->iqueue, n); + usbPrepareQueuedReceive(usbp, ep, &sdup->iqueue, n); chSysLockFromIsr(); - usbStartReceiveI(usbp, USB_CDC_DATA_AVAILABLE_EP); + usbStartReceiveI(usbp, ep); } chSysUnlockFromIsr(); -- cgit v1.2.3 From 954a365b01c1c755752e61f600408fe72759f47c Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 15 Sep 2012 18:14:43 +0000 Subject: Fixed bug 3567992. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4665 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 9b36be413..9cef45524 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -260,6 +260,11 @@ void sduConfigureHookI(USBDriver *usbp) { chIQResetI(&sdup->iqueue); chOQResetI(&sdup->oqueue); chnAddFlagsI(sdup, CHN_CONNECTED); + + /* Starts the first OUT transaction immediately.*/ + usbPrepareQueuedReceive(usbp, USB_CDC_DATA_AVAILABLE_EP, &sdup->iqueue, + usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize); + usbStartReceiveI(usbp, USB_CDC_DATA_AVAILABLE_EP); } /** -- cgit v1.2.3 From f90a0f37906a9363a6e702d8ac1c4c8257370efa Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 16 Sep 2012 09:08:43 +0000 Subject: Removed flags handling in BaseAsynchronousChannel. Modified serial drivers to use the new event flags. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4671 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 9cef45524..05cb60c3f 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -103,14 +103,9 @@ static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { return chIQReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, time); } -static chnflags_t getflags(void *ip) { - _chn_get_and_clear_flags_impl(ip); -} - static const struct SerialUSBDriverVMT vmt = { write, read, put, get, - putt, gett, writet, readt, - getflags + putt, gett, writet, readt }; /** @@ -197,7 +192,6 @@ void sduObjectInit(SerialUSBDriver *sdup) { sdup->vmt = &vmt; chEvtInit(&sdup->event); - sdup->flags = CHN_NO_ERROR; sdup->state = SDU_STOP; chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify, sdup); chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify, sdup); @@ -256,7 +250,6 @@ void sduStop(SerialUSBDriver *sdup) { void sduConfigureHookI(USBDriver *usbp) { SerialUSBDriver *sdup = usbp->param; - sdup->flags = CHN_NO_ERROR; chIQResetI(&sdup->iqueue); chOQResetI(&sdup->oqueue); chnAddFlagsI(sdup, CHN_CONNECTED); -- cgit v1.2.3 From 184a71345c6a36a9a8664eda8fbcc3ea728267a8 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 2 Feb 2013 10:58:09 +0000 Subject: Updated license years. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5102 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 05cb60c3f..23a323356 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -1,6 +1,6 @@ /* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012 Giovanni Di Sirio. + 2011,2012,2013 Giovanni Di Sirio. This file is part of ChibiOS/RT. -- cgit v1.2.3 From c41614ea66196b2e05b57a24064be449aa8a8830 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 24 Feb 2013 07:08:44 +0000 Subject: Fixed bug 3605793. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5304 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 23a323356..000d13951 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -323,8 +323,9 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { chSysLockFromIsr(); usbStartTransmitI(usbp, ep); } - else if (!(usbp->epc[ep]->in_state->txsize & - (usbp->epc[ep]->in_maxsize - 1))) { + else if ((usbp->epc[ep]->in_state->txsize > 0) && + !(usbp->epc[ep]->in_state->txsize & + (usbp->epc[ep]->in_maxsize - 1))) { /* Transmit zero sized packet in case the last one has maximum allowed size. Otherwise the recipient may expect more data coming soon and not return buffered data to app. See section 5.8.3 Bulk Transfer -- cgit v1.2.3 From 01f971ba1d63d8568789adf51cde22fb35f69e73 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 28 Feb 2013 16:23:19 +0000 Subject: Adjusted C file templates. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5339 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 000d13951..7b7d255ed 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -42,7 +42,7 @@ /*===========================================================================*/ /*===========================================================================*/ -/* Driver local variables. */ +/* Driver local variables and types. */ /*===========================================================================*/ /* -- cgit v1.2.3 From 53ebb098cb632593656bba3a28730ca2bb3de1ce Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 28 Apr 2013 13:12:20 +0000 Subject: Updated serial_usb driver and demos. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5637 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 7b7d255ed..37b1d3fe6 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -29,8 +29,6 @@ #include "ch.h" #include "hal.h" -#include "usb_cdc.h" - #if HAL_USE_SERIAL_USB || defined(__DOXYGEN__) /*===========================================================================*/ @@ -117,24 +115,25 @@ static void inotify(GenericQueue *qp) { /* If the USB driver is not in the appropriate state then transactions must not be started.*/ - if (usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) + if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || + (sdup->state != SDU_READY)) return; /* If there is in the queue enough space to hold at least one packet and a transaction is not yet started then a new transaction is started for the available space.*/ - maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize; - if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) && + maxsize = sdup->config->usbp->epc[sdup->config->bulk_out]->out_maxsize; + if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out) && ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize)) { chSysUnlock(); n = (n / maxsize) * maxsize; usbPrepareQueuedReceive(sdup->config->usbp, - USB_CDC_DATA_AVAILABLE_EP, + sdup->config->bulk_out, &sdup->iqueue, n); chSysLock(); - usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP); + usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out); } } @@ -147,21 +146,22 @@ static void onotify(GenericQueue *qp) { /* If the USB driver is not in the appropriate state then transactions must not be started.*/ - if (usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) + if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || + (sdup->state != SDU_READY)) return; /* If there is not an ongoing transaction and the output queue contains data then a new transaction is started.*/ - if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) && + if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in) && ((n = chOQGetFullI(&sdup->oqueue)) > 0)) { chSysUnlock(); usbPrepareQueuedTransmit(sdup->config->usbp, - USB_CDC_DATA_REQUEST_EP, + sdup->config->bulk_in, &sdup->oqueue, n); chSysLock(); - usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP); + usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in); } } @@ -236,6 +236,12 @@ void sduStop(SerialUSBDriver *sdup) { chDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), "sduStop(), #1", "invalid state"); + + chIQResetI(&sdup->iqueue); + chOQResetI(&sdup->oqueue); + chSchRescheduleS(); + chnAddFlagsI(sdup, CHN_DISCONNECTED); + sdup->state = SDU_STOP; chSysUnlock(); } @@ -255,9 +261,9 @@ void sduConfigureHookI(USBDriver *usbp) { chnAddFlagsI(sdup, CHN_CONNECTED); /* Starts the first OUT transaction immediately.*/ - usbPrepareQueuedReceive(usbp, USB_CDC_DATA_AVAILABLE_EP, &sdup->iqueue, - usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize); - usbStartReceiveI(usbp, USB_CDC_DATA_AVAILABLE_EP); + usbPrepareQueuedReceive(usbp, sdup->config->bulk_out, &sdup->iqueue, + usbp->epc[sdup->config->bulk_out]->out_maxsize); + usbStartReceiveI(usbp, sdup->config->bulk_out); } /** @@ -308,7 +314,8 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { size_t n; SerialUSBDriver *sdup = usbp->param; - (void)ep; + if (sdup->state != SDU_READY) + return; chSysLockFromIsr(); chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); @@ -353,14 +360,15 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { size_t n, maxsize; SerialUSBDriver *sdup = usbp->param; - (void)ep; + if (sdup->state != SDU_READY) + return; chSysLockFromIsr(); chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); /* Writes to the input queue can only happen when there is enough space to hold at least one packet.*/ - maxsize = usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize; + maxsize = usbp->epc[ep]->out_maxsize; if ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize) { /* The endpoint cannot be busy, we are in the context of the callback, so a packet is in the buffer for sure.*/ -- cgit v1.2.3 From 11ecb1a7586ddaf6276a087d51de829b00d5f386 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 1 May 2013 15:50:35 +0000 Subject: Fixed problem with multiple SerialUSB instances. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5651 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'os/hal/src/serial_usb.c') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 37b1d3fe6..ff6e94b07 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -206,6 +206,7 @@ void sduObjectInit(SerialUSBDriver *sdup) { * @api */ void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { + USBDriver *usbp = config->usbp; chDbgCheck(sdup != NULL, "sduStart"); @@ -213,8 +214,10 @@ void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { chDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), "sduStart(), #1", "invalid state"); + usbp->in_params[config->bulk_in - 1] = sdup; + usbp->out_params[config->bulk_out - 1] = sdup; + usbp->in_params[config->int_in - 1] = sdup; sdup->config = config; - config->usbp->param = sdup; sdup->state = SDU_READY; chSysUnlock(); } @@ -229,32 +232,40 @@ void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { * @api */ void sduStop(SerialUSBDriver *sdup) { + USBDriver *usbp = sdup->config->usbp; chDbgCheck(sdup != NULL, "sdStop"); chSysLock(); + chDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), "sduStop(), #1", "invalid state"); + /* Driver in stopped state.*/ + usbp->in_params[sdup->config->bulk_in - 1] = NULL; + usbp->out_params[sdup->config->bulk_out - 1] = NULL; + usbp->in_params[sdup->config->int_in - 1] = NULL; + sdup->state = SDU_STOP; + + /* Queues reset in order to signal the driver stop to the application.*/ + chnAddFlagsI(sdup, CHN_DISCONNECTED); chIQResetI(&sdup->iqueue); chOQResetI(&sdup->oqueue); chSchRescheduleS(); - chnAddFlagsI(sdup, CHN_DISCONNECTED); - sdup->state = SDU_STOP; chSysUnlock(); } /** * @brief USB device configured handler. * - * @param[in] usbp pointer to the @p USBDriver object + * @param[in] sdup pointer to a @p SerialUSBDriver object * * @iclass */ -void sduConfigureHookI(USBDriver *usbp) { - SerialUSBDriver *sdup = usbp->param; +void sduConfigureHookI(SerialUSBDriver *sdup) { + USBDriver *usbp = sdup->config->usbp; chIQResetI(&sdup->iqueue); chOQResetI(&sdup->oqueue); @@ -312,9 +323,9 @@ bool_t sduRequestsHook(USBDriver *usbp) { */ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { size_t n; - SerialUSBDriver *sdup = usbp->param; + SerialUSBDriver *sdup = usbp->in_params[ep - 1]; - if (sdup->state != SDU_READY) + if (sdup == NULL) return; chSysLockFromIsr(); @@ -358,9 +369,9 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { */ void sduDataReceived(USBDriver *usbp, usbep_t ep) { size_t n, maxsize; - SerialUSBDriver *sdup = usbp->param; + SerialUSBDriver *sdup = usbp->out_params[ep - 1]; - if (sdup->state != SDU_READY) + if (sdup == NULL) return; chSysLockFromIsr(); -- cgit v1.2.3