#ifndef _API_USB_H
#define _API_USB_H

//Recipient
#define REQ_DEVICE                      0
#define REQ_INTERFACE                   1
#define REQ_ENDPOINT                    2

enum {
    USBCHK_ONLY_HOST,
    USBCHK_ONLY_DEVICE,
    USBCHK_OTG,
};

enum {
    USB_DISCONNECT,
    USB_UDISK_CONNECTED,
    USB_PC_CONNECTED,
};

typedef struct {
    union {
        u8 bmRequest;
        u8 recipient: 5;
        u8 type: 2;
        u8 dir: 1;
    };
    u8 bRequest;
    u16 wValue;
    u16 wIndex;
    u16 wLength;
}spb_wrap_t;

void usb_init(void);
void usb_disable(void);
u8 usbchk_connect(u8 mode);
void udisk_remove(void);
void udisk_insert(void);
void udisk_invalid(void);

void udisk_suspend(void);
void udisk_resume(void);

void usb_device_enter(u8 enum_type);
void usb_device_exit(void);
void ude_tmr_isr(void);
void pc_remove(void);

/**
  * @brief  send data to USB host in bulk mode.
  * @param  buf: data that need to send.
  * @param  len: lenght of data that need to send.
  * @param  timeout: max time of waiting for sending completion.
  * @retval the result of transmission, it will return false when
            timeout or error.
  */
bool usb_bulk_send(u8 *buf, uint len, u32 timeout);

/**
  * @brief  Config printer transfer endpoint.
  * @param  out_ep: printer out endpoint.
  *         this parameter can be one of the following values:
  *             @arg EP_NUM_1: endpoint 1.
  *             @arg EP_NUM_2: endpoint 2.
  *             @arg EP_NUM_3: endpoint 3.
  * @param  in_ep: printer in endpoint.
  *         The optional value of this parameter is the same as the optional value
  *         of parameter "out_ep".
  * @retval None
  */
void usb_printer_ep_config(u8 out_ep, u8 in_ep);

/**
  * @brief  Config hid transfer endpoint.
  * @param  in_ep: hid in endpoint.
  *         this parameter can be one of the following values:
  *             @arg EP_NUM_1: endpoint 1.
  *             @arg EP_NUM_2: endpoint 2.
  *             @arg EP_NUM_3: endpoint 3.
  * @retval None
  */
void usb_hid_ep_config(u8 in_ep);

/**
 * @brief  Config hid transfer endpoint.
 * @param  ep_idx: user ep index.
 * @param  dir: direction.
 *               0: Host out.
 *               1: Host in.
 * @param  type: ep type.
 *               0: Ctrl
 *               1: Bulk
 *               2: Int
 *               3: Isoc
 * @retval None
 */
void usb_user_ep_config(u8 ep_idx, u8 dir, u8 type);

/**
  * @brief  send the ack signal to host, notify the host
  *         that can receive new data.
  * @param  void
  * @retval None
  */
void ude_rx_ack(void);

/**
 * @brief  send the ack signal to host, notify the host
 *         that can receive new data.
 * @param  void
 * @retval None
 */
void usb_user_ep_rx_ack(void);

/**
  * @brief  The usb bulk tx interrupt callback function. When
  *         one transmit is finish, the function will be call.
  *         you can rewrite this function to run something you want.
  * @param  void
  * @retval None
  */
void bulk_tx_handler(void);

/**
 * @brief  The usb user endpoint tx interrupt callback funciton. When
 *         one transmit is finish, the function will be call.
 *         you can rewrite this function to run something you want.
 * @param  void
 * @retval None
 */
void usb_user_ep_tx_handler(void);

/**
  * @brief  The usb bulk rx interrupt callback function. When
  *         USB receive one unit data, this function will be call.
  *         you can rewrite this function to process the data.
  * @param  buf: receive data.
  * @param  len: the length of receive data.
  * @retval None
  */
void bulk_rx_handler(u8 *buf, u8 len);

/**
  * @brief  send data to USB host in user endpoint.
  * @param  buf: data that need to send.
  * @param  len: lenght of data that need to send.
  * @param  timeout: max time of waiting for sending completion.
  * @retval the result of transmission, it will return false when
            timeout or error.
  */
bool usb_user_ep_send(u8 *buf, uint len, u32 timeout);

/**
 * @brief  The use user endpoint rx interrupt callback function. When
 *         USB receive one unit data, this function will be call.
 *         you can rewrite this function to process the data.
 * @param  buf: receive data.
 * @param  len: the length of receive data.
 * @retval None
 */
void usb_user_ep_rx_handler(u8 *buf, u8 len);

/**
 * @brief  Send Key Code.
 * @param  buf: the data buffer need to send.
 * @param  len: the length of data buffer.
 * @retval None
 */
bool usb_device_hid_send(u8 *buf, u8 len);

// Rewrite the following function to set the descriptor.
u8 *usb_get_device_descriptor(u8 *length);
u8 *usb_get_config_descriptor(u8 *length);
u8 *usb_get_lang_id_str_descriptor(u8 *length);
u8 *usb_get_manufacturer_str_descriptor(u8 *length);
u8 *usb_get_product_str_descriptor(u8 *length);
u8 *usb_get_serial_str_descriptor(u8 *length);
bool usb_itf_in_req(uint8_t *cmd, uint8_t **response, uint32_t *length);

/*!**************************************************************************************************
\brief          Bulk_EP_Tx
\param[in]      *buf:	Tx Buf Pointer
\param[in]      len:	Tx Buf len(can't be 0)
\param[in]      expire_val: Bulk EP send expire time,unit is "ms"/ Set "0" is not use expire function
\return         true:send data success
****************************************************************************************************/
bool ude_bulk_ep1_tx(u8 *buf, uint len, u32 expire_val);
#endif // _API_USB_H
