目录
2.1 HIC command格式 —-----具体参数参考链接5
3 .L2CAP(逻辑链路控制和适配协议) ------具体参数参考链接6
6. GAP(Generic Access Profile通用访问协议)
8. GATT (Generic Attribute Protocol 通用属性协议)
【参考链接如下】
1、ARM平台蓝牙协议栈移植详解:
https://blog.youkuaiyun.com/gatieme/article/details/48751743
2、蓝牙协议栈各层功能简介:
http://blog.chinaunix.net/uid-21411227-id-2780269.html
3、蓝牙广播通信相关技术分析:PDU数据包的构成及分析、channel分析、三种广播状态(7种广播类型)、command参数
https://blog.youkuaiyun.com/huangshuyi529/article/details/80435010
4、蓝牙HCI层采用不同串口分析:HCI层描述了Host和Controller之间可以通过串口、usb口进行连接的不同参数和不同的处理方式
5、HCI层数据包参数详解:OCF 、OGF、及其组合参数解析(详),供应商特定操作码解析,HCI数据传输过程的文字解析
6、I2CAP协议:信道工作模式,信道分类、各类信道在不同工作模式下的帧
https://blog.youkuaiyun.com/xsophiax/article/details/104052416
7、RFCOMM协议(详):https://blog.youkuaiyun.com/madannasf/article/details/102738074
8、SDP协议:https://blog.youkuaiyun.com/jobbofhe/article/details/78477407
9、GAP协议:https://blog.youkuaiyun.com/liwei16611/article/details/80958842
10、ATT协议(详):https://blog.youkuaiyun.com/zw515370851/article/details/88959205
10-1:GAP、ATT、GATT协议简析
https://blog.youkuaiyun.com/stivor/article/details/107507162
11、GATT协议:https://www.pianshen.com/article/2563508308/
1 蓝牙广播通信解析 -------具体参考链接3
1.1 广播类型及其编码
报头的内容取决于该报文是广播报文还是数据报文。广播报文的报头如下图
广播报文的报头包含4bit广播报文类型、2bit保留位、1bit发送地址类型和1bit接收地址类型。
广播类型可分为三类,Advertising Event Type(1-4), Scanning状态(5-6),Initiating状态(7),详细介绍如下所示:
1. 可连接的非定向广播(Connectable Undirected Event Type):
这是一种用途最广的广播类型,包括广播数据和扫描响应数据,它表示当前设备可以接受其他任何设备的连接请求。进行通用广播的设备能够被扫描设备扫描到,或者在接收到连接请求时作为“从设备”进入一个连接。通用广播可以在没有连接的情况下发出,换句话说,没有主从设备之分。
2. 可连接的定向广播(Connectable Directed Event Type):
定向广播类型是为了尽可能快的建立连接。这种报文包含两个地址:广播者的地址和发起者的地址。发起者收到发给自己的定向广播报文之后,可以立即发送连接请求作为回应。 定向广播类型有特殊的时序要求。完整的广播事件必须每3.75ms重复一次。这一要求使得扫描设备只需扫描3.75ms便可以收到定向广播设备的消息。
3. 可扫描的非定向广播(Scannable Undirected Event Type):
又称可发现广播,这种广播不能用于发起连接,但允许其他设备扫描该广播设备。这意味着该设备可以被发现,既可以发送广播数据,也可以响应扫描发送扫描回应数据,但不能建立连接。这是一种适用于广播数据的广播形式,动态数据可以包含于广播数据之中,而静态数据可以包含于扫描响应数据之中。
4. 不可连接的非定向广播(Non-connectable Undirected Event Type):
仅仅发送广播数据,而不想被扫描或者连接。这也是唯一可用于只有发射机而没有接收机设备的广播类型。不可连接广播设备不会进入连接态,因此,它只能根据主机的要求在广播态和就绪态之间切换。
5. 扫描请求(SCAN_REQ):
蓝牙一直会不间断的发送扫描请求,主动寻找正在广播的设备,以建立连接
6. 扫描响应(SCAN_RSP):
蓝牙进行文件传送时,传送几个文件,这里就会响应几次,接收数据
7. 连接请求(CONNECT_REQ):
它不关心广播数据,只关心ADV_DIRECT_IND和ADV_IND两类消息,并在符合条件的时候,发出CONNECT_REQ,请求建立连接。
LE定义了物理层、链路层、L2CAP、安全管理器、属性协议和通用属性配置文件。GAP定义了四个特定角色:Broadcaster(广播), Observer(观察)、从机和主机
2 HIC --------具体参数参考链接4
BLE协议在硬件上分为上下两部件:主机(Host,PC、单片机、Linux板)、控制器(蓝牙模块), Host和Controller之间,通过HCI(Host Controller Interface)相连,如下图所示:
Host和Controller之间的数据有命令(Command)、事件(Event)、ACL数据和SOC数据(传输层)。
HCI可分为三个部分,前两个 用于沟通Host和Control的接口,具体如下:
位于Control中的HCI Firmware
位于Host的HCI Driver
位于Host 和Control的HCI 传输层
HCI层描述了Host和Controller之间通过什么接口来连接,可以通过串口、usb口等进行连接。
当通过串口进行传输数据时,可以在数据的前面加上一个字节的头部,用来分辨这个数据是command、event还是acl data,头部格式如下图所示:
对于usb口,在usb硬件里面有多个endpoint,command可以发送给某个端点,event可以从某个端点发给Host,不同的数据使用不同的端点。在硬件上传输这些数据时,就不需要加上头部,只需发送数据本身就可以了。
send_packet函数原型为:
int (*send_packet)(uint8_t packet_type, uint8_t *packet, int size);
其中的packet_type有4种取值,代表4种类型的数据(在BLE中只有3种,不支持SCO),这些值在头文件btstack-master\src\bluetooth.h中定义:
2.1 HIC command格式 —-----具体参数参考链接5
OGF(组域)=OpCode Group Field OCF(命令域)=OpCode Command Field OpCode:用以区分不同的命令, OGF(最高有效位6比特) OCF(最低有效位10比特)),具体OCF 、OGF及其组合参数解析参考链接5的第2节
Parameter_Total_length:参数的长度(以字节为单位,一般为1字节)
Parameter 0~N :参数列表
Command分为六种类型(case OGF)
~0x01 链路控制命令(Link Control Commands)
~0x02 链路政策命令(Link Policy Commands)
~0x03 控制和基带命令(Control & Baseband Commands)
~0x04 信息命令(Informational Parameters)
~0x05 状态命令(Status Parameters)
~0x06 测试命令(Testing Commands)
~0x08 仅限LE指令( LE Only Commands)----Low Power
~0x3F 厂商调试命令(Reserved)
tip: 所有BLE相关的HCI Command的OGF都是0x08。
Host发出的大多数Command都会触发Control产生相应的Event作为响应
广播通信相关的HCI Command介绍: —-----具体参数参考链接3
用于设置广播参数(HCI_LE_Set_Advertising_Parameters);
广播数据(HCI_LE_Set_Advertising_Data,OCF为0x0008);
建立连接(HCI_LE_Create_Connection);
取消连接(HCI_LE_Create_Connection_Cancel)等
2.2 HIC event —-----具体参数参考链接5
Event Code 用以区分不同的事件(0x00~0xFF)
Parameter_Total_length 参数的长度(以字节为单位)
Event Parameter 0~N 参数列表
HCI事件使用8位事件代码,所有LE事件只有一个事件代码(0x3E)。
所有事件代码对于BT和BLE都是唯一的。
仅供应商特定事件保留事件代码255。
第一个事件参数用作子事件代码以区分LE事件类型,LE事件及对应的子事件代码如下图所示:
其他事件对应的代码如下所示:
3 .L2CAP(逻辑链路控制和适配协议) ------具体参数参考链接6
L2CAP位于基带之上,将基带的数据分组转换为便于高层应用的数据分组格式,并提供协议复用和服务质量交换等功能。L2CAP只支持ACL数据传输,不支持SCO数据。
L2CAP中文为逻辑链路适配层,主要提供信息数据的分割/重组等传输方式。在bluedroid中,很多的上层会向l2cap注册相关服务,比如rfcomm(虚拟串口,最多可虚拟64路),sdp,gatt等。
1、L2CA_Register (SDP_PSM, &sdp_cb.reg_info)
2、L2CA_Register (BT_PSM_ATT, (tL2CAP_APPL_INFO *) &dyn_info)
3.1 信道工作模式
逻辑信道可以工作在5种不同的模式下(可以理解为5种不同的使用场景),最后一种是LE设备特有的:
1、Basic L2CAP Mode 默认模式,在未选择其他模式的情况下,用此模式。
2、Flow Control Mode 此模式下不会进行重传,但是丢失的数据能够被检测到,并报告丢失。
3、Retransmission Mode 此模式确保数据包都能成功的传输给对端设备。
4、Enhanced Retransmission Mode 此模式和重传模式类似,加入了Poll-bit等提高恢复效率。
5、Streaming Mode 此模式是为了真实的实时传输,数据包被编号但是不需要ACK确认。设定一个超时定时器,一旦定时器超时就将超时数据冲掉。
6、LE Credit Based Flow Control Mode 被用于LE设备通讯。
3.2 信道分类
L2CAP信道有三种类型:
A、面向连接信道CO:Connection-Oriented,用于两个设备之间的数据通信。
B、无连接信道CL:Connection-Less,用来向一组设备广播方式传输数据。CID(channel ID)为固定值:0x0002。
C、信令信道:Signaling,用于创建CO通道,可以通过协商改变CO信道的特性。若当前蓝牙处于普通蓝牙模式下,CID = 0X0001; 若当前蓝牙处于低功耗模式下,CID = 0X0005
3.1.1 面向连接的信道
用于基础L2CAP模式下的面向连接信道。B帧格式如下:
其中的Length为Information payload的长度,不包括包头长度,Information payload的长度范围是0~65535。ChannelID为接收方的CID。
举例如下:
3.1.2 无连接信道
1) 用于基础L2CAP模式下面向无连接的信道。G帧用于固定的无连接信道0x0002,G帧格式如下:
PSM为(协议/服务复用器Protocol/Service Multiplexer)用于指定上层的传输类型,一般为SDP、RFCOMM、TCS等中介协议复用。小于0x1000的值,0x0001对应SDP,0x0003对应RFCOMM、0x0005对应TCS。CID为固定值:0x0002
抓包举例如下:
2) I/S帧用于重传、流控或者流模式下面向无连接的信道。I帧(Information frame)被用于L2CAP实体之间的信息传递;S帧被用于I帧的确认和请求重传。I/S帧格式如下:
Length为除了Basic L2CAP header外的数据长度。
需要指出的是:只有在服务数据包SDU需要分段,并且是第一个L2CAP包的时候才需要L2CAP SDU Length段。
Control字段与L2CAP模式有关,具体每种模式对应的control字段处理方式有a b c三种,如下所示:
3) LE帧,Channel I
D为接收方的CID。格式如下:(暂定为无连接信道,不确定)
3.1.3 信令信道
1) 控制帧(Control frame)在信令信道(传统蓝牙0x0001,BLE是0x0005)上传输。
在信令信道0x0001上可以多个控制命令同时包含于一个C帧中,但是0x0005信道上一个C帧只能够包含一个控制命令。C帧格式如下所示:
Code表示控制命令的固定编号,例如连接请求为0x02;
Identifier为请求方设置此标志,回应方回复请求帧的时候需要和请求帧的Identifier一致。
Length表示data的长度。
Data依据不同的命令而定的。
L2CAP信令指令码:
具体可参考以下例子进行分析:
L2CAP:
Role:Master
Address:11
PDULength: 6 //指令的长度,值为06 00
ChannelID: 0x0001 (Signaling)//L2CAP的信令通道,值为01 00
Code:Information request //信息请求,值为0a----对应信令指令码
Identifier:1//标识符,值为01
CommandLength: 2//命令长度,值为02 00
InfoType:Extended features supported//02 00
4. RFCOMM (串口仿真协议)
RFCOMM协议基于L2CAP协议的串行(9针RS-232)仿真。最新规范是V12,支持在两个蓝牙设备间高达60路的通信连接。
RFCOMM支持两种设备类型的存在:一是设备本身就是通信终端(如计算机,打印机) ,而是作为通信节点使用。
- Address
- Control字段
- Length 由最低位决定长度占位是1字节还是2字节,最低位为1时,长度为7bits(0~127),最低位为0时,长度为 5bits(0~32767)
- RFCOMM帧类型如下:
SABM | 异步平衡模式设置指令 |
UA | 未加编号的确认响应 |
DM | 断开连接模式响应 |
DISC | 断开连接指令 |
UIH | 带头校验的未编号信息命令和响应 |
- FCS校验
对于SABM,DISC,UA和DM帧,FCS计算Address,Control and Length字段用于接收方校验接收数据是否正确,校验原理采用循环冗余校验CRC-8
对于UIH帧,FCS计算Address and Control字段
具体帧的分析实例参考链接7---RFCOMM协议数据分析
5. SDP (服务发现协议)
SDP两种服务发现模式:
1)服务搜索:查询具有特定服务属性的服务;
2)服务浏览:简单的浏览全部可用服务。
PDU 格式:(协议数据单元)
PDU ID(1byte) | Transaction ID(2byte) | 参数长度(2byte) | 参数1 | …… | 参数N |
Header |
不同PDU ID实现SDP的不同功能,概述如下表格:
Value | Parameter Descirption | |
0x00 | Reserved | 保留 |
0x01 | SDP_ErrorResponse | 错误响应 |
0x02 | SDP_ServiceSearchRequest | 服务搜索请求 |
0x03 | SDP_ServiceSearchResponse | 服务搜索响应 |
0x04 | SDP_ServiceAttributeRequest | 服务属性请求 |
0x05 | SDP_ServiceAttributeResponse | 服务属性响应 |
0x06 | SDP_ServiceSearchAttributeRequest | 服务搜索属性请求 |
0x07 | SDP_ServiceSearchAttributeResponse | 服务搜索属性响应 |
0x08-0xff | Reserved | 保留 |
SDP的服务记录表对每一个服务进行描述,每条记录包含服务句柄(Handle)、一组服务属性(Attributes):
6. GAP(Generic Access Profile通用访问协议)
GAP 给设备定义了若干角色,其中主要的两个是:外围设备(Peripheral - 从机 - 服务端)和中心设备(Central - 主机 - 客户端)。
外围设备 - 从机:这一般就是非常小或者简单的低功耗设备,用来提供数据,并连接到一个更加相对强大的中心设备,例如小米手环;
中心设备 - 主机:中心设备相对比较强大,用来连接其他外围设备。例如手机等;
GAP 中外围设备通过两种方式向外广播数据:Advertising Data Payload(广播数据)和 Scan Response Data Payload(扫描回复):
每种数据最长可以包含 31 byte,广播数据是必需的,因为外设必需不停的向外广播,让中心设备知道它的存在;
扫描回复是可选的,中心设备可以向外设请求扫描回复,这里包含一些设备额外的信息,例如:设备的名字。
大部分情况下外设通过广播自己来让中心设备发现自己,并建立 GATT 连接,从而进行更多的数据交换;
也有些情况是不需要连接的,只要外设广播自己的数据即可,用这种方式主要目的是让外围设备,把自己的信息发送给多个中心设备。
1)定义GAP层的蓝牙设备角色(role)
和Link Layer的role类似,只不过GAP层的role更接近用户(可以等同于从用户的角度看到的蓝牙设备的role),包括:
Broadcaster Role,设备正在发送advertising events;
Observer Role,设备正在接收advertising events;
Peripheral Role,设备接受Link Layer连接(对应Link Layer的slave角色);
Central Role,设备发起Link Layer连接(对应Link Layer的master角色)。
2)定义GAP层的、用于实现各种通信的操作模式(Operational Mode)和过程(Procedures),包括:
Broadcast mode and observation procedure,实现单向的、无连接的通信方式;
Discovery modes and procedures,实现蓝牙设备的发现操作;
Connection modes and procedures,实现蓝牙设备的连接操作;
Bonding modes and procedures,实现蓝牙设备的配对操作。
3)定义User Interface有关的蓝牙参数,包括:
蓝牙地址(Bluetooth Device Address);
蓝牙名称(Bluetooth Device Name);
蓝牙的pincode(Bluetooth Passkey);
7. ATT (属性协议)
服务项包含一个或多个特征值,特征值包含一个或多个描述符,多个服务项组织在一起,构成属性规范ATT。
ATT协议将“信息”以“Attribute(属性)”的形式抽象出来,并允许client和server通过Attribute的形式共享信息,提供一些方法,供远端设备(remote device)读取、修改这些属性的值(Attribute value)。
Attribute Protocol的主要思路包括:
1)基于L2CAP,使用固定的Channel ID(0x0004)。
2)采用client-server的形式。提供信息(以后都称作Attribute)的一方称作ATT server(一般是那些传感器节点),访问信息的一方称作ATT client。
3)一个Attribute由Attribute Type、Attribute Handle和Attribute Value组成。
Attribute Type用于标示Attribute的类型,类似于我们常说的“温度”、“湿度”等,不同的是,Attribute Type使用UUID(Universally Unique IDentifier,16-bit、32-bit或者128-bit的数值)区分。
Attribute由4个字段表示:类型,句柄,权限,值
属性类型:由一个128bits的UUID表示 --------》用来搜索属性
句柄:唯一的无符号数(16bits) ---------》用来识别属性
权限:决定客户端是否可以读取和修改资源
属性值:可以是定长也可以是变长
方法有6种:对应6种Protocol Data Units(PDU 协议数据单元) ---具体参考链接9
Commands:由客户端发给服务端,并不作响应
Requests :由客户端发给服务端,并作响应
Responses:收到Requests(请求)后,服务的将响应发给客户端
Notifications :服务器主动发送通知给客户端,没响应
Indications :服务器发送指示给客户端,有响应
Confirmations :客户端发送给服务器以作为对指示(Indications)的确认
(客户端:一般指手机。服务端:指存储各种数据的设备)
ATT协议本身没有定义任何UUID。这部分工作留给了GATT和上层协议。
和属性相关的还有读写权限。读写权限存在属性值里,由高层协议确定。ATT本身不会关心,也不会试图解释属性值来确定权限。这部分工作也留给了GATT和上层协议。
ATT有一些良好的特征,比如通过UUID来搜索属性,通过handle区间范围来获取所有区间内的属性,因此client不需要提前获得handle的值,也不需要高层协议硬编码这些值。
8. GATT (Generic Attribute Protocol 通用属性协议)
用于提供通用的、信息的存储和共享等功能,基于 GATT 连接的方式的,只能是一个外设连接一个中心设备。
服务:服务可以由一个或多个特征,服务使用UUID与其他服务区别开来,对于通用的服务使用16bits的UUID,对于自定义服务则使用128bits的服务。
特征:每个特征包含特征属性,特征值,描述符
特征属性(上图中的properties)由以下属性组成
属性类型为:“特征“
属性值由3个位域组成:特征UUID(2/16字节),特征属性(1字节),特征句柄(2字节)
属性权限必须是可读的,并且不需要身份验证或授权
特征属性位域显示了如何使用特征值或其描述符可以访问。它可以是广播,读取,无响应写入,写入,通知,指示,已认证签名写入或扩展属性
特征值(上图中的value)
属性类型与特性声明中的UUID相同。
属性值是特征值。
属性权限是特定于实现的
描述符:特征描述符是可选的,用于提供有关特征的附加信息
GATT service的基础是UUID值为0x2800的属性。所有跟在这个属性后面的属性都属于这个属性定义的服务,直到另一个0x2800属性出现。
每个属性定义事实上包含了两个UUID,0x2800或者0x2801作为属性UUID,另外一个属性值里面存储的UUID。后面这个UUID是服务ID。这是GATT/ATT分层方式导致的后果。 UUID0x2800被GATT用来寻找服务定义边界。一旦找到了边界,属性值,也就是第二个UUID用来指定服务。这样client能够找到所有的服务而不需要知道服务的具体定义。
GATT中所有的服务细节通过ATT来描述,所以不需要像BR/EDR那样设置专门的服务发现协议。