/******************************************************************************* * Function Name : Post0_Process * Description : Stall the Endpoint 0 in case of error. * Input : None. * Output : None. * Return : - 0 if the control State is in PAUSE * - 1 if not. *******************************************************************************/ uint8_t Post0_Process(void) { #ifdef STM32F10X_CL USB_OTG_EP* ep; #endif /* STM32F10X_CL */ SetEPRxCount(ENDP0, Device_Property.MaxPacketSize); if(pInformation->ControlState == STALLED) { vSetEPRxStatus(EP_RX_STALL); vSetEPTxStatus(EP_TX_STALL); } #ifdef STM32F10X_CL else if((pInformation->ControlState == OUT_DATA) || (pInformation->ControlState == WAIT_STATUS_OUT)) { ep = PCD_GetInEP(0); ep->is_in = 0; OTGD_FS_EP0StartXfer(ep); vSetEPTxStatus(EP_TX_VALID); } else if((pInformation->ControlState == IN_DATA) || (pInformation->ControlState == WAIT_STATUS_IN)) { ep = PCD_GetInEP(0); ep->is_in = 1; OTGD_FS_EP0StartXfer(ep); } #endif /* STM32F10X_CL */ return (pInformation->ControlState == PAUSE); }
/******************************************************************************* * Function Name : USBF_EP_Write * Description : Read data from Fifo * Input : ep * Output : None * Return : status *******************************************************************************/ uint32_t PCD_EP_Write (uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len) { USB_OTG_EP *ep; ep = PCD_GetInEP(ep_addr & 0x7f); /* assign data to EP structure buffer */ ep->xfer_buff = pbuf; /* Setup and start the Transfer */ ep->xfer_count = 0; ep->xfer_len = buf_len; ep->is_in = 1; ep->num = ep_addr & 0x7F; if ( ep->num == 0 ) { OTGD_FS_EP0StartXfer(ep); } else { OTGD_FS_EPStartXfer( ep ); } return 0; }
/******************************************************************************* * Function Name : PCD_EP_Open * Description : Configure an Endpoint * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t PCD_EP_Open(EP_DESCRIPTOR *epdesc) { USB_OTG_EP *ep; if ((0x80 & epdesc->bEndpointAddress) != 0) { ep = PCD_GetInEP(epdesc->bEndpointAddress & 0x7F); ep->is_in = 1; } else { ep = PCD_GetOutEP(epdesc->bEndpointAddress & 0x7F); ep->is_in = 0; } ep->num = epdesc->bEndpointAddress & 0x7F; ep->maxpacket = epdesc->wMaxPacketSize; ep->type = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; if (ep->is_in) { /* Assign a Tx FIFO */ ep->tx_fifo_num = ep->num; } OTGD_FS_EPActivate(ep ); return 0; }
/******************************************************************************* * Function Name : PCD_WriteEmptyTxFifo * Description : Checks Fifo for the next packet to be loaded. * Input : None * Output : None * Return : Status *******************************************************************************/ static uint32_t PCD_WriteEmptyTxFifo(uint32_t epnum) { USB_OTG_DTXFSTS_TypeDef txstatus; USB_OTG_EP *ep; uint32_t len = 0; uint32_t dwords = 0; uint32_t fifoemptymsk = 0; txstatus.d32 = 0; ep = PCD_GetInEP(epnum); len = ep->xfer_len - ep->xfer_count; if (len > ep->maxpacket) { len = ep->maxpacket; } dwords = (len + 3) / 4; txstatus.d32 = USB_OTG_READ_REG32( &USB_OTG_FS_regs.DINEPS[epnum]->DTXFSTSx); while ((txstatus.b.txfspcavail > dwords) && (ep->xfer_count < ep->xfer_len) && (ep->xfer_len) != 0) { len = ep->xfer_len - ep->xfer_count; if (len > ep->maxpacket) { len = ep->maxpacket; } dwords = (len + 3) / 4; OTGD_FS_WritePacket(ep->xfer_buff, epnum, len); ep->xfer_count += len; ep->xfer_buff += len; txstatus.d32 = USB_OTG_READ_REG32(&USB_OTG_FS_regs.DINEPS[epnum]->DTXFSTSx); /* Mask the TxFIFOEmpty interrupt to prevent re-entring this routine */ if (ep->xfer_len == ep->xfer_count) { fifoemptymsk = 0x1 << ep->num; USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DIEPEMPMSK, fifoemptymsk, 0); } } return 1; }
/******************************************************************************* * Function Name : PCD_EP_Stall * Description : Stall an endpoint. * Input : Endpoint Address. * Output : None * Return : status *******************************************************************************/ uint32_t PCD_EP_Stall (uint8_t ep_addr) { USB_OTG_EP *ep; if ((0x80 & ep_addr) != 0) { ep = PCD_GetInEP(ep_addr & 0x7F); } else { ep = PCD_GetOutEP(ep_addr & 0x7F); } ep->num = ep_addr & 0x7F; ep->is_in = ((ep_addr & 0x80) == 0x80) ? 1 : 0; OTGD_FS_EPSetStall(ep); return (0); }
/******************************************************************************* * Function Name : PCD_EP_Close * Description : Called when an EP is disabled * Input : Endpoint address. * Output : None * Return : status *******************************************************************************/ uint32_t PCD_EP_Close(uint8_t ep_addr) { USB_OTG_EP *ep; if ((0x80 & ep_addr) != 0) { ep = PCD_GetInEP(ep_addr & 0x7F); } else { ep = PCD_GetOutEP(ep_addr & 0x7F); } ep->num = ep_addr & 0x7F; ep->is_in = (0x80 & ep_addr) != 0; OTGD_FS_EPDeactivate(ep ); return 0; }
/******************************************************************************* * Function Name : OTGD_FS_Handle_InEP_ISR * Description : Handles all IN endpoints interrupts. * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_InEP_ISR(void) { USB_OTG_DIEPINTx_TypeDef diepint; uint32_t ep_intr = 0; uint32_t epnum = 0; USB_OTG_EP *ep; uint32_t fifoemptymsk = 0; diepint.d32 = 0; ep_intr = OTGD_FS_ReadDevAllInEPItr(); while ( ep_intr ) { if (ep_intr&0x1) /* In ITR */ { ep = PCD_GetInEP(epnum); diepint.d32 = PCD_ReadDevInEP(ep); /* Get In ITR status */ if ( diepint.b.xfercompl ) { fifoemptymsk = 0x1 << ep->num; USB_OTG_MODIFY_REG32(&USB_OTG_FS_regs.DEV->DIEPEMPMSK, fifoemptymsk, 0); /* Clear the Interrupt flag */ CLEAR_IN_EP_INTR(epnum, xfercompl); if (epnum == 0) { /* Call the core IN process for EP0 */ In0_Process(); /* before terminate set Tx & Rx status */ OTG_DEV_SetEPRxStatus(epnum, SaveRState); OTG_DEV_SetEPTxStatus(epnum, SaveTState); } else { /* Call the relative IN endpoint callback */ (*pEpInt_IN[epnum -1])(); } } if ( diepint.b.timeout ) { CLEAR_IN_EP_INTR(epnum, timeout); } if (diepint.b.intktxfemp) { CLEAR_IN_EP_INTR(epnum, intktxfemp); } if (diepint.b.inepnakeff) { CLEAR_IN_EP_INTR(epnum, inepnakeff); } if (diepint.b.txfempty) { if ((epnum == 0) || (OTG_DEV_GetEPTxStatus(epnum) == DEV_EP_TX_VALID)) { PCD_WriteEmptyTxFifo(epnum); } CLEAR_IN_EP_INTR(epnum, txfempty); } if ( diepint.b.epdis) { /* Reset Endpoint Frame ID to 0 */ ep->even_odd_frame = 0; CLEAR_IN_EP_INTR(epnum, epdis); } } epnum++; ep_intr >>= 1; } /* Call user function */ INTR_INEPINTR_Callback(); return 1; }