惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
T
The Blog of Author Tim Ferriss
博客园 - 叶小钗
N
Netflix TechBlog - Medium
腾讯CDC
C
Check Point Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
S
SegmentFault 最新的问题
F
Fortinet All Blogs
美团技术团队
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
F
Full Disclosure
Recorded Future
Recorded Future
D
DataBreaches.Net
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
J
Java Code Geeks
I
InfoQ
Y
Y Combinator Blog
A
About on SuperTechFans
AI
AI
爱范儿
爱范儿
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Forbes - Security
Forbes - Security
W
WeLiveSecurity
M
MIT News - Artificial intelligence
雷峰网
雷峰网
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Schneier on Security
Schneier on Security
The GitHub Blog
The GitHub Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Docker
Recent Commits to openclaw:main
Recent Commits to openclaw:main
量子位
V2EX - 技术
V2EX - 技术
Project Zero
Project Zero

博客园 - SeanLin

Cocos2d-html5资源预加载列表自动扫描脚本 JSDoc参考注释模板 [转]Git常用操作命令 Cocos2d-html5 HelloWorld模板和引擎使用简介 Javascript API Document生成工具JSDoc HTML5游戏开发涉及到的安全问题 Javascript开发的HTML5游戏的知识产权保护 CCTextureCache的多线程加载原理和使用 引擎demo任务 引擎初始化过程 引擎开发数据记录 游戏引擎消息循环机制 渲染部分 几个需要思考的问题 【转】使用Jasob混淆javascript代码 【转】html5游戏开发引擎大全 【转】V8 Javascript 引擎设计理念 android 字体位置信息 【转】蓝牙协议的命令和事件
【转】蓝牙协议中HCI层的研究与开发
SeanLin · 2011-07-18 · via 博客园 - SeanLin


刘向阳,沈连丰

(东南大学移动通信国家重点实验室, 南京 210096)

一、HCI在蓝牙软件协议模型位置的分析

蓝牙系统的协议模型如图1所示。从图中可以看出,HCI是位于蓝牙系统的L2CAP(逻辑链路控制与适配协议)层和LMP(链路管理协议)层之间的一层协议。HCI为上层协议提供了进入LM的统一接口和进入基带的统一方式。在HCI的主机(Host)和HCI主机控制器(Host Controller)之间会存在若干传输层,这些传输层是透明的,只需完成传输数据的任务,不必清楚数据的具体格式。目前,蓝牙的SIG规定了四种与硬件连接的物理总线方式:USB、RS232、UART和PC卡。其中通过RS232串口线方式进行连接具有差错校验。

HCI层的底层层协议如图2所示。由图可看出,HCI层屏蔽了基带,为协议层的上层提供了进入基带的统一方式。

二、HCI与基带通信方式的研究与分析

蓝牙系统的底层协议通信如图3所示。下面结合图3对蓝牙系统中HCI层与基带间的通信作一些分析研究。

1.通信方式的分析

HCI是通过包的方式来传送数据、命令和事件的,所有在主机和主机控制器之间的通信都以包的形式进行。包括每个命令的返回参数都通过特定的事件包来传输。HCI有数据、命令和事件三种包,其中数据包是双向的,命令包只能从主机发往主机控制器,而事件包始终是主机控制器发向主机的。主机发出的大多数命令包都会触发主机控制器产生相应的事件包作为响应。
命令包分为六种类型:


* 链路控制命令;
* 链路政策和模式命令;
* 主机控制和基带命令;
* 信息命令;
* 状态命令;
* 测试命令。

事件包也可分为三种类型:
* 通用事件,包括命令完成包(Command Complete)和命令状态包(Command Status);
* 测试事件;
* 出错时发生的事件,如产生丢失(Flush Occured)和数据缓冲区溢出(Data Buffer Overflow)。
数据包则可分为ACL和SCO的数据包。包的格式如图4所示。

2.包的参数分析研究
命令包:命令包中的OCF(Opcode Command Field)和OGF(Opcode Group Field)是用于区分命令种的。Parameter Length表示所带参数的长度,以字节数为单位,随后就是所带的参数列表。下面以Inquiry命令为例对HCI的命令包做具体说明。

