1、Legacy Advertising 最核心的 4 个 HCI Command

Legacy BLE 广播配置主要就是这 4 个命令:

HCI Command Opcode 作用
LE Set Advertising Parameters 0x2006 设置广播参数
LE Set Advertising Data 0x2008 设置 Advertising Data
LE Set Scan Response Data 0x2009 设置 Scan Response Data
LE Set Advertising Enable 0x200A 开启 / 关闭广播

可以先把它理解成:

LE Set Advertising Parameters
  决定怎么广播

LE Set Advertising Data
  决定广播包里面放什么内容

LE Set Scan Response Data
  决定收到 Scan Request 后回复什么内容

LE Set Advertising Enable
  决定是否开始广播

在我上一篇博客《BLE 广播 rawBytes 解析说明》提到的rawBytes其实就是Advertising Data和Scan Response Data,为了连贯性所以本篇博客先把LE Set Advertising Data和LE Set Scan Response Data理解清楚。

2、LE Set Advertising Data
Part E Host Controller Interface Functional SpecificationThis Part describes the functional specification for the Host Controller interface (HCI). The HCI provides a uniform command interface to a Controller.https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-61/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-7b83376f-e321-e7ce-3bf1-2af187798be4

这张图就是 Legacy Advertising 的 HCI 命令:HCI_LE_Set_Advertising_Data。它对应前面说的“把 rawBytes 配置进广播包”。

核心可以这样理解:

HCI_LE_Set_Advertising_Data
作用:设置 Legacy 广播包里的 Advertising Data
最大长度:31 字节
数据格式:Vol 3, Part C, Section 11 定义的 AD Structure

2.1 这个命令设置的就是 Advertising Data

截图里这句话很关键:

This command is used to set the data used in advertising packets that have a data field.

意思是:

这个命令用于设置广播包中的 data field,也就是 Legacy 广播里的 Advertising Data

对于 App 开发来说,可以把它理解成:

这个命令设置的内容 ≈ 扫描端看到的 rawBytes 里面的 Advertising Data 部分

也就是这种结构:

Length | AD Type | AD Data
Length | AD Type | AD Data
Length | AD Type | AD Data
...

2.2 Advertising_Data_Length 是有效数据长度

截图里:

Advertising_Data_Length
Size: 1 octet
Value: 0x00 to 0x1F
The number of significant octets in the Advertising_Data.

重点是:

0x1F = 31

所以:

Advertising_Data_Length 最大就是 31 字节

它表示 Advertising_Data 里面有多少个有效字节。

比如你要设置:

02 01 06
03 03 0F 18
08 09 44 65 76 69 63 65 31

总长度是:

3 + 4 + 9 = 16 字节

那么:

Advertising_Data_Length = 0x10

因为:

0x10 = 16

2.3 Advertising_Data 固定是 31 octets

截图里:

Advertising_Data
Size: 31 octets
31 octets of advertising data formatted as defined in Vol 3 Part C, Section 11.

意思是:

这个 HCI 命令里的 Advertising_Data 参数固定给了 31 字节空间。

但是并不是说这 31 字节都一定有效。真正有效多少,看前面的:

Advertising_Data_Length

例如有效数据只有 16 字节,那么命令里面还是会带一个 31 字节数组:

Advertising_Data_Length = 0x10

Advertising_Data[31] =
02 01 06
03 03 0F 18
08 09 44 65 76 69 63 65 31
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

前 16 字节是有效数据,后面的 00 是补齐。

所以如果看到 rawBytes 后面有很多 00,就可以和这里对应上:

HCI 命令字段固定有 31 字节空间
但有效广播数据长度由 Advertising_Data_Length 决定

2.4 significant part 是什么意思?

截图里还有一句:

Only the significant part of the Advertising_Data should be transmitted in the advertising packets.

这里的 significant part 就是有效部分。

也就是说:

只有 Advertising_Data_Length 指定的那部分数据,才应该真正放进广播包发送出去。

例如:

Advertising_Data_Length = 0x07
Advertising_Data[31] =
02 01 06 03 03 0F 18 00 00 00 ...

那么真正广播出去的 Advertising Data 应该只有:

02 01 06 03 03 0F 18

后面的 00 00 00... 不属于有效广播内容。

2.5 如果广播已经开启,再设置 Advertising Data 会怎样?

截图里这段也很重要:

If advertising is currently enabled, the Controller shall use the new data in subsequent advertising events.
If an advertising event is in progress when this command is issued, the Controller may use the old or new data for that event.

意思是:

如果广播已经开启,此时再发 HCI_LE_Set_Advertising_Data,Controller 后续的广播事件会使用新的广播数据。

但是如果刚好有一个广播事件正在进行中,那么那个事件可能使用旧数据,也可能使用新数据。

所以实际工程里更稳妥的做法通常是:

1. 关闭广播
2. 设置 Advertising Data
3. 再开启广播

