华为 HiLink 接入
本文档介绍 AC63 系列蓝牙 SoC SDK 中接入华为 HiLink(华为智能家居/智慧生活)生态的实现,涵盖 HiLink 协议栈、任务调度、GATT Profile、OTA 升级与应用集成的完整机制。
Purpose and Scope
本页面向希望在 AC63 SDK 上开发 HiLink 设备的开发者,完整说明 HiLink 接入能力的端到端实现:
- HiLink 协议栈(
hilink_protocol.c/h):消息编解码、命令类型、AES-GCM 加解密相关定义; - 任务调度层(
hilink_task.c/h):基于环形缓冲区 + 信号量的独立任务,负责 BLE 数据包的接收与分发; - HiLink OTA(
hilink_ota.c/h):基于双 Bank 升级的固件空中升级通道; - BLE GATT Profile(
hilink_profile.h):华为 HiLink 私有服务与特征值的二进制 Profile 定义; - 应用集成(
app_hilink.c、app_main.c):应用入口、蓝牙初始化、软关机与线程创建。
与 HiLink 相关的密钥协商细节、华为云账号绑定流程属于华为私有协议,SDK 中仅保留数据结构与消息入口,具体字节级语义以仓库内 doc/HiLink协议开发说明/HiLink协议开发说明.pdf 及华为官方文档为准。其他第三方接入(如涂鸦、米家等)不在本页范围内,参见目录中对应的第三方集成页面。
Overview
华为 HiLink 是华为面向智能家居设备推出的互联协议。在 AC63 蓝牙 SDK 中,设备以 BLE GATT 从机 身份暴露华为定义的私有服务(UUID 前缀 15F1E6xx-A277-43FC-A484-DD39EF8A9100),通过特征值读写承载 HiLink 消息。手机端华为智慧生活 App 作为 GATT 主机发起连接、配对与数据交互。
整个接入采用"协议栈 + 独立任务 + 应用壳"的三层结构:
- 协议层负责 HiLink 消息的编解码、设备信息描述(
dev_info_t)与认证信息管理(hi_auth_info_t),并对消息按REQ/RSP/RPT(请求/响应/上报)分类; - 任务层(
hilink_task)把 BLE 控制器回调上来的裸数据写入环形缓冲区(cbuf),由独立任务按包头中的通道号分发到设备信息消息处理(hilink_msg_handle)或 OTA 控制/数据通道; - 应用层(
app_hilink.c)负责系统启动流程:切换时钟、初始化 EDR/BLE、注册 Profile、处理电源事件与软关机。
该设计把协议处理与 BLE 协议栈解耦:即便蓝牙链路抖动或数据突发,环形缓冲 + 信号量也能平滑吸收,协议解析不阻塞蓝牙任务;OTA 通道与设备信息通道分离,保证升级大流量数据与业务消息互不干扰。
Architecture
flowchart TD
subgraph sg_App["应用层 apps/spp_and_le/examples/hilink"]
AppHilink["app_hilink.c<br/>应用状态机/启动/软关机"]
Profile["hilink_profile.h<br/>HiLink GATT Profile"]
AppMain["app_main.c<br/>创建 hilink_task 线程"]
end
subgraph sg_Protocol["HiLink 协议栈 apps/common/third_party_profile/hilink_protocol"]
Task["hilink_task.c<br/>环形缓冲+信号量分发"]
Proto["hilink_protocol.c<br/>消息解析/设备与认证信息"]
Ota["hilink_ota.c<br/>OTA 控制/数据通道"]
end
subgraph sg_Bt["蓝牙协议栈"]
BtStack["btstack<br/>BLE GATT/ATT"]
end
subgraph sg_Hw["硬件/系统服务"]
Flash["dual_bank_updata_api<br/>双 Bank Flash 升级"]
Power["电源管理<br/>软关机"]
end
AppMain -->|"task_create hilink_task"| Task
BtStack -->|"hilink_packet_recieve"| Task
Task -->|"HILINK_DEVICE_INFO_MSG_CH"| Proto
Task -->|"HILINK_OTA_CTL/DATA_MSG_CH"| Ota
AppHilink -->|"注册/使用"| Profile
Profile --> BtStack
Ota --> Flash
AppHilink --> Power
架构说明:app_main.c 在系统启动时按 CONFIG_APP_HILINK 创建 hilink_task 线程(见 app_main.c),BLE 协议栈通过 hilink_packet_recieve() 把收到的数据写入任务层环形缓冲区;任务按包头的 packet_channel 分发给协议层或 OTA 层。hilink_profile.h 中定义的 GATT 表由应用层注册进 btstack,手机 App 通过读写/指示特征值完成与协议层的双向数据交换。OTA 通道最终调用 dual_bank_updata_api 落盘到 Flash,实现断点续传式的固件升级。
classDiagram
class dev_info_t {
+const char *prodId
+const char *sn
+const char *dev_id
+const char *model
+const char *dev_t
+const char *manu
+const char mac[18]
+const char *hiv
+const char *fwv
+const char *hwv
+const char *swv
+const char *prot_t
}
class hi_auth_info_t {
+uint8_t hilink_authcode[16]
+uint8_t hilink_sessionkey[16]
+uint8_t sessid[32]
+uint8_t hilink_authcodeid_tmp[33]
+uint8_t hilink_hmackey[32]
+char time[13]
+uint8_t hilink_pair_flag
+hi_attribute_t hilink_attr
}
class hi_msg_store_t {
+uint8_t msg_id
+uint16_t data_len
+uint16_t data_index
+uint8_t *data
}
hi_auth_info_t --> hi_attribute_t : "包含属性"
dev_info_t ..> hi_auth_info_t : "配套使用"
以上类型定义取自 hilink_protocol.h:dev_info_t 描述设备身份(产品 ID、SN、型号、MAC、各版本号),hi_auth_info_t 承载配网/认证后的会话材料(认证码、会话密钥、会话 ID、HMAC 密钥),hi_msg_store_t 用于暂存分片消息。
核心模块与实现分析
1. 协议层:hilink_protocol
协议头文件 hilink_protocol.h 定义了 HiLink 消息的基本契约:
| 宏 | 值 | 含义 |
|---|---|---|
HILINK_MCU | 0 | 标识设备端为 MCU(非 SoC 主控) |
AES128_KEY_LENGTH | 128 | AES-128 密钥长度(bit) |
GCM_TAG_LEN | 16 | GCM 认证标签长度(字节) |
CMD_TYPE_REQ | 0 | 命令类型:请求 |
CMD_TYPE_RSP | 1 | 命令类型:响应 |
CMD_TYPE_RPT | 2 | 命令类型:上报(主动上报状态/事件) |
MSG_WITHOUT_ENCRY | 0 | 消息明文传输 |
MSG_ENCRY | 1 | 消息加密传输 |
设计意图:命令类型三态(REQ/RSP/RPT)是 HiLink 消息体系的基础——App 下发指令为 REQ,设备处理完毕回 RSP,设备状态变化主动推送用 RPT。加解密开关 MSG_ENCRY 配合 AES128_KEY_LENGTH/GCM_TAG_LEN 表明协议采用 AES-128-GCM 认证加密:GCM 同时提供机密性与完整性保护,防止中间人篡改固件或控制指令,这是 HiLink 安全模型的核心。
协议对外只暴露一个处理入口:
void hilink_msg_handle(uint8_t *buf, uint16_t len);
它接收完整的一条 HiLink 消息(已由任务层组包完成),在 hilink_protocol.c 内部完成解密、解析与业务分发。hi_msg_store_t 的存在说明协议支持分片消息重组(data_len + data_index 记录片段的长度与偏移),用于承载超过单包 MTU 的长消息。
2. 任务调度层:hilink_task
任务层 hilink_task.c 是 HiLink 数据通路的"心脏",由三部分组成:
a) 全局控制块:HILINK_PACKET_CONTROL HILINK_packet_c,内含信号量 hilink_sem、环形缓冲区 cbuf 及其内存 hilink_buf。
b) 任务主循环:hilink_task() 永久阻塞在 os_sem_pend 上,被唤醒后检查 cbuf 中是否凑齐一帧(数据长度 > HILINK_PACKET_HEAD_LEN 包头长度),随后:
- 读取包头(含包长
len与通道号packet_channel); malloc(len)分配一帧缓冲区;- 读取整帧数据;
- 按通道号分发:
HILINK_DEVICE_INFO_MSG_CH→hilink_msg_handle()(业务/设备信息消息);HILINK_OTA_CTL_MSG_CH→hilink_ota_ctl_deal()(OTA 控制:开始/校验/结束);HILINK_OTA_DATA_MSG_CH→hilink_ota_data_deal()(OTA 数据块写入);
free(buffer)释放。
设计意图:把"接收"(BLE 中断/回调上下文)与"处理"(任务上下文)分离——接收侧只做 cbuf_write 快速入队,处理侧在独立线程中慢速消费,天然实现生产者-消费者解耦,避免在蓝牙回调里做加解密等耗时操作导致丢包。
c) 初始化与接收接口:
int hilink_task_init(void)
{
os_sem_create(&(__this->hilink_sem), 0);
u32 malloc_size = HILINK_MSG_POOL_SIZE;
__this->hilink_buf = malloc(malloc_size);
memset(__this->hilink_buf, 0x0, malloc_size);
cbuf_init(&(__this->cbuf), __this->hilink_buf, malloc_size);
int ret = task_create(hilink_task, 0, "hilink_task");
if (ret) {
log_info("hilink task create error:%d", ret);
}
return 0;
}
void hilink_packet_recieve(void *buf, u16 len)
{
if (cbuf_is_write_able(&(__this->cbuf), len) >= len) {
cbuf_write(&(__this->cbuf), buf, len);
} else {
log_info("[L]\n");
}
os_sem_post(&(__this->hilink_sem));
}
设计意图:hilink_packet_recieve 是 BLE 协议栈到 HiLink 任务层的唯一入口,任何 GATT Write 收到的裸数据都经此入队。cbuf_is_write_able 的容量检查保证环形缓冲区永不溢出;写满时打印 [L](overflow 简记)并丢弃,属于有界背压策略——宁可丢帧也不破坏缓冲区一致性。task_create 创建的线程在 app_main.c 中定义为 {"hilink_task", 2, 0, 1024, 0}(优先级 2、栈 1024 字)。
3. OTA 升级:hilink_ota
hilink_ota.c 实现 HiLink 固件空中升级:
- 依赖
dual_bank_updata_api.h(双 Bank 升级接口)与hilink_ota.h; - 维护三个静态状态对象:
hilink_ota_t hilink_ota—— 当前升级会话(进度、分块参数);hilink_hash_list_t hilink_hash—— 分块哈希链表,用于逐块校验数据完整性;hilink_signature_t hilink_signature—— 整包签名校验;
- 通过
extern dev_info_t *hilink_info与extern uint16_t hilink_mtu读取设备信息与协商后的 MTU; - 关键函数:
ota_reply(uint8_t clean_map)回复 OTA 结果(并按需清理升级区映射)、hilink_ota_rsp_send(uint16_t op, ...)发送 OTA 命令响应。
设计意图:双 Bank(A/B)升级机制保证升级失败时可回滚到上一版本;逐块哈希 + 整包签名构成"边收边验"链路——App 分块下发,设备每块校验哈希,最后校验整体签名,任何篡改都会导致升级中止并回滚,符合 HiLink 对固件安全的要求。MTU 协商结果(hilink_mtu)用于决定单帧 OTA 数据块大小,最大化吞吐同时避免超出链路 MTU。
4. 应用集成:app_hilink.c 与 app_main.c
apps/spp_and_le/examples/hilink/app_hilink.c 是 HiLink Demo 应用(以 CONFIG_APP_HILINK 编译开关启用),职责包括:
- 启动序列
hilink_app_start():打印 banner → 首次进入时clk_set("sys", BT_NORMAL_HZ)切到蓝牙工作频率 →bt_pll_para()配置 PLL → 按TCFG_USER_EDR_ENABLE/TCFG_USER_BLE_ENABLE分别btstack_edr_start_before_init/btstack_ble_start_before_init→btstack_init()完成协议栈初始化 →sys_key_event_enable()使能按键; - BLE 初始化配置:
hilink_data_ble_config设置appearance = BD_CLASS_HEADPHONES,并依据DOUBLE_BT_SAME_MAC决定 EDR/BLE 是否同 MAC; - 电源事件
hilink_power_event_to_user():把电源事件包装成SYS_DEVICE_EVENT通过sys_event_notify广播; - 软关机
hilink_set_soft_poweroff():先主动断开蓝牙链路(btstack_ble_exit/btstack_edr_exit),延时WAIT_DISCONN_TIME_MS(300ms) 确保链路断开后调用power_set_soft_poweroff()——注释明确说明"必须先主动断开蓝牙链路,否则要等链路超时断开",避免关机时序问题; - 状态机
hilink_state_machine():标准杰理应用状态机(APP_STA_CREATE→ ...),处理应用创建、消息分发等生命周期。
static void hilink_set_soft_poweroff(void)
{
log_info("set_soft_poweroff\n");
is_app_hilink_active = 1;
//必须先主动断开蓝牙链路,否则要等链路超时断开
#if TCFG_USER_BLE_ENABLE
btstack_ble_exit(0);
#endif
#if TCFG_USER_EDR_ENABLE
btstack_edr_exit(0);
#endif
#if (TCFG_USER_EDR_ENABLE || TCFG_USER_BLE_ENABLE)
//延时300ms,确保BT退出链路断开
sys_timeout_add(NULL, power_set_soft_poweroff, WAIT_DISCONN_TIME_MS);
#else
power_set_soft_poweroff();
#endif
}
来源:app_hilink.c
在 app_main.c 中,CONFIG_APP_HILINK 同时决定线程表项({"hilink_task", 2, 0, 1024, 0})与应用启动动作 ACTION_HILINK_MAIN(it.name = "hilink"),即编译该宏后系统会自动拉起 HiLink 任务并进入 HiLink 应用。
BLE GATT Profile:hilink_profile.h
华为 HiLink 依赖一组固定的 BLE 服务。hilink_profile.h 中的 hilink_profile_data[] 是二进制 GATT 表(由杰理 gatt_inc_generator.exe 工具生成),定义如下结构:
| Handle | 类型 | UUID | 属性 |
|---|---|---|---|
| 0x0001 | PRIMARY_SERVICE | 0x1800 (GAP) | - |
| 0x0003 | VALUE | 0x2A00 (Device Name) | READ | DYNAMIC |
| 0x0004 | PRIMARY_SERVICE | 0x1801 (GATT) | - |
| 0x0006 | VALUE | 0x2A05 (Service Changed) | INDICATE |
| 0x0007 | CCCD | 0x2902 | - |
| 0x0008 | PRIMARY_SERVICE | 15F1E600-A277-43FC-A484-DD39EF8A9100 | HiLink 控制服务 |
| 0x000A | VALUE | 15F1E601-...-DD39EF8A9100 | INDICATE | READ | DYNAMIC |
| 0x000B | CCCD | 0x2902 | - |
| 0x000D | VALUE | 15F1E602-...-DD39EF8A9100 | WRITE | DYNAMIC |
| 0x000E | PRIMARY_SERVICE | 15F1E610-A277-43FC-A484-DD39EF8A9100 | HiLink OTA 服务 |
| 0x0010 | VALUE | 15F1E611-...-DD39EF8A9100 | INDICATE | WRITE | DYNAMIC |
| 0x0011 | CCCD | 0x2902 | - |
| 0x0013 | VALUE | 15F1E612-...-DD39EF8A9100 | WRITE_WITHOUT_RESPONSE | DYNAMIC |
通道语义(结合任务层分发逻辑):
- 15F1E601(下行→设备):手机 Write,走
HILINK_DEVICE_INFO_MSG_CH,即普通 HiLink 业务消息(配网、属性控制、查询等); - 15F1E602(设备→上行):设备 Indicate,用于回复/上报,App 订阅后通过 CCCD 0x000B 接收;
- 15F1E611(OTA 双向):OTA 控制通道(开始/停止/校验/响应),走
HILINK_OTA_CTL_MSG_CH; - 15F1E612(OTA 下行大流量):Write Without Response,承载 OTA 数据分块,走
HILINK_OTA_DATA_MSG_CH——无响应对写避免逐包握手,是升级吞吐的关键。
设计意图:业务通道与 OTA 通道分开(两个服务、四个特征值),使升级大流量数据不阻塞业务消息处理;OTA 数据用 WriteWithoutResponse 提升吞吐、控制命令用有响应 Write 保证可靠性、上行用 Indicate 由 App 主动订阅控制流量,是一套针对"控制面可靠、数据面高效"的典型 BLE 服务设计。
文件末尾导出了句柄宏(如 ATT_CHARACTERISTIC_15F1E601_A277_43FC_A484_DD39EF8A9100_01_VALUE_HANDLE 0x000a),应用层与协议栈通过这些宏直接引用特征值句柄,避免硬编码魔法数。
核心数据流
sequenceDiagram
participant Phone as 华为智慧生活 App
participant Bt as btstack BLE GATT
participant Task as hilink_task 线程
participant Proto as hilink_protocol.c
participant Ota as hilink_ota.c
participant Flash as 双 Bank Flash
Note over Phone,Flash: 业务消息通路(设备信息通道)
Phone->>Bt: Write 15F1E601 (HiLink 消息, 可加密)
Bt->>Task: hilink_packet_recieve(buf, len)
Task->>Task: cbuf_write + os_sem_post
Task->>Task: 读包头, channel=DEVICE_INFO
Task->>Proto: hilink_msg_handle(buf, len)
Proto->>Proto: AES-128-GCM 解密/解析, REQ/RSP/RPT 分发
Proto-->>Bt: 回写 Indicate (15F1E602)
Bt-->>Phone: Indicate 通知
Note over Phone,Flash: OTA 升级通路(控制 + 数据通道)
Phone->>Bt: Write 15F1E611 OTA 控制(开始)
Task->>Ota: hilink_ota_ctl_deal
loop 逐块下发
Phone->>Bt: WriteWithoutResponse 15F1E612 (数据块)
Task->>Ota: hilink_ota_data_deal
Ota->>Ota: 块哈希校验 (hilink_hash_list)
Ota->>Flash: dual_bank 写入
end
Phone->>Bt: Write 15F1E611 OTA 结束/校验
Task->>Ota: hilink_ota_ctl_deal
Ota->>Ota: 整包签名校验 (hilink_signature)
Ota->>Flash: 切换 Bank + 重启
Ota-->>Phone: 通过 15F1E611 Indicate 回复结果
逐步说明:
- 入队:GATT Write 回调调用
hilink_packet_recieve,数据进入环形缓冲并os_sem_post唤醒任务——接收路径 O(1),不涉及任何协议解析; - 组帧:
hilink_task依据包头长度字段判断帧完整性,malloc后整帧读出,避免 cbuf 中残留半包; - 分发:按
packet_channel路由到协议层或 OTA 层,两个通道互不阻塞; - 处理:协议层解密(AES-128-GCM)并解析为 REQ/RSP/RPT;OTA 层逐块校验哈希后写入双 Bank Flash;
- 回程:设备通过 Indicate 特征值向 App 上报结果/状态,App 侧收到通知后更新 UI 或发起下一动作。
异常路径:若 cbuf 容量不足(cbuf_is_write_able 失败),接收侧打印 [L] 并丢帧——由于协议层支持分片重组(hi_msg_store_t),对端会因缺少响应而重发,属于可恢复的丢包策略;malloc 失败时任务打印 buf malloc err 并退出循环,属致命错误,由系统 watchdog 兜底。
认证与设备信息
设备上电后需向 App 提供身份信息完成配网/绑定。dev_info_t 字段即为此设计:
| 字段 | 长度约束 | 说明 |
|---|---|---|
prodId | (0,5] | 设备 HiLink 认证号 |
sn | (0,40] | 设备唯一标识(SN) |
dev_id | - | 设备 ID |
model | (0,32] | 设备型号 |
dev_t | (0,4] | 设备类型 |
manu | (0,4] | 设备制造商 |
mac[18] | 固定 18 字节 | MAC 地址(字符串) |
hiv | (0,32] | HiLink 协议版本 |
fwv | [0,64] | 固件版本 |
hwv | [0,64] | 硬件版本 |
swv | [0,64] | 软件版本 |
prot_t | [1,3] | 设备协议类型 |
配网/认证成功后,hi_auth_info_t 保存会话密钥材料:hilink_authcode(16B 认证码)、hilink_sessionkey(16B 会话密钥,AES-GCM 加密数据用)、sessid(32B 会话 ID)、hilink_hmackey(32B HMAC 密钥)、time[13](时间戳,防重放)、hilink_pair_flag(配对标志)、hilink_attr(设备属性,如 onoff 开关状态)。hilink_authcodeid_tmp[33] 特意比 32 多 1 字节用于存放字符串结尾的 \0,注释直接标注了这一意图。
使用示例
示例 1:创建 HiLink 任务并接入数据接收
以下代码展示了 HiLink 任务层的初始化与接收接口——这是把 BLE 数据接入 HiLink 协议栈的标准写法(由 SDK 内部在启动时调用):
int hilink_task_init(void)
{
os_sem_create(&(__this->hilink_sem), 0);
u32 malloc_size = HILINK_MSG_POOL_SIZE;
__this->hilink_buf = malloc(malloc_size);
memset(__this->hilink_buf, 0x0, malloc_size);
cbuf_init(&(__this->cbuf), __this->hilink_buf, malloc_size);
int ret = task_create(hilink_task, 0, "hilink_task");
if (ret) {
log_info("hilink task create error:%d", ret);
}
return 0;
}
void hilink_packet_recieve(void *buf, u16 len)
{
if (cbuf_is_write_able(&(__this->cbuf), len) >= len) {
cbuf_write(&(__this->cbuf), buf, len);
} else {
log_info("[L]\n");
}
os_sem_post(&(__this->hilink_sem));
}
示例 2:任务主循环的通道分发
BLE 数据入队后,任务线程按包头通道号分发——新增业务通道时在此扩展 switch:
switch (hilink_packet_head.packet_channel) {
case HILINK_DEVICE_INFO_MSG_CH:
hilink_msg_handle(buffer, hilink_packet_head.len);
break;
case HILINK_OTA_CTL_MSG_CH:
hilink_ota_ctl_deal(buffer, hilink_packet_head.len);
break;
case HILINK_OTA_DATA_MSG_CH:
hilink_ota_data_deal(buffer, hilink_packet_head.len);
break;
}
示例 3:应用启动与 BLE 初始化
在 app_hilink.c 中,HiLink 应用首次启动时完成时钟切换、EDR/BLE 协议栈初始化与 GATT Profile 注册前置准备:
if (enter_btstack_num == 0) {
enter_btstack_num = 1;
clk_set("sys", BT_NORMAL_HZ);
#if (TCFG_USER_EDR_ENABLE || TCFG_USER_BLE_ENABLE)
u32 sys_clk = clk_get("sys");
bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0);
#if TCFG_USER_EDR_ENABLE
btstack_edr_start_before_init(NULL, 0);
#endif
#if TCFG_USER_BLE_ENABLE
btstack_ble_start_before_init(&hilink_data_ble_config, 0);
#endif
btstack_init();
#else
printf("no bt!!!");
#endif
}
/* 按键消息使能 */
sys_key_event_enable();
来源:app_hilink.c
示例 4:GATT 特征值句柄宏
hilink_profile.h 末尾导出特征值句柄宏,业务代码通过宏引用而非硬编码句柄值:
#define ATT_CHARACTERISTIC_2A00_01_VALUE_HANDLE 0x0003
#define ATT_CHARACTERISTIC_2a05_01_VALUE_HANDLE 0x0006
#define ATT_CHARACTERISTIC_2a05_01_CLIENT_CONFIGURATION_HANDLE 0x0007
#define ATT_CHARACTERISTIC_15F1E601_A277_43FC_A484_DD39EF8A9100_01_VALUE_HANDLE 0x000a
配置选项
HiLink 功能通过编译宏与线程表项启用,无运行时配置文件:
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
CONFIG_APP_HILINK | 编译宏 | 未定义 | 定义后编译 HiLink Demo 应用,创建 hilink_task 线程并设置 ACTION_HILINK_MAIN 启动动作 |
hilink_task 线程项 | 线程表项 | 优先级 2 / 栈 1024 | 在 app_main.c 中定义({"hilink_task", 2, 0, 1024, 0}) |
HILINK_MSG_POOL_SIZE | 宏 | 由 hilink_task.h 定义 | 环形缓冲池大小,决定可缓冲的帧数上限 |
HILINK_PACKET_HEAD_LEN | 宏 | 由 hilink_task.h 定义 | 帧头长度(含包长与通道号) |
HILINK_DEVICE_INFO_MSG_CH / HILINK_OTA_CTL_MSG_CH / HILINK_OTA_DATA_MSG_CH | 宏 | 由 hilink_task.h 定义 | 通道号枚举,用于帧分发 |
TCFG_USER_BLE_ENABLE / TCFG_USER_EDR_ENABLE | 编译宏 | 按工程 | 是否启用 BLE/EDR 协议栈,直接决定 HiLink 启动路径 |
DOUBLE_BT_SAME_MAC | 编译宏 | 按工程 | EDR 与 BLE 是否共用同一 MAC,影响 hilink_data_ble_config.same_address |
| HILINK 日志开关 | 日志配置 | v/i/d/w/e 均使能 | 见 log_config.c,LOG_TAG_CONST HILINK |
API 参考
void hilink_msg_handle(uint8_t *buf, uint16_t len)
- 描述:HiLink 业务消息唯一处理入口,接收完整一帧(已组包、含头部),内部完成解密、解析与 REQ/RSP/RPT 分发。定义于 hilink_protocol.h。
- 参数:
buf消息帧指针;len帧长度。 - 返回:无。回复通过 GATT Indicate 特征值(15F1E602)异步发出。
int hilink_task_init(void)
- 描述:初始化 HiLink 任务:创建信号量、分配
HILINK_MSG_POOL_SIZE环形缓冲、创建hilink_task线程。见 hilink_task.c。 - 返回:0 表示成功;
task_create返回非 0 时打印hilink task create error:%d。
void hilink_packet_recieve(void *buf, u16 len)
- 描述:BLE 协议栈数据接收接口(生产者侧):数据写入环形缓冲并唤醒任务线程。见 hilink_task.c。
- 参数:
buf原始数据;len数据长度。 - 行为:缓冲不足时打印
[L]并丢弃该帧(有界背压),随后仍os_sem_post。
void hilink_ota_ctl_deal(void *buf, u16 len) / void hilink_ota_data_deal(void *buf, u16 len)
- 描述:OTA 控制/数据通道处理函数(消费者侧),由
hilink_task按通道号调用;内部完成块哈希校验(hilink_hash_list_t)、双 Bank 写入与整包签名校验(hilink_signature_t)。 - 参数:
bufOTA 帧数据;len帧长度。 - 返回:无,结果经
hilink_ota_rsp_send(op, buf, len)回传。
void hilink_set_soft_poweroff(void)
- 描述:HiLink 软关机流程:先断开 BLE/EDR 链路,延时
WAIT_DISCONN_TIME_MS(300ms) 后调用power_set_soft_poweroff()。见 app_hilink.c。 - 设计要点:必须先主动断开蓝牙,避免关机时等待链路超时。
void hilink_power_event_to_user(u8 event)
- 描述:把电源事件包装为
SYS_DEVICE_EVENT(DEVICE_EVENT_FROM_POWER)广播给系统事件队列,供上层 UI/业务响应。 - 参数:
event电源事件码。
失败模式、边界情况与并发
缓冲溢出与丢帧
hilink_packet_recieve 中 cbuf_is_write_able 失败时打印 [L] 并丢弃整帧。这是有界背压设计:环形缓冲容量(HILINK_MSG_POOL_SIZE)决定吸收突发的能力。若手机端连续大流量写入(如 OTA 数据通道),而任务线程因加解密/Flash 写入繁忙,可能出现丢帧。由于协议层支持分片重组(hi_msg_store_t)且 OTA 通道有块哈希校验,对端(App 或 OTA 主控)检测到缺少响应后会重传,丢帧可恢复——但需保证重传机制存在,否则升级会停滞。
内存分配失败
任务主循环对每帧 malloc(len),失败时打印 buf malloc err 并 break 退出循环(线程结束)。这是致命路径:此后 hilink_packet_recieve 仍可写缓冲并 post 信号量,但无人消费,缓冲区最终写满后持续丢帧。生产环境依赖系统级 watchdog 或任务重启机制兜底;len 受帧头长度字段约束,理论上不应超过缓冲池大小,建议协议层对超长帧做拒收校验。
并发模型
- 生产者:BLE 协议栈回调(中断/协议栈任务上下文)调用
hilink_packet_recieve,只操作 cbuf 写指针 + 信号量 post,全程无锁但依赖 cbuf 的单生产者单消费者(SPSC)语义; - 消费者:
hilink_task线程独占 cbuf 读端,负责 malloc/解析/分发/释放; - 因此 cbuf 无需加锁,前提是接收入口只能有一个调用者——若未来有多个 GATT 特征值同时写入,需在接收侧串行化,否则 SPSC 假设被破坏;
hilink_ota/hilink_hash/hilink_signature为静态全局变量,只在任务线程内访问,天然线程安全;dev_info_t *hilink_info为跨模块 extern,若被其他线程修改需自行保证一致性。
时序边界
- 软关机要求先断开蓝牙链路再关机,
WAIT_DISCONN_TIME_MS(300ms) 延时不足或链路异常时可能导致关机被阻塞; - OTA 升级期间若出现断电,双 Bank 机制保证回滚到旧固件;若出现链路断开,任务层继续等待后续块,App 侧需提供断点续传或重新开始策略。
安全与加密边界
MSG_ENCRY指示消息加密,配套 AES-128-GCM;hilink_sessionkey只在配对成功后有效,未配对(hilink_pair_flag未置位)时设备应拒绝加密消息或仅接受白名单明文命令;time[13]时间戳用于防重放,设备 RTC 不准确时可能误拒合法消息——需评估时间同步策略。
性能与运维注意事项
- 吞吐瓶颈:OTA 数据走
WRITE_WITHOUT_RESPONSE(15F1E612),无逐包应答,吞吐上限取决于 BLE 连接间隔、MTU(hilink_mtu)与任务侧处理耗时。如需提升,可优先增大 MTU 与减小连接间隔; - CPU 占用:AES-128-GCM 解密与 SHA 哈希在任务线程内完成,属于 CPU 密集操作;
hilink_task优先级 2、栈 1024,若 Flash 写入慢可考虑调整任务优先级或拆分校验线程; - 日志:
LOG_TAG_CONST HILINK各级日志默认全开(见 log_config.c),量产固件建议关闭 d/v 级以降低开销;hilink_ota.c使用独立的[HILINK_OTA]printf 前缀,便于从串口日志中过滤升级过程; - 调试抓手:
printf_buf(log_info_hexdump)可打印收发原始帧,是排查加解密/组包问题的第一手段。
扩展点
- 新增业务通道:在
hilink_task.c的switch中增加新packet_channel枚举与对应处理函数,即可在任务线程内扩展独立协议通道,无需改动接收侧; - 新增设备属性:扩展
hi_attribute_t(当前仅有onoff),并同步华为开发者平台属性定义与 App 侧联动; - 替换认证算法:
hilink_protocol.c内封装 AES-GCM 与 HMAC 调用点,可替换为软件实现或硬件加密引擎,接口不变; - 自定义 OTA 策略:
hilink_ota.c依赖dual_bank_updata_api,可替换为单 Bank + 外部 Flash 方案,只要保留hilink_ota_ctl_deal/hilink_ota_data_deal的帧接口; - GATT Profile 调整:
hilink_profile.h由杰理 gatt 工具生成,修改服务/特征值后用工具重新生成二进制表并同步句柄宏; - 多设备形态:
dev_info_t字段完整覆盖华为平台对设备描述的要求,量产时从配置分区/产品信息模块填充即可,无需改协议层。