/**
  ******************************************************************************
  * @file    bl702_usb.h
  * @version V1.0
  * @date
  * @brief   This file is the standard driver header file
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2019 Bouffalo Lab</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of Bouffalo Lab nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
#ifndef __BL702_USB_H__
#define __BL702_USB_H__

#include "usb_reg.h"
#include "bl702_common.h"

/** @addtogroup  BL702_Peripheral_Driver
 *  @{
 */

/** @addtogroup  USB
 *  @{
 */

/** @defgroup  USB_Public_Types
 *  @{
 */

/**
 *  @brief USB end point ID
 */
typedef enum {
    EP_ID0 = 0, /*!< USB end point 0 */
    EP_ID1,     /*!< USB end point 1 */
    EP_ID2,     /*!< USB end point 2 */
    EP_ID3,     /*!< USB end point 3 */
    EP_ID4,     /*!< USB end point 4 */
    EP_ID5,     /*!< USB end point 5 */
    EP_ID6,     /*!< USB end point 6 */
    EP_ID7,     /*!< USB end point 7 */
} USB_EP_ID;

/**
 *  @brief USB end point type
 */
typedef enum {
    EP_INT = 0,  /*!< interrupt transfer ep */
    EP_ISO = 2,  /*!< isochronous transfer ep */
    EP_BULK = 4, /*!< bulk transfer ep */
    EP_CTRL = 5, /*!< control transfer ep */
} EP_XFER_Type;

/**
 *  @brief USB end point transfer directions
 */
typedef enum {
    EP_DISABLED = 0, /*!< end point disabled */
    EP_IN = 1,       /*!< IN end point,device to host */
    EP_OUT = 2,      /*!< OUT end point ,host to device */
} EP_XFER_DIR;

typedef enum {
    USB_INT_SOF = 0,
    USB_INT_RESET,
    USB_INT_VBUS_TGL,
    USB_INT_GET_DCT_CMD,
    USB_INT_EP0_SETUP_CMD,
    USB_INT_EP0_SETUP_DONE,
    USB_INT_EP0_IN_CMD,
    USB_INT_EP0_IN_DONE,
    USB_INT_EP0_OUT_CMD,
    USB_INT_EP0_OUT_DONE,
    USB_INT_EP1_CMD,
    USB_INT_EP1_DONE,
    USB_INT_EP2_CMD,
    USB_INT_EP2_DONE,
    USB_INT_EP3_CMD,
    USB_INT_EP3_DONE,
    USB_INT_EP4_CMD,
    USB_INT_EP4_DONE,
    USB_INT_EP5_CMD,
    USB_INT_EP5_DONE,
    USB_INT_EP6_CMD,
    USB_INT_EP6_DONE,
    USB_INT_EP7_CMD,
    USB_INT_EP7_DONE,
    USB_INT_RESET_END = 27,
    USB_INT_LPM_WAKEUP = 28,
    USB_INT_LPM_PACKET = 29,
    USB_INT_LOST_SOF_3_TIMES = 30,
    USB_INT_ERROR = 31,
    USB_INT_ALL = 32, /* special */
} USB_INT_Type;

typedef enum {
    USB_FIFO_EMPTY = 0,
    USB_FIFO_FULL,
} USB_FIFO_STATUS_Type;

typedef enum {
    USB_FIFO_ERROR_OVERFLOW = 0,
    USB_FIFO_ERROR_UNDERFLOW,
} USB_FIFO_ERROR_FLAG_Type;

typedef enum {
    USB_EP_STATUS_ACK = 0,
    USB_EP_STATUS_NACK,
    USB_EP_STATUS_STALL,
    USB_EP_STATUS_NSTALL,
} USB_EP_STATUS_Type;

typedef enum {
    USB_LPM_DEFAULT_RESP_ACK = 0,
    USB_LPM_DEFAULT_RESP_NACK,
    USB_LPM_DEFAULT_RESP_STALL,
    USB_LPM_DEFAULT_RESP_NYET,
} USB_LPM_DEFAULT_RESP_Type;

