关键词:蓝牙核心技术协议 HCI L2CAP SDP RFCOMM
作者:xubin341719(欢迎转载,请注明作者,请尊重版权,谢谢!)欢迎指正错误,共同学习、共同进步!!下载链接:Bluetooth PROFILE SPECIFICATIONS (基本涵盖所有蓝牙协议)、buletooth core 2.1-4.0 SPECIFICATION(三蓝牙版本的核心协议v2.1/v3.0/v4.0)、蓝牙核心技术与应用 马建仓 版(蓝牙协议相关初学者必读,开发者参考)
蓝牙核心技术概述(一):蓝牙概述蓝牙核心技术概述(二):蓝牙使用场景蓝牙核心技术概述(三): 蓝牙协议规范(射频、基带链路控制、链路管理)蓝牙核心技术概述(四):蓝牙协议规范(HCI、L2CAP、SDP、RFOCMM)蓝牙核心技术概述(五):蓝牙协议规范(irOBEX、BNEP、AVDTP、AVCTP)
一、主机控制接口协议  HCI蓝牙主机-主机控模型
蓝牙软件协议栈堆的数据传输过程:
1、蓝牙控制器接口数据分组:指令分组、事件分组、数据分组(1)、指令分组

如:Accpet Connection RequestOpcode为:0x0409参数长度为: 07 参数中蓝牙地址为:00:0d:fd:5f:16:9f角色为:从设备  0x01大端数据模式指令为:09 04 07 9f 16 5f fd 0d 00 01(2)、事件分组

如上图:Opcode :0x0409状态: 0x00总长度: 4字节命令状态:0x0f(3)、数据分组ACL 数据分组
连接句柄(12bit)  | PB(2bit)  | BC(2bit)  | 数据长度(16bit)  | 
数据…………  | |||
注:PB Packet_Boundary BC Broadcast FlagSCO 数据分组
连接句柄(12bit)  | 保留(4bit)  | 数据长度(16bit)  | 
数据…………  | ||
(4)、RS232分组指示器:
HCI 分组类型  | RS232分组指示器  | 
HCI指令分组  | 0x01  | 
HCI ACL数据分组  | 0x02  | 
HCI SCO数据分组  | 0x03  | 
HCI事件分组  | 0x04  | 
HCI错误消息分组  | 0x05  | 
HCI协商分组  | 0x06  | 
2、HCI控制命令
(1)、链路控制指令
命令  | OCF  | 概述  | 
Inquiry  | 0x0001  | 蓝牙设备进入查询模式,搜索临近设备  | 
Inquiry Cancel  | 0x0002  | 退出查询模式  | 
Periodic Inquiry Mode  | 0x0003  | 蓝牙设备在指定周期内自动查询  | 
Exit Periodic Inquiry Mode  | 0x0004  | 退出自动查询模式  | 
Create Connection  | 0x0005  | 按指定蓝牙设备的BD_ADDR创建ACL链路  | 
Disconnect  | 0x0006  | 终止现有连接  | 
Add SCO Connection  | 0x0007  | 利用连接句柄参数指定的ACL连接创建SCO  | 
Cancel Create Connection  | 0x0008  | 
  | 
Accept Connection Request  | 0x0009  | 接收新的呼入连接请求  | 
Reject Connection Request  | 0x000A  | 拒绝新的呼入连接请求  | 
Link Key Request Reply  | 0x000B  | 应答从主机控制器发出的链路密钥请求事件,并指定存储在主机上的链路密钥做为与BD_ADDR指定的蓝牙设备进行连接使用的链路密钥请求事件  | 
Link Key Request Negative Reply  | 0x000C  | 如果主机上没有存储链路密钥,作为与BD_ADDR指定的蓝牙设备进行连接使用的链路密钥,就应答从主机控制器发出的链路密钥请求事件  | 
PIN Code Request Reply  | 0x000D  | 应答从主机控制器发出的PIN请求事件,并指定用于连接的PIN  | 
PIN Code Request Negative Reply  | 0x000E  | 当主机不能指定连接的PIN时,应回答从机控制器发出的PIN请求事件  | 
Change Connection Packet Type  | 0x000F  | 改变正在建立连接的分组类型  | 
Authentication Request  | 0x0011  | 指定连接句柄关联的两个蓝牙设备之间建立身份鉴权  | 
Set Connection Encryption  | 0x0013  | 建立取消连接加密  | 
Change Connection Link Key  | 0x0015  | 强制关联了连接句柄的两个设备建立连接,并生成一个新的链路密钥  | 
Master Link Key  | 0x0017  | 强制关联了连接句柄的两个设备利用主设备时链路密钥或常规密钥  | 
Remote Name Request  | 0x0019  | 获取远端设备的名称  | 
Cancel Remote Name Request  | 
  | 
  | 
