蓝牙协议栈学习笔记

蓝牙协议栈学习笔记

蓝牙简介

蓝牙工作在全球通用的 2.4GHz ISM(即工业、科学、医学)频段,使用 IEEE802.11 协议

蓝牙 4.0 是迄今为止第一个蓝牙综合协议规范,将三种规格集成在一起。其中最重要的变化就是 BLE(Bluetooth Low Energy)低功耗功能,提出了低功耗蓝牙、传统蓝牙和高速蓝牙三种模式:
”高速蓝牙“主攻数据交换与传输;“传统蓝牙”则以信息沟通、设备连接为重点;”低功耗蓝牙“以不需占用太多带宽的设备连接为主,功耗较老版本降低了 90%。

蓝牙 4.0 的芯片模式分为 Single mode 与 Dual mode。
Single mode 只能与蓝牙 4.0 互相传输无法向下与 3.0/2.1/2.0 版本兼容;
Dual mode 可以向下兼容 3.0/2.1/2.0 版本。
前者应用于使用纽扣电池的传感器设备,例如对功耗要求较高的心率检测器和温度计;后者应用于传统蓝牙设备,同时兼顾低功耗的需求。
此外,蓝牙 4.0 还把蓝牙的传输距离提升到 100 米以上(低功耗模式条件下)。拥有更快的响应速度,最短可在 3 毫秒内完成连接设置并开始传输数据。更安全的技术,使用AES-128 CCM 加密算法进行数据包加密和认证。

蓝牙 5.0 在低功耗模式下具备更快更远的传输能力,传输速率是蓝牙 4.2 的两倍(速度上限为 2Mbps),有效传输距离是蓝牙 4.2 的四倍(理论上可达 300 米),数据包容量是蓝牙 4.2 的八倍。
支持室内定位导航功能,结合 WiFi 可以实现精度小于 1 米的室内定位。
针对 IoT 物联网进行底层优化,力求以更低的功耗和更高的性能为智能家居服务。

随着蓝牙 5 技术的出现和蓝牙 mesh 技术的成熟,大大降低了设备之间的长距离、多设备通讯门槛,为未来的 IoT 带来了更大的想象空间。

HCI蓝牙架构

BT Controller:此部分指的是蓝牙芯片,包括 BR/EDR 芯片(蓝牙 2.1 芯片),AMP 芯片(蓝牙 3.0 芯片),LE 芯片(蓝牙 4.0 芯片),后续我们把 4.0 以下统称为传统蓝牙,4.0 以上称为低功耗蓝牙,芯片层面会有 2 种模式,包括
单模蓝牙芯片:单一传统蓝牙芯片,单一低功耗蓝牙芯片
双模蓝牙芯片:同时支持传统蓝牙跟低功耗蓝牙的芯片
BT Host:蓝牙协议栈

简单架构图
展开的架构图
HW 层:这里就是蓝牙芯片层,包含以下几个部分

  1. RF(RADIO):射频层,本地蓝牙数据通过射频发送给远端设备,并且通过射频接收来自远端蓝牙设备的数据
  2. BB(BASEBAND):基带层,进行射频信号与数字或语音信号的相互转化,实现基带协议和其它的底层连接规程。
  3. LMP(LINK MANAGER PROTOCOL):链路管理层,负责管理蓝牙设备之间的通信,实现链路的建立、验证、链路配置等操作
  4. HCI(HOST CONTROLLER INTERFACE):主机控制器接口层,HCI 层在芯片以及协议栈都有,芯片层面的 HCI 负责把协议栈的数据做处理,转换为芯片内部动作,并且接收到远端的数据,通过 HCI 上报给协议栈。
  5. BLE PHY:BLE 的物理层
  6. BLE LL:BLE 的链路层

TRANSPORT 层:此部分在硬件接口(UART/USB/SDIO)实现 HOST 跟 CONTROLLER 的交互,此部分会分为以下几个协议,在后续章节会对 transport 协议做详细的说明

  1. H2:USB 的 transport
  2. H4: UART 的 transport
  3. H5: UART 的 transport
  4. BCSP: UART 的 transport
  5. SDIO的 transport
    其中2,3,4的主要差别在于H4需要BT CHIP UART_TX/UART_RX/UART_CTS/UART_RTS/VCC/GND接到 MCU,而 H5,BCSP 只需要 BT CHIP 的 UART_TX/UART_RX/VCC/GND 接到 MCU 就可以通信。

HOST 层:此部分就是蓝牙协议栈,是我们本书的重点

  1. HCI(HOST CONTROLLER INTERFACE):主机控制层接口,主要负责透过 transport把协议栈的数据发送给蓝牙芯片,并且接受来自蓝牙芯片的数据

core 文档 HCI 的架构如下:
在这里插入图片描述

在这里插入图片描述
2. L2CAP(Logical Link Control and Adaptation Protocol):逻辑链路控制与适配协议,将ACL数据分组交换为便于高层应用的数据分组格式,并提供协议复用和服务质量交换等功能。
通过协议多路复用、分段重组操作和组概念,向高层提供面向连接的和无连接的数据服务,L2CAP还屏蔽了低层传输协议中的很多特性,使得高层协议应用开发人员可以不必了解基层协议而进行开发。架构如下:
在这里插入图片描述
3. SDP(SERVICE DISCOVERY PROTOCOL):服务发现协议,服务发现协议(SDP)为应用程序提供了一种方法来发现哪些服务可用,并确定这些可用服务的特征

在这里插入图片描述
4. RFCOMM(SerialPortEmulation):串口仿真协议,上层协议蓝牙电话,蓝牙透传SPP等协议都是直接走的RFCOMM
在这里插入图片描述
5. OBEX:对象交换协议,蓝牙电话本,蓝牙短信,文件传输等协议都是走的OBEX

在这里插入图片描述
6. HFP(Hands-Free):蓝牙免提协议
在这里插入图片描述
一共分为两个角色:AG跟HF,蓝牙耳机跟手机连接,那么手机的角色就是AG,蓝牙耳机的角色是HF
在这里插入图片描述
7. HSP:蓝牙耳机协议,最开始的蓝牙耳机协议。算是一个简化版的HFP。
8. SPP(SERIAL PORT PROFILE):蓝牙串口协议,架构如下:
在这里插入图片描述
在这里插入图片描述
9. IAP:苹果的特有协议,分为IAP1/IAP2,一般做Carplay或者iPod功能的人肯定接触过这块
10. PBAP(Phone Book Access):蓝牙电话本访问协议,架构如下:
在这里插入图片描述
在这里插入图片描述
11. MAP(MESSAGE ACCESS PROFILE):蓝牙短信访问协议,架构如下:
在这里插入图片描述
在这里插入图片描述
12. OPP(OBJECT PUSH PROFILE):对象推送协议,架构如下:
在这里插入图片描述
在这里插入图片描述
13. AVCTP(AUDIO/VIDEO CONTROL TRANSPORT PROTOCOL):音视频控制传输协议,是AVRCP的底层,架构如下:
在这里插入图片描述
14. AVDTP(AUDIO/VIDEODISTRIBUTIONTRANSPORTPROTOCOL):音视频分布传输协议,是A2DP的底层,架构如下:
在这里插入图片描述
15. HID(HUMAN INTERFACE DEVICE):人机接口协议,架构如下:
在这里插入图片描述
16. A2DP(Advanced AudioDistribution): 蓝牙音乐协议,架构如下:
在这里插入图片描述
在这里插入图片描述
17. AVRCP(AUDIO/VIDEO REMOTE CONTROL PROFILE):蓝牙音乐控制协议
在这里插入图片描述
在这里插入图片描述
18. ATT:蓝牙 BLE 属性协议
ATT,Attribute Protocol,用于发现、读、写对端设备的协议(针对 BLE 设备),ATT允许设备作为服务端提供拥有关联值的属性集 ,让作为客户端的设备来发现、读、写这些属性;同时服务端能主动通知客户端。
说到属性协议,我们就不得不提属性是什么,在 ATT 中属性分为 3 个内容:
1)属性类型(attribute type),用 UUID 的形式来表现
2)属性句柄(attribute handle),用于标识一个属性
3)属性权限(permissions), 控制是否该 Attribute 可读、可写、属性值是否通过加密链路发送!
ATT 分为两个角色:Server/Client

  1. GATT:蓝牙BLE通用属性协议
    GATT(Generic Attribute Profile),描述了一种使用ATT的服务框架,该框架定义了服务(Server)和服务属性(characteristic)的过程(Procedure)及格式。
    Procedure定义了characteristic的发现、读、写、通知(Notifing)、指示(Indicating)及配置characteristic的广播。
    GATT可以被Application或其他Profile使用,其协议栈如下图
    在这里插入图片描述
    在这里插入图片描述
  2. SM: 蓝牙BLE安全管理协议