typedef enum {
    USB_ERROR_UTMI_RX = 0,
    USB_ERROR_XFER_TO,
    USB_ERROR_IVLD_EP,
    USB_ERROR_PID_SEQ,
    USB_ERROR_PID_CKS,
    USB_ERROR_CRC5,
    USB_ERROR_CRC16,
} USB_ERROR_Type;

/**
 *  @brief USB configuration structure type definition
 */
typedef struct
{
    BL_Fun_Type EnumOutEn;             /*!< EP0 IN direction enable or disable */
    BL_Fun_Type EnumInEn;              /*!< EP0 OUT direction enable or disable */
    uint8_t EnumMaxPacketSize;         /*!< EP0 max packet size, only valid when SoftwareCtrl is set */
    uint8_t DeviceAddress;             /*!< Device(EP0) address, only valid when SoftwareCtrl is set */
    BL_Fun_Type SoftwareCtrl;          /*!< EP0 software control enable */
    BL_Fun_Type RomBaseDescriptorUsed; /*!< Enable signal of ROM-based descriptors (don't care if SoftwareCtrl is set) */
} USB_Config_Type;

/**
 *  @brief end point configuration structure type definition
 */
typedef struct
{
    uint16_t EPMaxPacketSize; /*!< Endpoint max packet size */
    EP_XFER_DIR dir;          /*!< Endpoint direction */
    EP_XFER_Type type;        /*!< Endpoint type */
} EP_Config_Type;

typedef struct
{
    uint32_t cr_ep_size     : 9;
    uint32_t cr_ep_dir      : 2;
    uint32_t cr_ep_type     : 3;
    uint32_t cr_ep_stall    : 1;
    uint32_t cr_ep_nack     : 1;
    uint32_t cr_ep_rdy      : 1;
    uint32_t reserved_17_31 : 15;
} usb_reg_epx_config_t;

typedef struct
{
    uint32_t ep_dma_tx_en         : 1;
    uint32_t ep_dma_rx_en         : 1;
    uint32_t ep_tx_fifo_clr       : 1;
    uint32_t ep_rx_fifo_clr       : 1;
    uint32_t ep_tx_fifo_overflow  : 1;
    uint32_t ep_tx_fifo_underflow : 1;
    uint32_t ep_rx_fifo_overflow  : 1;
    uint32_t ep_rx_fifo_underflow : 1;
    uint32_t reserved_8_31        : 24;
} usb_reg_epx_fifo_config_t;

typedef struct
{
    uint32_t ep_tx_fifo_cnt   : 7;
    uint32_t reserved_7_13    : 7;
    uint32_t ep_tx_fifo_empty : 1;
    uint32_t ep_tx_fifo_full  : 1;
    uint32_t ep_rx_fifo_cnt   : 7;
    uint32_t reserved_23_29   : 7;
    uint32_t ep_rx_fifo_empty : 1;
    uint32_t ep_rx_fifo_full  : 1;
} usb_reg_epx_fifo_status_t;

typedef struct
{
    uint32_t fifo          : 8;
    uint32_t reserved_8_31 : 24;
} usb_reg_epx_fifo_t;

/*@} end of group USB_Public_Types */

/** @defgroup  USB_Public_Constants
 *  @{
 */

/** @defgroup  USB_EP_ID
 *  @{
 */
#define IS_USB_EP_ID(type) (((type) == EP_ID0) || \
                            ((type) == EP_ID1) || \
                            ((type) == EP_ID2) || \
                            ((type) == EP_ID3) || \
                            ((type) == EP_ID4) || \
                            ((type) == EP_ID5) || \
                            ((type) == EP_ID6) || \
                            ((type) == EP_ID7))

/** @defgroup  EP_XFER_TYPE
 *  @{
 */
