
HCI_Inquiry_Result事件是蓝牙通信中的一个重要事件,它发生在蓝牙设备执行查询(Inquiry)操作时,当主机控制器(Host Controller)发现周围的蓝牙设备并成功接收到其响应时,就会触发该事件。
HCI_Inquiry_Result 事件主要用于在当前的蓝牙设备查询(Inquiry)过程中,向主机反馈已经接收到的来自蓝牙基本速率 / 增强数据速率(BR/EDR)控制器或者多个此类控制器的响应情况。简单来说,就是把查询过程中发现的蓝牙设备相关信息传递给主机,为主机后续决定与哪些设备进一步交互、连接等操作提供依据。

在整个蓝牙设备查询流程中,主机发送 HCI_Inquiry 命令来启动查询操作。在查询过程中,当主机控制器发现一个或多个蓝牙设备并获取其相关信息后,就会产生 HCI_Inquiry_Result 事件,将这些设备信息逐个或批量地发送给主机。
HCI_Inquiry_Result 事件主要由事件头、事件参数两大部分构成,整体上用于向主机传递在蓝牙设备查询(Inquiry)过程中所获取到的相关设备信息,协助主机完成诸如设备发现、连接及后续管理等操作。

- Class_Of_Device: XX:XX:XX
- Clock_Offset: XX:XX
Device 2:
- BD_ADDR: YY:YY:YY:YY:YY:YY
- Page_Scan_Repetition_Mode: 0x00
- Reserved: 0x00
- Class_Of_Device: YY:YY:YY
- Clock_Offset: YY:YY解析HCI_Inquiry_Result事件的内容,主机可以获取到查询到的蓝牙设备的详细信息,并根据这些信息执行后续操作,如发起连接请求、获取设备名称等。
Num_Responses 用于表示此次事件中包含的响应数量,也就是一共携带了多少个蓝牙设备的相关信息。通过这个参数,主机可以提前知晓后续要解析的设备信息组数,方便对整个事件数据进行合理的处理和拆分。

示例应用场景:比如在一个蓝牙设备发现应用中,主机接收到的 HCI_Inquiry_Result 事件里 Num_Responses 的值为 5,那就意味着后面跟着的是 5 组不同蓝牙设备的详细信息,主机就可以按照这个数量依次去解析和处理每组设备信息,为后续展示设备列表、进行设备连接等操作做准备。
BD_ADDR [i] 是一个数组形式的参数,其中每个元素代表一个被查询到的蓝牙设备的地址(蓝牙设备地址,Bluetooth Device Address)。它是一个在全球范围内唯一标识蓝牙设备的标识符,其长度通常是固定的(比如 48 位,以十六进制表示形式较为常见),作用类似于设备的 “身份证号码”,主机通过这个地址能精准区分不同的蓝牙设备。蓝牙MAC地址-CSDN博客

Page_Scan_Repetition_Mode [i] 同样是一个数组形式的参数,每个元素对应一个被查询到的蓝牙设备,用于表示该设备的寻呼扫描重复模式。不同的模式决定了设备在被寻呼(例如,后续主机尝试与该设备建立连接等操作时)时的扫描频率、响应方式等行为特点,是了解设备寻呼相关特性的重要参数。

主机在接收到 HCI_Inquiry_Result 事件后,会解析 Page_Scan_Repetition_Mode 数组,并根据这些信息执行后续操作,如优化连接请求的时序、处理不同设备的响应等。
R0(0x00):表示设备不进行额外的页面扫描重复,即只响应一次查询。R1(0x01):表示设备在响应查询之前会重复page扫描一次。R2(0x02):表示设备在响应查询之前会重复page扫描两次。Reserved [i] 是预留参数,在当前的蓝牙协议规范下,它暂时可能没有实际的使用用途。

Reserved [i] 参数的大小为 Num_Responses × 2 个八位字节(octets)。意味着它的总字节长度取决于此次 HCI_Inquiry_Result 事件中所包含的设备响应数量(由 Num_Responses 确定),每个响应设备都对应着 2 个字节的预留空间。
对于主机来说,在接收到 HCI_Inquiry_Result 事件时,可以忽略 Reserved[i] 参数的值,因为它当前没有定义具体的功能。
Class_Of_Device [i] 是一个数组形式的参数,用于标识每个被查询到的蓝牙设备的设备类别。它按照蓝牙协议规定的编码格式,通过不同的位组合来表示设备属于何种类型,比如是音频播放设备、输入设备(像键盘、鼠标等)、打印设备还是其他类型,有助于主机快速对设备进行分类筛选。

Clock_Offset [i] 是一个数组形式的参数,用于表示每个被查询到的蓝牙设备的时钟偏移量。蓝牙设备之间在通信时需要进行时钟同步,这个参数所体现的时钟偏移量就是衡量设备内部时钟与主机时钟差异的关键指标,对于后续准确、高效地进行数据传输以及设备间的同步协作有着重要意义。