蓝牙debug方式

一般蓝牙有几种方式可以debug
1)直接分析debuglog,就是打印log,这是最简单粗暴的方式,一般程序调试都是用这种方式,这种方式对于逻辑错误,执行流程有很大的帮助,但是对于不懂协议栈的人来说,直接打印有的时候很难定位蓝牙具体问题
2)Btsnoop调试蓝牙协议栈,这种通过软件来根据特定的格式来写一个文件,来看蓝牙整个的交互流程,在后续章节有介绍
3)直接录制HCI log,跟2的区别在于2是通过软件来生成文件,而这种方式是通过特定的工具+软件来采集蓝牙芯片端跟协议栈的收发数据,打开效果类似于btsnoop,但是更加有参考意义常用的hci log工具有frontline,ellisys,都是很贵,另外这个是有使用场景或者需求在的!
假设你的MCU没有FileSystem或者Flash不足以保存足够大的btsnoop,那替代btsnoop的方式推荐使用HCIHWsniffer,另外一种场景是上层确定调用uart 收发接口是正常的,但是到了芯片这端就是不响应,或者controller给你一个错误的应答,为了防止跟驱动扯皮,HCI HW sniffer也有应用场景在的!
4)录制airlog,也就是空中包来抓本地芯片跟远端芯片的蓝牙交互流程,也是用特定的工具跟软件来查看,常用的同样是ellisys,frontline,传统蓝牙的一般都比较贵,但是低功耗的蓝牙有更多的选择,而且价格相对于便宜很多,淘宝有<100RMB的。
5)抓芯片log,比如TI有TI logger,csr有spi接口来抓取相应的芯片log
总结下:以上5种方式各有各的好处,也各有各的弊端,针对具体问题采用不同的debug方式!

transport类型介绍

H4

H4 是 UART 传输中最简的一个 Transport,只是在
HCI raw data 的前面加一个 type 就行,如下 HCI 一共有五种 HCI data:
1)HCI COMMAND:由蓝牙协议栈发送给芯片的命令(HOST->CONTROLLER)
2)HCI EVENT:由蓝牙芯片上报给蓝牙协议栈的事件(HOST<-CONTROLLER)
3)HCI ACL:蓝牙协议栈跟蓝牙芯片双向交互的普通数据(HOST<->CONTROLLER)
4)HCI SCO:蓝牙芯片跟蓝牙协议栈双向交互的通话/语音识别数据(HOST<->CONTROLLER)
5)HCI ISO(这部分是在 core5.2 才添加):BLE audio(HOST<->CONTROLLER)

仅在HCI原始数据之前添加了一个字节,表示type

主机控制器接口层

HCI流控

蓝牙协议栈到蓝牙芯片的流控

从 host 到 Controller 的数据流控分为两种:Packet-based Data Flow Control和 Data-Block-Based Data Flow Control。通过 HCI_Write_Flow_Control_Mode 命令来切换,Packet-based data flow control 对于 BR/EDR和LE 芯片来说是默认的,Data-Block-Based Data Flow Control对于AMP controller来说是默认的

协议栈给芯片发送read buffer size command,芯片回复read buffer size event
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在初始化的时候我们读到的 acl buffer size 是 10,所以我们发送了一个 acl 数据,此部分变为 9.

蓝牙协议栈收到蓝牙芯片回送的 Num of complete packet event 后,协议栈更新 acl buffer size 数量。

蓝牙芯片到蓝牙协议栈的流控

一般不常用,可以分别控制ACL和SCO的流控开关,通过Set Controller To Host Flow Control
command 命令控制,初始化的时候通过 Host Buffer Size command 由蓝牙协议栈发送给芯片
acl,sco packet num,以及 length,协议栈收到 acl 后发送给芯片 Host Number Of Completed Packets command,断开后,芯片自己维护重新计数

传统蓝牙command/event/acl/sco/iso命令格式

除非特别声明,否则所有的数据都采用小端模式。

蓝牙command格式

HCI 命令包用于从协议栈发送给芯片的命令。HCI 命令包的格式如下图所示
在这里插入图片描述

Opcode

每个命令被分配一个2字节的而操作码,分为两个字段:操作码组字段(OGF),操作码命令字段(OCF),OGF占用高6bit位置,OCF占用低10bit位置。代码实现:
在这里插入图片描述

OGF分为以下8组:
  1. Link Control commands, the OGF is defined as 0x01.
    此组 Command 集合是用于连接控制的,比如搜索啦,连接啦等等
  2. Link Policy commands, the OGF is defined as 0x02
    此组 Command 集合是用于连接策略的,比如进入 Sniffer mode/角色切换等
  3. HCI Control and Baseband commands, the OGF is defined as 0x03
    此组 Command 集合是用于控制本地 Controller 跟基带的,比如复位,设置连接
    超时等!
  4. Informational Parameters commands, the OGF is defined as 0x04
    此组 Command 集合是设置或者获取信息参数的,比如读取蓝牙地址
  5. Status parameters commands, the OGF is defined as 0x05
    此组 Command 集合是状态参数的,比如读取信号强度等
  6. Testing commands, the OGF is defined as 0x06
    此组 Command 集合是测试命令,比如让设备进度 DUT(Device under Test)模式的
  7. LE Controller commands, the OGF code is defined as 0x08
    此组 Command 集合是 BLE 的 command
  8. vendor-specific debug commands,the OGF code is defined as 0x3F
    此部分是 vendor 定义的,也就是芯片厂商为了扩展 core 文档的 HCI command 定义
OCF 众多,在每个 OGF 下都有一堆的 OCF 定义,后面详细介绍
Parameter Total Length(1字节):后续参数的长度
Parameter:每个 command 的 para
我们在组合封包的时候代码如下

在这里插入图片描述

蓝牙event格式

HCI event 是蓝牙芯片发送给协议栈的事件。HCI 事件包的格式如下图所示,每个字段的定义如下所示:
在这里插入图片描述

Event code:唯一 event 编码,在后续的小节会介绍
Parameter Total Length:后续参数的长度
Parameter:event 参数
Event header 结构体代码如下

在这里插入图片描述
以 HCI_Command_Complete 格式为例:
在这里插入图片描述
是reset命令的回复event
raw data 分析:
0x04-》是H4 transport的开头type
0x0E -> command complete event code
0x04 -> para len,也就是后面参数的长度
0x01 -> num HCI command pacekets(允许从host发往ctrler的命令数量,一般都是1?)
0x03 0x0c -> HCI reset command opcode
0x00 -> status success

蓝牙acl格式

HCI acl 用于从协议栈跟蓝牙芯片双向交互上层协议的数据。HCI acl 的格式如
下图所示,每个字段的定义如下所示:
在这里插入图片描述

Handle(一个半字节):连接句柄,用于蓝牙连接后跟remote交互acl数据用
PB flag(2位):此部分就是用于上层数据(L2CAP),是否是分隔数据,具体 bit 的定义如下(不理解,意思是首包数据或中间数据或者结尾数据?)