Read Remote Supported Features  | 0x001B  | 请求远端设备所支持的特性列表  | 
Read Remote Extended Features  | 
  | 
  | 
Read Remote Version Information  | 0x001D  | 从远端设备读取版本信息  | 
Read Clock Offset  | 0x001F  | 读取远端的时钟信息  | 
(2)、链路策略指令
命令  | OCF  | 简介  | 
Hold Mode  | 0x0001  | 改变LM状态和本地及远程设备为主模式的LM位置  | 
Sniff Mode  | 0x0003  | 改变LM状态和本地及远程设备为呼吸模式的LM位置  | 
Exit Sniff Mode  | 0x0004  | 结束连接句柄在当前呼吸模式里的呼吸模式  | 
Park State  | 0x0005  | 改变LM状态和本地及远程设备为休眠模式的LM位置  | 
Exit Park State  | 0x0006  | 切换从休眠模式返回到激活模式的蓝牙设备  | 
QoS Setup  | 0x0007  | 指出连接句柄的服务质量参数  | 
Role Discovery  | 0x0009  | 蓝牙设备连接后确定自己的主从角色  | 
Switch Role  | 0x000B  | 角色互换  | 
Read Link Policy Settings  | 0x000C  | 为指定连接句柄读链路策略设置。链路策略设置允许主机控制器指定用于连接句柄的LM连接模式  | 
Write Link Policy Settings  | 0x000D  | 为指定连接句柄写链路策略设置。链路策略设置允许主机控制器指定用于连接句柄的LM连接模式  | 
Read Default Link Policy Settings  | 0x000E  | 
  | 
Write Default Link Policy Settings  | 0x000F  | 
  | 
Flow Specification  | 0X0010  | 
  | 
