mcu_hi3321_watch/application/wearable/alipay/service/alipay_bluetooth.c
2025-05-26 20:15:20 +08:00

451 lines
18 KiB
C

/**
* Copyright (c) CompanyNameMagicTag 2023-2023. All rights reserved.
* Description: alipay bluetooth module.
* Author:
* Create:
*/
#include "common_def.h"
#include "bts_def.h"
#include "bts_gatt_stru.h"
#include "bts_a2dp_source.h"
#include "bts_gatt_server.h"
#include "bts_le_gap.h"
#include "bts_br_gap.h"
#include "osal_task.h"
#include "alipay_feature.h"
#include "securec.h"
#include "cmsis_os2.h"
#ifdef SUPPORT_OHOSFWK
#include "BluetoothWrapper.h"
#endif
/* Gatt service UUID */
#define ALIPAYY_SERVICE_ID 0x0238
/* Gatt Characteristic UUID */
#define ALIPAYY_CHARACTERISTIC_ID 0x024A
/* Client Characteristic Configuration UUID */
#define ALIPAYY_BLE_UUID_CLIENT_CHARACTERISTIC_CONF 0x2902
/* Gatt Characteristic max length */
#define ALIPAY_CHARACTERISTIC_MAX_LENGTH 256
#define ALIPAY_BLE_ADV_ID 1
#define ALIPAY_BLE_ADV_DATA_MAX_LENGTH 31
#define ALIPAY_BLE_ADV_BLE_NAME_MAX_LENGTH 13 // 31-4-2-3-9 = 13
#define ALIPAY_BLE_NAME_LENGTH 20
#define ALIPAY_BLE_ADV_MAC_HEAD_LENTH 4
#define ALIPAY_BLE_ADV_MAC_LENTH 10
#define ALIPAY_BLE_ADV_TYPE_LENTH 3
#define ALIPAY_BLE_ADV_UUID_LENTH 4
#define ALIPAY_BLE_DEFAULT_NAME "WatchDemo"
#define ALIPAY_BLE_DEFAULT_NAME_LEN 9
#define ALIPAY_DESC_HANDLE_NUM 2
#define UUID16_LEN 2
// Alipay 蓝牙模块全局变量
static gap_ble_callbacks_t g_alipay_gapble_cbs;
static gatts_callbacks_t g_alipay_gatts_cbs;
static bool g_alipay_adv_start_state = false;
static uint16_t g_alipay_server_id = 1;
static uint16_t g_alipay_characteristic_handle = 0;
static uint16_t g_alipay_descriptor_handle[ALIPAY_DESC_HANDLE_NUM] = { 0 };
static uint16_t g_alipay_svr_handle = 0;
static uint16_t g_alipay_conn_id = 0;
static uint8_t g_alipay_character_buf[ALIPAY_CHARACTERISTIC_MAX_LENGTH] = {0};
static bool g_alipay_ble_init_flag = false;
static const uint8_t alipay_adv_type[ALIPAY_BLE_ADV_TYPE_LENTH] = {2, 1, 2};
static const uint8_t alipay_adv_uuid[ALIPAY_BLE_ADV_UUID_LENTH] = {0x3, 0x3, 0x02, 0x38};
static bool svr_alipay_get_adv_start_state(void)
{
return g_alipay_adv_start_state;
}
static void svr_alipay_set_adv_start_state(bool state)
{
g_alipay_adv_start_state = state;
}
void svr_alipay_ble_adv_stop(void)
{
gap_ble_stop_adv(ALIPAY_BLE_ADV_ID);
}
/* adapt ios adv data. */
static void svr_alipay_ble_adv_data_set(int adv_id)
{
uint8_t ble_name[ALIPAY_BLE_NAME_LENGTH] = {0};
uint8_t ble_name_len = ALIPAY_BLE_NAME_LENGTH;
uint8_t adv_data[ALIPAY_BLE_ADV_DATA_MAX_LENGTH] = {0};
uint8_t adv_data_len = 0;
uint8_t ble_data_name[ALIPAY_BLE_ADV_BLE_NAME_MAX_LENGTH + 1 ] = {0}; // +TYPE LENGTH
uint8_t ble_data_mac_switch[BD_ADDR_LEN] = {0};
uint8_t adv_mac_head[ALIPAY_BLE_ADV_MAC_LENTH] = {0x9, 0x16, 0x02, 0x38};
gap_ble_config_adv_data_t adv_data_info;
memset_s(&adv_data_info, sizeof(gap_ble_config_adv_data_t), 0, sizeof(gap_ble_config_adv_data_t));
int32_t ret = gap_ble_get_local_name(ble_name, &ble_name_len);
if (ret != 0) {
ALIPAY_PRINT_ERR(0, "gap_ble_get_local_name fail, name:%s,len:%u,ret:%u.", ble_name, ble_name_len, ret);
memset_s(ble_name, ALIPAY_BLE_NAME_LENGTH, 0, ALIPAY_BLE_NAME_LENGTH);
memcpy_s(ble_name, ALIPAY_BLE_NAME_LENGTH, ALIPAY_BLE_DEFAULT_NAME, ALIPAY_BLE_DEFAULT_NAME_LEN);
ble_name_len = ALIPAY_BLE_DEFAULT_NAME_LEN + 1;
}
ALIPAY_PRINT_DEBUG(0, "gap_ble_get_local_name name:%s,len:%u,ret:%u.", ble_name, ble_name_len, ret);
bd_addr_t addr_info;
ret = gap_ble_get_local_addr(&addr_info);
ALIPAY_PRINT_DEBUG(0, "gap_ble_get_local_addr, ret:%u.", ret);
memcpy_s(adv_data, sizeof(alipay_adv_type), alipay_adv_type, sizeof(alipay_adv_type));
adv_data_len = sizeof(alipay_adv_type);
if (ble_name_len > ALIPAY_BLE_ADV_BLE_NAME_MAX_LENGTH) {
ble_name_len = ALIPAY_BLE_ADV_BLE_NAME_MAX_LENGTH;
}
ble_data_name[0] = ble_name_len;
ble_data_name[1] = 0x9;
memcpy_s(&ble_data_name[2], ble_name_len - 1, ble_name, ble_name_len - 1);
memcpy_s(adv_data + adv_data_len, ble_name_len + 1, ble_data_name, ble_name_len + 1);
adv_data_len = adv_data_len + ble_name_len + 1;
memcpy_s(adv_data + adv_data_len, sizeof(alipay_adv_uuid), alipay_adv_uuid, sizeof(alipay_adv_uuid));
adv_data_len = adv_data_len + sizeof(alipay_adv_uuid);
int k = BD_ADDR_LEN;
for (int i = 0; i < BD_ADDR_LEN; i++) {
ble_data_mac_switch[--k] = addr_info.addr[i];
}
ALIPAY_PRINT_DEBUG(0, "ble_info:%02x:%02x:%02x:%02x:%02x:%02x", ble_data_mac_switch[0], ble_data_mac_switch[1],
ble_data_mac_switch[2], ble_data_mac_switch[3], ble_data_mac_switch[4], ble_data_mac_switch[5]);
memcpy_s(adv_mac_head + ALIPAY_BLE_ADV_MAC_HEAD_LENTH, BD_ADDR_LEN, ble_data_mac_switch, BD_ADDR_LEN);
memcpy_s(adv_data + adv_data_len, sizeof(adv_mac_head), adv_mac_head, sizeof(adv_mac_head));
adv_data_len = adv_data_len + sizeof(adv_mac_head);
adv_data_info.adv_data = adv_data;
adv_data_info.adv_length = adv_data_len;
ALIPAY_PRINT_DEBUG(0, "adv_data_info.adv_length:%u.", adv_data_len);
gap_ble_set_adv_data(adv_id, &adv_data_info);
return;
}
void svr_alipay_ble_adv_start(void)
{
int adv_id = ALIPAY_BLE_ADV_ID;
if (svr_alipay_get_adv_start_state()) {
ALIPAY_PRINT_ERR(0, "BleAdvStart already started");
gap_ble_stop_adv(adv_id);
osDelay(50);
}
gap_ble_adv_params_t adv_para;
memset_s(&adv_para, sizeof(gap_ble_adv_params_t), 0, sizeof(gap_ble_adv_params_t));
adv_para.min_interval = 0x30;
adv_para.max_interval = 0x60;
adv_para.adv_type = GAP_BLE_ADV_CONN_SCAN_UNDIR;
adv_para.channel_map = 0x7;
adv_para.duration = 0;
gap_ble_set_adv_param(adv_id, &adv_para);
gap_ble_set_local_appearance(GAP_BLE_APPEARANCE_TYPE_GENERIC_WATCH);
svr_alipay_ble_adv_data_set(adv_id);
bool ret = gap_ble_start_adv(adv_id);
if (ret) {
ALIPAY_PRINT_ERR(0, "svr_alipay_ble_adv_start bt gap_ble_start_adv ret = 0x%x", ret);
}
ALIPAY_PRINT_DEBUG(0, "svr_alipay_ble_adv_start bt gap_ble_start_adv ret = 0x%x", ret);
}
static void svr_alipay_ble_connstate_change_cb(unsigned short conn_id, bd_addr_t *addr, gap_ble_conn_state_t conn_state,
gap_ble_pair_state_t pair_state, gap_ble_disc_reason_t disc_reason)
{
unused(addr);
unused(pair_state);
unused(disc_reason);
ALIPAY_PRINT_DEBUG(0, "BleConnStateChangeCallback conn_id 0x%x, conn_state 0x%x, pair_state 0x%x", conn_id,
conn_state, pair_state);
if (GAP_BLE_STATE_DISCONNECTED == conn_state) {
g_alipay_conn_id = 0;
} else {
g_alipay_conn_id = conn_id;
}
}
static void svr_alipay_ble_adv_start_cb(uint8_t adv_id, adv_status_t status)
{
unused(status);
if (adv_id == ALIPAY_BLE_ADV_ID) {
ALIPAY_PRINT_DEBUG(0, "BleAdvStartCallback adv_id: %d, status:%d\n", adv_id, status);
svr_alipay_set_adv_start_state(true);
}
}
static void svr_alipay_ble_set_adv_data_cb(uint8_t adv_id, errcode_t status)
{
unused(adv_id);
unused(status);
ALIPAY_PRINT_DEBUG(0, "BleAdvSetDataCallback adv_id: %d, status:%d\n", adv_id, status);
}
static void svr_alipay_ble_terminate_adv_cb(uint8_t adv_id, adv_status_t status)
{
unused(status);
if (adv_id == ALIPAY_BLE_ADV_ID) {
ALIPAY_PRINT_DEBUG(0, "BleTerminateAdvCallback adv_id: %d, status:%d\n", adv_id, status);
svr_alipay_set_adv_start_state(false);
}
}
static void svr_alipay_ble_adv_stop_cb(uint8_t adv_id, adv_status_t status)
{
unused(status);
if (adv_id == ALIPAY_BLE_ADV_ID) {
ALIPAY_PRINT_DEBUG(0, "BleAdvStopCallback adv_id: %d, status:%d\n", adv_id, status);
svr_alipay_set_adv_start_state(false);
}
}
static void svr_alipay_bt_gatts_service_add_cb(uint8_t server_id, bt_uuid_t *uuid, uint16_t srv_handle,
errcode_t status)
{
unused(status);
if ((uuid->uuid_len == sizeof(uint16_t)) && (*((uint16_t *)uuid->uuid) == ALIPAYY_SERVICE_ID)) {
ALIPAY_PRINT_DEBUG(0, "BtGattsServiceAddCallback 0x%x 0x%x 0x%x 0x%x",
status, server_id, srv_handle, *((uint16_t *)uuid->uuid));
uint16_t id = ALIPAYY_CHARACTERISTIC_ID;
gatts_add_chara_info_t character;
uint16_t value = 0;
memset_s(&character, sizeof(gatts_add_chara_info_t), 0, sizeof(gatts_add_chara_info_t));
character.chara_uuid.uuid_len = sizeof(id);
memcpy_s(character.chara_uuid.uuid, sizeof(character.chara_uuid.uuid), (char *)&id, sizeof(id));
character.permissions = GATT_ATTRIBUTE_PERMISSION_READ | GATT_ATTRIBUTE_PERMISSION_WRITE;
character.properties =
GATT_CHARACTER_PROPERTY_BIT_READ | GATT_CHARACTER_PROPERTY_BIT_WRITE | GATT_CHARACTER_PROPERTY_BIT_NOTIFY;
character.value_len = ALIPAY_CHARACTERISTIC_MAX_LENGTH;
character.value = g_alipay_character_buf;
int ret = gatts_add_characteristic(server_id, srv_handle, &character);
if (ret != ERRCODE_SUCC) {
ALIPAY_PRINT_ERR(0, "gatts_add_characteristic fail, ret:%u.\r\n", ret);
}
g_alipay_svr_handle = srv_handle;
}
}
/* 将uint16的uuid数字转化为bt_uuid_t */
static void bts_data_to_uuid_len2(uint16_t uuid_data, bt_uuid_t *out_uuid)
{
out_uuid->uuid_len = UUID16_LEN;
out_uuid->uuid[0] = (uint8_t)(uuid_data >> 8); /* 8: octet bit num */
out_uuid->uuid[1] = (uint8_t)(uuid_data);
}
static void svr_alipay_bt_gatts_characteristic_add_cb(uint8_t server_id, bt_uuid_t *uuid, uint16_t srv_handle,
gatts_add_character_result_t *result, errcode_t status)
{
unused(status);
if ((uuid->uuid_len == sizeof(uint16_t)) && (*((uint16_t *)uuid->uuid) == ALIPAYY_CHARACTERISTIC_ID)) {
ALIPAY_PRINT_DEBUG(0, "BtGattsCharacteristicAddCallback 0x%x 0x%x 0x%x 0x%x 0x%x",
status, server_id, srv_handle, result->handle, result->value_handle);
uint8_t bas_ccc_val[] = {
0x01,
0x00
};
bt_uuid_t ccc_uuid = { 0 };
bts_data_to_uuid_len2(0x2902, &ccc_uuid);
gatts_add_desc_info_t descriptor;
descriptor.desc_uuid = ccc_uuid;
descriptor.permissions = GATT_ATTRIBUTE_PERMISSION_READ | GATT_ATTRIBUTE_PERMISSION_WRITE;
descriptor.value_len = (uint16_t)sizeof(bas_ccc_val);
descriptor.value = bas_ccc_val;
int ret = 0;
ret = gatts_add_descriptor(server_id, srv_handle, &descriptor);
if (ret != ERRCODE_SUCC) {
ALIPAY_PRINT_ERR(0, "gatts_add_descriptor fail, ret:%u.\r\n", ret);
}
bd_addr_t addr_info;
gatts_add_desc_info_t descriptor_ap;
gap_ble_get_local_addr(&addr_info);
bts_data_to_uuid_len2(0x4b02, &ccc_uuid);
descriptor_ap.desc_uuid = ccc_uuid;
descriptor_ap.permissions = GATT_ATTRIBUTE_PERMISSION_READ | GATT_ATTRIBUTE_PERMISSION_WRITE;
descriptor_ap.value_len = BD_ADDR_LEN;
uint8_t ble_data_mac_switch[BD_ADDR_LEN] = {0};
int k = BD_ADDR_LEN;
for (int i = 0; i < BD_ADDR_LEN; i++) {
ble_data_mac_switch[--k] = addr_info.addr[i];
}
descriptor_ap.value = ble_data_mac_switch;
ret = gatts_add_descriptor(server_id, srv_handle, &descriptor_ap);
if (ret != ERRCODE_SUCC) {
ALIPAY_PRINT_ERR(0, "gatts_add_descriptor second fail, ret:%u.\r\n", ret);
}
ret = gatts_start_service(server_id, srv_handle);
if (ret != ERRCODE_SUCC) {
ALIPAY_PRINT_ERR(0, "gatts_start_service fail, ret:%u.\r\n", ret);
}
g_alipay_characteristic_handle = result->value_handle;
}
}
static void svr_alipay_bt_gatts_descriptor_add_cb(uint8_t server_id, bt_uuid_t *uuid, uint16_t srv_handle,
uint16_t desc_handle, errcode_t status)
{
unused(server_id);
unused(uuid);
unused(status);
if (g_alipay_svr_handle == srv_handle) {
ALIPAY_PRINT_DEBUG(0, "BtGattsDescriptorAddCallback 0x%x 0x%x 0x%x 0x%x", status, server_id, srv_handle,
desc_handle);
static uint8_t desc_handle_count = 0;
desc_handle_count = desc_handle_count % ALIPAY_DESC_HANDLE_NUM;
g_alipay_descriptor_handle[desc_handle_count] = desc_handle;
desc_handle_count++;
}
}
static void svr_alipay_bt_gatts_service_start_cb(uint8_t server_id, uint16_t srv_handle, errcode_t status)
{
unused(server_id);
unused(status);
if (g_alipay_svr_handle == srv_handle) {
ALIPAY_PRINT_DEBUG(0, "BtGattsServiceStartCallback 0x%x 0x%x 0x%x", status, server_id, srv_handle);
}
}
static void svr_alipay_bt_gatts_service_stop_cb(uint8_t server_id, uint16_t srv_handle, errcode_t status)
{
unused(server_id);
unused(srv_handle);
unused(status);
ALIPAY_PRINT_DEBUG(0, "BtGattsServiceStopCallback 0x%x 0x%x 0x%x", status, server_id, srv_handle);
}
static void svr_alipay_bt_gatts_service_del_cb(uint8_t server_id, errcode_t status)
{
unused(server_id);
unused(status);
ALIPAY_PRINT_DEBUG(0, "BtGattsServiceDeleteCallback 0x%x 0x%x", status, server_id);
}
static void svr_alipay_bt_gatts_req_read_cb(uint8_t server_id, uint16_t conn_id, gatts_req_read_cb_t *read_cb_para,
errcode_t status)
{
unused(server_id);
unused(conn_id);
unused(read_cb_para);
unused(status);
ALIPAY_PRINT_DEBUG(0, "BtGattsRequestReadCallback");
}
static void svr_alipay_bt_gatts_req_write_cb(uint8_t server_id, uint16_t conn_id, gatts_req_write_cb_t *write_cb_para,
errcode_t status)
{
unused(server_id);
unused(conn_id);
unused(status);
if ((g_alipay_characteristic_handle == write_cb_para->handle) ||
(g_alipay_descriptor_handle[0] == write_cb_para->handle) ||
(g_alipay_descriptor_handle[1] == write_cb_para->handle)) {
ALIPAY_PRINT_DEBUG(0, "write callback,handle:%u str:%s len:%u",
write_cb_para->handle, write_cb_para->value, write_cb_para->length);
uint8_t *msg_data = write_cb_para->value;
errcode_t ret = svr_alipay_msg_write(ALIPAY_MSG_BT, msg_data, write_cb_para->length, false);
if (ret != ERRCODE_SUCC) {
ALIPAY_PRINT_ERR(0, "svr_alipay_msg_write fail, ret:%u.\r\n", ret);
}
}
return;
}
void svr_alipay_bt_gatts_noyify(uint8_t *data, uint16_t data_len)
{
gatts_ntf_ind_t data_info;
data_info.attr_handle = g_alipay_characteristic_handle;
data_info.value = data;
data_info.value_len = data_len;
errcode_t ret = gatts_notify_indicate(g_alipay_server_id, g_alipay_conn_id, &data_info);
ALIPAY_PRINT_DEBUG(0, "gatts_notify_indicate ret:0x%x. serverid:%u,conn_id:%u,handle:%u.", ret, g_alipay_server_id,
g_alipay_conn_id, g_alipay_characteristic_handle);
}
static void svr_alipay_btcallback_reg(void)
{
g_alipay_gapble_cbs.conn_state_change_cb = svr_alipay_ble_connstate_change_cb;
g_alipay_gapble_cbs.start_adv_cb = svr_alipay_ble_adv_start_cb;
g_alipay_gapble_cbs.stop_adv_cb = svr_alipay_ble_adv_stop_cb;
g_alipay_gapble_cbs.set_adv_data_cb = svr_alipay_ble_set_adv_data_cb;
g_alipay_gapble_cbs.terminate_adv_cb = svr_alipay_ble_terminate_adv_cb;
#ifndef SUPPORT_OHOSFWK
gap_ble_register_callbacks(&g_alipay_gapble_cbs);
#else
wrapper_gap_ble_register_callbacks(&g_alipay_gapble_cbs);
#endif
g_alipay_gatts_cbs.add_service_cb = svr_alipay_bt_gatts_service_add_cb;
g_alipay_gatts_cbs.add_characteristic_cb = svr_alipay_bt_gatts_characteristic_add_cb;
g_alipay_gatts_cbs.add_descriptor_cb = svr_alipay_bt_gatts_descriptor_add_cb;
g_alipay_gatts_cbs.start_service_cb = svr_alipay_bt_gatts_service_start_cb;
g_alipay_gatts_cbs.stop_service_cb = svr_alipay_bt_gatts_service_stop_cb;
g_alipay_gatts_cbs.delete_service_cb = svr_alipay_bt_gatts_service_del_cb;
g_alipay_gatts_cbs.read_request_cb = svr_alipay_bt_gatts_req_read_cb;
g_alipay_gatts_cbs.write_request_cb = svr_alipay_bt_gatts_req_write_cb;
g_alipay_gatts_cbs.mtu_changed_cb = NULL;
#ifndef SUPPORT_OHOSFWK
gatts_register_callbacks(&g_alipay_gatts_cbs);
#else
wrapper_gatts_register_callbacks(&g_alipay_gatts_cbs);
#endif
}
static void svr_alipay_bt_init_gatts(void)
{
uint16_t service_id = ALIPAYY_SERVICE_ID;
uint8_t server_id = 0;
bt_uuid_t uuid;
int ret;
uuid.uuid_len = sizeof(service_id);
memcpy_s(uuid.uuid, sizeof(uuid.uuid), (char *)&service_id, sizeof(service_id));
#ifndef SUPPORT_OHOSFWK
ret = gatts_register_server(&uuid, &server_id); /* 注册gatt server */
#else
ret = wrapper_gatts_register_server(&uuid, &server_id); /* 注册gatt server */
#endif
if (ret != ERRCODE_SUCC) {
ALIPAY_PRINT_ERR(0, "gatts_register_server ret:%u.\r\n", ret);
}
ALIPAY_PRINT_DEBUG(0, "gatts_register_server ret: 0x%x server_id = 0x%x", ret, server_id);
g_alipay_server_id = server_id;
uuid.uuid_len = sizeof(service_id);
memcpy_s(uuid.uuid, sizeof(uuid.uuid), (char *)&service_id, sizeof(service_id));
#ifndef SUPPORT_OHOSFWK
ret = gatts_add_service(server_id, &uuid, true);
#else
ret = wrapper_gatts_add_service(server_id, &uuid, true);
#endif
if (ret != ERRCODE_SUCC) {
ALIPAY_PRINT_ERR(0, "gatts_add_service ret:%u.\r\n", ret);
}
return;
}
void svr_alipay_bluetooth_init(void)
{
#ifndef SUPPORT_OHOSFWK
bool ret = enable_bt_stack();
if (ret != ERRCODE_SUCC) {
ALIPAY_PRINT_ERR(0, "enable_bt_stack ret:%u.\r\n", ret);
}
#endif
if (g_alipay_ble_init_flag == true) {
return;
}
svr_alipay_btcallback_reg();
svr_alipay_bt_init_gatts();
g_alipay_ble_init_flag = true;
return;
}