#define IS_EP_XFER_TYPE(type) (((type) == EP_INT) ||  \
                               ((type) == EP_ISO) ||  \
                               ((type) == EP_CTRL) || \
                               ((type) == EP_BULK))

/** @defgroup  EP_XFER_DIR
 *  @{
 */
#define IS_EP_XFER_DIR(type) (((type) == EP_DISABLED) || \
                              ((type) == EP_IN) ||       \
                              ((type) == EP_OUT))

/*@} end of group USB_Public_Constants */

/** @defgroup  USB_Public_Macros
 *  @{
 */
#define USB_INT_TYPE_SOF              0x00000001
#define USB_INT_TYPE_RESET            0x00000002
#define USB_INT_TYPE_GET_DCT_CMD      0x00000008
#define USB_INT_TYPE_EP0_SETUP_CMD    0x00000010
#define USB_INT_TYPE_EP0_SETUP_DONE   0x00000020
#define USB_INT_TYPE_EP0_IN_CMD       0x00000040
#define USB_INT_TYPE_EP0_IN_DONE      0x00000080
#define USB_INT_TYPE_EP0_OUT_CMD      0x00000100
#define USB_INT_TYPE_EP0_OUT_DONE     0x00000200
#define USB_INT_TYPE_EP1_CMD          0x00000400
#define USB_INT_TYPE_EP1_DONE         0x00000800
#define USB_INT_TYPE_EP2_CMD          0x00001000
#define USB_INT_TYPE_EP2_DONE         0x00002000
#define USB_INT_TYPE_EP3_CMD          0x00004000
#define USB_INT_TYPE_EP3_DONE         0x00008000
#define USB_INT_TYPE_EP4_CMD          0x00010000
#define USB_INT_TYPE_EP4_DONE         0x00020000
#define USB_INT_TYPE_EP5_CMD          0x00040000
#define USB_INT_TYPE_EP5_DONE         0x00080000
#define USB_INT_TYPE_EP6_CMD          0x00100000
#define USB_INT_TYPE_EP6_DONE         0x00200000
#define USB_INT_TYPE_EP7_CMD          0x00400000
#define USB_INT_TYPE_EP7_DONE         0x00800000
#define USB_INT_TYPE_RESET_END        0x08000000
#define USB_INT_TYPE_LPM_WAKEUP       0x10000000
#define USB_INT_TYPE_LPM_PACKET       0x20000000
#define USB_INT_TYPE_LOST_SOF_3_TIMES 0x40000000
#define USB_INT_TYPE_ERROR            0x80000000
#define USB_INT_TYPE_ALL              (USB_INT_TYPE_SOF | \
                          USB_INT_TYPE_RESET |            \
                          USB_INT_TYPE_GET_DCT_CMD |      \
                          USB_INT_TYPE_EP0_SETUP_CMD |    \
                          USB_INT_TYPE_EP0_SETUP_DONE |   \
                          USB_INT_TYPE_EP0_IN_CMD |       \
                          USB_INT_TYPE_EP0_IN_DONE |      \
                          USB_INT_TYPE_EP0_OUT_CMD |      \
                          USB_INT_TYPE_EP0_OUT_DONE |     \
                          USB_INT_TYPE_EP1_CMD |          \
                          USB_INT_TYPE_EP1_DONE |         \
                          USB_INT_TYPE_EP2_CMD |          \
                          USB_INT_TYPE_EP2_DONE |         \
                          USB_INT_TYPE_EP3_CMD |          \
                          USB_INT_TYPE_EP3_DONE |         \
                          USB_INT_TYPE_EP4_CMD |          \
                          USB_INT_TYPE_EP4_DONE |         \
                          USB_INT_TYPE_EP5_CMD |          \
                          USB_INT_TYPE_EP5_DONE |         \
                          USB_INT_TYPE_EP6_CMD |          \
                          USB_INT_TYPE_EP6_DONE |         \
                          USB_INT_TYPE_EP7_CMD |          \
                          USB_INT_TYPE_EP7_DONE |         \
                          USB_INT_TYPE_RESET_END |        \
                          USB_INT_TYPE_LPM_WAKEUP |       \
                          USB_INT_TYPE_LPM_PACKET |       \
                          USB_INT_TYPE_LOST_SOF_3_TIMES | \
                          USB_INT_TYPE_ERROR)