(3)、主机控制器与基带指令
Set Event Mark  | 0x0001  | 使能主机过滤HCI产生的事件  | 
Reset  | 0x0003  | 复位蓝牙控制器、链路管理器、基带链路管理器  | 
Set Event Filter  | 0x0005  | 使能主机指定不同事件过滤  | 
Flush  | 0x0008  | 针对指定的蓝牙句柄,放弃所有作为当前待传输数据,甚至当前是属于多个在主机控制器里的L2CAP指令的数据块  | 
Read PIN Type  | 0x0009  | 主机读取指定主机的PIN类型是可变的还是固定的  | 
Write PIN Type  | 0x000A  | 主机写入指定主机的PIN类型是可变的还是固定的  | 
Create New Unit Key  | 0x000B  | 创建新的单一密钥  | 
Read Stored Link Key  | 0x000D  | 读取存放在蓝牙控制器中的单个或者多个密钥  | 
Write Stored Link Key  | 0x0011  | 写入存放在蓝牙控制器中的单个或者多个密钥  | 
Delete Stored Link Key  | 0x0012  | 删除存放在蓝牙控制器中的单个或者多个密钥  | 
Write Local Name  | 0x0013  | 修改蓝牙设备名称  | 
Read Local Name  | 0x0014  | 读取蓝牙设备名称  | 
Read Connection Accept Timeout  | 0x0015  | 读连接识别超时参数值,定时器终止后蓝牙硬件自动拒绝连接  | 
Write Connection Accept Timeout  | 0x0016  | 写连接识别超时参数值,定时器终止后蓝牙硬件自动拒绝连接  | 
Read Page Timeout  | 0x0017  | 读寻呼超时参数值,本地设备返回连接失败前,该值是允许蓝牙硬件定义等待远程设备连接申请时间  | 
Write Page Timeout  | 0x0018  | 写寻呼超时参数值,本地设备返回连接失败前,该值是允许蓝牙硬件定义等待远程设备连接申请时间  | 
Read Scan Enable  | 0x0019  | 写出扫描允许参数值---用来控制蓝牙设备周期性查询  | 
Write Scan Enable  | 0x001A  | 读出扫描允许参数值---用来控制蓝牙设备周期性查询  | 
Read Page Scan Activity  | 0x001B  | 读寻呼扫描间隔、寻呼扫描区间参数  | 
Write Page Scan Activity  | 0x001C  | 写寻呼扫描间隔、寻呼扫描区间参数  | 
Read Inquiry Scan Activity  | 0x001D  | 读查询扫描间隔、查询扫描区间参数  | 
Write Inquiry Scan Activity  | 0x001E  | 写查询扫描间隔、查询扫描区间参数  | 
Read Authentication Enable  | 0x001F  | 读取鉴权允许参数---控制蓝牙设备是否对每个连接进行鉴权  | 
Write Authentication Enable  | 0x0020  | 写取鉴权允许参数---控制蓝牙设备是否对每个连接进行鉴权  | 
Read Encryption Mode  | 0x0021  | 读加密模式数值---控制蓝牙设备是否对每个连接进行加密  | 
Write Encryption Mode  | 0x0022  | 写加密模式数值---控制蓝牙设备是否对每个连接进行加密  | 
Read Class Of Device  | 0x0023  | 读取设备类型参数值,用于区别设备能力  | 
Write Class Of Device  | 0x0024  | 写设备类型参数值,用于区别设备能力  | 
Read Voice Setting  | 0x0025  | 读取语音设置参数值,控制语音连接的各种设置  | 
Write Voice Setting  | 0x0026  | 写语音设置参数值,控制语音连接的各种设置  | 
Read Automatic Flush Timeout  | 0x0027  | 对指定句柄,读取刷新超时值  | 
Write Automatic Flush Timeout  | 0x0028  | 对指定句柄,写入刷新超时值  | 
Read Num Broadcast Retransmissions  | 0x0029  | 读取设备的广播重复发送次数,重复发送提高广播消息的可靠性  | 
Write Num Broadcast Retransmissions  | 0x002A  | 写入设备的广播重复发送次数,重复发送提高广播消息的可靠性  | 
Read Hold Mode Activity  | 0x002B  | 读取Hold Mode Activity的参数值,用来确定Hold挂起的时间  | 
Write Hold Mode Activity  | 0x002C  | 写入Hold Mode Activity的参数值,用来确定Hold挂起的时间  | 
Read Transmit Power Level  | 0x002D  | 对指定句柄,读取传输功率的参数值  | 
Read Synchronous Flow Control Enable  | 0x002E  | 读取SCO流量控制设置。通过使用该设置,主机控制器决定是否主机控制器发送与SCO连接句柄相关的完成分组事件的数量  | 
Write Synchronous Flow Control Enable  | 0x002F  | 读写入SCO流量控制设置。通过使用该设置,主机控制器决定是否主机控制器发送与SCO连接句柄相关的完成分组事件的数量  | 
Set Host Controller To Host Flow Control  | 0x0031  | 主机控制器的打开、关闭,主机控制器到主机的流量控制  | 
Host Buffer Size  | 0x0033  | 主机通知主机控制器自己的ACL、SCO数据缓冲区大小。主机控制器分段传输数据,而数据不会超出这个范围  | 
Host Number Of Completed Packets  | 0x0035  | 当主机对于任何连接的句柄准备接受较多的HCI指令时,该指令用于通过主机指出主机控制器  | 
Read Link Supervision Timeout  | 0x0036  | 读取连接管理超时参数。主从蓝牙设备用该参数监视链路丢失情况  | 
Write Link Supervision Timeout  | 0x0037  | 写入连接管理超时参数。主从蓝牙设备用该参数监视链路丢失情况  | 
Read Number of Supported IAC  | 0x0038  | 读取查询扫描期间本地蓝牙扫描的查询识别码(ICA)的数值  | 
Read Current IAC LAP  | 0x0039  | 读取创建在查询扫描期间本地蓝牙设备正同时扫描的蓝牙识别码的LAP  | 
Write Current IAC LAP  | 0x003A  | 写入创建在查询扫描期间本地蓝牙设备正同时扫描的蓝牙识别码的LAP  | 
Read Page Scan Period Mode  | 0x003B  | 读取本地蓝牙设备的强制寻呼扫描区间模式  | 
Write Page Scan Period Mode  | 0x003C  | 写入本地蓝牙设备的强制寻呼扫描区间模式  | 
Read Page Scan Mode  | 0x003D  | 读取本地蓝牙设备的默认寻呼扫描区间模式  | 
Write Page Scan Mode  | 0x003E  | 写入本地蓝牙设备的默认寻呼扫描区间模式  | 
(4)、信息指令参数
Read Local Version Information  | 0x0001  | 读取本地蓝牙版本信息  | 
Read Local Supported Features  | 0x0003  | 读取本地蓝牙设备特征表  | 
Read Local Extended Features  | 0x0004  | 
  | 