也就是:

LE Set Advertising Enable = 0x00
LE Set Advertising Data
LE Set Advertising Enable = 0x01

不过规范也允许在广播开启时更新数据,只是当前那个正在进行的 advertising event 不保证一定立即使用新数据。

这点和多 Beacon 轮播有关。

如果模块内部做多 Beacon 轮播,它可能就是周期性更新 Advertising Data。某个广播事件用旧数据还是新数据,底层有一定时序差异。

2.6 默认值是什么意思?

截图里:

The default Advertising_Data_Length shall be zero
and the default Advertising_Data shall be 31 all-zero octets.

意思是默认情况下:

Advertising_Data_Length = 0
Advertising_Data = 31 个 0

也就是:

默认没有有效 Advertising Data

不是说默认广播 31 个 00,而是有效长度为 0。

2.7 Return Parameters 只有 Status

这个命令返回参数只有:

Status

如果:

Status = 0x00

表示:

HCI_LE_Set_Advertising_Data command succeeded

如果:

Status = 0x01 ~ 0xFF

表示命令失败,具体错误码要查 Controller Error Codes。

所以这个命令只是告诉你:

广播数据是否设置成功

它不会返回当前广播数据,也不会帮你解析 AD Structure。

2.8 Event generated:Command Complete

截图最后说:

When the HCI_LE_Set_Advertising_Data command has completed,
an HCI_Command_Complete event shall be generated.

意思是:

Host 发出这个 HCI Command 后,Controller 执行完成,会返回一个:

HCI_Command_Complete Event

里面带上 Status。

所以 HCI 层交互大概是:

Host -> Controller:
  HCI_LE_Set_Advertising_Data

Controller -> Host:
  HCI_Command_Complete Event
    Status = 0x00 / error code

以上内容总结如下:

LE Set Advertising Data 命令用于设置 Legacy 广播包中的 Advertising Data。
Advertising_Data_Length 表示有效数据长度,最大 0x1F,也就是 31 字节。
Advertising_Data 是固定 31 字节数组,里面的数据必须按 AD Structure 格式组织:
Length | AD Type | AD Data。
只有 Advertising_Data_Length 指定的有效部分会被放进广播包发送。

3、LE Set Scan Response Datahttps://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-61/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-7f9e3a5b-fa09-5292-b64e-1a5304b6a255https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-61/out/en/host-controller-interface/host-controller-interface-functional-specification.html#UUID-7f9e3a5b-fa09-5292-b64e-1a5304b6a255

这个命令和上一条 LE Set Advertising Data 是一对的。区别是:

LE Set Advertising Data
设置主动广播包里的 Advertising Data

LE Set Scan Response Data
设置收到 SCAN_REQ 后回复的 Scan Response Data

也就是说,这张图讲的是 Legacy BLE 扫描响应数据的配置命令

3.1 这个命令设置的是什么?

命令名:

HCI_LE_Set_Scan_Response_Data

OCF:

0x0009

完整理解:

Host 通过这个 HCI Command,把 Scan Response Data 配置到 Controller 里。
当 Controller 后续收到 Scanner 发来的 SCAN_REQ 时,就可以回复 SCAN_RSP。
SCAN_RSP 里面携带的就是这里配置的 Scan_Response_Data。

也就是说:

LE Set Scan Response Data
    ↓
配置 Scan_Response_Data
    ↓
外设收到 SCAN_REQ
    ↓
回复 SCAN_RSP
    ↓
手机扫描端可能拿到这部分数据

3.2 Scan_Response_Data_Length

截图里这个字段:

Scan_Response_Data_Length
Size: 1 octet
Value: 0x00 to 0x1F

意思是:

Scan Response Data 的有效数据长度,范围 0 到 31 字节。

因为:

0x1F = 31

所以 Legacy BLE 下:

Scan Response Data 最大也是 31 字节

和 Advertising Data 一样。

例如你配置扫描响应数据:

08 09 44 65 76 69 63 65 31

这表示:

08 = Length
09 = AD Type,Complete Local Name
44 65 76 69 63 65 31 = Device1

总长度是 9 字节,所以:

Scan_Response_Data_Length = 0x09

3.3 Scan_Response_Data 固定 31 字节

截图里写:

Scan_Response_Data
Size: 31 octets

意思是 HCI 命令参数里固定提供一个 31 字节数组。

但真正有效的字节数由:

Scan_Response_Data_Length

决定。

例如:

Scan_Response_Data_Length = 0x09

Scan_Response_Data[31] =
08 09 44 65 76 69 63 65 31
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

前面 9 字节有效,后面的 00 是补齐,不是有效扫描响应内容。

3.4 Scan Response Data 里面仍然是 AD Structure

截图里提到:

formatted as defined in Vol 3 Part C, Section 11

意思是它的格式和 Advertising Data 一样,仍然是:

