#ifndef _API_BTSTACK_H
#define _API_BTSTACK_H

//Working mode
#define MODE_NORMAL                     0       //In normal connection mode, turn off the DUT test
#define MODE_NORMAL_DUT                 1       //Normal connection mode, enabling DUT test
#define MODE_FCC_TEST                   2       //FCC test mode, communication through serial port
#define MODE_BQB_RF_BREDR               3       //BR/EDR DUT test mode, communicating via Bluetooth
#define MODE_BQB_RF_BLE                 4       //BLE DUT test mode, communication through serial port

//Bluetooth function
#define PROF_A2DP                       0x0007  //Bluetooth music function
#define PROF_HID                        0x0018  //Bluetooth keyboard function
#define PROF_HFP                        0x0060  //Bluetooth call function
#define PROF_SPP                        0x0080  //Bluetooth serial port function
#define PROF_PBAP                       0x0100  //Bluetooth phonebook function
#define PROF_HSP                        0x0200

//Bluetooth status
enum {
    BT_STA_OFF,                                 //Bluetooth module is off
    BT_STA_INITING,                             //Initializing
    BT_STA_IDLE,                                //Bluetooth module open, not connected

    BT_STA_SCANNING,                            //Scanning
    BT_STA_DISCONNECTING,                       //Disconnecting
    BT_STA_CONNECTING,                          //Connecting

    BT_STA_CONNECTED,                           //Connected
    BT_STA_PLAYING,                             //Play
    BT_STA_INCOMING,                            //Incoming call ring
    BT_STA_OUTGOING,                            //Outgoing
    BT_STA_INCALL,                              //On call
    BT_STA_OTA,                                 //OTA upgrading
};

//Bluetooth notification
enum {
    BT_NOTICE_INIT_FINISH,                      //Bluetooth initialization completed
    BT_NOTICE_CONNECT_START,                    //Start connecting back to the phone, param[0]=status, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_CONNECT_FAIL,                     //Failed to connect back to the phone, param[0]=reason, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_DISCONNECT,                       //Bluetooth disconnected,     param[0]=feat,index, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_LOSTCONNECT,                      //Bluetooth connection lost, param[0]=status, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_CONNECTED,                        //Bluetooth connection succeeded, param[0]=feat,index, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_SCO_SETUP,
    BT_NOTICE_SCO_FAIL,
    BT_NOTICE_SCO_KILL,
    BT_NOTICE_INCOMING,                         //Incoming call
    BT_NOTICE_RING,                             //Incoming call ring
    BT_NOTICE_OUTGOING,                         //Deenergize
    BT_NOTICE_CALL_NUMBER,                      //Incoming/outgoing number
    BT_NOTICE_CALL,                             //Establish a call
    BT_NOTICE_SET_SPK_GAIN,                     //Set call volume
    BT_NOTICE_MUSIC_PLAY,                       //Bluetooth music starts playing
    BT_NOTICE_MUSIC_STOP,                       //Bluetooth music stop playing
    BT_NOTICE_MUSIC_CHANGE_VOL,                 //Change Bluetooth music volume
    BT_NOTICE_MUSIC_SET_VOL,                    //Set Bluetooth music volume
    BT_NOTICE_HID_CONN_EVT,                     //HID service connection event
    BT_NOTICE_RECON_FINISH,                     //The back-connection is completed, param[0]=status, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_ABORT_STATUS,                     //Abort status, param[0]=status, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_NORCONNECT_FAIL,                  //Mobile phone initiated connection half failed
    BT_NOTICE_LOW_LATENCY_STA,                  //Low delay state switching
    BT_NOTICE_MUSIC_CHANGE_DEV,                 //When dragging 1 to 2, the playback device is changed, such as switching from mobile phone A to mobile phone B, param[0]=index, param[1]=feature

