diff --git a/apps/common/third_party_profile/jieli/wireless_mic/le_wireless_mic_client.c b/apps/common/third_party_profile/jieli/wireless_mic/le_wireless_mic_client.c index 9ba8ac0..49d8b00 100644 --- a/apps/common/third_party_profile/jieli/wireless_mic/le_wireless_mic_client.c +++ b/apps/common/third_party_profile/jieli/wireless_mic/le_wireless_mic_client.c @@ -1,3 +1,5 @@ + + // ***************************************************************************** /* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT * diff --git a/apps/earphone/log_config/lib_btstack_config.c b/apps/earphone/log_config/lib_btstack_config.c index 6b35c31..29874cd 100644 --- a/apps/earphone/log_config/lib_btstack_config.c +++ b/apps/earphone/log_config/lib_btstack_config.c @@ -55,7 +55,7 @@ const int config_rcsp_stack_enable = 0; const int config_le_hci_connection_num = 1;//支持同时连接个数 const int config_le_sm_support_enable = 0; //是否支持加密配对 const int config_le_gatt_client_num = 1; //支持client角色个数 -const int config_le_gatt_server_num = 1; //支持server角色个数 +const int config_le_gatt_server_num = 0; //支持server角色个数 #elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_WIRELESS_MIC_SERVER) const int config_le_hci_connection_num = 1;//支持同时连接个数 diff --git a/apps/earphone/xtell_remote_control/ble_handler/client_handler copy.c b/apps/earphone/xtell_remote_control/ble_handler/client_handler copy.c new file mode 100644 index 0000000..0e8aa92 --- /dev/null +++ b/apps/earphone/xtell_remote_control/ble_handler/client_handler copy.c @@ -0,0 +1,1592 @@ +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" + +#include "le_client_demo.h" +#include "le_common.h" +#include "ble_user.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_WIRELESS_MIC_CLIENT) + +#define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 0 +#define SHOW_RX_DATA_RATE 1 +#define SHOW_TX_DATA_RATE 1 + +#if LE_DEBUG_PRINT_EN +/* #define log_info printf */ +#define log_info(x, ...) printf("[LE_CLIENT]" x " ", ## __VA_ARGS__) +#define log_info_hexdump put_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + + +//------ +#define ATT_LOCAL_MTU_SIZE (517) //note: need >= 20 +#define ATT_SEND_CBUF_SIZE (200)//(256)//(512*10) //note: need >= 20,缓存大小,可修改 +#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_MTU_SIZE + ATT_SEND_CBUF_SIZE) //note: +static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); + +#define SEARCH_PROFILE_BUFSIZE (512) //note: +static u8 search_ram_buffer[SEARCH_PROFILE_BUFSIZE] __attribute__((aligned(4))); +#define scan_buffer search_ram_buffer +//--------------- +//搜索类型 +#define SET_SCAN_TYPE SCAN_ACTIVE +//搜索 周期大小, 参数一:320 参数二:320 参数三:168 +#define SET_SCAN_INTERVAL 320//48//256//48 //(unit:0.625ms), 96没有干扰的情况下, 连接速度为60ms, 如需要降低功耗, 可以在+16的倍数 +//搜索 窗口大小 参数一:102 参数二:70 参数三:30 +#define SET_SCAN_WINDOW 70//48//24//48 //(unit:0.625ms) + +//连接周期 +#define SET_CONN_INTERVAL 3 //(unit:1.25ms) +//连接latency +#define SET_CONN_LATENCY 0 //(unit:conn_interval) +//连接超时 +#define SET_CONN_TIMEOUT 400 //(unit:10ms) +#if WIRELESS_TOOL_BLE_NAME_EN +#define TEST_BOX_BLE_NAME "W_MIC_01" +#define TEST_BOX_BLE_NAME_LEN (sizeof(TEST_BOX_BLE_NAME)-1) +static u8 *match_name; +#endif +//---------------------------------------------------------------------------- +static u8 scan_ctrl_en; +static u8 ble_work_state = 0; +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; + +static hci_con_handle_t con_handle; + +#define BLE_VM_HEAD_TAG (0xB95C) +#define BLE_VM_TAIL_TAG (0x5CB9) +struct pair_info_t { + u16 head_tag; + u8 pair_flag; + u8 peer_address_info[7]; + u16 tail_tag; +}; +static struct pair_info_t conn_pair_info; +static u8 pair_bond_enable = 0; + +//------------------------------------------------------------------------------- +typedef struct { + uint16_t read_handle; + uint16_t read_long_handle; + uint16_t write_handle; + uint16_t write_no_respond; + uint16_t notify_handle; + uint16_t indicate_handle; +} target_hdl_t; + +//记录handle 使用 +static target_hdl_t target_handle; +static opt_handle_t opt_handle_table[OPT_HANDLE_MAX]; +static u8 opt_handle_used_cnt; +static u8 force_seach_onoff = 0; +static s8 force_seach_rssi = -127; +static u8 cur_peer_address_info[7]; +static u8 flag_specific_adv_name = 0; +static u8 flag_need_judge_rssi = 0; +static u8 flag_specific_sacn = 0; + +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type); +static int bt_ble_scan_enable(void *priv, u32 en); +static int client_write_send(void *priv, u8 *data, u16 len); +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type); +#if WIRELESS_TOOL_BLE_NAME_EN +static ble_state_e get_ble_work_state(void); +#else +static void set_ble_work_state(ble_state_e state); +#endif +static void client_create_connection_cannel(void); +//--------------------------------------------------------------------------- +#if 1//default +//指定搜索uuid +//指定搜索uuid +static const target_uuid_t default_search_uuid_table[] = { + + // for uuid16 + // PRIMARY_SERVICE, ae30 + // CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, + // CHARACTERISTIC, ae02, NOTIFY, + + { + .services_uuid16 = 0xae30, + .characteristic_uuid16 = 0xae01, + .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, + }, + + { + .services_uuid16 = 0xae30, + .characteristic_uuid16 = 0xae02, + .opt_type = ATT_PROPERTY_NOTIFY, + }, + + //for uuid128,sample + // PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 + // CHARACTERISTIC, 0000F531-1212-EFDE-1523-785FEABCD123, NOTIFY, + // CHARACTERISTIC, 0000F532-1212-EFDE-1523-785FEABCD123, WRITE_WITHOUT_RESPONSE | DYNAMIC, + /* + { + .services_uuid16 = 0, + .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , + .characteristic_uuid16 = 0, + .characteristic_uuid128 = {0x00,0x00,0xF5,0x31 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, + .opt_type = ATT_PROPERTY_NOTIFY, + }, + + { + .services_uuid16 = 0, + .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , + .characteristic_uuid16 = 0, + .characteristic_uuid128 = {0x00,0x00,0xF5,0x32 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, + .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, + }, + */ + +}; + + +static void default_report_data_deal(att_data_report_t *report_data, target_uuid_t *search_uuid) +{ + log_info("report_data:%02x,%02x,%d,len(%d)", report_data->packet_type, + report_data->value_handle, report_data->value_offset, report_data->blob_length); + + log_info_hexdump(report_data->blob, report_data->blob_length); + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION: //notify + break; + case GATT_EVENT_INDICATION://indicate + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + break; + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long + break; + + default: + break; + } +} +static const u8 test_remoter_name1[] = "CM-22222"; +// static const u8 test_remoter_name1[] = "AC637N_MX(BLE)";// +/* static const u8 test_remoter_name2[] = "AC630N_HID567(BLE)";// */ +static u16 default_client_write_handle; +static u16 test_client_timer = 0; + +static const client_match_cfg_t match_dev01 = { + .create_conn_mode = BIT(CLI_CREAT_BY_NAME), + .compare_data_len = sizeof(test_remoter_name1) - 1, //去结束符 + .compare_data = test_remoter_name1, + .bonding_flag = 0, +}; + +/* static const client_match_cfg_t match_dev02 = { */ +/* .create_conn_mode = BIT(CLI_CREAT_BY_NAME), */ +/* .compare_data_len = sizeof(test_remoter_name2) - 1, //去结束符 */ +/* .compare_data = test_remoter_name2, */ +/* .bonding_flag = 1, */ +/* }; */ + +static void default_test_write(void) +{ + static u32 count = 0; + count++; + int ret = client_operation_send(default_client_write_handle, &count, 16, ATT_OP_WRITE_WITHOUT_RESPOND); + log_info("test_write:%x", ret); +} + +static void default_event_callback(le_client_event_e event, u8 *packet, int size) +{ + switch (event) { + case CLI_EVENT_MATCH_DEV: { + client_match_cfg_t *match_dev = packet; + log_info("match_name:%s\n", match_dev->compare_data); + } + break; + + case CLI_EVENT_MATCH_UUID: { + opt_handle_t *opt_hdl = packet; + if (opt_hdl->search_uuid == &default_search_uuid_table[0]) { + default_client_write_handle = opt_hdl->value_handle; + log_info("match_uuid22\n"); + } + } + break; + + case CLI_EVENT_SEARCH_PROFILE_COMPLETE: + log_info("CLI_EVENT_SEARCH_PROFILE_COMPLETE\n"); + if ((!test_client_timer) && default_client_write_handle) { + log_info("test timer_add\n"); + test_client_timer = sys_hi_timer_add(0, default_test_write, 500); + extern void test_func_main(void); + test_func_main(); + } + break; + + case CLI_EVENT_CONNECTED: + break; + + case CLI_EVENT_DISCONNECT: + if (test_client_timer) { + sys_timeout_del(test_client_timer); + test_client_timer = 0; + } + default_client_write_handle = 0; + break; + + default: + break; + } +} + + +static const client_conn_cfg_t client_conn_config_default = { + .match_dev_cfg[0] = &match_dev01, + .match_dev_cfg[1] = NULL, + .match_dev_cfg[2] = NULL, + /* .match_dev_cfg[1] = &match_dev02, */ + .report_data_callback = default_report_data_deal, + .search_uuid_cnt = (sizeof(default_search_uuid_table) / sizeof(target_uuid_t)), + .search_uuid_table = default_search_uuid_table, + .security_en = 0, + .event_callback = default_event_callback, +}; + +#endif + +//--------------------------------------------------------------------------- +static client_conn_cfg_t *client_config = (void *) &client_conn_config_default ; +//---------------------------------------------------------------------------- + + +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 0, 600},//11 + {12, 28, 0, 600},//3.7 + {8, 20, 0, 600}, + {50, 60, 0, 600}, +}; + +static u8 send_param_index = 3; + +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode); +static int client_create_cannel_api(void); +//---------------------------------------------------------------------------- + +static void client_event_report(le_client_event_e event, u8 *packet, int size) +{ + if (client_config->event_callback) { + client_config->event_callback(event, packet, size); + } +} + +static bool check_device_is_match(u8 info_type, u8 *data, int size) +{ + int i; + u8 conn_mode = BIT(info_type); + client_match_cfg_t *cfg; + + /* log_info_hexdump(data,size); */ + + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + /* log_info("cfg = %08x\n",cfg); */ + /* log_info_hexdump(cfg,sizeof(client_match_cfg_t)); */ + if (cfg->create_conn_mode == conn_mode && size == cfg->compare_data_len) { + log_info("match check\n"); + /* log_info_hexdump(data, size); */ + /* log_info_hexdump(cfg->compare_data, size); */ + if (0 == memcmp(data, cfg->compare_data, cfg->compare_data_len)) { + log_info("match ok\n"); + pair_bond_enable = cfg->bonding_flag; + client_event_report(CLI_EVENT_MATCH_DEV, cfg, sizeof(client_match_cfg_t)); + return true; + } + } + } + return false; +} + +static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag) +{ + /* return; */ + + int ret; + int vm_len = sizeof(struct pair_info_t); + + log_info("-conn_pair_info vm_do:%d\n", rw_flag); + if (rw_flag == 0) { + ret = syscfg_read(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); + if (!ret) { + log_info("-null--\n"); + } + if ((BLE_VM_HEAD_TAG == info->head_tag) && (BLE_VM_TAIL_TAG == info->tail_tag)) { + log_info("-exist--\n"); + log_info_hexdump((u8 *)info, vm_len); + } else { + memset(info, 0, vm_len); + info->head_tag = BLE_VM_HEAD_TAG; + info->tail_tag = BLE_VM_TAIL_TAG; + } + } else { + syscfg_write(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); + } +} +//------------------------------------------------------------ +static ble_state_e get_ble_work_state(void) +{ + return ble_work_state; +} + +void clear_bonding_info(void) +{ + log_info("client_clear_bonding_info\n"); + conn_pair_vm_do(&conn_pair_info, 0); + if (conn_pair_info.pair_flag) { + //del pair bond + memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); + conn_pair_vm_do(&conn_pair_info, 1); + +#if WIRELESS_PAIR_BONDING + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + bt_ble_scan_enable(0, 1); + } else if (con_handle) { + ble_disconnect(); + } +#endif + } +} + +//------------------------------------------------------------ +static void set_ble_work_state(ble_state_e state) +{ + if (state != ble_work_state) { + log_info("ble_client_work_st:%x->%x\n", ble_work_state, state); + ble_work_state = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} + + +//------------------------------------------------------------------------------- +static void check_target_uuid_match(search_result_t *result_info) +{ + u32 i; + target_uuid_t *t_uuid; + + for (i = 0; i < client_config->search_uuid_cnt; i++) { + t_uuid = &client_config->search_uuid_table[i]; + if (result_info->services.uuid16) { + if (result_info->services.uuid16 != t_uuid->services_uuid16) { + /* log_info("b1"); */ + continue; + } + } else { + if (memcmp(result_info->services.uuid128, t_uuid->services_uuid128, 16)) { + /* log_info("b2"); */ + continue; + } + } + + if (result_info->characteristic.uuid16) { + if (result_info->characteristic.uuid16 != t_uuid->characteristic_uuid16) { + /* log_info("b3"); */ + /* log_info("%d: %04x--%04x",result_info->characteristic.uuid16,t_uuid->characteristic_uuid16); */ + continue; + } + } else { + if (memcmp(result_info->characteristic.uuid128, t_uuid->characteristic_uuid128, 16)) { + /* log_info("b4"); */ + continue; + } + } + + break;//match one + } + + if (i >= client_config->search_uuid_cnt) { + return; + } + + if (opt_handle_used_cnt >= OPT_HANDLE_MAX) { + log_info("opt_handle is full!!!\n"); + return; + } + + if ((t_uuid->opt_type & result_info->characteristic.properties) != t_uuid->opt_type) { + log_info("properties not match!!!\n"); + return; + } + + log_info("match one uuid\n"); + + opt_handle_t *opt_get = &opt_handle_table[opt_handle_used_cnt++]; + opt_get->value_handle = result_info->characteristic.value_handle; + opt_get->search_uuid = t_uuid; + + switch (t_uuid->opt_type) { + case ATT_PROPERTY_READ: + target_handle.read_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE_WITHOUT_RESPONSE: + target_handle.write_no_respond = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE: + target_handle.write_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_NOTIFY: + target_handle.notify_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_INDICATE: + target_handle.indicate_handle = result_info->characteristic.value_handle; + break; + + default: + break; + } + + client_event_report(CLI_EVENT_MATCH_UUID, opt_get, sizeof(opt_handle_t)); + +} + +//操作handle,完成 write ccc +static void do_operate_search_handle(void) +{ + u16 tmp_16; + u16 i, cur_opt_type; + opt_handle_t *opt_hdl_pt; + + log_info("opt_handle_used_cnt= %d\n", opt_handle_used_cnt); + + log_info("find target_handle:"); + log_info_hexdump(&target_handle, sizeof(target_hdl_t)); + + if (0 == opt_handle_used_cnt) { + goto opt_end; + } + + /* test_send_conn_update();//for test */ + + for (i = 0; i < opt_handle_used_cnt; i++) { + opt_hdl_pt = &opt_handle_table[i]; + cur_opt_type = opt_hdl_pt->search_uuid->opt_type; + switch ((u8)cur_opt_type) { + case ATT_PROPERTY_READ: + if (1) { + tmp_16 = 0x55A2;//fixed + log_info("read_long:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ_LONG); + } else { + tmp_16 = 0x55A1;//fixed + log_info("read:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ); + } + break; + + case ATT_PROPERTY_NOTIFY: + tmp_16 = 0x01;//fixed + log_info("write_ntf_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + break; + + case ATT_PROPERTY_INDICATE: + tmp_16 = 0x02;//fixed + log_info("write_ind_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + break; + + default: + break; + } + } + +opt_end: + set_ble_work_state(BLE_ST_SEARCH_COMPLETE); + +} + +//协议栈内部调用 +//return: 0--accept,1--reject +int l2cap_connection_update_request_just(u8 *packet, hci_con_handle_t handle) +{ + log_info("slave request conn_update:\n-interval_min= %d,\n-interval_max= %d,\n-latency= %d,\n-timeout= %d\n", + little_endian_read_16(packet, 0), little_endian_read_16(packet, 2), + little_endian_read_16(packet, 4), little_endian_read_16(packet, 6)); + return 0; + /* return 1; */ +} + +//协议栈内部调用 +void user_client_report_search_result(search_result_t *result_info) +{ + if (result_info == (void *) - 1) { + log_info("client_report_search_result finish!!!\n"); + do_operate_search_handle(); + client_event_report(CLI_EVENT_SEARCH_PROFILE_COMPLETE, 0, 0); + return; + } + + log_info("\n*** services, uuid16:%04x,index=%d ***\n", result_info->services.uuid16, result_info->service_index); + log_info("{charactc, uuid16:%04x,index=%d,handle:%04x~%04x,value_handle=%04x}\n", + result_info->characteristic.uuid16, result_info->characteristic_index, + result_info->characteristic.start_handle, result_info->characteristic.end_handle, + result_info->characteristic.value_handle + ); + + if (!result_info->services.uuid16) { + log_info("######services_uuid128:"); + log_info_hexdump(result_info->services.uuid128, 16); + } + + if (!result_info->characteristic.uuid16) { + log_info("######charact_uuid128:"); + log_info_hexdump(result_info->characteristic.uuid128, 16); + } + + check_target_uuid_match(result_info); +} + +#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) + +static u32 client_timer_handle = 0; +static u32 test_rx_data_count; +static u32 test_tx_data_count; + +static void client_timer_handler(void) +{ + if (!con_handle) { + test_rx_data_count = 0; + + test_tx_data_count = 0; + + return; + } + + if (test_rx_data_count) { + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); + /* log_info("\n-ble_data_rate: %d bps-\n", test_rx_data_count * 8); */ + log_info("%d bytes receive: %d.%02d KB/s \n", test_rx_data_count, test_rx_data_count / 1000, test_rx_data_count % 1000); + + test_rx_data_count = 0; + } + + if (test_tx_data_count) { + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); + log_info("%d bytes send: %d.%02d KB/s \n", test_tx_data_count, test_tx_data_count / 1000, test_tx_data_count % 1000); + + test_tx_data_count = 0; + } +} + +static void client_timer_start(void) +{ + client_timer_handle = sys_timer_add(NULL, client_timer_handler, 1000); +} + +#endif /* SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE */ + +static target_uuid_t *get_match_handle_target(u16 handle) +{ + for (int i = 0; i < opt_handle_used_cnt; i++) { + if (opt_handle_table[i].value_handle == handle) { + return opt_handle_table[i].search_uuid; + } + } + return NULL; +} + +//协议栈内部调用 +void user_client_report_data_callback(att_data_report_t *report_data) +{ + /* log_info("\n-report_data:type %02x,handle %04x,offset %d,len %d:",report_data->packet_type, */ + /* report_data->value_handle,report_data->value_offset,report_data->blob_length); */ + /* log_info_hexdump(report_data->blob,report_data->blob_length); */ + +#if SHOW_RX_DATA_RATE + test_rx_data_count += report_data->blob_length; +#endif /* SHOW_RX_DATA_RATE */ + + target_uuid_t *search_uuid = get_match_handle_target(report_data->value_handle); + + if (client_config->report_data_callback) { + client_config->report_data_callback(report_data, search_uuid); + return; + } + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION://notify +// log_info("\n-notify_rx(%d):",report_data->blob_length); + case GATT_EVENT_INDICATION://indicate + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long + break; + default: + break; + } +} + +// PRIMARY_SERVICE,AE30 +/* static const u16 test_services_uuid16 = 0xae30; */ + +// PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 +/* static const u8 test_services_uuid128[16] = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}; */ + +static void client_search_profile_start(void) +{ + opt_handle_used_cnt = 0; + memset(&target_handle, 0, sizeof(target_hdl_t)); + user_client_init(con_handle, search_ram_buffer, SEARCH_PROFILE_BUFSIZE); + if (client_config->search_uuid_cnt) { + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); + ble_op_search_profile_all(); + } else { + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); + user_client_set_search_complete(); + } +} + +//------------------------------------------------------------ +static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rssi) +{ + u8 i, lenght, ad_type; + u8 *adv_data_pt; + u8 find_remoter = 0; + /* u8 tmp_addr[6]; */ + u32 tmp32; + + if (check_device_is_match(CLI_CREAT_BY_ADDRESS, adv_address, 6)) { + find_remoter = 1; + } + + adv_data_pt = data; + for (i = 0; i < data_length;) { + if (*adv_data_pt == 0) { + /* log_info("analyze end\n"); */ + break; + } + + lenght = *adv_data_pt++; + + if (lenght >= data_length || (lenght + i) >= data_length) { + /*过滤非标准包格式*/ + printf("!!!error_adv_packet:"); + put_buf(data, data_length); + break; + } + + ad_type = *adv_data_pt++; + i += (lenght + 1); + + switch (ad_type) { + case HCI_EIR_DATATYPE_FLAGS: + /* log_info("flags:%02x\n",adv_data_pt[0]); */ + break; + + case HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_128BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_128BIT_SERVICE_UUIDS: + /* log_info("service uuid:"); */ + /* log_info_hexdump(adv_data_pt, lenght - 1); */ + break; + + case HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME: + case HCI_EIR_DATATYPE_SHORTENED_LOCAL_NAME: + tmp32 = adv_data_pt[lenght - 1]; + adv_data_pt[lenght - 1] = 0;; + log_info("remoter_name: %s,rssi:%d\n", adv_data_pt, rssi); + log_info_hexdump(adv_address, 6); + adv_data_pt[lenght - 1] = tmp32; + //------- +#if 0 //无线麦产线通过识别特殊字符串进行近距离连接测试 + if (0 == memcmp(adv_data_pt, SPECIFIC_STRING, strlen(SPECIFIC_STRING))) { + flag_specific_adv_name = 1; + flag_need_judge_rssi = 1; + } + if (flag_specific_sacn) { + flag_need_judge_rssi = 1; + } + if (flag_need_judge_rssi) { + flag_need_judge_rssi = 0; + if (rssi + TCFG_WIRELESS_RSSI < 0) { + printf("rssi no satisfy,break"); + break; + } else { + printf("rssi satisfy,RSSI = %d", rssi); + if (flag_specific_adv_name) { + find_remoter = 1; + break; + } + } + } + + flag_specific_adv_name = 0; +#endif + +#if SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN +#if !WIRELESS_TOOL_BLE_NAME_EN +#define TEST_BOX_BLE_NAME "W_MIC_01" +#define TEST_BOX_BLE_NAME_LEN sizeof(TEST_BOX_BLE_NAME) + printf("TEST_BOX_BLE_NAME_LEN=%d", TEST_BOX_BLE_NAME_LEN); + if (0 == memcmp(adv_data_pt, TEST_BOX_BLE_NAME, TEST_BOX_BLE_NAME_LEN)) { + find_remoter = 1; + break; + } +#else + put_buf(match_name, strlen(match_name)); + if (lenght == strlen(match_name) + 1) { + printf("TEST_BOX_BLE_NAME_LEN=%d", TEST_BOX_BLE_NAME_LEN); + if (0 == memcmp(adv_data_pt, match_name, lenght - 1)) { + find_remoter = 1; + break; + } + } +#endif +#endif + /* log_info("target name:%s", client_config->compare_data); */ + if (check_device_is_match(CLI_CREAT_BY_NAME, adv_data_pt, lenght - 1)) { + find_remoter = 1; + log_info("catch name ok\n"); + } + break; + + case HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA: + if (check_device_is_match(CLI_CREAT_BY_TAG, adv_data_pt, lenght - 1)) { + log_info("get_tag_string!\n"); + find_remoter = 1; + } + break; + + case HCI_EIR_DATATYPE_APPEARANCE_DATA: + /* log_info("get_class_type:%04x\n",little_endian_read_16(adv_data_pt,0)); */ + break; + + default: + /* log_info("unknow ad_type:"); */ + break; + } + + if (find_remoter) { + log_info_hexdump(adv_data_pt, lenght - 1); + } + adv_data_pt += (lenght - 1); + } + + return find_remoter; +} + +static void client_report_adv_data(adv_report_t *report_pt, u16 len) +{ + bool find_remoter; + + /* log_info("event_type,addr_type: %x,%x; ",report_pt->event_type,report_pt->address_type); */ + /* log_info_hexdump(report_pt->address,6); */ + + /* log_info("adv_data_display:"); */ + /* log_info_hexdump(report_pt->data,report_pt->length); */ + +// log_info("rssi:%d\n",report_pt->rssi); +#if WIRELESS_PAIR_BONDING + + if (conn_pair_info.pair_flag) { + if (report_pt->event_type != 1) { + return; + } + printf("report_add_type == %x", report_pt->address_type); + printf("conn_add_type == %x", conn_pair_info.peer_address_info[0]); + put_buf(report_pt->address, 6); + put_buf(&conn_pair_info.peer_address_info[1], 6); + if (report_pt->address_type == conn_pair_info.peer_address_info[0] + && 0 == memcmp(&conn_pair_info.peer_address_info[1], report_pt->address, 6)) { + log_info("match bond_dev\n"); + find_remoter = 1; + goto just_creat; + } else { + return; + } + } + find_remoter = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); + +just_creat: + +#else + find_remoter = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); +#endif + + if (find_remoter) { + if (force_seach_onoff && force_seach_rssi > report_pt->rssi) { + log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); + return; + } + + log_info("rssi:%d\n", report_pt->rssi); + log_info("\n*********create_connection***********\n"); + log_info("***remote type %d,addr:", report_pt->address_type); + log_info_hexdump(report_pt->address, 6); + bt_ble_scan_enable(0, 0); + client_create_connect_api(report_pt->address, report_pt->address_type, 0); + log_info("*create_finish\n"); + } +} + + +static void client_create_connection(u8 *conn_addr, u8 addr_type) +{ + struct create_conn_param_t *create_conn_par = scan_buffer; + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + log_info("already create conn!!!\n"); + return; + } + create_conn_par->conn_interval = SET_CONN_INTERVAL; + create_conn_par->conn_latency = SET_CONN_LATENCY; + create_conn_par->supervision_timeout = SET_CONN_TIMEOUT; + memcpy(create_conn_par->peer_address, conn_addr, 6); + create_conn_par->peer_address_type = addr_type; + + set_ble_work_state(BLE_ST_CREATE_CONN); + log_info_hexdump(create_conn_par, sizeof(struct create_conn_param_t)); + ble_op_create_connection(create_conn_par); +} + +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type) +{ + client_create_connection(conn_addr, addr_type); +} + +static void client_create_connection_cannel(void) +{ + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + set_ble_work_state(BLE_ST_SEND_CREATE_CONN_CANNEL); + ble_op_create_connection_cancel(); + } +} + +static int ble_disconnect(void *priv) +{ + if (con_handle) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state()) { + log_info(">>>ble send disconnect\n"); + set_ble_work_state(BLE_ST_SEND_DISCONN); + ble_op_disconnect(con_handle); + } else { + log_info(">>>ble wait disconnect...\n"); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + +static void connection_update_complete_success(u8 *packet) +{ + int con_handle, conn_interval, conn_latency, conn_timeout; + + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + + +static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + sm_just_event_t *event = (void *)packet; + u32 tmp32; + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + log_info_hexdump(packet, size); + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); + break; + } + break; + } +} + +static void can_send_now_wakeup(void) +{ + /* putchar('E'); */ + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } +} + +const char *const phy_result[] = { + "None", + "1M", + "2M", + "Coded", +}; + +static void set_connection_data_length(u16 tx_octets, u16 tx_time) +{ + if (con_handle) { + ble_op_set_data_length(con_handle, tx_octets, tx_time); + } +} + +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == con_handle) { + return; + } + + u8 all_phys = 0; + u16 phy_options = 0; + + ble_op_set_ext_phy(con_handle, all_phys, tx_phy, rx_phy, phy_options); +} + +static void client_profile_start(u16 con_handle) +{ + ble_op_att_send_init(con_handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_MTU_SIZE); + set_ble_work_state(BLE_ST_CONNECT); + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); + if (0 == client_config->security_en) { + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); + client_search_profile_start(); + } +} + +/* LISTING_START(packetHandler): Packet Handler */ +static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u32 tmp; + u8 status; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: + status = hci_subevent_le_enhanced_connection_complete_get_status(packet); + if (status) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", status); + set_ble_work_state(BLE_ST_DISCONN); + break; + } + con_handle = hci_subevent_le_enhanced_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE : 0x%0x\n", con_handle); + log_info("conn_interval = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_interval(packet)); + log_info("conn_latency = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_latency(packet)); + log_info("conn_timeout = %d\n", hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(packet)); + client_profile_start(con_handle); + break; + + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: + if (packet[3]) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", packet[3]); + set_ble_work_state(BLE_ST_DISCONN); + break; + } + con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE : %0x\n", con_handle); + connection_update_complete_success(packet + 8); + client_profile_start(con_handle); + client_event_report(CLI_EVENT_CONNECTED, packet, size); +#if WIRELESS_PAIR_BONDING + memcpy(cur_peer_address_info, &packet[7], 7); + conn_pair_info.pair_flag = 1; + printf("pair_flag == %d", conn_pair_info.pair_flag); + put_buf(cur_peer_address_info, 7); + memcpy(&conn_pair_info.peer_address_info, cur_peer_address_info, 7); + conn_pair_info.head_tag = BLE_VM_HEAD_TAG; + conn_pair_info.tail_tag = BLE_VM_TAIL_TAG; + conn_pair_vm_do(&conn_pair_info, 1); +#else + if (pair_bond_enable) { + conn_pair_info.pair_flag = 1; + memcpy(&conn_pair_info.peer_address_info, &packet[7], 7); + conn_pair_vm_do(&conn_pair_info, 1); + pair_bond_enable = 0; + } +#endif + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE\n"); + connection_update_complete_success(packet); + + client_event_report(CLI_EVENT_CONNECTION_UPDATE, packet, size); + + break; + + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE"); + break; + + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_PHY_UPDATE %s\n", hci_event_le_meta_get_phy_update_complete_status(packet) ? "Fail" : "Succ"); + log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); + log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); + break; + + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); + con_handle = 0; + ble_op_att_send_init(con_handle, 0, 0, 0); + set_ble_work_state(BLE_ST_DISCONN); + client_event_report(CLI_EVENT_DISCONNECT, packet, size); + + //auto to do +#if !WIRELESS_PAIR_BONDING + if (conn_pair_info.pair_flag) { + client_create_connect_api(0, 0, 1); + } else +#endif + { + bt_ble_scan_enable(0, 1); + } + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_op_att_set_send_mtu(mtu); + break; + + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp: %02x\n", tmp); + break; + + case GAP_EVENT_ADVERTISING_REPORT: + /* putchar('@'); */ + client_report_adv_data((void *)&packet[2], packet[1]); + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + if (client_config->security_en) { + client_search_profile_start(); + } + break; + } + break; + } +} + + +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_op_att_get_remain(&vaild_len); + return vaild_len; +} + +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type) +{ + int ret = APP_BLE_NO_ERROR; + if (!con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (!handle) { + log_info("handle is null\n"); + return APP_BLE_OPERATION_ERROR; + } + + + if (get_buffer_vaild_len(0) < len) { + /* log_info("opt_buff_full!!!\n"); */ + return APP_BLE_BUFF_FULL; + } + + ret = ble_op_att_send_data(handle, data, len, att_op_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } else { +#if SHOW_TX_DATA_RATE + test_tx_data_count += len; +#endif /* SHOW_TX_DATA_RATE */ + } + + return ret; +} + + +//----------------------------------------------- +static int client_write_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle.write_handle, data, len, ATT_OP_WRITE); +} + +static int client_write_without_respond_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle.write_no_respond, data, len, ATT_OP_WRITE_WITHOUT_RESPOND); +} + +static int client_read_value_send(void *priv) +{ + u16 tmp_flag = 0x55A1; + return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ); +} + +static int client_read_long_value_send(void *priv) +{ + u16 tmp_flag = 0x55A2; + return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ_LONG); +} + + +//扫描数设置 +static void scanning_setup_init(void) +{ + ble_op_set_scan_param(SET_SCAN_TYPE, SET_SCAN_INTERVAL, SET_SCAN_WINDOW); +} + +static int bt_ble_scan_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (!scan_ctrl_en && en) { + return APP_BLE_OPERATION_ERROR; + } + + if (en) { + next_state = BLE_ST_SCAN; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(); + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; + } + + + log_info("scan_en:%d\n", en); + set_ble_work_state(next_state); + + if (en) { + scanning_setup_init(); + } + ble_op_scan_enable2(en, 0); + + return APP_BLE_NO_ERROR; +} + +static int client_regiest_wakeup_send(void *priv, void *cbk) +{ + /* att_regist_wakeup_send(cbk); */ + return APP_BLE_NO_ERROR; +} + +static int client_regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int client_regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +//该接口重新配置搜索的配置项 +static int client_init_config(void *priv, const client_conn_cfg_t *cfg) +{ + log_info("client_init_config\n"); + client_config = cfg;//reset config + return APP_BLE_NO_ERROR; +} + +//可配置进入强制搜索方式连接,更加信号强度过滤设备 +static int client_force_search(u8 onoff, s8 rssi) +{ + force_seach_rssi = rssi; + if (force_seach_onoff != onoff) { + + force_seach_onoff = onoff; + //强制搜索前后,关创建监听 + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + } + } + return 0; +} + +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) +{ + u8 cur_state = get_ble_work_state(); + + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == BLE_ST_SCAN) { + log_info("stop scan\n"); + bt_ble_scan_enable(0, 0); + } + + //pair mode + if (mode == 1) { + if (conn_pair_info.pair_flag) { + if (conn_pair_info.pair_flag) { + //有配对,跳过搜索,直接创建init_creat + log_info("pair to creat!\n"); + log_info_hexdump(conn_pair_info.peer_address_info, 7); + bt_ble_create_connection(&conn_pair_info.peer_address_info[1], conn_pair_info.peer_address_info[0]); + return 0; + } + + } else { + log_info("no pair to creat!\n"); + return APP_BLE_OPERATION_ERROR; + } + } else { + log_info("addr to creat!\n"); + log_info_hexdump(addr, 7); + bt_ble_create_connection(addr, addr_type); + } + return 0; +} + +static int client_create_cannel_api(void) +{ + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + return 0; + } + return 1; +} + +static const struct ble_client_operation_t client_operation = { + .scan_enable = bt_ble_scan_enable, + .disconnect = ble_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .write_data = (void *)client_write_without_respond_send, + .read_do = (void *)client_read_value_send, + .regist_wakeup_send = client_regiest_wakeup_send, + .regist_recieve_cbk = client_regiest_recieve_cbk, + .regist_state_cbk = client_regiest_state_cbk, + .init_config = client_init_config, + .opt_comm_send = client_operation_send, + .set_force_search = client_force_search, + .create_connect = client_create_connect_api, + .create_connect_cannel = client_create_cannel_api, + .get_work_state = get_ble_work_state, +}; + +struct ble_client_operation_t *ble_get_client_operation_table(void) +{ + return &client_operation; +} + +#define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey +//重设passkey回调函数,在这里可以重新设置passkey +//passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 +static void reset_passkey_cb(u32 *key) +{ +#if 1 + u32 newkey = rand32();//获取随机数 + + newkey &= 0xfffff; + if (newkey > 999999) { + newkey = newkey - 999999; //不能大于999999 + } + *key = newkey; //小于或等于六位数 + log_info("set new_key= %06u\n", *key); +#else + *key = 123456; //for debug +#endif +} + +#if 0 +//协议栈内部调用 +extern void sm_set_master_request_pair(int enable); +static void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) +{ + //setup SM: Display only + sm_init(); + sm_set_io_capabilities(io_type); + sm_set_authentication_requirements(auth_req); + sm_set_encryption_key_size_range(min_key_size, 16); + sm_set_master_request_pair(security_en); + sm_event_callback_set(&cbk_sm_packet_handler); + + if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { + reset_PK_cb_register(reset_passkey_cb); + } +} +#endif + + +//协议栈内部调用 +void ble_profile_init(void) +{ + log_info("ble profile init\n"); + le_device_db_init(); + ble_stack_gatt_role(1); + +//#if PASSKEY_ENTER_ENABLE +// ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, client_config->security_en); +//#else +// ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, client_config->security_en); +//#endif + + /* setup ATT client */ + gatt_client_init(); + gatt_client_register_packet_handler(cbk_packet_handler); + + // register for HCI events + hci_event_callback_set(&cbk_packet_handler); + le_l2cap_register_packet_handler(&cbk_packet_handler); + + ble_vendor_set_default_att_mtu(ATT_LOCAL_MTU_SIZE); +} + + +static void device_bonding_init(void) +{ + int i; + int cfg_bonding = 0; + client_match_cfg_t *cfg; + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + if (cfg->bonding_flag) { + cfg_bonding = 1; + } + } + if (!cfg_bonding) { + clear_bonding_info(); + } +} + +static u8 client_idle_query(void) +{ + return 0; +} + +REGISTER_LP_TARGET(client_user_target) = { + .name = "client_user_demo", + .is_idle = client_idle_query, +}; + + + + +void bt_ble_init(void) +{ + log_info("***** ble_init******\n"); +#if WIRELESS_TOOL_BLE_NAME_EN + u8 *config_name; + u8 config_name_len; +#endif + +#if (WIRELESS_24G_ENABLE) + rf_set_24g_hackable_coded(WIRELESS_24G_CODE_ID); +#endif +#if WIRELESS_TOOL_BLE_NAME_EN +#if 1 //使用配置工具的蓝牙名 + extern const char *bt_get_local_name(); + config_name = (u8 *)(bt_get_local_name()); + config_name_len = strlen(config_name) + 1; + put_buf(config_name, config_name_len); + printf("len = %d", config_name_len); +#else + config_name = TEST_BOX_BLE_NAME; + config_name_len = sizeof(TEST_BOX_BLE_NAME); +#endif + match_name = (u8 *)zalloc(config_name_len); + memcpy(match_name, config_name, config_name_len); + printf("match_name"); + put_buf(match_name, config_name_len); + printf("%s", match_name); +#endif + // if (0 == memcmp(match_name, SPECIFIC_STRING, strlen(SPECIFIC_STRING))) { + // match_name = &match_name[strlen(SPECIFIC_STRING)]; + // printf("specific scan%s", match_name); + // flag_specific_sacn = 1; + + // } + + set_ble_work_state(BLE_ST_INIT_OK); + conn_pair_vm_do(&conn_pair_info, 0); + +#if !WIRELESS_PAIR_BONDING + device_bonding_init(); +#endif + ble_module_enable(1); + extern void wifi_detect_set_master_first(u8 first); +#if TCFG_WIFI_DETECT_ENABLE +#if TCFG_WIFI_DETCET_PRIOR + wifi_detect_set_master_first(0); +#else + wifi_detect_set_master_first(1); +#endif +#endif + +#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) + client_timer_start(); +#endif /* SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE */ +} + +void bt_ble_exit(void) +{ + log_info("***** ble_exit******\n"); +} + +void ble_app_disconnect(void) +{ + ble_disconnect(NULL); +} +//统一接口,关闭模块 +void bt_ble_adv_enable(u8 enable) +{ + ble_module_enable(enable); +} + +//模块开关 +void ble_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + if (en) { + scan_ctrl_en = 1; + bt_ble_scan_enable(0, 1); + } else { + if (con_handle) { + scan_ctrl_en = 0; + ble_disconnect(NULL); + } else { + bt_ble_scan_enable(0, 0); + scan_ctrl_en = 0; + } + } + +} + +void client_send_conn_param_update(void) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[send_param_index];//for test + log_info("client update param:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (con_handle) { + ble_op_conn_param_update(con_handle, param); + } +} + + + +//---------------------------------------------------------------------------------- +//lmx +void rcsp_adv_fill_mac_addr(u8 *mac_addr_buf) +{ +#if (MUTIl_CHARGING_BOX_EN) + u8 *mac_addr = get_chargebox_adv_addr(); + if (mac_addr) { + swapX(mac_addr, mac_addr_buf, 6); + } + + /* printf("mac_addr:"); */ + /* printf_buf(mac_addr_buf, 6); */ + +#else + swapX(bt_get_mac_addr(), mac_addr_buf, 6); +#endif +} + +/** + * @brief 发送数据给server + * + * @param data + * @param length + */ +void g_send_data_to_ble_server(const u8* data, u16 length){ + // 检查数据长度是否有效 + if (length == 0 || length > 512) { + printf("Error: Data length %d is out of range (1-512)\n", length); + return; + } + + int ret = client_operation_send(default_client_write_handle, data, length, ATT_OP_WRITE_WITHOUT_RESPOND); + if(ret == 0){ + printf("success: send data to server\n"); + return; + } + printf("error: send data to server\n"); +} + +#endif + + diff --git a/apps/earphone/xtell_remote_control/ble_handler/client_handler.c b/apps/earphone/xtell_remote_control/ble_handler/client_handler.c index 2ca204b..0e8aa92 100644 --- a/apps/earphone/xtell_remote_control/ble_handler/client_handler.c +++ b/apps/earphone/xtell_remote_control/ble_handler/client_handler.c @@ -1,20 +1,3 @@ -/** - ************************************************************************************************** - * 设备扫描与发现 - * 创建和管理连接 - * 服务和特征的发现 - * 数据读写操作 - * 连接状态管理和事件处理 - * 配对与绑定 - ************************************************************************************************** - */ - - -/* - ************************************************************************************************** - * 头文件包含 - ************************************************************************************************** - */ #include "system/app_core.h" #include "system/includes.h" @@ -31,540 +14,275 @@ #include "le_client_demo.h" #include "le_common.h" #include "ble_user.h" -#include "../nvs/nvs.h" -#if (BLE_WIRELESS_CLIENT_EN == 1) // 作为主设备主动去连接其他蓝牙 -/* - ************************************************************************************************** - * 宏定义 - ************************************************************************************************** - */ +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_WIRELESS_MIC_CLIENT) -// 功能开关宏 -#define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 0 // 是否支持测试盒BLE主设备测试 -#define SHOW_RX_DATA_RATE 1 // 是否显示接收数据速率 -#define SHOW_TX_DATA_RATE 1 // 是否显示发送数据速率 -#define XTELL_DEBUG 1 +#define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 0 +#define SHOW_RX_DATA_RATE 1 +#define SHOW_TX_DATA_RATE 1 -// 日志打印宏 -#if XTELL_DEBUG == 1 -#define log_info(x, ...) printf("[LE_CLIENT]" x " ", ## __VA_ARGS__) // 带前缀的信息打印 -#define log_info_hexdump put_buf // 16进制数据打印 +#if LE_DEBUG_PRINT_EN +/* #define log_info printf */ +#define log_info(x, ...) printf("[LE_CLIENT]" x " ", ## __VA_ARGS__) +#define log_info_hexdump put_buf #else -#define log_info(...) // 禁用信息打印 -#define log_info_hexdump(...) // 禁用16进制数据打印 +#define log_info(...) +#define log_info_hexdump(...) #endif -// ATT 协议相关宏 -#define ATT_LOCAL_MTU_SIZE (517) // 本地ATT最大传输单元(MTU)大小,需>=20 -#define ATT_SEND_CBUF_SIZE (200) // ATT发送数据循环缓冲区大小,需>=20 -#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_MTU_SIZE + ATT_SEND_CBUF_SIZE) // 总ATT RAM缓冲区大小 -// 搜索Profile缓冲区宏 -#define SEARCH_PROFILE_BUFSIZE (512) // 搜索Profile时使用的RAM缓冲区大小 -#define scan_buffer search_ram_buffer // 将scan_buffer定义为search_ram_buffer的别名 +//------ +#define ATT_LOCAL_MTU_SIZE (517) //note: need >= 20 +#define ATT_SEND_CBUF_SIZE (200)//(256)//(512*10) //note: need >= 20,缓存大小,可修改 +#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_MTU_SIZE + ATT_SEND_CBUF_SIZE) //note: +static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); -// BLE扫描参数宏 (单位: 0.625ms) -#define SET_SCAN_TYPE SCAN_ACTIVE // 扫描类型:主动扫描 -#define SET_SCAN_INTERVAL 320 // 扫描间隔 (e.g., 320 * 0.625ms = 200ms) -#define SET_SCAN_WINDOW 70 // 扫描窗口 (e.g., 70 * 0.625ms = 43.75ms) +#define SEARCH_PROFILE_BUFSIZE (512) //note: +static u8 search_ram_buffer[SEARCH_PROFILE_BUFSIZE] __attribute__((aligned(4))); +#define scan_buffer search_ram_buffer +//--------------- +//搜索类型 +#define SET_SCAN_TYPE SCAN_ACTIVE +//搜索 周期大小, 参数一:320 参数二:320 参数三:168 +#define SET_SCAN_INTERVAL 320//48//256//48 //(unit:0.625ms), 96没有干扰的情况下, 连接速度为60ms, 如需要降低功耗, 可以在+16的倍数 +//搜索 窗口大小 参数一:102 参数二:70 参数三:30 +#define SET_SCAN_WINDOW 70//48//24//48 //(unit:0.625ms) -// BLE连接参数宏 -#define SET_CONN_INTERVAL 3 // 连接间隔 (单位: 1.25ms, e.g., 3 * 1.25ms = 3.75ms) -#define SET_CONN_LATENCY 0 // 连接延迟 (单位: conn_interval) -#define SET_CONN_TIMEOUT 400 // 连接超时 (单位: 10ms, e.g., 400 * 10ms = 4000ms) - -// 测试盒蓝牙名称宏 +//连接周期 +#define SET_CONN_INTERVAL 3 //(unit:1.25ms) +//连接latency +#define SET_CONN_LATENCY 0 //(unit:conn_interval) +//连接超时 +#define SET_CONN_TIMEOUT 400 //(unit:10ms) #if WIRELESS_TOOL_BLE_NAME_EN -#define TEST_BOX_BLE_NAME "W_MIC_01" // 测试盒默认蓝牙名称 -#define TEST_BOX_BLE_NAME_LEN (sizeof(TEST_BOX_BLE_NAME)-1) // 名称长度(不含结束符) +#define TEST_BOX_BLE_NAME "W_MIC_01" +#define TEST_BOX_BLE_NAME_LEN (sizeof(TEST_BOX_BLE_NAME)-1) +static u8 *match_name; #endif +//---------------------------------------------------------------------------- +static u8 scan_ctrl_en; +static u8 ble_work_state = 0; +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; -// VM(非易失性存储)存储配对信息标签 -#define BLE_VM_HEAD_TAG (0xB95C) // VM数据头标签 -#define BLE_VM_TAIL_TAG (0x5CB9) // VM数据尾标签 +static hci_con_handle_t con_handle; -// Passkey输入功能开关 -#define PASSKEY_ENTER_ENABLE 0 // 是否启用输入Passkey进行配对 - -/* - ************************************************************************************************** - * 类型定义 - ************************************************************************************************** - */ - -/** - * @brief 配对信息结构体,用于存储到VM - */ +#define BLE_VM_HEAD_TAG (0xB95C) +#define BLE_VM_TAIL_TAG (0x5CB9) struct pair_info_t { - u16 head_tag; // 数据头标签,用于校验 - u8 pair_flag; // 配对标志,1表示已配对 - u8 peer_address_info[7]; // 对端设备地址信息 (1字节类型 + 6字节地址) - u16 tail_tag; // 数据尾标签,用于校验 + u16 head_tag; + u8 pair_flag; + u8 peer_address_info[7]; + u16 tail_tag; }; +static struct pair_info_t conn_pair_info; +static u8 pair_bond_enable = 0; -/** - * @brief 目标设备特征句柄集合 - */ +//------------------------------------------------------------------------------- typedef struct { - uint16_t read_handle; // 读特征句柄 - uint16_t read_long_handle; // 长读特征句柄 - uint16_t write_handle; // 写特征句柄 - uint16_t write_no_respond; // 无响应写特征句柄 - uint16_t notify_handle; // 通知特征句柄 - uint16_t indicate_handle; // 指示特征句柄 + uint16_t read_handle; + uint16_t read_long_handle; + uint16_t write_handle; + uint16_t write_no_respond; + uint16_t notify_handle; + uint16_t indicate_handle; } target_hdl_t; +//记录handle 使用 +static target_hdl_t target_handle; +static opt_handle_t opt_handle_table[OPT_HANDLE_MAX]; +static u8 opt_handle_used_cnt; +static u8 force_seach_onoff = 0; +static s8 force_seach_rssi = -127; +static u8 cur_peer_address_info[7]; +static u8 flag_specific_adv_name = 0; +static u8 flag_need_judge_rssi = 0; +static u8 flag_specific_sacn = 0; -/* - ************************************************************************************************** - * 静态函数声明 - ************************************************************************************************** - */ -// 状态管理 -static void set_ble_work_state(ble_state_e state); -static ble_state_e get_ble_work_state(void); - -// 扫描与连接 -static int bt_ble_scan_enable(void *priv, u32 en); -static void scanning_setup_init(void); -static void client_report_adv_data(adv_report_t *report_pt, u16 len); -static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rssi); -static bool check_device_is_match(u8 info_type, u8 *data, int size); -static void client_create_connection(u8 *conn_addr, u8 addr_type); static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type); -static void client_create_connection_cannel(void); -static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode); -static int client_create_cannel_api(void); -static int ble_disconnect(void *priv); - -// Profile 发现与操作 -static void client_search_profile_start(void); -static void user_client_report_search_result(search_result_t *result_info); -static void check_target_uuid_match(search_result_t *result_info); -static void do_operate_search_handle(void); -static target_uuid_t *get_match_handle_target(u16 handle); - -// 数据收发 -static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type); +static int bt_ble_scan_enable(void *priv, u32 en); static int client_write_send(void *priv, u8 *data, u16 len); -static int client_write_without_respond_send(void *priv, u8 *data, u16 len); -static int client_read_value_send(void *priv); -static int client_read_long_value_send(void *priv); -static int get_buffer_vaild_len(void *priv); -static void can_send_now_wakeup(void); - -// 事件与回调处理 -static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); -static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); -static void user_client_report_data_callback(att_data_report_t *report_data); -static void client_event_report(le_client_event_e event, u8 *packet, int size); -static void connection_update_complete_success(u8 *packet); -static int l2cap_connection_update_request_just(u8 *packet, hci_con_handle_t handle); - -// 配对与绑定 -static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag); -static void device_bonding_init(void); -static void reset_passkey_cb(u32 *key); - -// 初始化与配置 -static int client_init_config(void *priv, const client_conn_cfg_t *cfg); -static int client_regiest_wakeup_send(void *priv, void *cbk); -static int client_regiest_recieve_cbk(void *priv, void *cbk); -static int client_regiest_state_cbk(void *priv, void *cbk); - -// 其他辅助函数 -static int client_force_search(u8 onoff, s8 rssi); -static void set_connection_data_length(u16 tx_octets, u16 tx_time); -static void set_connection_data_phy(u8 tx_phy, u8 rx_phy); -static u8 client_idle_query(void); - -// 默认示例相关 -#if 1 //default -static void default_report_data_deal(att_data_report_t *report_data, target_uuid_t *search_uuid); -static void default_test_write(void); -static void default_event_callback(le_client_event_e event, u8 *packet, int size); +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type); +#if WIRELESS_TOOL_BLE_NAME_EN +static ble_state_e get_ble_work_state(void); +#else +static void set_ble_work_state(ble_state_e state); #endif - -// 数据速率统计 -#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) -static void client_timer_handler(void); -static void client_timer_start(void); -#endif - -/* - ************************************************************************************************** - * 全局/静态变量定义 - ************************************************************************************************** - */ -static u8 connect_state = 0; //0:连接断开; 1:连接成功 - -// --- 缓冲区 --- -static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); // ATT协议栈RAM缓冲区 -static u8 search_ram_buffer[SEARCH_PROFILE_BUFSIZE] __attribute__((aligned(4))); // Profile搜索RAM缓冲区 - -// --- 状态变量 --- -static u8 scan_ctrl_en; // 扫描总开关,由上层应用控制 -static u8 ble_work_state = 0; // BLE工作状态机 -static hci_con_handle_t con_handle; // 当前连接句柄 -static u8 force_seach_onoff = 0; // 强制搜索开关(根据RSSI过滤) -static s8 force_seach_rssi = -127; // 强制搜索的RSSI阈值 -static u8 cur_peer_address_info[7]; // 当前连接的对端设备地址信息 -static u8 flag_specific_adv_name = 0; // 产测用:是否发现特定广播名称的标志 -static u8 flag_need_judge_rssi = 0; // 产测用:是否需要判断RSSI的标志 -static u8 flag_specific_sacn = 0; // 产测用:是否为特定扫描的标志 - -// --- 回调函数指针 --- -static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; // 应用层数据接收回调 -static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; // 应用层状态变化回调 -static void (*ble_resume_send_wakeup)(void) = NULL; // 数据发送恢复唤醒回调 -static u32 channel_priv; // 回调函数私有参数 - -// --- 配对与绑定信息 --- -static struct pair_info_t conn_pair_info; // 连接配对信息 -static u8 pair_bond_enable = 0; // 本次连接是否需要绑定 - -// --- Profile句柄管理 --- -static target_hdl_t target_handle; // 存储发现的目标特征句柄 -static opt_handle_t opt_handle_table[OPT_HANDLE_MAX]; // 存储所有匹配到的特征操作句柄 -static u8 opt_handle_used_cnt; // 已使用的操作句柄数量 - -// --- 默认示例配置 --- -#if 1 //default -// 默认搜索的UUID表 +static void client_create_connection_cannel(void); +//--------------------------------------------------------------------------- +#if 1//default +//指定搜索uuid +//指定搜索uuid static const target_uuid_t default_search_uuid_table[] = { - // 服务UUID: 0xae30, 特征UUID: 0xae01, 操作类型: 无响应写 + + // for uuid16 + // PRIMARY_SERVICE, ae30 + // CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, + // CHARACTERISTIC, ae02, NOTIFY, + { .services_uuid16 = 0xae30, .characteristic_uuid16 = 0xae01, .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, }, - // 服务UUID: 0xae30, 特征UUID: 0xae02, 操作类型: 通知 + { .services_uuid16 = 0xae30, .characteristic_uuid16 = 0xae02, .opt_type = ATT_PROPERTY_NOTIFY, }, + + //for uuid128,sample + // PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 + // CHARACTERISTIC, 0000F531-1212-EFDE-1523-785FEABCD123, NOTIFY, + // CHARACTERISTIC, 0000F532-1212-EFDE-1523-785FEABCD123, WRITE_WITHOUT_RESPONSE | DYNAMIC, + /* + { + .services_uuid16 = 0, + .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , + .characteristic_uuid16 = 0, + .characteristic_uuid128 = {0x00,0x00,0xF5,0x31 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, + .opt_type = ATT_PROPERTY_NOTIFY, + }, + + { + .services_uuid16 = 0, + .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , + .characteristic_uuid16 = 0, + .characteristic_uuid128 = {0x00,0x00,0xF5,0x32 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, + .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, + }, + */ + }; -// 默认匹配的设备名称 -static u8 test_remoter_name1[] = "CM-22222"; -// 默认匹配规则 -static client_match_cfg_t match_dev01 = { - .create_conn_mode = BIT(CLI_CREAT_BY_NAME), // 通过名称匹配 - .compare_data_len = sizeof(test_remoter_name1) - 1, // 名称长度 - .compare_data = test_remoter_name1, // 名称数据 - .bonding_flag = 0, // 不进行绑定 + +static void default_report_data_deal(att_data_report_t *report_data, target_uuid_t *search_uuid) +{ + log_info("report_data:%02x,%02x,%d,len(%d)", report_data->packet_type, + report_data->value_handle, report_data->value_offset, report_data->blob_length); + + log_info_hexdump(report_data->blob, report_data->blob_length); + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION: //notify + break; + case GATT_EVENT_INDICATION://indicate + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + break; + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long + break; + + default: + break; + } +} +static const u8 test_remoter_name1[] = "CM-22222"; +// static const u8 test_remoter_name1[] = "AC637N_MX(BLE)";// +/* static const u8 test_remoter_name2[] = "AC630N_HID567(BLE)";// */ +static u16 default_client_write_handle; +static u16 test_client_timer = 0; + +static const client_match_cfg_t match_dev01 = { + .create_conn_mode = BIT(CLI_CREAT_BY_NAME), + .compare_data_len = sizeof(test_remoter_name1) - 1, //去结束符 + .compare_data = test_remoter_name1, + .bonding_flag = 0, }; -// 默认客户端连接配置 -static client_conn_cfg_t client_conn_config_default = { +/* static const client_match_cfg_t match_dev02 = { */ +/* .create_conn_mode = BIT(CLI_CREAT_BY_NAME), */ +/* .compare_data_len = sizeof(test_remoter_name2) - 1, //去结束符 */ +/* .compare_data = test_remoter_name2, */ +/* .bonding_flag = 1, */ +/* }; */ + +static void default_test_write(void) +{ + static u32 count = 0; + count++; + int ret = client_operation_send(default_client_write_handle, &count, 16, ATT_OP_WRITE_WITHOUT_RESPOND); + log_info("test_write:%x", ret); +} + +static void default_event_callback(le_client_event_e event, u8 *packet, int size) +{ + switch (event) { + case CLI_EVENT_MATCH_DEV: { + client_match_cfg_t *match_dev = packet; + log_info("match_name:%s\n", match_dev->compare_data); + } + break; + + case CLI_EVENT_MATCH_UUID: { + opt_handle_t *opt_hdl = packet; + if (opt_hdl->search_uuid == &default_search_uuid_table[0]) { + default_client_write_handle = opt_hdl->value_handle; + log_info("match_uuid22\n"); + } + } + break; + + case CLI_EVENT_SEARCH_PROFILE_COMPLETE: + log_info("CLI_EVENT_SEARCH_PROFILE_COMPLETE\n"); + if ((!test_client_timer) && default_client_write_handle) { + log_info("test timer_add\n"); + test_client_timer = sys_hi_timer_add(0, default_test_write, 500); + extern void test_func_main(void); + test_func_main(); + } + break; + + case CLI_EVENT_CONNECTED: + break; + + case CLI_EVENT_DISCONNECT: + if (test_client_timer) { + sys_timeout_del(test_client_timer); + test_client_timer = 0; + } + default_client_write_handle = 0; + break; + + default: + break; + } +} + + +static const client_conn_cfg_t client_conn_config_default = { .match_dev_cfg[0] = &match_dev01, .match_dev_cfg[1] = NULL, .match_dev_cfg[2] = NULL, + /* .match_dev_cfg[1] = &match_dev02, */ .report_data_callback = default_report_data_deal, .search_uuid_cnt = (sizeof(default_search_uuid_table) / sizeof(target_uuid_t)), .search_uuid_table = default_search_uuid_table, - .security_en = 0, //不加密 + .security_en = 0, .event_callback = default_event_callback, }; -static u16 default_client_write_handle; // 默认示例的写句柄 -static u16 test_client_timer = 0; // 默认示例的定时器 #endif -// --- 全局配置指针 --- -static client_conn_cfg_t *client_config = (void *) &client_conn_config_default; // 指向当前客户端连接配置 +//--------------------------------------------------------------------------- +static client_conn_cfg_t *client_config = (void *) &client_conn_config_default ; +//---------------------------------------------------------------------------- + -// --- 连接更新参数 --- static const struct conn_update_param_t connection_param_table[] = { - {16, 24, 0, 600}, - {12, 28, 0, 600}, + {16, 24, 0, 600},//11 + {12, 28, 0, 600},//3.7 {8, 20, 0, 600}, {50, 60, 0, 600}, }; -static u8 send_param_index = 3; // 当前使用的连接参数索引 -// --- 数据速率统计 --- -#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) -static u32 client_timer_handle = 0; // 速率统计定时器 -static u32 test_rx_data_count; // 接收字节计数 -static u32 test_tx_data_count; // 发送字节计数 -#endif - -// --- 其他 --- -#if WIRELESS_TOOL_BLE_NAME_EN -static u8 *match_name; // 动态配置的匹配名称 -#endif - -static const char *const phy_result[] = { // PHY速率类型字符串 - "None", "1M", "2M", "Coded", -}; - -// --- 接口操作结构体 --- -static const struct ble_client_operation_t client_operation = { - .scan_enable = bt_ble_scan_enable, - .disconnect = ble_disconnect, - .get_buffer_vaild = get_buffer_vaild_len, - .write_data = (void *)client_write_without_respond_send, - .read_do = (void *)client_read_value_send, - .regist_wakeup_send = client_regiest_wakeup_send, - .regist_recieve_cbk = client_regiest_recieve_cbk, - .regist_state_cbk = client_regiest_state_cbk, - .init_config = client_init_config, - .opt_comm_send = client_operation_send, - .set_force_search = client_force_search, - .create_connect = client_create_connect_api, - .create_connect_cannel = client_create_cannel_api, - .get_work_state = get_ble_work_state, -}; - -/* - ************************************************************************************************** - * 外部调用函数实现 - ************************************************************************************************** - */ - - -/** - * @brief 获取客户端操作接口表 - * @return 指向ble_client_operation_t结构体的指针 - */ -struct ble_client_operation_t *ble_get_client_operation_table(void) -{ - return (struct ble_client_operation_t *)&client_operation; -} - -/** - * @brief BLE协议栈初始化函数,由协议栈内部调用 - */ -void ble_profile_init(void) -{ - log_info("ble profile init\n"); - le_device_db_init(); - ble_stack_gatt_role(1); // 设置为客户端角色 - - /* setup ATT client */ - gatt_client_init(); - gatt_client_register_packet_handler(cbk_packet_handler); - - // 注册HCI事件回调 - hci_event_callback_set(&cbk_packet_handler); - le_l2cap_register_packet_handler(&cbk_packet_handler); - - ble_vendor_set_default_att_mtu(ATT_LOCAL_MTU_SIZE); -} - -/** - * @brief BLE客户端总初始化 - */ -void bt_ble_init(void) -{ - log_info("***** ble_init******\n"); - -#if WIRELESS_TOOL_BLE_NAME_EN - u8 *config_name; - u8 config_name_len; -#if 1 // 使用配置工具的蓝牙名 - extern const char *bt_get_local_name(); - config_name = (u8 *)(bt_get_local_name()); - config_name_len = strlen((const char *)config_name) + 1; - log_info("use config name, len=%d", config_name_len); - log_info_hexdump(config_name, config_name_len); -#else - config_name = (u8 *)TEST_BOX_BLE_NAME; - config_name_len = sizeof(TEST_BOX_BLE_NAME); -#endif - match_name = (u8 *)zalloc(config_name_len); - memcpy(match_name, config_name, config_name_len); - log_info("match_name: %s", match_name); -#endif - - set_ble_work_state(BLE_ST_INIT_OK); - conn_pair_vm_do(&conn_pair_info, 0); // 读取VM中的配对信息 - -#if !WIRELESS_PAIR_BONDING - device_bonding_init(); -#endif - - ble_module_enable(1); // 使能BLE模块 - -#if TCFG_WIFI_DETECT_ENABLE - extern void wifi_detect_set_master_first(u8 first); -#if TCFG_WIFI_DETCET_PRIOR - wifi_detect_set_master_first(0); -#else - wifi_detect_set_master_first(1); -#endif -#endif - -#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) - client_timer_start(); // 启动数据速率统计定时器 -#endif -} - -/** - * @brief BLE客户端退出 - */ -void bt_ble_exit(void) -{ - log_info("***** ble_exit******\n"); - // 可添加退出清理代码 -} - -/** - * @brief 应用层调用的断开连接接口 - */ -void ble_app_disconnect(void) -{ - ble_disconnect(NULL); -} - -/** - * @brief BLE模块使能/禁止 (兼容旧接口) - * @param enable 1:使能, 0:禁止 - */ -void bt_ble_adv_enable(u8 enable) -{ - ble_module_enable(enable); -} - -/** - * @brief BLE模块使能/禁止 - * @param en 1:使能, 0:禁止 - */ -void ble_module_enable(u8 en) -{ - log_info("mode_en:%d\n", en); - if (en) { - scan_ctrl_en = 1; - bt_ble_scan_enable(0, 1); // 开始扫描 - } else { - scan_ctrl_en = 0; - if (con_handle) { - ble_disconnect(NULL); // 如果已连接,则断开 - } else { - bt_ble_scan_enable(0, 0); // 如果未连接,则停止扫描 - } - } -} - -/** - * @brief 客户端发起连接参数更新请求 - */ -void client_send_conn_param_update(void) -{ - struct conn_update_param_t *param = (void *)&connection_param_table[send_param_index]; - log_info("client update param:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); - if (con_handle) { - ble_op_conn_param_update(con_handle, param); - } -} - -/** - * @brief 清除绑定信息 - */ -void clear_bonding_info(void) -{ - log_info("client_clear_bonding_info\n"); - conn_pair_vm_do(&conn_pair_info, 0); - if (conn_pair_info.pair_flag) { - // 清空配对信息并写回VM - memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); - conn_pair_vm_do(&conn_pair_info, 1); - -#if WIRELESS_PAIR_BONDING - if (get_ble_work_state() == BLE_ST_CREATE_CONN) { - client_create_connection_cannel(); - bt_ble_scan_enable(0, 1); - } else if (con_handle) { - ble_disconnect(NULL); - } -#endif - } -} - -/** - * @brief 填充MAC地址到RCSP广播(示例函数) - * @param mac_addr_buf 存储MAC地址的缓冲区 - */ -void rcsp_adv_fill_mac_addr(u8 *mac_addr_buf) -{ -#if (MUTIl_CHARGING_BOX_EN) - u8 *mac_addr = get_chargebox_adv_addr(); - if (mac_addr) { - swapX(mac_addr, mac_addr_buf, 6); - } -#else - swapX(bt_get_mac_addr(), mac_addr_buf, 6); -#endif -} - -/** - * @brief 发送数据给server - * - * @param data - * @param length - */ -void g_send_data_to_ble_server(const u8* data, u16 length){ - // 检查数据长度是否有效 - if (length == 0 || length > 512) { - printf("Error: Data length %d is out of range (1-512)\n", length); - return; - } - int ret = client_operation_send(default_client_write_handle, data, length, ATT_OP_WRITE_WITHOUT_RESPOND); - if(ret == 0){ - printf("success: send data to server\n"); - return; - } - printf("error: send data to server\n"); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -static u8 new_device_name[MAIN_BOARD_MAC_ADDR_LENGTH] = {0}; - -static client_match_cfg_t new_match_dev = { - .create_conn_mode = BIT(CLI_CREAT_BY_NAME), // 通过名称匹配 - .compare_data_len = MAIN_BOARD_MAC_ADDR_LENGTH, // 名称长度,不包含"\0" - .compare_data = new_device_name, // 名称数据 - .bonding_flag = 0, // 不进行绑定 -}; - - -/** - * @brief 连接新的设备 - * - * @param name 设备的名称 - */ -void g_ble_connect_new_device(char* name){ - memcpy(new_device_name, name, MAIN_BOARD_MAC_ADDR_LENGTH); - client_config->match_dev_cfg[0] = &new_match_dev; - - // client_operation.init_config(NULL, client_config); //新配置 - - // client_operation.disconnect(NULL); //断开成功后会自动使用新配置进行扫描 - - client_init_config(NULL, client_config);//新配置 - ble_disconnect(NULL); //断开成功后会自动使用新配置进行扫描 - connect_state = 0; - -} - -/** - * @brief 获取当前ble连接状态 - * - * @return //0:连接断开; 1:连接成功 - */ -u8 g_ble_get_state(void){ - return connect_state; -} - -/* - ************************************************************************************************** - * 内部静态函数实现 - ************************************************************************************************** - */ +static u8 send_param_index = 3; +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode); +static int client_create_cannel_api(void); +//---------------------------------------------------------------------------- static void client_event_report(le_client_event_e event, u8 *packet, int size) { @@ -573,10 +291,88 @@ static void client_event_report(le_client_event_e event, u8 *packet, int size) } } -/** - * @brief 设置BLE工作状态 - * @param state 新的状态 - */ +static bool check_device_is_match(u8 info_type, u8 *data, int size) +{ + int i; + u8 conn_mode = BIT(info_type); + client_match_cfg_t *cfg; + + /* log_info_hexdump(data,size); */ + + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + /* log_info("cfg = %08x\n",cfg); */ + /* log_info_hexdump(cfg,sizeof(client_match_cfg_t)); */ + if (cfg->create_conn_mode == conn_mode && size == cfg->compare_data_len) { + log_info("match check\n"); + /* log_info_hexdump(data, size); */ + /* log_info_hexdump(cfg->compare_data, size); */ + if (0 == memcmp(data, cfg->compare_data, cfg->compare_data_len)) { + log_info("match ok\n"); + pair_bond_enable = cfg->bonding_flag; + client_event_report(CLI_EVENT_MATCH_DEV, cfg, sizeof(client_match_cfg_t)); + return true; + } + } + } + return false; +} + +static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag) +{ + /* return; */ + + int ret; + int vm_len = sizeof(struct pair_info_t); + + log_info("-conn_pair_info vm_do:%d\n", rw_flag); + if (rw_flag == 0) { + ret = syscfg_read(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); + if (!ret) { + log_info("-null--\n"); + } + if ((BLE_VM_HEAD_TAG == info->head_tag) && (BLE_VM_TAIL_TAG == info->tail_tag)) { + log_info("-exist--\n"); + log_info_hexdump((u8 *)info, vm_len); + } else { + memset(info, 0, vm_len); + info->head_tag = BLE_VM_HEAD_TAG; + info->tail_tag = BLE_VM_TAIL_TAG; + } + } else { + syscfg_write(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); + } +} +//------------------------------------------------------------ +static ble_state_e get_ble_work_state(void) +{ + return ble_work_state; +} + +void clear_bonding_info(void) +{ + log_info("client_clear_bonding_info\n"); + conn_pair_vm_do(&conn_pair_info, 0); + if (conn_pair_info.pair_flag) { + //del pair bond + memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); + conn_pair_vm_do(&conn_pair_info, 1); + +#if WIRELESS_PAIR_BONDING + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + bt_ble_scan_enable(0, 1); + } else if (con_handle) { + ble_disconnect(); + } +#endif + } +} + +//------------------------------------------------------------ static void set_ble_work_state(ble_state_e state) { if (state != ble_work_state) { @@ -588,108 +384,312 @@ static void set_ble_work_state(ble_state_e state) } } -/** - * @brief 获取当前BLE工作状态 - * @return ble_state_e 当前状态 - */ -static ble_state_e get_ble_work_state(void) -{ - return ble_work_state; -} -/** - * @brief 读写VM中的配对信息 - * @param info 指向配对信息结构体的指针 - * @param rw_flag 0:读, 1:写 - */ -static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag) +//------------------------------------------------------------------------------- +static void check_target_uuid_match(search_result_t *result_info) { - int ret; - int vm_len = sizeof(struct pair_info_t); + u32 i; + target_uuid_t *t_uuid; - log_info("-conn_pair_info vm_do:%d\n", rw_flag); - if (rw_flag == 0) { // 读操作 - ret = syscfg_read(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); - if (!ret) { - log_info("-null--\n"); - } - // 校验数据有效性 - if ((BLE_VM_HEAD_TAG == info->head_tag) && (BLE_VM_TAIL_TAG == info->tail_tag)) { - log_info("-exist--\n"); - log_info_hexdump((u8 *)info, vm_len); + for (i = 0; i < client_config->search_uuid_cnt; i++) { + t_uuid = &client_config->search_uuid_table[i]; + if (result_info->services.uuid16) { + if (result_info->services.uuid16 != t_uuid->services_uuid16) { + /* log_info("b1"); */ + continue; + } } else { - // 无效则初始化 - memset(info, 0, vm_len); - info->head_tag = BLE_VM_HEAD_TAG; - info->tail_tag = BLE_VM_TAIL_TAG; - } - } else { // 写操作 - syscfg_write(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); - } -} - -/** - * @brief 检查广播数据中的设备是否与预设规则匹配 - * @param info_type 匹配类型 (名称/地址/Tag) - * @param data 待比较的数据 - * @param size 数据长度 - * @return true:匹配, false:不匹配 - */ -static bool check_device_is_match(u8 info_type, u8 *data, int size) -{ - int i; - u8 conn_mode = BIT(info_type); - client_match_cfg_t *cfg; - - for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { - cfg = client_config->match_dev_cfg[i]; - if (cfg == NULL) { - continue; - } - // 检查匹配模式和数据长度是否一致 - if (cfg->create_conn_mode == conn_mode && size == cfg->compare_data_len) { - log_info("match check\n"); - // 比较数据内容 - if (0 == memcmp(data, cfg->compare_data, cfg->compare_data_len)) { - log_info("match ok\n"); - pair_bond_enable = cfg->bonding_flag; // 设置绑定标志 - client_event_report(CLI_EVENT_MATCH_DEV, (u8 *)cfg, sizeof(client_match_cfg_t)); - return true; + if (memcmp(result_info->services.uuid128, t_uuid->services_uuid128, 16)) { + /* log_info("b2"); */ + continue; } } + + if (result_info->characteristic.uuid16) { + if (result_info->characteristic.uuid16 != t_uuid->characteristic_uuid16) { + /* log_info("b3"); */ + /* log_info("%d: %04x--%04x",result_info->characteristic.uuid16,t_uuid->characteristic_uuid16); */ + continue; + } + } else { + if (memcmp(result_info->characteristic.uuid128, t_uuid->characteristic_uuid128, 16)) { + /* log_info("b4"); */ + continue; + } + } + + break;//match one } - return false; + + if (i >= client_config->search_uuid_cnt) { + return; + } + + if (opt_handle_used_cnt >= OPT_HANDLE_MAX) { + log_info("opt_handle is full!!!\n"); + return; + } + + if ((t_uuid->opt_type & result_info->characteristic.properties) != t_uuid->opt_type) { + log_info("properties not match!!!\n"); + return; + } + + log_info("match one uuid\n"); + + opt_handle_t *opt_get = &opt_handle_table[opt_handle_used_cnt++]; + opt_get->value_handle = result_info->characteristic.value_handle; + opt_get->search_uuid = t_uuid; + + switch (t_uuid->opt_type) { + case ATT_PROPERTY_READ: + target_handle.read_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE_WITHOUT_RESPONSE: + target_handle.write_no_respond = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE: + target_handle.write_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_NOTIFY: + target_handle.notify_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_INDICATE: + target_handle.indicate_handle = result_info->characteristic.value_handle; + break; + + default: + break; + } + + client_event_report(CLI_EVENT_MATCH_UUID, opt_get, sizeof(opt_handle_t)); + } -/** - * @brief 解析广播数据包 - * @param adv_address 广播设备地址 - * @param data_length 广播数据长度 - * @param data 广播数据内容 - * @param rssi 信号强度 - * @return true:找到目标设备, false:未找到 - */ +//操作handle,完成 write ccc +static void do_operate_search_handle(void) +{ + u16 tmp_16; + u16 i, cur_opt_type; + opt_handle_t *opt_hdl_pt; + + log_info("opt_handle_used_cnt= %d\n", opt_handle_used_cnt); + + log_info("find target_handle:"); + log_info_hexdump(&target_handle, sizeof(target_hdl_t)); + + if (0 == opt_handle_used_cnt) { + goto opt_end; + } + + /* test_send_conn_update();//for test */ + + for (i = 0; i < opt_handle_used_cnt; i++) { + opt_hdl_pt = &opt_handle_table[i]; + cur_opt_type = opt_hdl_pt->search_uuid->opt_type; + switch ((u8)cur_opt_type) { + case ATT_PROPERTY_READ: + if (1) { + tmp_16 = 0x55A2;//fixed + log_info("read_long:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ_LONG); + } else { + tmp_16 = 0x55A1;//fixed + log_info("read:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ); + } + break; + + case ATT_PROPERTY_NOTIFY: + tmp_16 = 0x01;//fixed + log_info("write_ntf_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + break; + + case ATT_PROPERTY_INDICATE: + tmp_16 = 0x02;//fixed + log_info("write_ind_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + break; + + default: + break; + } + } + +opt_end: + set_ble_work_state(BLE_ST_SEARCH_COMPLETE); + +} + +//协议栈内部调用 +//return: 0--accept,1--reject +int l2cap_connection_update_request_just(u8 *packet, hci_con_handle_t handle) +{ + log_info("slave request conn_update:\n-interval_min= %d,\n-interval_max= %d,\n-latency= %d,\n-timeout= %d\n", + little_endian_read_16(packet, 0), little_endian_read_16(packet, 2), + little_endian_read_16(packet, 4), little_endian_read_16(packet, 6)); + return 0; + /* return 1; */ +} + +//协议栈内部调用 +void user_client_report_search_result(search_result_t *result_info) +{ + if (result_info == (void *) - 1) { + log_info("client_report_search_result finish!!!\n"); + do_operate_search_handle(); + client_event_report(CLI_EVENT_SEARCH_PROFILE_COMPLETE, 0, 0); + return; + } + + log_info("\n*** services, uuid16:%04x,index=%d ***\n", result_info->services.uuid16, result_info->service_index); + log_info("{charactc, uuid16:%04x,index=%d,handle:%04x~%04x,value_handle=%04x}\n", + result_info->characteristic.uuid16, result_info->characteristic_index, + result_info->characteristic.start_handle, result_info->characteristic.end_handle, + result_info->characteristic.value_handle + ); + + if (!result_info->services.uuid16) { + log_info("######services_uuid128:"); + log_info_hexdump(result_info->services.uuid128, 16); + } + + if (!result_info->characteristic.uuid16) { + log_info("######charact_uuid128:"); + log_info_hexdump(result_info->characteristic.uuid128, 16); + } + + check_target_uuid_match(result_info); +} + +#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) + +static u32 client_timer_handle = 0; +static u32 test_rx_data_count; +static u32 test_tx_data_count; + +static void client_timer_handler(void) +{ + if (!con_handle) { + test_rx_data_count = 0; + + test_tx_data_count = 0; + + return; + } + + if (test_rx_data_count) { + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); + /* log_info("\n-ble_data_rate: %d bps-\n", test_rx_data_count * 8); */ + log_info("%d bytes receive: %d.%02d KB/s \n", test_rx_data_count, test_rx_data_count / 1000, test_rx_data_count % 1000); + + test_rx_data_count = 0; + } + + if (test_tx_data_count) { + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); + log_info("%d bytes send: %d.%02d KB/s \n", test_tx_data_count, test_tx_data_count / 1000, test_tx_data_count % 1000); + + test_tx_data_count = 0; + } +} + +static void client_timer_start(void) +{ + client_timer_handle = sys_timer_add(NULL, client_timer_handler, 1000); +} + +#endif /* SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE */ + +static target_uuid_t *get_match_handle_target(u16 handle) +{ + for (int i = 0; i < opt_handle_used_cnt; i++) { + if (opt_handle_table[i].value_handle == handle) { + return opt_handle_table[i].search_uuid; + } + } + return NULL; +} + +//协议栈内部调用 +void user_client_report_data_callback(att_data_report_t *report_data) +{ + /* log_info("\n-report_data:type %02x,handle %04x,offset %d,len %d:",report_data->packet_type, */ + /* report_data->value_handle,report_data->value_offset,report_data->blob_length); */ + /* log_info_hexdump(report_data->blob,report_data->blob_length); */ + +#if SHOW_RX_DATA_RATE + test_rx_data_count += report_data->blob_length; +#endif /* SHOW_RX_DATA_RATE */ + + target_uuid_t *search_uuid = get_match_handle_target(report_data->value_handle); + + if (client_config->report_data_callback) { + client_config->report_data_callback(report_data, search_uuid); + return; + } + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION://notify +// log_info("\n-notify_rx(%d):",report_data->blob_length); + case GATT_EVENT_INDICATION://indicate + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long + break; + default: + break; + } +} + +// PRIMARY_SERVICE,AE30 +/* static const u16 test_services_uuid16 = 0xae30; */ + +// PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 +/* static const u8 test_services_uuid128[16] = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}; */ + +static void client_search_profile_start(void) +{ + opt_handle_used_cnt = 0; + memset(&target_handle, 0, sizeof(target_hdl_t)); + user_client_init(con_handle, search_ram_buffer, SEARCH_PROFILE_BUFSIZE); + if (client_config->search_uuid_cnt) { + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); + ble_op_search_profile_all(); + } else { + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); + user_client_set_search_complete(); + } +} + +//------------------------------------------------------------ static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rssi) { u8 i, lenght, ad_type; u8 *adv_data_pt; u8 find_remoter = 0; + /* u8 tmp_addr[6]; */ u32 tmp32; - // 1. 按地址匹配 if (check_device_is_match(CLI_CREAT_BY_ADDRESS, adv_address, 6)) { find_remoter = 1; } - // 2. 解析广播数据字段 adv_data_pt = data; for (i = 0; i < data_length;) { if (*adv_data_pt == 0) { + /* log_info("analyze end\n"); */ break; } lenght = *adv_data_pt++; + if (lenght >= data_length || (lenght + i) >= data_length) { + /*过滤非标准包格式*/ printf("!!!error_adv_packet:"); put_buf(data, data_length); break; @@ -699,29 +699,74 @@ static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rss i += (lenght + 1); switch (ad_type) { + case HCI_EIR_DATATYPE_FLAGS: + /* log_info("flags:%02x\n",adv_data_pt[0]); */ + break; + + case HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_128BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_128BIT_SERVICE_UUIDS: + /* log_info("service uuid:"); */ + /* log_info_hexdump(adv_data_pt, lenght - 1); */ + break; + case HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME: case HCI_EIR_DATATYPE_SHORTENED_LOCAL_NAME: tmp32 = adv_data_pt[lenght - 1]; - adv_data_pt[lenght - 1] = 0; - // log_info("remoter_name: %s,rssi:%d\n", adv_data_pt, rssi); + adv_data_pt[lenght - 1] = 0;; + log_info("remoter_name: %s,rssi:%d\n", adv_data_pt, rssi); log_info_hexdump(adv_address, 6); adv_data_pt[lenght - 1] = tmp32; + //------- +#if 0 //无线麦产线通过识别特殊字符串进行近距离连接测试 + if (0 == memcmp(adv_data_pt, SPECIFIC_STRING, strlen(SPECIFIC_STRING))) { + flag_specific_adv_name = 1; + flag_need_judge_rssi = 1; + } + if (flag_specific_sacn) { + flag_need_judge_rssi = 1; + } + if (flag_need_judge_rssi) { + flag_need_judge_rssi = 0; + if (rssi + TCFG_WIRELESS_RSSI < 0) { + printf("rssi no satisfy,break"); + break; + } else { + printf("rssi satisfy,RSSI = %d", rssi); + if (flag_specific_adv_name) { + find_remoter = 1; + break; + } + } + } + + flag_specific_adv_name = 0; +#endif #if SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN #if !WIRELESS_TOOL_BLE_NAME_EN #define TEST_BOX_BLE_NAME "W_MIC_01" #define TEST_BOX_BLE_NAME_LEN sizeof(TEST_BOX_BLE_NAME) + printf("TEST_BOX_BLE_NAME_LEN=%d", TEST_BOX_BLE_NAME_LEN); if (0 == memcmp(adv_data_pt, TEST_BOX_BLE_NAME, TEST_BOX_BLE_NAME_LEN)) { find_remoter = 1; + break; } #else - if (lenght == strlen((const char *)match_name) + 1) { + put_buf(match_name, strlen(match_name)); + if (lenght == strlen(match_name) + 1) { + printf("TEST_BOX_BLE_NAME_LEN=%d", TEST_BOX_BLE_NAME_LEN); if (0 == memcmp(adv_data_pt, match_name, lenght - 1)) { find_remoter = 1; + break; } } #endif #endif + /* log_info("target name:%s", client_config->compare_data); */ if (check_device_is_match(CLI_CREAT_BY_NAME, adv_data_pt, lenght - 1)) { find_remoter = 1; log_info("catch name ok\n"); @@ -735,13 +780,17 @@ static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rss } break; - // 其他类型可在此添加解析 + case HCI_EIR_DATATYPE_APPEARANCE_DATA: + /* log_info("get_class_type:%04x\n",little_endian_read_16(adv_data_pt,0)); */ + break; + default: + /* log_info("unknow ad_type:"); */ break; } if (find_remoter) { - break; // 找到后即可退出循环 + log_info_hexdump(adv_data_pt, lenght - 1); } adv_data_pt += (lenght - 1); } @@ -749,37 +798,45 @@ static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rss return find_remoter; } -/** - * @brief 报告并处理接收到的广播数据 - * @param report_pt 广播报告 - * @param len 报告长度 - */ static void client_report_adv_data(adv_report_t *report_pt, u16 len) { bool find_remoter; + /* log_info("event_type,addr_type: %x,%x; ",report_pt->event_type,report_pt->address_type); */ + /* log_info_hexdump(report_pt->address,6); */ + + /* log_info("adv_data_display:"); */ + /* log_info_hexdump(report_pt->data,report_pt->length); */ + +// log_info("rssi:%d\n",report_pt->rssi); #if WIRELESS_PAIR_BONDING - // 绑定模式下,优先匹配已绑定的设备 + if (conn_pair_info.pair_flag) { - if (report_pt->event_type != 1) { // 只处理可连接的广播 + if (report_pt->event_type != 1) { return; } + printf("report_add_type == %x", report_pt->address_type); + printf("conn_add_type == %x", conn_pair_info.peer_address_info[0]); + put_buf(report_pt->address, 6); + put_buf(&conn_pair_info.peer_address_info[1], 6); if (report_pt->address_type == conn_pair_info.peer_address_info[0] && 0 == memcmp(&conn_pair_info.peer_address_info[1], report_pt->address, 6)) { log_info("match bond_dev\n"); find_remoter = 1; + goto just_creat; } else { - return; // 不是绑定的设备,直接返回 + return; } - } else { - find_remoter = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); } + find_remoter = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); + +just_creat: + #else find_remoter = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); #endif if (find_remoter) { - // 强制搜索模式下,检查RSSI if (force_seach_onoff && force_seach_rssi > report_pt->rssi) { log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); return; @@ -789,80 +846,20 @@ static void client_report_adv_data(adv_report_t *report_pt, u16 len) log_info("\n*********create_connection***********\n"); log_info("***remote type %d,addr:", report_pt->address_type); log_info_hexdump(report_pt->address, 6); - - bt_ble_scan_enable(0, 0); // 停止扫描 - client_create_connect_api(report_pt->address, report_pt->address_type, 0); // 发起连接 + bt_ble_scan_enable(0, 0); + client_create_connect_api(report_pt->address, report_pt->address_type, 0); log_info("*create_finish\n"); } } -/** - * @brief 使能/禁止BLE扫描 - * @param priv 私有参数 (未使用) - * @param en 1:使能, 0:禁止 - * @return 0:成功, 非0:失败 - */ -static int bt_ble_scan_enable(void *priv, u32 en) -{ - ble_state_e next_state, cur_state; - if (!scan_ctrl_en && en) { - return APP_BLE_OPERATION_ERROR; // 如果总开关关闭,则不允许开启 - } - - next_state = en ? BLE_ST_SCAN : BLE_ST_IDLE; - cur_state = get_ble_work_state(); - - // 检查当前状态是否允许切换 - switch (cur_state) { - case BLE_ST_SCAN: - case BLE_ST_IDLE: - case BLE_ST_INIT_OK: - case BLE_ST_NULL: - case BLE_ST_DISCONN: - case BLE_ST_CONNECT_FAIL: - case BLE_ST_SEND_CREATE_CONN_CANNEL: - break; - default: - return APP_BLE_OPERATION_ERROR; - } - - if (cur_state == next_state) { - return APP_BLE_NO_ERROR; // 状态未改变 - } - - log_info("scan_en:%d\n", en); - set_ble_work_state(next_state); - - if (en) { - scanning_setup_init(); // 设置扫描参数 - } - ble_op_scan_enable2(en, 0); - - return APP_BLE_NO_ERROR; -} - -/** - * @brief 初始化扫描参数 - */ -static void scanning_setup_init(void) -{ - ble_op_set_scan_param(SET_SCAN_TYPE, SET_SCAN_INTERVAL, SET_SCAN_WINDOW); -} - -/** - * @brief 创建连接的底层实现 - * @param conn_addr 对端设备地址 - * @param addr_type 地址类型 - */ static void client_create_connection(u8 *conn_addr, u8 addr_type) { + struct create_conn_param_t *create_conn_par = scan_buffer; if (get_ble_work_state() == BLE_ST_CREATE_CONN) { log_info("already create conn!!!\n"); return; } - - struct create_conn_param_t *create_conn_par = (void *)scan_buffer; create_conn_par->conn_interval = SET_CONN_INTERVAL; create_conn_par->conn_latency = SET_CONN_LATENCY; create_conn_par->supervision_timeout = SET_CONN_TIMEOUT; @@ -874,19 +871,11 @@ static void client_create_connection(u8 *conn_addr, u8 addr_type) ble_op_create_connection(create_conn_par); } -/** - * @brief 创建连接的封装 (兼容旧接口) - * @param conn_addr 对端设备地址 - * @param addr_type 地址类型 - */ static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type) { client_create_connection(conn_addr, addr_type); } -/** - * @brief 取消正在创建的连接 - */ static void client_create_connection_cannel(void) { if (get_ble_work_state() == BLE_ST_CREATE_CONN) { @@ -895,11 +884,6 @@ static void client_create_connection_cannel(void) } } -/** - * @brief 断开当前BLE连接 - * @param priv 私有参数 (未使用) - * @return 0:成功, 非0:失败 - */ static int ble_disconnect(void *priv) { if (con_handle) { @@ -916,249 +900,139 @@ static int ble_disconnect(void *priv) } } -/** - * @brief 检查发现的特征是否与目标UUID匹配 - * @param result_info 搜索结果 - */ -static void check_target_uuid_match(search_result_t *result_info) +static void connection_update_complete_success(u8 *packet) { - u32 i; - target_uuid_t *t_uuid; + int con_handle, conn_interval, conn_latency, conn_timeout; - // 遍历预设的UUID表 - for (i = 0; i < client_config->search_uuid_cnt; i++) { - t_uuid = &client_config->search_uuid_table[i]; + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); - // 比较服务UUID - if (result_info->services.uuid16) { - if (result_info->services.uuid16 != t_uuid->services_uuid16) { - continue; - } - } else { - if (memcmp(result_info->services.uuid128, t_uuid->services_uuid128, 16)) { - continue; - } - } - - // 比较特征UUID - if (result_info->characteristic.uuid16) { - if (result_info->characteristic.uuid16 != t_uuid->characteristic_uuid16) { - continue; - } - } else { - if (memcmp(result_info->characteristic.uuid128, t_uuid->characteristic_uuid128, 16)) { - continue; - } - } - break; // 找到匹配 - } - - if (i >= client_config->search_uuid_cnt) { - return; // 未找到匹配 - } - - if (opt_handle_used_cnt >= OPT_HANDLE_MAX) { - log_info("opt_handle is full!!!\n"); - return; - } - - // 检查属性是否匹配 - if ((t_uuid->opt_type & result_info->characteristic.properties) != t_uuid->opt_type) { - log_info("properties not match!!!\n"); - return; - } - - log_info("match one uuid\n"); - - // 存储匹配到的句柄信息 - opt_handle_t *opt_get = &opt_handle_table[opt_handle_used_cnt++]; - opt_get->value_handle = result_info->characteristic.value_handle; - opt_get->search_uuid = t_uuid; - - switch (t_uuid->opt_type) { - case ATT_PROPERTY_READ: - target_handle.read_handle = result_info->characteristic.value_handle; - break; - case ATT_PROPERTY_WRITE_WITHOUT_RESPONSE: - target_handle.write_no_respond = result_info->characteristic.value_handle; - break; - case ATT_PROPERTY_WRITE: - target_handle.write_handle = result_info->characteristic.value_handle; - break; - case ATT_PROPERTY_NOTIFY: - target_handle.notify_handle = result_info->characteristic.value_handle; - break; - case ATT_PROPERTY_INDICATE: - target_handle.indicate_handle = result_info->characteristic.value_handle; - break; - default: - break; - } - - client_event_report(CLI_EVENT_MATCH_UUID, (u8 *)opt_get, sizeof(opt_handle_t)); + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); } -/** - * @brief 在Profile搜索完成后,执行后续操作(如使能Notify/Indicate) - */ -static void do_operate_search_handle(void) + +static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { - u16 tmp_16; - u16 i, cur_opt_type; - opt_handle_t *opt_hdl_pt; - - log_info("opt_handle_used_cnt= %d\n", opt_handle_used_cnt); - log_info("find target_handle:"); - log_info_hexdump(&target_handle, sizeof(target_hdl_t)); - - if (0 == opt_handle_used_cnt) { - goto opt_end; - } - - // 遍历所有匹配到的句柄,并执行相应操作 - for (i = 0; i < opt_handle_used_cnt; i++) { - opt_hdl_pt = &opt_handle_table[i]; - cur_opt_type = opt_hdl_pt->search_uuid->opt_type; - switch ((u8)cur_opt_type) { - case ATT_PROPERTY_NOTIFY: - tmp_16 = 0x01; // 使能Notify - log_info("write_ntf_ccc:%04x\n", opt_hdl_pt->value_handle); - client_operation_send(opt_hdl_pt->value_handle + 1, (u8 *)&tmp_16, 2, ATT_OP_WRITE); + sm_just_event_t *event = (void *)packet; + u32 tmp32; + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); break; - case ATT_PROPERTY_INDICATE: - tmp_16 = 0x02; // 使能Indicate - log_info("write_ind_ccc:%04x\n", opt_hdl_pt->value_handle); - client_operation_send(opt_hdl_pt->value_handle + 1, (u8 *)&tmp_16, 2, ATT_OP_WRITE); - break; - // 其他操作可在此添加 - default: + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + log_info_hexdump(packet, size); + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); break; } - } - -opt_end: - set_ble_work_state(BLE_ST_SEARCH_COMPLETE); -} - -/** - * @brief 协议栈上报搜索结果的回调,内部调用 - * @param result_info 搜索结果,为-1时表示搜索完成 - */ -void user_client_report_search_result(search_result_t *result_info) -{ - if (result_info == (void *) - 1) { - log_info("client_report_search_result finish!!!\n"); - do_operate_search_handle(); // 搜索完成,执行后续操作 - client_event_report(CLI_EVENT_SEARCH_PROFILE_COMPLETE, 0, 0); - return; - } - - log_info("\n*** services, uuid16:%04x,index=%d ***\n", result_info->services.uuid16, result_info->service_index); - log_info("{charactc, uuid16:%04x,index=%d,handle:%04x~%04x,value_handle=%04x}\n", - result_info->characteristic.uuid16, result_info->characteristic_index, - result_info->characteristic.start_handle, result_info->characteristic.end_handle, - result_info->characteristic.value_handle - ); - - check_target_uuid_match(result_info); // 检查是否是目标UUID -} - -/** - * @brief 协议栈上报对端设备数据的回调 - * @param report_data 数据报告 - */ -void user_client_report_data_callback(att_data_report_t *report_data) -{ -#if SHOW_RX_DATA_RATE - test_rx_data_count += report_data->blob_length; -#endif - - target_uuid_t *search_uuid = get_match_handle_target(report_data->value_handle); - - // 调用上层注册的回调函数 - if (client_config->report_data_callback) { - client_config->report_data_callback(report_data, search_uuid); - return; - } - - // 默认处理 - switch (report_data->packet_type) { - case GATT_EVENT_NOTIFICATION: - case GATT_EVENT_INDICATION: - case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT: - case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT: - break; - default: break; } } -/** - * @brief 开始搜索Profile - */ -static void client_search_profile_start(void) +static void can_send_now_wakeup(void) { - opt_handle_used_cnt = 0; - memset(&target_handle, 0, sizeof(target_hdl_t)); - user_client_init(con_handle, search_ram_buffer, SEARCH_PROFILE_BUFSIZE); - if (client_config->search_uuid_cnt) { - ble_op_search_profile_all(); // 搜索所有服务和特征 - } else { - user_client_set_search_complete(); // 如果没有指定UUID,直接结束 + /* putchar('E'); */ + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); } } -/** - * @brief 连接建立后,开始Profile相关流程 - * @param handle 连接句柄 - */ -static void client_profile_start(u16 handle) +const char *const phy_result[] = { + "None", + "1M", + "2M", + "Coded", +}; + +static void set_connection_data_length(u16 tx_octets, u16 tx_time) { - ble_op_att_send_init(handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_MTU_SIZE); + if (con_handle) { + ble_op_set_data_length(con_handle, tx_octets, tx_time); + } +} + +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == con_handle) { + return; + } + + u8 all_phys = 0; + u16 phy_options = 0; + + ble_op_set_ext_phy(con_handle, all_phys, tx_phy, rx_phy, phy_options); +} + +static void client_profile_start(u16 con_handle) +{ + ble_op_att_send_init(con_handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_MTU_SIZE); set_ble_work_state(BLE_ST_CONNECT); - + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); if (0 == client_config->security_en) { - // 如果不要求加密,直接开始搜索Profile + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); client_search_profile_start(); } } -/** - * @brief 协议栈事件总处理函数 - */ +/* LISTING_START(packetHandler): Packet Handler */ static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { int mtu; + u32 tmp; u8 status; switch (packet_type) { case HCI_EVENT_PACKET: switch (hci_event_packet_get_type(packet)) { + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); case ATT_EVENT_CAN_SEND_NOW: can_send_now_wakeup(); break; case HCI_EVENT_LE_META: switch (hci_event_le_meta_get_subevent_code(packet)) { + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: - case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: - status = packet[3]; + status = hci_subevent_le_enhanced_connection_complete_get_status(packet); if (status) { log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", status); set_ble_work_state(BLE_ST_DISCONN); break; } + con_handle = hci_subevent_le_enhanced_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE : 0x%0x\n", con_handle); + log_info("conn_interval = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_interval(packet)); + log_info("conn_latency = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_latency(packet)); + log_info("conn_timeout = %d\n", hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(packet)); + client_profile_start(con_handle); + break; + + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: + if (packet[3]) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", packet[3]); + set_ble_work_state(BLE_ST_DISCONN); + break; + } con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE : %0x\n", con_handle); connection_update_complete_success(packet + 8); client_profile_start(con_handle); client_event_report(CLI_EVENT_CONNECTED, packet, size); - #if WIRELESS_PAIR_BONDING - // 绑定模式下,保存地址信息 memcpy(cur_peer_address_info, &packet[7], 7); conn_pair_info.pair_flag = 1; + printf("pair_flag == %d", conn_pair_info.pair_flag); + put_buf(cur_peer_address_info, 7); memcpy(&conn_pair_info.peer_address_info, cur_peer_address_info, 7); conn_pair_info.head_tag = BLE_VM_HEAD_TAG; conn_pair_info.tail_tag = BLE_VM_TAIL_TAG; @@ -1176,7 +1050,9 @@ static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *p case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: log_info("APP HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE\n"); connection_update_complete_success(packet); + client_event_report(CLI_EVENT_CONNECTION_UPDATE, packet, size); + break; case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: @@ -1188,6 +1064,7 @@ static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *p log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); break; + } break; @@ -1198,14 +1075,14 @@ static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *p set_ble_work_state(BLE_ST_DISCONN); client_event_report(CLI_EVENT_DISCONNECT, packet, size); - // 断线后自动重连或重新扫描 + //auto to do #if !WIRELESS_PAIR_BONDING if (conn_pair_info.pair_flag) { - client_create_connect_api(0, 0, 1); // 尝试重连 + client_create_connect_api(0, 0, 1); } else #endif { - bt_ble_scan_enable(0, 1); // 重新扫描 + bt_ble_scan_enable(0, 1); } break; @@ -1215,14 +1092,23 @@ static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *p ble_op_att_set_send_mtu(mtu); break; + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp: %02x\n", tmp); + break; + case GAP_EVENT_ADVERTISING_REPORT: + /* putchar('@'); */ client_report_adv_data((void *)&packet[2], packet[1]); break; case HCI_EVENT_ENCRYPTION_CHANGE: log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); if (client_config->security_en) { - // 加密完成后,开始搜索Profile client_search_profile_start(); } break; @@ -1231,44 +1117,7 @@ static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *p } } -/** - * @brief SM (Security Manager) 事件处理 - */ -static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) -{ - sm_just_event_t *event = (void *)packet; - u32 tmp32; - switch (packet_type) { - case HCI_EVENT_PACKET: - switch (hci_event_packet_get_type(packet)) { - case SM_EVENT_JUST_WORKS_REQUEST: - sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); - log_info("Just Works Confirmed.\n"); - break; - case SM_EVENT_PASSKEY_DISPLAY_NUMBER: - memcpy(&tmp32, event->data, 4); - log_info("Passkey display: %06u.\n", tmp32); - break; - } - break; - } -} -/** - * @brief 协议栈通知可以发送数据时的唤醒函数 - */ -static void can_send_now_wakeup(void) -{ - if (ble_resume_send_wakeup) { - ble_resume_send_wakeup(); - } -} - -/** - * @brief 获取ATT发送缓冲区剩余有效长度 - * @param priv 私有参数 (未使用) - * @return 剩余长度 - */ static int get_buffer_vaild_len(void *priv) { u32 vaild_len = 0; @@ -1276,25 +1125,21 @@ static int get_buffer_vaild_len(void *priv) return vaild_len; } -/** - * @brief 通用ATT操作发送函数 - * @param handle 特征值句柄 - * @param data 数据指针 - * @param len 数据长度 - * @param att_op_type ATT操作类型 - * @return 0:成功, 非0:失败 - */ static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type) { int ret = APP_BLE_NO_ERROR; if (!con_handle) { return APP_BLE_OPERATION_ERROR; } + if (!handle) { log_info("handle is null\n"); return APP_BLE_OPERATION_ERROR; } + + if (get_buffer_vaild_len(0) < len) { + /* log_info("opt_buff_full!!!\n"); */ return APP_BLE_BUFF_FULL; } @@ -1304,109 +1149,58 @@ static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type) } else { #if SHOW_TX_DATA_RATE test_tx_data_count += len; -#endif +#endif /* SHOW_TX_DATA_RATE */ } + return ret; } -/** - * @brief 发送写请求 (Write Request) - */ + +//----------------------------------------------- static int client_write_send(void *priv, u8 *data, u16 len) { return client_operation_send(target_handle.write_handle, data, len, ATT_OP_WRITE); } -/** - * @brief 发送无响应写请求 (Write Command) - */ static int client_write_without_respond_send(void *priv, u8 *data, u16 len) { return client_operation_send(target_handle.write_no_respond, data, len, ATT_OP_WRITE_WITHOUT_RESPOND); } -/** - * @brief 发送读请求 (Read Request) - */ static int client_read_value_send(void *priv) { u16 tmp_flag = 0x55A1; return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ); } -/** - * @brief 发送长读请求 (Read Long Request) - */ static int client_read_long_value_send(void *priv) { u16 tmp_flag = 0x55A2; return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ_LONG); } -/** - * @brief 注册数据发送恢复唤醒回调 - */ -static int client_regiest_wakeup_send(void *priv, void *cbk) + +//扫描数设置 +static void scanning_setup_init(void) { - ble_resume_send_wakeup = cbk; - return APP_BLE_NO_ERROR; + ble_op_set_scan_param(SET_SCAN_TYPE, SET_SCAN_INTERVAL, SET_SCAN_WINDOW); } -/** - * @brief 注册应用层数据接收回调 - */ -static int client_regiest_recieve_cbk(void *priv, void *cbk) +static int bt_ble_scan_enable(void *priv, u32 en) { - channel_priv = (u32)priv; - app_recieve_callback = cbk; - return APP_BLE_NO_ERROR; -} + ble_state_e next_state, cur_state; -/** - * @brief 注册应用层状态变化回调 - */ -static int client_regiest_state_cbk(void *priv, void *cbk) -{ - channel_priv = (u32)priv; - app_ble_state_callback = cbk; - return APP_BLE_NO_ERROR; -} - -/** - * @brief 重新配置客户端搜索参数 - */ -static int client_init_config(void *priv, const client_conn_cfg_t *cfg) -{ - log_info("client_init_config\n"); - client_config = (client_conn_cfg_t *)cfg; // 重置配置 - return APP_BLE_NO_ERROR; -} - -/** - * @brief 设置强制搜索模式(根据RSSI过滤) - */ -static int client_force_search(u8 onoff, s8 rssi) -{ - force_seach_rssi = rssi; - if (force_seach_onoff != onoff) { - force_seach_onoff = onoff; - if (get_ble_work_state() == BLE_ST_CREATE_CONN) { - client_create_connection_cannel(); - } + if (!scan_ctrl_en && en) { + return APP_BLE_OPERATION_ERROR; } - return 0; -} -/** - * @brief 创建连接的API接口 - * @param addr 地址 (mode=1时可为NULL) - * @param addr_type 地址类型 (mode=1时可忽略) - * @param mode 0:按地址连接, 1:按配对信息连接 - * @return 0:成功, 非0:失败 - */ -static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) -{ - u8 cur_state = get_ble_work_state(); + if (en) { + next_state = BLE_ST_SCAN; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(); switch (cur_state) { case BLE_ST_SCAN: case BLE_ST_IDLE: @@ -1418,6 +1212,84 @@ static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) break; default: return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; + } + + + log_info("scan_en:%d\n", en); + set_ble_work_state(next_state); + + if (en) { + scanning_setup_init(); + } + ble_op_scan_enable2(en, 0); + + return APP_BLE_NO_ERROR; +} + +static int client_regiest_wakeup_send(void *priv, void *cbk) +{ + /* att_regist_wakeup_send(cbk); */ + return APP_BLE_NO_ERROR; +} + +static int client_regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int client_regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +//该接口重新配置搜索的配置项 +static int client_init_config(void *priv, const client_conn_cfg_t *cfg) +{ + log_info("client_init_config\n"); + client_config = cfg;//reset config + return APP_BLE_NO_ERROR; +} + +//可配置进入强制搜索方式连接,更加信号强度过滤设备 +static int client_force_search(u8 onoff, s8 rssi) +{ + force_seach_rssi = rssi; + if (force_seach_onoff != onoff) { + + force_seach_onoff = onoff; + //强制搜索前后,关创建监听 + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + } + } + return 0; +} + +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) +{ + u8 cur_state = get_ble_work_state(); + + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; } if (cur_state == BLE_ST_SCAN) { @@ -1425,17 +1297,22 @@ static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) bt_ble_scan_enable(0, 0); } - if (mode == 1) { // 按配对信息连接 + //pair mode + if (mode == 1) { if (conn_pair_info.pair_flag) { - log_info("pair to creat!\n"); - log_info_hexdump(conn_pair_info.peer_address_info, 7); - bt_ble_create_connection(&conn_pair_info.peer_address_info[1], conn_pair_info.peer_address_info[0]); - return 0; + if (conn_pair_info.pair_flag) { + //有配对,跳过搜索,直接创建init_creat + log_info("pair to creat!\n"); + log_info_hexdump(conn_pair_info.peer_address_info, 7); + bt_ble_create_connection(&conn_pair_info.peer_address_info[1], conn_pair_info.peer_address_info[0]); + return 0; + } + } else { log_info("no pair to creat!\n"); return APP_BLE_OPERATION_ERROR; } - } else { // 按地址连接 + } else { log_info("addr to creat!\n"); log_info_hexdump(addr, 7); bt_ble_create_connection(addr, addr_type); @@ -1443,9 +1320,6 @@ static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) return 0; } -/** - * @brief 取消连接的API接口 - */ static int client_create_cannel_api(void) { if (get_ble_work_state() == BLE_ST_CREATE_CONN) { @@ -1455,27 +1329,92 @@ static int client_create_cannel_api(void) return 1; } -/** - * @brief 重设Passkey的回调函数 - */ +static const struct ble_client_operation_t client_operation = { + .scan_enable = bt_ble_scan_enable, + .disconnect = ble_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .write_data = (void *)client_write_without_respond_send, + .read_do = (void *)client_read_value_send, + .regist_wakeup_send = client_regiest_wakeup_send, + .regist_recieve_cbk = client_regiest_recieve_cbk, + .regist_state_cbk = client_regiest_state_cbk, + .init_config = client_init_config, + .opt_comm_send = client_operation_send, + .set_force_search = client_force_search, + .create_connect = client_create_connect_api, + .create_connect_cannel = client_create_cannel_api, + .get_work_state = get_ble_work_state, +}; + +struct ble_client_operation_t *ble_get_client_operation_table(void) +{ + return &client_operation; +} + +#define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey +//重设passkey回调函数,在这里可以重新设置passkey +//passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 static void reset_passkey_cb(u32 *key) { #if 1 - u32 newkey = rand32(); + u32 newkey = rand32();//获取随机数 + newkey &= 0xfffff; if (newkey > 999999) { - newkey = newkey - 999999; + newkey = newkey - 999999; //不能大于999999 } - *key = newkey; + *key = newkey; //小于或等于六位数 log_info("set new_key= %06u\n", *key); #else - *key = 123456; // for debug + *key = 123456; //for debug #endif } -/** - * @brief 初始化设备绑定相关配置 - */ +#if 0 +//协议栈内部调用 +extern void sm_set_master_request_pair(int enable); +static void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) +{ + //setup SM: Display only + sm_init(); + sm_set_io_capabilities(io_type); + sm_set_authentication_requirements(auth_req); + sm_set_encryption_key_size_range(min_key_size, 16); + sm_set_master_request_pair(security_en); + sm_event_callback_set(&cbk_sm_packet_handler); + + if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { + reset_PK_cb_register(reset_passkey_cb); + } +} +#endif + + +//协议栈内部调用 +void ble_profile_init(void) +{ + log_info("ble profile init\n"); + le_device_db_init(); + ble_stack_gatt_role(1); + +//#if PASSKEY_ENTER_ENABLE +// ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, client_config->security_en); +//#else +// ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, client_config->security_en); +//#endif + + /* setup ATT client */ + gatt_client_init(); + gatt_client_register_packet_handler(cbk_packet_handler); + + // register for HCI events + hci_event_callback_set(&cbk_packet_handler); + le_l2cap_register_packet_handler(&cbk_packet_handler); + + ble_vendor_set_default_att_mtu(ATT_LOCAL_MTU_SIZE); +} + + static void device_bonding_init(void) { int i; @@ -1491,205 +1430,163 @@ static void device_bonding_init(void) } } if (!cfg_bonding) { - clear_bonding_info(); // 如果配置中没有需要绑定的设备,则清除本地绑定信息 + clear_bonding_info(); } } -/** - * @brief 查询客户端是否空闲(用于低功耗) - */ static u8 client_idle_query(void) { - // 返回0表示不空闲,防止系统进入深眠 return 0; } -// 注册低功耗目标 REGISTER_LP_TARGET(client_user_target) = { .name = "client_user_demo", .is_idle = client_idle_query, }; -/** - * @brief 连接更新成功事件处理 - */ -static void connection_update_complete_success(u8 *packet) -{ - int conn_interval, conn_latency, conn_timeout; - conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); - conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); - conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); - log_info("conn_interval = %d\n", conn_interval); - log_info("conn_latency = %d\n", conn_latency); - log_info("conn_timeout = %d\n", conn_timeout); -} -/** - * @brief L2CAP连接参数更新请求处理 - */ -int l2cap_connection_update_request_just(u8 *packet, hci_con_handle_t handle) -{ - log_info("slave request conn_update:\n-interval_min= %d,\n-interval_max= %d,\n-latency= %d,\n-timeout= %d\n", - little_endian_read_16(packet, 0), little_endian_read_16(packet, 2), - little_endian_read_16(packet, 4), little_endian_read_16(packet, 6)); - return 0; // 接受请求 -} -/** - * @brief 根据句柄查找对应的目标UUID信息 - */ -static target_uuid_t *get_match_handle_target(u16 handle) -{ - for (int i = 0; i < opt_handle_used_cnt; i++) { - if (opt_handle_table[i].value_handle == handle) { - return opt_handle_table[i].search_uuid; - } - } - return NULL; -} -/** - * @brief 设置数据包长度 - */ -static void set_connection_data_length(u16 tx_octets, u16 tx_time) +void bt_ble_init(void) { - if (con_handle) { - ble_op_set_data_length(con_handle, tx_octets, tx_time); - } -} + log_info("***** ble_init******\n"); +#if WIRELESS_TOOL_BLE_NAME_EN + u8 *config_name; + u8 config_name_len; +#endif -/** - * @brief 设置PHY速率 - */ -static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) -{ - if (0 == con_handle) { - return; - } - u8 all_phys = 0; - u16 phy_options = 0; - ble_op_set_ext_phy(con_handle, all_phys, tx_phy, rx_phy, phy_options); -} +#if (WIRELESS_24G_ENABLE) + rf_set_24g_hackable_coded(WIRELESS_24G_CODE_ID); +#endif +#if WIRELESS_TOOL_BLE_NAME_EN +#if 1 //使用配置工具的蓝牙名 + extern const char *bt_get_local_name(); + config_name = (u8 *)(bt_get_local_name()); + config_name_len = strlen(config_name) + 1; + put_buf(config_name, config_name_len); + printf("len = %d", config_name_len); +#else + config_name = TEST_BOX_BLE_NAME; + config_name_len = sizeof(TEST_BOX_BLE_NAME); +#endif + match_name = (u8 *)zalloc(config_name_len); + memcpy(match_name, config_name, config_name_len); + printf("match_name"); + put_buf(match_name, config_name_len); + printf("%s", match_name); +#endif + // if (0 == memcmp(match_name, SPECIFIC_STRING, strlen(SPECIFIC_STRING))) { + // match_name = &match_name[strlen(SPECIFIC_STRING)]; + // printf("specific scan%s", match_name); + // flag_specific_sacn = 1; + + // } + + set_ble_work_state(BLE_ST_INIT_OK); + conn_pair_vm_do(&conn_pair_info, 0); + +#if !WIRELESS_PAIR_BONDING + device_bonding_init(); +#endif + ble_module_enable(1); + extern void wifi_detect_set_master_first(u8 first); +#if TCFG_WIFI_DETECT_ENABLE +#if TCFG_WIFI_DETCET_PRIOR + wifi_detect_set_master_first(0); +#else + wifi_detect_set_master_first(1); +#endif +#endif #if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) -/** - * @brief 数据速率统计定时器处理函数 - */ -static void client_timer_handler(void) + client_timer_start(); +#endif /* SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE */ +} + +void bt_ble_exit(void) { - if (!con_handle) { - test_rx_data_count = 0; - test_tx_data_count = 0; + log_info("***** ble_exit******\n"); +} + +void ble_app_disconnect(void) +{ + ble_disconnect(NULL); +} +//统一接口,关闭模块 +void bt_ble_adv_enable(u8 enable) +{ + ble_module_enable(enable); +} + +//模块开关 +void ble_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + if (en) { + scan_ctrl_en = 1; + bt_ble_scan_enable(0, 1); + } else { + if (con_handle) { + scan_ctrl_en = 0; + ble_disconnect(NULL); + } else { + bt_ble_scan_enable(0, 0); + scan_ctrl_en = 0; + } + } + +} + +void client_send_conn_param_update(void) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[send_param_index];//for test + log_info("client update param:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (con_handle) { + ble_op_conn_param_update(con_handle, param); + } +} + + + +//---------------------------------------------------------------------------------- +//lmx +void rcsp_adv_fill_mac_addr(u8 *mac_addr_buf) +{ +#if (MUTIl_CHARGING_BOX_EN) + u8 *mac_addr = get_chargebox_adv_addr(); + if (mac_addr) { + swapX(mac_addr, mac_addr_buf, 6); + } + + /* printf("mac_addr:"); */ + /* printf_buf(mac_addr_buf, 6); */ + +#else + swapX(bt_get_mac_addr(), mac_addr_buf, 6); +#endif +} + +/** + * @brief 发送数据给server + * + * @param data + * @param length + */ +void g_send_data_to_ble_server(const u8* data, u16 length){ + // 检查数据长度是否有效 + if (length == 0 || length > 512) { + printf("Error: Data length %d is out of range (1-512)\n", length); return; } - if (test_rx_data_count) { - log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); - log_info("%d bytes receive: %d.%02d KB/s \n", test_rx_data_count, test_rx_data_count / 1000, test_rx_data_count % 1000); - test_rx_data_count = 0; - } - if (test_tx_data_count) { - log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); - log_info("%d bytes send: %d.%02d KB/s \n", test_tx_data_count, test_tx_data_count / 1000, test_tx_data_count % 1000); - test_tx_data_count = 0; + + int ret = client_operation_send(default_client_write_handle, data, length, ATT_OP_WRITE_WITHOUT_RESPOND); + if(ret == 0){ + printf("success: send data to server\n"); + return; } + printf("error: send data to server\n"); } -/** - * @brief 启动数据速率统计定时器 - */ -static void client_timer_start(void) -{ - client_timer_handle = sys_timer_add(NULL, client_timer_handler, 1000); -} #endif -#if 1 //default -/** - * @brief 默认示例的数据上报处理 - */ -static void default_report_data_deal(att_data_report_t *report_data, target_uuid_t *search_uuid) -{ - log_info("report_data:%02x,%02x,%d,len(%d)", report_data->packet_type, - report_data->value_handle, report_data->value_offset, report_data->blob_length); - log_info_hexdump(report_data->blob, report_data->blob_length); - switch (report_data->packet_type) { - case GATT_EVENT_NOTIFICATION: - case GATT_EVENT_INDICATION: - case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT: - case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT: - break; - default: - break; - } -} - -/** - * @brief 默认示例的定时写数据函数 - */ -static void default_test_write(void) -{ - static u32 count = 0; - count++; - int ret = client_operation_send(default_client_write_handle, (u8 *)&count, 16, ATT_OP_WRITE_WITHOUT_RESPOND); - log_info("test_write:%x", ret); -} - -/** - * @brief 默认示例的事件回调处理 - */ -static void default_event_callback(le_client_event_e event, u8 *packet, int size) -{ - switch (event) { - case CLI_EVENT_MATCH_DEV: { - client_match_cfg_t *match_dev = (void *)packet; - log_info("match_name:%s\n", match_dev->compare_data); - } - break; - - case CLI_EVENT_MATCH_UUID: { - opt_handle_t *opt_hdl = (void *)packet; - if (opt_hdl->search_uuid == &default_search_uuid_table[0]) { - default_client_write_handle = opt_hdl->value_handle; - log_info("match_uuid22\n"); - } - } - break; - - case CLI_EVENT_SEARCH_PROFILE_COMPLETE: - log_info("CLI_EVENT_SEARCH_PROFILE_COMPLETE\n"); - if ((!test_client_timer) && default_client_write_handle) { - log_info("test timer_add\n"); - // test_client_timer = sys_hi_timer_add(0, default_test_write, 500); //xtell - extern void test_func_main(void); - test_func_main(); - } - break; - - case CLI_EVENT_CONNECTED: - connect_state = 1; - log_info("<<<<<<<<<< BLE Connection Successful! >>>>>>>>>>\n"); - - break; - - case CLI_EVENT_DISCONNECT: - connect_state = 0; - if (test_client_timer) { - sys_timeout_del(test_client_timer); - test_client_timer = 0; - } - default_client_write_handle = 0; - break; - - default: - break; - } -} -#endif - -///////////////////////////////////////////////////////////////////////////////// - - - - -#endif /* (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_WIRELESS_MIC_CLIENT) */ diff --git a/apps/earphone/xtell_remote_control/ble_handler/example/client_handler.c.hide b/apps/earphone/xtell_remote_control/ble_handler/example/client_handler.c.hide new file mode 100644 index 0000000..1981f72 --- /dev/null +++ b/apps/earphone/xtell_remote_control/ble_handler/example/client_handler.c.hide @@ -0,0 +1,1731 @@ +/** + ************************************************************************************************** + * 设备扫描与发现 + * 创建和管理连接 + * 服务和特征的发现 + * 数据读写操作 + * 连接状态管理和事件处理 + * 配对与绑定 + ************************************************************************************************** + */ + +/* + ************************************************************************************************** + * 头文件包含 + ************************************************************************************************** + */ +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" + +#include "le_client_demo.h" +#include "le_common.h" +#include "ble_user.h" +#include "../nvs/nvs.h" +#if (BLE_WIRELESS_CLIENT_EN == 1) // 作为主设备主动去连接其他蓝牙 + +/* + ************************************************************************************************** + * 宏定义 + ************************************************************************************************** + */ + +// 功能开关宏 +#define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 0 // 是否支持测试盒BLE主设备测试 +#define SHOW_RX_DATA_RATE 1 // 是否显示接收数据速率 +#define SHOW_TX_DATA_RATE 1 // 是否显示发送数据速率 +#define XTELL_DEBUG 1 + +// 日志打印宏 +#if XTELL_DEBUG == 1 +#define log_info(x, ...) printf("[LE_CLIENT]" x " ", ## __VA_ARGS__) // 带前缀的信息打印 +#define log_info_hexdump put_buf // 16进制数据打印 +#else +#define log_info(...) // 禁用信息打印 +#define log_info_hexdump(...) // 禁用16进制数据打印 +#endif + +// ATT 协议相关宏 +#define ATT_LOCAL_MTU_SIZE (517) // 本地ATT最大传输单元(MTU)大小,需>=20 +#define ATT_SEND_CBUF_SIZE (200) // ATT发送数据循环缓冲区大小,需>=20 +#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_MTU_SIZE + ATT_SEND_CBUF_SIZE) // 总ATT RAM缓冲区大小 + +// 搜索Profile缓冲区宏 +#define SEARCH_PROFILE_BUFSIZE (512) // 搜索Profile时使用的RAM缓冲区大小 +#define scan_buffer search_ram_buffer // 将scan_buffer定义为search_ram_buffer的别名 + +// BLE扫描参数宏 (单位: 0.625ms) +#define SET_SCAN_TYPE SCAN_ACTIVE // 扫描类型:主动扫描 +#define SET_SCAN_INTERVAL 320 // 扫描间隔 (e.g., 320 * 0.625ms = 200ms) +#define SET_SCAN_WINDOW 70 // 扫描窗口 (e.g., 70 * 0.625ms = 43.75ms) + +// BLE连接参数宏 +#define SET_CONN_INTERVAL 3 // 连接间隔 (单位: 1.25ms, e.g., 3 * 1.25ms = 3.75ms) +#define SET_CONN_LATENCY 0 // 连接延迟 (单位: conn_interval) +#define SET_CONN_TIMEOUT 400 // 连接超时 (单位: 10ms, e.g., 400 * 10ms = 4000ms) + +// 测试盒蓝牙名称宏 +#if WIRELESS_TOOL_BLE_NAME_EN +#define TEST_BOX_BLE_NAME "W_MIC_01" // 测试盒默认蓝牙名称 +#define TEST_BOX_BLE_NAME_LEN (sizeof(TEST_BOX_BLE_NAME)-1) // 名称长度(不含结束符) +#endif + +// VM(非易失性存储)存储配对信息标签 +#define BLE_VM_HEAD_TAG (0xB95C) // VM数据头标签 +#define BLE_VM_TAIL_TAG (0x5CB9) // VM数据尾标签 + +// Passkey输入功能开关 +#define PASSKEY_ENTER_ENABLE 0 // 是否启用输入Passkey进行配对 + +/* + ************************************************************************************************** + * 类型定义 + ************************************************************************************************** + */ + +/** + * @brief 配对信息结构体,用于存储到VM + */ +struct pair_info_t { + u16 head_tag; // 数据头标签,用于校验 + u8 pair_flag; // 配对标志,1表示已配对 + u8 peer_address_info[7]; // 对端设备地址信息 (1字节类型 + 6字节地址) + u16 tail_tag; // 数据尾标签,用于校验 +}; + +/** + * @brief 目标设备特征句柄集合 + */ +typedef struct { + uint16_t read_handle; // 读特征句柄 + uint16_t read_long_handle; // 长读特征句柄 + uint16_t write_handle; // 写特征句柄 + uint16_t write_no_respond; // 无响应写特征句柄 + uint16_t notify_handle; // 通知特征句柄 + uint16_t indicate_handle; // 指示特征句柄 +} target_hdl_t; + + +/* + ************************************************************************************************** + * 静态函数声明 + ************************************************************************************************** + */ +// 状态管理 +static void set_ble_work_state(ble_state_e state); +static ble_state_e get_ble_work_state(void); + +// 扫描与连接 +static int bt_ble_scan_enable(void *priv, u32 en); +static void scanning_setup_init(void); +static void client_report_adv_data(adv_report_t *report_pt, u16 len); +static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rssi); +static bool check_device_is_match(u8 info_type, u8 *data, int size); +static void client_create_connection(u8 *conn_addr, u8 addr_type); +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type); +static void client_create_connection_cannel(void); +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode); +static int client_create_cannel_api(void); +static int ble_disconnect(void *priv); + +// Profile 发现与操作 +static void client_search_profile_start(void); +static void user_client_report_search_result(search_result_t *result_info); +static void check_target_uuid_match(search_result_t *result_info); +static void do_operate_search_handle(void); +static target_uuid_t *get_match_handle_target(u16 handle); + +// 数据收发 +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type); +static int client_write_send(void *priv, u8 *data, u16 len); +static int client_write_without_respond_send(void *priv, u8 *data, u16 len); +static int client_read_value_send(void *priv); +static int client_read_long_value_send(void *priv); +static int get_buffer_vaild_len(void *priv); +static void can_send_now_wakeup(void); + +// 事件与回调处理 +static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +static void user_client_report_data_callback(att_data_report_t *report_data); +static void client_event_report(le_client_event_e event, u8 *packet, int size); +static void connection_update_complete_success(u8 *packet); +static int l2cap_connection_update_request_just(u8 *packet, hci_con_handle_t handle); + +// 配对与绑定 +static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag); +static void device_bonding_init(void); +static void reset_passkey_cb(u32 *key); + +// 初始化与配置 +static int client_init_config(void *priv, const client_conn_cfg_t *cfg); +static int client_regiest_wakeup_send(void *priv, void *cbk); +static int client_regiest_recieve_cbk(void *priv, void *cbk); +static int client_regiest_state_cbk(void *priv, void *cbk); + +// 其他辅助函数 +static int client_force_search(u8 onoff, s8 rssi); +static void set_connection_data_length(u16 tx_octets, u16 tx_time); +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy); +static u8 client_idle_query(void); + +// 默认示例相关 +#if 1 //default +static void default_report_data_deal(att_data_report_t *report_data, target_uuid_t *search_uuid); +static void default_test_write(void); +static void default_event_callback(le_client_event_e event, u8 *packet, int size); +#endif + +// 数据速率统计 +#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) +static void client_timer_handler(void); +static void client_timer_start(void); +#endif + +/* + ************************************************************************************************** + * 全局/静态变量定义 + ************************************************************************************************** + */ +static u8 connect_state = 0; //0:连接断开; 1:连接成功 + +// --- 缓冲区 --- +static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); // ATT协议栈RAM缓冲区 +static u8 search_ram_buffer[SEARCH_PROFILE_BUFSIZE] __attribute__((aligned(4))); // Profile搜索RAM缓冲区 + +// --- 状态变量 --- +static u8 scan_ctrl_en; // 扫描总开关,由上层应用控制 +static u8 ble_work_state = 0; // BLE工作状态机 +static hci_con_handle_t con_handle; // 当前连接句柄 +static u8 force_seach_onoff = 0; // 强制搜索开关(根据RSSI过滤) +static s8 force_seach_rssi = -127; // 强制搜索的RSSI阈值 +static u8 cur_peer_address_info[7]; // 当前连接的对端设备地址信息 +static u8 flag_specific_adv_name = 0; // 产测用:是否发现特定广播名称的标志 +static u8 flag_need_judge_rssi = 0; // 产测用:是否需要判断RSSI的标志 +static u8 flag_specific_sacn = 0; // 产测用:是否为特定扫描的标志 + +// --- 回调函数指针 --- +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; // 应用层数据接收回调 +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; // 应用层状态变化回调 +static void (*ble_resume_send_wakeup)(void) = NULL; // 数据发送恢复唤醒回调 +static u32 channel_priv; // 回调函数私有参数 + +// --- 配对与绑定信息 --- +static struct pair_info_t conn_pair_info; // 连接配对信息 +static u8 pair_bond_enable = 0; // 本次连接是否需要绑定 + +// --- Profile句柄管理 --- +static target_hdl_t target_handle; // 存储发现的目标特征句柄 +static opt_handle_t opt_handle_table[OPT_HANDLE_MAX]; // 存储所有匹配到的特征操作句柄 +static u8 opt_handle_used_cnt; // 已使用的操作句柄数量 + +// --- 默认示例配置 --- +#if 1 //default +// 默认搜索的UUID表 +static const target_uuid_t default_search_uuid_table[] = { + // 服务UUID: 0xae30, 特征UUID: 0xae01, 操作类型: 无响应写 + { + .services_uuid16 =0xae30, + .characteristic_uuid16 = 0xae01, + .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, + }, + // 服务UUID: 0xae30, 特征UUID: 0xae02, 操作类型: 通知 + { + .services_uuid16 = 0xae30, + .characteristic_uuid16 = 0xae02, + .opt_type = ATT_PROPERTY_NOTIFY, + }, +}; + +// 默认匹配的设备名称 +static u8 test_remoter_name1[] = "CM-22222"; +// 默认匹配规则 +static client_match_cfg_t match_dev01 = { + .create_conn_mode = BIT(CLI_CREAT_BY_NAME), // 通过名称匹配 + .compare_data_len = sizeof(test_remoter_name1) - 1, // 名称长度 + .compare_data = test_remoter_name1, // 名称数据 + .bonding_flag = 0, // 不进行绑定 +}; + +// 默认客户端连接配置 +static client_conn_cfg_t client_conn_config_default = { + .match_dev_cfg[0] = &match_dev01, + .match_dev_cfg[1] = NULL, + .match_dev_cfg[2] = NULL, + .report_data_callback = default_report_data_deal, + .search_uuid_cnt = (sizeof(default_search_uuid_table) / sizeof(target_uuid_t)), + .search_uuid_table = default_search_uuid_table, + .security_en = 0, //不加密 + .event_callback = default_event_callback, +}; + +static u16 default_client_write_handle; // 默认示例的写句柄 +static u16 test_client_timer = 0; // 默认示例的定时器 +#endif + +// --- 全局配置指针 --- +static client_conn_cfg_t *client_config = (void *) &client_conn_config_default; // 指向当前客户端连接配置 + +// --- 连接更新参数 --- +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 0, 600}, + {12, 28, 0, 600}, + {8, 20, 0, 600}, + {50, 60, 0, 600}, +}; +static u8 send_param_index = 3; // 当前使用的连接参数索引 + +// --- 数据速率统计 --- +#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) +static u32 client_timer_handle = 0; // 速率统计定时器 +static u32 test_rx_data_count; // 接收字节计数 +static u32 test_tx_data_count; // 发送字节计数 +#endif + +// --- 其他 --- +#if WIRELESS_TOOL_BLE_NAME_EN +static u8 *match_name; // 动态配置的匹配名称 +#endif + +static const char *const phy_result[] = { // PHY速率类型字符串 + "None", "1M", "2M", "Coded", +}; + +// --- 接口操作结构体 --- +static const struct ble_client_operation_t client_operation = { + .scan_enable = bt_ble_scan_enable, + .disconnect = ble_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .write_data = (void *)client_write_without_respond_send, + .read_do = (void *)client_read_value_send, + .regist_wakeup_send = client_regiest_wakeup_send, + .regist_recieve_cbk = client_regiest_recieve_cbk, + .regist_state_cbk = client_regiest_state_cbk, + .init_config = client_init_config, + .opt_comm_send = client_operation_send, + .set_force_search = client_force_search, + .create_connect = client_create_connect_api, + .create_connect_cannel = client_create_cannel_api, + .get_work_state = get_ble_work_state, +}; + +/* + ************************************************************************************************** + * 外部调用函数实现 + ************************************************************************************************** + */ + + +/** + * @brief 获取客户端操作接口表 + * @return 指向ble_client_operation_t结构体的指针 + */ +struct ble_client_operation_t *ble_get_client_operation_table(void) +{ + return (struct ble_client_operation_t *)&client_operation; +} + +/** + * @brief BLE协议栈初始化函数,由协议栈内部调用 + */ +void ble_profile_init(void) +{ + log_info("ble profile init\n"); + le_device_db_init(); + ble_stack_gatt_role(1); // 设置为客户端角色 + + /* setup ATT client */ + gatt_client_init(); + gatt_client_register_packet_handler(cbk_packet_handler); + + // 注册HCI事件回调 + hci_event_callback_set(&cbk_packet_handler); + le_l2cap_register_packet_handler(&cbk_packet_handler); + + ble_vendor_set_default_att_mtu(ATT_LOCAL_MTU_SIZE); +} + +/** + * @brief BLE客户端总初始化 + */ +void bt_ble_init(void) +{ + log_info("***** ble_init******\n"); + +#if WIRELESS_TOOL_BLE_NAME_EN + u8 *config_name; + u8 config_name_len; +#if 1 // 使用配置工具的蓝牙名 + extern const char *bt_get_local_name(); + config_name = (u8 *)(bt_get_local_name()); + config_name_len = strlen((const char *)config_name) + 1; + log_info("use config name, len=%d", config_name_len); + log_info_hexdump(config_name, config_name_len); +#else + config_name = (u8 *)TEST_BOX_BLE_NAME; + config_name_len = sizeof(TEST_BOX_BLE_NAME); +#endif + match_name = (u8 *)zalloc(config_name_len); + memcpy(match_name, config_name, config_name_len); + log_info("match_name: %s", match_name); +#endif + + set_ble_work_state(BLE_ST_INIT_OK); + conn_pair_vm_do(&conn_pair_info, 0); // 读取VM中的配对信息 + +#if !WIRELESS_PAIR_BONDING + device_bonding_init(); +#endif + + ble_module_enable(1); // 使能BLE模块 + +#if TCFG_WIFI_DETECT_ENABLE + extern void wifi_detect_set_master_first(u8 first); +#if TCFG_WIFI_DETCET_PRIOR + wifi_detect_set_master_first(0); +#else + wifi_detect_set_master_first(1); +#endif +#endif + +#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) + client_timer_start(); // 启动数据速率统计定时器 +#endif +} + +/** + * @brief BLE客户端退出 + */ +void bt_ble_exit(void) +{ + log_info("***** ble_exit******\n"); + // 可添加退出清理代码 +} + +/** + * @brief 应用层调用的断开连接接口 + */ +void ble_app_disconnect(void) +{ + ble_disconnect(NULL); +} + +/** + * @brief BLE模块使能/禁止 (兼容旧接口) + * @param enable 1:使能, 0:禁止 + */ +void bt_ble_adv_enable(u8 enable) +{ + ble_module_enable(enable); +} + +/** + * @brief BLE模块使能/禁止 + * @param en 1:使能, 0:禁止 + */ +void ble_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + if (en) { + scan_ctrl_en = 1; + bt_ble_scan_enable(0, 1); // 开始扫描 + } else { + scan_ctrl_en = 0; + if (con_handle) { + ble_disconnect(NULL); // 如果已连接,则断开 + } else { + bt_ble_scan_enable(0, 0); // 如果未连接,则停止扫描 + } + } +} + +/** + * @brief 客户端发起连接参数更新请求 + */ +void client_send_conn_param_update(void) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[send_param_index]; + log_info("client update param:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (con_handle) { + ble_op_conn_param_update(con_handle, param); + } +} + +/** + * @brief 清除绑定信息 + */ +void clear_bonding_info(void) +{ + log_info("client_clear_bonding_info\n"); + conn_pair_vm_do(&conn_pair_info, 0); + if (conn_pair_info.pair_flag) { + // 清空配对信息并写回VM + memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); + conn_pair_vm_do(&conn_pair_info, 1); + +#if WIRELESS_PAIR_BONDING + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + bt_ble_scan_enable(0, 1); + } else if (con_handle) { + ble_disconnect(NULL); + } +#endif + } +} + +/** + * @brief 填充MAC地址到RCSP广播(示例函数) + * @param mac_addr_buf 存储MAC地址的缓冲区 + */ +void rcsp_adv_fill_mac_addr(u8 *mac_addr_buf) +{ +#if (MUTIl_CHARGING_BOX_EN) + u8 *mac_addr = get_chargebox_adv_addr(); + if (mac_addr) { + swapX(mac_addr, mac_addr_buf, 6); + } +#else + swapX(bt_get_mac_addr(), mac_addr_buf, 6); +#endif +} + +/** + * @brief 发送数据给server + * + * @param data + * @param length + */ +void g_send_data_to_ble_server(const u8* data, u16 length){ + // 检查数据长度是否有效 + if (length == 0 || length > 512) { + printf("Error: Data length %d is out of range (1-512)\n", length); + return; + } + + // 优先使用default_client_write_handle,如果为0则使用target_handle.write_no_respond + u16 write_handle = default_client_write_handle ? default_client_write_handle : target_handle.write_no_respond; + + if (write_handle == 0) { + printf("Error: No valid write handle available\n"); + return; + } + + int ret = client_operation_send(write_handle, data, length, ATT_OP_WRITE_WITHOUT_RESPOND); + if(ret == 0){ + printf("success: send data to server\n"); + return; + } + printf("error: send data to server\n"); +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// +static u8 new_device_name[MAIN_BOARD_MAC_ADDR_LENGTH] = {0}; + +static client_match_cfg_t new_match_dev = { + .create_conn_mode = BIT(CLI_CREAT_BY_NAME), // 通过名称匹配 + .compare_data_len = MAIN_BOARD_MAC_ADDR_LENGTH, // 名称长度,不包含"\0" + .compare_data = new_device_name, // 名称数据 + .bonding_flag = 0, // 不进行绑定 +}; + + +/** + * @brief 连接新的设备 + * + * @param name 设备的名称 + */ +void g_ble_connect_new_device(char* name){ + memcpy(new_device_name, name, MAIN_BOARD_MAC_ADDR_LENGTH); + client_config->match_dev_cfg[0] = &new_match_dev; + + // client_operation.init_config(NULL, client_config); //新配置 + + // client_operation.disconnect(NULL); //断开成功后会自动使用新配置进行扫描 + + client_init_config(NULL, client_config);//新配置 + ble_disconnect(NULL); //断开成功后会自动使用新配置进行扫描 + connect_state = 0; + +} + +/** + * @brief 获取当前ble连接状态 + * + * @return //0:连接断开; 1:连接成功 + */ +u8 g_ble_get_state(void){ + return connect_state; +} + +/* + ************************************************************************************************** + * 内部静态函数实现 + ************************************************************************************************** + */ + + +static void client_event_report(le_client_event_e event, u8 *packet, int size) +{ + if (client_config->event_callback) { + client_config->event_callback(event, packet, size); + } +} + +/** + * @brief 设置BLE工作状态 + * @param state 新的状态 + */ +static void set_ble_work_state(ble_state_e state) +{ + if (state != ble_work_state) { + log_info("ble_client_work_st:%x->%x\n", ble_work_state, state); + ble_work_state = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} + +/** + * @brief 获取当前BLE工作状态 + * @return ble_state_e 当前状态 + */ +static ble_state_e get_ble_work_state(void) +{ + return ble_work_state; +} + +/** + * @brief 读写VM中的配对信息 + * @param info 指向配对信息结构体的指针 + * @param rw_flag 0:读, 1:写 + */ +static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag) +{ + int ret; + int vm_len = sizeof(struct pair_info_t); + + log_info("-conn_pair_info vm_do:%d\n", rw_flag); + if (rw_flag == 0) { // 读操作 + ret = syscfg_read(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); + if (!ret) { + log_info("-null--\n"); + } + // 校验数据有效性 + if ((BLE_VM_HEAD_TAG == info->head_tag) && (BLE_VM_TAIL_TAG == info->tail_tag)) { + log_info("-exist--\n"); + log_info_hexdump((u8 *)info, vm_len); + } else { + // 无效则初始化 + memset(info, 0, vm_len); + info->head_tag = BLE_VM_HEAD_TAG; + info->tail_tag = BLE_VM_TAIL_TAG; + } + } else { // 写操作 + syscfg_write(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); + } +} + +/** + * @brief 检查广播数据中的设备是否与预设规则匹配 + * @param info_type 匹配类型 (名称/地址/Tag) + * @param data 待比较的数据 + * @param size 数据长度 + * @return true:匹配, false:不匹配 + */ +static bool check_device_is_match(u8 info_type, u8 *data, int size) +{ + int i; + u8 conn_mode = BIT(info_type); + client_match_cfg_t *cfg; + + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + // 检查匹配模式和数据长度是否一致 + if (cfg->create_conn_mode == conn_mode && size == cfg->compare_data_len) { + log_info("match check\n"); + // 比较数据内容 + if (0 == memcmp(data, cfg->compare_data, cfg->compare_data_len)) { + log_info("match ok\n"); + pair_bond_enable = cfg->bonding_flag; // 设置绑定标志 + client_event_report(CLI_EVENT_MATCH_DEV, (u8 *)cfg, sizeof(client_match_cfg_t)); + return true; + } + } + } + return false; +} + +/** + * @brief 解析广播数据包 + * @param adv_address 广播设备地址 + * @param data_length 广播数据长度 + * @param data 广播数据内容 + * @param rssi 信号强度 + * @return true:找到目标设备, false:未找到 + */ +static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rssi) +{ + u8 i, lenght, ad_type; + u8 *adv_data_pt; + u8 find_remoter = 0; + u32 tmp32; + + // 1. 按地址匹配 + if (check_device_is_match(CLI_CREAT_BY_ADDRESS, adv_address, 6)) { + find_remoter = 1; + } + + // 2. 解析广播数据字段 + adv_data_pt = data; + for (i = 0; i < data_length;) { + if (*adv_data_pt == 0) { + break; + } + + lenght = *adv_data_pt++; + if (lenght >= data_length || (lenght + i) >= data_length) { + printf("!!!error_adv_packet:"); + put_buf(data, data_length); + break; + } + + ad_type = *adv_data_pt++; + i += (lenght + 1); + + switch (ad_type) { + case HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME: + case HCI_EIR_DATATYPE_SHORTENED_LOCAL_NAME: + tmp32 = adv_data_pt[lenght - 1]; + adv_data_pt[lenght - 1] = 0; + // log_info("remoter_name: %s,rssi:%d\n", adv_data_pt, rssi); + log_info_hexdump(adv_address, 6); + adv_data_pt[lenght - 1] = tmp32; + +#if SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN +#if !WIRELESS_TOOL_BLE_NAME_EN +#define TEST_BOX_BLE_NAME "W_MIC_01" +#define TEST_BOX_BLE_NAME_LEN sizeof(TEST_BOX_BLE_NAME) + if (0 == memcmp(adv_data_pt, TEST_BOX_BLE_NAME, TEST_BOX_BLE_NAME_LEN)) { + find_remoter = 1; + } +#else + if (lenght == strlen((const char *)match_name) + 1) { + if (0 == memcmp(adv_data_pt, match_name, lenght - 1)) { + find_remoter = 1; + } + } +#endif +#endif + if (check_device_is_match(CLI_CREAT_BY_NAME, adv_data_pt, lenght - 1)) { + find_remoter = 1; + log_info("catch name ok\n"); + } + break; + + case HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA: + if (check_device_is_match(CLI_CREAT_BY_TAG, adv_data_pt, lenght - 1)) { + log_info("get_tag_string!\n"); + find_remoter = 1; + } + break; + + // 其他类型可在此添加解析 + default: + break; + } + + if (find_remoter) { + break; // 找到后即可退出循环 + } + adv_data_pt += (lenght - 1); + } + + return find_remoter; +} + +/** + * @brief 报告并处理接收到的广播数据 + * @param report_pt 广播报告 + * @param len 报告长度 + */ +static void client_report_adv_data(adv_report_t *report_pt, u16 len) +{ + bool find_remoter; + +#if WIRELESS_PAIR_BONDING + // 绑定模式下,优先匹配已绑定的设备 + if (conn_pair_info.pair_flag) { + if (report_pt->event_type != 1) { // 只处理可连接的广播 + return; + } + if (report_pt->address_type == conn_pair_info.peer_address_info[0] + && 0 == memcmp(&conn_pair_info.peer_address_info[1], report_pt->address, 6)) { + log_info("match bond_dev\n"); + find_remoter = 1; + } else { + return; // 不是绑定的设备,直接返回 + } + } else { + find_remoter = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); + } +#else + find_remoter = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); +#endif + + if (find_remoter) { + // 强制搜索模式下,检查RSSI + if (force_seach_onoff && force_seach_rssi > report_pt->rssi) { + log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); + return; + } + + log_info("rssi:%d\n", report_pt->rssi); + log_info("\n*********create_connection***********\n"); + log_info("***remote type %d,addr:", report_pt->address_type); + log_info_hexdump(report_pt->address, 6); + + bt_ble_scan_enable(0, 0); // 停止扫描 + client_create_connect_api(report_pt->address, report_pt->address_type, 0); // 发起连接 + log_info("*create_finish\n"); + } +} + +/** + * @brief 使能/禁止BLE扫描 + * @param priv 私有参数 (未使用) + * @param en 1:使能, 0:禁止 + * @return 0:成功, 非0:失败 + */ +static int bt_ble_scan_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (!scan_ctrl_en && en) { + return APP_BLE_OPERATION_ERROR; // 如果总开关关闭,则不允许开启 + } + + next_state = en ? BLE_ST_SCAN : BLE_ST_IDLE; + cur_state = get_ble_work_state(); + + // 检查当前状态是否允许切换 + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; // 状态未改变 + } + + log_info("scan_en:%d\n", en); + set_ble_work_state(next_state); + + if (en) { + scanning_setup_init(); // 设置扫描参数 + } + ble_op_scan_enable2(en, 0); + + return APP_BLE_NO_ERROR; +} + +/** + * @brief 初始化扫描参数 + */ +static void scanning_setup_init(void) +{ + ble_op_set_scan_param(SET_SCAN_TYPE, SET_SCAN_INTERVAL, SET_SCAN_WINDOW); +} + +/** + * @brief 创建连接的底层实现 + * @param conn_addr 对端设备地址 + * @param addr_type 地址类型 + */ +static void client_create_connection(u8 *conn_addr, u8 addr_type) +{ + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + log_info("already create conn!!!\n"); + return; + } + + struct create_conn_param_t *create_conn_par = (void *)scan_buffer; + create_conn_par->conn_interval = SET_CONN_INTERVAL; + create_conn_par->conn_latency = SET_CONN_LATENCY; + create_conn_par->supervision_timeout = SET_CONN_TIMEOUT; + memcpy(create_conn_par->peer_address, conn_addr, 6); + create_conn_par->peer_address_type = addr_type; + + set_ble_work_state(BLE_ST_CREATE_CONN); + log_info_hexdump(create_conn_par, sizeof(struct create_conn_param_t)); + ble_op_create_connection(create_conn_par); +} + +/** + * @brief 创建连接的封装 (兼容旧接口) + * @param conn_addr 对端设备地址 + * @param addr_type 地址类型 + */ +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type) +{ + client_create_connection(conn_addr, addr_type); +} + +/** + * @brief 取消正在创建的连接 + */ +static void client_create_connection_cannel(void) +{ + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + set_ble_work_state(BLE_ST_SEND_CREATE_CONN_CANNEL); + ble_op_create_connection_cancel(); + } +} + +/** + * @brief 断开当前BLE连接 + * @param priv 私有参数 (未使用) + * @return 0:成功, 非0:失败 + */ +static int ble_disconnect(void *priv) +{ + if (con_handle) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state()) { + log_info(">>>ble send disconnect\n"); + set_ble_work_state(BLE_ST_SEND_DISCONN); + ble_op_disconnect(con_handle); + } else { + log_info(">>>ble wait disconnect...\n"); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + +/** + * @brief 检查发现的特征是否与目标UUID匹配 + * @param result_info 搜索结果 + */ +static void check_target_uuid_match(search_result_t *result_info) +{ + u32 i; + target_uuid_t *t_uuid; + printf("Found service UUID: 0x%04x, characteristic UUID: 0x%04x\n", + result_info->services.uuid16, result_info->characteristic.uuid16); + + // 遍历预设的UUID表 + for (i = 0; i < client_config->search_uuid_cnt; i++) { + t_uuid = &client_config->search_uuid_table[i]; + + log_info("Found service UUID: 0x%04x, characteristic UUID: 0x%04x\n", + result_info->services.uuid16, result_info->characteristic.uuid16); + + // 比较服务UUID + if (result_info->services.uuid16) { + if (result_info->services.uuid16 != t_uuid->services_uuid16) { + continue; + } + } else { + if (memcmp(result_info->services.uuid128, t_uuid->services_uuid128, 16)) { + continue; + } + } + + // 比较特征UUID + if (result_info->characteristic.uuid16) { + if (result_info->characteristic.uuid16 != t_uuid->characteristic_uuid16) { + continue; + } + } else { + if (memcmp(result_info->characteristic.uuid128, t_uuid->characteristic_uuid128, 16)) { + continue; + } + } + break; // 找到匹配 + } + + if (i >= client_config->search_uuid_cnt) { + return; // 未找到匹配 + } + + if (opt_handle_used_cnt >= OPT_HANDLE_MAX) { + log_info("opt_handle is full!!!\n"); + return; + } + + // 检查属性是否匹配 + if ((t_uuid->opt_type & result_info->characteristic.properties) != t_uuid->opt_type) { + log_info("properties not match!!!\n"); + return; + } + + log_info("match one uuid\n"); + + // 存储匹配到的句柄信息 + opt_handle_t *opt_get = &opt_handle_table[opt_handle_used_cnt++]; + opt_get->value_handle = result_info->characteristic.value_handle; + opt_get->search_uuid = t_uuid; + + switch (t_uuid->opt_type) { + case ATT_PROPERTY_READ: + target_handle.read_handle = result_info->characteristic.value_handle; + log_info("ATT_PROPERTY_READ:%d\n",target_handle.read_handle); + break; + case ATT_PROPERTY_WRITE_WITHOUT_RESPONSE: + target_handle.write_no_respond = result_info->characteristic.value_handle; + log_info("ATT_PROPERTY_WRITE_WITHOUT_RESPONSE:%d\n",target_handle.write_no_respond); + break; + case ATT_PROPERTY_WRITE: + target_handle.write_handle = result_info->characteristic.value_handle; + log_info("ATT_PROPERTY_WRITE:%d\n",target_handle.write_handle); + break; + case ATT_PROPERTY_NOTIFY: + target_handle.notify_handle = result_info->characteristic.value_handle; + log_info("ATT_PROPERTY_NOTIFY:%d\n",target_handle.notify_handle); + break; + case ATT_PROPERTY_INDICATE: + target_handle.indicate_handle = result_info->characteristic.value_handle; + log_info("ATT_PROPERTY_INDICATE:%d\n",target_handle.indicate_handle); + break; + default: + break; + } + + client_event_report(CLI_EVENT_MATCH_UUID, (u8 *)opt_get, sizeof(opt_handle_t)); +} + +/** + * @brief 在Profile搜索完成后,执行后续操作(如使能Notify/Indicate) + */ +static void do_operate_search_handle(void) +{ + u16 tmp_16; + u16 i, cur_opt_type; + opt_handle_t *opt_hdl_pt; + + log_info("opt_handle_used_cnt= %d\n", opt_handle_used_cnt); + log_info("find target_handle:"); + log_info_hexdump(&target_handle, sizeof(target_hdl_t)); + + if (0 == opt_handle_used_cnt) { + goto opt_end; + } + + // 遍历所有匹配到的句柄,并执行相应操作 + for (i = 0; i < opt_handle_used_cnt; i++) { + opt_hdl_pt = &opt_handle_table[i]; + cur_opt_type = opt_hdl_pt->search_uuid->opt_type; + switch ((u8)cur_opt_type) { + case ATT_PROPERTY_NOTIFY: + tmp_16 = 0x01; // 使能Notify + log_info("write_ntf_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, (u8 *)&tmp_16, 2, ATT_OP_WRITE); + break; + case ATT_PROPERTY_INDICATE: + tmp_16 = 0x02; // 使能Indicate + log_info("write_ind_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, (u8 *)&tmp_16, 2, ATT_OP_WRITE); + break; + // 其他操作可在此添加 + default: + break; + } + } + +opt_end: + set_ble_work_state(BLE_ST_SEARCH_COMPLETE); +} + +/** + * @brief 协议栈上报搜索结果的回调,内部调用 + * @param result_info 搜索结果,为-1时表示搜索完成 + */ +void user_client_report_search_result(search_result_t *result_info) +{ + if (result_info == (void *) - 1) { + log_info("client_report_search_result finish!!!\n"); + do_operate_search_handle(); + client_event_report(CLI_EVENT_SEARCH_PROFILE_COMPLETE, 0, 0); + return; + } + + log_info("\n*** services, uuid16:%04x,index=%d ***\n", result_info->services.uuid16, result_info->service_index); + log_info("{charactc, uuid16:%04x,index=%d,handle:%04x~%04x,value_handle=%04x}\n", + result_info->characteristic.uuid16, result_info->characteristic_index, + result_info->characteristic.start_handle, result_info->characteristic.end_handle, + result_info->characteristic.value_handle + ); + + if (!result_info->services.uuid16) { + log_info("######services_uuid128:"); + log_info_hexdump(result_info->services.uuid128, 16); + } + + if (!result_info->characteristic.uuid16) { + log_info("######charact_uuid128:"); + log_info_hexdump(result_info->characteristic.uuid128, 16); + } + + check_target_uuid_match(result_info); +} + +/** + * @brief 协议栈上报对端设备数据的回调 + * @param report_data 数据报告 + */ +void user_client_report_data_callback(att_data_report_t *report_data) +{ +#if SHOW_RX_DATA_RATE + test_rx_data_count += report_data->blob_length; +#endif + + target_uuid_t *search_uuid = get_match_handle_target(report_data->value_handle); + + // 调用上层注册的回调函数 + if (client_config->report_data_callback) { + client_config->report_data_callback(report_data, search_uuid); + return; + } + + // 默认处理 + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION: + case GATT_EVENT_INDICATION: + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT: + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT: + break; + default: + break; + } +} + +/** + * @brief 开始搜索Profile + */ +static void client_search_profile_start(void) +{ + opt_handle_used_cnt = 0; + memset(&target_handle, 0, sizeof(target_hdl_t)); + user_client_init(con_handle, search_ram_buffer, SEARCH_PROFILE_BUFSIZE); + + log_info("client_config->search_uuid_cnt = %d\n", client_config->search_uuid_cnt); + + if (client_config->search_uuid_cnt) { + log_info("Starting profile search...\n"); + ble_op_search_profile_all(); // 搜索所有服务和特征 + } else { + log_info("No UUID to search, setting search complete directly\n"); + user_client_set_search_complete(); // 如果没有指定UUID,直接结束 + } +} + +/** + * @brief 连接建立后,开始Profile相关流程 + * @param handle 连接句柄 + */ +static void client_profile_start(u16 handle) +{ + ble_op_att_send_init(handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_MTU_SIZE); + set_ble_work_state(BLE_ST_CONNECT); + + if (0 == client_config->security_en) { + // 如果不要求加密,直接开始搜索Profile + log_info("call client_search_profile_start\n"); + client_search_profile_start(); + } +} + +/** + * @brief 协议栈事件总处理函数 + */ +static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u8 status; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: + status = packet[3]; + if (status) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", status); + set_ble_work_state(BLE_ST_DISCONN); + break; + } + con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE : %0x\n", con_handle); + connection_update_complete_success(packet + 8); + client_profile_start(con_handle); + client_event_report(CLI_EVENT_CONNECTED, packet, size); + +#if WIRELESS_PAIR_BONDING + // 绑定模式下,保存地址信息 + memcpy(cur_peer_address_info, &packet[7], 7); + conn_pair_info.pair_flag = 1; + memcpy(&conn_pair_info.peer_address_info, cur_peer_address_info, 7); + conn_pair_info.head_tag = BLE_VM_HEAD_TAG; + conn_pair_info.tail_tag = BLE_VM_TAIL_TAG; + conn_pair_vm_do(&conn_pair_info, 1); +#else + if (pair_bond_enable) { + conn_pair_info.pair_flag = 1; + memcpy(&conn_pair_info.peer_address_info, &packet[7], 7); + conn_pair_vm_do(&conn_pair_info, 1); + pair_bond_enable = 0; + } +#endif + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE\n"); + connection_update_complete_success(packet); + client_event_report(CLI_EVENT_CONNECTION_UPDATE, packet, size); + break; + + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE"); + break; + + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_PHY_UPDATE %s\n", hci_event_le_meta_get_phy_update_complete_status(packet) ? "Fail" : "Succ"); + log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); + log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); + break; + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); + con_handle = 0; + ble_op_att_send_init(con_handle, 0, 0, 0); + set_ble_work_state(BLE_ST_DISCONN); + client_event_report(CLI_EVENT_DISCONNECT, packet, size); + + // 断线后自动重连或重新扫描 +#if !WIRELESS_PAIR_BONDING + if (conn_pair_info.pair_flag) { + client_create_connect_api(0, 0, 1); // 尝试重连 + } else +#endif + { + bt_ble_scan_enable(0, 1); // 重新扫描 + } + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_op_att_set_send_mtu(mtu); + break; + + case GAP_EVENT_ADVERTISING_REPORT: + client_report_adv_data((void *)&packet[2], packet[1]); + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + if (client_config->security_en) { + // 加密完成后,开始搜索Profile + client_search_profile_start(); + } + break; + } + break; + } +} + +/** + * @brief SM (Security Manager) 事件处理 + */ +static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + sm_just_event_t *event = (void *)packet; + u32 tmp32; + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); + break; + } + break; + } +} + +/** + * @brief 协议栈通知可以发送数据时的唤醒函数 + */ +static void can_send_now_wakeup(void) +{ + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } +} + +/** + * @brief 获取ATT发送缓冲区剩余有效长度 + * @param priv 私有参数 (未使用) + * @return 剩余长度 + */ +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_op_att_get_remain(&vaild_len); + return vaild_len; +} + +/** + * @brief 通用ATT操作发送函数 + * @param handle 特征值句柄 + * @param data 数据指针 + * @param len 数据长度 + * @param att_op_type ATT操作类型 + * @return 0:成功, 非0:失败 + */ +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type) +{ + int ret = APP_BLE_NO_ERROR; + if (!con_handle) { + return APP_BLE_OPERATION_ERROR; + } + if (!handle) { + log_info("handle is null\n"); + return APP_BLE_OPERATION_ERROR; + } + if (get_buffer_vaild_len(0) < len) { + return APP_BLE_BUFF_FULL; + } + + ret = ble_op_att_send_data(handle, data, len, att_op_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } else { +#if SHOW_TX_DATA_RATE + test_tx_data_count += len; +#endif + } + return ret; +} + +/** + * @brief 发送写请求 (Write Request) + */ +static int client_write_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle.write_handle, data, len, ATT_OP_WRITE); +} + +/** + * @brief 发送无响应写请求 (Write Command) + */ +static int client_write_without_respond_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle.write_no_respond, data, len, ATT_OP_WRITE_WITHOUT_RESPOND); +} + +/** + * @brief 发送读请求 (Read Request) + */ +static int client_read_value_send(void *priv) +{ + u16 tmp_flag = 0x55A1; + return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ); +} + +/** + * @brief 发送长读请求 (Read Long Request) + */ +static int client_read_long_value_send(void *priv) +{ + u16 tmp_flag = 0x55A2; + return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ_LONG); +} + +/** + * @brief 注册数据发送恢复唤醒回调 + */ +static int client_regiest_wakeup_send(void *priv, void *cbk) +{ + ble_resume_send_wakeup = cbk; + return APP_BLE_NO_ERROR; +} + +/** + * @brief 注册应用层数据接收回调 + */ +static int client_regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +/** + * @brief 注册应用层状态变化回调 + */ +static int client_regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +/** + * @brief 重新配置客户端搜索参数 + */ +static int client_init_config(void *priv, const client_conn_cfg_t *cfg) +{ + log_info("client_init_config\n"); + client_config = (client_conn_cfg_t *)cfg; // 重置配置 + return APP_BLE_NO_ERROR; +} + +/** + * @brief 设置强制搜索模式(根据RSSI过滤) + */ +static int client_force_search(u8 onoff, s8 rssi) +{ + force_seach_rssi = rssi; + if (force_seach_onoff != onoff) { + force_seach_onoff = onoff; + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + } + } + return 0; +} + +/** + * @brief 创建连接的API接口 + * @param addr 地址 (mode=1时可为NULL) + * @param addr_type 地址类型 (mode=1时可忽略) + * @param mode 0:按地址连接, 1:按配对信息连接 + * @return 0:成功, 非0:失败 + */ +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) +{ + u8 cur_state = get_ble_work_state(); + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + } + + if (cur_state == BLE_ST_SCAN) { + log_info("stop scan\n"); + bt_ble_scan_enable(0, 0); + } + + if (mode == 1) { // 按配对信息连接 + if (conn_pair_info.pair_flag) { + log_info("pair to creat!\n"); + log_info_hexdump(conn_pair_info.peer_address_info, 7); + bt_ble_create_connection(&conn_pair_info.peer_address_info[1], conn_pair_info.peer_address_info[0]); + return 0; + } else { + log_info("no pair to creat!\n"); + return APP_BLE_OPERATION_ERROR; + } + } else { // 按地址连接 + log_info("addr to creat!\n"); + log_info_hexdump(addr, 7); + bt_ble_create_connection(addr, addr_type); + } + return 0; +} + +/** + * @brief 取消连接的API接口 + */ +static int client_create_cannel_api(void) +{ + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + return 0; + } + return 1; +} + +/** + * @brief 重设Passkey的回调函数 + */ +static void reset_passkey_cb(u32 *key) +{ +#if 1 + u32 newkey = rand32(); + newkey &= 0xfffff; + if (newkey > 999999) { + newkey = newkey - 999999; + } + *key = newkey; + log_info("set new_key= %06u\n", *key); +#else + *key = 123456; // for debug +#endif +} + +/** + * @brief 初始化设备绑定相关配置 + */ +static void device_bonding_init(void) +{ + int i; + int cfg_bonding = 0; + client_match_cfg_t *cfg; + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + if (cfg->bonding_flag) { + cfg_bonding = 1; + } + } + if (!cfg_bonding) { + clear_bonding_info(); // 如果配置中没有需要绑定的设备,则清除本地绑定信息 + } +} + +/** + * @brief 查询客户端是否空闲(用于低功耗) + */ +static u8 client_idle_query(void) +{ + // 返回0表示不空闲,防止系统进入深眠 + return 0; +} + +// 注册低功耗目标 +REGISTER_LP_TARGET(client_user_target) = { + .name = "client_user_demo", + .is_idle = client_idle_query, +}; + +/** + * @brief 连接更新成功事件处理 + */ +static void connection_update_complete_success(u8 *packet) +{ + int conn_interval, conn_latency, conn_timeout; + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + +/** + * @brief L2CAP连接参数更新请求处理 + */ +int l2cap_connection_update_request_just(u8 *packet, hci_con_handle_t handle) +{ + log_info("slave request conn_update:\n-interval_min= %d,\n-interval_max= %d,\n-latency= %d,\n-timeout= %d\n", + little_endian_read_16(packet, 0), little_endian_read_16(packet, 2), + little_endian_read_16(packet, 4), little_endian_read_16(packet, 6)); + return 0; // 接受请求 +} + +/** + * @brief 根据句柄查找对应的目标UUID信息 + */ +static target_uuid_t *get_match_handle_target(u16 handle) +{ + for (int i = 0; i < opt_handle_used_cnt; i++) { + if (opt_handle_table[i].value_handle == handle) { + return opt_handle_table[i].search_uuid; + } + } + return NULL; +} + +/** + * @brief 设置数据包长度 + */ +static void set_connection_data_length(u16 tx_octets, u16 tx_time) +{ + if (con_handle) { + ble_op_set_data_length(con_handle, tx_octets, tx_time); + } +} + +/** + * @brief 设置PHY速率 + */ +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == con_handle) { + return; + } + u8 all_phys = 0; + u16 phy_options = 0; + ble_op_set_ext_phy(con_handle, all_phys, tx_phy, rx_phy, phy_options); +} + +#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) +/** + * @brief 数据速率统计定时器处理函数 + */ +static void client_timer_handler(void) +{ + if (!con_handle) { + test_rx_data_count = 0; + test_tx_data_count = 0; + return; + } + if (test_rx_data_count) { + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); + log_info("%d bytes receive: %d.%02d KB/s \n", test_rx_data_count, test_rx_data_count / 1000, test_rx_data_count % 1000); + test_rx_data_count = 0; + } + if (test_tx_data_count) { + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); + log_info("%d bytes send: %d.%02d KB/s \n", test_tx_data_count, test_tx_data_count / 1000, test_tx_data_count % 1000); + test_tx_data_count = 0; + } +} + +/** + * @brief 启动数据速率统计定时器 + */ +static void client_timer_start(void) +{ + client_timer_handle = sys_timer_add(NULL, client_timer_handler, 1000); +} +#endif + +#if 1 //default +/** + * @brief 默认示例的数据上报处理 + */ +static void default_report_data_deal(att_data_report_t *report_data, target_uuid_t *search_uuid) +{ + log_info("report_data:%02x,%02x,%d,len(%d)", report_data->packet_type, + report_data->value_handle, report_data->value_offset, report_data->blob_length); + log_info_hexdump(report_data->blob, report_data->blob_length); + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION: + case GATT_EVENT_INDICATION: + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT: + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT: + break; + default: + break; + } +} + +/** + * @brief 默认示例的定时写数据函数 + */ +static void default_test_write(void) +{ + static u32 count = 0; + count++; + int ret = client_operation_send(default_client_write_handle, (u8 *)&count, 16, ATT_OP_WRITE_WITHOUT_RESPOND); + log_info("test_write:%x", ret); +} + +/** + * @brief 默认示例的事件回调处理 + */ +static void default_event_callback(le_client_event_e event, u8 *packet, int size) +{ + switch (event) { + case CLI_EVENT_MATCH_DEV: { + client_match_cfg_t *match_dev = (void *)packet; + log_info("match_name:%s\n", match_dev->compare_data); + } + break; + + case CLI_EVENT_MATCH_UUID: { + opt_handle_t *opt_hdl = (void *)packet; + if (opt_hdl->search_uuid == &default_search_uuid_table[0]) { + default_client_write_handle = opt_hdl->value_handle; + log_info("match_uuid22\n"); + } + } + break; + + case CLI_EVENT_SEARCH_PROFILE_COMPLETE: + log_info("CLI_EVENT_SEARCH_PROFILE_COMPLETE\n"); + if ((!test_client_timer) && default_client_write_handle) { + log_info("test timer_add\n"); + test_client_timer = sys_hi_timer_add(0, default_test_write, 500); //xtell + // extern void test_func_main(void); + // test_func_main(); + } + break; + + case CLI_EVENT_CONNECTED: + connect_state = 1; + log_info("<<<<<<<<<< BLE Connection Successful! >>>>>>>>>>\n"); + // extern void test_func_main(void); + // test_func_main(); + break; + + case CLI_EVENT_DISCONNECT: + connect_state = 0; + if (test_client_timer) { + sys_timeout_del(test_client_timer); + test_client_timer = 0; + } + default_client_write_handle = 0; + break; + + default: + break; + } +} +#endif + +///////////////////////////////////////////////////////////////////////////////// + + + + +#endif /* (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_WIRELESS_MIC_CLIENT) */ diff --git a/apps/earphone/xtell_remote_control/task_func.c b/apps/earphone/xtell_remote_control/task_func.c index 8bbe905..e0269f6 100644 --- a/apps/earphone/xtell_remote_control/task_func.c +++ b/apps/earphone/xtell_remote_control/task_func.c @@ -258,11 +258,11 @@ void contol_key_task(void){ static u16 Xout_adc = 0; static u16 Yout_adc = 0; static u8 key1_state = 1; - u8 ble_data_buff[13] = {0xBE, 0xBB, 0x0A, 0x01, //0-3 + u8 ble_data_buff[12] = {0xBE, 0xBB, 0x0A, 0x01, //0-3 0x00, 0x00, 0x00, 0x00, //4-7 遥感值:上下、左右 0x00, 0x00, //8、9 两个按键 - 0x00, 0x00, //10、11 vbat adc值 - 0x0C}; //12 校验和 + 0x00, //10 电量百分比 + 0x0C}; //11 校验和 control_key_init(); //遥感按键初始化 @@ -279,8 +279,7 @@ void contol_key_task(void){ ble_data_buff[8] = key1_state; ble_data_buff[9] = 0x01; - ble_data_buff[10] = (u8)(vbat_value & 0xFF); - ble_data_buff[11] = (u8)((vbat_value >> 8) & 0xFF); + ble_data_buff[10] = get_vbat_percent(); g_send_data_to_ble_server(ble_data_buff, sizeof(ble_data_buff)); os_time_dly(5); diff --git a/cpu/br28/tools/aec.bin b/cpu/br28/tools/aec.bin index dcfc80f..31ebf3e 100644 Binary files a/cpu/br28/tools/aec.bin and b/cpu/br28/tools/aec.bin differ diff --git a/cpu/br28/tools/app.bin b/cpu/br28/tools/app.bin index 078dafd..efa6c05 100644 Binary files a/cpu/br28/tools/app.bin and b/cpu/br28/tools/app.bin differ diff --git a/cpu/br28/tools/data_code.bin b/cpu/br28/tools/data_code.bin index 2fd083d..218ee04 100644 Binary files a/cpu/br28/tools/data_code.bin and b/cpu/br28/tools/data_code.bin differ diff --git a/cpu/br28/tools/download/earphone/jl_isd.bin b/cpu/br28/tools/download/earphone/jl_isd.bin index fa0fa08..7bfd36c 100644 Binary files a/cpu/br28/tools/download/earphone/jl_isd.bin and b/cpu/br28/tools/download/earphone/jl_isd.bin differ diff --git a/cpu/br28/tools/sdk.elf.resolution.txt b/cpu/br28/tools/sdk.elf.resolution.txt index 275711c..d85a420 100644 --- a/cpu/br28/tools/sdk.elf.resolution.txt +++ b/cpu/br28/tools/sdk.elf.resolution.txt @@ -5175,9 +5175,15 @@ objs/apps/earphone/xtell_remote_control/ble_handler/ble_test.c.o -r=objs/apps/earphone/xtell_remote_control/ble_handler/ble_test.c.o,xt_bl_new_name,pl -r=objs/apps/earphone/xtell_remote_control/ble_handler/ble_test.c.o,xt_ble_new_name,pl objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,clear_bonding_info,pl +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,printf,l +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,l2cap_connection_update_request_just,pl +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,little_endian_read_16,l +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,user_client_report_search_result,pl +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,put_buf,l +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,user_client_report_data_callback,pl -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,ble_get_client_operation_table,pl -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,ble_profile_init,pl --r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,printf,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,le_device_db_init,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,ble_stack_gatt_role,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,gatt_client_init,l @@ -5192,24 +5198,22 @@ objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,bt_ble_adv_enable,pl -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,client_send_conn_param_update,pl -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,ble_user_cmd_prepare,l --r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,clear_bonding_info,pl -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,rcsp_adv_fill_mac_addr,pl -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,swapX,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,bt_get_mac_addr,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,g_send_data_to_ble_server,pl --r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,g_ble_connect_new_device,pl --r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,g_ble_get_state,pl --r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,put_buf,l --r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,test_func_main,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,syscfg_read,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,syscfg_write,l --r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,little_endian_read_16,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,memcmp,l +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,usr_timer_add,l +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,test_func_main,l +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,sys_timeout_del,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,user_client_init,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,user_client_set_search_complete,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,sys_timer_add,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,ble_vendor_get_peer_rssi,l -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,puts,l +-r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,phy_result,pl -r=objs/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.o,client_user_target,pl objs/apps/earphone/xtell_remote_control/ble_handler/example/example.c.o objs/apps/earphone/xtell_remote_control/nvs/nvs.c.o @@ -5365,7 +5369,7 @@ objs/apps/earphone/xtell_remote_control/task_func.c.o -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,strncmp,l -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,nvs_write_main_board_mac,l -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,nvs_clear_info,l --r=objs/apps/earphone/xtell_remote_control/task_func.c.o,g_ble_get_state,l +-r=objs/apps/earphone/xtell_remote_control/task_func.c.o,g_ble_get_state, -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,rc_ble_callback_handler,pl -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,nvs_read_main_board_mac,l -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,control_key_init,pl @@ -5379,6 +5383,7 @@ objs/apps/earphone/xtell_remote_control/task_func.c.o -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,gpio_read,l -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,contol_key_task,pl -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,get_vbat_level,l +-r=objs/apps/earphone/xtell_remote_control/task_func.c.o,get_vbat_percent,l -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,g_send_data_to_ble_server,l -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,os_time_dly,l -r=objs/apps/earphone/xtell_remote_control/task_func.c.o,rc_app_main_init,pl @@ -8600,7 +8605,7 @@ cpu/br28/liba/btstack.a.llvm.343146.l2cap.c -r=cpu/br28/liba/btstack.a.llvm.343146.l2cap.c,l2cap_signaling_handler_channel,pl -r=cpu/br28/liba/btstack.a.llvm.343146.l2cap.c,l2cap_signaling_handler_dispatch,pl -r=cpu/br28/liba/btstack.a.llvm.343146.l2cap.c,clear_sniff_cnt,l --r=cpu/br28/liba/btstack.a.llvm.343146.l2cap.c,l2cap_connection_update_request_just,pl +-r=cpu/br28/liba/btstack.a.llvm.343146.l2cap.c,l2cap_connection_update_request_just,l -r=cpu/br28/liba/btstack.a.llvm.343146.l2cap.c,l2cap_acl_handler,pl -r=cpu/br28/liba/btstack.a.llvm.343146.l2cap.c,l2cap_packet_handler,pl -r=cpu/br28/liba/btstack.a.llvm.343146.l2cap.c,gap_request_connection_parameter_update,pl @@ -9791,12 +9796,12 @@ cpu/br28/liba/btstack.a.llvm.2207106.att_send.c -r=cpu/br28/liba/btstack.a.llvm.2207106.att_send.c,config_asser,l -r=cpu/br28/liba/btstack.a.llvm.2207106.att_send.c,CONFIG_BTCTLER_TWS_ENABLE,l cpu/br28/liba/btstack.a.llvm.2252410.client_user.c --r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,user_client_report_search_result,pl +-r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,user_client_report_search_result,l -r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,user_client_report_descriptor_result,pl -r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,printf,l -r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,put_buf,l -r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,user_client_search_descriptor_is_enable,pl --r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,user_client_report_data_callback,pl +-r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,user_client_report_data_callback,l -r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,user_client_set_search_complete,pl -r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,user_client_gatt_event,pl -r=cpu/br28/liba/btstack.a.llvm.2252410.client_user.c,gatt_client_discover_characteristics_for_service,l