/******************************************************************************* * Function Name : USB_SIL_Read * Description : Write a buffer of data to a selected endpoint. * Input : - bEpAddr: The address of the non control endpoint. * - pBufferPointer: The pointer to which will be saved the * received data buffer. * Output : None. * Return : Number of received data (in Bytes). *******************************************************************************/ uint32_t USB_SIL_Read(uint8_t bEpAddr, uint8_t* pBufferPointer) { uint32_t DataLength = 0; #ifndef STM32F10X_CL /* Get the number of received data on the selected Endpoint */ DataLength = GetEPRxCount(bEpAddr & 0x7F); /* Use the memory interface function to write to the selected endpoint */ PMAToUserBufferCopy(pBufferPointer, GetEPRxAddr(bEpAddr & 0x7F), DataLength); #else USB_OTG_EP *ep; /* Get the structure pointer of the selected Endpoint */ ep = PCD_GetOutEP(bEpAddr); /* Get the number of received data */ DataLength = ep->xfer_len; /* Use the PCD interface layer function to read the selected endpoint */ PCD_EP_Read (bEpAddr, pBufferPointer, DataLength); #endif /* STM32F10X_CL */ /* Return the number of received data */ return DataLength; }
/******************************************************************************* * Function Name : PCD_EP_Read * Description : Read data from Fifo * Input : Endpoint address. * Output : None * Return : status *******************************************************************************/ uint32_t PCD_EP_Read (uint8_t ep_addr, uint8_t *pbuf, uint32_t buf_len) { USB_OTG_EP *ep; uint32_t i = 0; ep = PCD_GetOutEP(ep_addr & 0x7F); /* copy received data into application buffer */ for (i = 0 ; i < buf_len ; i++) { pbuf[i] = ep->xfer_buff[i]; } /*setup and start the Xfer */ ep->xfer_buff = pbuf; ep->xfer_len = buf_len; ep->xfer_count = 0; ep->is_in = 0; 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 : EP1_OUT_Callback * Description : Endpoint 1 out callback routine. * Input : None. * Output : None. * Return : None. *******************************************************************************/ void EP1_OUT_Callback(void) { DMA_InitTypeDef DMA_InitStructure; #ifdef USE_STM3210C_EVAL /* Get the Endpoint descriptor pointer */ ep = PCD_GetOutEP(ENDP1 & 0x7F); /* Enable the Endpoint transfer (since the the Read Endpoint function is not called) */ OTGD_FS_EPStartXfer(ep); /* Toggle the data PID */ if (ep->even_odd_frame != 0) { ep->even_odd_frame = 0; } else { ep->even_odd_frame = 1; } /* If Half of global buffer has been filled and DMA is still not enabled, Re-configure the DMA and unMute the codec */ #if (NUM_SUB_BUFFERS == 2) if (((DMA1_Channel5->CCR & 0x1) == 0) && (IsocBufferIdx == 1)) #else if (((DMA1_Channel5->CCR & 0x1) == 0) && (IsocBufferIdx == ((NUM_SUB_BUFFERS / 2) - 1))) #endif /* NUM_SUB_BUFFERS */ { /* Disable the mute mode */ CODEC_Mute(MUTE_OFF); /* Disable the I2S before starting configuration to avoid spurious transfer */ SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_TXE, DISABLE); I2S_Cmd(SPI2, DISABLE); /* Initialize the DMA1 Channel5 to its default values */ DMA_DeInit(DMA1_Channel5); /* Configure the DMA parameters */ DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)((uint16_t*)IsocBuff); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPI2_DR_Address; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = (ISOC_BUFFER_SZE * NUM_SUB_BUFFERS) / 2; /* Divided by 2 because USB data are 8 bit and I2S buffer is 16 bit */ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel5, &DMA_InitStructure); } #endif /* USE_STM3210C_EVAL */ }
/******************************************************************************* * Function Name : Setup0_Process * Description : Get the device request data and dispatch to individual process. * Input : None. * Output : None. * Return : Post0_Process. *******************************************************************************/ uint8_t Setup0_Process(void) { union { uint8_t* b; uint16_t* w; } pBuf; #ifdef STM32F10X_CL USB_OTG_EP *ep; uint16_t offset = 0; ep = PCD_GetOutEP(ENDP0); pBuf.b = ep->xfer_buff; OTGD_FS_EP0StartXfer(ep); #else uint16_t offset = 1; pBuf.b = PMAAddr + (uint8_t *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */ #endif /* STM32F10X_CL */ if (pInformation->ControlState != PAUSE) { pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */ pInformation->USBbRequest = *pBuf.b++; /* bRequest */ pBuf.w += offset; /* word not accessed because of 32 bits addressing */ pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */ pBuf.w += offset; /* word not accessed because of 32 bits addressing */ pInformation->USBwIndex = ByteSwap(*pBuf.w++); /* wIndex */ pBuf.w += offset; /* word not accessed because of 32 bits addressing */ pInformation->USBwLength = *pBuf.w; /* wLength */ } pInformation->ControlState = SETTING_UP; if (pInformation->USBwLength == 0) { /* Setup with no data stage */ NoData_Setup0(); } else { /* Setup with data stage */ Data_Setup0(); } return Post0_Process(); }
/******************************************************************************* * 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_RxStatusQueueLevel_ISR * Description : Handles the Rx Status Queue Level Interrupt. * Input : None * Output : None * Return : status *******************************************************************************/ uint32_t OTGD_FS_Handle_RxStatusQueueLevel_ISR(void) { USB_OTG_GINTMSK_TypeDef int_mask; USB_OTG_GRXSTSP_TypeDef status; USB_OTG_EP *ep; int_mask.d32 = 0; status.d32 = 0; /* Disable the Rx Status Queue Level interrupt */ int_mask.b.rxstsqlvl = 1; USB_OTG_MODIFY_REG32( &USB_OTG_FS_regs.GREGS->GINTMSK, int_mask.d32, 0); /* Get the Status from the top of the FIFO */ status.d32 = USB_OTG_READ_REG32( &USB_OTG_FS_regs.GREGS->GRXSTSP ); /* Get the related endpoint structure */ ep = PCD_GetOutEP(status.b.epnum); switch (status.b.pktsts) { case STS_GOUT_NAK: break; case STS_DATA_UPDT: if (status.b.bcnt) { if (ep->type == EP_TYPE_ISOC) { /* Call user function */ INTR_RXSTSQLVL_ISODU_Callback(); /* Copy the received buffer to the RAM */ OTGD_FS_ReadPacket((uint8_t*)(IsocBuff + (ISOC_BUFFER_SZE * IsocBufferIdx)), status.b.bcnt); ep->xfer_buff = (uint8_t*)(IsocBuff + (ISOC_BUFFER_SZE * IsocBufferIdx)); /* Check if the end of the global buffer has been reached */ if (IsocBufferIdx == (NUM_SUB_BUFFERS - 1)) { /* Reset the buffer index */ IsocBufferIdx = 0; } else { /* Increment the buffer index */ IsocBufferIdx ++; } } else { /* Copy the received buffer to the RAM */ OTGD_FS_ReadPacket(USBD_Data_Buffer, status.b.bcnt); ep->xfer_buff = USBD_Data_Buffer; } /* Update the endpoint structure */ ep->xfer_len = status.b.bcnt; ep->xfer_count += status.b.bcnt; } else { ep->xfer_len = status.b.bcnt; } break; case STS_XFER_COMP: break; case STS_SETUP_COMP: break; case STS_SETUP_UPDT: /* Copy the setup packet received in Fifo into the setup buffer in RAM */ OTGD_FS_ReadPacket(USBD_Data_Buffer, 8); ep->xfer_buff = USBD_Data_Buffer; ep->xfer_count += status.b.bcnt; ep->xfer_len = status.b.bcnt; break; default: break; } /* Call the user function */ INTR_RXSTSQLVL_Callback(); /* Enable the Rx Status Queue Level interrupt */ USB_OTG_MODIFY_REG32( &USB_OTG_FS_regs.GREGS->GINTMSK, 0, int_mask.d32); /* Clear interrupt: this is a read only bit, it cannot be cleared by register access */ return 1; }
/******************************************************************************* * Function Name : OTGD_FS_Handle_OutEP_ISR * Description : Handles all OUT endpoints interrupts. * Input : None * Output : None * Return : Status *******************************************************************************/ uint32_t OTGD_FS_Handle_OutEP_ISR(void) { uint32_t ep_intr = 0; USB_OTG_DOEPINTx_TypeDef doepint; uint32_t epnum = 0; USB_OTG_EP *ep; doepint.d32 = 0; /* Read in the device interrupt bits */ ep_intr = OTGD_FS_ReadDevAllOutEp_itr(); while ( ep_intr ) { if (ep_intr&0x1) { /* Get EP pointer */ ep = PCD_GetOutEP(epnum); doepint.d32 = OTGD_FS_ReadDevOutEP_itr(ep); /* Transfer complete */ if ( doepint.b.xfercompl ) { /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(epnum, xfercompl); if (epnum == 0) { /* Call the OUT process for the EP0 */ Out0_Process(); } else { (*pEpInt_OUT[epnum-1])(); } } /* Endpoint disable */ if ( doepint.b.epdis) { /* Clear the bit in DOEPINTn for this interrupt */ CLEAR_OUT_EP_INTR(epnum, epdis); } /* Setup Phase Done (control EPs) */ if ( doepint.b.setup ) { if (epnum == 0) { /* Call the SETUP process for the EP0 */ Setup0_Process(); /* Before exit, update the Tx status */ OTG_DEV_SetEPTxStatus(0x80, SaveTState); } else { /* Other control endpoints */ } /* Clear the EP Interrupt */ CLEAR_OUT_EP_INTR(epnum, setup); } /* Back to back setup received */ if ( doepint.b.b2bsetup ) { if (epnum == 0) { /* Call the SETUP process for the EP0 */ Setup0_Process(); /* Before exit, update the Tx status */ OTG_DEV_SetEPTxStatus(0x80, SaveTState); } } } epnum++; ep_intr >>= 1; } /* Call user function */ INTR_OUTEPINTR_Callback(); return 1; }