    BT_NOTICE_TWS_SEARCH_FAIL = 0x40,           //Search TWS failed,, param[0]=(0=timeout, 0x0B=conn_exists, 0x0C=cmd_disallow)
    BT_NOTICE_TWS_CONNECT_START,                //Start to connect back to TWS, param[0]=status, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_TWS_CONNECT_FAIL,                 //TWS back-connection failed, param[0]=reason, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_TWS_DISCONNECT,                   //TWS tooth is disconnected,   param[0]=feat,index, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_TWS_LOSTCONNECT,                  //TWS connection lost, param[0]=status, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_TWS_CONNECTED,                    //TWS connection succeeded, param[0]=feat,index, param[1]=reason, param[7:2]=bd_addr
    BT_NOTICE_TWS_SET_VOL,                      //Set TWS music volume
    BT_NOTICE_TWS_HID_SHUTTER,                  //Remote TWS photographing key
    BT_NOTICE_TWS_USER_KEY,                     //TWS custom key
    BT_NOTICE_TWS_RES4,
    BT_NOTICE_TWS_STATUS_CHANGE,
    BT_NOTICE_TWS_ROLE_CHANGE,                  //Master-slave character transformation
    BT_NOTICE_TWS_RES5,
    BT_NOTICE_TWS_RES6,
    BT_NOTICE_TWS_RES7,
    BT_NOTICE_TWS_WARNING,
};

//param[0]=feat,index
enum
{
    FEAT_TWS_FLAG       = 0x80,
    FEAT_TWS_ROLE       = 0x40,
    FEAT_TWS_MUTE_FLAG  = 0x20,
    FEAT_TWS_FIRST_ROLE = 0x10,
    FEAT_INCOME_CON     = 0x08,
    FEAT_FIRST_CON      = 0x04,
    FEAT_INDEX_MASK     = 0x03,
};

//Control message
enum {
    BT_CTL_VOL_CHANGE               = 0,        //Volume adjustment
    BT_CTL_PLAY_PAUSE,                          //Switch play and pause
    BT_CTL_MSC_RES0,
    BT_CTL_MSC_RES1,
    BT_CTL_EAR_STA_CHANGE,
    BT_CTL_NR_STA_CHANGE,
    BT_CTL_AAP_USER_DATA,
    BT_CTL_MSC_RES3,

    BT_CTL_CALL_REDIAL,                         //Callback call (last call)
    BT_CTL_CALL_REDIAL_NUMBER,                  //Call back (get the number from hfp_get_outgoing_number)
    BT_CTL_CALL_ANSWER_INCOM,                   //Answer the call (suspend the current call during the three-way connection)
    BT_CTL_CALL_ANSWER_INCOM_REJ_OTHER,         //Answer the call (hang up the current call during the three-way connection)
    BT_CTL_CALL_TERMINATE,                      //Hang up or call
    BT_CTL_CALL_SWAP,                           //Switch three calls
    BT_CTL_CALL_PRIVATE_SWITCH,                 //Switch private calls
    BT_CTL_HFP_REPORT_BAT,                      //Report battery level
    BT_CTL_HFP_SPK_GAIN,                        //Set call speaker volume
    BT_CTL_HFP_MIC_GAIN,                        //Set call microphone volume
    BT_CTL_HFP_AT_CMD,                          //Send AT command (get command from hfp_get_at_cmd)
    BT_CTL_HFP_SIRI_SW,                         //Call out/close siri
    BT_CTL_HFP_CUSTOM_AT_CMD,
    BT_CTL_HFP_RES0,
    BT_CTL_HFP_RES1,
    BT_CTL_HFP_RES2,
    BT_CTL_HFP_RES3,

    BT_CTL_TWS_DISCONNECT,                      //Disconnect TWS
    BT_CTL_TWS_CONNECT,                         //Establish TWS connection
    BT_CTL_TWS_NOTICE_RING,
    BT_CTL_TWS_SWITCH,                          //Master-slave switching
    BT_CTL_NOR_CONNECT,
    BT_CTL_NOR_DISCONNECT,
    BT_CTL_HID_CONNECT,
    BT_CTL_HID_DISCONNECT,
    BT_CTL_TWS_RES0,
    BT_CTL_BLE_ADV_DISABLE,                     //Turn off BLE broadcast
    BT_CTL_BLE_ADV_ENABLE,                      //Turn on BLE radio
    BT_CTL_TWS_RES1,
    BT_CTL_TWS_RES2,
    BT_CTL_TWS_RES3,

    BT_CTL_DUEROS_AI_START,
    BT_CTL_DUEROS_AI_STOP,
    BT_CTL_DUEROS_DMA_CTL,
    BT_CTL_FOT_RESP,
    BT_CTL_LOW_LATENCY_EN,
    BT_CTL_LOW_LATENCY_DIS,
    BT_CTL_FCC_TEST,
    BT_CTL_MAX,

