#ifndef _API_BTSTACK_H
#define _API_BTSTACK_H

//BLE WORK MODE
typedef enum {
    MODE_NORMAL     = 0,       //normal mode
    MODE_WIRELESS   = 1,       //wireless mode, 2.4G
    MODE_FCC_TEST   = 2,       //fcc test mode, use uart for communication
    MODE_BQB_RF_BLE = 4,       //bqb test mode，use uart for communication
    MODE_IODM_TEST  = 5,       //iodm test mode，use uart for communication
} BT_WORK_MODE;


typedef enum {
    FCC_TX_TONE = 1,
    FCC_TX_TEST,
    FCC_RX_TEST,
} FCC_RF_MODE;

enum {
    TXPKT_KICK_DISABLE = 0,
    TXPKT_KICK_ENABLE,
    TXPKT_KICK_AUTO,
};


/**
 * @format 21
 * @param handle
 * @param status
 */
#define BLE_EVT_PROFILE_FIND_DONE                                   0xA0

/**
 * @format 2228
 * @param con_handle
 * @param start_group_handle
 * @param end_group_handle
 * @param uuid128
 */
#define BLE_EVT_SERVICE_FIND_RESULT                                 0xA1

/**
 * @format 222228
 * @param con_handle
 * @param start_handle
 * @param value_handle
 * @param end_handle
 * @param properties
 * @param uuid128
 */
#define BLE_EVT_CHARACTERISTIC_FIND_RESULT                          0xA2


/**
 * @format 12222
 * @param status
 * @param handle
 * @param interval
 * @param latency
 * @param timeout
 */
#define BLE_EVT_CONNECT_PARAM_UPDATE_DONE                           0xB2

/**
 * @format 1621
 * @param address_type
 * @param address
 * @param handle
 * @param role
 */
#define BLE_EVT_CONNECT                                             0xB3

/**
 * @format 21
 * @param handle
 * @param disconnect_reason
 */
#define BLE_EVT_DISCONNECT                                          0xB4

/**
 * @format 22
 * @param handle
 * @param MTU
 */
#define BLE_EVT_MTU_EXCHANGE_DONE                                   0xB5

 /**
  * @format 122
  * @param status
  * @param conn_handle
  * @param attribute_handle
  */
#define BLE_EVT_INDICATE_DONE                                       0xB6

/**
 * @format 121
 * @param status
 * @param conn_handle
 * @param encryption_enabled
 */
#define BLE_EVT_ENCRYPTION_CHANGE                                   0xC7

 /**
  * @format 21614
  * @param handle
  * @param addr_type
  * @param address
  * @param secure_connection - set to 1 if LE Secure Connection pairing will be used
  * @param passkey
  */
#define BLE_EVT_PASSKEY_DISPLAY                                     0xC9


 /**
  * @format 2161
  * @param handle
  * @param addr_type
  * @param address
  * @param secure_connection - set to 1 if LE Secure Connection pairing will be used
  */
#define BLE_EVT_PASSKEY_INPUT                                       0xCB

 /**
  * @format 216
  * @param handle
  * @param addr_type
  * @param address
  */
#define BLE_EVT_IDENTITY_RESOLVING_FAIL                             0xCE

 /**
  * @brief Identify resolving succeeded
  *
  * @format 216162
  * @param handle
  * @param addr_type
  * @param address
  * @param identity_addr_type
  * @param identity_address
  * @param index
  *
  */
#define BLE_EVT_IDENTITY_RESOLVING_SUCCEED                          0xCF


/**
 * @brief Emitted to inform app that pairing has started.
 * @format 216
 * @param handle
 * @param addr_type
 * @param address
 */
#define BLE_EVT_PAIRING_START                                       0xD4

/**
  * @brief Emitted to inform app that pairing is complete.
  * @format 21611
  * @param handle
  * @param addr_type
  * @param address
  * @param status
  * @param reason
  */
#define BLE_EVT_PAIRING_DONE                                        0xD5

/**
 * @brief Emitted to inform app that ltk is missing.
 * @format 216
 * @param handle
 * @param addr_type
 * @param address
 */
#define BLE_EVT_LTK_MISSING                                         0xD8


/**
 * @format 11611N
 * @param advertising_event_type
 * @param address_type
 * @param address
 * @param rssi
 * @param data_length
 * @param data
 */
#define BLE_EVT_ADV_REPORT                                          0xE2