Length | AD Type | AD Data

所以 Scan Response Data 不是另一套格式。

例如:

08 09 44 65 76 69 63 65 31

解析为:

08 = Length,后面有 8 字节
09 = AD Type,Complete Local Name
44 65 76 69 63 65 31 = AD Data,字符串 Device1

再比如:

05 FF 34 12 01 02

解析为:

05 = Length
FF = Manufacturer Specific Data
34 12 = Company ID,小端序,0x1234
01 02 = 厂商自定义数据

所以不管是 Advertising Data 还是 Scan Response Data,本质都使用同一套 AD Structure。

3.5 和 LE Set Advertising Data 的区别

这两个命令非常像:

命令 设置的数据 最大长度 什么时候发送
LE Set Advertising Data Advertising Data 31 字节 外设主动广播时发送
LE Set Scan Response Data Scan Response Data 31 字节 外设收到 SCAN_REQ 后回复

也就是说:

Advertising Data 是外设主动发的。
Scan Response Data 是别人问了之后才回复的。

Legacy BLE 里常见的配置方式是:

Advertising Data:
  Flags
  Service UUID
  Manufacturer Data

Scan Response Data:
  Complete Local Name

因为设备名称比较占空间,放到广播包里可能不够,所以很多设备会把完整名称放到扫描响应包里。

3.6 不是所有广播都会用到 Scan Response Data

这个很关键。

你配置了 Scan_Response_Data,并不代表它一定会被发出去。

它需要几个条件:

1. 广播类型必须是 scannable
2. 扫描设备必须处于 Active Scanning
3. 扫描设备实际发送了 SCAN_REQ
4. 外设 Controller 收到 SCAN_REQ
5. 外设回复 SCAN_RSP

例如:

Advertising Type Link Layer PDU 是否可扫描 是否会用到 Scan Response Data
0x00 ADV_IND 可能
0x02 ADV_SCAN_IND 可能
0x03 ADV_NONCONN_IND 不会

所以如果你把广播类型设置成:

ADV_NONCONN_IND

即使你配置了 Scan Response Data,正常情况下手机也不会发 SCAN_REQ,模块也不会回复 SCAN_RSP

3.7 如果广播已经开启,再修改 Scan Response Data 会怎样?

截图里这段和上一条命令一样:

If advertising is currently enabled, the Controller shall use the new data in subsequent advertising events.
If an advertising event is in progress when this command is issued, the Controller may use the old or new data for that event.

意思是:

如果广播已经开启,再设置新的 Scan Response Data,那么 Controller 后续的 advertising events 会使用新数据。

但是如果刚好某个 advertising event 正在进行中,这个事件可能使用旧数据,也可能使用新数据。

所以工程上更稳妥的配置流程仍然是:

1. 关闭广播
2. 设置 Advertising Parameters
3. 设置 Advertising Data
4. 设置 Scan Response Data
5. 开启广播

也就是:

LE Set Advertising Enable = 0x00
LE Set Advertising Parameters
LE Set Advertising Data
LE Set Scan Response Data
LE Set Advertising Enable = 0x01

3.8 默认值

截图里写:

The default Scan_Response_Data_Length shall be zero
and the default Scan_Response_Data shall be 31 all-zero octets.

意思是默认情况下:

Scan_Response_Data_Length = 0
Scan_Response_Data = 31 个 0

也就是:

默认没有有效的 Scan Response Data

不是说默认会扫描响应 31 个 00

有效长度为 0,就表示没有有效扫描响应数据。

3.9 App 层看到它时是什么样?

这个命令配置的是底层 SCAN_RSP 里的数据。

但是到了 iOS / Android App 层,一般不会明确告诉你:

这个字段来自 Advertising Data
这个字段来自 Scan Response Data

系统可能会把两部分整理到扫描结果里。

例如底层配置:

Advertising Data:
02 01 06
03 03 0F 18

Scan Response Data:
08 09 44 65 76 69 63 65 31

App 层可能看到:

Flags: 0x06
Service UUID: 0x180F
Local Name: Device1

但是 App 通常不能可靠判断:

Device1 是从 Advertising Data 来的,还是从 Scan Response Data 来的。

3.10 总结

这张图说明的是:

LE Set Scan Response Data 命令用于设置 Legacy BLE 的 Scan Response Data。
Scan_Response_Data_Length 表示有效数据长度,最大 31 字节。
Scan_Response_Data 是固定 31 字节数组,内容格式仍然是 AD Structure:
Length | AD Type | AD Data。
这部分数据只有在广播类型可扫描,并且扫描设备发送 SCAN_REQ 后,才会通过 SCAN_RSP 发出去。

可以把它和上一条命令放在一起记:

LE Set Advertising Data:
设置主动广播出去的 31 字节 Advertising Data。

LE Set Scan Response Data:
设置被主动扫描时回复的 31 字节 Scan Response Data。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