/**
 * @file tkl_bluetooth.c
 * @brief this file was auto-generated by tuyaos v&v tools, developer can add implements between BEGIN and END
 * 
 * @warning: changes between user 'BEGIN' and 'END' will be keeped when run tuyaos v&v tools
 *           changes in other place will be overwrited and lost
 *
 * @copyright Copyright 2020-2021 Tuya Inc. All Rights Reserved.
 * 
 */

// --- BEGIN: user defines and implements ---
#include "tkl_bluetooth.h"
#include "tuya_error_code.h"
#include "utilities/uni_log.h"/*PR_xxx打印*/
#include <stdio.h>
// --- END: user defines and implements ---

extern uint16_t blesmt_write_handle;
extern uint16_t blesmt_notify_handle;
extern uint16_t blesmt_read_handle;

static TKL_BLE_GAP_EVT_FUNC_CB g_gap_evt_cb = NULL;
static TKL_BLE_GATT_EVT_FUNC_CB g_gatt_evt_cb = NULL;

OPERATE_RET tkl_ble_gap_evt_cb(TKL_BLE_GAP_EVT_TYPE_E e)
{
    PR_DEBUG("tkl_ble_gap_evt_cb %d",e);
    TKL_BLE_GAP_PARAMS_EVT_T evt;
    evt.type = e;
    g_gap_evt_cb(&evt);
    return OPRT_OK;
}


OPERATE_RET tkl_ble_gatt_evt_cb(TKL_BLE_GATT_EVT_TYPE_E e)
{
    PR_DEBUG("tkl_ble_gatt_evt_cb %d",e);
    TKL_BLE_GATT_PARAMS_EVT_T evt;
    evt.type = e;
    g_gatt_evt_cb(&evt);
    return OPRT_OK;
}

/**
 * @brief   Function for initializing the ble stack
 * @param   role                Indicate the role for ble stack.
 *                              role = 1: ble peripheral    @TKL_BLE_ROLE_SERVER
 *                              role = 2: ble central       @TKL_BLE_ROLE_CLIENT
 * @return  SUCCESS             Initialized successfully.
 *          ERROR
 * */
OPERATE_RET tkl_ble_stack_init(UCHAR_T role)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_stack_init");
    main_bleapp();
    tkl_ble_gap_evt_cb(TKL_BLE_EVT_STACK_INIT);
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Function for de-initializing the ble stack features
 * @param   role                 Indicate the role for ble stack.
 *                               role = 1: ble peripheral
 *                               role = 2: ble central
 * @return  SUCCESS             Deinitialized successfully.
 *          ERROR
 * */
OPERATE_RET tkl_ble_stack_deinit(UCHAR_T role)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_stack_deinit");
    tkl_ble_gap_evt_cb(TKL_BLE_EVT_STACK_DEINIT);
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Function for getting the GATT Link-Support.
 * @param   p_link              return gatt link                 
 * @return  SUCCESS             Support Gatt Link
 *          ERROR               Only Beacon or Mesh Beacon, Not Support Gatt Link.
 * */
OPERATE_RET tkl_ble_stack_gatt_link(USHORT_T *p_link)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_stack_deinit");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Register GAP Event Callback
 * @param   TKL_BLE_GAP_EVT_FUNC_CB Refer to @TKL_BLE_GAP_EVT_FUNC_CB
 * @return  SUCCESS         Register successfully.
 *          ERROR
 * */
OPERATE_RET tkl_ble_gap_callback_register(CONST TKL_BLE_GAP_EVT_FUNC_CB gap_evt)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_callback_register");
    g_gap_evt_cb = gap_evt;
    // xm_ble_gap_callback_register(gap_evt);
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Register GATT Event Callback
 * @param   TKL_BLE_GATT_EVT_FUNC_CB Refer to @TKL_BLE_GATT_EVT_FUNC_CB
 * @return  SUCCESS         Register successfully.
 *          ERROR
 * */
OPERATE_RET tkl_ble_gatt_callback_register(CONST TKL_BLE_GATT_EVT_FUNC_CB gatt_evt)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gatt_callback_register");
    g_gatt_evt_cb = gatt_evt;
    // xm_ble_gatt_callback_register(gatt_evt);
    return OPRT_OK;
    // --- END: user implements ---
}

/******************************************************************************************************************************/
/** @brief Define All GAP Interface
 */