// ATT_ERR_CODE
#define ATT_ERR_NO_ERR                                              0x00
#define ATT_ERR_INVALID_HANDLE                                      0x01
#define ATT_ERR_READ_NOT_PERMITTED                                  0x02
#define ATT_ERR_WRITE_NOT_PERMITTED                                 0x03
#define ATT_ERR_INVALID_PDU                                         0x04
#define ATT_ERR_INSUFFICIENT_AUTHENTICATION                         0x05
#define ATT_ERR_REQUEST_NOT_SUPPORTED                               0x06
#define ATT_ERR_INVALID_OFFSET                                      0x07
#define ATT_ERR_INSUFFICIENT_AUTHORIZATION                          0x08
#define ATT_ERR_PREPARE_QUEUE_FULL                                  0x09
#define ATT_ERR_ATTRIBUTE_NOT_FOUND                                 0x0a
#define ATT_ERR_ATTRIBUTE_NOT_LONG                                  0x0b
#define ATT_ERR_INSUFFICIENT_ENCRYPTION_KEY_SIZE                    0x0c
#define ATT_ERR_INVALID_ATTRIBUTE_VALUE_LENGTH                      0x0d
#define ATT_ERR_UNLIKELY_ERROR                                      0x0e
#define ATT_ERR_INSUFFICIENT_ENCRYPTION                             0x0f
#define ATT_ERR_UNSUPPORTED_GROUP_TYPE                              0x10
#define ATT_ERR_INSUFFICIENT_RESOURCES                              0x11
#define ATT_ERR_VALUE_NOT_ALLOWED                                   0x13
#define ATT_ERR_IN_WRONG_STATE                                      0x80
#define ATT_ERR_NOTIFICATION_NOT_SUPPORTED                          0x81
#define ATT_ERR_INDICATION_NOT_SUPPORTED                            0x82
#define ATT_ERR_INDICATION_IN_PORGRESS                              0x83
#define ATT_ERR_TIMEOUT                                             0x84
#define ATT_ERR_DISCONNECT                                          0x85
#define ATT_ERR_DATA_MISMATCH                                       0x86




//Attribute Property
#define ATT_PROPERTY_BROADCAST                                      0x01
#define ATT_PROPERTY_READ                                           0x02
#define ATT_PROPERTY_WRITE_WITHOUT_RESPONSE                         0x04
#define ATT_PROPERTY_WRITE                                          0x08
#define ATT_PROPERTY_NOTIFY                                         0x10
#define ATT_PROPERTY_INDICATE                                       0x20
#define ATT_PROPERTY_AUTHENTICATED_SIGNED_WRITE                     0x40
#define ATT_PROPERTY_EXTENDED_PROPERTIES                            0x80


//GATT_CLIENT_CHARACTERISTIC_CONFIGURATION
#define GATT_CCC_NOTIFICATION                                       0x01
#define GATT_CCC_INDICATION                                         0x02


//ATT_TRANSACTION_MODE
#define ATT_TRANSACTION_WRITE                                       0x00
#define ATT_TRANSACTION_PREPARE_WRITE                               0x01
#define ATT_TRANSACTION_WRITE_EXECUTE                               0x02
#define ATT_TRANSACTION_WRITE_CANCEL                                0x03


//SM_AUTHREQ
#define SM_AUTHREQ_NO_BONDING                                       0x00
#define SM_AUTHREQ_BONDING                                          0x01
#define SM_AUTHREQ_MITM_PROTECTION                                  0x04
#define SM_AUTHREQ_SECURE_CONNECTION                                0x08
#define SM_AUTHREQ_KEYPRESS                                         0x10
#define SM_AUTHREQ_CT2                                              0x20


typedef uint16_t ble_con_handle_t;

typedef uint32_t bt_timer_handle_t;

typedef void (*kick_func_t)(uint16_t con_handle, uint16_t config);

typedef uint16_t (*att_read_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t * buffer, uint16_t buffer_size);

typedef int (*att_write_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint16_t trans_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size);

typedef uint16_t (*att_notify_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint8_t * buffer, uint16_t buffer_size);

typedef void (*att_event_callback_t) (uint8_t event_type, uint8_t *param, uint16_t size);

typedef void (*ble_init_callback_t)(void);

typedef void (*bb_timer_proc_callback_t)(uint32_t time);

typedef void (*ble_vs_tbox_init_callback_t)(void);

// IO Capability Values
enum {
    IO_CAPABILITY_DISPLAY_ONLY = 0,
    IO_CAPABILITY_DISPLAY_YES_NO,
    IO_CAPABILITY_KEYBOARD_ONLY,
    IO_CAPABILITY_NO_INPUT_NO_OUTPUT,
    IO_CAPABILITY_KEYBOARD_DISPLAY, // not used by secure simple pairing
};

