From 035f43329983e17b18e2ccadc7fbddf0551d7ed8 Mon Sep 17 00:00:00 2001 From: luozheng <1732036298@qq.com> Date: Fri, 16 May 2025 10:52:36 +0800 Subject: [PATCH] =?utf8?q?alipay=20=E6=96=87=E4=BB=B6=E5=A4=B9=E5=90=88?= =?utf8?q?=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../alipay/driver_adapt/CMakeLists.txt | 1 + .../wearable/alipay/driver_adapt/soc_adapt.c | 32 ++++ .../wearable/alipay/driver_adapt/vendor_net.c | 82 ++++++++ .../alipay/driver_adapt/vendor_product.c | 8 + .../wearable/alipay/service/CMakeLists.txt | 11 -- .../alipay/service/alipay_bluetooth.c | 175 +++++++++++------- .../alipay/service/alipay_bluetooth.h | 42 +++++ .../wearable/alipay/service/alipay_feature.c | 17 +- .../wearable/alipay/service/alipay_feature.h | 43 +++-- .../br/libbt_host_audio_manager_wrapper.a | Bin 219888 -> 219892 bytes 10 files changed, 310 insertions(+), 101 deletions(-) create mode 100644 code/sdk/application/wearable/alipay/service/alipay_bluetooth.h diff --git a/code/sdk/application/wearable/alipay/driver_adapt/CMakeLists.txt b/code/sdk/application/wearable/alipay/driver_adapt/CMakeLists.txt index d83743aac..a71517769 100644 --- a/code/sdk/application/wearable/alipay/driver_adapt/CMakeLists.txt +++ b/code/sdk/application/wearable/alipay/driver_adapt/CMakeLists.txt @@ -10,6 +10,7 @@ set(PRIVATE_HEADER ${ALIPAY_SDK_DIR}/lib/rv70_llvm/share/common/inc ${ALIPAY_SDK_DIR}/lib/rv70_llvm/hal/network/inc ${ROOT_DIR}/application/wearable/service/alipay_msg + ${ROOT_DIR}/open_source/openharmony/third_party/lwip/port/lwip-2.1/porting/include/lwip/ ) set(SOURCES diff --git a/code/sdk/application/wearable/alipay/driver_adapt/soc_adapt.c b/code/sdk/application/wearable/alipay/driver_adapt/soc_adapt.c index 3a221726d..2aa4dd3fe 100644 --- a/code/sdk/application/wearable/alipay/driver_adapt/soc_adapt.c +++ b/code/sdk/application/wearable/alipay/driver_adapt/soc_adapt.c @@ -14,6 +14,8 @@ #include "gpio.h" #include "cmsis_os2.h" +#define PRINT_I2C_LOG 0 + #define ALIPAY_SEC_I2C_MEMPOOL_SIZE 2048 #define ALIPAY_SEC_I2C_SLAVE_ADDR 100 @@ -52,6 +54,22 @@ int IIC_Master_Send(unsigned char byAddr, unsigned char *pData, unsigned short w if (ret != ERRCODE_SUCC) { MyPrintf("se i2c data write fail! ret=0x%x", ret); } + +#if PRINT_I2C_LOG + char printbuf[128*3]={0}; + uint8_t buflen = sizeof(printbuf)/3; + uint8_t printlen = wLen; + if(wLen > buflen) + { + printlen = buflen; + } + for( int ii=0;ii buflen) + { + printlen = buflen; + } + for( int ii=0;ii +#include +#endif + void alipay_iot_gettimeofday(alipay_iot_timeval *now) { now->tv_sec = time(NULL); @@ -55,6 +65,22 @@ int alipay_iot_dns(const char *name, unsigned char ip[4]) ret = msg_center_alipay_hostent_request((void*)name, strlen(name)); ret |= msg_center_alipay_hostent_reponse(ip); return ret; + #if IF_SUPPORT_LWIP + printf("alipay_iot_dns name:%s\n",name);// 发起 DNS 解析请求 + unsigned int ipaddr = get_hostip(name); + if (ipaddr == 0) { + printf("dns_gethostbyname request %s ipaddr fail\n", name); + return -1; + } + printf("%s %d ipaddr 0x%x\n",__func__,__LINE__,ipaddr); + // 将 ipaddr 按字节拆分并存储到 ip 数组中 + ip[0] = (ipaddr >> 24) & 0xFF; + ip[1] = (ipaddr >> 16) & 0xFF; + ip[2] = (ipaddr >> 8) & 0xFF; + ip[3] = ipaddr & 0xFF; + printf("alipay_iot_dns ip:%d.%d.%d.%d\n",ip[0],ip[1],ip[2],ip[3]); + return 0; + #endif } int alipay_iot_socket_create(int domain, alipay_socket_type_enum type, int protocol) @@ -67,6 +93,15 @@ int alipay_iot_socket_create(int domain, alipay_socket_type_enum type, int proto } int fd = DEFAULT_SOCKET_FD; return fd; + #if IF_SUPPORT_LWIP + // 创建套接字 + int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) { + printf("socket create fail\n"); + return; + } + return fd; + #endif } int alipay_iot_socket_connect(int s, const struct alipay_iot_sockaddr *name, @@ -87,6 +122,29 @@ int alipay_iot_socket_connect(int s, const struct alipay_iot_sockaddr *name, ret = msg_center_alipay_connect_request(&request, sizeof(alipay_connect_request)); ret |= msg_center_alipay_connect_reponse(); return ret; + #if IF_SUPPORT_LWIP + struct sockaddr_in server_addr; + int ret; + // 检查网络状态,这里可以根据 lwIP 的网络接口状态来判断 + // if (!netif_is_up(&g_mynetif)) { + // return -1; + // } + // 填充服务器地址结构体 + memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_port = name->data.sin_data.port; + memcpy(&server_addr.sin_addr.s_addr, name->data.sin_data.ip, 4); + // 发起连接请求 + ret = connect(s, (struct sockaddr *)&server_addr, sizeof(server_addr)); + if (ret < 0) { + // 连接失败,可以根据具体情况添加错误处理逻辑 + // 例如记录日志等 + printf("connect fail\n"); + close(s); + return -1; + } + return ret; + #endif } int alipay_iot_socket_write(int s, const void *dataptr, int len) @@ -99,6 +157,15 @@ int alipay_iot_socket_write(int s, const void *dataptr, int len) } ret = msg_center_alipay_tcpdata_request((void *)dataptr, len); return ret; + #if IF_SUPPORT_LWIP + ret = send(s, dataptr, len, 0);//调用 lwIP 的 send 函数发送数据 + if (ret < 0) { + // 发送失败,可以根据具体情况添加错误处理逻辑 + // 例如记录日志等 + return -1; + } + return ret; + #endif } int alipay_iot_fd_isset(int fd, alipay_iot_fd_set* fdset) @@ -161,6 +228,13 @@ int alipay_iot_socket_read(int s, void *mem, int len) } ret = msg_center_alipay_tcpdata_read(mem, len); return ret; + #if IF_SUPPORT_LWIP + ret = recv(s, mem, len, 0);// 调用 lwIP 的 recv 函数接收数据 + if (ret < 0) { + return -1; + } + return ret; + #endif } int alipay_iot_socket_close(int s) @@ -170,6 +244,14 @@ int alipay_iot_socket_close(int s) int ret; ret = msg_center_alipay_close_request(); return ret; + #if IF_SUPPORT_LWIP + ret = close(s); + if (ret < 0) { + // 关闭失败 + return -1; + } + return ret; + #endif } #else int alipay_iot_dns(const char *name, unsigned char ip[4]) diff --git a/code/sdk/application/wearable/alipay/driver_adapt/vendor_product.c b/code/sdk/application/wearable/alipay/driver_adapt/vendor_product.c index bd141fc98..835cd5de1 100644 --- a/code/sdk/application/wearable/alipay/driver_adapt/vendor_product.c +++ b/code/sdk/application/wearable/alipay/driver_adapt/vendor_product.c @@ -20,6 +20,8 @@ extern void Ble_SendDataSimple(uint16_t handle, uint8_t *data, uint16_t len); extern uint32_t Unix_time; +// #define ALIPAY_CSI_LOG_EXT_ON + #define ALIPAY_BLE_MAC_ADDR_NUM 6 #define ALIPAY_ADAPT_LOG_MAX_NUM 300 @@ -100,6 +102,7 @@ csi_error_t csi_get_sn(uint8_t *buf_sn, uint32_t *len_sn) return CSI_ERROR; } +#if 1 bd_addr_t addr_info; gap_ble_get_local_addr(&addr_info); char str[18] = {0}; @@ -111,6 +114,11 @@ csi_error_t csi_get_sn(uint8_t *buf_sn, uint32_t *len_sn) *len_sn = strlen(str); memcpy(buf_sn, str, strlen(str)); +#else + const char *mock_sn = ""; + *len_sn = strlen(mock_sn); + memcpy(buf_sn, mock_sn, strlen(mock_sn)); +#endif return CSI_OK; } diff --git a/code/sdk/application/wearable/alipay/service/CMakeLists.txt b/code/sdk/application/wearable/alipay/service/CMakeLists.txt index 4fc190762..f6a8a07d3 100644 --- a/code/sdk/application/wearable/alipay/service/CMakeLists.txt +++ b/code/sdk/application/wearable/alipay/service/CMakeLists.txt @@ -17,17 +17,6 @@ set(PRIVATE_HEADER ${ALIPAY_SDK_DIR}/lib/rv70_llvm/share/common/inc ${ALIPAY_SDK_DIR}/lib/rv70_llvm/hal/file/inc ) -if("FD230" IN_LIST DEFINES) -set(PRIVATE_HEADER - ${PRIVATE_HEADER} - ${ROOT_DIR}/application/wearable/fd230/nativeapp/nativeui/bluetooth/include -) -else() -set(PRIVATE_HEADER - ${PRIVATE_HEADER} - ${ROOT_DIR}/application/wearable/nativeapp/nativeui/bluetooth/include -) -endif() set(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/alipay_feature.c diff --git a/code/sdk/application/wearable/alipay/service/alipay_bluetooth.c b/code/sdk/application/wearable/alipay/service/alipay_bluetooth.c index 1d9d5c050..0bb7eb569 100644 --- a/code/sdk/application/wearable/alipay/service/alipay_bluetooth.c +++ b/code/sdk/application/wearable/alipay/service/alipay_bluetooth.c @@ -55,6 +55,8 @@ 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}; +#define ALIPAY_PRINT_LOG 0 + static bool svr_alipay_get_adv_start_state(void) { return g_alipay_adv_start_state; @@ -205,47 +207,46 @@ static void svr_alipay_ble_adv_stop_cb(uint8_t adv_id, adv_status_t status) } } +//在服务添加成功后添加特征 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)) { + // 检查UUID是否匹配支付宝服务ID + 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 id = ALIPAYY_CHARACTERISTIC_ID;// 支付宝特征值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); + character.chara_uuid.uuid_len = sizeof(id); // 设置特征值UUID长度 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; + 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; + 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)) { + 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[] = { @@ -253,38 +254,43 @@ static void svr_alipay_bt_gatts_characteristic_add_cb(uint8_t server_id, bt_uuid 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); + bts_data_to_uuid_len2(0x2902, &ccc_uuid); // 将0x2902转换为UUID格式 + gatts_add_desc_info_t descriptor; + descriptor.desc_uuid = ccc_uuid; //设置描述符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; + bts_data_to_uuid_len2(0x4b02, &ccc_uuid); // 将0x4b02转换为UUID格式 + descriptor_ap.desc_uuid = ccc_uuid; // 设置描述符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]; + ble_data_mac_switch[--k] = addr_info.addr[i]; // 反转蓝牙地址字节顺序 } - descriptor_ap.value = ble_data_mac_switch; + + // 添加第二个描述符到特征值 + 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; } } @@ -292,9 +298,6 @@ static void svr_alipay_bt_gatts_characteristic_add_cb(uint8_t server_id, bt_uuid 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); @@ -307,8 +310,6 @@ static void svr_alipay_bt_gatts_descriptor_add_cb(uint8_t server_id, bt_uuid_t * 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); } @@ -316,41 +317,42 @@ static void svr_alipay_bt_gatts_service_start_cb(uint8_t server_id, uint16_t srv 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"); } +bool is_alipay_handle(uint16_t hande) +{ + if ((g_alipay_characteristic_handle == hande) || + (g_alipay_descriptor_handle[0] == hande) || + (g_alipay_descriptor_handle[1] == hande)) + { + return true; + } + return false; +} +// 接收手机数据 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; + 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); @@ -359,6 +361,7 @@ static void svr_alipay_bt_gatts_req_write_cb(uint8_t server_id, uint16_t conn_id return; } +//发送数据到手机 void svr_alipay_bt_gatts_noyify(uint8_t *data, uint16_t data_len) { gatts_ntf_ind_t data_info; @@ -366,6 +369,16 @@ void svr_alipay_bt_gatts_noyify(uint8_t *data, uint16_t data_len) data_info.value = data; data_info.value_len = data_len; + #if ALIPAY_PRINT_LOG + // 打印 data 数据 + printf("发送数据到手机: "); + for (uint16_t i = 0; i < data_len; i++) { + printf("%02x ", data[i]); + } + printf("数据长度:%d",data_len); + printf("\n"); + #endif + 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); @@ -400,51 +413,81 @@ static void svr_alipay_btcallback_reg(void) #endif } -static void svr_alipay_bt_init_gatts(void) +void ble_add_alipay_service(uint8_t server_id) +{ + printf("ble_add_alipay_service\r\n"); + bt_uuid_t alipay_service_uuid = {0}; + bts_data_to_uuid_len2(ALIPAYY_SERVICE_ID, &alipay_service_uuid); + //只有一个服务,永远是1 + errcode_t ret = 0; +#ifndef SUPPORT_OHOSFWK + ret = gatts_add_service(server_id, &alipay_service_uuid, true); + printf(" NO SUPPORT_OHOSFWK\r\n"); + #else + ret = wrapper_gatts_add_service(server_id, &alipay_service_uuid, true); + printf("ble_add_alipay_service wrapper_gatts_add_service ret: 0x%x serverId = 0x%x uuid.uuid_len:%d\n", ret, server_id,alipay_service_uuid.uuid_len); +#endif + g_alipay_server_id=server_id; +} + + +void svr_alipay_bt_init_gatts(uint8_t server_id ) { uint16_t service_id = ALIPAYY_SERVICE_ID; - uint8_t server_id = 0; + //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); - } +// #ifndef SUPPORT_OHOSFWK +// ret = gatts_register_server(&uuid, &server_id); /* 注册gatt server */ +// if (ret != ERRCODE_SUCC) { +// ALIPAY_PRINT_ERR(0, "gatts_register_server ret:0x%x.\r\n", ret); +// } +// #else +// ret = wrapper_gatts_register_server(&uuid, &server_id); /* 注册gatt server */ +// if (ret != ERRCODE_SUCC) { +// ALIPAY_PRINT_ERR(0, "wrapper_gatts_register_server ret:0x%x.\r\n", ret); +// } +// #endif + 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); + if (ret != ERRCODE_SUCC) { + ALIPAY_PRINT_ERR(0, "gatts_add_service ret:0x%x.\r\n", ret); + } #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); + ALIPAY_PRINT_ERR(0, "wrapper_gatts_add_service ret:0x%x.\r\n", ret); } +#endif + return; } -void svr_alipay_bluetooth_init(void) +//2.Alipay蓝牙模块初始化 +void svr_alipay_bluetooth_init(uint8_t server_id) { -#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 +// #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; } + printf("svr_alipay_bluetooth_init \r\n"); svr_alipay_btcallback_reg(); - svr_alipay_bt_init_gatts(); + svr_alipay_bt_init_gatts(server_id); + g_alipay_ble_init_flag = true; return; } diff --git a/code/sdk/application/wearable/alipay/service/alipay_bluetooth.h b/code/sdk/application/wearable/alipay/service/alipay_bluetooth.h new file mode 100644 index 000000000..c4cdd583c --- /dev/null +++ b/code/sdk/application/wearable/alipay/service/alipay_bluetooth.h @@ -0,0 +1,42 @@ +#ifndef _ALPAY_BLUETOOTH_H +#define _ALPAY_BLUETOOTH_H +#include +#include +#include "stdbool.h" +#include "bts_def.h" + +/* 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 15 // 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_BLE_MAC_MAX_LEN 6 +void svr_alipay_bluetooth_init(uint8_t); +void ble_alipay_add_characters_input_report_cbk(uint16_t srvc_handle); +void svr_alipay_bt_gatts_characteristic_add_dec(uint8_t server_id,uint16_t srv_handle); +void svr_alipay_set_adv_start_state(bool state); +bool svr_alipay_get_adv_start_state(void); +void svr_alipay_bt_init_gatts(uint8_t); +void svr_alipay_ble_adv_start_t(void); +void ble_add_alipay_service(uint8_t server_id); + +uint16_t get_g_alipay_conn_id(void); + +bool is_alipay_handle(uint16_t hande); + +#endif + diff --git a/code/sdk/application/wearable/alipay/service/alipay_feature.c b/code/sdk/application/wearable/alipay/service/alipay_feature.c index e02955308..8bf65855d 100644 --- a/code/sdk/application/wearable/alipay/service/alipay_feature.c +++ b/code/sdk/application/wearable/alipay/service/alipay_feature.c @@ -24,6 +24,8 @@ #include "osal_msgqueue.h" #include "thread_init.h" #include "alipay_transit.h" +#include "bleService.h" +#include "alipay_bluetooth.h" #include "vendor_file.h" #if defined(__FREERTOS__) #include "FreeRTOS.h" @@ -73,9 +75,9 @@ static mc_payment_state_t svr_alipay_get_paystate(void) static int32_t svr_alipay_notify_bt(bool value) { if (value) { - svr_alipay_ble_adv_start(); + // svr_alipay_ble_adv_start(); //统一采用 bleService的adv } else { - svr_alipay_ble_adv_stop(); + // svr_alipay_ble_adv_stop(); //统一采用 bleService的adv } return 0; } @@ -501,7 +503,7 @@ static int32_t svr_alipay_msg_proc(uint32_t msg_id, uint8_t *data, uint16_t size return ERRCODE_SUCC; } -static void svr_alipay_msg_thread(void *data) +static errcode_t svr_alipay_msg_thread(void *data) { uint8_t msg_data[ALIPAY_MAX_SIZE + ALIPAY_ID_LEN + ALIPAY_MSG_LEN]; uint32_t msg_data_size = sizeof(msg_data); @@ -522,7 +524,7 @@ static void svr_alipay_msg_thread(void *data) svr_alipay_msg_proc(msg_id, &msg_data[ALIPAY_ID_LEN + ALIPAY_MSG_LEN], msg_len); } ALIPAY_PRINT_ERR(0, "svr_alipay_msg_thread exit"); - return; + return ERRCODE_SUCC; } static errcode_t svr_alipay_task_init(void) @@ -604,7 +606,7 @@ errcode_t uapi_alipay_svr_init(void) uapi_gpio_set_dir(ALIPAY_SEC_GPIO, GPIO_DIRECTION_OUTPUT); uapi_gpio_set_val(ALIPAY_SEC_GPIO, GPIO_LEVEL_HIGH); osDelay(30); - svr_alipay_bluetooth_init(); + // svr_alipay_bluetooth_init(); HS_IIC_Init(); alipay_pre_init(); svr_alipay_enter_lpm(); @@ -613,6 +615,11 @@ errcode_t uapi_alipay_svr_init(void) return ERRCODE_SUCC; } +bool Alipay_is_init(void) +{ + return g_alipay_init_flag; +} + errcode_t uapi_alipay_svr_reset(void) { if (g_alipay_init_flag) { diff --git a/code/sdk/application/wearable/alipay/service/alipay_feature.h b/code/sdk/application/wearable/alipay/service/alipay_feature.h index fe7eec9de..27b1ecfe1 100644 --- a/code/sdk/application/wearable/alipay/service/alipay_feature.h +++ b/code/sdk/application/wearable/alipay/service/alipay_feature.h @@ -30,13 +30,16 @@ extern "C" { #define APP_FAILURE (-1) #if !defined(SW_UART_DEBUG) && !defined(SW_RTT_DEBUG) +#ifdef WEARABLE_LOG_DEBUG +#define ALIPAY_PRINT_DEBUG(log_num, fmt, arg...) uapi_diag_debug_log(0, fmt, ##arg) #define ALIPAY_PRINT_ERR(log_num, fmt, arg...) uapi_diag_error_log(0, fmt, ##arg) #define ALIPAY_PRINT_WARN(log_num, fmt, arg...) uapi_diag_warning_log(0, fmt, ##arg) #define ALIPAY_PRINT_INFO(log_num, fmt, arg...) uapi_diag_info_log(0, fmt, ##arg) -#ifdef WEARABLE_LOG_DEBUG -#define ALIPAY_PRINT_DEBUG(log_num, fmt, arg...) uapi_diag_debug_log(0, fmt, ##arg) #else #define ALIPAY_PRINT_DEBUG(log_num, fmt, arg...) +#define ALIPAY_PRINT_ERR(log_num, fmt, arg...) +#define ALIPAY_PRINT_WARN(log_num, fmt, arg...) +#define ALIPAY_PRINT_INFO(log_num, fmt, arg...) #endif #else #define ALIPAY_PRINT_ERR(log_num, fmt, arg...) PRINT("[ALIPAY SVR E/] %s: " fmt "\r\n", __FUNCTION__, ##arg) @@ -97,27 +100,27 @@ typedef struct { typedef enum { ALIPAY_TRANS_SUCCESS = 0, ALIPAY_TRANS_CARD_LIST_START = ALIPAY_TRANS_CARD_SHIFT << 8, - ALIPAY_TRANS_CARD_LIST_UNBIND = ALIPAY_TRANS_CARD_LIST_START, // 设备已经在服务端解绑,设备端也需要调用解绑接口 - ALIPAY_TRANS_CARD_LIST_NET_ERROR, // 网络错误 - ALIPAY_TRANS_CARD_LIST_OWN_TOO_MANY_CARD, // 用户开通了太多乘车码 - ALIPAY_TRANS_CARD_LIST_FUNC_NOT_SUPPPORT, // 不支持该功能 - ALIPAY_TRANS_CARD_LIST_DEV_ERROR, // 不该出现的错误 - ALIPAY_TRANS_CARD_LIST_BUF_TOO_SHORT, // 入参的缓存太小 + ALIPAY_TRANS_CARD_LIST_UNBIND = ALIPAY_TRANS_CARD_LIST_START, // 设备已经在服务端解绑,设备端也需要调用解绑接口 + ALIPAY_TRANS_CARD_LIST_NET_ERROR, // 网络错误 + ALIPAY_TRANS_CARD_LIST_OWN_TOO_MANY_CARD, // 用户开通了太多乘车码 + ALIPAY_TRANS_CARD_LIST_FUNC_NOT_SUPPPORT, // 不支持该功能 + ALIPAY_TRANS_CARD_LIST_DEV_ERROR, // 不该出现的错误 + ALIPAY_TRANS_CARD_LIST_BUF_TOO_SHORT, // 入参的缓存太小 ALIPAY_TRANS_CODE_START = ALIPAY_TRANS_CODE_SHIFT << 8, - ALIPAY_TRANS_CODE_UNBIND = ALIPAY_TRANS_CODE_START, // 设备已经在服务端解绑,设备端也需要调用解绑接口 - ALIPAY_TRANS_CODE_NET_ERROR, // 网络错误 - ALIPAY_TRANS_CODE_DATA_LIMIT, // 因安全原因限制生码 - ALIPAY_TRANS_CODE_NOT_SUPPORT, // 该乘车码不支持 - ALIPAY_TRANS_CODE_SERVER_ERROR, // 服务端报错 - ALIPAY_TRANS_CODE_DEV_ERROR, // 不该出现的错误 + ALIPAY_TRANS_CODE_UNBIND = ALIPAY_TRANS_CODE_START, // 设备已经在服务端解绑,设备端也需要调用解绑接口 + ALIPAY_TRANS_CODE_NET_ERROR, // 网络错误 + ALIPAY_TRANS_CODE_DATA_LIMIT, // 因安全原因限制生码 + ALIPAY_TRANS_CODE_NOT_SUPPORT, // 该乘车码不支持 + ALIPAY_TRANS_CODE_SERVER_ERROR, // 服务端报错 + ALIPAY_TRANS_CODE_DEV_ERROR, // 不该出现的错误 } mc_alipay_trans_errcode_t; typedef enum { ALIPAY_MSG_BT = 0, - ALIPAY_MSG_UPDATA_TRANS_LIST, - ALIPAY_MSG_UPDATA_SPECIAL_CARD, - ALIPAY_MSG_UPDATA_ALL_CARDS, + ALIPAY_MSG_UPDATA_TRANS_LIST, // 设备端更新乘车码列表 + ALIPAY_MSG_UPDATA_SPECIAL_CARD, // 设备端更新特殊卡列表 + ALIPAY_MSG_UPDATA_ALL_CARDS, // 设备端更新所有卡列表 } mc_alipay_msg_type_t; @@ -362,8 +365,7 @@ void svr_alipay_bt_gatts_noyify(uint8_t *data, uint16_t data_len); * @brief alipay BLE module initialization. * @return NULL. */ -void svr_alipay_bluetooth_init(void); - +void svr_alipay_bluetooth_init(uint8_t); /* * @brief alipay BLE adv start. * @return NULL. @@ -413,6 +415,9 @@ mc_alipay_trans_context_t * svr_alipay_get_trans_context(void); */ uint32_t svr_alipay_register_cb(alipay_msgf_event_callback_func callback); + +bool Alipay_is_init(void); + #ifdef __cplusplus #if __cplusplus } diff --git a/code/sdk/interim_binary/brandy/libs/bt/evb_standard/liteos/br/libbt_host_audio_manager_wrapper.a b/code/sdk/interim_binary/brandy/libs/bt/evb_standard/liteos/br/libbt_host_audio_manager_wrapper.a index 8a914dc23bf50be958d61f422fde8aa151edb629..6775998dfbda0e24a1402ecbf12dc6bbfc488451 100644 GIT binary patch delta 15060 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 -- 2.17.1