在这里插入图片描述

BC flag:此部分定义是否为广播,

在这里插入图片描述

Data total length:后续 payload 的长度

蓝牙sco格式

HCI sco 用于从协议栈跟蓝牙芯片双向交互音频数据,主要用于传统蓝牙。HCI
sco 的格式如下图所示,每个字段的定义如下所示:
在这里插入图片描述

Connection_Handle(一个半字节):连接句柄,用于之后交互soc数据
Packet_Status_Flag(2位):此部分协议栈发送给芯片的设置为 0x00,芯片发送给协议栈的如下图

在这里插入图片描述

Data_Total_Length:SCO数据长度

蓝牙ISO格式

此部分是从 core5.2 开始增加,主要是蓝牙协议栈跟蓝牙芯片交互同步数据,主要用来传输 BLE Audio 的数据
HCI iso 的格式如下图所示,每个字段的定义如下所示:
在这里插入图片描述

实际应用介绍部分command/event

搜索command以及产生的event

整个流程如下:
1)首先协议栈给蓝牙芯片发送搜索 command
2)芯片收到搜索命令上报协议栈一个 command status 的 event
3)然后芯片上报协议栈搜索结果
4)最终芯片上报协议栈搜索完成

在这里插入图片描述

HCI_Inquiry命令

参数:
LAP:分为通用搜索访问代码(GIAC)和受限搜索访问代码(LIAC)
Unlimited inquiry 可以搜索到处于limited inquiry scan 跟 unlimited inquiry scan 状态的设备。
limited inquiry 只能搜索到处于limited inquiry scan 状态的设备。

Inquiry_Length,
Num_Responses,
后两个参数决定停止搜索的时间

HCI_Command_Status事件

异步指令才会触发该事件
参数:status 0x00表示该命令正常处理中,其他表示命令存在问题
Num_HCI_Command_Packets:控制器允许主机发送的命令数量
Command_Opcode:表示该事件是主机下发的哪个命令的响应

HCI_Inquiry_Result事件

一般是每搜到一个设备就会上报一个该事件
参数:Num_Responses:搜索到设备的个数
BD_ADDR:搜到的蓝牙地址
Page_Scan_Repetition_Mode:page scan 重复模式
Reserved:保留参数
Class_of_Device:设备类型
Clock_Offset:时钟偏移
注意此部分普通的搜索不会上来 remote bluetooth name,需要额外去调用
Remote Name Request command 去请求,当然 EIR 除外,后续我们会说明 EIR。

如下是带有 remote bluetooth name的EIR事件,应该是需要先发送Write Extended Inquiry Response命令配置
在这里插入图片描述

HCI_Inquiry_Complete事件

达到搜索完成的条件之后,会触发该事件
参数:status,0x00表示成功完成了搜索,其他表示出错

取消搜索command以及产生的event

流程是,先发送取消搜索的命令,然后收到命令完成的事件

HCI_Inquiry_Cancel命令

无参数

HCI_Command_Complete事件

一般的同步命令完成都会触发该事件上报
参数:
Num_HCI_Command_Packets:控制器允许主机发送的命令数量
Command_Opcode:该事件对应的命令Opcode
Return_Parameters:根据对应的具体命令确定返回的参数

hci connection command 以及产生的 event

流程如下:
在这里插入图片描述

总结步骤:1)蓝牙协议栈向芯片发送连接的 command
2)蓝牙芯片上报蓝牙协议栈 command status with create connection opcode
3)蓝牙芯片上报蓝牙协议栈 connect complete

HCI_Create_Connection命令

异步命令
参数:
BD_ADDR:要连接的remote设备的蓝牙地址
Packet_Type:支持的数据封包类型
Page_Scan_Repetition_Mode:page scan 重复模式
Reserved:保留
Clock_Offset:时钟偏移
Allow_Role_Switch:是否允许角色转换

在这里插入图片描述

HCI_Connection_Complete事件

参数:
status:00代表连接成功
Connection_Handle:连接句柄
BD_ADDR:连接的蓝牙地址
Link_Type:连接的类型,SCO或者ACL
Encryption_Enabled:是否允许加密

hci 接受连线请求 command 以及产生的 event

在这里插入图片描述
步骤整理如下:
1)收到芯片上报给协议栈 connect request 的事件
2)协议栈发送给芯片接受连接请求的 command
3)收到 command status with accept connection req 的 opcode
4)收到 connect complete 的 event

HCI_Connection_Request事件

参数:
BD_ADDR:蓝牙地址
Class_of_Device: 对方的 cod设备类型(可穿戴设备,智能手机等等)
Link_Type:连线类型:SCO,ACL,eSCO

HCI_Accept_Connection_Request命令

参数:BD_ADDR:蓝牙地址
Role:当前连接的角色,00作为master,会产生一个role switch行为,01作为slave

传统蓝牙初始化介绍

每个协议栈使用顺序的会有所不同,并没有一个固定的顺序,一定要哪条指令先发,
举例如下:

  1. 发送 HCI Reset 以及接收回应
  2. 发送Vendor command(我司自己定义的host和controller之间的vendor comman)
  3. 发送 Read Buffer Size command,接收到 command complete with command opcode
  4. 发送 Read BT address command,接收到 command complete with command opcode.
  5. 发送 Write code command,接收到 command complete with comand opcode.
  6. 发送 Change Local Name command,接收到 command complete with comand opcode.
  7. 发送 Write page timeout command,接收到 command complete with comand opcode.
  8. 发送 Write set Event Mask command,接收到 command complete with comand opcode.
  9. 发送 Write Write Simple Pairing command,接收到 command complete with comand
  10. 发送 Write Scan Enable command,接收到 command complete with comand opcode.

Core手册查询方法:
command和event,位于Vol 4,Part E,第7章,1846~2632页之间
另外LE和传统BT的command有部分不同

我司流程:

  1. HCI_Vendor_Command 0x01
  2. HCI Reset
  3. HCI Read Local Version Information
  4. HCI Read Buffer Size
  5. HCI Read BDADDR
  6. HCI Write Class of Device (Pager)
  7. HCI Write Page Timeout (Timeout=5 s)
  8. HCI Write Local Name (Local Name=“XS09 Ultra-B80”)
  9. HCI Write Simple Pairing Mode (Mode=Enabled)(SSP配对方式)
  10. HCI Write Inquiry Mode (Mode=Extended)
  11. HCI Write Scan Enable (Enable=Both)(inquiry scan影响其他设备搜索本设备;page scan影响其他设备跟本设备建立连接,但关闭并不影响本设备搜索和连接其他设备)
  12. HCI Write Extended Inquiry Response

蓝牙PINCODE配对方式

步骤:

  1. 收到HCI_PIN_Code_Request事件
  2. 发送HCI_PIN_Code_Request_Reply命令(带上了PIN_Code长度和PIN_Code内容)

蓝牙SSP配对方式

1)接受到 IO Capability Response event(0x32)
2)接受到 IO Capability Request event(0x31)
3)发送 IO Capability Request Reply command(OGF=0x01 OCF=0x2B),并接收到 command complete with opcode
4)接收到 User Confirmation Request event(0x33)
5)发送 User Confirmation Request Reply command(OGF=0x01 OCF=0x2C),并接收到 command complete with opcode
6)接收到 Simple Pairing Complete event(0x36)

在这里插入图片描述

应该是需要先建立一个HCI连接,才能进行SSP配对

HCI_IO_Capability_Response事件

参数:
BD_ADDR:蓝牙地址
IO_Capability:IO能力(log中为DisplayYesNo)
OOB_Data_Present:是否需要 OOB data(log中为None)
Authentication_Requirements:是否需要 auth(log中为MITM Protection Not Required, No Bonding)

IO能力意思如下:
DisplayOnly 只是需要显示随机数字就好了
DisplayYesNo 让 user 来决定是否要配对或者不配对
KeyBoardonly 让用户通过键盘来输入配对码
NoInputNoOutput 啥也不需要显示。