//ADDRESS TYPE
typedef enum {
    GAP_PUBLIC_ADDRESS_TYPE = 0,
    GAP_RANDOM_ADDRESS_TYPE_STATIC,
    GAP_RANDOM_ADDRESS_NON_RESOLVABLE,
    GAP_RANDOM_ADDRESS_RESOLVABLE,
} gap_random_address_type_t;

typedef enum {
    BD_ADDR_TYPE_PUBLIC = 0,
    BD_ADDR_TYPE_RANDOM = 1,
} bd_addr_type_t;


//ADV_TYPE
enum {
    ADV_TYPE_IND = 0,
    ADV_TYPE_DIRECT_HI_IND,
    ADV_TYPE_SCAN_IND,
    ADV_TYPE_NONCONN_IND,
    ADV_TYPE_DIRECT_LO_IND,
};

//SCAN STA
typedef enum {
    LE_SCAN_IDLE,
    LE_START_SCAN,
    LE_SCANNING,
    LE_STOP_SCAN,
} le_scanning_state_t;

typedef struct {
    uint8_t adv_en;
    uint8_t adv_data[31];
    uint8_t adv_len;
    uint8_t scan_rsp[31];
    uint8_t scan_rsp_len;
    uint16_t adv_int_min;           //advertisement interval
    uint16_t adv_int_max;           //advertisement interval
    uint8_t adv_type;
    uint8_t direct_address_typ;     //only use for direct adv
    uint8_t direct_address[6];      //only use for direct adv
    uint8_t channel_map;
    uint8_t filter_policy;
} adv_param_t;

typedef struct __attribute__((packed)){
    uint8_t     event_type;
    uint8_t     addr_type;
    uint8_t     addr[6];
    char        rssi;
    uint8_t     report_len;
    const uint8_t * report;
    uint8_t     offset;
} adv_report_t;

typedef struct {
     uint8_t   adv_type;
     uint8_t   data_len;
     uint8_t*  data;
} adv_struct_t;

typedef struct {
    uint8_t scan_type;
    uint16_t scan_interval;
    uint16_t scan_window;
} scan_param_t;

typedef struct {
    ///6-byte array address value
    uint8_t  addr[6];
}bd_addr_t;

typedef struct {
    // Key value MSB -> LSB
    uint8_t key[16];
}gap_sec_key_t;

// Do not modify!!
typedef struct {
    // Address type of device. 0 public/1 random
    uint8_t addr_type;
    // BD Address of device
    bd_addr_t addr;
}gap_bdaddr_t;

/**
 * @brief Identity Resolving Key Information
 */
typedef struct {
    // Identify Resolving Key
    gap_sec_key_t irk;
    // Identity broadcast address of device
    gap_bdaddr_t addr;
}gapc_irk_t;

/**
 * @brief Resolving list information about a device.
 */
typedef struct {
    // Privacy Mode
    uint8_t priv_mode;  //PRIV_TYPE_NETWORK = 0x00, Controller accept identity address only
                        //PRIV_TYPE_DEVICE  = 0x01, Controller accept both identity address and resolvable address.
    // Device Identity address
    gap_bdaddr_t addr;
    // Peer device identity resolve key
    uint8_t peer_irk[16];
}gap_ral_dev_info_t;

typedef struct {
    uint8_t rpa_en;
    uint8_t privacy_mode;
    uint16_t renew_to;
    gap_sec_key_t peer_irk;
    gap_bdaddr_t addr;
}rpa_param_t;

typedef struct {
    // Number of entries to be added in the list. 0 means that list content has to be cleard.
    uint8_t size;
    // List of entries to be added in the list.
    gap_bdaddr_t addr;
}wlist_param_t;

typedef struct {
    uint16_t        address_type;
    uint16_t        real_address_type;
    bd_addr_t       address;
    gap_sec_key_t   peer_irk;
} sm_bonding_info_t;

// Read & Write Callbacks for handle range
typedef struct att_service_handler {
    void * item;
    uint16_t start_handle;
    uint16_t end_handle;
    att_read_callback_t read_callback;
    att_write_callback_t write_callback;
    att_event_callback_t event_handler;
} att_service_handler_t;

typedef struct att_client_handler {
    void * item;
    att_read_callback_t read_callback;
    att_notify_callback_t notify_callback;
    att_event_callback_t event_handler;
} att_client_handler_t;

typedef struct {
    uint16_t start_group_handle;
    uint16_t end_group_handle;
    uint16_t uuid16;
    uint8_t  uuid128[16];
} gatt_client_service_t;

typedef struct {
    uint16_t start_handle;
    uint16_t value_handle;
    uint16_t end_handle;
    uint16_t properties;
    uint16_t uuid16;
    uint8_t  uuid128[16];
} gatt_client_characteristic_t;

