/***************************************************************************//** * @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 Writes data to the USB FIFO * @param fifoNum * USB Endpoint FIFO to write * @param numBytes * Number of bytes to write to the FIFO * @param dat * Pointer to buffer hoding data to write to the FIFO * @param txPacket * If TRUE, the packet will be sent immediately after loading the * FIFO * If FALSE, the packet will be stored in the FIFO and the * transmission must be started at a later time ******************************************************************************/ void USB_WriteFIFO(uint8_t fifoNum, uint8_t numBytes, uint8_t *dat, bool txPacket) { USB_EnableWriteFIFO(fifoNum); // Convert generic pointer to memory-specific pointer and call the // the corresponding memory-specific function, if possible. // The memory-specific functions are much faster than the generic functions. #ifdef SI_GPTR switch (((SI_GEN_PTR_t *)&dat)->gptr.memtype) { case SI_GPTR_MTYPE_IDATA: USB_WriteFIFO_Idata(numBytes, dat); break; // For some compilers, IDATA and DATA are treated the same. // Only call the USB_WriteFIFO_Data() if the compiler differentiates between // DATA and IDATA. #if (SI_GPTR_MTYPE_DATA != SI_GPTR_MTYPE_IDATA) case SI_GPTR_MTYPE_DATA: USB_WriteFIFO_Data(numBytes, dat); break; #endif case SI_GPTR_MTYPE_XDATA: USB_WriteFIFO_Xdata(numBytes, dat); break; // For some compilers, XDATA and PDATA are treated the same. // Only call the USB_WriteFIFO_Pdata() if the compiler differentiates // between XDATA and PDATA. #if (SI_GPTR_MTYPE_PDATA != SI_GPTR_MTYPE_XDATA) case SI_GPTR_MTYPE_PDATA: USB_WriteFIFO_Pdata(numBytes, dat); break; #endif case SI_GPTR_MTYPE_CODE: USB_WriteFIFO_Code(numBytes, dat); break; default: break; } #else USB_WriteFIFO_Generic(numBytes, dat); #endif // #ifdef SI_GPTR USB_DisableWriteFIFO(fifoNum); if ((txPacket == true) && (fifoNum > 0)) { USB_SetIndex(fifoNum); USB_EpnSetInPacketReady(); } }
void USB_ActivateEp(uint8_t ep, uint16_t packetSize, bool inDir, bool splitMode, bool isoMode) { uint8_t CSRH_mask = 0; uint16_t fifoSize; USB_SetIndex(ep); // Determine the available fifoSize for a given endpoint based on the // splitMode setting fifoSize = (splitMode == true) ? (16 << ep) : (32 << ep); if (packetSize <= fifoSize) { CSRH_mask |= EINCSRH_DBIEN__ENABLED; } if (isoMode == true) { CSRH_mask |= EINCSRH_ISO__ENABLED; } if (inDir == true) { CSRH_mask |= EINCSRH_DIRSEL__IN; if (splitMode == true) { CSRH_mask |= EINCSRH_SPLIT__ENABLED; } USB_WRITE_BYTE(EINCSRL, EINCSRL_CLRDT__BMASK); USB_WRITE_BYTE(EINCSRH, CSRH_mask); } else // OUT { USB_WRITE_BYTE(EOUTCSRL, EOUTCSRL_CLRDT__BMASK); USB_WRITE_BYTE(EOUTCSRH, CSRH_mask); if (splitMode == false) { USB_WRITE_BYTE(EINCSRH, 0); } } }
/***************************************************************************//** * @brief Handle Endpoint 2 IN transfer interrupt * @note This function takes no parameters, but it uses the EP2IN status * variables stored in @ref myUsbDevice.ep2in. ******************************************************************************/ void handleUsbIn2Int(void) { uint8_t xferred; bool callback; USB_SetIndex(2); if (USB_EpnInGetSentStall()) { USB_EpnInClearSentStall(); } else if (myUsbDevice.ep2in.state == D_EP_TRANSMITTING) { xferred = (myUsbDevice.ep2in.remaining > SLAB_USB_EP2IN_MAX_PACKET_SIZE) ? SLAB_USB_EP2IN_MAX_PACKET_SIZE : myUsbDevice.ep2in.remaining; myUsbDevice.ep2in.remaining -= xferred; myUsbDevice.ep2in.buf += xferred; callback = myUsbDevice.ep2in.misc.bits.callback; // Load more data if (myUsbDevice.ep2in.remaining > 0) { USB_WriteFIFO(2, (myUsbDevice.ep2in.remaining > SLAB_USB_EP2IN_MAX_PACKET_SIZE) ? SLAB_USB_EP2IN_MAX_PACKET_SIZE : myUsbDevice.ep2in.remaining, myUsbDevice.ep2in.buf, true); } else { myUsbDevice.ep2in.misc.bits.callback = false; myUsbDevice.ep2in.state = D_EP_IDLE; } if (callback == true) { USBD_XferCompleteCb(EP2IN, USB_STATUS_OK, xferred, myUsbDevice.ep2in.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 } } }
/***************************************************************************//** * @brief Handle Endpoint 3 IN transfer interrupt * @details Endpoint 3 IN is the only IN endpoint that supports isochronous * transfers. * @note This function takes no parameters, but it uses the EP3IN status * variables stored in @ref myUsbDevice.ep3in. ******************************************************************************/ void handleUsbIn3Int(void) { #if SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC uint16_t xferred, nextIdx; #else uint8_t xferred; bool callback; #endif USB_SetIndex(3); if (USB_EpnInGetSentStall()) { USB_EpnInClearSentStall(); } else if (myUsbDevice.ep3in.state == D_EP_TRANSMITTING) { #if ((SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_INTR)) xferred = (myUsbDevice.ep3in.remaining > SLAB_USB_EP3IN_MAX_PACKET_SIZE) ? SLAB_USB_EP3IN_MAX_PACKET_SIZE : myUsbDevice.ep3in.remaining; myUsbDevice.ep3in.remaining -= xferred; myUsbDevice.ep3in.buf += xferred; #endif #if ((SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_INTR)) callback = myUsbDevice.ep3in.misc.bits.callback; #elif (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC) if (myUsbDevice.ep3in.misc.bits.callback == true) { // In Isochronous mode, the meaning of the USBD_XferCompleteCb parameters changes: // xferred is ignored // remaining is the current index into the circular buffer // the return value is the number of bytes to transmit in the next packet xferred = USBD_XferCompleteCb(EP3IN, USB_STATUS_OK, 0, myUsbDevice.ep3inIsoIdx); if (xferred == 0) { myUsbDevice.ep3in.misc.bits.inPacketPending = true; return; } } #endif // Load more data #if ((SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_BULK) || (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_INTR)) if (myUsbDevice.ep3in.remaining > 0) { USB_WriteFIFO(3, (myUsbDevice.ep3in.remaining > SLAB_USB_EP3IN_MAX_PACKET_SIZE) ? SLAB_USB_EP3IN_MAX_PACKET_SIZE : myUsbDevice.ep3in.remaining, myUsbDevice.ep3in.buf, true); } else { myUsbDevice.ep3in.misc.bits.callback = false; myUsbDevice.ep3in.state = D_EP_IDLE; } if (callback == true) { USBD_XferCompleteCb(EP3IN, USB_STATUS_OK, xferred, myUsbDevice.ep3in.remaining); } #elif (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC) nextIdx = xferred + myUsbDevice.ep3inIsoIdx; myUsbDevice.ep3in.misc.bits.inPacketPending = false; // Check if the next index is past the end of the circular buffer. // If so, break the write up into two calls to USB_WriteFIFOIso() if (nextIdx > myUsbDevice.ep3in.remaining) { USB_WriteFIFOIso(3, myUsbDevice.ep3in.remaining - myUsbDevice.ep3inIsoIdx, &myUsbDevice.ep3in.buf[myUsbDevice.ep3inIsoIdx]); myUsbDevice.ep3inIsoIdx = nextIdx - myUsbDevice.ep3in.remaining; USB_WriteFIFOIso(3, myUsbDevice.ep3inIsoIdx, myUsbDevice.ep3in.buf); } else { USB_WriteFIFOIso(3, xferred, &myUsbDevice.ep3in.buf[myUsbDevice.ep3inIsoIdx]); myUsbDevice.ep3inIsoIdx = nextIdx; } #endif // ( ( SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_BULK ) || ( SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_INTR ) ) } }
/***************************************************************************//** * @brief Processes Standard Request (Chapter 9 Command) * @return Status of request (type @ref USB_Status_TypeDef) * @note This function takes no parameters, but it uses the setup command * stored in @ref myUsbDevice.setup. ******************************************************************************/ USB_Status_TypeDef USBDCH9_SetupCmd(void) { USB_Status_TypeDef status = USB_STATUS_OK; switch (myUsbDevice.setup.bRequest) { case GET_STATUS: status = GetStatus(); break; case CLEAR_FEATURE: status = ClearFeature(); break; case SET_FEATURE: status = SetFeature(); break; case SET_ADDRESS: status = SetAddress(); break; case GET_DESCRIPTOR: status = GetDescriptor(); break; case GET_CONFIGURATION: status = GetConfiguration(); break; case SET_CONFIGURATION: status = SetConfiguration(); break; case GET_INTERFACE: status = GetInterface(); break; case SET_INTERFACE: status = SetInterface(); break; // case GET_MS_DESCRIPTOR: // status = HandleMsRequest(); // break; default: status = USB_STATUS_REQ_ERR; break; } // Reset index to 0 in case one of the above commands modified it USB_SetIndex(0); // If the command resulted in an error, send a procedural stall if (status == USB_STATUS_REQ_ERR) { SendEp0Stall(); } return status; }
/***************************************************************************//** * @brief Clears the requested feature * @details Supports CLEAR_FEATURE for Remote Wakeup and Endpoint Halt * @return Status of request (type @ref USB_Status_TypeDef) * @note This function takes no parameters, but it uses the setup command * stored in @ref myUsbDevice.setup. ******************************************************************************/ static USB_Status_TypeDef ClearFeature(void) { USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR; if (myUsbDevice.setup.wLength == 0) { switch (myUsbDevice.setup.bmRequestType.Recipient) { #if SLAB_USB_REMOTE_WAKEUP_ENABLED case USB_SETUP_RECIPIENT_DEVICE: if ((myUsbDevice.setup.wIndex == 0) && (myUsbDevice.setup.wValue == USB_FEATURE_DEVICE_REMOTE_WAKEUP) && (myUsbDevice.state >= USBD_STATE_ADDRESSED)) { // Remote wakeup feature clear myUsbDevice.remoteWakeupEnabled = false; retVal = USB_STATUS_OK; } break; #endif // SLAB_USB_REMOTE_WAKEUP_ENABLED case USB_SETUP_RECIPIENT_ENDPOINT: if (myUsbDevice.setup.wValue == USB_FEATURE_ENDPOINT_HALT) { // Device does not support halting endpoint 0, but do not return // an error as this is a valid request if (((myUsbDevice.setup.wIndex & ~USB_EP_DIR_IN) == 0) && (myUsbDevice.state >= USBD_STATE_ADDRESSED)) { retVal = USB_STATUS_OK; } else if (((myUsbDevice.setup.wIndex & ~USB_SETUP_DIR_D2H) < SLAB_USB_NUM_EPS_USED) && (myUsbDevice.state == USBD_STATE_CONFIGURED)) { retVal = USB_STATUS_OK; USB_SetIndex((myUsbDevice.setup.wIndex & 0xFF) & ~USB_SETUP_DIR_D2H); #if (SLAB_USB_EP1IN_USED || SLAB_USB_EP2IN_USED || SLAB_USB_EP3IN_USED) if ((myUsbDevice.setup.wIndex & 0xFF) & USB_EP_DIR_IN) { USB_EpnInEndStallAndClearDataToggle(); } #endif #if (SLAB_USB_EP1OUT_USED || SLAB_USB_EP2OUT_USED || SLAB_USB_EP3OUT_USED) if (((myUsbDevice.setup.wIndex & 0xFF) & USB_EP_DIR_IN) == 0) { USB_EpnOutEndStallAndClearDataToggle(); } #endif switch (myUsbDevice.setup.wIndex & 0xFF) { #if SLAB_USB_EP1OUT_USED case (USB_EP_DIR_OUT | 1): if (myUsbDevice.ep1out.state != D_EP_RECEIVING) { myUsbDevice.ep1out.state = D_EP_IDLE; } break; #endif #if SLAB_USB_EP2OUT_USED case (USB_EP_DIR_OUT | 2): if (myUsbDevice.ep2out.state != D_EP_RECEIVING) { myUsbDevice.ep2out.state = D_EP_IDLE; } break; #endif #if SLAB_USB_EP3OUT_USED case (USB_EP_DIR_OUT | 3): if (myUsbDevice.ep3out.state != D_EP_RECEIVING) { myUsbDevice.ep3out.state = D_EP_IDLE; } break; #endif #if SLAB_USB_EP1IN_USED case (USB_EP_DIR_IN | 1): if (myUsbDevice.ep1in.state != D_EP_TRANSMITTING) { myUsbDevice.ep1in.state = D_EP_IDLE; } break; #endif #if SLAB_USB_EP2IN_USED case (USB_EP_DIR_IN | 2): if (myUsbDevice.ep2in.state != D_EP_TRANSMITTING) { myUsbDevice.ep2in.state = D_EP_IDLE; } break; #endif #if SLAB_USB_EP3IN_USED case (USB_EP_DIR_IN | 3): if (myUsbDevice.ep3in.state != D_EP_TRANSMITTING) { myUsbDevice.ep3in.state = D_EP_IDLE; } break; #endif } } } } } return retVal; }
void usbIrqHandler(void) #endif { uint8_t statusCommon, statusIn, statusOut, indexSave; #if SLAB_USB_HANDLER_CB // Callback to user before processing USBD_EnterHandler(); #endif // Get the interrupt sources statusCommon = USB_GetCommonInts(); statusIn = USB_GetInInts(); statusOut = USB_GetOutInts(); #if SLAB_USB_POLLED_MODE if ((statusCommon == 0) && (statusIn == 0) && (statusOut == 0)) { return; } #endif // Save the current index indexSave = USB_GetIndex(); // Check Common USB Interrupts if (USB_IsSofIntActive(statusCommon)) { #if SLAB_USB_SOF_CB USBD_SofCb(USB_GetSofNumber()); #endif // SLAB_USB_SOF_CB // Check for unhandled USB packets on EP0 and set the corresponding IN or // OUT interrupt active flag if necessary. if (((myUsbDevice.ep0.misc.bits.outPacketPending == true) && (myUsbDevice.ep0.state == D_EP_RECEIVING)) || ((myUsbDevice.ep0.misc.bits.inPacketPending == true) && (myUsbDevice.ep0.state == D_EP_TRANSMITTING))) { USB_SetEp0IntActive(statusIn); } // Check for unhandled USB OUT packets and set the corresponding OUT // interrupt active flag if necessary. #if SLAB_USB_EP1OUT_USED if ((myUsbDevice.ep1out.misc.bits.outPacketPending == true) && (myUsbDevice.ep1out.state == D_EP_RECEIVING)) { USB_SetOut1IntActive(statusOut); } #endif #if SLAB_USB_EP2OUT_USED if ((myUsbDevice.ep2out.misc.bits.outPacketPending == true) && (myUsbDevice.ep2out.state == D_EP_RECEIVING)) { USB_SetOut2IntActive(statusOut); } #endif #if SLAB_USB_EP3OUT_USED if ((myUsbDevice.ep3out.misc.bits.outPacketPending == true) && (myUsbDevice.ep3out.state == D_EP_RECEIVING)) { USB_SetOut3IntActive(statusOut); } #endif #if (SLAB_USB_EP3IN_USED && (SLAB_USB_EP3IN_TRANSFER_TYPE == USB_EPTYPE_ISOC)) if ((myUsbDevice.ep3in.misc.bits.inPacketPending == true) && (myUsbDevice.ep3in.state == D_EP_TRANSMITTING)) { USB_SetIn3IntActive(statusIn); } #endif } if (USB_IsResetIntActive(statusCommon)) { handleUsbResetInt(); // If VBUS is not present on detection of a USB reset, enter suspend mode. #if (SLAB_USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF) if (USB_IsVbusOn() == false) { USB_SetSuspendIntActive(statusCommon); } #endif } if (USB_IsResumeIntActive(statusCommon)) { handleUsbResumeInt(); } if (USB_IsSuspendIntActive(statusCommon)) { handleUsbSuspendInt(); } #if SLAB_USB_EP3IN_USED if (USB_IsIn3IntActive(statusIn)) { handleUsbIn3Int(); } #endif // EP3IN_USED #if SLAB_USB_EP3OUT_USED if (USB_IsOut3IntActive(statusOut)) { handleUsbOut3Int(); } #endif // EP3OUT_USED #if SLAB_USB_EP2IN_USED if (USB_IsIn2IntActive(statusIn)) { handleUsbIn2Int(); } #endif // EP2IN_USED #if SLAB_USB_EP1IN_USED if (USB_IsIn1IntActive(statusIn)) { handleUsbIn1Int(); } #endif // EP1IN_USED #if SLAB_USB_EP2OUT_USED if (USB_IsOut2IntActive(statusOut)) { handleUsbOut2Int(); } #endif // EP2OUT_USED #if SLAB_USB_EP1OUT_USED if (USB_IsOut1IntActive(statusOut)) { handleUsbOut1Int(); } #endif // EP1OUT_USED // Check USB Endpoint 0 Interrupt if (USB_IsEp0IntActive(statusIn)) { handleUsbEp0Int(); } // Restore index USB_SetIndex(indexSave); #if SLAB_USB_HANDLER_CB // Callback to user before exiting USBD_ExitHandler(); #endif }
/***************************************************************************//** * @brief Send a procedural stall on Endpoint 0 ******************************************************************************/ void SendEp0Stall(void) { USB_SetIndex(0); myUsbDevice.ep0.state = D_EP_STALL; USB_Ep0SendStall(); }
/***************************************************************************//** * @brief Handles Endpoint 0 transfer interrupt ******************************************************************************/ static void handleUsbEp0Int(void) { USB_SetIndex(0); if (USB_Ep0SentStall() || USB_GetSetupEnd()) { USB_Ep0ClearSentStall(); USB_ServicedSetupEnd(); myUsbDevice.ep0.state = D_EP_IDLE; myUsbDevice.ep0.misc.c = 0; } if (USB_Ep0OutPacketReady()) { if (myUsbDevice.ep0.misc.bits.waitForRead == true) { myUsbDevice.ep0.misc.bits.outPacketPending = true; } else if (myUsbDevice.ep0.state == D_EP_IDLE) { myUsbDevice.ep0String.c = USB_STRING_DESCRIPTOR_UTF16LE; USB_ReadFIFOSetup(); // Vendor unique, Class or Standard setup commands override? #if SLAB_USB_SETUP_CMD_CB if (USBD_SetupCmdCb(&myUsbDevice.setup) == USB_STATUS_REQ_UNHANDLED) { #endif if (myUsbDevice.setup.bmRequestType.Type == USB_SETUP_TYPE_STANDARD) { USBDCH9_SetupCmd(); } else { SendEp0Stall(); } #if SLAB_USB_SETUP_CMD_CB } else { // If in-packet but callback didn't setup a USBD_Read and we are expecting a data byte then // we need to wait for the read to be setup and nack packets till USBD_Read is called. if ((myUsbDevice.setup.bmRequestType.Direction == USB_SETUP_DIR_OUT) && (myUsbDevice.ep0.state != D_EP_RECEIVING) && (myUsbDevice.setup.wLength) ) { myUsbDevice.ep0.misc.bits.waitForRead = true; } } #endif } else if (myUsbDevice.ep0.state == D_EP_RECEIVING) { handleUsbEp0Rx(); } else { myUsbDevice.ep0.misc.bits.outPacketPending = true; } } if ((myUsbDevice.ep0.state == D_EP_TRANSMITTING) && (USB_Ep0InPacketReady() == 0)) { handleUsbEp0Tx(); } }
int8_t USBD_UnStallEp(uint8_t epAddr) { bool usbIntsEnabled; USB_SaveSfrPage(); // Verify the endpoint address is valid and not Endpoint 0. if ((epAddr == EP0) || (epAddr >= SLAB_USB_NUM_EPS_USED)) { SLAB_ASSERT(false); return USB_STATUS_ILLEGAL; } else { DISABLE_USB_INTS; // End the stall condition and set the endpoint state to idle. switch (epAddr) { #if SLAB_USB_EP1IN_USED case (EP1IN): myUsbDevice.ep1in.state = D_EP_IDLE; USB_SetIndex(1); USB_EpnInEndStall(); break; #endif #if SLAB_USB_EP2IN_USED case (EP2IN): myUsbDevice.ep2in.state = D_EP_IDLE; USB_SetIndex(2); USB_EpnInEndStall(); break; #endif #if SLAB_USB_EP3IN_USED case (EP3IN): myUsbDevice.ep3in.state = D_EP_IDLE; USB_SetIndex(3); USB_EpnInEndStall(); break; #endif #if SLAB_USB_EP1OUT_USED case (EP1OUT): myUsbDevice.ep1out.state = D_EP_IDLE; USB_SetIndex(1); USB_EpnOutEndStall(); break; #endif #if SLAB_USB_EP2OUT_USED case (EP2OUT): myUsbDevice.ep2out.state = D_EP_IDLE; USB_SetIndex(2); USB_EpnOutEndStall(); break; #endif #if SLAB_USB_EP3OUT_USED case (EP3OUT): myUsbDevice.ep3out.state = D_EP_IDLE; USB_SetIndex(3); USB_EpnOutEndStall(); break; #endif } ENABLE_USB_INTS; USB_RestoreSfrPage(); } return USB_STATUS_OK; }
int8_t USBD_StallEp(uint8_t epAddr) { bool usbIntsEnabled; USB_SaveSfrPage(); // Verify the endpoint address is valid and not Endpoint 0. if ((epAddr == EP0) || (epAddr >= SLAB_USB_NUM_EPS_USED)) { SLAB_ASSERT(false); return USB_STATUS_ILLEGAL; } DISABLE_USB_INTS; // Halt the appropriate endpoint by sending a stall and setting the endpoint // state to Halted (D_EP_HALT). switch (epAddr) { #if SLAB_USB_EP1IN_USED case (EP1IN): myUsbDevice.ep1in.state = D_EP_HALT; USB_SetIndex(1); USB_EpnInStall(); break; #endif #if SLAB_USB_EP2IN_USED case (EP2IN): myUsbDevice.ep2in.state = D_EP_HALT; USB_SetIndex(2); USB_EpnInStall(); break; #endif #if SLAB_USB_EP3IN_USED case (EP3IN): myUsbDevice.ep3in.state = D_EP_HALT; USB_SetIndex(3); USB_EpnInStall(); break; #endif #if SLAB_USB_EP1OUT_USED case (EP1OUT): myUsbDevice.ep1out.state = D_EP_HALT; USB_SetIndex(1); USB_EpnOutStall(); break; #endif #if SLAB_USB_EP2OUT_USED case (EP2OUT): myUsbDevice.ep2out.state = D_EP_HALT; USB_SetIndex(2); USB_EpnOutStall(); break; #endif #if SLAB_USB_EP3OUT_USED case (EP3OUT): myUsbDevice.ep3out.state = D_EP_HALT; USB_SetIndex(3); USB_EpnOutStall(); break; #endif } ENABLE_USB_INTS; USB_RestoreSfrPage(); return USB_STATUS_OK; }
void USB_AbortOutEp(uint8_t fifoNum) { USB_SetIndex(fifoNum); USB_EpnOutFlush(); USB_EpnOutFlush(); }
void USB_AbortInEp(uint8_t fifoNum) { USB_SetIndex(fifoNum); USB_EpnInFlush(); USB_EpnInFlush(); }