当前位置: 首页 > article >正文

【0x03】HCI_Connection_Complete事件详解

目录

一、事件概述

二、事件格式及参数详解

2.1. HCI_Connection_Complete事件格式

2.2. 事件参数 

2.2.1. Status

2.2.2. Connection_Handle

2.2.3. BD_ADDR

2.2.5. Encryption_Enabled

三、事件处理流程

3.1. 事件触发

3.2. 事件接收与解析

3.3. 状态更新与反馈

3.4. 后续操作与管理

3.5. 示例代码

四、使用场景

五、注意事项

5.1. 事件接收与解析

5.2. 参数处理

5.3. 连接状态管理与资源分配

5.4. 并发与异步操作处理


HCI_Connection_Complete事件是蓝牙通信中的一个重要事件,用于通知主机(Host)一个新的连接已经建立。

一、事件概述

HCI_Connection_Complete 事件的事件码为 0x03。此事件是蓝牙主机控制器接口(HCI)中的一个重要事件,用于向参与连接的两个主机表明一个新的连接已经成功建立。

同时,对于发出 HCI_Create_Connection、HCI_Accept_Connection_Request 或 HCI_Reject_Connection_Request 命令,并随后收到 HCI_Command_Status 事件的主机来说,该事件也用于告知其之前发出的命令最终是否成功。

二、事件格式及参数详解

2.1. HCI_Connection_Complete事件格式

在蓝牙HCI协议中,事件类型用于区分不同类型的事件,以便主机能够正确地解析和处理。

2.2. 事件参数 

HCI_Connection_Complete事件包含多个参数,这些参数提供了连接尝试的详细结果和相关信息。

2.2.1. Status

Status 参数用于指示蓝牙连接尝试的结果。

  • 0x00:表示蓝牙设备间的连接已经成功建立。此时,事件中的其他参数(如 Connection Handle、BD_ADDR 和 Link Type)将包含有关成功连接的有效信息。
  • 0x01 至 0xFF:表示连接尝试失败。具体的失败原因由 Status 参数的值决定,这些值对应于蓝牙协议中定义的控制器错误代码。蓝牙Controller错误代码全面概览_connection rejected due to limited resources-CSDN博客

2.2.2. Connection_Handle

当蓝牙设备成功建立连接时,蓝牙控制器会为该连接分配一个唯一的 Connection_Handle。这个句柄在连接的生命周期内有效,并可用于后续的数据通信和连接管理操作。例如,当主机想要向特定的蓝牙设备发送数据时,它会使用与该设备连接对应的 Connection_Handle 来指定目标设备。

  • 0x0000 to 0x0EFF表示 Connection_Handle 的有效值范围。由于只有12位是有效的,因此其最大值为 0x0EFF(即二进制的 0000 1110 1111),最小值为 0x0000。这个范围确保了 Connection_Handle 的唯一性,在同一时间内,蓝牙控制器不会为不同的连接分配相同的句柄。

在处理 HCI_Connection_Complete 事件时,主机应检查 Connection_Handle 参数的值,并将其存储在适当的数据结构中,以便在后续操作中使用。如果连接失败,则可能不会提供有效的 Connection_Handle

2.2.3. BD_ADDR

BD_ADDR表示蓝牙设备地址(Bluetooth Device Address)。用于表示与当前设备建立连接的另一个蓝牙设备的地址。

当两个蓝牙设备成功建立连接时,它们的 BD_ADDR 会被记录在连接信息中。这些信息可以用于后续的数据通信和连接管理操作。例如,主机可以使用 BD_ADDR 来指定要与之通信的蓝牙设备,或者查询与特定 BD_ADDR 关联的连接状态。

Link_Type 参数用于指示蓝牙连接的类型。

  • 0x00:表示 SCO(Synchronous Connection-Oriented)连接。SCO 连接主要用于语音传输,因为它提供了固定的带宽和较低的时延,对于实时语音通信至关重要。
  • 0x01:表示 ACL(Asynchronous Connection-Less)连接(数据通道)。ACL 连接用于数据传输,它提供了更灵活的带宽分配,可以适应不同类型的数据传输需求。ACL 连接是非面向连接的,意味着数据包可以在任何时候发送,而不需要先建立连接状态。
  • 所有其他值:保留供将来使用。

2.2.5. Encryption_Enabled

Encryption_Enabled 参数用于指示链路层加密是否已启用。

  • 如果为0x00,表示未启用加密。
  • 如果为0x01,表示已启用加密。

三、事件处理流程

3.1. 事件触发

  • 当蓝牙链路管理器检测到与远程设备的连接建立时,触发HCI_Connection_Complete事件。
  • 该事件包含连接句柄、远程设备地址等关键信息。