#define USB_EP_TX_FIFO_EMPTY    0x00004000
#define USB_EP_TX_FIFO_FULL     0x00008000
#define USB_EP_RX_FIFO_EMPTY    0x40000000
#define USB_EP_RX_FIFO_FULL     0x80000000
#define USB_EP_FIFO_STATUS_MASK (USB_EP_TX_FIFO_EMPTY | \
                                 USB_EP_TX_FIFO_FULL |  \
                                 USB_EP_RX_FIFO_EMPTY | \
                                 USB_EP_RX_FIFO_FULL)
#define USB_EP_TX_FIFO_OVERFLOW  0x00000010
#define USB_EP_TX_FIFO_UNDERFLOW 0x00000020
#define USB_EP_RX_FIFO_OVERFLOW  0x00000040
#define USB_EP_RX_FIFO_UNDERLOW  0x00000080
#define USB_EP_FIFO_ERROR_MASK   (USB_EP_TX_FIFO_OVERFLOW | \
                                USB_EP_TX_FIFO_UNDERFLOW |  \
                                USB_EP_RX_FIFO_OVERFLOW |   \
                                USB_EP_RX_FIFO_UNDERLOW)

#define EP_ID_MAX 8

/*@} end of group USB_Public_Macros */

/** @defgroup  USB_Public_Functions
 *  @{
 */

/**
 *  @brief USB Functions
 */

