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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/959313.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PCI 总线学习笔记(三)

PCI 总线学习系列&#xff0c;参考自 技术大牛博客&#xff1a; PCIe 扫盲系列博文连载目录篇 书籍&#xff1a;王齐老师的《PCI Express 体系结构导读》 下面的文章中加入了自己的一些理解和实际使用中遇到的一些场景&#xff0c;供日后查询和回忆使用 阅读本篇文章前&#x…

麒麟操作系统基础知识保姆级教程(二十一)进入单用户模式

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 在咱们运维工作中&#xff0c;服务器的密码长度&#xff0c;密码复杂度&#xff0c;修改时间&#xff0c;超时时间&#xff0c;用户权限管理&#xff0c;root直接远程连接&#xff0c;普通用户su到r…

ARM64平台Flutter环境搭建

ARM64平台Flutter环境搭建 Flutter简介问题背景搭建步骤1. 安装ARM64 Android Studio2. 安装Oracle的JDK3. 安装 Dart和 Flutter 开发插件4. 安装 Android SDK5. 安装 Flutter SDK6. 同意 Android 条款7. 运行 Flutter 示例项目8. 修正 aapt2 报错9. 修正 CMake 报错10. 修正 N…

OpenCV:高通滤波之索贝尔、沙尔和拉普拉斯

目录 简述 什么是高通滤波&#xff1f; 高通滤波的概念 应用场景 索贝尔算子 算子公式 实现代码 特点 沙尔算子 算子公式 实现代码 特点 拉普拉斯算子 算子公式 实现代码 特点 高通滤波器的对比与应用场景 相关阅读 OpenCV&#xff1a;图像滤波、卷积与卷积核…

VS企业版和专业版的区别

网上查询vs分析dump文件&#xff0c;查找托管内存泄露&#xff0c;需要使用“调试托管内存”功能&#xff0c;当前安装的vs2022 专用版找不到这个选项&#xff0c;vs2015是ok的&#xff0c;比较版本发现2022是专业版&#xff0c;2015是企业版。网上搜索专业版和企业版差异如下&…

ESP8266 NodeMCU与WS2812灯带:实现多种花样变换

在现代电子创意项目中&#xff0c;LED灯带的应用已经变得极为广泛。通过结合ESP8266 NodeMCU的强大处理能力和FastLED库的高效功能&#xff0c;我们可以轻松实现多达100种灯带变换效果。本文将详细介绍如何使用Arduino IDE编程&#xff0c;实现从基础到高级的灯光效果&#xff…

技术 · 创作 · 生活 | 我的 2024 全面复盘

目录 &#x1f31f;2024年度总结&#xff1a;回顾、成长与突破&#x1f31f;&#x1f680; 一、技术成长与突破 &#x1f680;&#x1f517; 1. 深入区块链与智能合约&#x1f50d; 2. 探索新兴技术 ✍️ 二、创作与博客历程 ✍️&#x1f4d6; 1. 内容创作的演变&#x1f3c6;…

嵌入式MCU面试笔记2

目录 串口通信 概论 原理 配置 HAL库代码 1. 初始化函数 2. 数据发送和接收函数 3. 中断和DMA函数 4. 中断服务函数 串口通信 概论 我们知道&#xff0c;通信桥接了两个设备之间的交流。一个经典的例子就是使用串口通信交换上位机和单片机之间的数据。 比较常见的串…

LeetCode --- 433周赛

题目列表 3427. 变长子数组求和 3428. 最多 K 个元素的子序列的最值之和 3429. 粉刷房子 IV 3430. 最多 K 个元素的子数组的最值之和 一、变长子数组求和 题意要求我们能快速算出 n u m s [ s t a r t . . . i ] nums[start...i] nums[start...i] 这段区间和&#xff0c;其中…

EasyNVR免费版已发布!EasyNVR接入海康NVR大华NVR宇视NVR天地伟业NVR接入各种IPC摄像机工业监控家庭监控

EasyNVR不用多说了&#xff0c;驰名已久&#xff01;之前一直是收费的&#xff0c;不管多少个摄像机接入都是收费的&#xff0c;这就导致&#xff0c;很多个人用户&#xff0c;或者说是家庭用户&#xff0c;家里就那么两三个摄像机&#xff0c;想通过EasyNVR接入NAS系统&#x…