HCI_IO_Capability_Request事件

参数:
BD_ADDR:蓝牙地址

HCI_IO_Capability_Request_Reply命令

BD_ADDR:蓝牙地址
IO_Capability:IO 能力(log中为No Input/Output)
OOB_Data_Present:是否需要 OOB data(log中为None)
Authentication_Requirements:是否需要 auth(log中为MITM Protection Not Required, General Bonding)

HCI_User_Confirmation_Request事件

参数:
BD_ADDR:蓝牙地址
Numeric_Value:随机数(十进制0-999999,16进制0-0x000F423F)

HCI_User_Confirmation_Request_Reply命令

参数:
BD_ADDR:蓝牙地址

HCI_Simple_Pairing_Complete事件

参数:
status:同上,00表示成功
BD_ADDR:蓝牙地址

EIR注册以及extern inquiry扫描对方的EIR

搜索分为三种类型:
标准/RSSI/EIR
区别在于:
标准搜索只会附带以下信息:
在这里插入图片描述
RSSI就是在此基础上附带RSSI,那么 EIR(EXTENDED INQUIRY RESPONSE)就是在这些基础上会附带额外的一些信息,比如 remote name,对方支持的 UUID 等(前提是对方注册了 EIR),TX power 等

EIR格式说明:
在这里插入图片描述
EIR 信息不管是否有效数据是多少 byte,最终都要 240byte
EIR Data Structure 的格式为:1Byte length+nByte type(一般是 1byte)+(len-n) byte EIR raw data
EIR具体信息在文档 CSS_V9/V10 中

要让其他设备可以搜到本设备的EIR信息,需要先进行写入
HCI_Write_Extended_Inquity_response命令用于写入相关信息,local name,uuid(表示支持哪些profile)

要获取其他设备的EIR信息,需要先设置inquiry模式为extended模式,再搜索

HCI_Write_Inquiry_Mode命令

参数
Inquiry_mode:标准,rssi,extended

Extended inquiry使用注意点:

  1. Extern inquiry 的结果会反复上来(有重复),需要协议栈过滤
    可以看到同样的蓝牙地址,同样的蓝牙名称,但是 RSSI 不同,在同一次搜索中
    会上来几次
  2. Extern inquiry 的搜索可能有的时候不带 EIR 数据
    可以看到同样的蓝牙地址,有的时候并没有上来 EIR 的 data
  3. Extern inquiry 跟标准的搜索前面的格式稍有区别(可以看到 cod 的偏移是相差一个 byte 的)

逻辑链路控制和适配协议(L2CAP)

一些概念

L2CAP channel,在两个设备之间的逻辑通道,通过CID区分
SDU, L2CAP跟上层通信使用的数据包,服务数据单元
PDU,L2CAP跟下层通信使用的数据包,协议数据单元
L2CAP有基础模式,增强重传模式,流模式,重传模式,流控模式
基础模式主要用Basic information frame(B-frame);它是PDU的开头,包含长度和CID
Control frame(C-frame);它是包含L2CAP信令信息的PDU,仅用在信令通道上
segmentation和reassembly,SDU的拆包组包,主要用于非基础模式;
fragmentation和recombination,PDU的拆包组包,他们可能会用在所有模式下

• Basic L2CAP Mode((equivalent to L2CAP specification in Bluetooth v1.1) 默认模式,在未选择其他模式的情况下,用此模式。
• Flow Control Mode,此模式下不会进行重传,但是丢失的数据能够被检测到,并报告丢失。
• Retransmission Mode,此模式确保数据包都能成功的传输给对端设备。
• Enhanced Retransmission Mode,此模式和重传模式类似,加入了 Poll-bit 等提高恢复效率。
• Streaming Mode,此模式是为了真实的实时传输,数据包被编号但是不需要 ACK 确认。设定一个超时定时器,一旦定时器超时就将超时数据冲掉。
• LE Credit Based Flow Control Mode,被用于 LE 设备通讯。
• Enhanced Credit BasedFlow Control Mode

低功耗蓝牙host介绍

主机控制器接口层(HCI)

低功耗蓝牙HCI Command命令说明

低功耗蓝牙HCI Event事件说明

LE Meta event

Event Code:0x3E
这个事件封装了所有LE controller的特有事件,其参数的第一个字节就是子事件代码。

初始化过程:

  1. HCI_Vendor_Command 0x01
  2. HCI Reset
  3. HCI Read Local Version Information
  4. HCI Read Buffer Size
  5. HCI Read BDADDR
  6. HCI Write Class of Device (Pager)
  7. HCI Write Page Timeout (Timeout=5 s)
  8. HCI Write Local Name (Local Name=“XS09 Ultra-B80”)
  9. HCI Set Event Mask (Enabled=62)
  10. HCI Write Simple Pairing Mode (Mode=Enabled)(SSP配对方式)
  11. HCI Write Inquiry Mode (Mode=Extended)
  12. HCI Write Scan Enable (Enable=Both)
  13. HCI Write Extended Inquiry Response
  14. HCI Write LE Host Supported (LE=Enabled, Simultaneous=Disabled)
  15. HCI LE Set Event Mask (Events=56)
  16. HCI LE Set Random Address (Address=C9:D1:09:85:3D:6D (Static))
  17. HCI LE Read Buffer Size › Data=251, Packets=4
  18. HCI LE Read Local Supported Features › Encr, ParReq, ExtRej, FeatEx, Ping, CIS, BIS
  19. HCI LE Set Advertising Parameters (Min=480 ms, Max=640 ms, Type=Connectable, Own=Public, Direct=Public, Address=00:00:00:00:00:00, Channels=37 | 38 | 39, Filter=Scan Any, Request Any)
  20. HCI LE Set Advertising Data (Data=7 bytes)
  21. HCI LE Set Advertise Enable (Advertising=Enabled)

LE_SCAN
LE_Scan_Type:分主动扫描跟被动扫描
区别主要有几个
① 被动扫描仅仅接受广播包,不会发起扫描请求
② 主动扫描接受广播包后悔发送扫描请求给处于广播态的设备,来获取额外的广播数据
一般被动扫描用于确定从机不会发送扫描响应,只会发送 31byte 的广播数据
而主动扫描用于不确定从机是否有额外的数据,所以要额外发起扫描请求来接受更多的广播的数据
注意:主动扫描的扫描请求以及扫描响应也是广播封包

BLE 搜索广播 command 以及 event
步骤 1)发送设置事件掩码的 command(set event mask)以及收到commnd complete event
步骤 2)发送设置支持 BLE 的 command(write le host support)收到command complete event
步骤 3)发送设置 BLE scan 参数的 command(LE set scan param)
步骤 4)发送 BLE 搜索使能的 command(LE set scan enable)
步骤 5)收到步骤 3)4)的 command complete
步骤 6)解析 BLE 广播 event 的数据包
步骤 7)发送结束搜索的 command(LE set scan enable)以及收到commnd complete event

属性协议(ATT)

ATT概念

ATT,Attribute Protocol,用于发现、读、写对端设备属性的协议(针对 BLE设备),ATT 分为两个角色:Server/Client,ATT 允许设备作为服务端提供拥有关联值的属性集,让作为客户端的设备来发现、读、写这些属性;同时服务端能主动通知客户端。

ATT 有固定的 L2CAP CID,也就是 0x0004

ATT部分术语

属性类型(Attribute type)

通过 UUID(universally unique identifier)来标识,UUID 一般分为16bit/32bit/128bit 的 UUID,在 ATT 协议中,32bit 的 UUID 必须转换为 128bit的 UUID!
另外,16bit的UUID是通过加一个128 bit的base uuid来转换为128bit的UUID,base UUID 为:00000000-0000-1000-8000-00805F9B34FB,只所以本来 128bit的 UUID,大部分却采用 16 bit 来发送数据,主要是为了提搞传输速率以及减少交互次数!