/*----------*/
#ifndef BFLB_USE_HAL_DRIVER
void USB_IRQHandler(void);
#endif
/*----------*/
BL_Err_Type USB_Enable(void);
BL_Err_Type USB_Disable(void);
BL_Err_Type USB_Set_Config(BL_Fun_Type enable, USB_Config_Type *usbCfg);
BL_Err_Type USB_Set_Device_Addr(uint8_t addr);
uint8_t USB_Get_Device_Addr(void);
/*----------*/
BL_Err_Type USB_Set_EPx_Xfer_Size(USB_EP_ID epId, uint8_t size);
BL_Err_Type USB_Set_EPx_IN_Busy(USB_EP_ID epId);
BL_Err_Type USB_Set_EPx_IN_Stall(USB_EP_ID epId);
BL_Err_Type USB_Set_EPx_OUT_Busy(USB_EP_ID epId);
BL_Err_Type USB_Set_EPx_OUT_Stall(USB_EP_ID epId);
BL_Err_Type USB_Set_EPx_Rdy(USB_EP_ID epId);
BL_Sts_Type USB_Is_EPx_RDY_Free(USB_EP_ID epId);
BL_Err_Type USB_Set_EPx_STALL(USB_EP_ID epId);
BL_Err_Type USB_Clr_EPx_STALL(USB_EP_ID epId);
BL_Err_Type USB_Set_EPx_Busy(USB_EP_ID epId);
BL_Err_Type USB_Set_EPx_Status(USB_EP_ID epId, USB_EP_STATUS_Type sts);
USB_EP_STATUS_Type USB_Get_EPx_Status(USB_EP_ID epId);
/*----------*/
BL_Err_Type USB_IntEn(USB_INT_Type intType, uint8_t enable);
BL_Err_Type USB_IntMask(USB_INT_Type intType, BL_Mask_Type intMask);
BL_Sts_Type USB_Get_IntStatus(USB_INT_Type intType);
BL_Err_Type USB_Clr_IntStatus(USB_INT_Type intType);
BL_Err_Type USB_Clr_EPx_IntStatus(USB_EP_ID epId);
/*----------*/
uint16_t USB_Get_Frame_Num(void);
/*----------*/
BL_Err_Type USB_Set_EPx_Config(USB_EP_ID epId, EP_Config_Type *epCfg);
BL_Err_Type USB_Set_EPx_Type(USB_EP_ID epId, EP_XFER_Type type);
EP_XFER_Type USB_Get_EPx_Type(USB_EP_ID epId);
BL_Err_Type USB_Set_EPx_Dir(USB_EP_ID epId, EP_XFER_DIR dir);
EP_XFER_DIR USB_Get_EPx_Dir(USB_EP_ID epId);
BL_Err_Type USB_Set_EPx_Size(USB_EP_ID epId, uint32_t size);
/*----------*/
BL_Sts_Type USB_Get_EPx_TX_FIFO_Errors(USB_EP_ID epId, USB_FIFO_ERROR_FLAG_Type errFlag);
BL_Sts_Type USB_Get_EPx_RX_FIFO_Errors(USB_EP_ID epId, USB_FIFO_ERROR_FLAG_Type errFlag);
BL_Err_Type USB_Clr_EPx_TX_FIFO_Errors(USB_EP_ID epId);
BL_Err_Type USB_Clr_EPx_RX_FIFO_Errors(USB_EP_ID epId);
/*----------*/
BL_Err_Type USB_EPx_Write_Data_To_FIFO(USB_EP_ID epId, uint8_t *pData, uint16_t len);
BL_Err_Type USB_EPx_Read_Data_From_FIFO(USB_EP_ID epId, uint8_t *pBuff, uint16_t len);
/*----------*/
BL_Err_Type USB_Set_EPx_TX_DMA_Interface_Config(USB_EP_ID epId, BL_Fun_Type newState);
BL_Err_Type USB_Set_EPx_RX_DMA_Interface_Config(USB_EP_ID epId, BL_Fun_Type newState);
BL_Err_Type USB_EPx_Write_Data_To_FIFO_DMA(USB_EP_ID epId, uint8_t *pData, uint16_t len);
BL_Err_Type USB_EPx_Read_Data_From_FIFO_DMA(USB_EP_ID epId, uint8_t *pBuff, uint16_t len);
/*----------*/
uint16_t USB_Get_EPx_TX_FIFO_CNT(USB_EP_ID epId);
uint16_t USB_Get_EPx_RX_FIFO_CNT(USB_EP_ID epId);
BL_Sts_Type USB_Get_EPx_TX_FIFO_Status(USB_EP_ID epId, USB_FIFO_STATUS_Type sts);
BL_Sts_Type USB_Get_EPx_RX_FIFO_Status(USB_EP_ID epId, USB_FIFO_STATUS_Type sts);
/*----------*/
BL_Err_Type USB_Set_Internal_PullUp_Config(BL_Fun_Type newState);
/*----------*/
BL_Sts_Type USB_Get_LPM_Status(void);
uint16_t USB_Get_LPM_Packet_Attr(void);
BL_Err_Type USB_Set_LPM_Default_Response(USB_LPM_DEFAULT_RESP_Type defaultResp);
BL_Err_Type USB_LPM_Enable(void);
BL_Err_Type USB_LPM_Disable(void);
/*----------*/
BL_Err_Type USB_Device_Output_K_State(uint16_t stateWidth);
/*----------*/
uint8_t USB_Get_Current_Packet_PID(void);
uint8_t USB_Get_Current_Packet_EP(void);
/*----------*/
BL_Sts_Type USB_Get_Error_Status(USB_ERROR_Type err);
BL_Err_Type USB_Clr_Error_Status(USB_ERROR_Type err);
/*----------*/

/*@} end of group USB_Public_Functions */

/*@} end of group USB */

/*@} end of group BL702_Peripheral_Driver */

#endif /* __BL702_USB_H__ */