    BT_CTL_VOLUME_UP            = 0xff0041,     //Volume increase
    BT_CTL_VOLUME_DOWN          = 0xff0042,     //Volume decrease
    BT_CTL_MUTE                 = 0xff0043,     //MUTE
    BT_CTL_PLAY                 = 0xff0044,     //Play
    BT_CTL_STOP                 = 0xff0045,     //Stop
    BT_CTL_PAUSE                = 0xff0046,     //Pause
    BT_CTL_RECORD               = 0xff0047,
    BT_CTL_REWIND               = 0xff0048,     //Fast rewind
    BT_CTL_FAST_FORWARD         = 0xff0049,     //Fast forward
    BT_CTL_EJECT                = 0xff004a,
    BT_CTL_FORWARD              = 0xff004b,     //Next song
    BT_CTL_BACKWARD             = 0xff004c,     //Previous song
    BT_CTL_REWIND_END           = 0xff00c8,     //End Rewind
    BT_CTL_FAST_FORWARD_END     = 0xff00c9,     //End fast forward

    BT_CTL_NO                   = 0xffffff,
};

enum bt_msg_comm_t {
    COMM_BT_CTL0,                               //Message without parameters
    COMM_BT_START_WORK,                         //Bluetooth starts working
    COMM_BT_SET_SCAN,                           //Set discoverable/connectable
    COMM_BT_CONNECT,                            //Connect Bluetooth
    COMM_BT_DISCONNECT,                         //Disconnect Bluetooth
    COMM_BT_ABORT_RECONNECT,                    //Abort reconnection
    COMM_BT_ATT_MSG,
    COMM_BT_SET_SCAN_INTV,                      //Set PAGE SCAN PARAM
};


enum bt_msg_hid_t {
    HID_KEYBOARD,
    HID_CONSUMER,
    HID_TOUCH_SCREEN,
};

//Bluetooth message
enum bt_msg_t {
    BT_MSG_CTRL                 = 0,            //Bluetooth control message
    BT_MSG_COMM,
    BT_MSG_RES1,
    BT_MSG_TWS,                                 //TWS news
    BT_MSG_ADV0,
    BT_MSG_A2DP,                                //A2DP news
    BT_MSG_HFP,                                 //HFP news
    BT_MSG_HSP,                                 //HSP news
    BT_MSG_HID,                                 //HID news，KEYPAD key/CONSUMER Key/touch screen
    BT_MSG_PBAP,                                //PBAP news
    BT_MSG_MAX,
    BT_MSG_RES                  = 0xf0,         //0xf0~0xff Reserved for api with more parameters
};

enum sync_info_enum {
    SYNC_INFO_SETTING,                  //VOL/LANG/EQ/BAT/...
    SYNC_INFO_LEDCNT,                   //synchronization led cnt
    SYNC_INFO_EQPARAM,
    SYNC_INFO_FOT_DATA,
    SYNC_INFO_DUEROS_DMA_DATA,
};

//LE Addr Type, public or random(static or non resolvable or resolvable)
typedef enum {
    GAP_RANDOM_ADDRESS_TYPE_OFF = 0,    //Public
    GAP_RANDOM_ADDRESS_TYPE_STATIC,
    GAP_RANDOM_ADDRESS_NON_RESOLVABLE,
    GAP_RANDOM_ADDRESS_RESOLVABLE,
} gap_random_address_type_t;

//LE状态
enum {
    LE_STA_STANDBY,
    LE_STA_ADVERTISING,                         //be on the air
    LE_STA_CONNECTION,                          //Connected
};

//LE GATT Service related
/**
    BLE GATTS ERR return
*/
#define BLE_GATTS_SUCCESS                                       0x00
#define BLE_GATTS_SRVC_TYPE_ERR                                 0x01
#define BLE_GATTS_SRVC_RULES_ERR                                0x02
#define BLE_GATTS_SRVC_PROPS_ERR                                0x03
#define BLE_GATTS_SRVC_ATT_FULL_ERR                             0x04
#define BLE_GATTS_SRVC_PROFILE_FULL_ERR                         0x05


/**
    att property flag
*/
#define ATT_BROADCAST                                           0x01
#define ATT_READ                                                0x02
#define ATT_WRITE_WITHOUT_RESPONSE                              0x04
#define ATT_WRITE                                               0x08
#define ATT_NOTIFY                                              0x10
#define ATT_INDICATE                                            0x20
#define ATT_AUTHENTICATED_SIGNED_WRITE                          0x40
#define ATT_EXTENDED_PROPERTIES                                 0x80
#define ATT_DYNAMIC                                             0x100
#define ATT_UUID128                                             0x200
#define ATT_AUTHENTICATION_REQUIRED                             0x400
#define ATT_AUTHORIZATION_REQUIRED                              0x800

