/***************************************************************************//** * @brief Handle Endpoint 2 OUT transfer interrupt * @note This function takes no parameters, but it uses the EP2OUT status * variables stored in @ref myUsbDevice.ep2out. ******************************************************************************/ void handleUsbOut2Int(void) { uint8_t count; USB_Status_TypeDef status; bool xferComplete = false; USB_SetIndex(2); if (USB_EpnOutGetSentStall()) { USB_EpnOutClearSentStall(); } else if (USB_EpnGetOutPacketReady()) { count = USB_EpOutGetCount(); // If USBD_Read() has not been called, return an error if (myUsbDevice.ep2out.state != D_EP_RECEIVING) { myUsbDevice.ep2out.misc.bits.outPacketPending = true; status = USB_STATUS_EP_ERROR; } // Check for overrun of user buffer else if (myUsbDevice.ep2out.remaining < count) { myUsbDevice.ep2out.state = D_EP_IDLE; myUsbDevice.ep2out.misc.bits.outPacketPending = true; status = USB_STATUS_EP_RX_BUFFER_OVERRUN; } else { USB_ReadFIFO(2, count, myUsbDevice.ep2out.buf); myUsbDevice.ep2out.misc.bits.outPacketPending = false; myUsbDevice.ep2out.remaining -= count; myUsbDevice.ep2out.buf += count; if ((myUsbDevice.ep2out.remaining == 0) || (count != SLAB_USB_EP2OUT_MAX_PACKET_SIZE)) { myUsbDevice.ep2out.state = D_EP_IDLE; xferComplete = true; } status = USB_STATUS_OK; USB_EpnClearOutPacketReady(); } if (myUsbDevice.ep2out.misc.bits.callback == true) { if (xferComplete == true) { myUsbDevice.ep2out.misc.bits.callback = false; } USBD_XferCompleteCb(EP2OUT, status, count, myUsbDevice.ep2out.remaining); } } }
/***************************************************************************//** * @brief Reads and formats a setup packet ******************************************************************************/ static void USB_ReadFIFOSetup(void) { uint16_t MEM_MODEL_SEG *ptr = &myUsbDevice.setup; USB_ReadFIFO(0, 8, (uint8_t *)ptr); USB_Ep0ServicedOutPacketReady(); // Modify for Endian-ness of the compiler ptr[1] = le16toh(ptr[1]); ptr[2] = le16toh(ptr[2]); ptr[3] = le16toh(ptr[3]); }
// ---------------------------------------------------------------------------- // If Isochronous mode is enabled and the max packet size is greater than 255, // break the FIFO reads up into multiple reads of 255 or less bytes. // ---------------------------------------------------------------------------- void USB_ReadFIFOIso(uint8_t fifoNum, uint16_t numBytes, uint8_t *dat) { uint8_t numBytesRead; // USB_ReadFIFO() accepts a maximum of 255 bytes. If the number of bytes to // send is greated than 255, call USB_ReadFIFO() multiple times. while (numBytes > 0) { numBytesRead = (numBytes > 255) ? 255 : numBytes; USB_ReadFIFO(fifoNum, numBytesRead, dat); numBytes -= numBytesRead; dat += numBytesRead; } }
/***************************************************************************//** * @brief Handles receive data phase on Endpoint 0 ******************************************************************************/ void handleUsbEp0Rx(void) { uint8_t count; USB_Status_TypeDef status; bool callback = myUsbDevice.ep0.misc.bits.callback; // Get the number of bytes received count = USB_Ep0GetCount(); // If the call to USBD_Read() did not give a large enough buffer to hold this // data, set the outPacketPending flag and signal an RX overrun. if (myUsbDevice.ep0.remaining < count) { myUsbDevice.ep0.state = D_EP_IDLE; myUsbDevice.ep0.misc.bits.outPacketPending = true; status = USB_STATUS_EP_RX_BUFFER_OVERRUN; } else { USB_ReadFIFO(0, count, myUsbDevice.ep0.buf); myUsbDevice.ep0.buf += count; myUsbDevice.ep0.remaining -= count; status = USB_STATUS_OK; // If the last packet of the transfer is exactly the maximum EP0 packet // size, we will must wait to receive a ZLP (zero-length packet) after the // last data packet. This signals that the host has completed the transfer. // Check for the ZLP packet case here. if ((myUsbDevice.ep0.remaining == 0) && (count != USB_EP0_SIZE)) { USB_Ep0SetLastOutPacketReady(); myUsbDevice.ep0.state = D_EP_IDLE; myUsbDevice.ep0.misc.bits.callback = false; } else { // Do not call USB_Ep0SetLastOutPacketReady() until we get the ZLP. USB_Ep0ServicedOutPacketReady(); } } // Make callback if requested if (callback == true) { USBD_XferCompleteCb(EP0, status, count, myUsbDevice.ep0.remaining); } }
/***************************************************************************//** * @brief Handle Endpoint 3 OUT transfer interrupt * @details Endpoint 3 OUT is the only OUT endpoint that supports * isochronous transfers. * @note This function takes no parameters, but it uses the EP3OUT status * variables stored in @ref myUsbDevice.ep3out. ******************************************************************************/ void handleUsbOut3Int(void) { #if (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC) uint16_t nextIdx; #if (SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255) uint16_t count; #else uint8_t count; #endif // ( SLAB_USB_EP3OUT_MAX_PACKET_SIZE > 255 ) #else uint8_t count; #endif // ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC ) USB_Status_TypeDef status; bool xferComplete = false; USB_SetIndex(3); if (USB_EpnOutGetSentStall()) { USB_EpnOutClearSentStall(); } else if (USB_EpnGetOutPacketReady()) { count = USB_EpOutGetCount(); // If USBD_Read() has not been called, return an error if (myUsbDevice.ep3out.state != D_EP_RECEIVING) { myUsbDevice.ep3out.misc.bits.outPacketPending = true; status = USB_STATUS_EP_ERROR; } #if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR)) // Check for overrun of user buffer else if (myUsbDevice.ep3out.remaining < count) { myUsbDevice.ep3out.state = D_EP_IDLE; myUsbDevice.ep3out.misc.bits.outPacketPending = true; status = USB_STATUS_EP_RX_BUFFER_OVERRUN; } #endif else { #if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR)) USB_ReadFIFO(3, count, myUsbDevice.ep3out.buf); myUsbDevice.ep3out.remaining -= count; myUsbDevice.ep3out.buf += count; if ((myUsbDevice.ep3out.remaining == 0) || (count != SLAB_USB_EP3OUT_MAX_PACKET_SIZE)) { myUsbDevice.ep3out.state = D_EP_IDLE; xferComplete = true; } #elif (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC) nextIdx = count + myUsbDevice.ep3outIsoIdx; // In isochronous mode, a circular buffer is used to hold the data // If the next index into the circular buffer passes the end of the // buffer, make two calls to USB_ReadFIFOIso() if (nextIdx > myUsbDevice.ep3out.remaining) { USB_ReadFIFOIso(3, myUsbDevice.ep3out.remaining - myUsbDevice.ep3outIsoIdx, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]); myUsbDevice.ep3outIsoIdx = nextIdx - myUsbDevice.ep3out.remaining; USB_ReadFIFOIso(3, myUsbDevice.ep3outIsoIdx, myUsbDevice.ep3out.buf); } else { USB_ReadFIFOIso(3, count, &myUsbDevice.ep3out.buf[myUsbDevice.ep3outIsoIdx]); myUsbDevice.ep3outIsoIdx = nextIdx; } #endif // ( ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK ) || ( SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR ) ) myUsbDevice.ep3out.misc.bits.outPacketPending = false; status = USB_STATUS_OK; USB_EpnClearOutPacketReady(); } if (myUsbDevice.ep3out.misc.bits.callback == true) { if (xferComplete == true) { myUsbDevice.ep3out.misc.bits.callback = false; } #if ((SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_INTR)) USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3out.remaining); #elif (SLAB_USB_EP3OUT_TRANSFER_TYPE == USB_EPTYPE_ISOC) // In Isochronous mode, the meaning of the USBD_XferCompleteCb parameters changes: // xferred is the number of bytes received in the last packet // remaining is the current index into the circular buffer USBD_XferCompleteCb(EP3OUT, status, count, myUsbDevice.ep3outIsoIdx); #endif } } }