struct txbuf_tag {
    uint8_t *ptr;
    uint16_t len;
    uint16_t att_handle;
    uint16_t con_handle;
    uint16_t config;
} __attribute__ ((packed)) ;

struct txpkt_tag {
    struct txbuf_tag *buf;
    uint16_t buf_size;
    uint8_t total;
    volatile uint8_t cnt;
    uint8_t rptr;
    volatile uint8_t wptr;
    kick_func_t send_kick;
};

typedef struct {
    uint8_t rf_mode;
    uint8_t tx_power;
    uint8_t tx_freq;
    uint8_t rx_freq;
    uint8_t phy_type;
    uint8_t todo;
} fcc_cfg_t;

typedef struct {
    uint8_t mem[28];
} bt_timer_mem_t;

extern struct txpkt_tag ble_tx;

//control
void bt_init(void);

int bt_setup(void);

void bt_off(void);

//sleep
bool bt_is_sleep(void);

uint32_t bt_sleep_proc(void);

void bt_enter_sleep(void);

void bt_exit_sleep(void);

uint32_t txpkt_init(struct txpkt_tag *txpkt, void *mem_pool, uint8_t total, uint16_t buf_size);

bool txpkt_is_full(struct txpkt_tag *txpkt);

uint8_t txpkt_available_num(struct txpkt_tag *txpkt);

void txpkt_flush(struct txpkt_tag *txpkt);

/**
  * @brief  Triggers ble to start notify data, Can be used with ble_notify_for_handle_kick function
  * @param  txpkt
  * @param  con_handle
  */
void txpkt_server_send_tick(struct txpkt_tag *txpkt, uint16_t con_handle);

/**
  * @brief  Triggers ble to start write data, Can be used with ble_write_cmd_for_character_kick function(Todo)
  * @param  txpkt
  * @param  con_handle
  */
void txpkt_client_send_tick(struct txpkt_tag *txpkt, uint16_t con_handle);

/**
  * @brief  Triggers ble to start sending data
  * @param  con_handle
  */
void ble_send_kick(uint16_t con_handle, uint16_t config);

/**
  * @brief  ble fcc test mode config
  * @param  rf_mode: FCC_RF_MODE
  * @param  tx_power: [0,7]
  * @param  tx_freq: [0,39],freq = 2402 + tx_freq * 2
  * @param  tx_freq: [0,39],freq = 2402 + tx_freq * 2
  * @param  phy_type: 0:1M  1:2M
  * @param  todo: 1
  */
void ble_fcc_cfg_init(fcc_cfg_t *cfg);

/**
 * @brief ble advertisement ctrl
 * @param none
 */
void ble_adv_dis(void);

void ble_adv_en(void);

bool ble_adv_is_en(void);

/**
  * @brief  set up ble advertisement interval
  * @param  interval: 0x20 - 0x4000(uint:0.625ms)
  * @return return true if ok, invalid parameters will return false
  */
bool ble_set_adv_interval(uint16_t interval);

/**
  * @brief  get ble advertisement interval
  * @param  interval: 0x20 - 0x4000(uint:0.625ms)
  * @return return true if ok, invalid parameters will return false
  */
bool ble_get_adv_interval(uint16_t *interval);

/**
 * @brief set advertisement data
 * @param advertising_data (max 31 octets)
 * @param advertising_data_length
 * @return return true if ok, invalid parameters will return false
 */
bool ble_set_adv_data(const uint8_t *adv_buf, uint32_t size);

/**
 * @brief set scan response Data
 * @param advertising_data (max 31 octets)
 * @param advertising_data_length
 * @return return true if ok, invalid parameters will return false
 */
bool ble_set_scan_rsp_data(const uint8_t *scan_rsp_buf, uint32_t size);

/**
 * @brief initialize advertisement parameter
 * @param advertisement parameter
 * @return return true if ok, invalid parameters will return false
 */
bool ble_set_adv_param(adv_param_t* param);

adv_param_t* ble_get_adv_param(void);

/**
 * @brief initialize advertisement parameter
 * @param advertisement parameter
 * @return return true if ok, invalid parameters will return false
 */
bool ble_set_ext_adv_param(adv_param_t* param);

/**
 * @brief analyse advertisement report, the results will be store in advertisement struct
 * @param report, can be get by BLE_EVT_ADV_REPORT
 * @param adv_struct
 * @return analysis is complete will return true, else will return false
 */
bool ble_adv_report_info_analyse(adv_report_t* report, adv_struct_t* adv_struct);

