diff options
Diffstat (limited to 'tmk_core/protocol/chibios/usb_driver.c')
-rw-r--r-- | tmk_core/protocol/chibios/usb_driver.c | 435 |
1 files changed, 191 insertions, 244 deletions
diff --git a/tmk_core/protocol/chibios/usb_driver.c b/tmk_core/protocol/chibios/usb_driver.c index fe535eeb3..28a8c6663 100644 --- a/tmk_core/protocol/chibios/usb_driver.c +++ b/tmk_core/protocol/chibios/usb_driver.c @@ -41,93 +41,62 @@ /* * Current Line Coding. */ -static cdc_linecoding_t linecoding = { - {0x00, 0x96, 0x00, 0x00}, /* 38400. */ - LC_STOP_1, LC_PARITY_NONE, 8 -}; +static cdc_linecoding_t linecoding = {{0x00, 0x96, 0x00, 0x00}, /* 38400. */ + LC_STOP_1, + LC_PARITY_NONE, + 8}; /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ static bool qmkusb_start_receive(QMKUSBDriver *qmkusbp) { - uint8_t *buf; - - /* If the USB driver is not in the appropriate state then transactions - must not be started.*/ - if ((usbGetDriverStateI(qmkusbp->config->usbp) != USB_ACTIVE) || - (qmkusbp->state != QMKUSB_READY)) { - return true; - } - - /* Checking if there is already a transaction ongoing on the endpoint.*/ - if (usbGetReceiveStatusI(qmkusbp->config->usbp, qmkusbp->config->bulk_in)) { - return true; - } - - /* Checking if there is a buffer ready for incoming data.*/ - buf = ibqGetEmptyBufferI(&qmkusbp->ibqueue); - if (buf == NULL) { - return true; - } - - /* Buffer found, starting a new transaction.*/ - usbStartReceiveI(qmkusbp->config->usbp, qmkusbp->config->bulk_out, - buf, qmkusbp->ibqueue.bsize - sizeof(size_t)); - - return false; -} - -/* - * Interface implementation. - */ - -static size_t _write(void *ip, const uint8_t *bp, size_t n) { + uint8_t *buf; - return obqWriteTimeout(&((QMKUSBDriver *)ip)->obqueue, bp, - n, TIME_INFINITE); -} + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if ((usbGetDriverStateI(qmkusbp->config->usbp) != USB_ACTIVE) || (qmkusbp->state != QMKUSB_READY)) { + return true; + } -static size_t _read(void *ip, uint8_t *bp, size_t n) { + /* Checking if there is already a transaction ongoing on the endpoint.*/ + if (usbGetReceiveStatusI(qmkusbp->config->usbp, qmkusbp->config->bulk_in)) { + return true; + } - return ibqReadTimeout(&((QMKUSBDriver *)ip)->ibqueue, bp, - n, TIME_INFINITE); -} + /* Checking if there is a buffer ready for incoming data.*/ + buf = ibqGetEmptyBufferI(&qmkusbp->ibqueue); + if (buf == NULL) { + return true; + } -static msg_t _put(void *ip, uint8_t b) { + /* Buffer found, starting a new transaction.*/ + usbStartReceiveI(qmkusbp->config->usbp, qmkusbp->config->bulk_out, buf, qmkusbp->ibqueue.bsize - sizeof(size_t)); - return obqPutTimeout(&((QMKUSBDriver *)ip)->obqueue, b, TIME_INFINITE); + return false; } -static msg_t _get(void *ip) { - - return ibqGetTimeout(&((QMKUSBDriver *)ip)->ibqueue, TIME_INFINITE); -} +/* + * Interface implementation. + */ -static msg_t _putt(void *ip, uint8_t b, systime_t timeout) { +static size_t _write(void *ip, const uint8_t *bp, size_t n) { return obqWriteTimeout(&((QMKUSBDriver *)ip)->obqueue, bp, n, TIME_INFINITE); } - return obqPutTimeout(&((QMKUSBDriver *)ip)->obqueue, b, timeout); -} +static size_t _read(void *ip, uint8_t *bp, size_t n) { return ibqReadTimeout(&((QMKUSBDriver *)ip)->ibqueue, bp, n, TIME_INFINITE); } -static msg_t _gett(void *ip, systime_t timeout) { +static msg_t _put(void *ip, uint8_t b) { return obqPutTimeout(&((QMKUSBDriver *)ip)->obqueue, b, TIME_INFINITE); } - return ibqGetTimeout(&((QMKUSBDriver *)ip)->ibqueue, timeout); -} +static msg_t _get(void *ip) { return ibqGetTimeout(&((QMKUSBDriver *)ip)->ibqueue, TIME_INFINITE); } -static size_t _writet(void *ip, const uint8_t *bp, size_t n, systime_t timeout) { +static msg_t _putt(void *ip, uint8_t b, systime_t timeout) { return obqPutTimeout(&((QMKUSBDriver *)ip)->obqueue, b, timeout); } - return obqWriteTimeout(&((QMKUSBDriver *)ip)->obqueue, bp, n, timeout); -} +static msg_t _gett(void *ip, systime_t timeout) { return ibqGetTimeout(&((QMKUSBDriver *)ip)->ibqueue, timeout); } -static size_t _readt(void *ip, 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) { return obqWriteTimeout(&((QMKUSBDriver *)ip)->obqueue, bp, n, timeout); } - return ibqReadTimeout(&((QMKUSBDriver *)ip)->ibqueue, bp, n, timeout); -} +static size_t _readt(void *ip, uint8_t *bp, size_t n, systime_t timeout) { return ibqReadTimeout(&((QMKUSBDriver *)ip)->ibqueue, bp, n, timeout); } -static const struct QMKUSBDriverVMT vmt = { - _write, _read, _put, _get, - _putt, _gett, _writet, _readt -}; +static const struct QMKUSBDriverVMT vmt = {_write, _read, _put, _get, _putt, _gett, _writet, _readt}; /** * @brief Notification of empty buffer released into the input buffers queue. @@ -135,8 +104,8 @@ static const struct QMKUSBDriverVMT vmt = { * @param[in] bqp the buffers queue pointer. */ static void ibnotify(io_buffers_queue_t *bqp) { - QMKUSBDriver *qmkusbp = bqGetLinkX(bqp); - (void) qmkusb_start_receive(qmkusbp); + QMKUSBDriver *qmkusbp = bqGetLinkX(bqp); + (void)qmkusb_start_receive(qmkusbp); } /** @@ -145,25 +114,24 @@ static void ibnotify(io_buffers_queue_t *bqp) { * @param[in] bqp the buffers queue pointer. */ static void obnotify(io_buffers_queue_t *bqp) { - size_t n; - QMKUSBDriver *qmkusbp = bqGetLinkX(bqp); - - /* If the USB driver is not in the appropriate state then transactions - must not be started.*/ - if ((usbGetDriverStateI(qmkusbp->config->usbp) != USB_ACTIVE) || - (qmkusbp->state != QMKUSB_READY)) { - return; - } - - /* Checking if there is already a transaction ongoing on the endpoint.*/ - if (!usbGetTransmitStatusI(qmkusbp->config->usbp, qmkusbp->config->bulk_in)) { - /* Trying to get a full buffer.*/ - uint8_t *buf = obqGetFullBufferI(&qmkusbp->obqueue, &n); - if (buf != NULL) { - /* Buffer found, starting a new transaction.*/ - usbStartTransmitI(qmkusbp->config->usbp, qmkusbp->config->bulk_in, buf, n); + size_t n; + QMKUSBDriver *qmkusbp = bqGetLinkX(bqp); + + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if ((usbGetDriverStateI(qmkusbp->config->usbp) != USB_ACTIVE) || (qmkusbp->state != QMKUSB_READY)) { + return; + } + + /* Checking if there is already a transaction ongoing on the endpoint.*/ + if (!usbGetTransmitStatusI(qmkusbp->config->usbp, qmkusbp->config->bulk_in)) { + /* Trying to get a full buffer.*/ + uint8_t *buf = obqGetFullBufferI(&qmkusbp->obqueue, &n); + if (buf != NULL) { + /* Buffer found, starting a new transaction.*/ + usbStartTransmitI(qmkusbp->config->usbp, qmkusbp->config->bulk_in, buf, n); + } } - } } /*===========================================================================*/ @@ -177,8 +145,7 @@ static void obnotify(io_buffers_queue_t *bqp) { * * @init */ -void qmkusbInit(void) { -} +void qmkusbInit(void) {} /** * @brief Initializes a generic full duplex driver object. @@ -190,17 +157,12 @@ void qmkusbInit(void) { * @init */ void qmkusbObjectInit(QMKUSBDriver *qmkusbp, const QMKUSBConfig *config) { - - qmkusbp->vmt = &vmt; - osalEventObjectInit(&qmkusbp->event); - qmkusbp->state = QMKUSB_STOP; - // Note that the config uses the USB direction naming - ibqObjectInit(&qmkusbp->ibqueue, true, config->ob, - config->out_size, config->out_buffers, - ibnotify, qmkusbp); - obqObjectInit(&qmkusbp->obqueue, true, config->ib, - config->in_size, config->in_buffers, - obnotify, qmkusbp); + qmkusbp->vmt = &vmt; + osalEventObjectInit(&qmkusbp->event); + qmkusbp->state = QMKUSB_STOP; + // Note that the config uses the USB direction naming + ibqObjectInit(&qmkusbp->ibqueue, true, config->ob, config->out_size, config->out_buffers, ibnotify, qmkusbp); + obqObjectInit(&qmkusbp->obqueue, true, config->ib, config->in_size, config->in_buffers, obnotify, qmkusbp); } /** @@ -212,21 +174,20 @@ void qmkusbObjectInit(QMKUSBDriver *qmkusbp, const QMKUSBConfig *config) { * @api */ void qmkusbStart(QMKUSBDriver *qmkusbp, const QMKUSBConfig *config) { - USBDriver *usbp = config->usbp; - - osalDbgCheck(qmkusbp != NULL); - - osalSysLock(); - osalDbgAssert((qmkusbp->state == QMKUSB_STOP) || (qmkusbp->state == QMKUSB_READY), - "invalid state"); - usbp->in_params[config->bulk_in - 1U] = qmkusbp; - usbp->out_params[config->bulk_out - 1U] = qmkusbp; - if (config->int_in > 0U) { - usbp->in_params[config->int_in - 1U] = qmkusbp; - } - qmkusbp->config = config; - qmkusbp->state = QMKUSB_READY; - osalSysUnlock(); + USBDriver *usbp = config->usbp; + + osalDbgCheck(qmkusbp != NULL); + + osalSysLock(); + osalDbgAssert((qmkusbp->state == QMKUSB_STOP) || (qmkusbp->state == QMKUSB_READY), "invalid state"); + usbp->in_params[config->bulk_in - 1U] = qmkusbp; + usbp->out_params[config->bulk_out - 1U] = qmkusbp; + if (config->int_in > 0U) { + usbp->in_params[config->int_in - 1U] = qmkusbp; + } + qmkusbp->config = config; + qmkusbp->state = QMKUSB_READY; + osalSysUnlock(); } /** @@ -239,31 +200,30 @@ void qmkusbStart(QMKUSBDriver *qmkusbp, const QMKUSBConfig *config) { * @api */ void qmkusbStop(QMKUSBDriver *qmkusbp) { - USBDriver *usbp = qmkusbp->config->usbp; + USBDriver *usbp = qmkusbp->config->usbp; - osalDbgCheck(qmkusbp != NULL); + osalDbgCheck(qmkusbp != NULL); - osalSysLock(); + osalSysLock(); - osalDbgAssert((qmkusbp->state == QMKUSB_STOP) || (qmkusbp->state == QMKUSB_READY), - "invalid state"); + osalDbgAssert((qmkusbp->state == QMKUSB_STOP) || (qmkusbp->state == QMKUSB_READY), "invalid state"); - /* Driver in stopped state.*/ - usbp->in_params[qmkusbp->config->bulk_in - 1U] = NULL; - usbp->out_params[qmkusbp->config->bulk_out - 1U] = NULL; - if (qmkusbp->config->int_in > 0U) { - usbp->in_params[qmkusbp->config->int_in - 1U] = NULL; - } - qmkusbp->config = NULL; - qmkusbp->state = QMKUSB_STOP; + /* Driver in stopped state.*/ + usbp->in_params[qmkusbp->config->bulk_in - 1U] = NULL; + usbp->out_params[qmkusbp->config->bulk_out - 1U] = NULL; + if (qmkusbp->config->int_in > 0U) { + usbp->in_params[qmkusbp->config->int_in - 1U] = NULL; + } + qmkusbp->config = NULL; + qmkusbp->state = QMKUSB_STOP; - /* Enforces a disconnection.*/ - chnAddFlagsI(qmkusbp, CHN_DISCONNECTED); - ibqResetI(&qmkusbp->ibqueue); - obqResetI(&qmkusbp->obqueue); - osalOsRescheduleS(); + /* Enforces a disconnection.*/ + chnAddFlagsI(qmkusbp, CHN_DISCONNECTED); + ibqResetI(&qmkusbp->ibqueue); + obqResetI(&qmkusbp->obqueue); + osalOsRescheduleS(); - osalSysUnlock(); + osalSysUnlock(); } /** @@ -279,10 +239,9 @@ void qmkusbStop(QMKUSBDriver *qmkusbp) { * @iclass */ void qmkusbSuspendHookI(QMKUSBDriver *qmkusbp) { - - chnAddFlagsI(qmkusbp, CHN_DISCONNECTED); - bqSuspendI(&qmkusbp->ibqueue); - bqSuspendI(&qmkusbp->obqueue); + chnAddFlagsI(qmkusbp, CHN_DISCONNECTED); + bqSuspendI(&qmkusbp->ibqueue); + bqSuspendI(&qmkusbp->obqueue); } /** @@ -298,10 +257,9 @@ void qmkusbSuspendHookI(QMKUSBDriver *qmkusbp) { * @iclass */ void qmkusbWakeupHookI(QMKUSBDriver *qmkusbp) { - - chnAddFlagsI(qmkusbp, CHN_CONNECTED); - bqResumeX(&qmkusbp->ibqueue); - bqResumeX(&qmkusbp->obqueue); + chnAddFlagsI(qmkusbp, CHN_CONNECTED); + bqResumeX(&qmkusbp->ibqueue); + bqResumeX(&qmkusbp->obqueue); } /** @@ -312,13 +270,12 @@ void qmkusbWakeupHookI(QMKUSBDriver *qmkusbp) { * @iclass */ void qmkusbConfigureHookI(QMKUSBDriver *qmkusbp) { - - ibqResetI(&qmkusbp->ibqueue); - bqResumeX(&qmkusbp->ibqueue); - obqResetI(&qmkusbp->obqueue); - bqResumeX(&qmkusbp->obqueue); - chnAddFlagsI(qmkusbp, CHN_CONNECTED); - (void) qmkusb_start_receive(qmkusbp); + ibqResetI(&qmkusbp->ibqueue); + bqResumeX(&qmkusbp->ibqueue); + obqResetI(&qmkusbp->obqueue); + bqResumeX(&qmkusbp->obqueue); + chnAddFlagsI(qmkusbp, CHN_CONNECTED); + (void)qmkusb_start_receive(qmkusbp); } /** @@ -337,24 +294,23 @@ void qmkusbConfigureHookI(QMKUSBDriver *qmkusbp) { * @retval false Message not handled. */ bool qmkusbRequestsHook(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), 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; + 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); + 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; + return false; } /** @@ -367,36 +323,34 @@ bool qmkusbRequestsHook(USBDriver *usbp) { * @iclass */ void qmkusbSOFHookI(QMKUSBDriver *qmkusbp) { + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if ((usbGetDriverStateI(qmkusbp->config->usbp) != USB_ACTIVE) || (qmkusbp->state != QMKUSB_READY)) { + return; + } - /* If the USB driver is not in the appropriate state then transactions - must not be started.*/ - if ((usbGetDriverStateI(qmkusbp->config->usbp) != USB_ACTIVE) || - (qmkusbp->state != QMKUSB_READY)) { - return; - } - - /* If there is already a transaction ongoing then another one cannot be - started.*/ - if (usbGetTransmitStatusI(qmkusbp->config->usbp, qmkusbp->config->bulk_in)) { - return; - } - - /* Checking if there only a buffer partially filled, if so then it is - enforced in the queue and transmitted.*/ - if (obqTryFlushI(&qmkusbp->obqueue)) { - size_t n; - uint8_t *buf = obqGetFullBufferI(&qmkusbp->obqueue, &n); - - /* For fixed size drivers, fill the end with zeros */ - if (qmkusbp->config->fixed_size) { - memset(buf + n, 0, qmkusbp->config->in_size - n); - n = qmkusbp->config->in_size; + /* If there is already a transaction ongoing then another one cannot be + started.*/ + if (usbGetTransmitStatusI(qmkusbp->config->usbp, qmkusbp->config->bulk_in)) { + return; } - osalDbgAssert(buf != NULL, "queue is empty"); + /* Checking if there only a buffer partially filled, if so then it is + enforced in the queue and transmitted.*/ + if (obqTryFlushI(&qmkusbp->obqueue)) { + size_t n; + uint8_t *buf = obqGetFullBufferI(&qmkusbp->obqueue, &n); - usbStartTransmitI(qmkusbp->config->usbp, qmkusbp->config->bulk_in, buf, n); - } + /* For fixed size drivers, fill the end with zeros */ + if (qmkusbp->config->fixed_size) { + memset(buf + n, 0, qmkusbp->config->in_size - n); + n = qmkusbp->config->in_size; + } + + osalDbgAssert(buf != NULL, "queue is empty"); + + usbStartTransmitI(qmkusbp->config->usbp, qmkusbp->config->bulk_in, buf, n); + } } /** @@ -408,49 +362,45 @@ void qmkusbSOFHookI(QMKUSBDriver *qmkusbp) { * @param[in] ep IN endpoint number */ void qmkusbDataTransmitted(USBDriver *usbp, usbep_t ep) { - uint8_t *buf; - size_t n; - QMKUSBDriver *qmkusbp = usbp->in_params[ep - 1U]; + uint8_t * buf; + size_t n; + QMKUSBDriver *qmkusbp = usbp->in_params[ep - 1U]; - if (qmkusbp == NULL) { - return; - } + if (qmkusbp == NULL) { + return; + } - osalSysLockFromISR(); + osalSysLockFromISR(); - /* Signaling that space is available in the output queue.*/ - chnAddFlagsI(qmkusbp, CHN_OUTPUT_EMPTY); + /* Signaling that space is available in the output queue.*/ + chnAddFlagsI(qmkusbp, CHN_OUTPUT_EMPTY); - /* Freeing the buffer just transmitted, if it was not a zero size packet.*/ - if (usbp->epc[ep]->in_state->txsize > 0U) { - obqReleaseEmptyBufferI(&qmkusbp->obqueue); - } + /* Freeing the buffer just transmitted, if it was not a zero size packet.*/ + if (usbp->epc[ep]->in_state->txsize > 0U) { + obqReleaseEmptyBufferI(&qmkusbp->obqueue); + } - /* Checking if there is a buffer ready for transmission.*/ - buf = obqGetFullBufferI(&qmkusbp->obqueue, &n); + /* Checking if there is a buffer ready for transmission.*/ + buf = obqGetFullBufferI(&qmkusbp->obqueue, &n); - if (buf != NULL) { - /* The endpoint cannot be busy, we are in the context of the callback, - so it is safe to transmit without a check.*/ - usbStartTransmitI(usbp, ep, buf, n); - } - else if ((usbp->epc[ep]->in_state->txsize > 0U) && - ((usbp->epc[ep]->in_state->txsize & - ((size_t)usbp->epc[ep]->in_maxsize - 1U)) == 0U)) { - /* 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.*/ - if (!qmkusbp->config->fixed_size) { - usbStartTransmitI(usbp, ep, usbp->setup, 0); + if (buf != NULL) { + /* The endpoint cannot be busy, we are in the context of the callback, + so it is safe to transmit without a check.*/ + usbStartTransmitI(usbp, ep, buf, n); + } else if ((usbp->epc[ep]->in_state->txsize > 0U) && ((usbp->epc[ep]->in_state->txsize & ((size_t)usbp->epc[ep]->in_maxsize - 1U)) == 0U)) { + /* 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.*/ + if (!qmkusbp->config->fixed_size) { + usbStartTransmitI(usbp, ep, usbp->setup, 0); + } + + } else { + /* Nothing to transmit.*/ } - } - else { - /* Nothing to transmit.*/ - } - - osalSysUnlockFromISR(); + osalSysUnlockFromISR(); } /** @@ -462,27 +412,25 @@ void qmkusbDataTransmitted(USBDriver *usbp, usbep_t ep) { * @param[in] ep OUT endpoint number */ void qmkusbDataReceived(USBDriver *usbp, usbep_t ep) { - QMKUSBDriver *qmkusbp = usbp->out_params[ep - 1U]; - if (qmkusbp == NULL) { - return; - } + QMKUSBDriver *qmkusbp = usbp->out_params[ep - 1U]; + if (qmkusbp == NULL) { + return; + } - osalSysLockFromISR(); + osalSysLockFromISR(); - /* Signaling that data is available in the input queue.*/ - chnAddFlagsI(qmkusbp, CHN_INPUT_AVAILABLE); + /* Signaling that data is available in the input queue.*/ + chnAddFlagsI(qmkusbp, CHN_INPUT_AVAILABLE); - /* Posting the filled buffer in the queue.*/ - ibqPostFullBufferI(&qmkusbp->ibqueue, - usbGetReceiveTransactionSizeX(qmkusbp->config->usbp, - qmkusbp->config->bulk_out)); + /* Posting the filled buffer in the queue.*/ + ibqPostFullBufferI(&qmkusbp->ibqueue, usbGetReceiveTransactionSizeX(qmkusbp->config->usbp, qmkusbp->config->bulk_out)); - /* The endpoint cannot be busy, we are in the context of the callback, - so a packet is in the buffer for sure. Trying to get a free buffer - for the next transaction.*/ - (void) qmkusb_start_receive(qmkusbp); + /* The endpoint cannot be busy, we are in the context of the callback, + so a packet is in the buffer for sure. Trying to get a free buffer + for the next transaction.*/ + (void)qmkusb_start_receive(qmkusbp); - osalSysUnlockFromISR(); + osalSysUnlockFromISR(); } /** @@ -494,9 +442,8 @@ void qmkusbDataReceived(USBDriver *usbp, usbep_t ep) { * @param[in] ep endpoint number */ void qmkusbInterruptTransmitted(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - (void)ep; + (void)usbp; + (void)ep; } /** @} */ |