在蓝牙通信中,为了发现和连接其他蓝牙设备,主机(Host)会向控制器(Controller)发送HCI_Inquiry命令,启动设备查询流程。控制器接收到命令后,会发送ID包以寻找周围的蓝牙设备。这些设备接收到ID包后,会响应并发送包含自身信息的FHS包。控制器解析这些包,并将找到的设备信息通过HCI_Inquiry_Result等事件返回给主机。【0x0001】HCI_Inquiry命令详解-CSDN博客
HCI_Inquiry_Result事件是在蓝牙设备查询过程中,由控制器在接收到其他蓝牙设备响应时触发的事件。该事件包含响应设备的相关信息,并用于报告给主机以便进一步处理。了解这些触发时机有助于更好地理解蓝牙设备查询流程,并在实际应用中进行相应的处理和优化。
HCI_Inquiry_Result事件处理流程是一个复杂的蓝牙设备查询和处理过程,涉及事件触发、生成与上传、以及事件处理等多个阶段。通过该流程,蓝牙设备能够获取周围蓝牙设备的信息,并根据这些信息执行后续操作,如设备连接、信息显示、通知发送、设备筛选和分类等。
以下是一个简化的伪代码或框架,以展示如何处理这类事件。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 假设的蓝牙设备地址类型
typedef struct {
uint8_t address[6];
} BluetoothAddress;
// 假设的查询结果结构体
typedef struct {
BluetoothAddress bd_addr;
uint8_t page_scan_repetition_mode;
uint8_t reserved[2];
uint8_t class_of_device[3];
uint16_t clock_offset;
} InquiryResult;
// 假设的查询数据库
typedef struct {
InquiryResult results[10]; // 假设数据库最多存储10个设备
int count;
} InquiryDatabase;
// 初始化查询数据库
void init_inquiry_database(InquiryDatabase *db) {
memset(db, 0, sizeof(InquiryDatabase));
db->count = 0;
}
// 更新查询数据库(简化版,不考虑数据库已满的情况)
void update_inquiry_database(InquiryDatabase *db, InquiryResult *result) {
// 在这里,我们简单地添加新结果到数据库末尾
// 在实际应用中,可能需要检查重复项、排序或执行其他操作
memcpy(&db->results[db->count], result, sizeof(InquiryResult));
db->count++;
}
// 处理HCI_Inquiry_Result事件的函数(简化版)
void handle_hci_inquiry_result(uint8_t *event_data, int event_length) {
// 假设event_data已经包含了HCI_Inquiry_Result事件的所有数据
// 并且event_length是数据的总长度(以字节为单位)
// 解析Num_Responses
int num_responses = event_data[0];
// 初始化查询结果结构体数组
InquiryResult results[num_responses];
// 解析每个设备的响应信息
for (int i = 0; i < num_responses; i++) {
// 提取BD_ADDR
memcpy(results[i].bd_addr.address, &event_data[1 + i * 11], 6);
// 提取Page_Scan_Repetition_Mode
results[i].page_scan_repetition_mode = event_data[7 + i * 11];
// 提取Reserved(虽然这里不使用,但仍然需要读取以保持同步)
memcpy(results[i].reserved, &event_data[8 + i * 11], 2);
// 提取Class_Of_Device
memcpy(results[i].class_of_device, &event_data[10 + i * 11], 3);
// 提取Clock_Offset(注意:这里可能需要考虑字节顺序和转换)
uint16_t clock_offset = (event_data[13 + i * 11] << 8) | event_data[14 + i * 11];
results[i].clock_offset = clock_offset;
}
// 假设我们有一个全局的查询数据库
static InquiryDatabase db;
init_inquiry_database(&db); // 在实际应用中,这应该在程序开始时调用一次,而不是在这里
// 更新数据库
for (int i = 0; i < num_responses; i++) {
update_inquiry_database(&db, &results[i]);
}
// 触发后续操作(例如,显示设备信息、发起连接请求等)
// 这里只是简单地打印设备地址作为示例
for (int i = 0; i < db.count; i++) {
printf("Device found: ");
for (int j = 0; j < 6; j++) {
printf("%02X ", db.results[i].bd_addr.address[j]);
}
printf("\n");
}
}
int main() {
// 假设在某个时刻,我们接收到了HCI_Inquiry_Result事件的数据
// 这里我们使用一个硬编码的数组来模拟接收到的数据
uint8_t mock_event_data[] = {
// Num_Responses, followed by device-specific data (simplified for brevity)
1, // 1 response
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, // BD_ADDR
0x00, // Page_Scan_Repetition_Mode
0x00, 0x00, // Reserved
0x18, 0x01, 0x05, // Class_Of_Device
0x00, 0xAA // Clock_Offset (simplified, should be 16-bit)
};
int mock_event_length = sizeof(mock_event_data);
// 处理HCI_Inquiry_Result事件
handle_hci_inquiry_result(mock_event_data, mock_event_length);
return 0;
}综上所述,HCI_Inquiry_Result事件是蓝牙通信中用于提供查询到的蓝牙设备信息的重要事件。通过解析该事件的内容,主机可以获取到蓝牙设备的详细信息,并据此执行后续操作。