属性句柄(Attribute handle)

采用 16bit 的值用于标识一个属性,范围是 0x0000~0xffff,0x0000 是保留数值,0xffff 是最大数值,所以我们一般不用!

属性句柄组(Attribute handle grouping)

Grouping 是一由高层协议定义的一组属性,他们位于其他属性组之前,客户可以请求第一个和最后一个与属性组关联的 Handle

属性值(Attribute value)

属性值是自定义的字段,可以是任何类型的数据,长度可以是固定的也可以是可变的,可变的情况下,在一个request、response、notification、indication中只能有一个attribute value,固定的情况下,长度在attribute type中定义好了,这时可以传送多个attribute value

属性权限(Attribute permission)

Attribute permissions是access permissions、encryption permissions、authentication permissions和authorization permissions的组合。
(1)access permissions用来表示attribute是否允许client进行读写,取值包括:Readable、Writeable、Readable and writable;
(2)encryption permissions用来表示是否加密,取值包括:Encryption required、No encryption required
(3)authentication permissions用来表示当client访问attribute value时是否需要一个已认证的物理链路,同样也表示当server向client发送notification和indication时是否需要一个已认证的物理链路,取值包括:Authentication Required、No Authentication Required
(4)authorization permissions用来表示当client访问attribute value时是否需要授权,取值包括:Authorization Required、No Authorization Required

控制点属性(Control-point attributes)

不可读,但是可写,可通知(Notified)和可指示(Indicated)的属性被称为Control-Point Attribute 高层协议可使用该属性来使能设备特定过程,比如设备上一个给定过程的命令或指示已经完成.

协议方法(Protocol methods)

ATT 使用 Protocol Methods 来发现、读、写、通知、指示属性,方法可分为如
下几种 Request/Response/Command/Notification/Indication/Confirmation

命令(Commands)是 ATT client 发送给 server 端的命令数据,并且不要求回复response,以 CMD 结尾.
请求(Requests)是 ATT client 发送给 server 端的请求数据,要求 server 回复response,以 REQ 结尾.
响应(Reponses)是 ATT server 为响应 client 请求,回复的 response 数据,以RSP 结尾.
通知(Notifications)是 ATT server 发送给 client 的通知数据,并且不要求回复 confirmation,以 NRF 结尾.
指示(Indications)是 ATT server 发送给 client 的指示数据,要求 client 发送confirmation 数据,以 IND 结尾.
确认(Confirmations)是 ATT client 为了回复 server 发送的 indications,发送的 indications 数据,以 CFM 结尾

在这里插入图片描述

ATT bearers

就是用来传输 ATT PDU 的 L2CAP 通道

交互MTU(Exchanging MTU size)

ATT_MTU 定义了 Client 和 Server 之间数据包的最大值;其默认值由高层协议来定义,Client 和 Server 可通过 Exchange MTU Request and Response PDUs 来交换最大数据包然后均使用交换值中的最小值进行通信,同时作为 Server 和Client 的设备应该使用相同的 Client Rx MTU 和 Server Rx MTU,每个 ATT Bearer(L2CAP等下层协议)均有其 ATT_MTU;当一个设备拥有多个 ATT Bearer 时,不同 ATT Bearer 的 ATT_MTU可能不同

长属性值(Long attribute value)

(1)一个数据包最大可以发送的attribute长度是ATT_MTU-1个字节,至少Attribute Opcode要占一个字节,如果attribute value的长度大于ATT_MTU-1个字节,则称为Long Attribute
(2)read长度大于ATT_MTU-1个字节Attribute,需要使用read blob request,使用read request可能读取到前面的ATT_MTU-1个字节
(3)write长度大于ATT_MTU-3个字节Attribute,使用prepare write request和execute write request,使用write request可能写入前面的ATT_MTU-3个字节
(4)在ATT协议中无法确定一个attribute的长度是否可以大于ATT_MTU-3,在上层协议中将声明给定属性的最大长度可以大于(ATT_MTU-3)字节
(5)attribute value最大长度是512个字节

原子操作(Atomic operations)

Server 应该将 Client 的每个请求或命令视为不受影像的原子操作,如果一个链路由于某种原因断开,高层协议应当对属性值得修改负责!Long Attribute 不能被单一的原子操作读、写!

ATT PDU(Protocol Data Unit)介绍

PDU类型

对应六种协议方法

PDU格式

整个 ATT PDU 包含 3 个部分:
1)Attribute Opcode
2)Attribyte Parameters
3)Authentication Signature
在这里插入图片描述

Attribute Opcode:ATT PDU 的操作码
Attribyte Parameters:ATT PDU 的参数,每个opcode有自己的参数
Authentication Signature Flag 取值如下

  • 0: PDU 不包含 Authentication Signature, X 为 1
  • 1: PDU 包含 Authentication Signature(12 octets), X 为 13
    当 Attribute PDU 包含 Authentication Signature 时,则该 PDU 应该通过加密链路传输
    Command Flag 取值如下
  • 1: PDU 为一个 Command
    注意: 只有 Write Command 可能包含一个 Authentication Signature
    ATT 是一种 Sequential Protocol,这意味着在执行下一个动作前应该得到相应的回应,ATT 将 Request-Response 和 Indication-Confirmation Pair 看作一个单一的事务(Transaction)

PDU具体介绍

Error Response

Error Response 用来声明一个给定的请求无法完成,并给出原因
备注:ATT_WRITE_CMD 不需要回复这个 PDU
参数:
Attribute Opcode:操作码,在上一小节中有讲,此处 ATT_ERROR_RSP PDU(0x01)
Request Opcode In Error:是回复哪个请求 Opcode
Attribute Handle In Error:发生错误的句柄
Error Code:错误码,可以查表

MTU exchange

Client 使用 MTU Exchange Request 来告知对方所支持的最大接收 MTU size,同时请求 Server 回应 Server 所支持的最大接收 MTU size.
在低功耗蓝牙连接中,属性协议默认的 MTU 为 23 字节。一般客户端如果不发起这个请求的,它的默认值就是 23,当双方交换的值不同时,用较小的那个作为最终使用的值。

Find information

Find information 包括两组 request/response
ATT_FIND_INFORMATION_REQ 对应 ATT_FIND_INFORMATION_RSP
ATT_FIND_BY_TYPE_VALUE_REQ 对应 ATT_FIND_BY_TYPE_VALUE_RSP

ATT_FIND_INFORMATION_REQ/ATT_FIND_INFORMATION_RSP

查找信息请求和回复用来查找一系列属性的句柄和类型信息。这是唯一一个能让客户端发现任意属性类型的消息。

查找信息请求包含有两个句柄:起始句柄和结束句柄。它们定义了该请求用到的属性句柄范围。为了找到所有数值的属性,该请求的起始句柄将是 0x0001,结束句柄设为 0xFFFF。但是回复的信息中因为长度限制,并不能包含所有的属性,所以需要再次请求,只是将起始句柄改为查找到的最大句柄的后一个句柄开始。

查找信息的响应格式包括format和information Data
format代表UUID的类型,是16bit还是128bit的
information Data是两字节的Handle(标识属性)还有两字节或16字节的UUID(标识属性类型的)

ATT_FIND_BY_TYPE_VALUE_REQ/ATT_FIND_BY_TYPE_VALUE_RSP

按类型值查找请求和回复可以根据给定的类型与数值查找相应的属性。该请求包含有两个句柄: 起始句柄和结束句柄,规定查找范围。对于这一范围类的所有属性,如果和请求中所指定的类型和数值一样,那么这个属性就要在响应中返回

Reading attribute

