目录
六、HCI
主机控制器接口(HCI)是主机与控制器之间的接口,主要完成两个任务:一个是发送命令给控制器和接收来自控制器的事件,另一个是发送和接收来自对端设备(peer device)的数据。
一般来说,主机接口既是两个设备之间的物理上的接口,也是逻辑上的接口。逻辑接口定义了命令、事件和数据的封包格式。而物理接口则规定了主机和控制器之间如何传输这些数据包。
6.1物理接口
在蓝牙规范中,定义了4种物理接口,每一种对应不同的用途:
- 通用异步收发器(UART):提供了最简单的传输方式。
- 3线UART:提供可靠的UART传输方式。
- USB:为电脑和类似的设备提供高速的、通用的传输方式。
- 安全数字输入输出(SDIO):为消费电子设备提供中等速度的传输方式。
6.1.1UART
UART 是所有传输协议中最简单的一种。
在零调制调解器配置下,为主机和控制器之间定义了一个简单的通用异步收发器(UART)传输规范。零调制调解器是指发送线和接收线在设备两端交叉对接,即TXD可以与RXD相连,反之亦然。
3线UART仅有TXD、RXD和地线,5线UART则多定义了两条流控线。控制器的请求发送端(RTS)与主机的清除发送端(CTS)相连,反之亦然。
在低功耗蓝牙中,UART接口一般使用不带奇偶校验位但带有一个停止位的8bit字符。该停止位是在每个字节末端的额外一位。
UART使用硬件控制流的方式来驱动CTS和RTS。每一个HCI数据包都带有下列三种报文类型编码中的一种:命令=0x01,数据=0x02,事件=0x04。
6.1.2 3线UART
对于3线UART工作模式来说,它使用了信道来标识不同的数据包。信道号码0x1标识命令,0x2标识数据,0x4标识事件。另外3线UART为链路建立和确认定义了另外两条信道:0xF用于链路建立,而0x0用于确认。在3线UART中,信道号码长度仅为4个比特。
3线UART主要有3种模式:链路建立、活动状态、低电压状态。
链路建立信道是用来确认对端设备运行模式、配置参数和自动探测波特率。实现自动波特率探测,采用的办法是依次选择不同的波特率发送链路建立信息,然后判断哪个波特率得到对端设备的应答。两个设备链路建立使用三次握手协议,在链路建立过程中,还设置了可靠滑动窗口的大小、是否使用循环冗余校验(CRC)以及是否使用帧错位软件流控。
在活动状态下的数据传输是可靠的。所有的数据包都封装成帧,每帧带有一个序列号和确认号。这些号码的长度均为3个bit,它们实现了多个数据包的同时发送。
数据包被划分为帧时遵循SLIP(串行线路IP协议)协议。SLIP规定每一个帧以0xC0(一个字节)作为开始标志和结束标志。如果一个数据包里面出现了0xC0,则使用0xDB 0xDC(两个字节)替代。由于0xDB是一个转义序列,因此,它也需要转换成为0xDB 0xDD(两字节)。如果使用了帧错位软件流控,那么XON和XOFF字节也需要分别转换为0xDB 0xDE和0xDB 0xDF。
通过发送睡眠(sleep)信息可以将连接状态切换为低功率模式。在该模式下,UART通常处于关闭状态,传输的数据包不能保证完整地接收。假如有数据包要发送,需要花费时间等待对端设备唤醒UART硬件。
为了实现高效的唤醒机制,在向对端设备发送HCI信息之前,首先向其发送一段很短的唤醒信息。对方一旦回复了已唤醒(woken)信息就会切换至活动状态。
6.1.3USB
USB接口主要为那些拥有USB Host的设备而设计。它定义了主机和设备之间是如何传送命令、事件和数据的。蓝牙的USB接口规范也定义了一个标准类代码来标识蓝牙设备。这使得各个制造商能够销售即插即用的蓝牙软件狗(Dongle)。
主机通过控制端点(0x00)给设备发送命令,使用“主机向设备请求,设备为目标”作为请求类型。主机使用中断端点(0x81)轮询来自设备的事件。端点能够每1ms轮询一次,这使得每个事件可以在非常短的延迟内输出。
数据在两个端点中传输:一个是0x02,主机向设备输出块数据。另一个是0x82,设备向主机输入块设备。此外,每隔1ms就有一次轮询。然而,当需要非常高的数据吞吐量时,可以在单个帧上批量发送USB块数据。
6.1.4SDIO
SDIO(Secure Digital Input and Output):安全数字输入输出,定义了一种外设接口。
SDIO协议定义了一个高速的传输接口。主机能够通过SDIO卡Type-A接口来和控制器通信。SDIO是一种基于分组的总线,可以工作在很低的功耗下,使用4~8线实现双向数据传输。
SDIO接口用来传输命令、事件和数据的信道与UART以及3线UART使用的信道完全一样。
6.2逻辑接口
上面定义的HCI物理传输接口就是一种逻辑接口。 逻辑接口是指在单芯片设备上,不需要在组件之间真正实现这样的信息传输接口。然而,如果系统中的控制器和主机分别位于两个芯片上,HCI逻辑接口就体现为在二者之间传输数据的物理接口。
6.2.1HCI信道
一旦控制器与其他设备建立了连接,控制器的底层HCI接口就创建一个HCI信道,我们使用一个连接句柄(connection handle)来标识这个HCI信道。
连接句柄既用来标识主机交给控制器并准备发往对端的数据,又用来标识控制器从对端收到的准备交给主机的数据。
6.2.2命令数据包
主机通过向控制器发送命令数据包来执行命令。这些命令通常用于配置控制器的状态或者请求控制器完成操作。
如图6-1所示,HCI命令数据包包括:用来确认发送命令的操作码、参数的长度字段、命令参数。每个命令都有自己的一套独特的参数。
在低功耗蓝牙中一共有三种基本命令类型,分别实现如下功能:配置控制器的状态、请求执行特定的操作、管理连接。
6.2.3事件数据包
控制器发往主机的事件数据包主要用于发送信息和反馈之前输入的命令。
如图6-2所示,HCI事件数据包由事件类型编码、参数的长度字段和事件参数组成。每个事件都有一套独特的参数。低功耗蓝牙主要有下列三种基本事件类型:通用命令完成事件、通用命令状态事件、特定命令完成事件。
1、通用命令完成事件
当主机发送给控制器的命令执行完毕时,控制器立即返回一个通用命令完成事件。事件的参数包括了之前发送的命令操作码和执行命令的返回参数。返回参数中的第一个参数是状态码,状态码用来表示命令执行成功与否。
注:每当控制器执行与无线传输无关的任务时,都将使用通用命令完成事件。
2、通用命令状态事件
如LE Create Connection等命令类型需要执行无线传输操作的,通常返回的是通用命令状态事件;一段时间后才会返回特定命令完成事件。
3、特定命令完成事件
有些命令需要一段时间才能完成执行,它们都有对应的、并且是唯一的特定命令完成事件。
例如LE Create Connection命令首先返回一个命令状态事件,随后等待连接建立完成或失败,再返回LE Connection Complete事件。
注:命令是否执行完毕并不以收到了特定命令完成事件作为标志。
6.2.4数据包
数据包是指主机和控制器之间传输的应用数据。控制器接收来自主机的数据包,将其传给对端设备。对端设备收到数据之后,将其从控制器发往主机。
如图6-3所示。数据包总是以连接句柄作为第一个字段,在LE Connection Complete事件中该字段占用了12位。如果主机一直没有收到LE Connection Complete事件,则不能发送任何数据给对端设备;只有收到该事件,主机才可以启动数据发送或者接收对端设备发送过来的数据。
HCI数据包有两种标记(flags):数据包边界标记(Packet Boundary Flag)和广播标记(Broadcast Flag)。由于其中一些标记继承自经典蓝牙,它们在低功耗蓝牙里没有什么意义。数据包边界标记用来确认上层协议(逻辑链路控制和适配协议,L2CAP)的信息是一个开始数据包还是一个延续包。
注:从主机发送给控制器的数据包,标记00表示开始包,标记01表示延续包;而从控制器发送给主机的数据包有些不同,标记为10表示开始包,标记01表示延续包。
6.2.5命令流控
HCI接口有两种流控形式:命令流控和数据流控。
控制器使用命令流控同时处理多个HCI命令。其原理是:控制器内部拥有足够的缓存,能够存储一定数量的命令;主机可以通过控制器来获知缓冲区的长度,从而得知可以同时发送的命令的最大数量。
HCI接口不支持事件流控,因为事件的数量受限于可处理命令的数量,另外主机比控制器拥有更多的资源,使用能够顺序地缓冲和处理这些事件。
要启动命令流控,所有命令完成(Command Complete)事件和命令状态(Command Status)事件都必须包含一个Num HCI Command Packets参数。该参数用来表示控制器能够缓存多少条命令。
控制器每次都从缓冲区中获取命令来执行。控制器每次向主机发送命令完成事件或命令状态事件,都会在其中包含缓冲区的剩余空间。控制器可以随时发送操作码为No Operation的命令完成事件,其中携带新的Num HCI Command Packets参数。
6.2.6数据流控
一共有两种数据流:主机到控制器以及控制器到主机。主机到控制器的数据流控是必须的,而控制器到主机的流控可以忽略。因为大部分的主机都能处理从控制器到主机的大量数据。
对于主机到控制器的数据流控,控制器拥有一定数量的缓冲区,每个缓冲区存放一个数据包。每次控制器都从一个缓冲区提取数据包来发送给对端设备,一旦数据包成功发送,控制器释放该缓冲区,以便装填主机发送给控制器的新数据包。
双模控制器的流控有两个不同的缓冲区:一个用于基本速率数据(basic rate data),另一个用于低功耗数据。要获得两种缓冲区的剩余空间分别要用Read Buffer Size命令和LE Read Buffer Size命令。
主机通过命令获知缓冲区的剩余数量,每发送一个数据包给控制器,就消耗控制器中的一个缓冲区。控制器发送Number Of Completed Packets事件给主机,当中包含连接句柄的列表和发送数据包的数量,之后释放相应缓冲区。因此,主机不仅知道控制器释放了多少个缓冲区,也知道哪些数据发送到了对端设备。
6.3控制器的配置
利用控制器与对端设备通信之前,主机可以先对控制器进行下列相关操作:重置控制器的状态、读取设备地址、设置事件掩码、读取流控缓存、读取控制器支持的功能列表、生成随机数、加密数据、设置随机地址以及配置白名单等。
6.3.1重置控制器为已知状态。
由于控制器可能正在执行其他操作,或者主机传输才刚刚建立。在这种情况下,我们可以把控制器重置为就绪态,这样会把所有可配置参数恢复为默认值。
主机通过发送Reset命令来重置控制器。控制器一旦重置,将向主机返回Command Complete事件。注:(1)重置命令不会重置物理链路,如果要重置链路的话,需要执行另外的链路重置操作;(2)虽然主机可以发送多条命令给控制器,但是如果控制器正在执行重置操作,也不能接受其他任何命令。(3)当控制器正在执行某条命令时,假如主机发送了重置命令,那么控制器会停止执行当前命令,转向执行重置命令。
6.3.2读取设备地址
主机通过向控制器Read BD_ADDR命令来读取设备地址,后者返回一个含有固定设备地址的Command Complete事件。如果控制器没有固定地址,则返回全0地址00:00:00:00:00:00。此时,主机需要为控制器生成一个随机地址,否则无法进行数据传输。
6.3.3设置事件掩码
设置事件掩码,是让主机告诉控制器哪些事件能接收,哪些事件不能接收。这样控制器只会发那些能被接收的事件。
设置事件掩码需要用到两条命令。一条是Set Event Mask命令,另一条是LE Set Event Mask命令。(1)主机使用Set Event Mask来启动或屏蔽meta-event事件。(2)LE Set Event Mask命令则是用来启动或屏蔽相关的低功耗蓝牙事件。
6.3.4读取缓冲区大小
在数据流控中,提到两种类型的缓冲区(基本速率数据缓冲区和低功耗数据缓冲区)来满足数据传输。要获得这两种类型的缓冲区大小,主机可以分别发送Read Buffer Size命令和LE Read Buffer Size命令。一旦收到相应的Command Complete事件,主机就能知道缓冲区的可用空间,从而确定还能向对端设备发送多少个数据包。
6.3.5读取控制器支持的功能
确保主机和控制器兼容的另一个办法是,主机向控制器发送命令之前首先确认控制器支持的功能。
如图6-5所示,主机通过发送LE Read Supported Features命令来获得控制器所支持的功能列表。在控制器返回的Command Complete事件中包含此功能列表。一般来说,6.
6.3.6读取控制器支持的状态
主机发送LE Read Supported States命令后,控制器返回带有支持的状态列表的Command Complete事件。
控制器可以支持 如下状态:不可连接广播、可连接广播、可扫描广播、定向广播、被动扫描、主动扫描、发起连接成为主设备、连接成为从设备。
还可以读取一些标志位来了解控制器支持哪些组合状态:同时处于不可连接广播状态和被动扫描状态、同时处于不可连接广播状态和连接成为从设备状态。
6.3.7随机数
主机发送LE Rand命令来让控制器为其生成随机数。随机数包含在返回的Command Complete事件中。
6.3.8加密数据
主机可以使用低功耗蓝牙的AES-128加密引擎来加密数据。由于控制器已经实现了加密功能,给主机提供相关的接口。
主机发送LE Encrypt命令来进行数据加密。在此命令中包含了需要加密的数据和加密密钥,如图6-6所示。控制器使用AES-128加密算法进行加密,并在返回的Command Complete事件中包含已加密数据。
注:在低功耗蓝牙中是没有解密命令的。主机可能要为使用私有地址的设备加密数据,但是无需实现数据解密。也就是说,主机只能检查相同的明文在变成密文后是否一致,而不能使用密钥将密文恢复为明文。
6.3.9设置随机地址
如果控制器没有固定地址,或者主机希望使用私有地址来代替固定地址,那么主机必须为控制器设置为一个随机地址,以便用于广播、主动扫描和发起连接等操作。
通常来讲,随机地址由随机数生成或者有随机数和IRK(identity resolving key)的组合生成。
如图6-7所示,主机首先使用LE Rand命令生成一个随机数。接下来,此随机数和IRK分别作为明文和加密密钥执行LE Encrypt命令。主机获得了返回值后将其作为随机地址,使用LE Set Random Address命令对控制器进行设置。只有收到了地址设置的Command Complete事件,该随机地址才可用于其他命令。
6.3.10白名单
控制器里面存储着一个设备地址列表,称为白名单。
白名单的容量有限,在使用之前首先要确定其容量的大小。主机可以通过命令对白名单进行添加、删除以及重置等操作,而控制器可以根据白名单来过滤广播数据包。
如图6-8所示,主机使用LE Read White List Size命令来读取白名单的容量大小,控制器在返回Command Complete事件中包含了最多能容纳的条目数量。在管理白名单方面,可以用LE Clear White List命令来清空列表,要从列表中添加和删除条目则应使用LE Add Device To White List和LE Remove Device White List。
当控制器正在使用白名单的时候不能改变其列表内容。
6.4广播和观察
6.4.1广播
控制器有两类数据可以通过广播发送:广播数据和扫描响应数据。
主机使用LE Set Advertising Parameters命令来设置广播参数。配置参数包括广播的最小间隔时间①和最大间隔时间②,范围从20ms~10.24ms。
另外,广播类型③一共有四种:
- 可连接的非定向广播:包括广播数据和扫描响应数据,它表示当前设备可以接受其他任何设备的连接请求。
- 可连接的定向广播:表示设备仅仅能接受某一特定设备的连接请求,不包括广播数据。
- 可扫描的非定向广播:发送广播数据和扫描响应数据,用来激活扫描者。
- 不可连接的非定向广播:仅仅发送广播数据。
LE Set Advertising Parameters命令还可以设置地址类型④,或者为固定设备地址,或者为随机地址。如果当前的广播类型为定向广播,那么在广播数据包中应包含有对端设备的地址。另外还有两个参数可以配置,分别是广播信道映射⑤和广播过滤策略⑥。
广播信道映射用来决定使用哪个广播信道,而过滤策略用来过滤不符合规则的广播数据包,过滤策略可以设置为如下规则之一:
- 接受任何设备的扫描请求或连接请求。
- 仅仅接受白名单中的特定设备的扫描请求,但是接受任何设备的连接请求。
- 接受任何设备的扫描请求,但仅接受白名单中的特定设备的连接请求
- 仅仅接受白名单中的特定设备的扫描请求和连接请求。
如果想要获得广播时的发射功率,那么可以使用LE Read Advertising Channel TX Power命令。另外,我们还将发射功率的值放在广播数据包中或扫描响应数据包中,从而实现靠近配对,或者供用户界面根据路径损耗对设备进行排序。
要设置广播数据包和扫描响应数据包的内容,主机可以分别使用LE Set Advertising Data命令和LE Set Scan Response Data命令实现。
当一些配置就绪,可以使用LE Set Advertising Enabled来启动或关闭广播。广播一旦启动,控制器将使用配置好的参数进行广播。
6.4.2被动扫描
要接收对端设备的广播数据包,可以使用被动扫描。
使用LE Set Scan Parameters命令来进行设置控制器的扫描参数。可配置的参数如下:
- 扫描类型——可设置为被动扫描或主动扫描。
- 扫描间隔——控制器间隔多长时间扫描一次。
- 扫描窗口——每一次扫描持续的时间。
- 扫描策略——接受任何数据包或者仅仅接受白名单设备的广播数据包。
扫描间隔和扫描窗口决定了控制器的扫描频率和扫描时间的长短。扫描间隔和扫描窗口共同决定控制器的扫描占空比,即扫描窗口与扫描间隔的比值。
扫描过滤策略决定了是否使用白名单。控制器可以接受任何的广播数据包,也可以仅仅接受白名单中符合过滤策略的广播数据包。要注意的是:如果定向广播数据包的目的地址并非是自己,那么,该数据包必须要抛弃,即使广播数据包的发送者在自己的白名单也不例外。
参数设置完毕,主机就可以使用LE Set Scan Enabled命令启动扫描。
在扫描过程中,如果控制器接收到的符合过滤策略和其他规则的广播数据包,则发送一个LE Advertising Report事件给主机。除了广播者的设备地址外,报告事件还包含广播数据包中的数据,以及接受广播数据包时的信号接收强度rssi。(可以利用该信号强度以及位于广播数据包中的发送功率,共同确定信号的路径损失,从而给出大致范围。)
主机想停止扫描,还是使用LE Set Scan Enable命令,只是参数设置为“停止扫描”。
6.4.3主动扫描
主动扫描不单可以捕获到对端设备的广播数据包,还可以捕获可能的扫描响应包。
在参数配置和启动扫描方面,主动扫描和被动扫描使用的命令完全一样。不过,因为控制器要发送SCAN_REQ数据包给对端设备,以便获得扫描响应数据包,而这些数据包需要包含设备地址,因此,在使用LE Set Scan Parameters命令时需要配置一个额外参数,决定链路层的数据包使用固定地址还是随机地址。
控制器收到SCAN_RSP数据包后将向主机发送一个LE Advertising Report事件。该事件同样包括了链路层数据包的广播类型。因此,主机能够判断对端设备是否可以连接或扫描,并且区分出广播数据包和扫描响应数据包。
6.5发起连接
6.5.1与白名单设备发起连接
主机先将对对端设备添加到白名单中,然后再与白名单中的设备进行连接。通过这种方式,控制器可以同一时间和多个设备发起连接。
如图6-11所示,主机使用LE Add Device To White List以及其他白名单管理命令实现该功能。一旦主机打算与白名单中的设备连接,则向控制器发送LE Create Connection命令。
LE Create Connection命令可配置如下参数:
- 扫描间隔和扫描窗口——与主动扫描参数共同决定控制器侦听广播的频率。
- 发起者过滤策略——可设置为“使用白名单”,表示仅与白名单中的设备发起连接。
- 发起者地址类型——该参数设置CONNECT_REQ数据包的地址类型是固定地址还是随机地址。
- 发起连接参数——该参数用于设置主设备传输数据给从设备的频率,从设备可以忽视主设备的等待时间(latency)、监控超时(supervision timeout)以及每个连接中发生从设备或来自从设备的预期的数据传输质量。
注:发起连接参数对白名单的所有设备是完全相同的。如果要与不同类型的设备进行连接,那么主机应该为LE Create Connection命令设置最坏情况下的连接参数。
如果控制器收到白名单中某一设备的可连接广播数据包,则向对端设备发送CONNECCT_REQ数据包,其中含有所有连接所需的信息。另外,控制器还向主机发送LE Connection Complete事件。如果对端设备接收到CONNECT_REQ数据包,它也会向其主机发送LE Connection Complete事件。
该LE Connection Complete事件包含连接句柄,用于标识主机和控制器之间传输的数据包。该事件还包括当前控制器的角色信息(主设备或从设备),以及从设备的地址、间隔时间、等待时间、监控超时和主设备的时钟精度等。从设备需要利用时钟精度来决定其出口扩展,而该参数提供给主机当做信息参考之用。
注:当连接已经建立并且发送了LE Connection Complete事件,所有的广播或者其他的发起连接请求将会自动停止。
6.5.2与单一设备发起连接
与单一设备进行连接,主机同样使用LE Create Connection命令。区别在于,发起者的过滤策略将设置为“忽略白名单”,另外还需要设置对端设备的地址等相关参数。
6.5.3取消连接请求
有时候由于连接的设备不在附近,连接请求的接收方长时间没有响应,此时,主机可以取消此连接请求,转而执行其他任务。
主机使用LE Create Connection命令向对端设备发出连接请求,如果主机想取消此次的连接,发送LE Create Connection Cancel命令即可,该命令会返回Command Complete事件。另外,不管连接成功与否,LE Create Connection命令的都会返回LE Connection Complete事件。
注:取消连接请求可能出现竞态条件。打个比方,主机向控制器发送LE Create Connection Cancel命令的同时,可能控制器已经向对端设备发送了CONNECT_REQ,但尚未返回LE Connection Complete事件。在这种情况下,LE Create Connection Cancel命令返回Command Complete事件,但还可能收到一个连接已经建立的LE Connection Complete事件。所以,即便试图取消某个连接,该连接也完全有可能成功建立。
6.6连接管理
建立连接之后,设备就可以对连接进行管理,包括切换至低功耗模式,增加或减少间隔时间、设置加密或者终止连接等。
6.6.1更新连接
如果当前的连接参数不再适用时,主设备可以进行修改。如图6-12所示,主设备使用LE Connection Update命令修改连接参数。连接参数包括新的连接间隔时间、等待时间、监控超时以及连接事件长度。
控制器收到命令后先返回Command Status事件,随后才发送链路连接更新请求数据包给对端设备。该数据包括了瞬时时刻。一旦计数器倒数结束,就必须更新连接参数,随后控制器返回LE Connection Update Complete事件表示连接参数已经更新。
6.6.2更新信道映射图
主机可能存有关于本地信道使用情况的信息,并且希望将该信息告知控制器。
比如说,本地有一个WiFi设备正在与访问点进行通信,而低功耗蓝牙的工作信道如果能与该WiFi设备的工作信道错开,无疑能减少互相干扰。
低功耗蓝牙并不能直接向对端设备发送请求以设置链路层信道图,但是主机可以使用LE Set Host Channel Classification命令来达到相同的目的,如图6-13所示。该命令中含有一个位字段
,表示每个链路层的数据信道是坏信道或者未知信道。 显然,主机无法知道某个信道是不是“好”的信道,但控制器可以通过监测信道中数据包的错误率来判断哪些未知信道的确很糟糕。
LE Set Channel Classification命令将返回Command Complete事件。控制器可以在任何时候启动链路层控制规程修改信道映射图。另外,主机也可以使用LE Read Channel Map命令获得当前的信道映射图,该命令的返回事件包含了每个链路层数据信道的使用情况。
6.6.3交换功能列表
主机可以获知当前连接所支持的功能。如图6-14所示,主设备的主机使用LE Read Remote Used Features命令请求获取对端设备的支持功能列表。该命令除了返回Command Status事件外,还会让控制器发送链路层功能请求(LL_FEATURE_REQ)以及获得对端设备的链路层功能响应包(LL_FEATURE_RSP)。随后,控制器在返回的LE Read Remote Used Features Complete事件中包含了对端设备的功能信息。
6.6.4交换版本信息
主机使用LE ReadRemote Version Information命令交互版本信息。控制器除了Command Status事件外,还将交换链路层版本信息。
交换版本信息后,控制器将该信息包含在LE Read Remote Version Information Complete事件中,并通知主机。如图6-15所示。
注:当再次执行LE Read Remote Version Information命令时,虽然仍然返回相同的事件,但是控制器并不会执行相关的链路层规程。这是因为版本信息会被当做一种静态信息缓存在控制器中。如果设备之间已经交换了版本信息,当再次执行版本交换命令时,控制器会在状态事件之后立即返回命令完成事件。
6.6.5加密连接
只要连接双方都有一共享密钥,主机就可以加密传输数据。共享密钥由安全管理器(Security Manager)设置,无论是初始化配对过程还是绑定过程中的密钥分配都是由它管理。
连接加密涉及两组命令和事件:一组与主设备相关,另一组与从设备相关。
主设备的主机使用LE Start Encryption命令要求链路层启动加密,该命令包含了连接加密密钥(如图6-16所示)。当加密规程开始后,控制器将返回Command Status事件。随后链路层开始加密。加密规程启动之后,控制器返回Encryption Change事件,告知主机加密已经成功或者加密过程出现了问题。
在从设备视角中,如图6-17所示,从设备的主机首先收到LE Long Term Key Request事件,通知从设备启动加密。主机接着发送LE Long Term Key Request Reply命令作为响应,其中包括了加密连接的密钥。由于这是一条命令,所以会返回相应的Command Complete事件。连接成功加密后,从设备的主机将收到Encryption Change事件,通知其更新加密状态。
6.6.6重启加密
有时候主机需要重新启动加密,或许是为了使用新的加密密钥,或许是为了刷新用来生成密钥的初始化向量。
如图6-18所示主设备用到的加密事件和命令与启动加密时的完全一样,不过链路层需要发送更多的数据包:首先要停止加密,然后再重启加密。
从设备用到的加密事件、命令也和初始加密时完全一样,如图6-19所示。
注:在低功耗蓝牙中,不允许在停止加密后发送应用数据或主机数据。因此一旦暂停加密后,不需要发送Encryption Key Refresh Complete事件。
6.6.7终止连接
如果不再需要发送数据,或者维持连接比断开后再重新连接需要更多的能量时,主机可以终止连接。
如图6-20所示,主机向链路层发送Disconnect命令终止连接,随后链路层返回Command Status事件并尝试终止连接。如果连接成功终止,控制器将返回Disconnect Complete事件。
当发生监控超时或者加密消息完整性检查失败导致了连接中断,主机也会收到Disconnect Complete事件。监控超时一般发生在两个设备距离较远时,彼此收不到对端的数据包。加密消息完整性检查失败通常不会发生,除非有攻击者试图接管连接,或者发生了某种特殊的情况,比如出现了较为罕见的位错误,导致报文通过了循环冗余校验而为通过消息完整性检查。