/** * @brief Deactivate an endpoint * @param hpcd: PCD handle * @param ep_addr: endpoint address * @retval HAL status */ HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef * hpcd, uint8_t ep_addr) { PCD_EPTypeDef *ep; if ((ep_addr & 0x80) == 0x80) { ep = &hpcd->IN_ep[ep_addr & 0x7F]; } else { ep = &hpcd->OUT_ep[ep_addr & 0x7F]; } ep->num = ep_addr & 0x7F; ep->is_in = (0x80 & ep_addr) != 0; __HAL_LOCK(hpcd); if (ep->doublebuffer == 0) { if (ep->is_in) { PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num); /* Configure DISABLE status for the Endpoint */ PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS); } else { PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num); /* Configure DISABLE status for the Endpoint */ PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_DIS); } } /*Double Buffer */ else { if (ep->is_in == 0) { /* Clear the data toggle bits for the endpoint IN/OUT */ PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num); PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num); /* Reset value of the data toggle bits for the endpoint out */ PCD_TX_DTOG(hpcd->Instance, ep->num); PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_DIS); PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS); } else { /* Clear the data toggle bits for the endpoint IN/OUT */ PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num); PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num); PCD_RX_DTOG(hpcd->Instance, ep->num); /* Configure DISABLE status for the Endpoint */ PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS); PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_DIS); } } __HAL_UNLOCK(hpcd); return HAL_OK; }
/** * @brief Clear a STALL condition over in an endpoint * @param hpcd: PCD handle * @param ep_addr: endpoint address * @retval HAL status */ HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr) { PCD_EPTypeDef *ep; if ((0x80 & ep_addr) == 0x80) { ep = &hpcd->IN_ep[ep_addr & 0x7F]; } else { ep = &hpcd->OUT_ep[ep_addr]; } ep->is_stall = 0; ep->num = ep_addr & 0x7F; ep->is_in = ((ep_addr & 0x80) == 0x80); __HAL_LOCK(hpcd); if (ep->is_in) { PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num); PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID); } else { PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num); PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID); } __HAL_UNLOCK(hpcd); return HAL_OK; }
/** * @brief Send an amount of data * @param hpcd: PCD handle * @param ep_addr: endpoint address * @param pBuf: pointer to the transmission buffer * @param len: amount of data to be sent * @retval HAL status */ HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len) { PCD_EPTypeDef *ep; uint16_t pmabuffer = 0; ep = &hpcd->IN_ep[ep_addr & 0x7F]; /*setup and start the Xfer */ ep->xfer_buff = pBuf; ep->xfer_len = len; ep->xfer_count = 0; ep->is_in = 1; ep->num = ep_addr & 0x7F; __HAL_LOCK(hpcd); /*Multi packet transfer*/ if (ep->xfer_len > ep->maxpacket) { len=ep->maxpacket; ep->xfer_len-=len; } else { len=ep->xfer_len; ep->xfer_len =0; } /* configure and validate Tx endpoint */ if (ep->doublebuffer == 0) { PCD_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, len); PCD_SET_EP_TX_CNT(hpcd->Instance, ep->num, len); } else { /*Write the data to the USB endpoint*/ if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num)& USB_EP_DTOG_TX) { /*Set the Double buffer counter for pmabuffer1*/ PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len); pmabuffer = ep->pmaaddr1; } else { /*Set the Double buffer counter for pmabuffer0*/ PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len); pmabuffer = ep->pmaaddr0; } PCD_WritePMA(hpcd->Instance, ep->xfer_buff, pmabuffer, len); PCD_FreeUserBuffer(hpcd->Instance, ep->num, ep->is_in); } PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID); __HAL_UNLOCK(hpcd); return HAL_OK; }
/** * @brief Set a STALL condition over an endpoint * @param hpcd: PCD handle * @param ep_addr: endpoint address * @retval HAL status */ HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef * hpcd, uint8_t ep_addr) { PCD_EPTypeDef *ep; __HAL_LOCK(hpcd); if ((0x80 & ep_addr) == 0x80) { ep = &hpcd->IN_ep[ep_addr & 0x7F]; } else { ep = &hpcd->OUT_ep[ep_addr]; } ep->is_stall = 1; ep->num = ep_addr & 0x7F; ep->is_in = ((ep_addr & 0x80) == 0x80); if (ep->num == 0) { /* This macro sets STALL status for RX & TX */ PCD_SET_EP_TXRX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_STALL, USB_EP_TX_STALL); } else { if (ep->is_in) { PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_STALL); } else { PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_STALL); } } __HAL_UNLOCK(hpcd); return HAL_OK; }
/** * @brief Open and configure an endpoint * @param hpcd: PCD handle * @param ep_addr: endpoint address * @param ep_mps: endpoint max packert size * @param ep_type: endpoint type * @retval HAL status */ HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type) { HAL_StatusTypeDef ret = HAL_OK; PCD_EPTypeDef *ep; if ((ep_addr & 0x80) == 0x80) { ep = &hpcd->IN_ep[ep_addr & 0x7F]; } else { ep = &hpcd->OUT_ep[ep_addr & 0x7F]; } ep->num = ep_addr & 0x7F; ep->is_in = (0x80 & ep_addr) != 0; ep->maxpacket = ep_mps; ep->type = ep_type; __HAL_LOCK(hpcd); /* initialize Endpoint */ switch (ep->type) { case PCD_EP_TYPE_CTRL: PCD_SET_EPTYPE(hpcd->Instance, ep->num, USB_EP_CONTROL); break; case PCD_EP_TYPE_BULK: PCD_SET_EPTYPE(hpcd->Instance, ep->num, USB_EP_BULK); break; case PCD_EP_TYPE_INTR: PCD_SET_EPTYPE(hpcd->Instance, ep->num, USB_EP_INTERRUPT); break; case PCD_EP_TYPE_ISOC: PCD_SET_EPTYPE(hpcd->Instance, ep->num, USB_EP_ISOCHRONOUS); break; } PCD_SET_EP_ADDRESS(hpcd->Instance, ep->num, ep->num); if (ep->doublebuffer == 0) { if (ep->is_in) { /*Set the endpoint Transmit buffer address */ PCD_SET_EP_TX_ADDRESS(hpcd->Instance, ep->num, ep->pmaadress); PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num); /* Configure NAK status for the Endpoint*/ PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_NAK); } else { /*Set the endpoint Receive buffer address */ PCD_SET_EP_RX_ADDRESS(hpcd->Instance, ep->num, ep->pmaadress); /*Set the endpoint Receive buffer counter*/ PCD_SET_EP_RX_CNT(hpcd->Instance, ep->num, ep->maxpacket); PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num); /* Configure VALID status for the Endpoint*/ PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID); } } /*Double Buffer*/ else { /*Set the endpoint as double buffered*/ PCD_SET_EP_DBUF(hpcd->Instance, ep->num); /*Set buffer address for double buffered mode*/ PCD_SET_EP_DBUF_ADDR(hpcd->Instance, ep->num,ep->pmaaddr0, ep->pmaaddr1); if (ep->is_in==0) { /* Clear the data toggle bits for the endpoint IN/OUT*/ PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num); PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num); /* Reset value of the data toggle bits for the endpoint out*/ PCD_TX_DTOG(hpcd->Instance, ep->num); PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_VALID); PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS); } else { /* Clear the data toggle bits for the endpoint IN/OUT*/ PCD_CLEAR_RX_DTOG(hpcd->Instance, ep->num); PCD_CLEAR_TX_DTOG(hpcd->Instance, ep->num); PCD_RX_DTOG(hpcd->Instance, ep->num); /* Configure DISABLE status for the Endpoint*/ PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_DIS); PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_DIS); } } __HAL_UNLOCK(hpcd); return ret; }