Read Buffer Size  | 0x0005  | 返回HCI缓冲容量。缓冲容量用于传输缓冲数据  | 
Read Country Code [Deprecated]  | 0x0007  | 读取国家代码状态参数值  | 
Read BD ADDR  | 0x0009  | 读取BD_ADDR的参数值  | 
(5)、状态指令参数
Read Failed Contact Count  | 0x0001  | 读取对于其他设备特殊连接的Failed Contact Count参数值。Failed Contact Count记录在刷新时终止及当前正在传输的L2CAP数据指令被自动刷新后,主单元或从单元不能连续响应事件次数  | 
Reset Failed Contact Count  | 0x0002  | 复位时对于其他设备的连接的Failed Contact Count的参数值。Failed Contact Count记录在刷新时终止及当前正在传输的L2CAP数据指令被自动刷新后,主单元或从单元不能连续响应事件次数  | 
Get Link Quality  | 0x0003  | 读取指定连接句柄的Link Quality的值  | 
Read rssI  | 0x0005  | 读取对于其他蓝牙设备连接句柄的接收信号强度指示  | 
Read AFH Channel Map  | 0x0007  | 
  | 
Read BD Clock  | 0x0009  | 
  | 
(6)、测试指令
Read Loopback Mode  | 0x0001  | 读取主机端控制器会送模式的设置值。回送模式设置可以确定信息发送路径  | 
Write Loopback Mode  | 0x0002  | 写入主机控制器会送模式的设置值。回送模式设置可以确定信息发送路径  | 
Enable Device Under Test Mode  | 0x0003  | 允许本地蓝牙设备模块通过LMP测试指令接入测试模式。当主机要求本地设备作为待测试设备,实现蓝牙测试模式文件中规定测试场景,则发送该指令  | 
(7)、错误代码
错误代码  | 错误含义  | 错误代码  | 错误含义  | 
0x01  | 位置HCI指令  | 0x14  | 由于另一端引起连接中断:资源限制  | 
0x02  | 不能连接  | 0x15  | 由于另一端引起连接中断:关机  | 
0x03  | 硬件故障  | 0x16  | 本机中断连接  | 
0x04  | 寻呼超时  | 0x17  | 重复尝试  | 
0x05  | 身份验证失败  | 0x18  | 不允许匹配  | 
0x06  | 键丢失  | 0x19  | 未知LMP PDU  | 
0x07  | 存储器已满  | 0x1A  | 不支持远端特性  | 
0x08  | 连接超时  | 0x1B  | 拒绝SCO补偿  | 
0x09  | 最大连接数  | 0x1C  | 拒绝SCO间歇模式  | 
0x0A  | 连接到设备A的最大SCO连接数  | 0x1D  | 拒绝SCO无线模式  | 
0x0B  | ACL连接已存在  | 0x1E  | 非法链路管理参数  | 
0x0C  | 指令非法  | 0x1F  | 未特别指明错误  | 
0x0D  | 由于资源有限,主机被拒绝  | 0x20  | 不支持链路管理器协议参数  | 
0x0E  | 由于安全原因,主机被拒绝  | 0x21  | 不允许角色改变  | 
0x0F  | 由于远端设备单连接设备,主机拒绝  | 0x22  | 链路管理响应超时  | 
0x10  | 主机超时  | 0x23  | 链路管理错误处理事务冲突  | 
0x11  | 不支持特性或参数值  | 0x24  | 不允许LMP PDU  | 
0x12  | 非法主机控制接口指令  | 0x25~0xFF  | 保留  | 
0x13  | 由于另一端引起连接中断:用户中断连接  | 
  | 
  | 