/**
 * @brief   Set the local Bluetooth identity address.
 *          The local Bluetooth identity address is the address that identifies this device to other peers.
 *          The address type must be either @ref TKL_BLE_GAP_ADDR_TYPE_PUBLIC or @ref TKL_BLE_GAP_ADDR_TYPE_RANDOM.
 * @param   [in] p_peer_addr:   pointer to local address parameters 
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gap_addr_set(TKL_BLE_GAP_ADDR_T CONST *p_peer_addr)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_addr_set");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Get the local Bluetooth identity address.
 * @param   [out] p_peer_addr:  pointer to local address
 * @return  SUCCESS             Set Address successfully.
 *          ERROR
 * */
OPERATE_RET tkl_ble_gap_address_get(TKL_BLE_GAP_ADDR_T *p_peer_addr)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_address_get");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Start advertising
 * @param   [in] p_adv_params : pointer to advertising parameters 
 * @return  SUCCESS
 *  ERROR
 * */ 
OPERATE_RET tkl_ble_gap_adv_start(TKL_BLE_GAP_ADV_PARAMS_T CONST *p_adv_params)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_adv_start");
    // if (g_adv_rsp_data_set == 1)
        xm_ble_gap_adv_start(p_adv_params);
    // else
        // PR_DEBUG("set adv&rsp data first");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Stop advertising
 * @param   VOID
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gap_adv_stop(VOID)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_adv_stop!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Setting advertising data
 * @param   [in] p_adv:         Data to be used in advertisement packets, and include adv data len
 *          [in] p_scan_rsp:    Data to be used in advertisement respond packets, and include rsp data len
 * @Note    Please Check p_adv and p_scan_rsp, if data->p_data == NULL or data->length == 0, we will not update these values.
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gap_adv_rsp_data_set(TKL_BLE_DATA_T CONST *p_adv, TKL_BLE_DATA_T CONST *p_scan_rsp)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_adv_rsp_data_set!\n");
    xm_ble_gap_adv_rsp_data_set(p_adv, p_scan_rsp);
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Update advertising data
 * @param   [in] p_adv: Data    to be used in advertisement packets, and include adv data len
 *          [in] p_scan_rsp:    Data to be used in advertisement respond packets, and include rsp data len
 * @Note    Please Check p_adv and p_scan_rsp, if data->p_data == NULL or data->length == 0, we will not update these values.
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gap_adv_rsp_data_update(TKL_BLE_DATA_T CONST *p_adv, TKL_BLE_DATA_T CONST *p_scan_rsp)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_adv_rsp_data_update!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Start scanning
 * @param   [in] scan_param:    scan parameters including interval, windows
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gap_scan_start(TKL_BLE_GAP_SCAN_PARAMS_T CONST *p_scan_params)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_scan_start!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Stop scanning
 * @param   VOID
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gap_scan_stop(VOID)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_scan_stop!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Start connecting one peer
 * @param   [in] p_peer_addr:   include address and address type
 *          [in] p_scan_params: scan parameters
 *          [in] p_conn_params: connection  parameters
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gap_connect(TKL_BLE_GAP_ADDR_T CONST *p_peer_addr, TKL_BLE_GAP_SCAN_PARAMS_T CONST *p_scan_params, TKL_BLE_GAP_CONN_PARAMS_T CONST *p_conn_params)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_connect!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Disconnect from peer
 * @param   [in] conn_handle:   the connection handle
 *          [in] hci_reason:    terminate reason
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gap_disconnect(USHORT_T conn_handle, UCHAR_T hci_reason)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_disconnect!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Start to update connection parameters
 * @param   [in] conn_handle:   connection handle
 *          [in] p_conn_params: connection  parameters
 * @return  SUCCESS
 *          ERROR
 * */
OPERATE_RET tkl_ble_gap_conn_param_update(USHORT_T conn_handle, TKL_BLE_GAP_CONN_PARAMS_T CONST *p_conn_params)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_conn_param_update!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Set the radio's transmit power.
 * @param   [in] role:          0: Advertising Tx Power; 1: Scan Tx Power; 2: Connection Power
 *          [in] tx_power:      tx power:This value will be magnified 10 times. 
 *                              If the tx_power value is -75, the real power is -7.5dB.(or 40 = 4dB)
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gap_tx_power_set(UCHAR_T role, INT_T tx_power)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_tx_power_set!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Get the received signal strength for the last connection event.
 * @param   [in]conn_handle:    connection handle
 * @return  SUCCESS             Successfully read the RSSI.
 *          ERROR               No sample is available.
 * */