在Inquiry命令中,OGF=0x01表示此命令属于链路控制命令,同时OCF=0x0001则表示此命令为链路控制命令中的Inquiry命令。OCF与OGF共占2字节,又由于底位字节在前,则它们在命令包为0x0104。在Inquiry 命令中,参数Parameter Length为5。Inquiry命令带3个参数,第一个参数为LAP(low address part), 它将用来产生Baseband中查询命令包的包头中的Access Code。第二个参数为Inquiry_Length,它时表示在Inquiry命令停止前所定义的最大时间,超过此时间,Inquiry命令将终止。第三个参数为NUM_Response,它的值为0X00表示设备响应数不受限制,只为0x00-0xff则表示在Inquiry命令终止前最大的设备响应数。因此,若LAP=0x9e8b00,Inquiry_Length=0x05,NUM_Response=0x05,则协议上层调用Inquiry命令是HCI向基带发的明令包将为:0x01 04 05 00 8b 9e 05 05。

事件包:事件包的Event Code用来区分不同的事件包,Parameter Length表示所带参数的长度,以字节数为单位,随后就是所带的参数列表。以Command Status Event事件包为例对HCI的事件包进行具体说明。

当主机控制器收到主机发来的如上面所提到的Inquiry命令包并开始处理时,它就会向主机发送Command Status Event事件包,此事件包为:0x0f 04 00 0a 01 04。0xOf表示此事件包为Command Status Event事件包,0x04表示此事件包带4字节长度的参数,0x00为此事件包的第一个参数即Status,表示命令包正在处理。0x0a为事件包的第二个参数NUM_HCI_Command_Packets,表示主机最多可在向主机控制器发10个命令包。0x01 04 为第三个参数Command_Opcode, 表示此事件包是对Inquiry命令包的响应。

数据包:ACL和SCO数据包中的Connection Handle即连接句柄是一个12比特的标志符,用于唯一确认两台蓝牙设备间的数据或语音连接,可以看作是两台蓝牙设备间唯一的数据通道的标识。两台设备间只能有一条ACL连接,也就是只有一个ACL的连接句柄,相应L2CAP的信道都是建立在这个连接句柄表示的数据通道上;两台设备间可以有多个SCO的连接,则一对设备间会有多个SCO的连接句柄。连接句柄在两设备连接期间一直存在,不管设备处于什么状态。在ACL数据包中,Flags分为PB Flag和BC Flag,PB Flag为包的界限标志,PB Flag=0x00表示此数据包为上层协议包(如L2CAP包)的起始部分;PB Flag=0x01表示此数据包为上层协议包(如L2CAP包)的后续部分。BC Flag为广播发送的标志,BC Flag=0x00表示无广播发送,只是点对点的发送;BC Flag=0x01表示对所有处于激活状态的从设备进行广播发送,BC Flag=0x02表示对所有的从设备包括处于休眠状态的从设备进行广播发送。ACL和SCO数据包中的Data Total Length 都表示所载荷的数据的长度,以字节位单位。

3.通信过程的研究与分析

当主机与基带之间用命令的方式进行通信时,主机向主机控制器发送命令包。主机控制器完成一个命令,大多数情况下,它会向主机发出一个命令完成事件包(Command Complete Packet),包中携带命令完成的信息。有些命令不会收到命令完成事件,而会收到命令状态事件包(Command Status Packet),当收到该事件则表示主机发出的命令已经被主机控制器接收并开始处理,过一段时间该命令被执行完毕时,主机控制器会向主机发出相应的事件包来通知主机。如果命令参数有误,则会在命令状态事件中给出相应错误码。假如错误出现在一个返回Command Complete事件包的命令中,则此Command Complete事件包不一定含有此命令所定义的所有参数。状态参数作为解释错误原因同时也是第一个返回的参数,总是要返回的。假如紧随状态参数之后是连接句柄或蓝牙的设备地址,则此参数也总是要返回,这样可判别出此Command Complete事件包属于那个实例的一个命令。在这种情况下,事件包中连接句柄或蓝牙的设备地址应与命令包种的相应参数一致。假如错误出现在一个不返回Command Complete事件包的命令中,则事件包包含的所有参数都不一定是有效的。主机必须根据于此命令相联系的事件包中的状态参数来决定它们的有效性。