//Gatt Client Config
#define GATT_CLIENT_CHARACTERISTIC_CONFIGURATION_NOTIFICATION       0x01
#define GATT_CLIENT_CHARACTERISTIC_CONFIGURATION_INDICATION         0x02

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 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_handler_t) (uint8_t event_type, uint8_t *param, uint16_t size);
typedef void (*ble_init_callback_t)(void);
typedef uint16_t hci_con_handle_t;

/**
 * @format 121
 * @param status
 * @param connection_handle
 * @param reason
 */
#define HCI_EVENT_DISCONNECTION_COMPLETE                            0x05

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

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

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

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

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

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

#define ATT_EVENT_BOND_IND                          				0xB8

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

#define HCI_EVENT_LE_META                                           0x3E

/**
 * @brief 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,
};

/**
    define group GATT Server Service Types
*/
typedef enum {
    BLE_GATTS_SRVC_TYPE_PRIMARY  =   0x00,                //Primary Service
    BLE_GATTS_SRVC_TYPE_SEVONDARY=   0x01,                //Secondary Service
    BLE_GATTS_SRVC_TYPE_INCLUDE  =   0x02,                //include Type
}ble_gatts_service_type;

/**
    define group GATT Server UUID Types
*/
typedef enum {
    BLE_GATTS_UUID_TYPE_16BIT  =   0x00,                //UUID 16BIT
    BLE_GATTS_UUID_TYPE_128BIT =   0x01,                //UUID 128BIT
}ble_gatts_uuid_type;

/**
    define GATT handler callback
*/
typedef u8 (*gatt_callback_func)(u8 *ptr, u16 len);


/**
    define GATT service base
*/
typedef struct gatts_service_base{
    uint8_t handle;
    uint8_t att_index;
}gatts_service_base_st;

/**
    define GATT service uuid
*/
typedef struct gatts_uuid_base{
    uint16_t props;
    uint8_t type;
    const uint8_t *uuid;
}gatts_uuid_base_st;

/**
 * @brief Peripheral Advertisement Params Typedef.
 */
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 adv_event_type;
    uint8_t address_type;
    uint8_t address[6];
    uint8_t rssi;
    uint8_t data_length;
    uint8_t *data;
    uint8_t offset;
} adv_report_t;