任务一:Android逆向

首先我使用了一个叫objection的东西。 列出了他所有的活动界面,列出来之后在慢慢筛选。 然后用了一个命令,就是可以跳到这个活动界面的命令。 我就确定了这个活动界面的位置,然后我就采取了objection的另一种栈追踪。 追踪到了这个地方。 先打印出具有特征参数的值,在…

黑龙江锅包肉:酸甜香酥的东北经典

黑龙江锅包肉:酸甜香酥的东北经典 黑龙江锅包肉,作为东北菜的代表之一,尤其在黑龙江省哈尔滨市享有极高的声誉。这道美食不仅承载着丰富的历史文化内涵,更以其鲜明的地域特色,成为了黑龙江省乃至整个东北地区的标志性菜肴。 历史渊源 锅包肉的历史可以追溯到清朝光绪年间,其…

[JavaScript] ES6及以后版本的新特性

文章目录 箭头函数&#xff08;Arrow Functions&#xff09;为什么需要箭头函数&#xff1f;箭头函数的完整语法箭头函数中的 this实用场景 解构赋值&#xff08;Destructuring Assignment&#xff09;为什么需要解构赋值&#xff1f;数组解构赋值的完整用法对象解构赋值的完整…

ipad和macbook同步zotero文献附件失败的解决办法

背景&#xff1a;我所有的文献及其附件pdf都是在台式机&#xff08;windows系统&#xff09;&#xff0c;想要把这些文献同步到云上&#xff0c;然后再从云上同步到平板和其他笔记本电脑比如macbook。文献同步虽已成功&#xff0c;但文献附件都无法打开。 平板报错如下&#xf…

element tbas增加下拉框

使用Tabs 标签页的label插槽&#xff0c;嵌入Dropdown 下拉菜单&#xff0c;实现Tabs 标签页增加下拉切换功能 Tabs 标签页 tab-click"事件"&#xff08;这个事件当中到拥有下拉框的tab里时&#xff0c;可以存一下Dropdown 第一个菜单的id&#xff0c;实现点击到拥有…

环境变量配置与问题解决

目录 方法 配置了还是运行不了想要的东西 解决方案 为什么 解决方案 方法 方法一&#xff1a;此电脑右击-属性-相关链接-高级系统设置-环境变量&#xff08;N&#xff09;-系统变量里面找到Path-三个确定】 方法二&#xff1a;winr cmd 黑框输入sysdm.cpl&#xff0c;后面…

【C++】详细讲解继承(下)

本篇来继续说说继承。上篇可移步至【C】详细讲解继承&#xff08;上&#xff09; 1.继承与友元 友元关系不能继承 &#xff0c;也就是说基类友元不能访问派⽣类私有和保护成员。 class Student;//前置声明class Same //基类 { public:friend void Fun(const Same& p, con…

联想电脑怎么设置u盘启动_联想电脑设置u盘启动方法(支持新旧机型)

有很多网友问联想电脑怎么设置u盘启动&#xff0c;联想电脑设置u盘启动的方法有两种&#xff0c;一是通过bios进行设置。二是通过快捷方式启动进入u盘启动。但需要注意有两种引导模式是&#xff0c;一种是uefi引导&#xff0c;一种是传统的leacy引导&#xff0c;所以需要注意制…

算法|牛客网华为机试53-62C++

牛客网华为机试 上篇&#xff1a;算法|牛客网华为机试41-52C 文章目录 HJ53 杨辉三角的变形HJ54 表达式求值HJ55 挑7HJ56 完全数计算HJ57 高精度整数加法HJ58 输入n个整数&#xff0c;输出其中最小的k个HJ59 找出字符串中第一个只出现一次的字符HJ60 查找组成一个偶数最接近的两…

消息队列篇--通信协议篇--TCP和UDP(3次握手和4次挥手,与Socket和webSocket的概念区别等)

1、TCP和UDP概述 TCP&#xff08;传输控制协议&#xff0c;Transmission Control Protocol&#xff09;和UDP&#xff08;用户数据报协议&#xff0c;User Datagram Protocol&#xff09;都算是最底层的通信协议&#xff0c;它们位于OSI模型的传输层。*传输层的主要职责是确保…