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 0e8aa92..b63ae61 100644 --- a/apps/earphone/xtell_remote_control/ble_handler/client_handler.c +++ b/apps/earphone/xtell_remote_control/ble_handler/client_handler.c @@ -1,552 +1,805 @@ -#include "system/app_core.h" -#include "system/includes.h" +/* + ************************************************************************************** + * - BLE Client 初始化和配置 + * - 设备扫描和匹配(按名称、MAC 地址、广播数据) + * - 连接指定设备或自动连接(支持配对和绑定) + * - 服务发现 (Service Discovery) 和特性 (Characteristic) 查找 + * - 数据读写 (Read, Write, Write Without Response) + * - 数据通知 (Notify) 和指示 (Indicate) 的接收 + * - 连接参数更新 + * - 功耗管理和状态机 + * - 数据传输速率显示 (可选) + ************************************************************************************** + */ -#include "app_config.h" -#include "app_action.h" +//====================================================================================== +// 包含头文件 +//====================================================================================== +#include "system/app_core.h" // 应用程序核心相关定义 +#include "system/includes.h" // 系统包含文件,提供基础类型和宏定义 +#include "app_config.h" // 应用程序配置宏定义 +#include "app_action.h" // 应用程序动作或状态机相关定义 +#include "btstack/btstack_task.h" // BTstack 任务相关头文件 +#include "btstack/bluetooth.h" // Bluetooth 核心 API 定义 +#include "user_cfg.h" // 用户自定义配置 +#include "vm.h" // Virtual Machine (VM) 存储相关接口 +#include "btcontroller_modules.h" // 蓝牙控制器模块定义 +#include "bt_common.h" // 蓝牙通用定义 +#include "le_client_demo.h" // LE Client Demo 相关头文件 (本文件对应的头文件) +#include "le_common.h" // LE 通用定义 +#include "ble_user.h" // BLE 用户相关定义 -#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" +//====================================================================================== +// 功能使能宏定义 +//====================================================================================== +// TCFG_BLE_DEMO_SELECT 配置为 DEF_BLE_DEMO_WIRELESS_MIC_CLIENT 时才编译此文件 #if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_WIRELESS_MIC_CLIENT) +// 是否使能测试盒 BLE Master 测试功能 (通常用于产线测试) #define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 0 +// 是否显示 RX (接收) 数据速率 #define SHOW_RX_DATA_RATE 1 +// 是否显示 TX (发送) 数据速率 #define SHOW_TX_DATA_RATE 1 +// LE_DEBUG_PRINT_EN: 控制 BLE 相关日志输出的宏 #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 +#define log_info(x, ...) printf("[LE_CLIENT]" x "\n", ## __VA_ARGS__) // 格式化打印日志信息,添加前缀 "[LE_CLIENT]" +#define log_info_hexdump put_buf // 打印十六进制数据 (假设 put_buf 是一个 hex dump 函数) #else -#define log_info(...) -#define log_info_hexdump(...) +#define log_info(...) // 如果 LE_DEBUG_PRINT_EN 未定义,则 log_info 无效 +#define log_info_hexdump(...) // 如果 LE_DEBUG_PRINT_EN 未定义,则 log_info_hexdump 无效 #endif +//====================================================================================== +// BLE 内存配置 +//====================================================================================== -//------ -#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: +// ATT (Attribute Protocol) 协议的本地 MTU (Maximum Transmission Unit) 大小 +// 必须 >= 20 +#define ATT_LOCAL_MTU_SIZE (517) +// ATT 协议发送缓冲区大小 +// (256), (512*10) 都是注释掉的备选值,当前使用 200 +#define ATT_SEND_CBUF_SIZE (200) +// ATT 协议使用的总 RAM 缓冲区大小,包括控制块、MTU 和发送缓冲区 +#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_MTU_SIZE + ATT_SEND_CBUF_SIZE) +// 分配 ATT 协议使用的 RAM 缓冲区,并进行 4 字节对齐 static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); -#define SEARCH_PROFILE_BUFSIZE (512) //note: +// 用于搜索 Profile 的 RAM 缓冲区大小 +// (512) 是当前使用的大小 +#define SEARCH_PROFILE_BUFSIZE (512) +// 分配用于搜索 Profile 的 RAM 缓冲区,并进行 4 字节对齐 static u8 search_ram_buffer[SEARCH_PROFILE_BUFSIZE] __attribute__((aligned(4))); +// 扫描时使用 search_ram_buffer #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) +//====================================================================================== +// BLE 扫描和连接参数配置 +//====================================================================================== + +// 扫描类型: SET_SCAN_TYPE +// SCAN_ACTIVE: 主动扫描,发送扫描请求 (SCN_REQ) +// SCAN_PASSIVE: 被动扫描,只监听广播包 (ADV) +#define SET_SCAN_TYPE SCAN_ACTIVE + +// 扫描周期大小 (Scan Interval) +// 单位: 0.625ms +// SET_SCAN_INTERVAL: 320 (约 200ms)。 +// 48 (约 30ms), 256 (约 160ms), 48 (约 30ms) 是注释掉的备选值。 +// 96 (约 60ms) 在没有干扰的情况下,连接速度为 60ms。 +// 如需降低功耗,可以增加扫描间隔(增大此值)。 +#define SET_SCAN_INTERVAL 320 + +// 扫描窗口大小 (Scan Window) +// 单位: 0.625ms +// SET_SCAN_WINDOW: 70 (约 43.75ms)。 +// 102 (约 63.75ms), 70 (约 43.75ms), 30 (约 18.75ms) 是注释掉的备选值。 +// 扫描窗口必须小于或等于扫描间隔。 +#define SET_SCAN_WINDOW 70 + +// 连接周期 (Connection Interval) +// 单位: 1.25ms +// SET_CONN_INTERVAL: 3 (约 3.75ms)。 +// 16 (约 20ms) 是注释掉的备选值。 +#define SET_CONN_INTERVAL 3 + +// 连接延迟 (Connection Latency) +// 单位: 连接周期 (conn_interval) 的倍数 +// SET_CONN_LATENCY: 0。表示 Server 在每个连接间隔都必须响应 Client。 +#define SET_CONN_LATENCY 0 + +// 连接超时 (Connection Supervision Timeout) +// 单位: 10ms +// SET_CONN_TIMEOUT: 400 (约 4000ms,即 4 秒)。 +// 用于检测连接是否断开。如果在此时间内双方没有通信,连接将被视为断开。 +#define SET_CONN_TIMEOUT 400 + +// WIRELESS_TOOL_BLE_NAME_EN: 是否使能通过特定蓝牙名称来匹配设备 #if WIRELESS_TOOL_BLE_NAME_EN +// 用于匹配的特定蓝牙设备名称 #define TEST_BOX_BLE_NAME "W_MIC_01" +// TEST_BOX_BLE_NAME 的长度 (不包含结束符 '\0') #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; +//====================================================================================== +// BLE 状态和回调函数定义 +//====================================================================================== + +// 扫描控制使能标志 +static u8 scan_ctrl_en; +// BLE 工作状态枚举 (BLE_ST_NULL, BLE_ST_INIT_OK, BLE_ST_SCAN, BLE_ST_CREATE_CONN, ...) +static ble_state_e ble_work_state = BLE_ST_NULL; // 初始状态为 NULL +// 接收数据的回调函数指针 +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +// BLE 状态改变的回调函数指针 +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +// 用于唤醒发送的信号量或回调函数指针 +static void (*ble_resume_send_wakeup)(void) = NULL; +// Channel 的私有数据指针 +static u32 channel_priv; +// 当前连接句柄 (Connection Handle) static hci_con_handle_t con_handle; +//====================================================================================== +// 配对 (Bonding) 信息存储 +//====================================================================================== + +// VM (Virtual Machine) 存储的头部标签 #define BLE_VM_HEAD_TAG (0xB95C) +// VM 存储的尾部标签 #define BLE_VM_TAIL_TAG (0x5CB9) +// 存储配对信息的结构体 struct pair_info_t { - u16 head_tag; - u8 pair_flag; - u8 peer_address_info[7]; - u16 tail_tag; + u16 head_tag; // 头部标签,用于校验数据有效性 + u8 pair_flag; // 配对标志,1表示已配对 + u8 peer_address_info[7]; // 对方的地址信息 (第一个字节存地址类型,后面6个字节存MAC地址) + 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; +//====================================================================================== +// GATT 客户端操作句柄记录 +//====================================================================================== -//记录handle 使用 +// 记录目标 Service/Characteristic 的句柄 (Handle) +typedef struct { + uint16_t read_handle; // 用于 Read 操作的 Characteristic Handle + uint16_t read_long_handle; // 用于 Read Long 操作的 Characteristic Handle + uint16_t write_handle; // 用于 Write 操作的 Characteristic Handle + uint16_t write_no_respond; // 用于 Write Without Response 操作的 Characteristic Handle + uint16_t notify_handle; // 用于使能 Notify 的 Characteristic Handle (通常是 Client Characteristic Configuration Descriptor, CCCD) + uint16_t indicate_handle; // 用于使能 Indicate 的 Characteristic Handle (通常是 CCCD) +} target_hdl_t; +// 记录目标句柄的实例 static target_hdl_t target_handle; -static opt_handle_t opt_handle_table[OPT_HANDLE_MAX]; +// 存储匹配到的 Service/Characteristic 的句柄信息表 +static opt_handle_t opt_handle_table[OPT_HANDLE_MAX]; // OPT_HANDLE_MAX 是一个预定义的宏,表示最大支持的句柄数量 +// 当前已使用的句柄表数量 static u8 opt_handle_used_cnt; + +//====================================================================================== +// 强制搜索和 RSSI 过滤配置 +//====================================================================================== + +// 强制搜索开关 (0: 关闭, 1: 开启) static u8 force_seach_onoff = 0; -static s8 force_seach_rssi = -127; +// 强制搜索的最小 RSSI 值 (小于此值的设备将被过滤) +static s8 force_seach_rssi = -127; // 默认值为非常低的 RSSI,表示不进行过滤 + +//====================================================================================== +// 目标设备匹配信息 +//====================================================================================== + +// 当前配对的对方设备的 MAC 地址信息 (包含地址类型和 MAC 地址) static u8 cur_peer_address_info[7]; +// 标志:是否需要根据指定的广播名称进行匹配 static u8 flag_specific_adv_name = 0; +// 标志:是否需要根据 RSSI 进行过滤判断 static u8 flag_need_judge_rssi = 0; +// 标志:是否需要根据指定的扫描条件进行匹配 static u8 flag_specific_sacn = 0; +//====================================================================================== +// 内部函数声明 +//====================================================================================== + +// 内部函数:根据给定的 MAC 地址和类型创建 BLE 连接 static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type); +// 内部函数:使能或禁用 BLE 扫描 static int bt_ble_scan_enable(void *priv, u32 en); +// 内部函数:发送数据给 Server (Write Without Response) static int client_write_send(void *priv, u8 *data, u16 len); +// 内部函数:发送 GATT 操作 (Read, Write, Notify 等) static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type); + +// 根据配置获取 BLE 工作状态 (如果 WIRELESS_TOOL_BLE_NAME_EN 为真) #if WIRELESS_TOOL_BLE_NAME_EN static ble_state_e get_ble_work_state(void); #else +// 设置 BLE 工作状态 (如果 WIRELESS_TOOL_BLE_NAME_EN 为假) static void set_ble_work_state(ble_state_e state); #endif + +// 内部函数:取消创建连接的请求 static void client_create_connection_cannel(void); -//--------------------------------------------------------------------------- -#if 1//default -//指定搜索uuid -//指定搜索uuid + +//====================================================================================== +// 默认的搜索 UUID 表和回调函数 (用于示例) +//====================================================================================== + +// 默认的搜索 UUID 表 +// 定义了 Client 需要查找的 Service 和 Characteristic 的 UUID 以及操作类型 (opt_type) +// target_uuid_t 结构体通常包含 services_uuid16, services_uuid128, characteristic_uuid16, characteristic_uuid128, opt_type static const target_uuid_t default_search_uuid_table[] = { - - // for uuid16 - // PRIMARY_SERVICE, ae30 - // CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, - // CHARACTERISTIC, ae02, NOTIFY, - + // 示例 1: 查找 16 位的 Service UUID (0xae30) + // 并查找其下的两个 Characteristic: + // 1. Characteristic UUID 0xae01, 操作类型为 ATT_PROPERTY_WRITE_WITHOUT_RESPONSE (写无响应) + // 2. Characteristic UUID 0xae02, 操作类型为 ATT_PROPERTY_NOTIFY (通知) { - .services_uuid16 = 0xae30, - .characteristic_uuid16 = 0xae01, - .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, + .services_uuid16 = 0xae30, // Service UUID (16-bit) + .characteristic_uuid16 = 0xae01, // Characteristic UUID (16-bit) + .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, // 操作类型: 写无响应 }, - { - .services_uuid16 = 0xae30, - .characteristic_uuid16 = 0xae02, - .opt_type = ATT_PROPERTY_NOTIFY, + .services_uuid16 = 0xae30, // Service UUID (16-bit) + .characteristic_uuid16 = 0xae02, // Characteristic UUID (16-bit) + .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, + // 示例 2: 查找 128 位的 Service UUID + // 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, - }, + { + .services_uuid16 = 0, // 16位 Service UUID 为 0,表示使用 128 位 UUID + .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , // 128位 Service UUID + .characteristic_uuid16 = 0, // 16位 Characteristic UUID 为 0,表示使用 128 位 UUID + .characteristic_uuid128 = {0x00,0x00,0xF5,0x31 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, // 128位 Characteristic UUID + .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, // 操作类型: 写无响应 + }, */ - }; - +// 默认的数据报告处理函数 +// 当接收到 Server 发送的数据 (Notification, Indication, Read result) 时调用 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("report_data: packet_type=%02x, handle=%04x, offset=%d, len=%d", + report_data->packet_type, report_data->value_handle, report_data->value_offset, report_data->blob_length); + // 打印报告数据的实际内容 (Hex Dump) log_info_hexdump(report_data->blob, report_data->blob_length); + // 根据接收到的数据包类型进行处理 switch (report_data->packet_type) { - case GATT_EVENT_NOTIFICATION: //notify + case GATT_EVENT_NOTIFICATION: // 收到通知 (Notify) + // 在这里可以处理接收到的通知数据 break; - case GATT_EVENT_INDICATION://indicate - case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + case GATT_EVENT_INDICATION: // 收到指示 (Indicate) + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT: // 收到 Read 操作的结果 + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT: // 收到 Read Long 操作的结果 break; - case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long - break; - default: + // 其他未处理的包类型 break; } } + +// 默认要匹配的远程设备名称 1 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 const u8 test_remoter_name1[] = "AC637N_MX(BLE)"; // 备选名称 +// static const u8 test_remoter_name2[] = "AC630N_HID567(BLE)"; //备选名称 + +// 默认的 Client 写操作使用的 Characteristic Handle static u16 default_client_write_handle; +// 用于定时触发写操作的定时器句柄 static u16 test_client_timer = 0; +// 默认的设备匹配配置 01 static const client_match_cfg_t match_dev01 = { + // 创建连接模式: BIT(CLI_CREAT_BY_NAME) 表示通过设备名称匹配来创建连接 .create_conn_mode = BIT(CLI_CREAT_BY_NAME), - .compare_data_len = sizeof(test_remoter_name1) - 1, //去结束符 + // 要匹配的名称长度 (减去字符串结束符 '\0') + .compare_data_len = sizeof(test_remoter_name1) - 1, + // 要匹配的设备名称 .compare_data = test_remoter_name1, + // bonding_flag: 0 表示不绑定,1 表示需要绑定 .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, */ -/* }; */ +/* +// 默认的设备匹配配置 02 +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); -} + +// 默认的 Client 事件回调函数 +// 当 BLE Client 发生各种事件时会被调用 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); + 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; + case CLI_EVENT_MATCH_UUID: { // 匹配到 UUID 事件 + opt_handle_t *opt_hdl = packet; // 接收匹配到的句柄信息 + // 如果匹配到的 UUID 是 default_search_uuid_table 的第一个元素 (0xae01) if (opt_hdl->search_uuid == &default_search_uuid_table[0]) { - default_client_write_handle = opt_hdl->value_handle; - log_info("match_uuid22\n"); + default_client_write_handle = opt_hdl->value_handle; // 记录下用于写入的 Characteristic Handle + log_info("match_uuid22\n"); // 打印日志 } } break; - - case CLI_EVENT_SEARCH_PROFILE_COMPLETE: + 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: + case CLI_EVENT_CONNECTED: // 连接建立事件 break; - - case CLI_EVENT_DISCONNECT: + case CLI_EVENT_DISCONNECT: // 断开连接事件 + // 如果定时器正在运行,则删除它 if (test_client_timer) { sys_timeout_del(test_client_timer); test_client_timer = 0; } - default_client_write_handle = 0; + default_client_write_handle = 0; // 清空写入句柄 break; - default: + // 其他未处理的事件 break; } } - +// 默认的 Client 连接配置结构体 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, */ + // 配置要匹配的设备,最多支持 CLIENT_MATCH_CONN_MAX 个配置 + .match_dev_cfg[0] = &match_dev01, // 使用 match_dev01 配置 + .match_dev_cfg[1] = NULL, // 备用匹配配置 1 + .match_dev_cfg[2] = NULL, // 备用匹配配置 2 + /* .match_dev_cfg[1] = &match_dev02, */ // 注释掉的备用配置 + // 数据报告回调函数 .report_data_callback = default_report_data_deal, + // 要搜索的 UUID 数量 .search_uuid_cnt = (sizeof(default_search_uuid_table) / sizeof(target_uuid_t)), + // 指向要搜索的 UUID 表 .search_uuid_table = default_search_uuid_table, + // 安全使能标志 (0: 关闭, 1: 开启) .security_en = 0, + // 事件回调函数 .event_callback = default_event_callback, }; -#endif +//====================================================================================== +// Client 操作接口配置 +//====================================================================================== -//--------------------------------------------------------------------------- -static client_conn_cfg_t *client_config = (void *) &client_conn_config_default ; -//---------------------------------------------------------------------------- +// 指向当前使用的 Client 连接配置,默认使用 default 配置 +static client_conn_cfg_t *client_config = (void *) &client_conn_config_default ; +//====================================================================================== +// 连接参数更新配置 +//====================================================================================== +// 连接参数更新表的定义 +// 结构体: {interval_min, interval_max, latency, timeout} +// 单位: interval: 1.25ms, latency: conn_interval倍数, timeout: 10ms 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}, + {16, 24, 0, 600}, // + {12, 28, 0, 600}, // (约 3.7ms) + {8, 20, 0, 600}, // + {50, 60, 0, 600}, // }; +// 当前使用的连接参数更新表的索引 +static u8 send_param_index = 3; // 默认使用索引为 3 的参数 -static u8 send_param_index = 3; +//====================================================================================== +// BLE Client API 函数声明 (内部使用) +//====================================================================================== +// 内部函数:通过 API 创建 BLE 连接 static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode); +// 内部函数:通过 API 取消创建 BLE 连接 static int client_create_cannel_api(void); -//---------------------------------------------------------------------------- +//====================================================================================== +// BLE Client 事件报告和处理 +//====================================================================================== + +// 统一的 Client 事件报告函数 +// 将事件转发给配置的回调函数 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); + if (client_config->event_callback) { // 如果配置了事件回调函数 + client_config->event_callback(event, packet, size); // 调用回调函数 } } + +/** + * @brief 检查设备是否匹配指定条件 + * + * @param info_type: 信息类型 (例如 CLI_CREAT_BY_NAME, CLI_CREAT_BY_ADDRESS, CLI_CREAT_BY_TAG) + * @param data: 要匹配的数据 + * @param size: 数据长度 + * @return true 匹配成功 + * @return 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; + u8 conn_mode = BIT(info_type); // 将 info_type 转换为位掩码 + client_match_cfg_t *cfg; // 指向匹配配置结构体 - /* log_info_hexdump(data,size); */ + // log_info_hexdump(data,size); + // 遍历所有配置的匹配规则 for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { - cfg = client_config->match_dev_cfg[i]; - if (cfg == NULL) { + 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)); */ + // 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); */ + 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; + 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 true; // 返回匹配成功 } } } - return false; + return false; // 未找到匹配的规则 } +//====================================================================================== +// 配对信息存储 (VM 操作) +//====================================================================================== + + +/** + * @brief 对配对信息结构体进行 VM 读写操作 + * + * @param info: 指向 pair_info_t 结构体的指针 + * @param rw_flag: 0 表示读操作, 1 表示写操作 + */ static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag) { - /* return; */ - + // return; int ret; - int vm_len = sizeof(struct pair_info_t); + int vm_len = sizeof(struct pair_info_t); // 获取结构体大小 + log_info("-conn_pair_info vm_do:%d\n", rw_flag); // 打印操作类型 - log_info("-conn_pair_info vm_do:%d\n", rw_flag); - if (rw_flag == 0) { + if (rw_flag == 0) { // 读操作 + // 从 VM 读取配对信息 ret = syscfg_read(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); - if (!ret) { - log_info("-null--\n"); + if (!ret) { // 如果读取失败 + log_info("-null--\n"); // 打印 null 信息 } + // 检查读到的数据是否包含正确的头部和尾部标签 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); + 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; + info->head_tag = BLE_VM_HEAD_TAG; // 设置头部标签 + info->tail_tag = BLE_VM_TAIL_TAG; // 设置尾部标签 } - } else { + } else { // 写操作 + // 将配对信息写入 VM syscfg_write(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); } } -//------------------------------------------------------------ + +//====================================================================================== +// BLE 工作状态管理 +//====================================================================================== + +/** + * @brief 获取当前的 BLE 工作状态 + * + * @return ble_state_e + */ static ble_state_e get_ble_work_state(void) { - return ble_work_state; + return ble_work_state; // 返回全局变量 ble_work_state } +// 清除配对信息 (包括 VM 中存储的信息和断开连接后的行为) void clear_bonding_info(void) { log_info("client_clear_bonding_info\n"); + // 从 VM 读取配对信息 conn_pair_vm_do(&conn_pair_info, 0); + // 如果 pair_flag 为真 (表示已配对) 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); + // 删除配对信息 + memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); // 清空结构体 + conn_pair_vm_do(&conn_pair_info, 1); // 将清空后的结构体写入 VM (相当于删除) -#if WIRELESS_PAIR_BONDING +#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(); + client_create_connection_cannel(); // 取消创建连接 + bt_ble_scan_enable(0, 1); // 停止扫描 + } + // 如果当前已连接 + else if (con_handle) { + ble_disconnect(); // 断开当前连接 } #endif } } -//------------------------------------------------------------ + +/** + * @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; + 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); } } } +//====================================================================================== +// UUID 匹配和句柄查找 +//====================================================================================== -//------------------------------------------------------------------------------- + +/** + * @brief 检查搜索到的 Service/Characteristic 是否匹配预设的 target_uuid_table + * + * @param result_info 搜索结果信息 (包含 Service 和 Characteristic 的 UUID 及属性) + */ static void check_target_uuid_match(search_result_t *result_info) { - u32 i; - target_uuid_t *t_uuid; + u32 i; // 循环变量 + target_uuid_t *t_uuid; // 指向当前匹配的 target_uuid_t + u16 tmp_16; // 临时变量 + // 遍历配置的 UUID 表 for (i = 0; i < client_config->search_uuid_cnt; i++) { - t_uuid = &client_config->search_uuid_table[i]; - if (result_info->services.uuid16) { + t_uuid = &client_config->search_uuid_table[i]; // 获取当前 UUID 配置 + + // 1. 匹配 Service UUID + if (result_info->services.uuid16) { // 如果搜索结果是 16 位 Service UUID if (result_info->services.uuid16 != t_uuid->services_uuid16) { - /* log_info("b1"); */ - continue; + /* log_info("b1"); // 调试信息 */ + continue; // UUID 不匹配,继续下一个 } - } else { + } else { // 如果搜索结果是 128 位 Service UUID + // 比较 128 位 UUID if (memcmp(result_info->services.uuid128, t_uuid->services_uuid128, 16)) { - /* log_info("b2"); */ - continue; + /* log_info("b2"); // 调试信息 */ + continue; // UUID 不匹配,继续下一个 } } - if (result_info->characteristic.uuid16) { + // 2. 匹配 Characteristic UUID + if (result_info->characteristic.uuid16) { // 如果搜索结果是 16 位 Characteristic UUID 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; + /* log_info("b3"); // 调试信息 */ + /* log_info("%d: %04x--%04x",result_info->characteristic.uuid16,t_uuid->characteristic_uuid16); // 调试信息 */ + continue; // UUID 不匹配,继续下一个 } - } else { + } else { // 如果搜索结果是 128 位 Characteristic UUID + // 比较 128 位 UUID if (memcmp(result_info->characteristic.uuid128, t_uuid->characteristic_uuid128, 16)) { - /* log_info("b4"); */ - continue; + /* log_info("b4"); // 调试信息 */ + continue; // UUID 不匹配,继续下一个 } } - - break;//match one + break; // 如果 Service 和 Characteristic UUID 都匹配,则跳出循环 } + // 如果遍历完所有配置都没有找到匹配的 UUID if (i >= client_config->search_uuid_cnt) { - return; + return; // 直接返回,不进行后续操作 } + // 3. 检查属性 (Properties) 是否匹配 + // opt_handle_used_cnt: 当前已使用的句柄表数量 + // OPT_HANDLE_MAX: 句柄表最大容量 if (opt_handle_used_cnt >= OPT_HANDLE_MAX) { - log_info("opt_handle is full!!!\n"); - return; + log_info("opt_handle is full!!!\n"); // 句柄表已满,打印错误信息 + return; // 返回 } - + // 检查搜索到的 Characteristic 的属性是否包含配置要求的操作类型 (opt_type) if ((t_uuid->opt_type & result_info->characteristic.properties) != t_uuid->opt_type) { - log_info("properties not match!!!\n"); - return; + log_info("properties not match!!!\n"); // 属性不匹配,打印错误信息 + return; // 返回 } - log_info("match one uuid\n"); + // 如果 UUID 和属性都匹配 + 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; + // 获取一个空的句柄表项 + opt_handle_t *opt_get = &opt_handle_table[opt_handle_used_cnt++]; // 使用并递增计数器 + opt_get->value_handle = result_info->characteristic.value_handle; // 记录 Characteristic 的 Handle + opt_get->search_uuid = t_uuid; // 记录匹配到的 UUID 配置 + // 根据操作类型,更新全局的 target_handle 结构体 switch (t_uuid->opt_type) { case ATT_PROPERTY_READ: - target_handle.read_handle = result_info->characteristic.value_handle; + target_handle.read_handle = result_info->characteristic.value_handle; // 记录 Read Handle break; - case ATT_PROPERTY_WRITE_WITHOUT_RESPONSE: - target_handle.write_no_respond = result_info->characteristic.value_handle; + target_handle.write_no_respond = result_info->characteristic.value_handle; // 记录 Write Without Response Handle break; - case ATT_PROPERTY_WRITE: - target_handle.write_handle = result_info->characteristic.value_handle; + target_handle.write_handle = result_info->characteristic.value_handle; // 记录 Write Handle break; - case ATT_PROPERTY_NOTIFY: - target_handle.notify_handle = result_info->characteristic.value_handle; + target_handle.notify_handle = result_info->characteristic.value_handle; // 记录 Notify Handle (通常是 CCCD 的 Handle) break; - case ATT_PROPERTY_INDICATE: - target_handle.indicate_handle = result_info->characteristic.value_handle; + target_handle.indicate_handle = result_info->characteristic.value_handle; // 记录 Indicate Handle (通常是 CCCD 的 Handle) break; - default: break; } - + // 触发匹配到 UUID 的事件 client_event_report(CLI_EVENT_MATCH_UUID, opt_get, sizeof(opt_handle_t)); - } -//操作handle,完成 write ccc +//====================================================================================== +// 操作已找到的句柄 (例如使能 Notify/Indicate, 执行 Read) +//====================================================================================== + +// 执行已找到的句柄操作 (例如使能 Notify/Indicate, 执行 Read) 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); + 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)); + log_info_hexdump(&target_handle, sizeof(target_hdl_t)); // 打印找到的目标句柄信息 + // 如果没有找到任何句柄,则直接跳转到结束 if (0 == opt_handle_used_cnt) { goto opt_end; } - /* test_send_conn_update();//for test */ + /* 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 + opt_hdl_pt = &opt_handle_table[i]; // 获取当前句柄信息 + cur_opt_type = opt_hdl_pt->search_uuid->opt_type; // 获取配置的操作类型 + + switch ((u8)cur_opt_type) { // 根据操作类型执行相应的 GATT 操作 + case ATT_PROPERTY_READ: // 如果是 Read 操作 + if (1) { // 这里的条件判断似乎是硬编码的,可以考虑优化 + tmp_16 = 0x55A2;// fixed value for read long operation log_info("read_long:%04x\n", opt_hdl_pt->value_handle); + // 发送 Read Long 操作请求 client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ_LONG); } else { - tmp_16 = 0x55A1;//fixed + tmp_16 = 0x55A1;// fixed value for read operation log_info("read:%04x\n", opt_hdl_pt->value_handle); + // 发送 Read 操作请求 client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ); } break; - - case ATT_PROPERTY_NOTIFY: - tmp_16 = 0x01;//fixed + case ATT_PROPERTY_NOTIFY: // 如果是 Notify 操作 + tmp_16 = 0x01;// 启用 Notify 的 CCCD 值 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); + // 发送写操作到 CCCD (Client Characteristic Configuration Descriptor),使能 Notify + // 注意:这里写入的是 opt_hdl_pt->value_handle + 1,通常 CCCD 的 Handle 比 Characteristic Handle 大 1 + client_operation_send(opt_hdl_pt->value_handle + 1, (u8 *)&tmp_16, 2, ATT_OP_WRITE); break; - - case ATT_PROPERTY_INDICATE: - tmp_16 = 0x02;//fixed + case ATT_PROPERTY_INDICATE: // 如果是 Indicate 操作 + tmp_16 = 0x02;// 启用 Indicate 的 CCCD 值 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); + // 发送写操作到 CCCD,使能 Indicate + client_operation_send(opt_hdl_pt->value_handle + 1, (u8 *)&tmp_16, 2, ATT_OP_WRITE); break; - default: + // 其他操作类型 (例如 Write, Write Without Response) break; } } - opt_end: + // 所有句柄操作完成后,将工作状态设置为搜索完成 set_ble_work_state(BLE_ST_SEARCH_COMPLETE); - } -//协议栈内部调用 -//return: 0--accept,1--reject +//====================================================================================== +// L2CAP 连接参数更新回调 ( Slave Request ) +//====================================================================================== + +/** + * @brief L2CAP 连接参数更新请求的回调函数 (由协议栈内部调用) + * + * @param packet: L2CAP 连接参数更新请求的数据包 + * @param handle: 连接句柄 + * @return int 返回值: 0 -- 接受连接参数更新, 1 -- 拒绝连接参数更新 + */ 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; */ + little_endian_read_16(packet, 0), // interval_min + little_endian_read_16(packet, 2), // interval_max + little_endian_read_16(packet, 4), // latency + little_endian_read_16(packet, 6)); // timeout + return 0; // 接受更新 + /* return 1; // 拒绝更新 (注释掉) */ } -//协议栈内部调用 +//====================================================================================== +// BLE Client 搜索结果回调 +//====================================================================================== + + +/** + * @brief 用户回调:处理 BLE Client 搜索到的 Service 和 Characteristic 信息 + * + * @param result_info result_info: 搜索结果信息结构体 + */ void user_client_report_search_result(search_result_t *result_info) { - if (result_info == (void *) - 1) { + u32 i; // 循环变量 + target_uuid_t *t_uuid; // 指向当前匹配的 target_uuid_t + + // 如果 result_info 为 -1,表示搜索完成 + 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); + do_operate_search_handle(); // 执行已找到句柄的操作 + client_event_report(CLI_EVENT_SEARCH_PROFILE_COMPLETE, 0, 0); // 报告搜索完成事件 return; } + // 打印搜索到的 Service 和 Characteristic 的 UUID 和 Handle 信息 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, @@ -554,562 +807,647 @@ void user_client_report_search_result(search_result_t *result_info) result_info->characteristic.value_handle ); + // 如果 Service UUID 是 128 位的,打印出来 if (!result_info->services.uuid16) { log_info("######services_uuid128:"); log_info_hexdump(result_info->services.uuid128, 16); } - + // 如果 Characteristic UUID 是 128 位的,打印出来 if (!result_info->characteristic.uuid16) { log_info("######charact_uuid128:"); log_info_hexdump(result_info->characteristic.uuid128, 16); } + // 调用内部函数检查搜索到的 UUID 是否匹配配置的 UUID check_target_uuid_match(result_info); } -#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) +//====================================================================================== +// 数据速率显示 (可选功能) +//====================================================================================== +#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) { + // 获取并打印对方的 RSSI 值 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("\n-ble_data_rate: %d bps-\n", test_rx_data_count * 8); // 注释掉的原始日志 */ + // 打印接收速率 (KB/s) 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; + test_rx_data_count = 0; // 重置接收计数器 } - + // 如果发送了数据 if (test_tx_data_count) { + // 获取并打印对方的 RSSI 值 log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); + // 打印发送速率 (KB/s) 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; + test_tx_data_count = 0; // 重置发送计数器 } } +// 启动数据速率显示定时器 static void client_timer_start(void) { + // 添加一个定时器,每 1000ms (1秒) 调用一次 client_timer_handler client_timer_handle = sys_timer_add(NULL, client_timer_handler, 1000); } - #endif /* SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE */ + +/** + * @brief 根据 Handle 获取匹配到的 target_uuid_t 指针 + * + * @param handle 要查找的 Characteristic Handle + * @return target_uuid_t* 匹配到的 target_uuid_t 指针,如果未找到则返回 NULL + */ static target_uuid_t *get_match_handle_target(u16 handle) { + // 遍历已找到的句柄表 for (int i = 0; i < opt_handle_used_cnt; i++) { + // 如果当前句柄表的 Handle 与目标 Handle 匹配 if (opt_handle_table[i].value_handle == handle) { - return opt_handle_table[i].search_uuid; + return opt_handle_table[i].search_uuid; // 返回对应的 UUID 配置 } } - return NULL; + return NULL; // 未找到,返回 NULL } -//协议栈内部调用 +//====================================================================================== +// BLE Client 数据接收回调 +//====================================================================================== + +/** + * @brief 用户回调:处理从 Server 接收到的数据 + * + * @param report_data 接收到的数据报告结构体 + */ 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); */ + /* 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; +#if SHOW_RX_DATA_RATE // 如果使能了显示接收速率 + test_rx_data_count += report_data->blob_length; // 累加接收到的字节数 #endif /* SHOW_RX_DATA_RATE */ + // 根据接收到的 Handle,查找匹配的 UUID 配置 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; + 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 + case GATT_EVENT_NOTIFICATION: // 收到通知 +// log_info("\n-notify_rx(%d):",report_data->blob_length); // 调试日志 + case GATT_EVENT_INDICATION: // 收到指示 + 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}; */ +//====================================================================================== +// BLE Client 搜索 Profile (服务) 的启动和初始化 +//====================================================================================== +// 启动 Client 的 Profile (服务) 搜索过程 static void client_search_profile_start(void) { - opt_handle_used_cnt = 0; - memset(&target_handle, 0, sizeof(target_hdl_t)); + opt_handle_used_cnt = 0; // 重置已找到的句柄计数 + memset(&target_handle, 0, sizeof(target_hdl_t)); // 清空目标句柄记录 + // 初始化 GATT 客户端,分配内存缓冲区 user_client_init(con_handle, search_ram_buffer, SEARCH_PROFILE_BUFSIZE); + + // 如果配置了要搜索的 UUID if (client_config->search_uuid_cnt) { - printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); - ble_op_search_profile_all(); + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); // 调试日志 + ble_op_search_profile_all(); // 开始搜索所有 Profile } else { - printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); - user_client_set_search_complete(); + // 如果没有配置要搜索的 UUID,则直接认为搜索完成 + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); // 调试日志 + user_client_set_search_complete(); // 标记搜索完成 } } -//------------------------------------------------------------ +//====================================================================================== +// BLE Adv 数据解析和设备匹配 +//====================================================================================== + +/** + * @brief 解析 Adv (Advertising) 数据报告,并检查设备是否匹配 + * + * @param adv_address: 设备的 MAC 地址 + * @param data_length: Adv 数据长度 + * @param data: Adv 数据内容 + * @param rssi: 接收到的 RSSI 值 + * @return true 匹配成功 + * @return 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; - /* u8 tmp_addr[6]; */ - u32 tmp32; + u8 i, lenght, ad_type; // 循环变量, 数据段长度, AD 类型 + u8 *adv_data_pt; // 指向当前解析的 Adv 数据指针 + u8 find_remoter = 0; // 标志:是否找到目标设备 + /* u8 tmp_addr[6]; */ // 临时 MAC 地址缓冲区 (注释掉) + u32 tmp32; // 临时变量 + // 1. 检查是否按 MAC 地址匹配 if (check_device_is_match(CLI_CREAT_BY_ADDRESS, adv_address, 6)) { - find_remoter = 1; + find_remoter = 1; // 如果按 MAC 地址匹配成功 } - adv_data_pt = data; + adv_data_pt = data; // 初始化 Adv 数据指针 + // 遍历 Adv 数据包中的每个 AD (Advertising Data) 结构 for (i = 0; i < data_length;) { - if (*adv_data_pt == 0) { + if (*adv_data_pt == 0) { // 如果 AD 数据长度为 0,表示解析结束 /* log_info("analyze end\n"); */ break; } - - lenght = *adv_data_pt++; - + lenght = *adv_data_pt++; // 获取当前 AD 结构的长度 (包含类型字节) + // 检查长度是否有效,防止越界 if (lenght >= data_length || (lenght + i) >= data_length) { - /*过滤非标准包格式*/ + /* 过滤非标准包格式 */ printf("!!!error_adv_packet:"); - put_buf(data, data_length); + put_buf(data, data_length); // 打印错误 Adv 包 break; } + ad_type = *adv_data_pt++; // 获取当前 AD 结构的类型 + i += (lenght + 1); // 更新循环索引,跳过当前 AD 结构 - ad_type = *adv_data_pt++; - i += (lenght + 1); - + // 根据 AD 类型进行解析 switch (ad_type) { - case HCI_EIR_DATATYPE_FLAGS: + 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: + case HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS: // 更多 16 位 Service UUID + case HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS: // 完整的 16 位 Service UUID + case HCI_EIR_DATATYPE_MORE_32BIT_SERVICE_UUIDS: // 更多 32 位 Service UUID + case HCI_EIR_DATATYPE_COMPLETE_32BIT_SERVICE_UUIDS: // 完整的 32 位 Service UUID + case HCI_EIR_DATATYPE_MORE_128BIT_SERVICE_UUIDS: // 更多 128 位 Service UUID + case HCI_EIR_DATATYPE_COMPLETE_128BIT_SERVICE_UUIDS: // 完整的 128 位 Service UUID /* log_info("service uuid:"); */ - /* log_info_hexdump(adv_data_pt, lenght - 1); */ + /* log_info_hexdump(adv_data_pt, lenght - 1); // 打印 Service UUID */ 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; // 临时将最后一个字节设为 0,使其成为一个 C 风格字符串 + log_info("remoter_name: %s,rssi:%d\n", adv_data_pt, rssi); // 打印设备名称和 RSSI + log_info_hexdump(adv_address, 6); // 打印设备 MAC 地址 + adv_data_pt[lenght - 1] = tmp32; // 恢复最后一个字节 - 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; + find_remoter = 1; // 匹配成功 log_info("catch name ok\n"); } break; - - case HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA: + 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; + find_remoter = 1; // 匹配成功 } break; - - case HCI_EIR_DATATYPE_APPEARANCE_DATA: + 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); + adv_data_pt += (lenght - 1); // 移动 Adv 数据指针 } - - return find_remoter; + return find_remoter; // 返回是否找到目标设备 } + +/** + * @brief 处理 GAP_EVENT_ADVERTISING_REPORT 事件 + * + * @param report_pt Adv 报告信息指针 + * @param len Adv 报告信息长度 + */ static void client_report_adv_data(adv_report_t *report_pt, u16 len) { - bool find_remoter; + 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("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); // 调试日志 - /* 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; - } - } + // 直接解析 Adv 数据 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 小于强制设置的 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); + log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); // RSSI 不满足要求,打印日志并返回 return; } - - log_info("rssi:%d\n", report_pt->rssi); - log_info("\n*********create_connection***********\n"); + log_info("rssi:%d\n", report_pt->rssi); // 打印 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); + log_info_hexdump(report_pt->address, 6); // 打印远程设备地址 + + bt_ble_scan_enable(0, 0); // 停止扫描 + // 调用 API 创建连接 client_create_connect_api(report_pt->address, report_pt->address_type, 0); - log_info("*create_finish\n"); + log_info("*create_finish\n"); // 打印创建连接完成日志 } } +//====================================================================================== +// BLE Client 连接创建和取消 +//====================================================================================== +/** + * @brief 创建 BLE 连接 (内部函数) + * + * @param conn_addr 目标设备的 MAC 地址 + * @param addr_type 目标设备的地址类型 + */ static void client_create_connection(u8 *conn_addr, u8 addr_type) { - struct create_conn_param_t *create_conn_par = scan_buffer; + 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); + // 配置连接参数 + 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); // 复制目标设备 MAC 地址 + 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 创建 BLE 连接 + * + * @param conn_addr 目标设备的 MAC 地址 + * @param addr_type 目标设备的地址类型 + */ static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type) { - client_create_connection(conn_addr, 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(); + set_ble_work_state(BLE_ST_SEND_CREATE_CONN_CANNEL); // 设置状态为发送取消请求 + ble_op_create_connection_cancel(); // 发起取消连接请求 } } +//====================================================================================== +// BLE 断开连接 +//====================================================================================== + +/** + * @brief API 函数:断开 BLE 连接 + * + * @param priv 私有数据指针 (未使用) + * @return int APP_BLE_NO_ERROR - 操作成功, APP_BLE_OPERATION_ERROR - 操作失败 + */ static int ble_disconnect(void *priv) { + // 如果当前已连接 (con_handle 不为 0) 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); + // 如果当前状态不是正在发送断开连接请求 + if (get_ble_work_state() != BLE_ST_SEND_DISCONN) { + 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"); + log_info(">>>ble wait disconnect...\n"); // 打印等待断开日志 } - return APP_BLE_NO_ERROR; + return APP_BLE_NO_ERROR; // 返回操作成功 } else { - return APP_BLE_OPERATION_ERROR; + return APP_BLE_OPERATION_ERROR; // 如果未连接,返回操作失败 } } +//====================================================================================== +// 连接参数更新完成处理 +//====================================================================================== + +/** + * @brief 处理 HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE 事件 + * + * @param packet 事件数据包 + */ static void connection_update_complete_success(u8 *packet) { - int con_handle, conn_interval, conn_latency, conn_timeout; - + 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); } +//====================================================================================== +// 安全管理器 (SM) 回调函数 (用于配对和加密) +//====================================================================================== + +/** + * @brief SM (Security Manager) 事件回调函数 + * + * @param packet_type: 包类型 + * @param channel: 通道号 + * @param packet: 事件数据包 + * @param size: 数据包大小 + */ 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; + sm_just_event_t *event = (void *)packet; // 将包转换为 SM 事件结构体 + u32 tmp32; // 临时变量 + switch (packet_type) { - case HCI_EVENT_PACKET: + case HCI_EVENT_PACKET: // 如果是 HCI 事件 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)); + case SM_EVENT_JUST_WORKS_REQUEST: // 收到 Just Works 配对请求 + 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); + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: // 收到 Passkey 显示请求 + log_info_hexdump(packet, size); // 打印事件包 + memcpy(&tmp32, event->data, 4); // 提取 Passkey (假设是 4 字节) + log_info("Passkey display: %06u.\n", tmp32); // 打印 Passkey (格式化为 6 位数字) break; } break; } } +//====================================================================================== +// ATT 发送缓冲区唤醒机制 +//====================================================================================== + +// 当 ATT 发送缓冲区有空间时,调用此函数唤醒发送任务 static void can_send_now_wakeup(void) { - /* putchar('E'); */ + /* putchar('E'); // 调试用的打印字符 (注释掉) */ + // 如果注册了唤醒发送的回调函数 if (ble_resume_send_wakeup) { - ble_resume_send_wakeup(); + ble_resume_send_wakeup(); // 调用回调函数 } } -const char *const phy_result[] = { - "None", - "1M", - "2M", - "Coded", +//====================================================================================== +// PHY 更新和数据长度更新 +//====================================================================================== + +// PHY 模式的字符串表示 +static const char *const phy_result[] = { + "None", // 0 + "1M", // 1 + "2M", // 2 + "Coded", // 3 }; +/** + * @brief 设置连接的数据长度 (TX Octets, TX Time) + * + * @param tx_octets TX Octets (传输的字节数) + * @param tx_time TX Time (传输的时间) + */ 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); + if (con_handle) { // 如果已连接 + ble_op_set_data_length(con_handle, tx_octets, tx_time); // 调用 API 设置数据长度 } } + +/** + * @brief 设置连接的 PHY (Physical Layer) + * + * @param tx_phy TX PHY 类型 + * @param rx_phy RX PHY 类型 + */ static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) { - if (0 == con_handle) { - return; + if (0 == con_handle) { // 如果未连接 + return; // 直接返回 } - - u8 all_phys = 0; - u16 phy_options = 0; - + u8 all_phys = 0; // 是否使用所有 PHY (0: 否, 1: 是) + u16 phy_options = 0; // PHY 选项 (通常为 0) + // 调用 API 设置 EXT PHY (扩展 PHY) ble_op_set_ext_phy(con_handle, all_phys, tx_phy, rx_phy, phy_options); } +//====================================================================================== +// BLE Client 连接成功后的初始化流程 +//====================================================================================== + +/** + * @brief 连接成功后,初始化 Client Profile (包括 ATT, GATT, Service Discovery 等) + * + * @param con_handle 新建立的连接句柄 + */ static void client_profile_start(u16 con_handle) { + // 初始化 ATT 客户端,分配内存缓冲区 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__); + 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(); + printf("[debug] %s, %d\n", __FUNCTION__, __LINE__); // 调试日志 + client_search_profile_start(); // 开始搜索 Profile } + // 如果安全模式使能,则会等待加密完成 (HCI_EVENT_ENCRYPTION_CHANGE 事件) 后再搜索 Profile } -/* LISTING_START(packetHandler): Packet Handler */ +//====================================================================================== +// BLE 主事件处理函数 (Packet Handler) +//====================================================================================== + + +/** + * @brief BLE 主事件处理函数,接收来自协议栈的各种事件 + * + * @param packet_type: 包类型 (HCI_EVENT_PACKET, L2CAP_EVENT_PACKET, etc.) + * @param channel: 通道号 + * @param packet: 事件数据包 + * @param size: 数据包大小 + */ static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { - int mtu; - u32 tmp; - u8 status; + int mtu; // MTU 值 + u32 tmp; // 临时变量 + u8 status; // 状态码 switch (packet_type) { - case HCI_EVENT_PACKET: + case HCI_EVENT_PACKET: // 处理 HCI 事件 switch (hci_event_packet_get_type(packet)) { - - /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* case DAEMON_EVENT_HCI_PACKET_SENT: // 注释掉的事件 */ /* break; */ - case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: // ATT 指示完成事件 log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); - case ATT_EVENT_CAN_SEND_NOW: - can_send_now_wakeup(); + case ATT_EVENT_CAN_SEND_NOW: // ATT 发送缓冲区有空间事件 + can_send_now_wakeup(); // 唤醒发送任务 break; - - case HCI_EVENT_LE_META: + case HCI_EVENT_LE_META: // LE Meta 事件 (与 LE 操作相关) 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) { + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: // LE 增强连接完成事件 + 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; + 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); + client_profile_start(con_handle); // 开始 Client Profile 初始化 break; - - case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: - if (packet[3]) { + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: // LE 连接完成事件 (旧版本) + if (packet[3]) { // 如果状态码非 0,表示连接失败 log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", packet[3]); - set_ble_work_state(BLE_ST_DISCONN); - break; + 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 + connection_update_complete_success(packet + 8); // 处理连接参数更新成功事件 + client_profile_start(con_handle); // 开始 Client Profile 初始化 + client_event_report(CLI_EVENT_CONNECTED, packet, size); // 报告连接成功事件 + +#if WIRELESS_PAIR_BONDING // 如果使能了无线配对绑定 + // 记录连接设备的 MAC 地址和类型 memcpy(cur_peer_address_info, &packet[7], 7); - conn_pair_info.pair_flag = 1; + 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 + 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); // 将配对信息写入 VM +#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; + conn_pair_info.pair_flag = 1; // 设置配对标志 + memcpy(&conn_pair_info.peer_address_info, &packet[7], 7); // 记录设备地址 + conn_pair_vm_do(&conn_pair_info, 1); // 写入 VM + pair_bond_enable = 0; // 清零配对使能标志 } #endif break; - - case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: // LE 连接参数更新完成事件 log_info("APP HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE\n"); - connection_update_complete_success(packet); - - client_event_report(CLI_EVENT_CONNECTION_UPDATE, packet, size); - + connection_update_complete_success(packet); // 处理连接参数更新成功 + client_event_report(CLI_EVENT_CONNECTION_UPDATE, packet, size); // 报告连接更新事件 break; - - case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: // LE 数据长度变化事件 log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE"); break; - - case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: // LE PHY 更新完成事件 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); // 初始化 ATT 客户端 (清空) + set_ble_work_state(BLE_ST_DISCONN); // 设置状态为已断开 + client_event_report(CLI_EVENT_DISCONNECT, packet, size); // 报告断开连接事件 - 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 !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; - - 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); + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: // MTU 交换完成事件 + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; // 获取 MTU 值 (减去 3 是因为协议栈内部处理) + log_info("ATT MTU = %u\n", mtu); // 打印 MTU 值 + ble_op_att_set_send_mtu(mtu); // 设置 ATT 客户端的发送 MTU break; - - case HCI_EVENT_VENDOR_REMOTE_TEST: + 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); + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: // L2CAP 连接参数更新响应事件 + 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]); + case GAP_EVENT_ADVERTISING_REPORT: // GAP 广告报告事件 + /* putchar('@'); // 调试用的打印字符 (注释掉) */ + client_report_adv_data((void *)&packet[2], packet[1]); // 解析 Adv 数据并处理 break; - - case HCI_EVENT_ENCRYPTION_CHANGE: - log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + case HCI_EVENT_ENCRYPTION_CHANGE: // 加密状态改变事件 + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); // 打印加密状态 (0: 成功, 非0: 失败) + // 如果使能了安全模式 if (client_config->security_en) { - client_search_profile_start(); + client_search_profile_start(); // 加密完成后开始搜索 Profile } break; } @@ -1117,90 +1455,157 @@ static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *p } } +//====================================================================================== +// ATT 发送缓冲区管理 +//====================================================================================== +/** + * @brief 获取 ATT 发送缓冲区中剩余可用的字节数 + * + * @param priv 私有数据指针 (未使用) + * @return int 可用字节数 + */ static int get_buffer_vaild_len(void *priv) { u32 vaild_len = 0; - ble_op_att_get_remain(&vaild_len); + ble_op_att_get_remain(&vaild_len); // 调用协议栈 API 获取剩余空间 return vaild_len; } +//====================================================================================== +// BLE Client 数据发送 API +//====================================================================================== + + +/** + * @brief 内部函数:发送 GATT 操作数据 + * + * @param handle: 要操作的 Characteristic Handle + * @param data: 要发送的数据 + * @param len: 数据长度 + * @param att_op_type: ATT 操作类型 (ATT_OP_READ, ATT_OP_WRITE, ATT_OP_WRITE_WITHOUT_RESPOND, etc.) + * @return int 0 - 成功, BLE_BUFFER_FULL - 缓冲区满, APP_BLE_OPERATION_ERROR - 操作失败 + */ static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type) { - int ret = APP_BLE_NO_ERROR; + int ret = APP_BLE_NO_ERROR; // 默认操作成功 + // 如果未连接或 Handle 无效,则返回错误 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; + /* log_info("opt_buff_full!!!\n"); // 调试日志 */ + return APP_BLE_BUFF_FULL; // 缓冲区已满,返回错误 } + // 调用协议栈 API 发送数据 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; + 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; + return ret; // 返回操作结果 } -//----------------------------------------------- +/** + * @brief 发送 Write 操作数据 (Write Without Response) + * + * @param priv: 私有数据指针 (未使用) + * @param data: 要发送的数据 + * @param len: 数据长度 + * @return int 操作结果 + */ static int client_write_send(void *priv, u8 *data, u16 len) { + // 调用内部函数,使用 Write Handle,操作类型为 ATT_OP_WRITE_WITHOUT_RESPOND return client_operation_send(target_handle.write_handle, data, len, ATT_OP_WRITE); } + +/** + * @brief 发送 Write Without Response 操作数据 + * + * @param priv: 私有数据指针 (未使用) + * @param data: 要发送的数据 + * @param len: 数据长度 + * @return int 操作结果 + */ static int client_write_without_respond_send(void *priv, u8 *data, u16 len) { + // 调用内部函数,使用 Write Without Response Handle,操作类型为 ATT_OP_WRITE_WITHOUT_RESPOND return client_operation_send(target_handle.write_no_respond, data, len, ATT_OP_WRITE_WITHOUT_RESPOND); } + +/** + * @brief 发送 Read 操作请求 + * + * @param priv 私有数据指针 (未使用) + * @return int 操作结果 + */ static int client_read_value_send(void *priv) { - u16 tmp_flag = 0x55A1; + u16 tmp_flag = 0x55A1; // 固定值,用于 Read 操作 + // 调用内部函数,使用 Read Handle,操作类型为 ATT_OP_READ return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ); } + +/** + * @brief 发送 Read Long 操作请求 + * + * @param priv + * @return int + */ static int client_read_long_value_send(void *priv) { - u16 tmp_flag = 0x55A2; + u16 tmp_flag = 0x55A2; // 固定值,用于 Read Long 操作 + // 调用内部函数,使用 Read Handle,操作类型为 ATT_OP_READ_LONG return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ_LONG); } +//====================================================================================== +// BLE 扫描配置和控制 +//====================================================================================== -//扫描数设置 +// 初始化扫描参数 static void scanning_setup_init(void) { + // 配置扫描类型、间隔和窗口 ble_op_set_scan_param(SET_SCAN_TYPE, SET_SCAN_INTERVAL, SET_SCAN_WINDOW); } + +/** + * @brief 使能或禁用 BLE 扫描 + * + * @param priv + * @param en + * @return int APP_BLE_NO_ERROR - 成功, APP_BLE_OPERATION_ERROR - 操作失败 + */ 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; - } + ble_state_e next_state, cur_state; // 目标状态和当前状态 + // 根据 en 的值确定目标状态 if (en) { - next_state = BLE_ST_SCAN; + next_state = BLE_ST_SCAN; // 使能扫描,目标状态为 SCAN } else { - next_state = BLE_ST_IDLE; + next_state = BLE_ST_IDLE; // 禁用扫描,目标状态为 IDLE } + cur_state = get_ble_work_state(); // 获取当前工作状态 - cur_state = get_ble_work_state(); + // 检查当前状态是否允许切换到目标状态 switch (cur_state) { case BLE_ST_SCAN: case BLE_ST_IDLE: @@ -1209,384 +1614,519 @@ static int bt_ble_scan_enable(void *priv, u32 en) 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); // 更新工作状态 - log_info("scan_en:%d\n", en); - set_ble_work_state(next_state); - - if (en) { - scanning_setup_init(); + if (en) { // 如果是使能扫描 + scanning_setup_init(); // 配置扫描参数 } + // 调用协议栈 API 开启或关闭扫描 + // 第二个参数 0 表示不进行扫描过滤 (即扫描所有设备) ble_op_scan_enable2(en, 0); - - return APP_BLE_NO_ERROR; + return APP_BLE_NO_ERROR; // 返回操作成功 } +//====================================================================================== +// BLE Client 回调函数注册 +//====================================================================================== + + +/** + * @brief 注册数据接收唤醒回调函数 + * + * @param priv + * @param cbk 回调函数指针 + * @return int APP_BLE_NO_ERROR - 成功 + */ static int client_regiest_wakeup_send(void *priv, void *cbk) { - /* att_regist_wakeup_send(cbk); */ + /* att_regist_wakeup_send(cbk); // 调用协议栈 API 注册唤醒发送回调 (注释掉) */ + ble_resume_send_wakeup = cbk; // 保存唤醒发送的回调函数指针 return APP_BLE_NO_ERROR; } + + +/** + * @brief 注册数据接收回调函数 + * + * @param priv 私有数据指针 (用于传递给回调函数) + * @param cbk 回调函数指针 + * @return int APP_BLE_NO_ERROR - 成功 + */ static int client_regiest_recieve_cbk(void *priv, void *cbk) { - channel_priv = (u32)priv; - app_recieve_callback = cbk; + channel_priv = (u32)priv; // 保存私有数据指针 + app_recieve_callback = cbk; // 保存接收回调函数指针 return APP_BLE_NO_ERROR; } + +/** + * @brief 注册 BLE 状态改变回调函数 + * + * @param priv + * @param cbk + * @return int APP_BLE_NO_ERROR - 成功 + */ static int client_regiest_state_cbk(void *priv, void *cbk) { - channel_priv = (u32)priv; - app_ble_state_callback = cbk; + channel_priv = (u32)priv; // 保存私有数据指针 + app_ble_state_callback = cbk; // 保存状态回调函数指针 return APP_BLE_NO_ERROR; } -//该接口重新配置搜索的配置项 +//====================================================================================== +// BLE Client 配置初始化 +//====================================================================================== + + +/** + * @brief 初始化 Client 的配置 + * + * @param priv + * @param cfg 指向 client_conn_cfg_t 配置结构体的指针 + * @return int 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 + client_config = cfg; // 更新全局的 Client 配置指针 return APP_BLE_NO_ERROR; } -//可配置进入强制搜索方式连接,更加信号强度过滤设备 +//====================================================================================== +// 强制搜索和 RSSI 过滤设置 +//====================================================================================== + + +/** + * @brief 配置强制搜索模式和 RSSI 过滤 + * + * @param onoff 0 - 关闭强制搜索, 1 - 开启强制搜索 + * @param rssi RSSI 过滤阈值 (负值,越接近 0 信号越强) + * @return int 0 - 成功 + */ static int client_force_search(u8 onoff, s8 rssi) { - force_seach_rssi = rssi; + force_seach_rssi = rssi; // 设置 RSSI 阈值 + // 如果强制搜索开关状态发生改变 if (force_seach_onoff != onoff) { - - force_seach_onoff = onoff; - //强制搜索前后,关创建监听 + force_seach_onoff = onoff; // 更新开关状态 + // 如果当前正在创建连接,则取消它 if (get_ble_work_state() == BLE_ST_CREATE_CONN) { - client_create_connection_cannel(); + client_create_connection_cannel(); // 取消创建连接 } } return 0; } +//====================================================================================== +// API 函数:创建 BLE 连接 (根据地址或配对信息) +//====================================================================================== + +/** + * @brief 创建 BLE 连接 + * + * @param addr: 目标设备的 MAC 地址 (如果 mode=1,则忽略此参数) + * @param addr_type: 目标设备的地址类型 (如果 mode=1,则忽略此参数) + * @param mode: 连接模式: 0 - 根据地址创建, 1 - 根据配对信息创建 (自动重连) + * @return int 0 - 成功, APP_BLE_OPERATION_ERROR - 操作失败 + */ static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) { - u8 cur_state = get_ble_work_state(); + 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: + 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); + bt_ble_scan_enable(0, 0); // 停止扫描 } - //pair mode - if (mode == 1) { + // 根据 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; - } - + // 如果有配对信息 + 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; + return APP_BLE_OPERATION_ERROR; // 返回操作失败 } - } else { - log_info("addr to creat!\n"); - log_info_hexdump(addr, 7); - bt_ble_create_connection(addr, addr_type); + } else { // 如果是按地址创建连接 + log_info("addr to creat!\n"); // 打印按地址创建日志 + log_info_hexdump(addr, 7); // 打印目标设备地址 + bt_ble_create_connection(addr, addr_type); // 使用指定的地址和类型创建连接 } - return 0; + return 0; // 返回成功 } +//====================================================================================== +// API 函数:取消 BLE 连接创建 +//====================================================================================== + +// 取消 BLE 连接创建 static int client_create_cannel_api(void) { + // 如果当前状态是正在创建连接 if (get_ble_work_state() == BLE_ST_CREATE_CONN) { - client_create_connection_cannel(); - return 0; + client_create_connection_cannel(); // 调用内部函数取消创建 + return 0; // 返回成功 } - return 1; + return 1; // 返回操作失败 } +//====================================================================================== +// BLE Client 操作接口结构体 +//====================================================================================== + +// 定义 BLE Client 的操作接口结构体 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, + .scan_enable = bt_ble_scan_enable, // 扫描使能/禁用接口 + .disconnect = ble_disconnect, // 断开连接接口 + .get_buffer_vaild = get_buffer_vaild_len, // 获取发送缓冲区可用空间接口 + .write_data = (void *)client_write_send, // 写入数据接口 (默认使用 Write Without Response) + .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, // 获取当前工作状态接口 }; +// 获取 BLE Client 操作接口表 struct ble_client_operation_t *ble_get_client_operation_table(void) { - return &client_operation; + return &client_operation; // 返回操作接口结构体 } -#define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey -//重设passkey回调函数,在这里可以重新设置passkey -//passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 +//====================================================================================== +// 安全管理器 (SM) 相关配置 (配对和加密) +//====================================================================================== + +#define PASSKEY_ENTER_ENABLE 0 // 输入 Passkey 使能标志 (0: 禁用, 1: 使能) + +// 重设 Passkey 的回调函数 +// key: 指向要设置的 Passkey 的指针 +// 在配对过程中,如果需要 Passkey,会调用此函数来获取新的 Passkey static void reset_passkey_cb(u32 *key) { -#if 1 - u32 newkey = rand32();//获取随机数 - - newkey &= 0xfffff; - if (newkey > 999999) { - newkey = newkey - 999999; //不能大于999999 +#if 1 // 使用随机数生成 Passkey + u32 newkey = rand32(); // 获取一个随机数 + newkey &= 0xfffff; // 取随机数的低 20 位 (确保不超过 6 位数字) + if (newkey > 999999) { // 如果大于 999999 (6 位数字的最大值) + newkey = newkey - 999999; // 调整使其不超过 6 位数字 } - *key = newkey; //小于或等于六位数 - log_info("set new_key= %06u\n", *key); + *key = newkey; // 设置新的 Passkey + log_info("set new_key= %06u\n", *key); // 打印设置的新 Passkey #else - *key = 123456; //for debug + *key = 123456; // for debug // 硬编码 Passkey (用于调试) #endif } -#if 0 -//协议栈内部调用 -extern void sm_set_master_request_pair(int enable); +/* +// SM (Security Manager) 初始化配置函数 +// io_type: IO 能力 (例如 IO_CAPABILITY_DISPLAY_ONLY) +// auth_req: 认证请求 (例如 SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING) +// min_key_size: 最小密钥长度 +// security_en: 安全模式使能标志 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); - + // setup SM: Display only + sm_init(); // 初始化 SM 模块 + sm_set_io_capabilities(io_type); // 设置 IO 能力 + sm_set_authentication_requirements(auth_req); // 设置认证要求 + sm_set_encryption_key_size_range(min_key_size, 16); // 设置密钥长度范围 + sm_set_master_request_pair(security_en); // 设置 Master 是否请求配对 + sm_event_callback_set(&cbk_sm_packet_handler); // 设置 SM 事件回调函数 + // 如果 IO 类型是 DISPLAY_ONLY if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { - reset_PK_cb_register(reset_passkey_cb); + reset_PK_cb_register(reset_passkey_cb); // 注册 Passkey 重置回调函数 } } -#endif +*/ +//====================================================================================== +// BLE 协议栈初始化 +//====================================================================================== -//协议栈内部调用 +// BLE Profile 初始化函数 (由主任务调用) void ble_profile_init(void) { - log_info("ble profile init\n"); - le_device_db_init(); - ble_stack_gatt_role(1); + log_info("ble profile init\n"); // 打印初始化日志 + le_device_db_init(); // 初始化 LE 设备数据库 + ble_stack_gatt_role(1); // 设置 GATT 角色为 Client (1 表示 Client) -//#if PASSKEY_ENTER_ENABLE -// ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, client_config->security_en); +//#if PASSKEY_ENTER_ENABLE // 如果使能了 Passkey 输入 +// ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, client_config->security_en); // 初始化 SM (Display Only, MITM, Bonding) //#else -// ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, client_config->security_en); +// ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, client_config->security_en); // 初始化 SM (No Input/Output, MITM, Bonding) //#endif /* setup ATT client */ - gatt_client_init(); - gatt_client_register_packet_handler(cbk_packet_handler); - + gatt_client_init(); // 初始化 GATT Client + gatt_client_register_packet_handler(cbk_packet_handler); // 注册 GATT Client 事件处理函数 // 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); + hci_event_callback_set(&cbk_packet_handler); // 注册 HCI 事件回调函数 + le_l2cap_register_packet_handler(&cbk_packet_handler); // 注册 L2CAP 事件回调函数 + ble_vendor_set_default_att_mtu(ATT_LOCAL_MTU_SIZE); // 设置默认的 ATT MTU } +//====================================================================================== +// 设备绑定初始化 +//====================================================================================== +// 初始化设备绑定配置 static void device_bonding_init(void) { int i; - int cfg_bonding = 0; - client_match_cfg_t *cfg; + 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) { + if (cfg == NULL) { // 如果配置为空,跳过 continue; } - if (cfg->bonding_flag) { - cfg_bonding = 1; + if (cfg->bonding_flag) { // 如果配置了 bonding_flag 为 1 + cfg_bonding = 1; // 设置需要绑定的标志 + break; // 找到一个需要绑定的,就可以停止遍历 } } + + // 如果没有配置需要绑定的设备 if (!cfg_bonding) { - clear_bonding_info(); + clear_bonding_info(); // 清除所有的配对信息 } } +//====================================================================================== +// 低功耗 (LP) 目标配置 +//====================================================================================== + +// 检查 Client 是否处于空闲状态 (用于低功耗管理) static u8 client_idle_query(void) { + // 返回 0 表示非空闲 (需要保持唤醒) + // 如果需要实现更精细的空闲判断,可以在这里添加逻辑 return 0; } +// 定义一个低功耗目标 REGISTER_LP_TARGET(client_user_target) = { - .name = "client_user_demo", - .is_idle = client_idle_query, + .name = "client_user_demo", // 目标名称 + .is_idle = client_idle_query, // 空闲查询函数 }; +//====================================================================================== +// BLE Client 模块初始化和退出 +//====================================================================================== - - +// BLE Client 模块初始化函数 void bt_ble_init(void) { - log_info("***** ble_init******\n"); -#if WIRELESS_TOOL_BLE_NAME_EN - u8 *config_name; - u8 config_name_len; + log_info("***** ble_init******\n"); // 打印初始化开始日志 + +#if WIRELESS_TOOL_BLE_NAME_EN // 如果使能了 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); +#if (WIRELESS_24G_ENABLE) // 如果使能了 2.4G 功能 + rf_set_24g_hackable_coded(WIRELESS_24G_CODE_ID); // 设置 2.4G 编码 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); + +#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); + // 为匹配名称分配内存并拷贝 + 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); + 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); + set_ble_work_state(BLE_ST_INIT_OK); // 设置工作状态为初始化完成 + conn_pair_vm_do(&conn_pair_info, 0); // 从 VM 读取配对信息 -#if !WIRELESS_PAIR_BONDING - device_bonding_init(); +#if !WIRELESS_PAIR_BONDING // 如果未使能无线配对绑定 + device_bonding_init(); // 初始化设备绑定配置 #endif - ble_module_enable(1); + + ble_module_enable(1); // 使能 BLE 模块 (开启扫描) + + // 以下是与 WiFi 相关的配置,可能用于协同工作 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); +#if TCFG_WIFI_DETCET_PRIOR // 如果使能了 WiFi 检测优先级 + wifi_detect_set_master_first(0); // 设置 WiFi 为 Master First #else - wifi_detect_set_master_first(1); + wifi_detect_set_master_first(1); // 设置 BLE 为 Master First #endif #endif -#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) - client_timer_start(); +#if (SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE) // 如果使能了数据速率显示 + client_timer_start(); // 启动数据速率显示定时器 #endif /* SHOW_RX_DATA_RATE | SHOW_TX_DATA_RATE */ } +// BLE Client 模块退出函数 void bt_ble_exit(void) { - log_info("***** ble_exit******\n"); + log_info("***** ble_exit******\n"); // 打印退出日志 } +// API 函数:断开 BLE 连接 (统一接口) void ble_app_disconnect(void) { - ble_disconnect(NULL); + ble_disconnect(NULL); // 调用断开连接函数 } -//统一接口,关闭模块 + +//====================================================================================== +// BLE 模块开关控制 +//====================================================================================== + +// API 函数:统一接口,控制 BLE 模块的开关 +// enable: 0 - 关闭模块, 1 - 打开模块 void bt_ble_adv_enable(u8 enable) { - ble_module_enable(enable); + ble_module_enable(enable); // 调用内部的模块开关函数 } -//模块开关 +// BLE 模块开关控制函数 +// en: 0 - 关闭模块, 1 - 打开模块 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 { + 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); + scan_ctrl_en = 0; // 禁止扫描控制 + ble_disconnect(NULL); // 断开连接 } else { - bt_ble_scan_enable(0, 0); - scan_ctrl_en = 0; + // 如果未连接 + bt_ble_scan_enable(0, 0); // 关闭扫描 + scan_ctrl_en = 0; // 禁止扫描控制 } } - } +//====================================================================================== +// 连接参数更新 API +//====================================================================================== + +// API 函数:发送连接参数更新请求 void client_send_conn_param_update(void) { - struct conn_update_param_t *param = (void *)&connection_param_table[send_param_index];//for test + // 从预定义的连接参数表中选择一个参数进行更新 (用于测试) + 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); + ble_op_conn_param_update(con_handle, param); // 发起连接参数更新请求 } } +//====================================================================================== +// 地址和外部调用发送 +//====================================================================================== - -//---------------------------------------------------------------------------------- -//lmx +// 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 (MUTIl_CHARGING_BOX_EN) // 如果使能了多路充电盒功能 + u8 *mac_addr = get_chargebox_adv_addr(); // 获取充电盒的 MAC 地址 if (mac_addr) { - swapX(mac_addr, mac_addr_buf, 6); + swapX(mac_addr, mac_addr_buf, 6); // 交换 MAC 地址到缓冲区 } - /* printf("mac_addr:"); */ /* printf_buf(mac_addr_buf, 6); */ - -#else - swapX(bt_get_mac_addr(), mac_addr_buf, 6); +#else // 否则使用默认的蓝牙 MAC 地址 + swapX(bt_get_mac_addr(), mac_addr_buf, 6); // 获取并填充蓝牙 MAC 地址 #endif } /** - * @brief 发送数据给server - * - * @param data - * @param length + * @brief 发送数据给 BLE Server (Client 发送数据给 Peripheral) + * + * @param data 要发送的数据指针 + * @param length 要发送的数据长度 */ void g_send_data_to_ble_server(const u8* data, u16 length){ // 检查数据长度是否有效 - if (length == 0 || length > 512) { + if (length == 0 || length > 512) { // 长度限制为 1 到 512 字节 printf("Error: Data length %d is out of range (1-512)\n", length); return; } - + + // 调用 client_operation_send 函数发送数据 + // 使用 default_client_write_handle (之前通过 CLI_EVENT_MATCH_UUID 获取) + // 数据类型为 ATT_OP_WRITE_WITHOUT_RESPOND (写无响应) int ret = client_operation_send(default_client_write_handle, data, length, ATT_OP_WRITE_WITHOUT_RESPOND); - if(ret == 0){ + if(ret == 0){ // 如果发送成功 (返回值 0 表示成功) printf("success: send data to server\n"); return; } - printf("error: send data to server\n"); + printf("error: send data to server\n"); // 发送失败 } -#endif - - +#endif // (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_WIRELESS_MIC_CLIENT) diff --git a/apps/earphone/xtell_remote_control/ble_handler/client_handler copy.c b/apps/earphone/xtell_remote_control/ble_handler/client_handler.c.hide similarity index 100% rename from apps/earphone/xtell_remote_control/ble_handler/client_handler copy.c rename to apps/earphone/xtell_remote_control/ble_handler/client_handler.c.hide diff --git a/cpu/br28/tools/aec.bin b/cpu/br28/tools/aec.bin index 31ebf3e..35080f1 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 efa6c05..481d73b 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 218ee04..b1b3469 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 7bfd36c..b962841 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 d85a420..695dc0f 100644 --- a/cpu/br28/tools/sdk.elf.resolution.txt +++ b/cpu/br28/tools/sdk.elf.resolution.txt @@ -5205,15 +5205,12 @@ 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,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,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