4.HCI流量控制(Flow Control)的分析研究

HCI的流量控制是为了管理主机和主机控制器中有限的资源并控制数据流量而设计的,由主机管理主机控制器的数据缓存区,主机可动态地调整每个连接句柄的流量。
对于命令包的流量控制,主机在每发一个命令之前都要确定当前能发命令包的数目,当然,在开机和重启动时发命令包可以不用考虑接收情况,直到收到命令完成事件包或命令状态事件包为止。因为在每个命令完成事件包和命令状态事件包中都有Num_HCI_Command_ Packets选项表明当时主机能向主机控制器发送的命令包的数目,而对于每个命令必然会有相应的命令完成事件包和命令状态事件包,主机就能控制命令包不会溢出。

对于数据包的流量控制,一开始,主机调用Read_Buffer_Size命令,该命令返回的两个参数决定了主机能发往主机控制器的ACL和SCO两种数据包的大小的最大值,同时两个附加参数则说明了主机控制器能接收的ACL和SCO数据包总的数目。而每隔一段时间,主机控制器会向主机发Number_Of_Complete_Packets事件,该事件的参数值表明了对每个连接句柄已经处理的数据包的数目(包括正确传输和被丢弃的)。主机根据一开始就知道的总数,减去已经处理的包的数目,则可计算出还能发多少数据包,从而控制数据包的流量。

如有必要,HCI的流量控制也可由主机控制器来实现对主机的控制,可以通过Set_Host_ Controller_To_Host_Flow_Control命令来设置,其控制过程基本与主机控制过程类似,只是命令稍有不同。当主机收到断链确认的事件后,就认为所有传往主机控制器的数据包已经全部被丢弃了,同时主机控制器中的数据缓冲区也被释放了。

三、HCI协议层软件开发

我们在对HCI层进行全面的分析研究之后,提出了HCI协议层软件开发的方案,定出了HCI层提供给协议上层的接口。这些接口给蓝牙协议栈的上层提供了进入BaseBand的统一入口。整个接口按协议站的要求分为八大部分。下面介绍每部分的接口。整个软件层采用传递消息加函数调用相结合的机制来实现,即上层对HCI层接口的调用采用函数调用的机制,HCI对上层的通信采用传递消息的方式。

1.接口分类及举例说明

(1)开始命令

此命令接口是主机向HCI注册及并启动HCI。
如启动HCI的函数接口为HCI_ReqStart(),HCI在启动后发向上层的消息接口为HCI_START_CNF()。命令执行过程如图5所示。

(2)链路控制命令

链路控制命令是允许主机控制器控制与其他蓝牙设备的连接。在链路控制命令运行时, LM 控制蓝牙微微网与分布网的建立与维持。这些命令指示LM创建及修改与远端蓝牙设备的连接链路,查询范围内的其他蓝牙设备,及其他链路管理协议命令。

以查找并发现周围设备为例,HCI层为上层提供了函数接口HCI_ReqInquiry,消息接口为HCI_INQUIRY_RESULT_EVT和HCI_INQUIRY_CNF。命令执行过程如图6所示。

主机首先调用HCI的HCI_ReqInquiry函数开始查询过程,在此过程中,如有蓝牙响应此查询,则会产生一HCI_INQUIRY_RESULT_EVT事件通知主机。在此次查询过程结束时,会产生HCI_INQUIRY_CNF这条消息通知主机,参数NrofResponse表示在此次查询过程所响应的蓝牙设备数。 

(3)链路政策命令

链路政策命令提供了一种影响LM怎样管理微微网的方法。当链路政策命令运行时,LM仍然以可调整的参数控制微微网及分布网的建立和维持。这些链路政策命令调整LM的行为,从尔导致与远端蓝牙设备的链路层连接的改变。