typedef struct {
    void * item;
    att_read_callback_t     read_callback;
    att_notify_callback_t   notify_callback;
    att_event_handler_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;

extern uint8_t cfg_bt_work_mode;
extern uint8_t cfg_bt_max_acl_link;
extern bool cfg_bt_dual_mode;
extern bool cfg_bt_scan_ctrl_mode;
extern bool cfg_bt_simple_pair_mode;
extern uint16_t cfg_bt_support_profile;
extern uint16_t cfg_bt_support_codec;
extern uint8_t cfg_bt_hid_type;
extern uint8_t cfg_bt_connect_times;
extern uint8_t cfg_bt_pwrup_connect_times;
extern uint16_t cfg_bt_sup_to_connect_times;

extern uint8_t cfg_bt_rf_def_txpwr;
extern uint8_t cfg_bt_page_txpwr;
extern uint8_t cfg_bt_inq_txpwr;
extern uint8_t cfg_ble_page_txpwr;
extern uint8_t cfg_ble_page_rssi_thr;

extern const uint16_t link_info_page_size;

extern bool cfg_bt_spp_rx_flow_ctrl_en;

#define bt_is_scan_ctrl()                       cfg_bt_scan_ctrl_mode

//control
void bt_fcc_init(void);
void bt_init(void);                             //Initialize Bluetooth variables
int bt_setup(void);                             //Open Bluetooth module
void bt_off(void);                              //Turn off Bluetooth module
void bt_wakeup(void);                           //Wake up Bluetooth module
void bt_start_work(uint8_t opcode, uint8_t scan_en); //Bluetooth starts working, opcode: 0=loopback, 1=no loopback
void bt_send_msg_do(uint msg);                  //Bluetooth control message, see bt for parameters_ msg_ t

void bt_set_scan(uint8_t scan_en);              //Turn on/off discoverable and connectable, bit0=discoverable, bit1=connectable
uint8_t bt_get_scan(void);                      //Get the discoverable and connectable status of the setting (the setting will not take effect immediately after the connection is completed, and the connection needs to be disconnected)
uint8_t bt_get_curr_scan(void);                 //Get the current discoverable and connectable status
void bt_connect(void);                          //Bluetooth device back-connection, back-connection times in cfg_ bt_ connect_ Times configuration
void bt_connect_address(void);                  //Bluetooth device callback address, the callback address is in bt_ get_ connect_ Addr function setting
void bt_disconnect(uint reason);                //Bluetooth device is disconnected, reason: 0=separate disconnection (warehousing); 1=Disconnection and synchronous shutdown (key/automatic shutdown); The user calls disconnect independently without shutting down reason=0xff
void bt_hid_connect(void);                      //Bluetooth HID service callback
void bt_hid_disconnect(void);                   //Bluetooth HID service disconnected
int bt_hid_is_connected(void);
bool bt_hid_is_ready_to_discon(void);

//status
uint bt_get_disp_status(void);                  //Get the current display status of Bluetooth, V060
uint bt_get_status(void);                       //Get the current status of Bluetooth
uint8_t bt_get_scan(void);                      //Determine the current connectable and scannable status
uint8_t bt_get_curr_scan(void);                 //Get real-time connectable and scannable status
bool bt_is_testmode(void);                      //Judge whether the current Bluetooth is in test mode
bool bt_is_sleep(void);                         //Judge whether Bluetooth is in sleep state
bool bt_is_connected(void);                     //Judge whether Bluetooth is connected (TWS auxiliary ear is connected, or main ear is connected to mobile phone)
bool bt_is_ios_device(void);                    //Judge whether the currently played ios device
uint32_t bt_sleep_proc(void);
void bt_enter_sleep(void);
void bt_exit_sleep(void);
void bt_updata_local_name(char *bt_name);
bool bt_sync_tick(void);                        //Synchronize to 50ms according to the Bluetooth clock, with an error of 5ms
bool bt_is_low_latency(void);                   //Judge whether Bluetooth is in low delay state

//info
bool bt_get_link_btname(uint8_t index, char *name, uint8_t max_size); //index: 0=link0, 1=link1, 0xff=auto(default link0)
void bt_nor_delete_link_info(void);
bool bt_nor_get_link_info(uint8_t *bd_addr);

#define bt_send_msg(ogf, ocf)                   bt_send_msg_do((ogf<<24) | (ocf))
#define bt_ctrl_msg(msg)                        bt_send_msg(BT_MSG_CTRL, msg)
#define bt_comm_msg(msg, param)                 bt_send_msg(BT_MSG_COMM, (msg<<16) | (u16)param)
#define bt_spp_msg(msg, param)                  bt_send_msg(BT_MSG_SPP, (msg<<16) | (u16)param)
#define bt_hid_msg(msg, param)                  bt_send_msg(BT_MSG_HID, (msg<<16) | (u16)param)

//Bluetooth connection
#define bt_scan_enable()                        bt_set_scan(0x03)                       //Open Scan
#define bt_scan_disable()                       bt_set_scan(0x00)                       //close Scan
#define bt_set_scan_param(ps_intv,is_intv)      bt_comm_msg(COMM_BT_SET_SCAN_INTV, (ps_intv << 8) | is_intv)  //Set scan parameters, 0x100 * (intv+1)
#define bt_abort_reconnect()                    bt_comm_msg(COMM_BT_ABORT_RECONNECT, 0xffff)       //Terminate loopback
#define bt_abort_reconnect_silence(feat)        bt_comm_msg(COMM_BT_ABORT_RECONNECT, (u16)feat)     //Terminate loopback，No message callback. Feature: 0=Mobile phone, BT_ FEAT_ TWS=TWS

#define bt_low_latency_enble()                  bt_ctrl_msg(BT_CTL_LOW_LATENCY_EN)      //Bluetooth enable low latency
#define bt_low_latency_disable()                bt_ctrl_msg(BT_CTL_LOW_LATENCY_DIS)     //Bluetooth off low delay
#define bt_fcc_test_start()						bt_ctrl_msg(BT_CTL_FCC_TEST)			//FCC test mode

//BLE
#define ble_adv_dis()                           bt_ctrl_msg(BT_CTL_BLE_ADV_DISABLE)
#define ble_adv_en()                            bt_ctrl_msg(BT_CTL_BLE_ADV_ENABLE)

#define bt_fot_tws_resp()                       bt_ctrl_msg(BT_CTL_FOT_RESP)

//pkt
typedef void (*kick_func_t)(void);

struct txbuf_tag {
    uint8_t *ptr;
    uint16_t len;
    uint16_t handle;
} __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;
};

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