/**
  * @brief  disconnect ble connection according to connect handle
  * @param  con_handle
  */
void ble_disconnect(uint16_t con_handle);

/**
 * @brief ble master create connect by ble address
 * @param addr_ptr
 * @param addr type : 0-3(0:public, 1:random, 2:public identity 3:random identity)
 * @param interval: 6 - 3200(unit: 1.25ms)
 * @param latency
 * @param timeout (unit: 10ms)
 * @return return true if ok, invalid parameters will return false
 */
bool ble_connect_by_addr(uint8_t *addr_ptr, uint8_t addr_type, uint16_t interval, uint16_t conn_latency, uint16_t supervision_timeout);

/**
 * @brief update of the connection parameter for a given LE connection
 * @param con_handle
 * @param interval: 6 - 3200(unit: 1.25ms)
 * @param latency
 * @param timeout (unit: 10ms)
 * @return return true if ok, invalid parameters will return false
 */
bool ble_update_conn_param(uint16_t con_handle, uint16_t interval, uint16_t latency, uint16_t timeout);

/**
 * @brief update of the connection parameter for a given LE connection
 * @param con_handle
 * @param interval_min: 6 - 3200(unit: 1.25ms)
 * @param interval_max: 6 - 3200(unit: 1.25ms) interval_min <= interval_max
 * @param latency
 * @param timeout (unit: 10ms)
 * @return return true if ok, invalid parameters will return false
 */
bool ble_update_conn_param_2(uint16_t con_handle, uint16_t interval_min, uint16_t interval_max, uint16_t latency, uint16_t timeout);

/**
 * @brief get of the connection parameter for a given LE connection
 * @param con_handle
 * @param interval: 6 - 3200(unit: 1.25ms)
 * @param latency
 * @param timeout (unit: 10ms)
 * @return return true if ok, invalid parameters will return false
 */
bool ble_get_conn_param(uint16_t con_handle, uint16_t *interval, uint16_t *latency, uint16_t *timeout);

/**
 * @brief Disable latency, only valid for the slave role. Even if connection parameters are updated later, latency is disabled also
 * @param con_handle
 * @return return true if ok, invalid parameters will return false
 */
bool ble_disable_latency(uint16_t con_handle);

/**
 * @brief Enable latency, only valid for the slave role.
 * @param con_handle
 * @return return true if ok, invalid parameters will return false
 */
bool ble_enable_latency(uint16_t con_handle);

/**
  * @brief  notify data according to handle
  * @param  connect handle
  * @param  attribute handle
  * @param  buf to be send
  * @param  len(must be less than att mtu)
  * @return return 0 if ok, other refer to ATT_ERR_CODE
  */
int ble_notify_for_handle(uint16_t con_handle, uint16_t att_handle, uint8_t* buf, uint16_t len);

/**
  * @brief  notify data according to handle
  * @param  connect handle
  * @param  attribute handle
  * @param  buf to be send
  * @param  len(must be less than att mtu)
  * @param  kick_cfg, The value is as follows:
            TXPKT_KICK_ENABLE: the Bluetooth thread is triggered to start sending data,
            TXPKT_KICK_DISABLE: the Bluetooth thread will not be triggered to send data immediately, but the data will be cached
            TXPKT_KICK_AUTO: Automatically managed by the Btstack
            It is suitable for continuous data transmission, and can trigger the Bluetooth thread to send data at the last to reduce the switching of threads
  * @return return 0 if ok, other refer to ATT_ERR_CODE
  */
int ble_notify_for_handle_kick(uint16_t con_handle, uint16_t att_handle, uint8_t* buf, uint16_t len, uint8_t kick_cfg);

/**
  * @brief  indicate data according to handle
  * @param  connect handle
  * @param  attribute handle
  * @param  buf to be send
  * @param  len(must be less than att mtu)
  * @return return 0 if ok, other refer to ATT_ERR_CODE
  */
int ble_indicate_for_handle(uint16_t con_handle, uint16_t att_handle, uint8_t* buf, uint16_t len);


/**
  * @brief  Writes the characteristic value using the characteristic's value handle
  * @param  connect handle
  * @param  character
  * @param  buf to be send
  * @param  len(must be less than att mtu)
  * @return return 0 if ok, other refer to ATT_ERR_CODE
  */
int ble_write_req_for_character(uint16_t con_handle, gatt_client_characteristic_t* character, uint8_t* buf, uint16_t len);

/**
  * @brief  Writes the characteristic value using the characteristic's value handle without an acknowledgment that the write was successfully performed.
  * @param  connect handle
  * @param  character
  * @param  buf to be send
  * @param  len(must be less than att mtu)
  * @return return 0 if ok, other refer to ATT_ERR_CODE
  */
