紧接着上面的内容。
(6)、链路层中的建立连接:
设备创建连接的过程如下图所示。
简言之,设备首先广播可连接广播事件,其他设备收到之后即可发起连接。在此过程中,广播者发送的事件类型要么是通用广播事件,要么是直接广播事件。发起者收到正确的广播报文时,将向广播者发送一个连接请求,其中包括
了连接开始时需要的所有信息,包括下列各项:
(*)连接中使用的接人地址
(*)CRC初始值
(*)发送窗口大小
(*)发进窗口偏穆
(*)连接间隔
(*)从设备延迟
接入地址:连接使用的接人地址总是由主设备来提供。地址通过随机生成,但是需要遵循一些规则。如果主设备有多个从设备,它会为每个从设备选择不同的随机接人地址。地址的随机性确保了在不同的主从设备之间发生的碰撞概率会降低。随机性也增强了隐私,扫描者无法得知是哪两个设备正在通信。CRC初始化:CRC初始值是另一个由主设备提供的随机数。随机的意义在于,如果在同一区域有两个主设备正在和不同从设备通信,那么使用相同的接人地址的概率将会很低。如果确实发生了这种情况,从设备会从错误的主设备收到干扰数据包。因此,为每个从设备设置随机的CRC初始值,主从设备既有相同的接人地址又有相同的CRC初始值的概率就会变得微乎其微。
发送窗口:从设备可以自行决定广播的时间,它们是最需要保存电量的设备,这样的设计并无不妥。但是,如果主设备已经在做其他事情,也许是一些更重要的事情,那么它必须让低功耗蓝牙断开当前的活动。在连接建立期间,有两个参数用来传递上述信息:窗口大小和窗口间隔。
连接事件:在一个连接当中,主设备会在每个连接事件里向从设备发送数据包。一个连接事件是指主设备和从设备之间相互发送数据包的过程。连接事件的进行始终位于一个频率,每个数据包会在上个数据包发完之后等待150ps再发送。
(7)、链路层中的发送数据:
在一个连接里,设备通过在连接事件中发送数据包来相互通信。数据报文和广播报文不同,前者是单独进行的通信,后者则是对所有的侦听设备发送广播。广播报文和数据报文之间的最大差别在于报头的格式和净荷的长度。数据报文的净荷的可以为。0 ~31字节不等。净荷长度为零的数据包是一个空包,它不含应用程序的数撂,但仍然可以在报文的头部包含一些信息。净荷的最大长度(31字节)小于广播报文的最大长度。通常只有加密报文才会使用。无论链路层加密与否,传给控制器的未加密数据包最多只能携带27个字节的数据。
数据报头:数据报文的报头如图所示,包含下面四个字段:
(*)逻辑链路标识符(LLID)
(*)序列号( SN)
(*)下一个预期序列号(NESN)
(*)更多数据(MD)
逻辑链路标识符:逻辑链路标识符( LLID)用于判断数据报文属于下列哪种类型:
(*)链路层控制报文(11)——用于管理连接
(*)高层报文开始(10) ——也可用于一个完整报文
(*)高层报文延续(01)
序列号:为了使数据传输变得可靠,所有的数据包均带有序列号。连接建立后,第一个数据包的序号为0;每次发送新的数据包时,其序列号与上个数据包的序列号不同。这使得接收装置能够判断接收的数据包的性质:如果序列号与之前的一样,则为重传报文,姐果序列号和之前的不同,则为新报文。
确认:数据包的确认需要用到另一个比特,即所谓的下一个预期序列号( NESN)。NESN的发送方用其通知对方自己期望接收的数据包的序列号。如果设备成功接收序列号为0的报文,在其确认报文中,应将下一个预期序列号设为l,否则序列号为O的数据包将被重传。因此,可以将NESN作为一个标志来判断数据包是被正确接收还是需要重传。下图说明了这一点
更多数据:数据信道报文的报头里还有最后一位——更多数据位,用来通知对端设备自己还有其他的数据准备发送。如果收到设置了更多数据位的数据包,应该在当前连接事件中继续与对端设备通信。这样一来,只要还有数据要发送,连接事件会自动扩展;一旦不再有散据发送,连接事件会迅速关闭。如果把更多数据位设为。
(8)、链路层中的加密:
在连接时,可以对净荷中的数据进行加密,确保数据的机密性,从而抵御攻击者。机密性是指第三方“攻击者”由于没有加密链路的共享秘密,因此无法拦截、破译或读取消息的原始内容。
AES加密:低功耗蓝牙中的所有加密和认证都基于同一个加密引擎,称为高级加密系统( AES)。AES最初源自美国的一项政府计划,试图寻找未来可用的加密引擎。一直以来.AES被用于许多有线和无线标准,迄今为止安全研究人员还没有找到其算法的弱点。
AES可以有多种形式,取决于在给定的时间内能够处理的数据块以及密钥的大小。低
功耗蓝牙使用128位的密匙和128位的数据块。也就是说,所有密钥的长度均为128位,
每次加密生成的密文长度为16个字节。
在低功耗蓝牙里.AES加密引擎被用于下列四个基本功能:
(*)加密净荷数据
(*)计算消息完整性校验值
(*)数据签名
(*)生成私有地址
(9)、链路层中的管理连接:
两个设备一旦连接,便可以收发数据和管理连接。连接管理涉及在链路层发送控制消息,包含下列七个链路屡控制规程:
(*)更新连接参数
(*)改变自适应跳频信道图
(*)加密链路
(*)重加密链路
(*)交换功能位
(*)交换版本信息
(*)终止链路
更新连接参数:连接建立时,主设备通过连接请求数据包发送连接参数。当连接活跃了一段时间,连接参数也许不再适用于当前使用的服务。出于提高效率的目的,连接参数需要进行更新。较之首先断开连接、接着更换新参数重新连接,还有一种在链路中更新参数的更为简单的途径
改变自适应跳频信道图:在一个开放的无线频段中,自适应跳频对于任何无线电技术的成功生存是非常重要的。不幸的是,某些技术没有采用自适应跳频,因此容易受到干扰。自适应跳顿,尤其是在一些典型设备中,存在一个很大的挑战:任何时刻,好的信道集合和差的信道集合都在不断地变化。
启动加密:只有尚未加密的链路才能启动加密。链路在加密时,需要创建一个随机数(nonce)和一个会话密钥( SK)。随机数需要每个设备分别提供4个字节的信息,会话密钥要求每个设备分别提供8个字节的信息。此外,还需要一个长期密钥( LTK)作为配对时的共享秘密。
启动加密的操作如图下图所示。
重启加密:重新启动加密有助于刷新会话密钥,一般发生在包计数器即将过期,或者主机选择了新的链路密钥,并且想要用它来获得新的会话密钥的情况下。重启加密的情况比较少见,事实上,一些设备的连接很少会持续一段较长的时间,所以没有必要重新启动加密。
4、主机/控制器接口
主机控制器接口(HCI)是主机与控制器之间的接口,主要完成两个任务:一个是发送命令给控制器和接收来自控制器的事件,另一个是发送和接收来自对端设备(peer device)的数据。一般来说,主机接口既是两个设备之间的物理上的接口,也是逻辑上的接口。逻辑接口
定义了命令、事件和数据的封包格式。而物理接口则规定了主机和控制器之间如何传输这些
数据包。
(1)、主机/控制器接口中的物理接口:
在蓝牙规范中,定义了4种物理接口,每一种对应着不同的用途:
(*)通用异步收发器(UART)提供了最简单的传输方式。
(*)3线UART 则提供可靠的UART传输方式。
(*)USB为电脑和类似的设备提供高速的、通用的传输方式。
(*)安全数字输入输出(SDIO)为消费电子设备提供中等速度的传输方式。
UART:UART是所有传输协议中最简单的一种。在零调制调解器配置下,为主机和控制器之间定义丁一个简单的通用异步收发器( UART)传输规范。零调制调解器是指发送线和接收线在设备两端交叉对接,即控制器的发送端( TXD)可以与主机的接收端(RXD)柏连,反之亦然。
3线UART:仅有TXD、RXD和地线,5线UART则多定义了两条流控线。控制器的请求发送端(RTS)与主机的清除发送端(CTS)相连,反之亦然。
3线UART:3钱UART比之前描述的UART复杂一些,它在设计上舍弃了硬件流控线,但考虑了一些误比特情况。如果你的主机和控制器之间的链路超过几毫米,并且它们处在一个有噪声的电气环境中,那么使用3线UART就再适合不过了。
对于3线UART工作模式来说,它使用了信道来标识不同的数据包,这种方式和之前
描述的UART划分数据包类型有些相似。信道号码0x1标识命令,0x2标识数据,Ox4标识
事件。另外3线UART为链路建立和确认定义了另外两条信道:OxF用于链路建立,而Ox0
则用于确认。需要注意的是,在3线UART中,信道号码长度仅为4个比特。
3线UART主要有3种模式:
(*)链路建立
(*)活动状态
(*)低电压状态
USB:USB接口主要为那些拥有USBHost的设备而设计。它定义了主机和设备之间是如何传送命令、事件和数据的。蓝牙的USB接口规范也定义了一个标准类代码(atandard class code)来标识蓝牙设备。这使得各个制造商能够销售即插即用的蓝牙软件狗(Dongle)。主机通过控制端点(0x00)给设备发送命令,使用“主机向设备请求,设备为目标”作为请求类型。主机使用中断端点(Ox81)轮询来自设备的事件。端点能够每1ms轮询一次,这使得每个事件可以在非常短的延迟内输出。
USB接口的最大缺点就是对功耗不太敏感。因为实现USB接口需要大量的高速硬件和软件控制,而它们常常抬高了成本。另一个缺点是主机必须每隔1ms向设备查询数据。通常情况下,当设备正在运行的时候,查询动作会让主机无法进入低功耗的工作模式。不过,可以使用USB的链路电源管理特性来解决这些问题,也非常建议在蓝牙设备上使用这种技术。
SDIO:SDIO协议定义了一种高速的传输接口。主机能够通过SDIO卡Type-A接口来和控制通信。SDIO是一种基于分组的总线,可以工作在很低的功耗下,使用4~8线实现双向
数据传输。SDIO接口用来传输命令、事件和数据的信道与UART以及3线UART使用的信道完一样。
另外.SDIO接口误码率非常低,这对那些拥有SDIO接口的设备来说十分有用。不过,要获得完整的SDIO传输规范,你必须是SD协会的成员之一。否则,你只能到一份用于评估SDIO技术的简版规范,它缺少了一些用于设备生产的细节,不过提供了够的信息来帮你理解系统是如何运作的。
(2)、主机/控制器接口中的逻辑接口:
HCI物理传输接口就是一种逻辑接口。所谓的逻辑接口是指在单芯片备上,你不需要在组件之间真正实现这样的信息传输接口。然而,如果系统中的控制器和机分别位于两个芯片上,HCI逻辑接口就体现为在二者之间传输数据的物理接口。
关于逻辑接口.我们需要理解三个相关的概念;
(*)信道( channel)
(*)数据包格式(packet format)
(*)流控(flow control)
HCI信道:一旦控制器与其他设备建立了连接,控制器的底层HCI接口就创建一个HCI信道,它们使用一个连接句柄(connection handle)来标识这个HCI信道。连接句柄既用来标识主机交给控制器并准备发往对端的数据,又用来标识控制器从对端收到的准备交给主机的数据。无论何时,只要主机尝试刨建一个连接,控制器就为主机提供一个连接句柄。直到连
结束连接句柄才会失效。连接结束的原因可能是本地的链路层终止规程,也可能是链路监
超时导致。
命令数据包:主机通过向控制器发送命令数据包来执行命令。这些命令通常用于配置控制器的状态或者请求控制器完成操作。
在低功耗蓝牙中一共有三种基本命令类型,分别实现如下功能
(*)配置控制器的状态
(*)请求执行特定的操作
(*)管理连接
配置控制器状态:我们可以将控制器视为一个大状态机,有一系列的参数可以进行配置。在低功耗蓝牙中,如果状态机里的某个状态正在被使用,通常是不能对其进行调整的。就好像如果启动了广播就不能再改变广播参数。这个时候,我们需要首先停止广播,修改广播参数,然后重新进行广播。
请求指定操作:一些命令可以请求控制器执行指定操作,但不会改变设备状态或者连接状态。
瞥理连接:设备建立连接之后,可以通过发送命令来管理连接
事件数据包:控制器发往主机的事件数据包主要用于发送信息和反馈之前输入的命令。HCI事件数据包由事件类型编码、参数的长度字段和事件参数组成。每个事件都有一套独特的参数。
低功耗蓝牙主要有下列三种基本事件类型:
(*)通用命令完成事件
(*)通用命令状态事件
(*)特定命令完成事件
数据包:数据包是指主机和控制器之间传输的应用数据。控制器接收来自主机的数据包,将其传给对端设备。对端设备收到数据之后,将其从控制器发往主机。
需要注意的是,从主机发送给控制器的数据包,标记00表示开始包,标记01表示延续包,然而从控制器发送给主机的数据包有些不同,标记10表示开始包,标记01表示延续包。这是因为在经典蓝牙中,主机发送给控制器的标记10表示可以在必要时将该数据包清除。而在低功耗蓝牙中不存在清除数据包的概念;相反,假如数据包无法送达,链路将被断开而不会用到上述值。
命令流控:HCI接口有两种流控形式:命令流控和数据流控。控制器使用命令流控同时处理多个HCI命令。究其原理,简单来说是因为控制器内部拥有足够的缓存,能够存储一定数量的命令;主机可以通过控制器来获知缓冲区的长度,从而得知可以同时发送的命令的最大数量。
数据流控:数据流控和命令流控的方式差不多。一共有两种数据流:主机到控制器以及控制器到主机。主机到控制器的数据流控是必须的,而控制器到主机的流控可以忽略。因为大部分的主机都能处理从控制器到主机的大量数据,因此该没有必要进行流控。对于主机到控制器的数据流控,控制器拥有一定数量的缓冲区,每个缓冲区存放一个数据包。每次控制器都从一个缓冲区提取数据包来发送给对端设备,一旦数据包成功发送,控制器释放该缓冲区,以便装填主机发送给控制器的新数据包。
(3)、主机/控制器接口中的控制器的配置:
利用控制器与对端设备通信之前,主机可以先对控制器进行下列相关操作:重置控制器
的状态、读取设备地址、设置事件掩码、读取流控缓存、读取控制器支持的功能列表、生成
随机数、加密数据、设置随机地址以及配置白名单等。
重置控制器为已知状态:在执行其他操作之前,有必要重置一下控制器的状态,由于控制器可能正在执行其他操作,或者主机传输才刚刚建立。在这种情况下,我们可以把控制器重置为就绪态,这样会把所有可配置参数恢复为默认值。
读取设备地址:很多低功耗蓝牙设备有预先设置的设备地址,可供主机读取。主机通过向控制器发送Read BD__ADDR命令来读取设备地址,后者返回一个含有固定设备地址的Command Complete事件。如果控制器没有固定地址,则返回全零地址00:00:00:00:00:00。
设置事件掩码:控制器定义了很多事件类型。考虑到未来的蓝牙规范还会添加新的事件和功能,控制器必须知道主机能够接受和处理哪些事件。如果主机不能理解控制器的事件,将会导致互操作性问题。解决问题的一个办法是设置事件掩码,让主机告诉控制器哪些事件能接收,哪些不能接收。
读取缓冲区大小:控制器最多可以有两种类型的缓冲区来满足数据传输。要获得这两种类型的缓冲区的大小,主机可以分别发送LE Read Buffer Size命令和Read Buffer Size命令。一旦收到相应的Command Complete事件,主机就能知道缓冲区的可用空间,从而确定还能向对端设备发送多少个数据包。
读取控制器支持的功能:确保主机和控制器兼容的另一个办法是,主机向控制器发送命令之前首先确认控制器支持的功能。
读取控制器支持的状态:控制器的设计可以非常简单,也可以非常复杂。因此主机必须知道控制器支持哪些状态及其组合,以免因设置了无效的状态而导致错误。
控制器可以支持如下状态:
(*)不可连接广播(nonconnectable advertising)
(*)可扫描广播(scannable advertising)
(*)可连接广播(connectable advertising)
(*)定向广播(directed advertising)
(*)被动扫描(passive scanning)
(*)主动扫描(active scanning)
(*)发起连接成为主设备(initiating a connectionto the master role)
(*)连接成为从设备(a connection to the slaverole)
(*)同时处于不可连接广播(nonconnectableadvertising)状态和被动扫描(passivescanning)状态
(*)同时处于不可连接广播(nonconnectable advertising)状态和连接成为从设备(aconnection to the slaverole)状态
随机数:控制器可以方便地生成随机数。这些随机数通常源于设备自身的物理特性,主机发送LE Rand命令来让控制器为其生成随机散。随机散包含在返回的Coand Complete事件中。
加密数据:主机可以使用低功耗蓝牙的AES-128加密引擎来加密数据。由于控制器已经实现了加密功能,给主机提供相关的接口也就顺理成章了。
设置随机地址:如果控制器没有固定地址,或者主机希望使用私有地址来替代固定地址,那么主机必须为控制器设置一个随机地址,以便用于广播、主动扫描和发起连接等操作。
白名单:控制器里面存储着一个设备地址列表,称为白名单。白名单在充满广播报文的密集环境中可用来搜索已知设备。不过由于白名单的容量有限,在使用之前首先要确定其容量的大小。主机可以通过命令对白名单进行添加、删除以及重置等操作,而控制器可以根据白名单来过滤广播数据包。
(4)、主机/控制器接口中的广播和观察:
两个低功耗蓝牙设备之间的最基本的通信模型就是广播(broadcasting)和观察(observing]
模型。二者采用广播和扫描来传输数据。
广播:广播类型一共有四种,它们分别是:
(*)可连接的非定向广播。这是一种常用的广播类型,包括广播数据和扫描响应数据,它
表示当前设备可以接受其他任何设备的连接请求。
(*)可连接的定向广播。表示设备仅仅能接受某一特定设备的连接请求,不过,它不包括
广播数据。
(*)可扫描的非定向广播。发送广播数据和扫描响应数据,用来激活扫描者。
(*)不可连接的非定向广播。仅仅发送广播数据。
被动扫描:要接收对端设备的广播数据包,可以使用被动扫描。
主动扫描:它不单可以捕获到对端设备的广播数据包,还可以捕获可能的扫描响应包。主动扫描和被动扫描使用的命令完全一样。不过,因为控制器要发送SCAN_REQ数据包给对端设备,以便获取扫描响应数据包,而这些数据包需要包含设备地址,因此,在使用LE Set Scan Parameters命令时需要配置一个额外参数,决定链路层的数据包使用固定地址抑或是随机地址
(5)、主机/控制器接口中的发起链接:
广播和扫描仅仅是蓝牙功能的一部分,要实现更多的应用功能必须依靠两个设备之间的连接。要建立连接,其中一个蓝牙设备应处于可连接的广播状态,由另一个设备发起连接。当然,连接的对象既可以是一个白名单,也可以是指定的单一设备。建立连接需要耗费一定的时间,如果用户或者应用程序不再需要连接时,可以在连接未建立之前取消。
(6)、主机/控制器接口中的连接管理:
建立连接之后,设备就可以对连接进行管理,包括切换至低功耗模式、增加或减少间隔时间、设置加密或者终止连接等。
更新连接:如果当前的连接参数不再适用时,主设备可以进行修改。比如为了加快设备韧始化,当初发起连接时使用了短间隔,假如设置已经正常运行服务了,那么使用长连接间隔会更加节能。