//init
void aap_init(void);
uint8_t sdp_add_service(void *item);

//spp
void spp_init(void);
extern struct txpkt_tag spp_tx;
void spp_send_kick(void);
int bt_spp_tx(uint8_t *packet, uint16_t len);
void spp_support_mul_server(uint8_t support);
bool spp_is_connect(void);
void spp_disconnect(void);
int spp_notify_rx_buffer_len(u16 len);
void spp_set_rx_new_credit(uint8_t credit);

//hid
void hid_device_init(void);
bool bt_hid_send(void *buf, uint len, bool auto_release);                                           //Custom HID array
bool bt_hid_send_key(uint type, uint keycode);                                                      //Standard HID key
#define bt_hid_key(keycode)                     bt_hid_send_key(HID_KEYBOARD, keycode)              //Standard HID key, such as Enter
#define bt_hid_consumer(keycode)                bt_hid_send_key(HID_CONSUMER, keycode)              //Customize HID key, such as VOL+VOL-
#define bt_hid_touch_screen(keycode)            bt_hid_send_key(HID_TOUCH_SCREEN, keycode)          //Touch screen
bool bt_hid_touch_screen_set_key(void *ts);


/*****************************************************************************
 * BLE connection related (channel 1, independent of BLE connectionless broadcast)
 *****************************************************************************/
 struct att_hdl_t {
    u16 hdl;    //att handle
    u8 cfg;     //client config enable
    u8 res;
};

extern struct txpkt_tag notify_tx;

/**
  * @brief  initialize ble read buf,only use for the attribute which can be read
  * @param  index for attribute handle
  * @param  attribute handle
  * @param  the data in the buf will be copy to libs
  * @param  len(must be less than 64 byte)
  */
void ble_init_att_do(u8 index, u16 handle, u8 config , u8* buf, u8 len);
void ble_init_att_for_handle(u16 handle,  u8* buf, u8 len);
void ble_send_kick(void);
u8 ble_get_status(void);
bool ble_is_connect(void);
u16 ble_get_gatt_mtu(void);
void ble_set_adv(u8 chanel, u8 type);

/**
 * @brief  set advertisement params.
 * @param  param: advertisement params structure.
 * @retval None
 */
bool ble_set_adv_params(adv_param_t *param);

/**
  * @brief  Set up ble advertisement interval
  * @param  interval: 0x20 - 0x4000(uint:0.625ms)
  */
void ble_set_adv_interval(u16 interval);

void ble_enable_adv(void);
void ble_disable_adv(void);
void ble_disconnect(void);

/**
  * @brief  notify data
  * @param  index for attribute handle
  * @param  buf to be send
  * @param  len(must be less than att mtu)
  * @return return 0 if ok
  */
int ble_tx_notify(u8 index, u8* buf, u16 len);

/**
  * @brief  indicate data
  * @param  index for attribute handle
  * @param  buf to be send
  * @param  len(must be less than att mtu)
  * @return return 0 if ok
  */
int ble_tx_indication(u8 index, u8* buf, u16 len);

/**
 * @brief update of the connection parameter for a given LE connection
 * @param interval: 6 - 3200(unit: 1.25ms)
 * @param latency
 * @param timeout (unit: 10ms)
 */
void ble_update_conn_param(u16 interval, u16 latency, u16 timeout);

/**
 * @brief Set Advertisement Data
 * @param advertising_data (max 31 octets)
 * @param advertising_data_length
 */
bool ble_set_adv_data(const u8 *adv_buf, u32 size);

/**
 * @brief Set Advertisement Data
 * @param advertising_data (max 31 octets)
 * @param advertising_data_length
 */
bool ble_set_scan_rsp_data(const u8 *scan_rsp_buf, u32 size);

/**
 * @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 le_sm_init(uint8_t security_req_en, uint8_t io_capability, uint8_t authentication_req_flag);

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

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

/**
 * @brief  Get the profile table.
 * @retval Table of BLE profile.
 */