int ble_write_cmd_for_character(uint16_t con_handle, gatt_client_characteristic_t* character, uint8_t* buf, uint16_t len);

/**
 * @brief reads the characteristic value using the characteristic's value handle.
 * @param  con_handle
 * @param  character
 * @return return 0 if ok, other refer to ATT_ERR_CODE
 */
int ble_read_req_for_character(uint16_t con_handle, gatt_client_characteristic_t* character);

/**
 * @brief reads the long characteristic value using the characteristic's value handle.
 * @param  con_handle
 * @param  character
 * @param  offset
 * @return return 0 if ok, other refer to ATT_ERR_CODE
 */
int ble_read_blob_for_character(uint16_t con_handle, gatt_client_characteristic_t* character, uint16_t offset);

/**
 * @brief set ble address type
 * @param address type
 */
void gap_random_address_set_mode(gap_random_address_type_t random_address_type);

/**
 * @brief BLE initialize callback function registration,
 * @param callback function, which will be called in bluetooth thread
 */
void ble_init_callback_register(ble_init_callback_t  func);

/**
 * @brief BLE test box initialize callback function registration,
 * @param callback function, which will be called in bluetooth thread
 */
void ble_vs_tbox_init_callback_register(ble_vs_tbox_init_callback_t  func);

/**
 * @brief Register server packet handle
 */
void att_server_register_service_handler(att_service_handler_t * handler);

/**
 * @brief Register client packet handle
 */
void att_client_register_handler(att_client_handler_t * handler);

/**
 * @brief ble sm init
 * @param security_req_en(whether to send an sm request when ble connecting)
 * @param io_capability
 * @param authentication_req_flag
 */
void ble_sm_init(uint8_t security_req_en, uint8_t io_capability, uint8_t authentication_req_flag);

/**
 * @brief Trigger Security Request
 */
void ble_sm_send_security_request(ble_con_handle_t con_handle);

/**
 * @brief setup ATT server
 * @param db attribute database created by profile tool
 */
void att_server_init(uint8_t const * db);

/**
 * @brief Set up GATT client.
 */
void gatt_client_init(void);

/**
 * @brief get att mtu
 * @param con_handle
 * @return mtu if ok, 0 otherwise
 */
uint8_t att_server_get_mtu(uint16_t con_handle, uint16_t * mtu);

/**
 * @brief Get att mtu. If status is equal to ATT_ERROR_NO_ERROR, it returns the real value, otherwise the default value ATT_DEFAULT_MTU
 * @param  con_handle
 * @param  mtu
 * @return return 0 if ok, other refer to ATT_ERR_CODE
 */
uint8_t gatt_client_get_mtu(uint16_t con_handle, uint16_t * mtu);

/**
 * @brief ble scan ctrl
 * @param none
 */
void ble_scan_en(void);

void ble_scan_dis(void);

/**
 * @brief  ble get scan status
 * @param  none
 * @return sta : 0-3(refer to le_scanning_state_t)
 */
le_scanning_state_t ble_get_scan_sta(void);

/**
 * @brief ble set scan param
 * @param type    : 0 or 1，0(Passive scan,no scan_rsp)，1(Active scan,adv+scan_rsp)
 * @param interval: 4 - 16384(unit: 0.625ms)
 * @param window  : 4 - 16384(less than or equal to interval unit: 0.625ms)
 * @return return true if ok, invalid parameters will return false
 */
bool ble_set_scan_param(scan_param_t* param);


/**
 * @brief Discovers all primary services. For each found service, BLE_EVT_SERVICE_FIND_RESULT will be generated and passed to the registered callback. BLE_EVT_PROFILE_FIND_DONE, marks the end of discovery.
 * @param  con_handle
 * @return return 0 if ok, other refer to ATT_ERR_CODE
 */
uint8_t ble_client_discover_primary_services(uint16_t con_handle);

/**
 * @brief Discovers a specific primary service given its UUID. For each found service, BLE_EVT_SERVICE_FIND_RESULT will be generated and passed to the registered callback. BLE_EVT_PROFILE_FIND_DONE, marks the end of discovery.
 * @param con_handle
 * @param uuid16
 * @return return 0 if ok, other refer to ATT_ERR_CODE
 */
uint8_t ble_client_discover_primary_services_by_uuid16(uint16_t con_handle, uint16_t uuid16);

uint8_t ble_client_discover_primary_services_by_uuid128(uint16_t con_handle, const uint8_t * uuid128);


/**
 * @brief Get field service from event BLE_EVT_SERVICE_FIND_RESULT
 * @param event packet
 * @param Pointer to storage for service
 */