3.2. 事件接收与解析

  • 主机通过HCI接口接收事件。
  • 解析事件包,提取事件码、连接句柄、远程设备地址、连接类型、加密状态等参数。
  • 根据Status参数判断连接是否成功。

3.3. 状态更新与反馈

  • 成功连接
    • 更新内部连接状态表,记录连接信息。
    • 向应用程序层反馈连接建立结果。
  • 连接失败
    • 记录错误信息,包括错误码和远程设备地址。
    • 根据错误码采取相应的错误处理策略,如重试连接、提示用户或更新设备状态。
    • 向应用程序层反馈连接失败结果。

3.4. 后续操作与管理

  • 根据连接类型和加密状态配置数据传输参数。
  • 初始化数据传输通道,确保数据能够顺利传输。
  • 对连接进行持续的管理和监控,处理连接中断、重连请求等异常情况。
  • 如需断开连接,发送HCI_Disconnect命令。

3.5. 示例代码

以下是一个简化的C语言代码示例,用于模拟HCI_Connection_Complete事件的处理流程。请注意,这只是一个示例,实际蓝牙设备上的实现会复杂得多,并且需要依赖于特定的蓝牙协议栈和硬件接口。

#include <stdint.h>
#include <stdbool.h>
#include <string.h>
 
// 假设这些结构体和枚举在蓝牙协议栈的头文件中定义
typedef struct {
    uint8_t Status;
    uint16_t Connection_Handle;
    uint8_t BD_ADDR[6];
    uint8_t Link_Type;
    bool Encryption_Enabled;
} HCI_Connection_Complete_Event;
 
// 假设的连接状态表
typedef struct {
    uint16_t Connection_Handle;
    uint8_t BD_ADDR[6];
    uint8_t Link_Type;
    bool Encryption_Enabled;
    bool IsConnected;
} ConnectionState;
 
#define MAX_CONNECTIONS 10
ConnectionState connectionStates[MAX_CONNECTIONS] = {0};
 
// 模拟事件接收函数
void receiveHCIConnectionCompleteEvent(HCI_Connection_Complete_Event* event) {
    // 在这里,我们假设事件已经通过HCI接口接收并填充到event结构体中
    // 这里只是简单地打印出事件信息
    printf("Received HCI_Connection_Complete Event:\n");
    printf("Status: 0x%02X\n", event->Status);
    printf("Connection Handle: 0x%04X\n", event->Connection_Handle);
    printf("BD_ADDR: ");
    for (int i = 0; i < 6; i++) {
        printf("%02X ", event->BD_ADDR[i]);
    }
    printf("\nLink Type: 0x%02X\n", event->Link_Type);
    printf("Encryption Enabled: %s\n", event->Encryption_Enabled ? "Yes" : "No");
 
    // 调用处理函数
    processHCIConnectionCompleteEvent(event);
}
 
// 处理HCI_Connection_Complete事件的函数
void processHCIConnectionCompleteEvent(HCI_Connection_Complete_Event* event) {
    if (event->Status == 0x00) {
        // 连接成功
        updateConnectionState(event);
        notifyApplicationLayer(true, event->Connection_Handle, event->BD_ADDR);
    } else {
        // 连接失败
        logError(event->Status, event->BD_ADDR);
        notifyApplicationLayer(false, 0, NULL);
    }
}
 
// 更新连接状态表的函数
void updateConnectionState(HCI_Connection_Complete_Event* event) {
    for (int i = 0; i < MAX_CONNECTIONS; i++) {
        if (!connectionStates[i].IsConnected) {
            connectionStates[i].Connection_Handle = event->Connection_Handle;
            memcpy(connectionStates[i].BD_ADDR, event->BD_ADDR, 6);
            connectionStates[i].Link_Type = event->Link_Type;
            connectionStates[i].Encryption_Enabled = event->Encryption_Enabled;
            connectionStates[i].IsConnected = true;
            break;
        }
    }
}
 
// 记录错误信息的函数
void logError(uint8_t status, uint8_t* bdAddr) {
    // 在这里,我们可以将错误信息记录到日志文件中
    // 这里只是简单地打印出错误信息
    printf("Connection failed with Status: 0x%02X\n", status);
    printf("BD_ADDR: ");
    for (int i = 0; i < 6; i++) {
        printf("%02X ", bdAddr[i]);
    }
    printf("\n");
}
 
// 通知应用程序层的函数
void notifyApplicationLayer(bool isConnected, uint16_t connectionHandle, uint8_t* bdAddr) {
    // 在这里,我们可以通过回调函数或其他机制通知应用程序层
    // 这里只是简单地打印出通知信息
    if (isConnected) {
        printf("Notifying application layer: Connection established with Handle: 0x%04X, BD_ADDR: ", connectionHandle);
    } else {
        printf("Notifying application layer: Connection failed\n");
        return;
    }
    for (int i = 0; i < 6; i++) {
        printf("%02X ", bdAddr[i]);
    }
    printf("\n");
}
 
