/** * @brief Starts a receive operation on an OUT endpoint. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @notapi */ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { USBOutEndpointState *osp = usbp->epc[ep]->out_state; /* Transfer initialization.*/ if (osp->rxsize == 0) /* Special case for zero sized packets.*/ osp->rxpkts = 1; else osp->rxpkts = (uint16_t)((osp->rxsize + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize); EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); }
/** * @brief Starts a receive operation on an OUT endpoint. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * @param[out] buf buffer where to copy the endpoint data * @param[in] n maximum number of bytes to copy in the buffer * * @notapi */ void usb_lld_start_out(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { USBOutEndpointState *osp = usbp->epc[ep]->out_state; osp->rxbuf = buf; osp->rxsize = n; osp->rxcnt = 0; if (osp->rxsize == 0) /* Special case for zero sized packets.*/ osp->rxpkts = 1; else osp->rxpkts = (uint16_t)((n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize); EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); }
/** * @brief Reads a setup packet from the dedicated packet buffer. * @details This function must be invoked in the context of the @p setup_cb * callback in order to read the received setup packet. * @pre In order to use this function the endpoint must have been * initialized as a control endpoint. * @post The endpoint is ready to accept another packet. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * @param[out] buf buffer where to copy the packet data * * @notapi */ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { uint32_t *pmap; stm32_usb_descriptor_t *udp; uint32_t n; (void)usbp; udp = USB_GET_DESCRIPTOR(ep); pmap = USB_ADDR2PTR(udp->RXADDR); for (n = 0; n < 4; n++) { *(uint16_t *)buf = (uint16_t)*pmap++; buf += 2; } EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); }
/** * @brief Reads a packet from the dedicated packet buffer. * @pre In order to use this function he endpoint must have been * initialized in packet mode. * @post The endpoint is ready to accept another packet. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * @param[out] buf buffer where to copy the packet data * @param[in] n maximum number of bytes to copy. This value must * not exceed the maximum packet size for this endpoint. * @return The received packet size regardless the specified * @p n parameter. * @retval 0 Zero size packet received. * * @notapi */ size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { uint32_t *pmap; stm32_usb_descriptor_t *udp; size_t count; (void)usbp; udp = USB_GET_DESCRIPTOR(ep); pmap = USB_ADDR2PTR(udp->RXADDR); count = udp->RXCOUNT & RXCOUNT_COUNT_MASK; if (n > count) n = count; n = (n + 1) / 2; while (n > 0) { *(uint16_t *)buf = (uint16_t)*pmap++; buf += 2; n--; } EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); return count; }
/** * @brief Brings an OUT endpoint in the stalled state. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @notapi */ void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { (void)usbp; EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL); }
/** * @brief Common ISR code, serves the EP-related interrupts. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @notapi */ static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) { size_t n; uint32_t epr = STM32_USB->EPR[ep]; const USBEndpointConfig *epcp = usbp->epc[ep]; if (epr & EPR_CTR_TX) { /* IN endpoint, transmission.*/ USBInEndpointState *isp = epcp->in_state; EPR_CLEAR_CTR_TX(ep); isp->txcnt += isp->txlast; n = isp->txsize - isp->txcnt; if (n > 0) { /* Transfer not completed, there are more packets to send.*/ if (n > epcp->in_maxsize) n = epcp->in_maxsize; /* Writes the packet from the defined buffer.*/ isp->txbuf += isp->txlast; isp->txlast = n; usb_packet_write_from_buffer(ep, isp->txbuf, n); /* Starting IN operation.*/ EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); } else { /* Transfer completed, invokes the callback.*/ _usb_isr_invoke_in_cb(usbp, ep); } } if (epr & EPR_CTR_RX) { /* OUT endpoint, receive.*/ EPR_CLEAR_CTR_RX(ep); if (epr & EPR_SETUP) { /* Setup packets handling, setup packets are handled using a specific callback.*/ _usb_isr_invoke_setup_cb(usbp, ep); } else { USBOutEndpointState *osp = epcp->out_state; /* Reads the packet into the defined buffer.*/ n = usb_packet_read_to_buffer(ep, osp->rxbuf); osp->rxbuf += n; /* Transaction data updated.*/ osp->rxcnt += n; osp->rxsize -= n; osp->rxpkts -= 1; /* The transaction is completed if the specified number of packets has been received or the current packet is a short packet.*/ if ((n < epcp->out_maxsize) || (osp->rxpkts == 0)) { /* Transfer complete, invokes the callback.*/ _usb_isr_invoke_out_cb(usbp, ep); } else { /* Transfer not complete, there are more packets to receive.*/ EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); } } } }
/** * @brief Starts a receive operation on an OUT endpoint. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @notapi */ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { (void)usbp; EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); }