u8 *ble_get_profile_data(void);

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

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

/**
 * @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(uint8_t type, uint16_t interval, uint16_t window);

/**
 * @brief  ble scan ctrl.
 * @retval None
 */
void ble_scan_en(void);

/**
 * @brief  ble scan ctrl.
 * @retval None
 */
void ble_scan_dis(void);

/**
 * @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)
 * @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 Discovers all primary services. For each found service, GATT_EVENT_SERVICE_QUERY_RESULT will be generated and passed to the registered callback. GATT_EVENT_QUERY_COMPLETE, marks the end of discovery.
 * @param  con_handle
 * @return return 0 if ok, other refer to ATT_ERR_CORE
 */
uint8_t ble_client_discover_primary_services(uint16_t con_handle);

/**
 * @brief Discovers a specific primary service given its UUID. For each found service, GATT_EVENT_SERVICE_QUERY_RESULT will be generated and passed to the registered callback. GATT_EVENT_QUERY_COMPLETE, marks the end of discovery.
 * @param con_handle
 * @param uuid16
 * @return return 0 if ok, other refer to ATT_ERR_CORE
 */
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 GATT_EVENT_SERVICE_QUERY_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 GATT_EVENT_CHARACTERISTIC_QUERY_RESULT will be generated and passed to the registered callback. The gatt_complete_event_t with type set to GATT_EVENT_QUERY_COMPLETE, marks the end of discovery.
 * @param  callback
 * @param  con_handle
 * @param  service
 * @return return 0 if ok, other refer to ATT_ERR_CORE
 */
uint8_t ble_client_discover_characteristics_for_service(uint16_t con_handle, gatt_client_service_t * service);

/**
 * @brief Get field characteristic from event GATT_EVENT_CHARACTERISTIC_QUERY_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, GATT_EVENT_CHARACTERISTIC_QUERY_RESULT will be generated and passed to the registered callback. GATT_EVENT_QUERY_COMPLETE, marks the end of discovery.
 * @param  con_handle
 * @param  service
 * @param  uuid
 * @return return 0 if ok, other refer to ATT_ERR_CORE
 */
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, uint8_t * uuid128);

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

/**
 * @brief Writes the characteristic value using the characteristic's value handle. The gatt_complete_event_t with type set to GATT_EVENT_QUERY_COMPLETE, marks the end of write. The write is successfully performed, if the event's att_status field is set to ATT_ERROR_SUCCESS (see bluetooth.h for ATT_ERROR codes).
 * @param  callback
 * @param  con_handle
 * @param  value_handle
 * @param  value_length
 * @param  value is not copied, make sure memory is accessible until write is done, i.e. GATT_EVENT_QUERY_COMPLETE is received
 * @return status ATT_ERROR_INVALID_HANDLE                                  if no GATT client for con_handle is found
 *                ATT_ERROR_IN_WRONG_STATE                                  if GATT client is not ready
 *                ATT_ERROR_NO_ERROR                                        if query is successfully registered
 */
uint8_t ble_gatt_client_write_value_of_characteristic(hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t * value);

/**
 * @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);

//gatt服务函数
void ble_gatts_init(void);
int ble_gatts_service_add(ble_gatts_service_type service_type, const uint8_t *service_uuid, ble_gatts_uuid_type uuid_type, uint8_t *service_handle);
int ble_gatts_characteristic_add( const uint8_t *att_uuid, ble_gatts_uuid_type uuid_type, uint16_t props,
                                          uint8_t *att_handle, uint8_t *att_index, gatt_callback_func call_back_func);

/*****************************************************************************
 * BLE connectionless broadcast related (channel 0, independent of BLE connection)
 *****************************************************************************/
#define BLE_ADV0_EN_BIT             0x01
#define BLE_ADV0_MS_VAR_BIT         0x02
#define BLE_ADV0_ADDR_PUBIC_BIT     0x04

extern const uint8_t cfg_ble_adv0_en;

void ble_adv0_set_intv(u16 intv);                       //Set broadcast interval, unit: 625us
void ble_adv0_set_ctrl(uint opcode);                    //0=turn off the broadcast, 1=turn on the broadcast, 2=update the broadcast data (directly broadcast when turned on, only update the buffer when turned off)
uint8_t ble_adv0_get_adv_en(void);

void ble_adv0_update_adv(void);
void ble_adv0_idx_update(void);

#endif //_API_BTSTACK_H