Ready attributes 包括 6 组 request/reponse
ATT_READ_BY_TYPE_REQ/ATT_READ_BY_TYPE_RSP
ATT_READ_REQ/ATT_READ_RSP
ATT_READ_BLOB_REQ/ATT_READ_BLOB_RSP
ATT_READ_MULTIPLE_REQ/ATT_READ_MULTIPLE_RSP
ATT_READ_BY_GROUP_TYPE_REQ/ATT_READ_BY_GROUP_TYPE_RSP
ATT_READ_MULTIPLE_VARIABLE_REQ/ATT_READ_MULTIPLE_VARIABLE_RSP

ATT_READ_BY_TYPE_REQ/ATT_READ_BY_TYPE_RSP

这个命令能在句柄范围内读取某个属性值。当客户端仅知道属性的类型而非句柄时可以使用该请求。请求包含有起始、结束句柄和需要读取的属性的类型。响应将给出符合的句柄和数值。这个请求用于搜索被包含的服务,并通过特性类型来发现服务中的所有的特性。它也被用来读取已知类型的特性值

ATT_READ_REQ/ATT_READ_RSP

读取请求是属性协议总最简单的请求。该请求包含一个句柄,响应将返回该句柄对应的属性值。只有在客户端已知属性句柄的情况下,才能使用该请求读取属性值。

ATT_READ_BLOB_REQ/ATT_READ_BLOB_RSP

有时属性值太长,无法装入一个读取响应,须使用大对象读取请求来获取剩余字节。大对象读取请求不光包含属性句柄,还包含属性值的这个数据中的偏移量。
其响应将从属性偏移量开始,包含尽可能多的属性值。在获得了属性值的前 22 (ATT_MTU-1)节后,假如客户端还想获取后续的属性值,则使用大对象读取请求。下一条响应将返回第 23 个字节到 44 个字节;如此继续,直到客户端读取到完整的属性值。该请求用于读取长特征值与长特征描述符。

ATT_READ_MULTIPLE_REQ/ATT_READ_MULTIPLE_RSP

用来在一个操作中读取多个属性值。该请求包含一个或多个属性句柄,响应则按顺序返回相应的属性值。然而因为响应中的数值之间没有界限,因此,在请求中除了最后一个属性允许可变的长度,其他属性必须为定长的属性值。也就是说,如果客户端用一个多重读取请求来读取三个属性,前两个属性的长度必须固定,最后一个属性的长度则可以变化。如果客户端请求读取的属性值的长度超过了响应数据包所能承载的最大长度,那么无法放入响应数据包的数值将被丢弃。

ATT_READ_BY_GROUP_TYPE_REQ/ATT_READ_BY_GROUP_TYPE_RSP

它和按类型读取请求类似,也包含有一个句柄范围,读取时将其视为一个属性的类型来处理,只不过属性的类型必须为分组属性。其响应包含所读取的属性句柄、属性分组中最后一个属性以及属性的数值。这意味着,如果分组类型是首要服务,它将返回所有首要服务声明的属性句柄、该首要服务中最后一个属性以及首要服务声明的数值。因此,可以仅凭单个请求来发现设备上的所有首要服务、与之关联的属性句柄的范围以及这些服务的类型。如同其他返回对个句柄-数值对的响应,如果返回的值长度可变,那么只有长度相同的属性值将在第一个响应中被返回。因此,客户端必须再次发起请求,更新起始句柄来发现想要获取的下一个属性

Writing attributes

Write attributes 包括 1 组 request/response,两组 command

ATT_WRITE_REQ/ATT_WRITE_RSP

这个是写特定的 handle 的属性值

ATT_WRITE_CMD

写入命令类似于读取请求,区别是写入命令没有响应。写入命令包含要写入的属性的句柄和要写入的数值。当无需响应时,可以使用写入命令。

ATT_SIGNED_WRITE_CMD

签名写命令和写命令类似,只是前者包含认证签名。通过这样的机制,发送端可以向服务器发送写入命令时认证自己,而无需加密通信连接。签名写命令适用于以下两种场合:
1)发起加密将显著增加数据连接的延迟
2)发起加密将显著增加简短且无需加密的数据的送达成本
认证签名由签名计数器和消息认证码构成。签名计数器对设备间发送的每一条消息赋予不同的值,不论消息发送的间隙连接中断与否。使用签名计数器可以抵御消息重放攻击,因此,假如签名写入命令的签名计数器值和先前的值相同,该命令会被忽略。消息认证码长度为 64 位,该码位于句柄、数值和签名计数器之后。注意,服务器需要为每一个客户端保存其最后使用的签名计数器。

Queued writes

长属性的写入,需要分为两步,先准备写,再执行写
准备写:ATT_PREPARE_WRITE_REQ 和ATT_PREPARE_WRITE_RSP
准备写过程是,客户端将长属性分段传输给了服务器,服务器先放入缓存队列之中,传完之后再执行写
执行写:ATT_EXECUTE_WRITE_REQ 和ATT_EXECUTE_WRITE_RSP
执行写过程就是将之前收到的属性值写入真正的属性中

Server initiated

Server initiated 包括 1 组 indication/confirms,两组 notification
ATT_HANDLE_VALUE_NTF
ATT_HANDLE_VALUE_IND/ATT_HANDLE_VALUE_CFM
ATT_MULTIPLE_HANDLE_VALUE_NTF

ATT_HANDLE_VALUE_NTF

当服务器想要向客户端发送快速的属性状态更新时,可以发送一条句柄值通知。这个是服务器能够发给客户端的两种消息中的一种,并且是不要求响应的那种。

ATT_HANDLE_VALUE_IND/ATT_HANDLE_VALUE_CFM

句柄值指示类似于句柄值通知。它有着相同的属性句柄字段和数值,不同的是客户端收到指示以后应回复。服务器一次只能发送一条指示,并且只有收到确认响应后才能发起下一条指示。
句柄值确认不含任何数据,主要用于流控。因为具备了确认机制,指示被视为可靠传输。一旦服务器收到确认信息,它便能确定客户端收到了该信息。

ATT_MULTIPLE_HANDLE_VALUE_NTF

可以发送两个或者两个以上的 notification

通用属性协议(GATT)

GATT概念

GATT(Generic Attribute Profile),描述了一种使用 ATT 的服务框架 ,该框架定义了服务(Server)和服务属性(characteristic)的过程(Procedure)及格式 。Procedure 定义了 characteristic 的发现、读、写、通知(Notifing)、指示(Indicating)及配置 characteristic 的广播。
GATT 可以被 Application 或其他 Profile 使用,其协议栈如下图
在这里插入图片描述

PC 就是做 GATT client 用来读取温度计的数据,,温度计 Sensor 做 GATT server 用来把温度数据发送送出去

GATT层级

GATT 指定了数据交互的结构(Structure);这个结构体定义了一些基本元素,如Service、Characteristic ,这些元素存在于 Attribute 中,层级结构如下:
GATT 中最上层是 Profile,Profile 由一个或多个服务(Service)组成 ,服务是由 Characteristics 组成,或是其他服务的引用(Include),Characteristic 包含一个值(Value),可能包含该 Value 的相关信息

服务(service)

一个service是被service definition定义的,service definition可能包含其他services的引用、必须的characteristics和可选的characteristics

有两种类型的 service
1)Primary Service : 拥有基本功能的服务,可被其他服务包含,可以通过Primary Service Discovery 过程来发现
2)Secondary Service : 仅用来被 Primary/Other Secondary Service、高层协议引用的服务.

service definition肯定包含一个service declaration,可能包含include definitions 和characteristic definitions,发现下一个service declaration或者Attribute Handle达到最大值则表示service definition结束了;
在这里插入图片描述
在这里插入图片描述

特性(Characteristic)

Characteristic 由 Characteristic Definition 定义,包含一个特征声明(Characteristic declaration)、特征值声明(Characteristic Value declaration)和可选的特征的描述声明(characteristic descriptor declarations)

特性声明(Characteristic declaration)

特性声明(Characteristic declaration):特性声明本身的 UUID 值是 0x2803,特性声明中需要声明的特性是在属性值中的,属性值包含有 3 个字段:
特性性质、属性句柄和属性类型,且仅为只读。如下:
在这里插入图片描述