已建立服务质量为例,HCI层为上层提供了函数接口HCI_ReqQoSSetup,消息接口为HCI_QOS_SETUP_EVT和HCI_QOS_SETUP_CNF,HCI_QOS_SETUP_CNF_NEG。命令执行过程如图7所示。

主机首先调用HCI_ReqQosSetup请求建立Qos。当Qos建立成HCI_QOS_SETUP_CNF 消息被送往发起端,同时一个事件消息送往远端设备。当Qos建立失败时,HCI_QOS_SETUP_CNF_NEG被送往发起端。

(4)主机控制器及基带命令

主机控制器及基带命令被用来改变与建立诸如声音设置,认证模式,加密模式的连接相联系的LM的操作方式。

已读取主机控制器所存储的Link Key为例,HCI层为上层提供了函数接口HCI_ReqReadLinkKey,消息接口为HCI_READ_LINK_KEY_RRESULT_EVT和HCI_READ_LINK_KEY_ CNF。命令执行过程如图8所示。

(5)信息命令

这些信息命令的参数是由蓝牙硬件制造商确定的。它们提供了关于蓝牙设备及设备的主机控制器,链路管理器及基带的信息。主机设备不能更改这些参数。

HCI层为上层提供了函数接口为:
HCI_ReqCountryCode HCI_ReqLocalAddress
HCI_ReqReadLocalFeatures HCI_ReqReadLocalVersion
HCI_ReqReadBD_ADDR
HCI层提供的消息接口为: 
HCI_COUNTRY_CODE_CNF HCI_COUNTRY_CODE_CNF_NEG
HCI_LOCAL_ADDRESS_CNF HCI_LOCAL_ADDRESS_CNF_NEG
HCI_READ_LOCAL_FEATURES_CNF HCI_READ_LOCAL_FEATURES_CNF_NEG
HCI_READ_LOCAL_VERSION_CNF HCI_READ_LOCAL_VERSION_CNF_NEG
HCI_READ_BD_ADDR_CNF HCI_READ_BD_ADDR_CNF_NEG

(6)状态命令

状态命令提供了目前HCI,LM,及BB的状态消息。这些状态参数不能被主机改变,除了一些参数可以被重置。

HCI层为上层提供了函数接口为:
HCI_ReqGetLinkQuality HCI_ReqReadFailedCounter
HCI_ReqResetFailedCounter HCI_ReqRssi
HCI层提供的消息接口为:
HCI_GET_LINK_QUALITY_CNF HCI_GET_LINK_QUALITY_CNF_NEG HCI_READ_FAILED_COUNTER_CNF HCI_READ_FAILED_COUNTER_CNF_NEG
HCI_RESET_FAILED_COUNTER_CNF HCI_RESET_FAILED_COUNTER_CNF_NEG
HCI_RSSI_CNF HCI_RSSI_CNF_NEG

(7)测试命令

测试命令能够测试蓝牙硬件各种功能,并蔚蓝牙设备的测试提供不同的测试条件。

HCI层为上层提供了函数接口为:
HCI_ReqEnableDutMode HCI_ReqReadLoopbackMode
HCI_ReqWriteLoopbackMode
HCI层提供的消息接口为:
HCI_ENABLE_DUT_MODE_CNF HCI_ENABLE_DUT_MODE_CNF_NEG
HCI_READ_LOOPBACK_MODE_CNF HCI_READ_LOOPBACK_MODE_CNF_NEG
HCI_WRITE_LOOPBACK_MODE_CNF HCI_WRITE_LOOPBACK_MODE_CNF_NEG

(8)数据传输命令:

这些命令为蓝牙设备之间传输数据提供了所需要的接口。如分配所需内存的接口HCI_DataAlloc,传输数据的接口HCI_DataSend,提取数据的接口HCI_DataExtract。图9说明了在蓝牙系统中传输数据时对这些接口的使用。

四、结论

HCI为为蓝牙协议层的上层提供了进入基带的统一接口。经过测试,所开发的接口能将上层的数据流匹配到基带,使基带能对之进行处理,并产生相应的事件。