479 lines
9.7 KiB
C
479 lines
9.7 KiB
C
|
/**
|
||
|
******************************************************************************
|
||
|
* @file usb_dcd.c
|
||
|
* @author MCD Application Team
|
||
|
* @version V2.1.0
|
||
|
* @date 19-March-2012
|
||
|
* @brief Peripheral Device Interface Layer
|
||
|
******************************************************************************
|
||
|
* @attention
|
||
|
*
|
||
|
* <h2><center>© COPYRIGHT 2012 STMicroelectronics</center></h2>
|
||
|
*
|
||
|
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||
|
* You may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at:
|
||
|
*
|
||
|
* http://www.st.com/software_license_agreement_liberty_v2
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*
|
||
|
******************************************************************************
|
||
|
*/
|
||
|
|
||
|
/* Includes ------------------------------------------------------------------*/
|
||
|
#include "usb_dcd.h"
|
||
|
#include "usb_bsp.h"
|
||
|
|
||
|
|
||
|
/** @addtogroup USB_OTG_DRIVER
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/** @defgroup USB_DCD
|
||
|
* @brief This file is the interface between EFSL ans Host mass-storage class
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USB_DCD_Private_Defines
|
||
|
* @{
|
||
|
*/
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USB_DCD_Private_TypesDefinitions
|
||
|
* @{
|
||
|
*/
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
/** @defgroup USB_DCD_Private_Macros
|
||
|
* @{
|
||
|
*/
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USB_DCD_Private_Variables
|
||
|
* @{
|
||
|
*/
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USB_DCD_Private_FunctionPrototypes
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
|
||
|
/** @defgroup USB_DCD_Private_Functions
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
|
||
|
|
||
|
void DCD_Init(USB_OTG_CORE_HANDLE *pdev ,
|
||
|
USB_OTG_CORE_ID_TypeDef coreID)
|
||
|
{
|
||
|
uint32_t i;
|
||
|
USB_OTG_EP *ep;
|
||
|
|
||
|
USB_OTG_SelectCore (pdev , coreID);
|
||
|
|
||
|
pdev->dev.device_status = USB_OTG_DEFAULT;
|
||
|
pdev->dev.device_address = 0;
|
||
|
|
||
|
/* Init ep structure */
|
||
|
for (i = 0; i < pdev->cfg.dev_endpoints ; i++)
|
||
|
{
|
||
|
ep = &pdev->dev.in_ep[i];
|
||
|
/* Init ep structure */
|
||
|
ep->is_in = 1;
|
||
|
ep->num = i;
|
||
|
ep->tx_fifo_num = i;
|
||
|
/* Control until ep is actvated */
|
||
|
ep->type = EP_TYPE_CTRL;
|
||
|
ep->maxpacket = USB_OTG_MAX_EP0_SIZE;
|
||
|
ep->xfer_buff = 0;
|
||
|
ep->xfer_len = 0;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < pdev->cfg.dev_endpoints; i++)
|
||
|
{
|
||
|
ep = &pdev->dev.out_ep[i];
|
||
|
/* Init ep structure */
|
||
|
ep->is_in = 0;
|
||
|
ep->num = i;
|
||
|
ep->tx_fifo_num = i;
|
||
|
/* Control until ep is activated */
|
||
|
ep->type = EP_TYPE_CTRL;
|
||
|
ep->maxpacket = USB_OTG_MAX_EP0_SIZE;
|
||
|
ep->xfer_buff = 0;
|
||
|
ep->xfer_len = 0;
|
||
|
}
|
||
|
|
||
|
USB_OTG_DisableGlobalInt(pdev);
|
||
|
|
||
|
/*Init the Core (common init.) */
|
||
|
USB_OTG_CoreInit(pdev);
|
||
|
|
||
|
|
||
|
/* Force Device Mode*/
|
||
|
USB_OTG_SetCurrentMode(pdev, DEVICE_MODE);
|
||
|
|
||
|
/* Init Device */
|
||
|
USB_OTG_CoreInitDev(pdev);
|
||
|
|
||
|
|
||
|
/* Enable USB Global interrupt */
|
||
|
USB_OTG_EnableGlobalInt(pdev);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief Configure an EP
|
||
|
* @param pdev : Device instance
|
||
|
* @param epdesc : Endpoint Descriptor
|
||
|
* @retval : status
|
||
|
*/
|
||
|
uint32_t DCD_EP_Open(USB_OTG_CORE_HANDLE *pdev ,
|
||
|
uint8_t ep_addr,
|
||
|
uint16_t ep_mps,
|
||
|
uint8_t ep_type)
|
||
|
{
|
||
|
USB_OTG_EP *ep;
|
||
|
|
||
|
if ((ep_addr & 0x80) == 0x80)
|
||
|
{
|
||
|
ep = &pdev->dev.in_ep[ep_addr & 0x7F];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ep = &pdev->dev.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;
|
||
|
if (ep->is_in)
|
||
|
{
|
||
|
/* Assign a Tx FIFO */
|
||
|
ep->tx_fifo_num = ep->num;
|
||
|
}
|
||
|
/* Set initial data PID. */
|
||
|
if (ep_type == USB_OTG_EP_BULK )
|
||
|
{
|
||
|
ep->data_pid_start = 0;
|
||
|
}
|
||
|
USB_OTG_EPActivate(pdev , ep );
|
||
|
return 0;
|
||
|
}
|
||
|
/**
|
||
|
* @brief called when an EP is disabled
|
||
|
* @param pdev: device instance
|
||
|
* @param ep_addr: endpoint address
|
||
|
* @retval : status
|
||
|
*/
|
||
|
uint32_t DCD_EP_Close(USB_OTG_CORE_HANDLE *pdev , uint8_t ep_addr)
|
||
|
{
|
||
|
USB_OTG_EP *ep;
|
||
|
|
||
|
if ((ep_addr&0x80) == 0x80)
|
||
|
{
|
||
|
ep = &pdev->dev.in_ep[ep_addr & 0x7F];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ep = &pdev->dev.out_ep[ep_addr & 0x7F];
|
||
|
}
|
||
|
ep->num = ep_addr & 0x7F;
|
||
|
ep->is_in = (0x80 & ep_addr) != 0;
|
||
|
USB_OTG_EPDeactivate(pdev , ep );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief DCD_EP_PrepareRx
|
||
|
* @param pdev: device instance
|
||
|
* @param ep_addr: endpoint address
|
||
|
* @param pbuf: pointer to Rx buffer
|
||
|
* @param buf_len: data length
|
||
|
* @retval : status
|
||
|
*/
|
||
|
uint32_t DCD_EP_PrepareRx( USB_OTG_CORE_HANDLE *pdev,
|
||
|
uint8_t ep_addr,
|
||
|
uint8_t *pbuf,
|
||
|
uint16_t buf_len)
|
||
|
{
|
||
|
USB_OTG_EP *ep;
|
||
|
|
||
|
ep = &pdev->dev.out_ep[ep_addr & 0x7F];
|
||
|
|
||
|
/*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 (pdev->cfg.dma_enable == 1)
|
||
|
{
|
||
|
ep->dma_addr = (uint32_t)pbuf;
|
||
|
}
|
||
|
|
||
|
if ( ep->num == 0 )
|
||
|
{
|
||
|
USB_OTG_EP0StartXfer(pdev , ep);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
USB_OTG_EPStartXfer(pdev, ep );
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Transmit data over USB
|
||
|
* @param pdev: device instance
|
||
|
* @param ep_addr: endpoint address
|
||
|
* @param pbuf: pointer to Tx buffer
|
||
|
* @param buf_len: data length
|
||
|
* @retval : status
|
||
|
*/
|
||
|
uint32_t DCD_EP_Tx ( USB_OTG_CORE_HANDLE *pdev,
|
||
|
uint8_t ep_addr,
|
||
|
uint8_t *pbuf,
|
||
|
uint32_t buf_len)
|
||
|
{
|
||
|
USB_OTG_EP *ep;
|
||
|
|
||
|
ep = &pdev->dev.in_ep[ep_addr & 0x7F];
|
||
|
|
||
|
/* Setup and start the Transfer */
|
||
|
ep->is_in = 1;
|
||
|
ep->num = ep_addr & 0x7F;
|
||
|
ep->xfer_buff = pbuf;
|
||
|
ep->dma_addr = (uint32_t)pbuf;
|
||
|
ep->xfer_count = 0;
|
||
|
ep->xfer_len = buf_len;
|
||
|
|
||
|
if ( ep->num == 0 )
|
||
|
{
|
||
|
USB_OTG_EP0StartXfer(pdev , ep);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
USB_OTG_EPStartXfer(pdev, ep );
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief Stall an endpoint.
|
||
|
* @param pdev: device instance
|
||
|
* @param epnum: endpoint address
|
||
|
* @retval : status
|
||
|
*/
|
||
|
uint32_t DCD_EP_Stall (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum)
|
||
|
{
|
||
|
USB_OTG_EP *ep;
|
||
|
if ((0x80 & epnum) == 0x80)
|
||
|
{
|
||
|
ep = &pdev->dev.in_ep[epnum & 0x7F];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ep = &pdev->dev.out_ep[epnum];
|
||
|
}
|
||
|
|
||
|
ep->is_stall = 1;
|
||
|
ep->num = epnum & 0x7F;
|
||
|
ep->is_in = ((epnum & 0x80) == 0x80);
|
||
|
|
||
|
USB_OTG_EPSetStall(pdev , ep);
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief Clear stall condition on endpoints.
|
||
|
* @param pdev: device instance
|
||
|
* @param epnum: endpoint address
|
||
|
* @retval : status
|
||
|
*/
|
||
|
uint32_t DCD_EP_ClrStall (USB_OTG_CORE_HANDLE *pdev, uint8_t epnum)
|
||
|
{
|
||
|
USB_OTG_EP *ep;
|
||
|
if ((0x80 & epnum) == 0x80)
|
||
|
{
|
||
|
ep = &pdev->dev.in_ep[epnum & 0x7F];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ep = &pdev->dev.out_ep[epnum];
|
||
|
}
|
||
|
|
||
|
ep->is_stall = 0;
|
||
|
ep->num = epnum & 0x7F;
|
||
|
ep->is_in = ((epnum & 0x80) == 0x80);
|
||
|
|
||
|
USB_OTG_EPClearStall(pdev , ep);
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief This Function flushes the FIFOs.
|
||
|
* @param pdev: device instance
|
||
|
* @param epnum: endpoint address
|
||
|
* @retval : status
|
||
|
*/
|
||
|
uint32_t DCD_EP_Flush (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum)
|
||
|
{
|
||
|
|
||
|
if ((epnum & 0x80) == 0x80)
|
||
|
{
|
||
|
USB_OTG_FlushTxFifo(pdev, epnum & 0x7F);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
USB_OTG_FlushRxFifo(pdev);
|
||
|
}
|
||
|
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief This Function set USB device address
|
||
|
* @param pdev: device instance
|
||
|
* @param address: new device address
|
||
|
* @retval : status
|
||
|
*/
|
||
|
void DCD_EP_SetAddress (USB_OTG_CORE_HANDLE *pdev, uint8_t address)
|
||
|
{
|
||
|
USB_OTG_DCFG_TypeDef dcfg;
|
||
|
dcfg.d32 = 0;
|
||
|
dcfg.b.devaddr = address;
|
||
|
USB_OTG_MODIFY_REG32( &pdev->regs.DREGS->DCFG, 0, dcfg.d32);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Connect device (enable internal pull-up)
|
||
|
* @param pdev: device instance
|
||
|
* @retval : None
|
||
|
*/
|
||
|
void DCD_DevConnect (USB_OTG_CORE_HANDLE *pdev)
|
||
|
{
|
||
|
#ifndef USE_OTG_MODE
|
||
|
USB_OTG_DCTL_TypeDef dctl;
|
||
|
dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL);
|
||
|
/* Connect device */
|
||
|
dctl.b.sftdiscon = 0;
|
||
|
USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCTL, dctl.d32);
|
||
|
USB_OTG_BSP_mDelay(3);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief Disconnect device (disable internal pull-up)
|
||
|
* @param pdev: device instance
|
||
|
* @retval : None
|
||
|
*/
|
||
|
void DCD_DevDisconnect (USB_OTG_CORE_HANDLE *pdev)
|
||
|
{
|
||
|
#ifndef USE_OTG_MODE
|
||
|
USB_OTG_DCTL_TypeDef dctl;
|
||
|
dctl.d32 = USB_OTG_READ_REG32(&pdev->regs.DREGS->DCTL);
|
||
|
/* Disconnect device for 3ms */
|
||
|
dctl.b.sftdiscon = 1;
|
||
|
USB_OTG_WRITE_REG32(&pdev->regs.DREGS->DCTL, dctl.d32);
|
||
|
USB_OTG_BSP_mDelay(3);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @brief returns the EP Status
|
||
|
* @param pdev : Selected device
|
||
|
* epnum : endpoint address
|
||
|
* @retval : EP status
|
||
|
*/
|
||
|
|
||
|
uint32_t DCD_GetEPStatus(USB_OTG_CORE_HANDLE *pdev ,uint8_t epnum)
|
||
|
{
|
||
|
USB_OTG_EP *ep;
|
||
|
uint32_t Status = 0;
|
||
|
|
||
|
if ((0x80 & epnum) == 0x80)
|
||
|
{
|
||
|
ep = &pdev->dev.in_ep[epnum & 0x7F];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ep = &pdev->dev.out_ep[epnum];
|
||
|
}
|
||
|
|
||
|
Status = USB_OTG_GetEPStatus(pdev ,ep);
|
||
|
|
||
|
/* Return the current status */
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Set the EP Status
|
||
|
* @param pdev : Selected device
|
||
|
* Status : new Status
|
||
|
* epnum : EP address
|
||
|
* @retval : None
|
||
|
*/
|
||
|
void DCD_SetEPStatus (USB_OTG_CORE_HANDLE *pdev , uint8_t epnum , uint32_t Status)
|
||
|
{
|
||
|
USB_OTG_EP *ep;
|
||
|
|
||
|
if ((0x80 & epnum) == 0x80)
|
||
|
{
|
||
|
ep = &pdev->dev.in_ep[epnum & 0x7F];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ep = &pdev->dev.out_ep[epnum];
|
||
|
}
|
||
|
|
||
|
USB_OTG_SetEPStatus(pdev ,ep , Status);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|
||
|
|
||
|
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|