int main() {
    // 假设我们收到了一个HCI_Connection_Complete事件
    HCI_Connection_Complete_Event event;
    event.Status = 0x00; // 连接成功
    event.Connection_Handle = 0x0001;
    event.BD_ADDR[0] = 0xAA; event.BD_ADDR[1] = 0xBB; event.BD_ADDR[2] = 0xCC;
    event.BD_ADDR[3] = 0xDD; event.BD_ADDR[4] = 0xEE; event.BD_ADDR[5] = 0xFF;
    event.Link_Type = 0x01; // 假设的Link Type值
    event.Encryption_Enabled = true;
 
    // 接收并处理事件
    receiveHCIConnectionCompleteEvent(&event);
 
    return 0;
}

四、使用场景

  • 设备连接管理:在蓝牙设备的管理中,通过监听HCI_Connection_Complete事件,可以实时了解设备的连接状态,从而进行相应的连接管理操作。
  • 数据传输准备:在连接建立后,可以使用Connection_Handle来建立L2CAP信道或其他类型的信道,以便进行数据传输。
  • 连接状态监控:在开发蓝牙应用时,可以通过监控该事件来实时获取设备的连接状态,从而为用户提供相应的连接状态提示或进行其他逻辑处理。

五、注意事项

5.1. 事件接收与解析

  • 数据完整性检查
    • 验证数据包是否完整接收,可通过校验和、序列号等机制实现。
    • 数据不完整时,请求重新发送或采取错误处理措施。
  • 协议版本兼容性
    • 根据蓝牙协议版本适配事件格式和参数定义。
    • 特别注意参数含义或取值范围的变化。

5.2. 参数处理

  • 错误码处理
    • 准确处理Status参数中的错误码。
    • 结合设备实际情况分析错误码,合理设置重试次数和间隔时间。
  • 连接句柄范围检查
    • 确保Connection_Handle在有效范围内。
    • 超出范围时,进行错误处理,如断开连接、重新初始化连接管理模块。
  • 设备地址验证
    • 验证BD_ADDR的合法性和唯一性。
    • 避免地址冲突或非法地址导致的连接混乱。
  • 连接类型策略适配
    • 根据Link_Type确定连接类型,适配相应的通信策略。
    • 避免策略适配不当导致的性能问题。
  • 加密安全性考虑
    • 评估Encryption_Enabled参数表示的连接安全性。
    • 在必要时,应用层添加额外加密措施或提示用户连接安全性。

5.3. 连接状态管理与资源分配

  • 连接状态更新
    • 及时更新设备内部的连接状态记录。
    • 通知其他相关模块连接状态的变化。
  • 资源分配与回收
    • 合理分配资源以满足数据传输和连接管理需求。
    • 连接失败时,及时回收已分配的资源,避免资源泄漏。
    • 考虑资源共享和竞争问题,避免系统性能下降。

5.4. 并发与异步操作处理

  • 并发连接处理
    • 采用并发控制机制(如互斥锁、信号量)确保对共享资源的安全访问。
    • 避免数据不一致或连接混乱。
  • 异步操作回调与通知
    • 确保事件处理函数不影响其他操作的正常进行。
    • 通过回调或通知机制将事件处理结果传递给其他相关模块。
    • 避免阻塞其他正在进行的蓝牙操作。

综上所述,HCI_Connection_Complete事件是蓝牙通信中一个重要的事件,用于通知主机一个新的连接已经建立,并提供了连接的相关信息。在蓝牙设备的管理和开发中,应充分利用该事件来实现设备的连接管理、数据传输准备以及连接状态监控等功能。


http://www.kler.cn/a/518560.html

相关文章:

  • 【人工智能】大模型大算法迭代优化过程
  • 用css实现一个类似于elementUI中Loading组件有缺口的加载圆环
  • list对象获取最大的日期
  • 【AI日记】25.01.24
  • C++ —— 智能指针 unique_ptr (上)
  • SQL-leetcode—1164. 指定日期的产品价格
  • 【GoLang】利用validator包实现服务端参数校验时自定义错误信息
  • 星动纪元ERA-42:端到端原生机器人大模型的革命性突破
  • Excel打印技巧
  • 【2024年华为OD机试】 (E卷,200分) - 寻找符合要求的最长子串(JavaScriptJava PythonC/C++)
  • HTML入门知识
  • java+vue项目部署记录
  • css命名规范——BEM
  • Java 中的设计模式:经典与现代实践
  • 【RK3588嵌入式图形编程】-SDL2-检测和管理错误
  • web速览
  • 【MARK】Cline配合FreeAPI,再薅亿点点token
  • [央企大赛 2025] pwn
  • http的请求体各项解析
  • 【Qt 常用控件】显示类控件1(QLabel)