void ble_service_query_result_get_service(const uint8_t * event, gatt_client_service_t * service);

/**
 * @brief Discovers all characteristics within the specified service. For each found characteristic, an le_characteristics_event_t with type set to BLE_EVT_CHARACTERISTIC_FIND_RESULT will be generated and passed to the registered callback. The gatt_complete_event_t with type set to BLE_EVT_PROFILE_FIND_DONE, marks the end of discovery.
 * @param  callback
 * @param  con_handle
 * @param  service
 * @return return 0 if ok, other refer to ATT_ERR_CODE
 */
uint8_t ble_client_discover_characteristics_for_service(uint16_t con_handle, gatt_client_service_t * service);

/**
 * @brief Get field characteristic from event BLE_EVT_CHARACTERISTIC_FIND_RESULT
 * @param event packet
 * @param Pointer to storage for characteristic
 */
void ble_characteristic_query_result_get_characteristic(const uint8_t * event, gatt_client_characteristic_t * characteristic);

/**
 * @brief Discover all characteristics within the specified service, and return those that match the given UUID. For each found characteristic, BLE_EVT_CHARACTERISTIC_FIND_RESULT will be generated and passed to the registered callback. BLE_EVT_PROFILE_FIND_DONE, marks the end of discovery.
 * @param  con_handle
 * @param  service
 * @param  uuid
 * @return return 0 if ok, other refer to ATT_ERR_CODE
 */
uint8_t ble_client_discover_characteristics_for_service_by_uuid16(uint16_t con_handle, gatt_client_service_t * service, uint16_t uuid16);

uint8_t ble_client_discover_characteristics_for_service_by_uuid128(uint16_t con_handle, gatt_client_service_t * service, const uint8_t * uuid128);


/**
 * @brief Writes the client characteristic configuration of the specified characteristic.
 * @param  con_handle
 * @param  characteristic
 * @param  configuration : GATT_CCC_NOTIFICATION, GATT_CCC_INDICATION
 * @return return 0 if ok, other refer to ATT_ERR_CODE
 */
uint8_t ble_client_write_client_characteristic_configuration(uint16_t con_handle, gatt_client_characteristic_t * characteristic, uint16_t configuration);

/**
 * @brief Get specific characteristic struct by its uuid.
 * @param  ALL characteristics to be matched
 * @param  The number of characteristics
 * @param  uuid
 * @return return 0 if ok, other refer to ATT_ERR_CODE
 */
gatt_client_characteristic_t* ble_get_characteristic_for_uuid16(gatt_client_characteristic_t *characteristic, uint8_t num, uint16_t uuid16);

gatt_client_characteristic_t* ble_get_characteristic_for_uuid128(gatt_client_characteristic_t *characteristic, uint8_t num, uint8_t *uuid128);


/**
  * @brief  Host renew resolvable private address timeout.
  * @param  rpa params. mainly timeout in seconds and address resolution enable.
  * @return none
  */
void ble_set_rslv_renew_to(rpa_param_t *param);

/**
  * @brief  Host set address resolution enable.
  * @param  1 enable
            0 disable.
  * @return none
  */
void ble_set_rslv_enable(uint8_t enable);

/**
  * @brief  Host add device to resolvable address list.
  * @param  privacy mode.
  * @param  peer device address.
  * @param  peer device irk.
  * @return none
  */
void ble_add_dev_to_ral_list(gap_ral_dev_info_t *ral_dev_info);

/**
  * @brief  Host remove device from resolvable address list.
  * @param  privacy mode.
  * @param  peer device address.
  * @param  peer device irk.
  * @return none
  */
void ble_rmv_dev_from_ral_list(gap_ral_dev_info_t *ral_dev_info);

/**
  * @brief  Host add device to filter accept list.
  * @param  size of wlist.
  * @param  peer device identity address type.
  * @param  peer device identity address.
  * @return none
  */
void ble_add_dev_to_white_list(wlist_param_t *param);

/**
  * @brief  Host remove device from filter accept list.
  * @param  peer device identity address type.
  * @param  peer device identity address.
  * @return none
  */
void ble_rmv_dev_from_white_list(wlist_param_t *param);

/**
  * @brief  Host read filter accept list size.
  * @return none
  */
void ble_rd_dev_white_list(void);

/**
  * @brief  Host clear filter accept list.
  * @return none
  */
void ble_clr_dev_white_list(void);

/**
  * @brief  Used by the user to enter passkey when BLE_EVT_PASSKEY_INPUT event is triggered.
  * @return none
  */
bool ble_sm_passkey_input(uint16_t con_handle, uint32_t passkey);