二、逻辑链路控制与适配协议  L2CAPL2CAP位于基带之上,将基带的数据分组转换为便于高层应用的数据分组格式,并提供协议复用和服务质量交换等功能。L2CAP只支持ACL数据传输,不支持SCO数据。L2CAP本身不提供加强信道可靠性和保证数据完整性的机制,其信道的可靠性依靠基带提供。
1、协议复用:底层传输协议没有提供对高层协议的复用机制,因而L2CAP支持高层协议复用,L2CAP层可以区分其上的SDP、RFCOMM、TCS等。
2、分段重组:L2CAP层帮助实现基带的短PDU和高层的长PDU相互传输,L2CAP本身不完成任何PDU的分段重组,具体的分段重组有低层和高层来完成。
3、服务质量 Qualityof Serivce 信息的交换:蓝牙建立连接的过程中,L2CAP允许交互蓝牙所期望的服务质量,建立完成后,通过监视资源的使用情况,来保证服务质量。
4、组抽象:L2CAP忽略地址组概念,他只关心数据。
L2CAP信道有三种类型:
A、面向连接信道:Connection-OrientedCO,用于两个设备之间的数据通信。
B、无连接信道:Connection-LessCL,用来向一组设备广播方式传输数据。CID为固定值:0x0002。
C、信令信道:Signaling,用于创建CO通道,可以通过协商改变CO信道的特性。
CL信道的L2CAP_PDU
长度(2bytes)  | 信道ID(0x0002)  | PSM(最小为2bytes)  | 有效载荷  | 
PSM为 协议/服务复用器Protocol/Service Multiplexer,一般为SDP、RFCOMM、TCS等中介协议复用。小于0x1000的值,0x0001对应SDP,0x0003对应RFCOMM、0x0005对应TCS。(1)、蓝牙逻辑链路控制与适配协议信令:L2CAP的信令通道的CID为0x0001
信令指令分组:
长度(2byte)  | CID(0x0001)  | 指令1  | 指令2  | ……………  | 指令n  | 
L2CAP 分组头部分  | 
  | ||||
信令指令格式:
代码(1byte)  | 标识符(1byte)  | 长度(2byte)  | 数据  | 
信令指令头  | |||

如上图所示,一条L2CAP信令,1为L2CAP分组头,2为信令指令头,3为数据部分。
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
所以这条指令完整的为:
06 00 01 00 0a 01 02 00 02 00
信令的其他操作如下:

L2CAP信令指令码:
Code  | Description  | 
  | 
0x00  | RESERVED  | 保留  | 
0x01  | Command reject  | 拒绝命令  | 
0x02  | Connection request  | 连接请求  | 
0x03  | Connection response  | 连接响应  | 
0x04  | Configure request  | 配置请求  | 
0x05  | Configure response  | 配置响应  | 
0x06  | Disconnection request  | 断开请求  | 
0x07  | Disconnection response  | 断开响应  | 
0x08  | Echo request  | 
  | 
0x09  | Echo response  | 
  | 
0x0A  | Information request  | 信息请求  | 
0x0B  | Information response  | 信息响应  | 
1)、连接请求Connection_Request Code=0x02
代码(0x02)  | 标识符(1字节)  | 长度(2字节)  | PSM(2字节)  | 源CID(2字节)  | 
例如:SDP 连接请求
如上红框所示:
代码(0x02)  | 标识符(1字节)  | 长度(2字节)  | PSM(2字节)  | 源CID(2字节)  | 
0x02  | 3  | 4  | SDP  | 0x0040  | 
2)、连接相应Connection_Response Code=0x03
代码(0x03)  | 标识符  | 长度  | 目标CID  | 源CID  | 结果  | 状态  | 
例如:SDP请求响应
如上面红框所示:
代码(0x03)  | 标识符  | 长度  | 目标CID  | 源CID  | 结果  | 状态  | 
0x03  | 3  | 8  | 0x0040  | 0x0040  | 0x0000  | 
  | 
(2)、MTU MAXIMUMTRANSMISSION UNIT最大传输单元
MTU最大传输单元,L2CAP应用必须支持最小为48字节的MTU,默认值为672
(3)、QoS 服务质量
三、服务发现协议 SDP
SDP两种服务发现模式:1)、服务搜索:查询具有特定服务属性的服务;2)、服务浏览:简单的浏览全部可用服务。(1)、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  | 保留  | 
(2)、服务记录表SDP的服务记录表对每一个服务进行描述,每条记录包含服务句柄、一组服务属性:

Service Record Attributes:服务记录;Service Record Handle 服务句柄;Attribute 服务属性;

四、串口仿真协议 RFCOMM
为建立在串口之上的传统应用提供环境接口,使他们可以做比较少协议改动就可以在蓝牙无线通信无线链路上工作。多路串口仿真是RFCOMM的重要功能,通过多路复用器(multiplexer),一条L2CAP链路可以同时 多个串行应用。两台设备间的串口仿真:
RFCOMM 两个蓝牙设备之间可以支持多达60多路仿真串口。
RFCOMM帧类型如下:
SABM  | 异步平衡模式设置指令  | 
UA  | 未加编号的确认响应  | 
DM  | 断开连接模式响应  | 
DISC  | 断开连接指令  | 
UIH  | 带头校验的未编号信息命令和响应  | 

新闻热点
疑难解答