特征值声明(Characteristic Value declaration)

Characteristic Value declaration包含characteristic的value,Characteristic Value declaration紧跟在characteristic declaration之后,一个characteristic definitions都有一个Characteristic Value
declaration,具体组成如下图所示:
在这里插入图片描述

特征的描述声明(characteristic descriptor declaration)

Characteristic descriptors主要包含一些Characteristic Value的相关信息.Characteristic descriptors位于Characteristic Value declaration之后,多个Characteristic descriptors之间没有顺序要求。

客户端特性配置描述符(Client Characteristic Configuration)

支持通知或者指示的特性必须使用客户端配置描述符。它的声明格式如图所示。
在这里插入图片描述
该描述符是一个 2byte 的数值,分别用于设置通知与指示,但是不允许同时设置。

服务器特性配置描述符(Server Characteristic Configuration)

使设备广播该特性所属服务的相关数据,格式如下:
在这里插入图片描述

特性表示格式描述符(Characteristic Presentation Format)

Characteristic Presentation Format declaration定义Characteristic Value的格式,如果在characteristic definition中有超过1个Characteristic Presentation Format declarations存在,那么肯定要有一个Characteristic Aggregate Format declaration存在

特定聚合格式描述符(Characteristic Aggregate Format)

有些特性值远比单一的数据复杂得多。譬如用标准的符号来表示地球上的某个位置,通常包含经度和纬度值,二者组合在一起便构成一个“坐标值”。为了构造类似的复杂的特性值,特性聚合格式描述符允许引用多个表示格式描述符来解释组合值的每个字段

GATT特性

GATT 一共定义了 11 个特性,如下:
There are 11 features defined in the GATT Profile:

  1. Server Configuration
  2. Primary Service Discovery
  3. Relationship Discovery
  4. Characteristic Discovery
  5. Characteristic Descriptor Discovery
  6. Reading a Characteristic Value
  7. Writing a Characteristic Value
  8. Notification of a Characteristic Value
  9. Indication of a Characteristic Value
    10.Reading a Characteristic Descriptor
    11.Writing a Characteristic Descriptor

Server Configuration

这个功能是client用来设置ATT的MTU,当client的ATT_MTU大于default ATT_MTU时,client就会调用Exchange MTU程序配置ATT_MTU,这个程序只有在连接过程中执行一次(虽然Spec中规定只能使用一次,但是NRF connect中可以无限测试)。
(client和server都会取Client Rx MTU和Server Rx MTU中最小的值作为ATT_MTU)

Primary Service Discovery

Client使用这个功能搜索server上的primary services,这个功能分为两个子程序:Discover All Primary Services和Discover Primary Services by Service UUID

Discover All Primary Services

在这里插入图片描述

Discover Primary Service by Service UUID

举例:
在这里插入图片描述
(1)Client使用ATT的Find By Type Value Request,设置Attribute Type为«Primary Service»,Starting Handle=0x0001,Ending Handle=0xFFFF,Attribute Value设置为UUID1;
(2)server回复Find By Type Value Response,Handles Information List为:0x0200,0x0214;最后一个元素的Group End Handle=0x0214,不是0xFFFF所以没有结束。
(3)client继续ATT的Find By Type Value Request,设置Attribute Type为«Primary Service»,Starting Handle=1 + 0x0214=0x0215,Ending Handle=0xFFFF,Attribute Value设置为UUID1;
(4)server回复Error Response,Error Code为«Attribute Not Found»,搜索结束

Relationship Discovery

在这里插入图片描述
举例:
(1)Client使用Read By Type Request,Attribute Type为«Include»,Starting Handle为包含这个«Include»的Service的starting handle即0x0200,Ending Handle为包含个«Include»的Service的最后一个handle即0x0214
(2)server回复Read By Type Response,Length=0x08,Attribute Data List为:0x0201,0x0500,0x518,«UUID1»;其中0x08表示Attribute Data List中每个元素的长度,0x0201表示include declaration的handle,0x0500,0x518分别表示被包含的那个service的service declaration、End Group Handle,«UUID1»即被包含的service的16bit的UUID。0x0201!=0x0214,所以没有结束。
(3)client继续发送ATT的Read By Type Request,设置Attribute Type为«Include»,Starting Handle=1 + 0x0201=0x0202,Ending Handle=0x0214
(4)server回复Read By Type Response,Length=0x06,Attribute Data List为:0x0202,0x0550,0x568;其中0x06表示Attribute Data List中每个元素的长度,0x0202表示include declaration的handle,0x0550,0x558分别表示被包含的那个service的service declaration、End Group Handle,没有被包含的那个service的UUID,所以被包含的那个service的UUID应该是128bit的,需要使用Read Request去获取
(5)Client使用Read Request,Attribute Handle参数设置为0x550
(6)Server回复Read Response,参数Attribute Value就是被包含的那个service的128bit的UUID
(7)client继续发送ATT的Read By Type Request,设置Attribute Type为«Include»,Starting Handle=1 + 0x0202=0x0203,Ending Handle=0x0214
(8)server回复Error Response,Error Code为«Attribute Not Found»,搜索结束

Characteristic Discovery

Discover All Characteristics of a Service

举例:
在这里插入图片描述
(1)Client使用Read By Type Request,Attribute Type为«Characteristic»,Starting Handle为包含个«Characteristic»的Service的starting handle即0x0200,Ending Handle为包含这个«Characteristic»的Service的最后一个handle即0x0214
(2)server回复Read By Type Response,Length=0x07,Attribute Data List为:0x0203,0x02,0x0204, «UUID1»,0x0210,0x02,0x212,«UUID2»;其中0x07表
示Attribute Data List中每个元素的长度,0x0203,0x02,0x204, «UUID1»是第一个Attribute Handle和Attribute Value对(Attribute Handle=0x0203,Characteristic Properties=0x02,Characteristic Value Handle=0x0204,Characteristic UUID= «UUID1»),0x0210,0x02,0x212,«UUID2»是第二个Attribute Handle和Attribute Value对;0x0210!=0x0214,所以没有结束。
(3)client继续发送ATT的Read By Type Request,设置Attribute Type为«Characteristic»,Starting Handle=1 + 0x0210=0x0211,Ending Handle=0x0214
(4)server回复Error Response,Error Code为«Attribute Not Found»,搜索结束

物理通道被细分为时间单位,称为事件。数据以包的形式在LE设备之间传输,这些包位于这些事件中。事件类型包括:Advertising事件、Extended Advertising事件、Periodic Advertising事件、Connection事件和Isochronous事件(分为BIS、BIG、CIS和CIG事件)。

Descriptor学习

characteristic Extended properties

这个描述符每个characteristic只能有一个
在characteristic properties中,extended properties位是1,那么这个描述符应该存在
只读,无需认证,无需授权

value:

reliable write 只占1bit
允许这个characteristic的value进行可靠写
可靠写过程举例如下:
在这里插入图片描述
writable Auxiliaries 只占1bit
允许写这个characteristic 的 characteristic user Descriptor

characteristic user Descriptor

这个描述符每个characteristic只能有一个
这个就是用户描述这个characteristic的描述符,value就是UTF-8的字符串

client characteristic configuration

这个描述符每个characteristic只能有一个
这个描述符的配置应在跨连接的绑定设备中保持持久(掉电保存)。客户端特征配置描述符值应在每次与非绑定设备连接时设置为默认值。
每个客户端都有自己的客户端特征配置实例。读取客户端特征配置仅显示该客户端的配置,写入仅影响该客户端的配置。服务器可能需要进行身份验证和授权才能写入配置描述符。
属性值长度应为两个八位字节,并应设置为特征描述符值。

value

notification:占1位,如果这位为1,这个characteristic value变化了,通知订阅了这个值的客户端
Indication:占1位,如果这位为1,这个characteristic value变化了,指示订阅了这个值的客户端