/**
 * @brief Delete the bonding information of a specified address
 * @param address_type
 * @param address
 * @return return true if ok, invalid parameters will return false
 */
bool ble_delete_bonding_for_addr(bd_addr_type_t address_type, bd_addr_t address);

/**
 * @brief Delete the bonding information of a specified index
 * @param index: [0,N), N can be get form ble_get_bonding_cnt() function
 * @return return true if ok, invalid parameters will return false
 */
bool ble_delete_bonding_for_index(uint8_t index);

/**
 * @brief Delete all bonding information
 */
void ble_delete_bonding_all(void);

/**
 * @brief Get the number of bonding information
 * @return The number of binding information
 */
uint8_t ble_get_bonding_cnt(void);


/**
 * @brief Gets the bonding information for the specified index
 * @param index: [0,N), N can be get form ble_get_bonding_cnt() function
 * @return specified bonding information
 */
sm_bonding_info_t* ble_get_bonding_info_for_index(uint8_t index);

/**
 * @brief  Initialize the timer memery pool.
 * @note   This function and a series of related functions are invoked after bt init.
 * @param  pool: memery pool head address.
 * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
 * @retval None.
 */
void bt_alarm_timer_init(void *pool, uint32_t size);

/**
 * @brief  Extend the timer memery pool, it can be used before and after initialization.
 * @param  pool: memery pool head address.
 * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
 * @retval result code.
 */
uint8_t bt_alarm_timer_mem_extend(void *pool, uint32_t size);

/**
 * @brief  Free the timer memery pool, and all timers in the space are released.
 * @param  pool: memery pool head address.
 * @param  size: byte size of memery pool, one alarm timer need 28Bytes memery.
 * @retval result code.
 */
uint8_t bt_alarm_timer_mem_free(void *pool, uint32_t size);

/**
 * @brief  Start specified id alarm timer.
 * @param  handle: alarm timer handle.
 * @retval result code.
 */
uint8_t bt_alarm_timer_start(uint32_t handle);

/**
 * @brief  Stop specified id alarm timer.
 * @param  handle: alarm timer handle.
 * @retval result code.
 */
uint8_t bt_alarm_timer_stop(uint32_t handle);

/**
 * @brief  Acquire a alarm timer.
 * @param  handle: alarm timer handle.
 * @param  interval: alarm timer trigger interval, unit [1, 0xffffff) ms.
 * @param  is_repeat: trigger mode.
 * @param  callback: callback function.
 * @retval result code.
 */
uint8_t bt_alarm_timer_acquire(uint32_t *handle, uint32_t interval, uint8_t is_repeat, void (*callback)(uint32_t handle));

/**
 * @brief  Release specified id alarm timer.
 * @param  handle: alarm timer handle.
 * @retval result code.
 */
uint8_t bt_alarm_timer_release(uint32_t handle);

/**
 * @brief  Query specified id alarm timer remain time.
 * @param  handle: alarm timer handle.
 * @param  remain: the remain time for specified id alarm timer.
 * @retval result code.
 */
uint8_t bt_alarm_timer_query_time(uint32_t handle, uint32_t *remain);

/**
 * @brief  Modify specified id alarm timer interval, if the timer is start, it
 *         will be re-start after update interval param.
 * @param  handle: alarm timer handle.
 * @param  interval: new interval, unit [1, 0xffffff) ms.
 * @param  is_repeat: new is_repeat mode state.
 * @retval result code.
 */
uint8_t bt_alarm_timer_modify_interval(uint32_t handle, uint32_t interval, uint8_t is_repeat);

/**
 * @brief  Get the time that depends on the Bluetooth clock.
 * @retval The value of current time, unit: (312.5 us).
 */
uint32_t bb_time_hs_get(void);

/**
 * @brief  Get connection rssi .
 * @param  conhdl: connect handle.
 * @retval -128 ~ 127dBm.
 */
int8_t ble_get_conn_rssi(uint16_t conhdl);

/**
 * @brief Set device random static address.
 * @param device random static address.
 * @return none
 */
void ble_set_static_addr(uint8_t *addr);

void ble_event_start_hook_register(uint16_t con_handle, void (*callback)(void));

/**
 * @brief  Config BLE DataLength suggested max length, it should be invoke after stack init and before link created.
 * @param  rx_octets: range [27, 251] in bytes, DataLengthExchange will refered to.
 * @param  tx_octets: range [27, 251] in bytes, DataLengthExchange will refered to.
 * @retval none
 */
void ble_suggested_max_length_write(uint16_t rx_octets, uint16_t tx_octets);


#endif //_API_BTSTACK_H