OPERATE_RET tkl_ble_gap_rssi_get(USHORT_T conn_handle)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_rssi_get!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Set the GAP Name For Bluetooth
 * @param   [in]p_name:         GAP Name String
 * @return  SUCCESS
 *          ERROR
 * */
OPERATE_RET tkl_ble_gap_name_set(CHAR_T *p_name)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gap_name_set!\n");
    PR_DEBUG("name=[%s]\n", p_name);
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Add Ble Gatt Service
 * @param   [in] p_service: define the ble service
 *
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gatts_service_add(TKL_BLE_GATTS_PARAMS_T *p_service)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gatts_service_add!\n");
    // 待实现
    // ble_smart_gatt_svcs_init();//初始接口有调用不需要重复调用会失败的
	int i = 0;
    for (i = 0; i < p_service->p_service[0].char_num; i++)
    {
        // p_service->p_service[0].p_char[i].handle = 0x2902;
        if(TKL_BLE_GATT_CHAR_PROP_NOTIFY == p_service->p_service[0].p_char[i].property){
			p_service->p_service[0].p_char[i].handle = blesmt_notify_handle;
		}else if(TKL_BLE_GATT_CHAR_PROP_WRITE== p_service->p_service[0].p_char[i].property){
			p_service->p_service[0].p_char[i].handle = blesmt_write_handle;
		}else if(TKL_BLE_GATT_CHAR_PROP_READ== p_service->p_service[0].p_char[i].property){
			p_service->p_service[0].p_char[i].handle = blesmt_read_handle;
		}
    }
    return OPRT_OK;
    // --- END: user implements ---
}

OPERATE_RET tkl_ble_gatts_service_change(USHORT_T conn_handle, USHORT_T start_handle, USHORT_T end_handle)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gatts_service_change!\n");
    return OPRT_OK;
    // --- END: user implements ---    
}
/**
 * @brief   Set the value of a given attribute. After Config Tuya Read-Char, we can update read-value at any time.
 * @param   [in] conn_handle    Connection handle.
 *          [in] char_handle    Attribute handle.
 *          [in,out] p_value    Attribute value information.
 * @return  SUCCESS
 *          ERROR
 *
 * @note Values other than system attributes can be set at any time, regardless of whether any active connections exist. 
 * */ 