server characteristic configuration

这个描述符每个characteristic只能有一个
这个描述符对所有客户端有效
实际上就是确定这个characteristic value是否要被广播

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

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

相关文章

深入理解Dubbo-7.服务消费调用源码分析

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理&#x1f525;如果感觉博主的文章还不错的话&#xff…

Linux权限(上)

目录 shell命令以及运行原理 Linux权限 Linux中的用户类别 文件类型 文件的访问权限 在讲权限之前&#xff0c;我们得先了解一下命令的执行原理。 shell命令以及运行原理 我们每次在打开Xshell执行相关命令时&#xff0c;通常会看到这样一段代码&#xff1a; [yjdhecs…

手工酸奶加盟店赚钱吗?一年有多少利润

手工酸奶以其新鲜、健康、美味的特点&#xff0c;受到了越来越多消费者的喜爱。 那开一家手工酸奶加盟店能赚钱吗&#xff1f;一年又能有多少利润呢&#xff1f; 作为经营酸奶店5年的创业者&#xff0c;我给大家分享下最真实的情况。&#xff08;可以点赞收藏&#xff0c;方便…

巨杉数据库入选“2023信创独角兽企业100强”

近日&#xff0c;《互联网周刊》、eNet研究院、德本咨询联合发布了“2023信创独角兽企业100强”榜单&#xff0c;巨杉数据库凭借卓越的技术实力和出色的研发能力荣登榜单&#xff0c;本次上榜既是对巨杉数据库长期深耕信创领域的高度认可&#xff0c;也是对其在分布式文档型数据…

通过“待办事项列表项目”快速学习Pyqt5的一些特性

Pyqt5相关文章: 快速掌握Pyqt5的三种主窗口 快速掌握Pyqt5的2种弹簧 快速掌握Pyqt5的5种布局 快速弄懂Pyqt5的5种项目视图&#xff08;Item View&#xff09; 快速弄懂Pyqt5的4种项目部件&#xff08;Item Widget&#xff09; 快速掌握Pyqt5的6种按钮 快速掌握Pyqt5的10种容器&…

W25N01GV 芯片应用

项目中处于成本考虑&#xff0c;要把Nor Flash换成低成本的Nand Flash。 这里总结下芯片应用。 总体概述&#xff1a; 1&#xff09;W25N01&#xff08;NandFlash&#xff09;和W25Q&#xff08;Nor Flash&#xff09;的操作大不一样。 NandFlash擦除以块&#xff08;128KB&…

LeetCode-反转链表问题

1.反转链表 题目描述&#xff1a; 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 思路&#xff1a; 反转链表也就是链表倒置&#xff0c;我一直以来的办法就是先建立一个头节点&#xff0c;之后再遍历链表来进行头插。 代码&#xff1…

HBuilderX 配置 夜神模拟器 详细图文教程

在电脑端查看App的效果&#xff0c;不用真机调试&#xff0c;下载一个模拟器就可以了 --- Nox Player&#xff0c;夜神模拟器&#xff0c;是一款 Android 模拟器。他的使用非常安全&#xff0c;最重要的是完全免费。 一. 安装模拟器 官网地址&#xff1a; (yeshen.com) 二.配…

也许你不需要人工智能

已经不记得我是什么时候开始使用谷歌搜索引擎的&#xff0c; 在刚开始的时候&#xff0c;我看到了一本书&#xff0c;里面有各种各样的搜索技巧。在考虑到如果我不会搜索引擎这种关键技能&#xff0c;那么我将在这个信息时代落后&#xff0c;我读了那本书。 从那本书中我学到了…

运行软件时提示msvcp140.dll丢失的5个解决方法

电脑打开软件提示找不到msvcp140.dll丢失&#xff0c;这是许多用户在使用电脑过程中会遇到的问题。本文将为您介绍五个详细的解决方法&#xff0c;以及msvcp140.dll丢失的原因、作用和是什么。 一、msvcp140.dll丢失原因 系统损坏&#xff1a;操作系统在使用过程中&#xff0…

使用SPSS的McNemar检验两种深度学习模型的差异性

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 使用SPSS的McNemar检验两种深度学习模型的差异性 前言简述&#xff1a;一、McNemar检验1.1来源1.2 两配对样本的McNemar(麦克尼马尔)变化显著性检验1.3 适用范围&#xff1a;…

机器学习之无监督学习

聚类&#xff1a;发掘纵向结构的某种模式信息&#xff0c;某些x属于相同的分布或者类别 特征学习&#xff1a;发掘横向结构的某种模式信息&#xff0c;每一行都可以看成是一种属性或特征 密度估计&#xff1a;发掘底层数据分布&#xff0c;x都是从某个未知分布p(x)采出来的&a…

Mysql数据库 19.Mysql 锁

MySQL锁 锁&#xff1a;锁是计算机用以协调多个进程间并发访问同一共享资源的一种机制&#xff0c;在数据库中&#xff0c;除传统的计算资源&#xff08;CPU、RAM、I/O&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源&#xff0c;如何保证数据并发访问的一…

C#中的封装、继承和多态

1.引言 在面向对象的编程中&#xff0c;封装、继承和多态是三个重要的概念。它们是C#语言中的基本特性&#xff0c;用于设计和实现具有高内聚和低耦合的代码。本文将详细介绍C#中的封装、继承和多态的相关知识。 目录 1.引言2. 封装2.1 类2.2 访问修饰符 3. 继承4. 多态4.1 虚方…

高云GW1NSR-4C开发板M3核串口通信

1.PLLVR频率计算 高云的M3核要用到PLLVR核&#xff0c;其输出频率FCLKIN*(FBDIV_SEL1)/(IDIV_SEL1)&#xff0c;但同时要满足FCLKIN*(FBDIV_SEL1)*ODIV_SEL)/(IDIV_SEL1)的值在600MHz和1200MHz之间。例如官方示例&#xff0c;其输入频率FCLKIN50MHz&#xff0c;要输出80MHz&am…

鸿蒙原生应用/元服务开发-Stage模型能力接口(三)

一、说明 AbilityLifecycleCallback模块提供应用上下文ApplicationContext的生命周期发生变化时触发相应回调的能力&#xff0c;包括onAbilityCreate、onWindowStageCreate、onWindowStageActive、onWindowStageInactive、onWindowStageDestroy、onAbilityDestroy、onAbilityFo…

一文弄懂自编码器 -- Autoencoders

1. 引言 近年来&#xff0c;自编码器&#xff08;Autoencoder&#xff09;一词在许多人工智能相关的研究论文、期刊和学位论文中被频繁提及。自动编码器于1980年推出&#xff0c;是一种用于神经网络的无监督学习技术&#xff0c;可以从未被标注的训练集中学习。 本文重点介绍…

指针进阶篇

指针的基本概念&#xff1a; 指针是一个变量&#xff0c;对应内存中唯一的一个地址指针在32位平台下的大小是4字节&#xff0c;在64位平台下是8字节指针是有类型的&#xff0c;指针类型决定该指针的步长&#xff0c;即走一步是多长指针运算&#xff1a;指针-指针表示的是两个指…

协方差和相关系数,还有信号与系统里的 互相关函数

协方差和相关系数参考&#xff1a;https://www.bilibili.com/video/BV1vK411N7Yp/ 协方差和相关系数的思想就是&#xff1a;同增同减&#xff0c;找相关的变量 协方差公式是如下图老师的板书 可以发现&#xff0c;当 X Y 同增同减趋势明显时&#xff0c;协方差的值就越大 所…

STM32_启动流程详解

目录标题 前言 启动流程概述复位中断函数详解SystemInit函数详解 __main函数详解 附录 stm32单片机的存储器映像中断向量表的映射 前言 最近在学习IAP远程OTA升级单片机固件程序&#xff0c;发现自己对单片机的启动流程还不是那么了解&#xff0c;就总结整理一下吧。 启动流程…