2040 lines
60 KiB
C
2040 lines
60 KiB
C
|
// Copyright 2020-2021 Beken
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
#include <common/sys_config.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <components/log.h>
|
||
|
#include <os/mem.h>
|
||
|
#include <os/str.h>
|
||
|
#include <os/os.h>
|
||
|
|
||
|
#include "components/bluetooth/bk_dm_bluetooth_types.h"
|
||
|
#include "components/bluetooth/bk_dm_gap_ble_types.h"
|
||
|
#include "components/bluetooth/bk_dm_gap_ble.h"
|
||
|
|
||
|
#include "dm_gatts.h"
|
||
|
#include "dm_gatt_connection.h"
|
||
|
#include "dm_gap_utils.h"
|
||
|
|
||
|
#define DYNAMIC_ADD_ATTR 0
|
||
|
#define SET_ADVTYPE_TO_IDENTITY_WHEN_NORPA 0
|
||
|
|
||
|
#define INVALID_ATTR_HANDLE 0
|
||
|
#define ADV_HANDLE 0
|
||
|
|
||
|
#define MIN_VALUE(x, y) (((x) < (y)) ? (x): (y))
|
||
|
|
||
|
#define dm_gatts_app_env_t dm_gatt_demo_app_env_t
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
DB_REG_STATUS_IDLE,
|
||
|
DB_REG_STATUS_WAIT_COMPLETED,
|
||
|
DB_REG_STATUS_COMPLETED
|
||
|
};
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
uint8_t status; //DB_REG_STATUS_IDLE
|
||
|
bk_gatts_attr_db_t *db;
|
||
|
uint16_t *attr_list;
|
||
|
uint32_t count;
|
||
|
dm_ble_gatts_db_cb cb;
|
||
|
} dm_gatts_db_reg_t;
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
dm_gatts_db_reg_t reg[2];
|
||
|
uint32_t count;
|
||
|
} dm_gatts_db_ctx_t;
|
||
|
|
||
|
|
||
|
static int32_t dm_gatts_set_adv_param(uint8_t local_addr_is_public);
|
||
|
static dm_gatts_db_reg_t *find_db_ctx_by_attr_handle(uint16_t attr_handle);
|
||
|
|
||
|
static beken_semaphore_t s_ble_sema = NULL;
|
||
|
|
||
|
static bk_gatt_if_t s_gatts_if;
|
||
|
static uint8_t s_dm_gatts_local_addr_is_public = 0;
|
||
|
static dm_gatts_db_ctx_t s_dm_gatts_db_ctx;
|
||
|
static uint8_t s_dm_gatts_is_init;
|
||
|
|
||
|
#if GATTS_TEST_ATTR_ENABLE
|
||
|
static beken_timer_t s_char_notify_timer;
|
||
|
|
||
|
static uint16_t s_service_attr_handle = INVALID_ATTR_HANDLE;
|
||
|
|
||
|
static uint16_t s_char_attr_handle = INVALID_ATTR_HANDLE;
|
||
|
static uint8_t s_char_buff[4] = {0};
|
||
|
|
||
|
static uint16_t s_char_desc_attr_handle = INVALID_ATTR_HANDLE;
|
||
|
static uint16_t s_char_desc_buff = 0;
|
||
|
|
||
|
static uint16_t s_char2_attr_handle = INVALID_ATTR_HANDLE;
|
||
|
static uint8_t s_char2_buff[312] = {0};
|
||
|
|
||
|
static uint16_t s_char2_desc_attr_handle = INVALID_ATTR_HANDLE;
|
||
|
static uint32_t s_char2_desc_buff = 0;
|
||
|
|
||
|
static uint16_t s_char_auto_rsp_attr_handle = INVALID_ATTR_HANDLE;
|
||
|
static uint8_t s_char_auto_rsp_buff[300] = {0};
|
||
|
|
||
|
static uint16_t s_char4_attr_handle = INVALID_ATTR_HANDLE;
|
||
|
|
||
|
static const bk_gatts_attr_db_t s_gatts_attr_db_service_1[] =
|
||
|
{
|
||
|
//service
|
||
|
{
|
||
|
BK_GATT_PRIMARY_SERVICE_DECL(INTERESTING_SERIVCE_UUID),
|
||
|
},
|
||
|
|
||
|
//char 1
|
||
|
{
|
||
|
BK_GATT_CHAR_DECL(INTERESTING_CHAR_UUID,
|
||
|
sizeof(s_char_buff), s_char_buff,
|
||
|
BK_GATT_CHAR_PROP_BIT_READ | BK_GATT_CHAR_PROP_BIT_WRITE_NR | BK_GATT_CHAR_PROP_BIT_WRITE | BK_GATT_CHAR_PROP_BIT_NOTIFY,
|
||
|
//BK_GATT_PERM_READ | BK_GATT_PERM_WRITE,
|
||
|
BK_GATT_PERM_READ_ENCRYPTED | BK_GATT_PERM_WRITE_ENCRYPTED,
|
||
|
//BK_GATT_PERM_READ_ENC_MITM | BK_GATT_PERM_WRITE_ENC_MITM, //gap iocap must not be BK_IO_CAP_NONE !!!
|
||
|
BK_GATT_RSP_BY_APP),
|
||
|
},
|
||
|
{
|
||
|
BK_GATT_CHAR_DESC_DECL(BK_GATT_UUID_CHAR_CLIENT_CONFIG,
|
||
|
sizeof(s_char_desc_buff), (uint8_t *)&s_char_desc_buff,
|
||
|
BK_GATT_PERM_READ | BK_GATT_PERM_WRITE,
|
||
|
BK_GATT_RSP_BY_APP),
|
||
|
},
|
||
|
|
||
|
//char 2
|
||
|
{
|
||
|
BK_GATT_CHAR_DECL(0x9abc,
|
||
|
sizeof(s_char2_buff), s_char2_buff,
|
||
|
BK_GATT_CHAR_PROP_BIT_READ | BK_GATT_CHAR_PROP_BIT_WRITE_NR | BK_GATT_CHAR_PROP_BIT_WRITE,
|
||
|
BK_GATT_PERM_READ | BK_GATT_PERM_WRITE,
|
||
|
//BK_GATT_PERM_READ_ENCRYPTED | BK_GATT_PERM_WRITE_ENCRYPTED,
|
||
|
//BK_GATT_PERM_READ_ENC_MITM | BK_GATT_PERM_WRITE_ENC_MITM, //gap iocap must not be BK_IO_CAP_NONE !!!
|
||
|
BK_GATT_RSP_BY_APP),
|
||
|
},
|
||
|
{
|
||
|
BK_GATT_CHAR_DESC_DECL(BK_GATT_UUID_CHAR_SRVR_CONFIG,
|
||
|
sizeof(s_char2_desc_buff), (uint8_t *)&s_char2_desc_buff,
|
||
|
BK_GATT_PERM_READ | BK_GATT_PERM_WRITE,
|
||
|
BK_GATT_RSP_BY_APP),
|
||
|
},
|
||
|
|
||
|
//char 3
|
||
|
{
|
||
|
BK_GATT_CHAR_DECL(0x15ab,
|
||
|
sizeof(s_char_auto_rsp_buff), s_char_auto_rsp_buff,
|
||
|
BK_GATT_CHAR_PROP_BIT_READ | BK_GATT_CHAR_PROP_BIT_WRITE_NR | BK_GATT_CHAR_PROP_BIT_WRITE,
|
||
|
BK_GATT_PERM_READ | BK_GATT_PERM_WRITE,
|
||
|
BK_GATT_AUTO_RSP),
|
||
|
},
|
||
|
|
||
|
//char 4 no buffer
|
||
|
{
|
||
|
BK_GATT_CHAR_DECL(0x15ac,
|
||
|
0, NULL,
|
||
|
BK_GATT_CHAR_PROP_BIT_READ | BK_GATT_CHAR_PROP_BIT_WRITE_NR | BK_GATT_CHAR_PROP_BIT_WRITE,
|
||
|
BK_GATT_PERM_READ | BK_GATT_PERM_WRITE,
|
||
|
BK_GATT_AUTO_RSP), //Without buffer, BK_GATT_AUTO_RSP will cause "NOT PERMITTED" err to peer when recv write or read req. So set BK_GATT_RSP_BY_APP instead.
|
||
|
},
|
||
|
};
|
||
|
|
||
|
//static const uint8_t s_gatts_128_attr[] = {0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x34, 0x22, 0x00, 0x00};
|
||
|
|
||
|
static const bk_gatts_attr_db_t s_gatts_attr_db_service_2[] =
|
||
|
{
|
||
|
//service
|
||
|
{
|
||
|
BK_GATT_PRIMARY_SERVICE_DECL(0x2234),
|
||
|
//BK_GATT_PRIMARY_SERVICE_DECL_128(s_gatts_128_attr),
|
||
|
},
|
||
|
|
||
|
//char 1
|
||
|
{
|
||
|
BK_GATT_CHAR_DECL(0x5678,
|
||
|
sizeof(s_char_buff), s_char_buff,
|
||
|
BK_GATT_CHAR_PROP_BIT_READ | BK_GATT_CHAR_PROP_BIT_WRITE_NR | BK_GATT_CHAR_PROP_BIT_WRITE | BK_GATT_CHAR_PROP_BIT_NOTIFY,
|
||
|
BK_GATT_PERM_READ | BK_GATT_PERM_WRITE,
|
||
|
//BK_GATT_PERM_READ_ENCRYPTED | BK_GATT_PERM_WRITE_ENCRYPTED,
|
||
|
//BK_GATT_PERM_READ_ENC_MITM | BK_GATT_PERM_WRITE_ENC_MITM, //gap iocap must not be BK_IO_CAP_NONE !!!
|
||
|
BK_GATT_AUTO_RSP),
|
||
|
},
|
||
|
{
|
||
|
BK_GATT_CHAR_DESC_DECL(BK_GATT_UUID_CHAR_CLIENT_CONFIG,
|
||
|
sizeof(s_char_desc_buff), (uint8_t *)&s_char_desc_buff,
|
||
|
BK_GATT_PERM_READ | BK_GATT_PERM_WRITE,
|
||
|
BK_GATT_AUTO_RSP),
|
||
|
},
|
||
|
|
||
|
//char 2
|
||
|
{
|
||
|
BK_GATT_CHAR_DECL(0x9abc,
|
||
|
sizeof(s_char2_buff), s_char2_buff,
|
||
|
BK_GATT_CHAR_PROP_BIT_READ | BK_GATT_CHAR_PROP_BIT_WRITE_NR | BK_GATT_CHAR_PROP_BIT_WRITE,
|
||
|
BK_GATT_PERM_READ_ENCRYPTED | BK_GATT_PERM_WRITE_ENCRYPTED,
|
||
|
BK_GATT_AUTO_RSP),
|
||
|
},
|
||
|
{
|
||
|
BK_GATT_CHAR_DESC_DECL(BK_GATT_UUID_CHAR_SRVR_CONFIG,
|
||
|
sizeof(s_char2_desc_buff), (uint8_t *)&s_char2_desc_buff,
|
||
|
BK_GATT_PERM_READ | BK_GATT_PERM_WRITE,
|
||
|
BK_GATT_AUTO_RSP),
|
||
|
},
|
||
|
|
||
|
//char 3
|
||
|
{
|
||
|
BK_GATT_CHAR_DECL(0x15ab,
|
||
|
sizeof(s_char_auto_rsp_buff), s_char_auto_rsp_buff,
|
||
|
BK_GATT_CHAR_PROP_BIT_READ | BK_GATT_CHAR_PROP_BIT_WRITE_NR | BK_GATT_CHAR_PROP_BIT_WRITE,
|
||
|
BK_GATT_PERM_READ_ENC_MITM | BK_GATT_PERM_WRITE_ENC_MITM, //gap iocap must not be BK_IO_CAP_NONE !!!
|
||
|
BK_GATT_AUTO_RSP),
|
||
|
},
|
||
|
};
|
||
|
|
||
|
static uint16_t *const s_attr_handle_list[sizeof(s_gatts_attr_db_service_1) / sizeof(s_gatts_attr_db_service_1[0])] =
|
||
|
{
|
||
|
&s_service_attr_handle,
|
||
|
&s_char_attr_handle,
|
||
|
&s_char_desc_attr_handle,
|
||
|
&s_char2_attr_handle,
|
||
|
&s_char2_desc_attr_handle,
|
||
|
&s_char_auto_rsp_attr_handle,
|
||
|
&s_char4_attr_handle,
|
||
|
};
|
||
|
|
||
|
|
||
|
static uint16_t s_attr_handle_list2[sizeof(s_gatts_attr_db_service_2) / sizeof(s_gatts_attr_db_service_2[0])];
|
||
|
|
||
|
|
||
|
#endif
|
||
|
|
||
|
static int32_t dm_ble_gap_cb(bk_ble_gap_cb_event_t event, bk_ble_gap_cb_param_t *param)
|
||
|
{
|
||
|
gatt_logd("event %d", event);
|
||
|
|
||
|
switch (event)
|
||
|
{
|
||
|
case BK_BLE_GAP_SET_STATIC_RAND_ADDR_EVT:
|
||
|
{
|
||
|
struct ble_set_rand_cmpl_evt_param *pm = (typeof(pm))param;
|
||
|
|
||
|
if (pm->status)
|
||
|
{
|
||
|
gatt_loge("set rand addr err %d", pm->status);
|
||
|
}
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_BLE_GAP_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT:
|
||
|
{
|
||
|
struct ble_adv_set_rand_addr_cmpl_evt_param *pm = (typeof(pm))param;
|
||
|
|
||
|
if (pm->status)
|
||
|
{
|
||
|
gatt_loge("set adv rand addr err %d", pm->status);
|
||
|
}
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_BLE_GAP_EXT_ADV_PARAMS_SET_COMPLETE_EVT:
|
||
|
{
|
||
|
struct ble_adv_params_set_cmpl_evt_param *pm = (typeof(pm))param;
|
||
|
|
||
|
if (pm->status)
|
||
|
{
|
||
|
gatt_loge("set adv param err 0x%x", pm->status);
|
||
|
}
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_BLE_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT:
|
||
|
{
|
||
|
struct ble_adv_data_set_cmpl_evt_param *pm = (typeof(pm))param;
|
||
|
|
||
|
if (pm->status)
|
||
|
{
|
||
|
gatt_loge("set adv data err %d", pm->status);
|
||
|
}
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_BLE_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT:
|
||
|
{
|
||
|
struct ble_adv_scan_rsp_set_cmpl_evt_param *pm = (typeof(pm))param;
|
||
|
|
||
|
if (pm->status)
|
||
|
{
|
||
|
gatt_loge("set adv data scan rsp err %d", pm->status);
|
||
|
}
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_BLE_GAP_EXT_ADV_START_COMPLETE_EVT:
|
||
|
{
|
||
|
struct ble_adv_start_cmpl_evt_param *pm = (typeof(pm))param;
|
||
|
|
||
|
if (pm->status)
|
||
|
{
|
||
|
gatt_loge("set adv enable err %d", pm->status);
|
||
|
}
|
||
|
|
||
|
gatt_logw("pls disable adv before remove pair !!!");
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return DM_BLE_GAP_APP_CB_RET_NO_INTERESTING;
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
return DM_BLE_GAP_APP_CB_RET_PROCESSED;
|
||
|
}
|
||
|
|
||
|
#if GATTS_TEST_ATTR_ENABLE
|
||
|
static int32_t nest_func_send_indicate(dm_gatt_app_env_t *env, void *arg)
|
||
|
{
|
||
|
uint8_t *tmp_buff = (typeof(tmp_buff))arg;
|
||
|
|
||
|
if (env && env->status == GAP_CONNECT_STATUS_CONNECTED && env->conn_id != 0xffff && env->data) //env->local_is_master == 0
|
||
|
{
|
||
|
dm_gatts_app_env_t *tmp = (typeof(tmp))env->data;
|
||
|
|
||
|
if (tmp->notify_status)
|
||
|
{
|
||
|
if (bk_ble_gatts_send_indicate(0, env->conn_id, s_char_attr_handle, sizeof(s_char_buff), tmp_buff, tmp->notify_status == 2 ? 1 : 0))
|
||
|
{
|
||
|
gatt_loge("notify err");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int32_t nest_func_check_timer_ref_count(dm_gatt_app_env_t *env, void *arg)
|
||
|
{
|
||
|
uint8_t *tmp_count = arg;
|
||
|
|
||
|
if (env && env->status == GAP_CONNECT_STATUS_CONNECTED && env->conn_id != 0xffff && env->data) //&& env->local_is_master == 0
|
||
|
{
|
||
|
dm_gatts_app_env_t *tmp_env = (typeof(tmp_env))env->data;
|
||
|
|
||
|
if (tmp_env->notify_status)
|
||
|
{
|
||
|
(*tmp_count)++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void ble_char_timer_callback(void *param)
|
||
|
{
|
||
|
static uint8_t value = 1;
|
||
|
|
||
|
uint8_t *tmp_buff = NULL;
|
||
|
uint32_t type = (typeof(type))param;
|
||
|
|
||
|
tmp_buff = os_malloc(sizeof(s_char_buff));
|
||
|
|
||
|
if (!tmp_buff)
|
||
|
{
|
||
|
gatt_loge("alloc send failed");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
os_memset(tmp_buff, 0, sizeof(s_char_buff));
|
||
|
tmp_buff[0] = value++;
|
||
|
|
||
|
//nest func only for gcc
|
||
|
dm_ble_app_env_foreach(nest_func_send_indicate, tmp_buff);
|
||
|
|
||
|
os_free(tmp_buff);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
static int32_t bk_gatts_cb (bk_gatts_cb_event_t event, bk_gatt_if_t gatts_if, bk_ble_gatts_cb_param_t *comm_param)
|
||
|
{
|
||
|
ble_err_t ret = 0;
|
||
|
dm_gatt_app_env_t *common_env_tmp = NULL;
|
||
|
dm_gatts_app_env_t *app_env_tmp = NULL;
|
||
|
|
||
|
switch (event)
|
||
|
{
|
||
|
case BK_GATTS_REG_EVT:
|
||
|
{
|
||
|
struct gatts_reg_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_REG_EVT %d %d", param->status, param->gatt_if);
|
||
|
s_gatts_if = param->gatt_if;
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_START_EVT:
|
||
|
{
|
||
|
struct gatts_start_evt_param *param = (typeof(param))comm_param;
|
||
|
gatt_logi("BK_GATTS_START_EVT compl %d %d", param->status, param->service_handle);
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_STOP_EVT:
|
||
|
{
|
||
|
struct gatts_stop_evt_param *param = (typeof(param))comm_param;
|
||
|
gatt_logi("BK_GATTS_STOP_EVT compl %d %d", param->status, param->service_handle);
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_CREAT_ATTR_TAB_EVT:
|
||
|
{
|
||
|
struct gatts_add_attr_tab_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_CREAT_ATTR_TAB_EVT %d %d", param->status, param->num_handle);
|
||
|
|
||
|
#if GATTS_TEST_ATTR_ENABLE
|
||
|
|
||
|
if (s_service_attr_handle == INVALID_ATTR_HANDLE)
|
||
|
{
|
||
|
for (int i = 0; i < param->num_handle; ++i)
|
||
|
{
|
||
|
*s_attr_handle_list[i] = param->handles[i];
|
||
|
|
||
|
bk_ble_gatts_char_property_operation(BK_GATTS_CHAR_PROPERTY_BIT_MASK_OP_GET, param->handles[i], NULL);
|
||
|
|
||
|
// uint16_t tmp_property = BK_GATT_CHAR_PROP_BIT_READ;
|
||
|
// bk_ble_gatts_char_property_operation(BK_GATTS_CHAR_PROPERTY_BIT_MASK_OP_SET, param->handles[i], &tmp_property);
|
||
|
// bk_ble_gatts_char_property_operation(BK_GATTS_CHAR_PROPERTY_BIT_MASK_OP_GET, param->handles[i], NULL);
|
||
|
|
||
|
if (i) //service handle cant get buff
|
||
|
{
|
||
|
uint16_t tmp_len = 0;
|
||
|
uint8_t *tmp_buff = NULL;
|
||
|
ble_err_t g_status = 0;
|
||
|
|
||
|
g_status = bk_ble_gatts_get_attr_value(param->handles[i], &tmp_len, &tmp_buff);
|
||
|
|
||
|
if (g_status)
|
||
|
{
|
||
|
gatt_loge("get attr value err %d", g_status);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (tmp_len != s_gatts_attr_db_service_1[i].att_desc.value.attr_len ||
|
||
|
tmp_buff != s_gatts_attr_db_service_1[i].att_desc.value.attr_value)
|
||
|
{
|
||
|
gatt_loge("get attr value not match create attr handle %d i %d %d %d %p %p!!!!",
|
||
|
param->handles[i], i,
|
||
|
tmp_len, s_gatts_attr_db_service_1[i].att_desc.value.attr_len,
|
||
|
tmp_buff, s_gatts_attr_db_service_1[i].att_desc.value.attr_value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (s_attr_handle_list2[0] == INVALID_ATTR_HANDLE)
|
||
|
{
|
||
|
for (int i = 0; i < param->num_handle; ++i)
|
||
|
{
|
||
|
s_attr_handle_list2[i] = param->handles[i];
|
||
|
|
||
|
if (i) //service handle cant get buff
|
||
|
{
|
||
|
uint16_t tmp_len = 0;
|
||
|
uint8_t *tmp_buff = NULL;
|
||
|
ble_err_t g_status = 0;
|
||
|
|
||
|
g_status = bk_ble_gatts_get_attr_value(param->handles[i], &tmp_len, &tmp_buff);
|
||
|
|
||
|
if (g_status)
|
||
|
{
|
||
|
gatt_loge("get attr value err %d", g_status);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (tmp_len != s_gatts_attr_db_service_2[i].att_desc.value.attr_len ||
|
||
|
tmp_buff != s_gatts_attr_db_service_2[i].att_desc.value.attr_value)
|
||
|
{
|
||
|
gatt_loge("get attr value not match create attr handle %d i %d %d %d %p %p!!!!",
|
||
|
param->handles[i], i,
|
||
|
tmp_len, s_gatts_attr_db_service_2[i].att_desc.value.attr_len,
|
||
|
tmp_buff, s_gatts_attr_db_service_2[i].att_desc.value.attr_value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
{
|
||
|
uint32_t j = 0;
|
||
|
|
||
|
for (j = 0; j < sizeof(s_dm_gatts_db_ctx.reg) / sizeof(s_dm_gatts_db_ctx.reg[0]); ++j)
|
||
|
{
|
||
|
if (s_dm_gatts_db_ctx.reg[j].status == DB_REG_STATUS_WAIT_COMPLETED)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (j >= sizeof(s_dm_gatts_db_ctx.reg) / sizeof(s_dm_gatts_db_ctx.reg[0]))
|
||
|
{
|
||
|
gatt_loge("cant found wait completed !!!");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
gatt_logi("reg attr handle %d~%d", param->handles[0], param->handles[param->num_handle - 1]);
|
||
|
|
||
|
for (int i = 0; i < param->num_handle; ++i)
|
||
|
{
|
||
|
s_dm_gatts_db_ctx.reg[j].attr_list[i] = param->handles[i];
|
||
|
|
||
|
if (i) //service handle cant get buff
|
||
|
{
|
||
|
uint16_t tmp_len = 0;
|
||
|
uint8_t *tmp_buff = NULL;
|
||
|
ble_err_t g_status = 0;
|
||
|
|
||
|
g_status = bk_ble_gatts_get_attr_value(param->handles[i], &tmp_len, &tmp_buff);
|
||
|
|
||
|
if (g_status)
|
||
|
{
|
||
|
gatt_loge("get attr value err %d", g_status);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (tmp_len != s_dm_gatts_db_ctx.reg[j].db[i].att_desc.value.attr_len ||
|
||
|
tmp_buff != s_dm_gatts_db_ctx.reg[j].db[i].att_desc.value.attr_value)
|
||
|
{
|
||
|
gatt_loge("get attr value not match create attr handle %d i %d %d %d %p %p!!!!",
|
||
|
param->handles[i], i,
|
||
|
tmp_len, s_dm_gatts_db_ctx.reg[j].db[i].att_desc.value.attr_len,
|
||
|
tmp_buff, s_dm_gatts_db_ctx.reg[j].db[i].att_desc.value.attr_value);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_CREATE_EVT:
|
||
|
{
|
||
|
struct gatts_create_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_CREATE_EVT %d %d", param->status, param->service_handle);
|
||
|
#if DYNAMIC_ADD_ATTR
|
||
|
s_service_attr_handle = param->service_handle;
|
||
|
#endif
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_ADD_CHAR_EVT:
|
||
|
{
|
||
|
struct gatts_add_char_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_ADD_CHAR_EVT %d %d %d", param->status, param->attr_handle, param->service_handle);
|
||
|
#if DYNAMIC_ADD_ATTR
|
||
|
|
||
|
if (s_char_attr_handle == INVALID_ATTR_HANDLE)
|
||
|
{
|
||
|
s_char_attr_handle = param->attr_handle;
|
||
|
}
|
||
|
else if (s_char2_attr_handle == INVALID_ATTR_HANDLE)
|
||
|
{
|
||
|
s_char2_attr_handle = param->attr_handle;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_char_auto_rsp_attr_handle = param->attr_handle;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_ADD_CHAR_DESCR_EVT:
|
||
|
{
|
||
|
struct gatts_add_char_descr_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_ADD_CHAR_DESCR_EVT %d %d %d", param->status, param->attr_handle, param->service_handle);
|
||
|
#if DYNAMIC_ADD_ATTR
|
||
|
|
||
|
if (s_char_desc_attr_handle == INVALID_ATTR_HANDLE)
|
||
|
{
|
||
|
s_char_desc_attr_handle = param->attr_handle;
|
||
|
}
|
||
|
else if (s_char2_desc_attr_handle == INVALID_ATTR_HANDLE)
|
||
|
{
|
||
|
s_char2_desc_attr_handle = param->attr_handle;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
if (s_ble_sema != NULL)
|
||
|
{
|
||
|
rtos_set_semaphore( &s_ble_sema );
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_READ_EVT:
|
||
|
{
|
||
|
struct gatts_read_evt_param *param = (typeof(param))comm_param;
|
||
|
bk_gatt_rsp_t rsp;
|
||
|
uint16_t final_len = 0;
|
||
|
|
||
|
gatt_logi("BK_GATTS_READ_EVT %d %d %d %d %d need rsp %d %02X:%02X:%02X:%02X:%02X:%02X", param->conn_id, param->trans_id, param->handle,
|
||
|
param->offset, param->is_long, param->need_rsp,
|
||
|
param->bda[5],
|
||
|
param->bda[4],
|
||
|
param->bda[3],
|
||
|
param->bda[2],
|
||
|
param->bda[1],
|
||
|
param->bda[0]);
|
||
|
|
||
|
memset(&rsp, 0, sizeof(rsp));
|
||
|
#if GATTS_TEST_ATTR_ENABLE
|
||
|
|
||
|
if (param->handle == s_char_attr_handle)
|
||
|
{
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
final_len = sizeof(s_char_buff) - param->offset;
|
||
|
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = param->offset;
|
||
|
rsp.attr_value.value = s_char_buff + param->offset;
|
||
|
rsp.attr_value.len = final_len;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
}
|
||
|
}
|
||
|
else if (param->handle == s_char_desc_attr_handle)
|
||
|
{
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
final_len = sizeof(s_char_desc_buff) - param->offset;
|
||
|
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = param->offset;
|
||
|
rsp.attr_value.value = (uint8_t *)&s_char_desc_buff + param->offset;
|
||
|
rsp.attr_value.len = final_len;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else if (param->handle == s_char2_attr_handle)
|
||
|
{
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
final_len = sizeof(s_char2_buff) - param->offset;
|
||
|
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = param->offset;
|
||
|
rsp.attr_value.value = s_char2_buff + param->offset;
|
||
|
rsp.attr_value.len = final_len;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
}
|
||
|
}
|
||
|
else if (param->handle == s_char2_desc_attr_handle)
|
||
|
{
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
final_len = sizeof(s_char2_desc_buff) - param->offset;
|
||
|
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = param->offset;
|
||
|
rsp.attr_value.value = (uint8_t *)&s_char2_desc_buff + param->offset;
|
||
|
rsp.attr_value.len = final_len;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
//ret = bk_ble_gatts_send_response(s_gatt_if, param->conn_id, param->trans_id, BK_GATT_INSUF_RESOURCE, &rsp);
|
||
|
}
|
||
|
}
|
||
|
else if (param->handle == s_char_auto_rsp_attr_handle)
|
||
|
{
|
||
|
gatt_logi("read auto rsp handle %d need rsp %d", param->handle, param->need_rsp);
|
||
|
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
final_len = sizeof(s_char_auto_rsp_buff) - param->offset;
|
||
|
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = param->offset;
|
||
|
rsp.attr_value.value = s_char_auto_rsp_buff + param->offset;
|
||
|
rsp.attr_value.len = final_len;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
{
|
||
|
dm_gatts_db_reg_t *tmp_reg = find_db_ctx_by_attr_handle(param->handle);
|
||
|
|
||
|
if (tmp_reg && tmp_reg->cb)
|
||
|
{
|
||
|
tmp_reg->cb(event, gatts_if, comm_param);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = 0;
|
||
|
rsp.attr_value.value = NULL;
|
||
|
rsp.attr_value.len = 0;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_REQ_NOT_SUPPORTED, &rsp);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_WRITE_EVT:
|
||
|
{
|
||
|
struct gatts_write_evt_param *param = (typeof(param))comm_param;
|
||
|
bk_gatt_rsp_t rsp;
|
||
|
uint16_t final_len = 0;
|
||
|
|
||
|
memset(&rsp, 0, sizeof(rsp));
|
||
|
|
||
|
gatt_logi("BK_GATTS_WRITE_EVT %d %d %d %d %d %d 0x%02X%02X need rsp %d %02X:%02X:%02X:%02X:%02X:%02X",
|
||
|
param->conn_id, param->trans_id, param->handle,
|
||
|
param->offset, param->is_prep, param->len,
|
||
|
param->value[0], param->value[1],
|
||
|
param->need_rsp,
|
||
|
param->bda[5],
|
||
|
param->bda[4],
|
||
|
param->bda[3],
|
||
|
param->bda[2],
|
||
|
param->bda[1],
|
||
|
param->bda[0]);
|
||
|
#if GATTS_TEST_ATTR_ENABLE
|
||
|
|
||
|
if (param->handle == s_char_attr_handle)
|
||
|
{
|
||
|
gatt_logi("len %d 0x%02X%02X%02X%02X", param->len,
|
||
|
param->value[0],
|
||
|
param->value[1],
|
||
|
param->value[2],
|
||
|
param->value[3]);
|
||
|
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
final_len = MIN_VALUE(param->len, sizeof(s_char_buff) - param->offset);
|
||
|
memcpy(s_char_buff + param->offset, param->value, final_len);
|
||
|
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = param->offset;
|
||
|
rsp.attr_value.len = final_len;
|
||
|
rsp.attr_value.value = s_char_buff + param->offset;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
}
|
||
|
}
|
||
|
else if (param->handle == s_char_desc_attr_handle)
|
||
|
{
|
||
|
uint16_t config = (((uint16_t)(param->value[1])) << 8) | param->value[0];
|
||
|
|
||
|
common_env_tmp = dm_ble_find_app_env_by_addr(param->bda);
|
||
|
|
||
|
if (!common_env_tmp || !common_env_tmp->data)
|
||
|
{
|
||
|
gatt_loge("conn max %p %p !!!!", common_env_tmp, common_env_tmp ? common_env_tmp : 0);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
app_env_tmp = (typeof(app_env_tmp))common_env_tmp->data;
|
||
|
|
||
|
if (config & 1)
|
||
|
{
|
||
|
gatt_logi("client notify open");
|
||
|
|
||
|
app_env_tmp->notify_status = 1;
|
||
|
|
||
|
if (!rtos_is_timer_init(&s_char_notify_timer))
|
||
|
{
|
||
|
rtos_init_timer(&s_char_notify_timer, 1000, ble_char_timer_callback, (void *)0);
|
||
|
rtos_start_timer(&s_char_notify_timer);
|
||
|
}
|
||
|
}
|
||
|
else if (config & 2)
|
||
|
{
|
||
|
gatt_logi("client indicate open");
|
||
|
|
||
|
app_env_tmp->notify_status = 2;
|
||
|
|
||
|
if (!rtos_is_timer_init(&s_char_notify_timer))
|
||
|
{
|
||
|
rtos_init_timer(&s_char_notify_timer, 1000, ble_char_timer_callback, (void *)0);
|
||
|
rtos_start_timer(&s_char_notify_timer);
|
||
|
}
|
||
|
}
|
||
|
else if (!config)
|
||
|
{
|
||
|
uint8_t timer_ref_count = 0;
|
||
|
gatt_logi("client config close");
|
||
|
|
||
|
app_env_tmp->notify_status = 0;
|
||
|
|
||
|
//nest func only for gcc
|
||
|
|
||
|
dm_ble_app_env_foreach(nest_func_check_timer_ref_count, &timer_ref_count);
|
||
|
|
||
|
if (!timer_ref_count && rtos_is_timer_init(&s_char_notify_timer))
|
||
|
{
|
||
|
if (rtos_is_timer_running(&s_char_notify_timer))
|
||
|
{
|
||
|
rtos_stop_timer(&s_char_notify_timer);
|
||
|
}
|
||
|
|
||
|
rtos_deinit_timer(&s_char_notify_timer);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gatt_logi("client config close");
|
||
|
}
|
||
|
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
final_len = MIN_VALUE(param->len, sizeof(s_char_desc_attr_handle) - param->offset);
|
||
|
memcpy((uint8_t *)&s_char_desc_buff + param->offset, param->value, final_len);
|
||
|
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = param->offset;
|
||
|
rsp.attr_value.len = final_len;
|
||
|
rsp.attr_value.value = (uint8_t *)&s_char_desc_buff + param->offset;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
}
|
||
|
}
|
||
|
else if (param->handle == s_char2_attr_handle)
|
||
|
{
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
final_len = MIN_VALUE(param->len, sizeof(s_char2_buff) - param->offset);
|
||
|
memcpy(s_char2_buff + param->offset, param->value, final_len);
|
||
|
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = param->offset;
|
||
|
rsp.attr_value.len = final_len;
|
||
|
rsp.attr_value.value = s_char2_buff + param->offset;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
}
|
||
|
}
|
||
|
else if (param->handle == s_char2_desc_attr_handle)
|
||
|
{
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = param->offset;
|
||
|
rsp.attr_value.value = (uint8_t *)&s_char2_desc_buff + param->offset;
|
||
|
|
||
|
if ((param->value[0] % 2) == 0)
|
||
|
{
|
||
|
final_len = MIN_VALUE(param->len, sizeof(s_char2_desc_buff) - param->offset);
|
||
|
|
||
|
memcpy((uint8_t *)&s_char2_desc_buff + param->offset, param->value, final_len);
|
||
|
|
||
|
rsp.attr_value.len = final_len;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gatt_loge("this attr %d must write with even num [0], not %d", param->handle, param->value[0]);
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_PARAM_VAL_NOT_ALLOW, &rsp);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (param->handle == s_char_auto_rsp_attr_handle)
|
||
|
{
|
||
|
gatt_logi("write auto rsp handle %d need rsp %d", param->handle, param->need_rsp);
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
{
|
||
|
dm_gatts_db_reg_t *tmp_reg = find_db_ctx_by_attr_handle(param->handle);
|
||
|
|
||
|
if (tmp_reg && tmp_reg->cb)
|
||
|
{
|
||
|
tmp_reg->cb(event, gatts_if, comm_param);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = param->handle;
|
||
|
rsp.attr_value.offset = 0;
|
||
|
rsp.attr_value.value = NULL;
|
||
|
rsp.attr_value.len = 0;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_REQ_NOT_SUPPORTED, &rsp);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_EXEC_WRITE_EVT:
|
||
|
{
|
||
|
struct gatts_exec_write_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_EXEC_WRITE_EVT %d %d %d %d", param->conn_id, param->trans_id, param->exec_write_flag, param->need_rsp);
|
||
|
|
||
|
for (uint32_t i = 0; i < sizeof(s_dm_gatts_db_ctx.reg) / sizeof(s_dm_gatts_db_ctx.reg[0]); ++i)
|
||
|
{
|
||
|
if (s_dm_gatts_db_ctx.reg[i].status == DB_REG_STATUS_COMPLETED && s_dm_gatts_db_ctx.reg[i].cb)
|
||
|
{
|
||
|
s_dm_gatts_db_ctx.reg[i].cb(event, gatts_if, comm_param);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (param->need_rsp)
|
||
|
{
|
||
|
bk_gatt_rsp_t rsp;
|
||
|
|
||
|
memset(&rsp, 0, sizeof(rsp));
|
||
|
|
||
|
rsp.attr_value.auth_req = BK_GATT_AUTH_REQ_NONE;
|
||
|
rsp.attr_value.handle = 0;
|
||
|
rsp.attr_value.offset = 0;
|
||
|
rsp.attr_value.value = NULL;
|
||
|
rsp.attr_value.len = 0;
|
||
|
|
||
|
ret = bk_ble_gatts_send_response(gatts_if, param->conn_id, param->trans_id, BK_GATT_OK, &rsp);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_CONF_EVT:
|
||
|
{
|
||
|
struct gatts_conf_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_CONF_EVT %d %d %d", param->status, param->conn_id, param->handle);
|
||
|
|
||
|
dm_gatts_db_reg_t *tmp_reg = find_db_ctx_by_attr_handle(param->handle);
|
||
|
|
||
|
if (tmp_reg && tmp_reg->cb)
|
||
|
{
|
||
|
tmp_reg->cb(event, gatts_if, comm_param);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_RESPONSE_EVT:
|
||
|
{
|
||
|
struct gatts_rsp_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_RESPONSE_EVT %d %d", param->status, param->handle);
|
||
|
|
||
|
dm_gatts_db_reg_t *tmp_reg = find_db_ctx_by_attr_handle(param->handle);
|
||
|
|
||
|
if (tmp_reg && tmp_reg->cb)
|
||
|
{
|
||
|
tmp_reg->cb(event, gatts_if, comm_param);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_SEND_SERVICE_CHANGE_EVT:
|
||
|
{
|
||
|
struct gatts_send_service_change_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_SEND_SERVICE_CHANGE_EVT %02x:%02x:%02x:%02x:%02x:%02x %d %d",
|
||
|
param->remote_bda[5],
|
||
|
param->remote_bda[4],
|
||
|
param->remote_bda[3],
|
||
|
param->remote_bda[2],
|
||
|
param->remote_bda[1],
|
||
|
param->remote_bda[0],
|
||
|
param->status, param->conn_id);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_CONNECT_EVT:
|
||
|
{
|
||
|
struct gatts_connect_evt_param *param = (typeof(param))comm_param;
|
||
|
uint16_t hci_handle = 0;
|
||
|
ble_err_t ret = bk_ble_get_hci_handle_from_gatt_conn_id(param->conn_id, &hci_handle);
|
||
|
|
||
|
gatt_logi("BK_GATTS_CONNECT_EVT role %d %02X:%02X:%02X:%02X:%02X:%02X conn_id %d hci_handle 0x%x",
|
||
|
param->link_role,
|
||
|
param->remote_bda[5],
|
||
|
param->remote_bda[4],
|
||
|
param->remote_bda[3],
|
||
|
param->remote_bda[2],
|
||
|
param->remote_bda[1],
|
||
|
param->remote_bda[0],
|
||
|
param->conn_id,
|
||
|
(!ret ? hci_handle : 0xffff)
|
||
|
);
|
||
|
{
|
||
|
uint16_t conn_id = 0;
|
||
|
ret = bk_ble_get_gatt_conn_id_from_hci_handle(hci_handle, &conn_id);
|
||
|
gatt_logi("conn_id %d from hci handle", !ret ? conn_id : -1);
|
||
|
}
|
||
|
|
||
|
common_env_tmp = dm_ble_alloc_app_env_by_addr(param->remote_bda, sizeof(dm_gatts_app_env_t));
|
||
|
|
||
|
if (!common_env_tmp)
|
||
|
{
|
||
|
gatt_loge("alloc app env err !!!!");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
common_env_tmp->status = GAP_CONNECT_STATUS_CONNECTED;
|
||
|
common_env_tmp->conn_id = param->conn_id;
|
||
|
common_env_tmp->local_is_master = (param->link_role == 0 ? 1 : 0);
|
||
|
|
||
|
for (uint32_t i = 0; i < sizeof(s_dm_gatts_db_ctx.reg) / sizeof(s_dm_gatts_db_ctx.reg[0]); ++i)
|
||
|
{
|
||
|
if (s_dm_gatts_db_ctx.reg[i].status == DB_REG_STATUS_COMPLETED && s_dm_gatts_db_ctx.reg[i].cb)
|
||
|
{
|
||
|
s_dm_gatts_db_ctx.reg[i].cb(event, gatts_if, comm_param);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_DISCONNECT_EVT:
|
||
|
{
|
||
|
struct gatts_disconnect_evt_param *param = (typeof(param))comm_param;
|
||
|
uint8_t timer_ref_count = 0;
|
||
|
|
||
|
gatt_logi("BK_GATTS_DISCONNECT_EVT %02X:%02X:%02X:%02X:%02X:%02X conn_id %d",
|
||
|
param->remote_bda[5],
|
||
|
param->remote_bda[4],
|
||
|
param->remote_bda[3],
|
||
|
param->remote_bda[2],
|
||
|
param->remote_bda[1],
|
||
|
param->remote_bda[0],
|
||
|
param->conn_id
|
||
|
);
|
||
|
|
||
|
common_env_tmp = dm_ble_find_app_env_by_addr(param->remote_bda);
|
||
|
|
||
|
if (!common_env_tmp)
|
||
|
{
|
||
|
gatt_loge("not found addr !!!!");
|
||
|
//break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (uint32_t i = 0; i < sizeof(s_dm_gatts_db_ctx.reg) / sizeof(s_dm_gatts_db_ctx.reg[0]); ++i)
|
||
|
{
|
||
|
if (s_dm_gatts_db_ctx.reg[i].status == DB_REG_STATUS_COMPLETED && s_dm_gatts_db_ctx.reg[i].cb)
|
||
|
{
|
||
|
s_dm_gatts_db_ctx.reg[i].cb(event, gatts_if, comm_param);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dm_ble_del_app_env_by_addr(param->remote_bda);
|
||
|
}
|
||
|
|
||
|
#if GATTS_TEST_ATTR_ENABLE
|
||
|
dm_ble_app_env_foreach(nest_func_check_timer_ref_count, &timer_ref_count);
|
||
|
|
||
|
if (!timer_ref_count && rtos_is_timer_init(&s_char_notify_timer))
|
||
|
{
|
||
|
if (rtos_is_timer_running(&s_char_notify_timer))
|
||
|
{
|
||
|
rtos_stop_timer(&s_char_notify_timer);
|
||
|
}
|
||
|
|
||
|
rtos_deinit_timer(&s_char_notify_timer);
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
#if 0
|
||
|
dm_gatts_set_adv_param(s_dm_gatts_local_addr_is_public);
|
||
|
rtos_delay_milliseconds(100);
|
||
|
|
||
|
const bk_ble_gap_ext_adv_t ext_adv =
|
||
|
{
|
||
|
.instance = 0,
|
||
|
.duration = 0,
|
||
|
.max_events = 0,
|
||
|
};
|
||
|
|
||
|
ret = bk_ble_gap_adv_start(1, &ext_adv);
|
||
|
|
||
|
if (ret)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gap_adv_start err %d", ret);
|
||
|
}
|
||
|
|
||
|
rtos_delay_milliseconds(100);
|
||
|
#endif
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case BK_GATTS_MTU_EVT:
|
||
|
{
|
||
|
struct gatts_mtu_evt_param *param = (typeof(param))comm_param;
|
||
|
|
||
|
gatt_logi("BK_GATTS_MTU_EVT %d %d", param->conn_id, param->mtu);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
int32_t dm_gatts_disconnect(uint8_t *addr)
|
||
|
{
|
||
|
dm_gatt_app_env_t *common_env_tmp = NULL;
|
||
|
int32_t err = 0;
|
||
|
|
||
|
gatt_logi("0x%02x:%02x:%02x:%02x:%02x:%02x",
|
||
|
addr[5],
|
||
|
addr[4],
|
||
|
addr[3],
|
||
|
addr[2],
|
||
|
addr[1],
|
||
|
addr[0]);
|
||
|
|
||
|
if (!s_gatts_if)
|
||
|
{
|
||
|
gatt_loge("gatts not init");
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
common_env_tmp = dm_ble_find_app_env_by_addr(addr);
|
||
|
|
||
|
if (!common_env_tmp || !common_env_tmp->data)
|
||
|
{
|
||
|
gatt_loge("conn not found !!!!", common_env_tmp, common_env_tmp ? common_env_tmp->data : NULL);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (common_env_tmp->status != GAP_CONNECT_STATUS_CONNECTED)
|
||
|
{
|
||
|
gatt_loge("connect status is not connected %d", common_env_tmp->status);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
bk_bd_addr_t peer_addr;
|
||
|
os_memcpy(peer_addr, addr, sizeof(peer_addr));
|
||
|
|
||
|
err = bk_ble_gap_disconnect(peer_addr);
|
||
|
|
||
|
if (err)
|
||
|
{
|
||
|
gatt_loge("disconnect fail %d", err);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
common_env_tmp->status = GAP_CONNECT_STATUS_DISCONNECTING;
|
||
|
}
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
static int32_t dm_gatts_set_adv_param(uint8_t local_addr_is_public)
|
||
|
{
|
||
|
int32_t ret = 0;
|
||
|
bk_bd_addr_t nominal_addr = {0};
|
||
|
uint8_t nominal_addr_type = 0;
|
||
|
bk_bd_addr_t identity_addr = {0};
|
||
|
uint8_t identity_addr_type = 0;
|
||
|
bk_ble_gap_ext_adv_params_t adv_param = {0};
|
||
|
|
||
|
adv_param = (bk_ble_gap_ext_adv_params_t)
|
||
|
{
|
||
|
.type = BK_BLE_GAP_SET_EXT_ADV_PROP_LEGACY_IND,
|
||
|
.interval_min = 120 * 1,
|
||
|
.interval_max = 160 * 1,
|
||
|
.channel_map = BK_ADV_CHNL_ALL,
|
||
|
.filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
|
||
|
.primary_phy = BK_BLE_GAP_PRI_PHY_1M,
|
||
|
.secondary_phy = BK_BLE_GAP_PHY_1M,
|
||
|
.sid = 0,
|
||
|
.scan_req_notif = 0,
|
||
|
};
|
||
|
|
||
|
// attention: some device could only connect rpa adv after pair, some device is opposite, some device behavior depend on which adv is used when pairing.
|
||
|
// so we need to decide if rpa should be used in adv.
|
||
|
|
||
|
if (g_dm_gap_use_rpa && 0 == dm_gatt_get_authen_status(nominal_addr, &nominal_addr_type, identity_addr, &identity_addr_type))
|
||
|
{
|
||
|
adv_param.own_addr_type = (local_addr_is_public ? BLE_ADDR_TYPE_RPA_PUBLIC : BLE_ADDR_TYPE_RPA_RANDOM);
|
||
|
|
||
|
adv_param.peer_addr_type = nominal_addr_type;
|
||
|
os_memcpy(adv_param.peer_addr, nominal_addr, sizeof(nominal_addr));
|
||
|
|
||
|
gatt_logw("set adv param rpa because pair, addr type 0x%x", adv_param.own_addr_type);
|
||
|
}
|
||
|
#if SET_ADVTYPE_TO_IDENTITY_WHEN_NORPA
|
||
|
else if (!g_dm_gap_use_rpa && !local_addr_is_public && 0 == dm_gatt_get_authen_status(nominal_addr, &nominal_addr_type, identity_addr, &identity_addr_type))
|
||
|
{
|
||
|
adv_param.own_addr_type = identity_addr_type;
|
||
|
gatt_logw("set adv param no rpa because pair, addr type 0x%x", adv_param.own_addr_type);
|
||
|
}
|
||
|
#endif
|
||
|
else
|
||
|
{
|
||
|
adv_param.own_addr_type = (local_addr_is_public ? BLE_ADDR_TYPE_PUBLIC : BLE_ADDR_TYPE_RANDOM);
|
||
|
gatt_logw("set adv param other, addr type 0x%x", adv_param.own_addr_type);
|
||
|
}
|
||
|
|
||
|
ret = bk_ble_gap_set_adv_params(ADV_HANDLE, &adv_param);
|
||
|
|
||
|
if (ret)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gap_set_adv_params err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
error:;
|
||
|
|
||
|
gatt_loge("err");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int32_t dm_gatts_enable_adv(uint8_t enable)
|
||
|
{
|
||
|
int32_t ret = 0;
|
||
|
|
||
|
if (!s_gatts_if)
|
||
|
{
|
||
|
gatt_loge("gatts not init");
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (enable)
|
||
|
{
|
||
|
const bk_ble_gap_ext_adv_t ext_adv =
|
||
|
{
|
||
|
.instance = 0,
|
||
|
.duration = 0,
|
||
|
.max_events = 0,
|
||
|
};
|
||
|
|
||
|
ret = bk_ble_gap_adv_start(1, &ext_adv);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
const uint8_t ext_adv_inst[] = {0};
|
||
|
ret = bk_ble_gap_adv_stop(sizeof(ext_adv_inst) / sizeof(ext_adv_inst[0]), ext_adv_inst);
|
||
|
}
|
||
|
|
||
|
if (ret)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gap_adv_start err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("wait set adv enable err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
error:;
|
||
|
gatt_loge("err");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int32_t dm_gatts_enable_service(uint32_t index, uint8_t enable)
|
||
|
{
|
||
|
int32_t ret = 0;
|
||
|
uint16_t handle = 0;
|
||
|
#if GATTS_TEST_ATTR_ENABLE
|
||
|
handle = (index == 0 ? s_service_attr_handle : s_attr_handle_list2[0]);
|
||
|
#endif
|
||
|
|
||
|
if (!s_gatts_if)
|
||
|
{
|
||
|
gatt_loge("gatts not init");
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (enable)
|
||
|
{
|
||
|
bk_ble_gatts_start_service(handle);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bk_ble_gatts_stop_service(handle);
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("wait start/stop service err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
bk_ble_gatts_send_service_change_indicate(s_gatts_if, 0, 1);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static dm_gatts_db_reg_t *find_db_ctx_by_attr_handle(uint16_t attr_handle)
|
||
|
{
|
||
|
for (uint32_t i = 0; i < sizeof(s_dm_gatts_db_ctx.reg) / sizeof(s_dm_gatts_db_ctx.reg[0]); ++i)
|
||
|
{
|
||
|
if (s_dm_gatts_db_ctx.reg[i].status == DB_REG_STATUS_COMPLETED &&
|
||
|
s_dm_gatts_db_ctx.reg[i].attr_list &&
|
||
|
s_dm_gatts_db_ctx.reg[i].attr_list[0] <= attr_handle &&
|
||
|
s_dm_gatts_db_ctx.reg[i].attr_list[s_dm_gatts_db_ctx.reg[i].count - 1] >= attr_handle
|
||
|
)
|
||
|
{
|
||
|
return &s_dm_gatts_db_ctx.reg[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
int32_t dm_gatts_reg_db(bk_gatts_attr_db_t *list, uint32_t count, uint16_t *attr_handle_list, dm_ble_gatts_db_cb cb)
|
||
|
{
|
||
|
uint32_t i = 0;
|
||
|
|
||
|
if (!list || !count)
|
||
|
{
|
||
|
gatt_loge("reg err %p %d", list, count);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < sizeof(s_dm_gatts_db_ctx.reg) / sizeof(s_dm_gatts_db_ctx.reg[0]); ++i)
|
||
|
{
|
||
|
if (s_dm_gatts_db_ctx.reg[i].status == DB_REG_STATUS_IDLE)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i >= sizeof(s_dm_gatts_db_ctx.reg) / sizeof(s_dm_gatts_db_ctx.reg[0]))
|
||
|
{
|
||
|
gatt_loge("reg full !!!");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
s_dm_gatts_db_ctx.reg[i].db = list;
|
||
|
s_dm_gatts_db_ctx.reg[i].attr_list = attr_handle_list;
|
||
|
s_dm_gatts_db_ctx.reg[i].count = count;
|
||
|
s_dm_gatts_db_ctx.reg[i].cb = cb;
|
||
|
s_dm_gatts_db_ctx.reg[i].status = DB_REG_STATUS_WAIT_COMPLETED;
|
||
|
|
||
|
ble_err_t ret = bk_ble_gatts_create_attr_tab(list, s_gatts_if, count, 30);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gatts_create_attr_tab err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
s_dm_gatts_db_ctx.reg[i].status = DB_REG_STATUS_COMPLETED;
|
||
|
|
||
|
bk_ble_gatts_start_service(attr_handle_list[0]);
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("wait start/stop service err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int32_t dm_gatts_get_buff_from_attr_handle(bk_gatts_attr_db_t *attr_list, uint16_t *attr_handle_list, uint32_t size, uint16_t attr_handle, uint32_t *output_index, uint8_t **output_buff, uint32_t *output_size)
|
||
|
{
|
||
|
uint32_t i;
|
||
|
|
||
|
for (i = 0; i < size; ++i)
|
||
|
{
|
||
|
if (attr_handle_list[i] == attr_handle)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i >= size)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
*output_index = i;
|
||
|
*output_buff = attr_list[i].att_desc.value.attr_value;
|
||
|
*output_size = attr_list[i].att_desc.value.attr_len;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int32_t dm_gatts_is_init(void)
|
||
|
{
|
||
|
return s_dm_gatts_is_init;
|
||
|
}
|
||
|
|
||
|
int dm_gatts_main(cli_gatt_param_t *param)
|
||
|
{
|
||
|
ble_err_t ret = 0;
|
||
|
|
||
|
if (s_dm_gatts_is_init)
|
||
|
{
|
||
|
gatt_loge("already init");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_init_semaphore(&s_ble_sema, 1);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("rtos_init_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (param)
|
||
|
{
|
||
|
if (param->p_pa)
|
||
|
{
|
||
|
s_dm_gatts_local_addr_is_public = *param->p_pa;
|
||
|
gatt_loge("set gatts addr is public %d", s_dm_gatts_local_addr_is_public);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bk_ble_gatts_register_callback(bk_gatts_cb);
|
||
|
|
||
|
ret = bk_ble_gatts_app_register(0);
|
||
|
|
||
|
if (ret)
|
||
|
{
|
||
|
gatt_loge("reg err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore reg err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
#if DYNAMIC_ADD_ATTR
|
||
|
|
||
|
bk_bt_uuid_t uuid;
|
||
|
const bk_gatt_perm_t perm = BK_GATT_PERM_READ | BK_GATT_PERM_WRITE;
|
||
|
bk_attr_value_t value;
|
||
|
bk_attr_control_t ctrl;
|
||
|
const bk_gatt_char_prop_t prop = BK_GATT_CHAR_PROP_BIT_READ | BK_GATT_CHAR_PROP_BIT_WRITE_NR | BK_GATT_CHAR_PROP_BIT_WRITE
|
||
|
| BK_GATT_CHAR_PROP_BIT_NOTIFY;
|
||
|
|
||
|
bk_gatt_srvc_id_t srvc_id;
|
||
|
|
||
|
memset(&srvc_id, 0, sizeof(srvc_id));
|
||
|
srvc_id.is_primary = 1;
|
||
|
srvc_id.id.uuid.len = BK_UUID_LEN_16;
|
||
|
srvc_id.id.uuid.uuid.uuid16 = 0x1234;
|
||
|
|
||
|
ret = bk_ble_gatts_create_service(0, &srvc_id, 30);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gatts_create_service err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
memset(&uuid, 0, sizeof(uuid));
|
||
|
memset(&value, 0, sizeof(value));
|
||
|
memset(&ctrl, 0, sizeof(ctrl));
|
||
|
|
||
|
uuid.len = BK_UUID_LEN_16;
|
||
|
uuid.uuid.uuid16 = 0x5678;
|
||
|
value.attr_value = s_char_buff;
|
||
|
value.attr_len = value.attr_max_len = sizeof(s_char_buff);
|
||
|
ctrl.auto_rsp = 0;
|
||
|
|
||
|
ret = bk_ble_gatts_add_char(s_service_attr_handle, &uuid, perm, prop, &value, &ctrl);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gatts_add_char err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
uint16_t tmp_len = 0;
|
||
|
uint8_t *tmp_buff = NULL;
|
||
|
bk_gatt_status_t g_status = 0;
|
||
|
|
||
|
g_status = bk_ble_gatts_get_attr_value(s_char_attr_handle, &tmp_len, &tmp_buff);
|
||
|
|
||
|
if (g_status)
|
||
|
{
|
||
|
gatt_loge("get attr value err %d", g_status);
|
||
|
}
|
||
|
|
||
|
if (tmp_len != value.attr_len || tmp_buff != value.attr_value)
|
||
|
{
|
||
|
gatt_loge("%d %d get attr value not match create %d %d %p %p!!!!", __LINE__, g_status,
|
||
|
tmp_len, value.attr_len, tmp_buff, value.attr_value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
memset(&uuid, 0, sizeof(uuid));
|
||
|
memset(&value, 0, sizeof(value));
|
||
|
memset(&ctrl, 0, sizeof(ctrl));
|
||
|
|
||
|
uuid.len = BK_UUID_LEN_16;
|
||
|
uuid.uuid.uuid16 = BK_GATT_UUID_CHAR_CLIENT_CONFIG;
|
||
|
value.attr_value = (uint8_t *)&s_char_desc_buff;
|
||
|
value.attr_len = value.attr_max_len = sizeof(s_char_desc_buff);
|
||
|
ctrl.auto_rsp = 0;
|
||
|
|
||
|
ret = bk_ble_gatts_add_char_descr(s_service_attr_handle, s_char_attr_handle, &uuid, perm, &value, &ctrl);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gatts_add_char_descr err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
uint16_t tmp_len = 0;
|
||
|
uint8_t *tmp_buff = NULL;
|
||
|
bk_gatt_status_t g_status = 0;
|
||
|
|
||
|
g_status = bk_ble_gatts_get_attr_value(s_char_desc_attr_handle, &tmp_len, &tmp_buff);
|
||
|
|
||
|
if (g_status)
|
||
|
{
|
||
|
gatt_loge("get attr value err %d", g_status);
|
||
|
}
|
||
|
|
||
|
if (tmp_len != value.attr_len || tmp_buff != value.attr_value)
|
||
|
{
|
||
|
gatt_loge("%d %d get attr value not match create %d %d %p %p!!!!", __LINE__, g_status,
|
||
|
tmp_len, value.attr_len, tmp_buff, value.attr_value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
memset(&uuid, 0, sizeof(uuid));
|
||
|
memset(&value, 0, sizeof(value));
|
||
|
memset(&ctrl, 0, sizeof(ctrl));
|
||
|
|
||
|
uuid.len = BK_UUID_LEN_16;
|
||
|
uuid.uuid.uuid16 = 0x9abc;
|
||
|
value.attr_value = s_char2_buff;
|
||
|
value.attr_len = value.attr_max_len = sizeof(s_char2_buff);
|
||
|
ctrl.auto_rsp = 0;
|
||
|
|
||
|
ret = bk_ble_gatts_add_char(s_service_attr_handle, &uuid, perm, prop, &value, &ctrl);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gatts_add_char 2 err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
uint16_t tmp_len = 0;
|
||
|
uint8_t *tmp_buff = NULL;
|
||
|
bk_gatt_status_t g_status = 0;
|
||
|
|
||
|
g_status = bk_ble_gatts_get_attr_value(s_char2_attr_handle, &tmp_len, &tmp_buff);
|
||
|
|
||
|
if (g_status)
|
||
|
{
|
||
|
gatt_loge("get attr value err %d", g_status);
|
||
|
}
|
||
|
|
||
|
if (tmp_len != value.attr_len || tmp_buff != value.attr_value)
|
||
|
{
|
||
|
gatt_loge("%d %d get attr value not match create %d %d %p %p!!!!", __LINE__, g_status,
|
||
|
tmp_len, value.attr_len, tmp_buff, value.attr_value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
memset(&uuid, 0, sizeof(uuid));
|
||
|
memset(&value, 0, sizeof(value));
|
||
|
memset(&ctrl, 0, sizeof(ctrl));
|
||
|
|
||
|
uuid.len = BK_UUID_LEN_16;
|
||
|
uuid.uuid.uuid16 = BK_GATT_UUID_CHAR_SRVR_CONFIG;
|
||
|
value.attr_value = (uint8_t *)&s_char2_desc_buff;
|
||
|
value.attr_len = value.attr_max_len = sizeof(s_char2_desc_buff);
|
||
|
ctrl.auto_rsp = 0;
|
||
|
|
||
|
ret = bk_ble_gatts_add_char_descr(s_service_attr_handle, s_char2_attr_handle, &uuid, perm, &value, &ctrl);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gatts_add_char_descr 2 err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
{
|
||
|
uint16_t tmp_len = 0;
|
||
|
uint8_t *tmp_buff = NULL;
|
||
|
bk_gatt_status_t g_status = 0;
|
||
|
|
||
|
g_status = bk_ble_gatts_get_attr_value(s_char2_desc_attr_handle, &tmp_len, &tmp_buff);
|
||
|
|
||
|
if (g_status)
|
||
|
{
|
||
|
gatt_loge("get attr value err %d", g_status);
|
||
|
}
|
||
|
|
||
|
if (tmp_len != value.attr_len || tmp_buff != value.attr_value)
|
||
|
{
|
||
|
gatt_loge("%d %d get attr value not match create %d %d %p %p!!!!", __LINE__, g_status,
|
||
|
tmp_len, value.attr_len, tmp_buff, value.attr_value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
memset(&uuid, 0, sizeof(uuid));
|
||
|
memset(&value, 0, sizeof(value));
|
||
|
memset(&ctrl, 0, sizeof(ctrl));
|
||
|
|
||
|
uuid.len = BK_UUID_LEN_16;
|
||
|
uuid.uuid.uuid16 = 0x15ab;
|
||
|
value.attr_value = s_char_auto_rsp_buff;
|
||
|
value.attr_len = value.attr_max_len = sizeof(s_char_auto_rsp_buff);
|
||
|
ctrl.auto_rsp = 1;
|
||
|
|
||
|
ret = bk_ble_gatts_add_char(s_service_attr_handle, &uuid, perm, prop, &value, &ctrl);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gatts_add_char auto err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
uint16_t tmp_len = 0;
|
||
|
uint8_t *tmp_buff = NULL;
|
||
|
bk_gatt_status_t g_status = 0;
|
||
|
|
||
|
g_status = bk_ble_gatts_get_attr_value(s_char_auto_rsp_attr_handle, &tmp_len, &tmp_buff);
|
||
|
|
||
|
if (g_status)
|
||
|
{
|
||
|
gatt_loge("get attr value err %d", g_status);
|
||
|
}
|
||
|
|
||
|
if (tmp_len != value.attr_len || tmp_buff != value.attr_value)
|
||
|
{
|
||
|
gatt_loge("%d %d get attr value not match create %d %d %p %p!!!!", __LINE__, g_status,
|
||
|
tmp_len, value.attr_len, tmp_buff, value.attr_value);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#elif GATTS_TEST_ATTR_ENABLE
|
||
|
|
||
|
ret = bk_ble_gatts_create_attr_tab(s_gatts_attr_db_service_1, s_gatts_if, sizeof(s_gatts_attr_db_service_1) / sizeof(s_gatts_attr_db_service_1[0]), 30);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gatts_create_attr_tab err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = bk_ble_gatts_create_attr_tab(s_gatts_attr_db_service_2, s_gatts_if, sizeof(s_gatts_attr_db_service_2) / sizeof(s_gatts_attr_db_service_2[0]), 30);
|
||
|
|
||
|
if (ret != 0)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gatts_create_attr_tab 2 err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
bk_ble_gatts_start_service(s_service_attr_handle);
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
bk_ble_gatts_start_service(s_attr_handle_list2[0]);
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("rtos_get_semaphore err %d", ret);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
bk_bd_addr_t current_addr = {0}, identity_addr = {0};
|
||
|
char adv_name[64] = {0};
|
||
|
|
||
|
dm_ble_gap_get_identity_addr(identity_addr);
|
||
|
|
||
|
os_memcpy(current_addr, identity_addr, sizeof(identity_addr));
|
||
|
|
||
|
dm_gatt_add_gap_callback(dm_ble_gap_cb);
|
||
|
|
||
|
snprintf((char *)(adv_name), sizeof(adv_name) - 1, "CENTRAL-%02X%02X%02X", identity_addr[2], identity_addr[1], identity_addr[0]);
|
||
|
|
||
|
gatt_logi("adv name %s", adv_name);
|
||
|
|
||
|
ret = bk_ble_gap_set_device_name(adv_name);
|
||
|
|
||
|
if (ret)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gap_set_device_name err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
ret = dm_gatts_set_adv_param(s_dm_gatts_local_addr_is_public);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("set adv param err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("wait set adv param err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
uint8_t need_set_random_addr = 0;
|
||
|
uint8_t identity_addr_type = 0;
|
||
|
|
||
|
if (g_dm_gap_use_rpa && dm_ble_gap_get_rpa(current_addr) == 0)
|
||
|
{
|
||
|
gatt_logw("set adv random addr with generate rpa");
|
||
|
need_set_random_addr = 1;
|
||
|
}
|
||
|
#if SET_ADVTYPE_TO_IDENTITY_WHEN_NORPA
|
||
|
else if (!g_dm_gap_use_rpa && !s_dm_gatts_local_addr_is_public && 0 == dm_gatt_get_authen_status(NULL, NULL, NULL, &identity_addr_type))
|
||
|
{
|
||
|
if(identity_addr_type == BLE_ADDR_TYPE_RANDOM)
|
||
|
{
|
||
|
gatt_logw("set adv random addr with identity addr because no rpa pair exist, type %d", identity_addr_type);
|
||
|
|
||
|
need_set_random_addr = 1;
|
||
|
os_memcpy(current_addr, identity_addr, sizeof(identity_addr));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//walkaround controller bug that random addr will take effect once bk_ble_gap_set_adv_rand_addr set
|
||
|
gatt_logw("no need set adv random addr because no rpa pair exist, type %d", identity_addr_type);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
else if (!s_dm_gatts_local_addr_is_public)
|
||
|
{
|
||
|
gatt_logw("set adv random addr with user define");
|
||
|
|
||
|
current_addr[0]++;
|
||
|
current_addr[5] |= 0xc0; // static random addr[47:46] must be 0b11 in msb !!!
|
||
|
//current_addr[5] = 0x0;
|
||
|
|
||
|
need_set_random_addr = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gatt_logw("no need set random addr");
|
||
|
}
|
||
|
|
||
|
if (need_set_random_addr)
|
||
|
{
|
||
|
ret = bk_ble_gap_set_adv_rand_addr(ADV_HANDLE, current_addr);
|
||
|
|
||
|
if (ret)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gap_set_adv_rand_addr err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("wait set adv rand addr err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
//use hid service
|
||
|
const uint8_t hogp_service_uuid[16] =
|
||
|
{
|
||
|
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
|
||
|
0x00, 0x10, 0x00, 0x00,
|
||
|
BK_GATT_UUID_HID_SVC & 0xff, (BK_GATT_UUID_HID_SVC >> 8) & 0xff, 0x00, 0x00
|
||
|
};
|
||
|
|
||
|
bk_ble_adv_data_t adv_data =
|
||
|
{
|
||
|
.set_scan_rsp = 0,
|
||
|
.include_name = 1,
|
||
|
.min_interval = 0x0006,
|
||
|
.max_interval = 0x0010,
|
||
|
.appearance = 0x8001,//0xc103,
|
||
|
.manufacturer_len = 0,
|
||
|
.p_manufacturer_data = NULL,
|
||
|
.service_data_len = 0,
|
||
|
.p_service_data = NULL,
|
||
|
.service_uuid_len = sizeof(hogp_service_uuid),
|
||
|
.p_service_uuid = (void *)hogp_service_uuid,
|
||
|
.flag = 2,//0x06,
|
||
|
};
|
||
|
#else
|
||
|
bk_ble_adv_data_t adv_data =
|
||
|
{
|
||
|
.set_scan_rsp = 0,
|
||
|
.include_name = 1,
|
||
|
.min_interval = 0x0006,
|
||
|
.max_interval = 0x0010,
|
||
|
.appearance = 0,
|
||
|
.manufacturer_len = 0,
|
||
|
.p_manufacturer_data = NULL,
|
||
|
.service_data_len = 0,
|
||
|
.p_service_data = NULL,
|
||
|
.service_uuid_len = 0,
|
||
|
.p_service_uuid = NULL,
|
||
|
.flag = 0x06,
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
ret = bk_ble_gap_set_adv_data((bk_ble_adv_data_t *)&adv_data);
|
||
|
|
||
|
if (ret)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gap_set_adv_data err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("wait set adv data err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
adv_data.set_scan_rsp = 1;
|
||
|
|
||
|
ret = bk_ble_gap_set_adv_data((bk_ble_adv_data_t *)&adv_data);
|
||
|
|
||
|
if (ret)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gap_set_adv_data scan rsp err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("wait set adv data scan rsp err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
const bk_ble_gap_ext_adv_t ext_adv =
|
||
|
{
|
||
|
.instance = 0,
|
||
|
.duration = 0,
|
||
|
.max_events = 0,
|
||
|
};
|
||
|
|
||
|
ret = bk_ble_gap_adv_start(1, &ext_adv);
|
||
|
|
||
|
if (ret)
|
||
|
{
|
||
|
gatt_loge("bk_ble_gap_adv_start err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
ret = rtos_get_semaphore(&s_ble_sema, SYNC_CMD_TIMEOUT_MS);
|
||
|
|
||
|
if (ret != kNoErr)
|
||
|
{
|
||
|
gatt_loge("wait set adv enable err %d", ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
s_dm_gatts_is_init = 1;
|
||
|
error:
|
||
|
return 0;
|
||
|
}
|