/** * @brief Starts a receive transaction on an OUT endpoint. * @note This function is meant to be called from ISR context outside * critical zones because there is a potentially slow operation * inside. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * @param[out] buf buffer where to copy the received data * @param[in] n transaction size. It is recommended a multiple of * the packet size because the excess is discarded. * * @iclass */ void usbStartReceiveI(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { USBOutEndpointState *osp; osalDbgCheckClassI(); osalDbgCheck((usbp != NULL) && (ep <= (usbep_t)USB_MAX_ENDPOINTS)); osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving"); /* Marking the endpoint as active.*/ usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); /* Setting up the transfer.*/ /*lint -save -e661 [18.1] pclint is confused by the check on ep.*/ osp = usbp->epc[ep]->out_state; /*lint -restore*/ osp->rxbuf = buf; osp->rxsize = n; osp->rxcnt = 0; #if USB_USE_WAIT == TRUE osp->thread = NULL; #endif /* Starting transfer.*/ usb_lld_start_out(usbp, ep); }
/** * @brief Notification of data removed from the input queue. * * @param[in] qp the queue pointer. */ static void inotify(io_queue_t *qp) { size_t n, maxsize; SerialUSBDriver *sdup = qGetLink(qp); /* If the USB driver is not in the appropriate state then transactions must not be started.*/ 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[sdup->config->bulk_out]->out_maxsize; if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out)) { if ((n = iqGetEmptyI(&sdup->iqueue)) >= maxsize) { osalSysUnlock(); n = (n / maxsize) * maxsize; usbPrepareQueuedReceive(sdup->config->usbp, sdup->config->bulk_out, &sdup->iqueue, n); osalSysLock(); (void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out); } } }
/** * @brief Notification of data removed from the input queue. */ static void inotify(GenericQueue *qp) { size_t n, maxsize; BulkUSBDriver *bdup = chQGetLink(qp); /* If the USB driver is not in the appropriate state then transactions must not be started.*/ if ((usbGetDriverStateI(bdup->config->usbp) != USB_ACTIVE) || (bdup->state != BDU_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 = bdup->config->usbp->epc[bdup->config->bulk_out]->out_maxsize; if (!usbGetReceiveStatusI(bdup->config->usbp, bdup->config->bulk_out) && ((n = chIQGetEmptyI(&bdup->iqueue)) >= maxsize)) { chSysUnlock(); n = (n / maxsize) * maxsize; usbPrepareQueuedReceive(bdup->config->usbp, bdup->config->bulk_out, &bdup->iqueue, n); chSysLock(); usbStartReceiveI(bdup->config->usbp, bdup->config->bulk_out); } }
/** * @brief Notification of data removed from the input queue. */ 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.*/ maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize; if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) && ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize)) { chSysUnlock(); 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); } }
/** * @brief Stalls an OUT endpoint. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval false Endpoint stalled. * @retval true Endpoint busy, not stalled. * * @iclass */ bool usbStallReceiveI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); if (usbGetReceiveStatusI(usbp, ep)) return true; usb_lld_stall_out(usbp, ep); return false; }
/** * @brief Stalls an OUT endpoint. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval FALSE Endpoint stalled. * @retval TRUE Endpoint busy, not stalled. * * @iclass */ bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep) { chDbgCheckClassI(); chDbgCheck(usbp != NULL, "usbStallReceiveI"); if (usbGetReceiveStatusI(usbp, ep)) return TRUE; usb_lld_stall_out(usbp, ep); return FALSE; }
/** * @brief Starts a receive transaction on an OUT endpoint. * @post The endpoint callback is invoked when the transfer has been * completed. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval FALSE Operation started successfully. * @retval TRUE Endpoint busy, operation not started. * * @iclass */ bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); if (usbGetReceiveStatusI(usbp, ep)) return TRUE; usbp->receiving |= (1 << ep); usb_lld_start_out(usbp, ep); return FALSE; }
/** * @brief Starts a receive transaction on an OUT endpoint. * @post The endpoint callback is invoked when the transfer has been * completed. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval false Operation started successfully. * @retval true Endpoint busy, operation not started. * * @iclass */ bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); if (usbGetReceiveStatusI(usbp, ep)) { return true; } usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); usb_lld_start_out(usbp, ep); return false; }
/** * @brief Notification of empty buffer released into the input buffers queue. * * @param[in] bqp the buffers queue pointer. */ static void ibnotify(io_buffers_queue_t *bqp) { SerialUSBDriver *sdup = bqGetLinkX(bqp); /* If the USB driver is not in the appropriate state then transactions must not be started.*/ if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || (sdup->state != SDU_READY)) { return; } /* Checking if there is already a transaction ongoing on the endpoint.*/ if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out)) { /* Trying to get a free buffer.*/ uint8_t *buf = ibqGetEmptyBufferI(&sdup->ibqueue); if (buf != NULL) { /* Buffer found, starting a new transaction.*/ usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, buf, SERIAL_USB_BUFFERS_SIZE); } } }