OPERATE_RET tkl_ble_gatts_value_set(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gatts_value_set!\n");
    fflush(stdout);
    XmBleReadBuf(p_data, length);
    int i = 0;
    PR_DEBUG("data=");
    fflush(stdout);
    for(;i < length;i++){
        printf("%x ", p_data[i]);
    }
    fflush(stdout);

    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Get the value of a given attribute.
 * @param   [in] conn_handle    Connection handle. Ignored if the value does not belong to a system attribute.
 * @param   [in] char_handle    Attribute handle.
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gatts_value_get(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gatts_value_get!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Notify an attribute value.
 * @param   [in] conn_handle    Connection handle.
 * @param   [in] char_handle    Attribute handle.
 *          [in] p_data         Notify Values
 *          [in] length         Value Length
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gatts_value_notify(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gatts_value_notify!\n");
	int rc;
    rc = gatt_svr_chr_notify(conn_handle, char_handle, p_data, length);
    if (rc != 0)
		PR_ERR("gatt_svr_chr_notify error\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Indicate an attribute value.
 * @param   [in] conn_handle    Connection handle.
 * @param   [in] char_handle    Attribute handle.
 *          [in] p_data         Notify Values
 *          [in] length         Value Length
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gatts_value_indicate(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gatts_value_indicate!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Reply to an ATT_MTU exchange request by sending an Exchange MTU Response to the client.
 * @param   [in] conn_handle    Connection handle.
 *          [in] server_rx_mtu  mtu size.
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gatts_exchange_mtu_reply(USHORT_T conn_handle, USHORT_T server_rx_mtu)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gatts_exchange_mtu_reply!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/******************************************************************************************************************************/
/** @brief Define All Gatt Client Interface, Refer to current ble gw and ble stack.
 *
 *  Notes: notice the handle will be the one of signed point.
 *  Discovery Operations belongs to GAP Interface, But declear here, because it will be used for the gatt client.
 */
 
/**
 * @brief   [Ble Central] Will Discovery All Service
 * @param   [in] conn_handle    Connection handle.
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gattc_all_service_discovery(USHORT_T conn_handle)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gattc_all_service_discovery!\n");
    return 0;
    // --- END: user implements ---
}

/**
 * @brief   [Ble Central] Will Discovery All Characteristic
 * @param   [in] conn_handle    Connection handle.
 *          [in] start_handle   Handle of start
 *          [in] end_handle     Handle of End
 * @return  SUCCESS
 *          ERROR
 * @Note:   For Tuya Service, it may contains more optional service, it is more better to find all Characteristic 
 *          instead of find specific uuid.
 * */  
OPERATE_RET tkl_ble_gattc_all_char_discovery(USHORT_T conn_handle, USHORT_T start_handle, USHORT_T end_handle)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gattc_all_char_discovery!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   [Ble Central] Will Discovery All Descriptor of Characteristic
 * @param   [in] conn_handle    Connection handle.
 * @param   [in] conn_handle    Connection handle.
 *          [in] start_handle   Handle of start
 *          [in] end_handle     Handle of End
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gattc_char_desc_discovery(USHORT_T conn_handle, USHORT_T start_handle, USHORT_T end_handle)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gattc_char_desc_discovery!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   [Ble Central] Write Data without Response
 * @param   [in] conn_handle    Connection handle.
 * @param   [in] char_handle    Attribute handle.
 *          [in] p_data         Write Values
 *          [in] length         Value Length
 * @return  SUCCESS
 *          ERROR
 * */ 
OPERATE_RET tkl_ble_gattc_write_without_rsp(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gattc_write_without_rsp!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   [Ble Central] Write Data with response
 * @param   [in] conn_handle    Connection handle.
 * @param   [in] char_handle    Attribute handle.
 *          [in] p_data         Write Values
 *          [in] length         Value Length
 * @return  SUCCESS
 *          ERROR
 * */
OPERATE_RET tkl_ble_gattc_write(USHORT_T conn_handle, USHORT_T char_handle, UCHAR_T *p_data, USHORT_T length)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gattc_write!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   [Ble Central] Read Data
 * @param   [in] conn_handle    Connection handle.
 * @param   [in] char_handle    Attribute handle.
 * @return  SUCCESS
 *          ERROR
 * */
OPERATE_RET tkl_ble_gattc_read(USHORT_T conn_handle, USHORT_T char_handle)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gattc_read!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   Start an ATT_MTU exchange by sending an Exchange MTU Request to the server.
 * @param   [in] conn_handle    Connection handle.
 *          [in] client_rx_mtu  mtu size.
 * @return  SUCCESS
 *          ERROR
 * */
OPERATE_RET tkl_ble_gattc_exchange_mtu_request(USHORT_T conn_handle, USHORT_T client_rx_mtu)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_gattc_exchange_mtu_request!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

/**
 * @brief   [Special Command Control] Base on Bluetooth, We can do some special commands for exchanging some informations.
 * @param   [in] opcode         Operations Opcode.
 *          [in] user_data      Post Some Special Commands Data.
 *          [in] data_len       User's Data Length.
 * @note    For Operations Codes, we can do anythings after exchange from TAL Application
 *          And We define some Opcodes as below for reference.
 *          For Bluetooth NCP Module: Mask=0x01, Code ID: 0x00~0xff. Opcode = ((0x01 << 8) & Code ID)
 *          eg:     0x0100: Special Vendor Module Init
 *                  0x0101: Special Vendor Module Deinit
 *                  0x0102: Special Vendor Module Reset
 *                  0x0103: Special Vendor Module Check Exist: Return OPRT_OK or OPRT_NOT_FOUND ..
 *                  0x0104: Specail Vendor Module Version Get.
 *                  0x0105: Specail Vendor Module Version Set.
 *                  0x0106: Specail Vendor Module Version Update.
 *                  0x0107: Specail Vendor Module Scan Switch.
 *                  0x0108: Specail Vendor Module Scan Stop.
 *                  0x0109: Specail Vendor Module Auth Check.
 *                  0x0110: Specail Vendor Module Auth Erase.
 *
 *  * @return  SUCCESS
 *          ERROR
 * */
OPERATE_RET tkl_ble_vendor_command_control(USHORT_T opcode, VOID_T *user_data, USHORT_T data_len)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_vendor_command_control!\n");
    return OPRT_OK;
    // --- END: user implements ---
}

OPERATE_RET tkl_ble_set_mode(CONST BOOL_T enable, CONST UCHAR_T mode)
{
    // --- BEGIN: user implements ---
    PR_DEBUG("tkl_ble_set_mode!\n");
    return OPRT_OK;
    // --- END: user implements ---    
}