文章目录
5 链路层控制
链路层控制协议LLCP
用来控制和协商两个链路层之间链接中的操作部分。包括控制链接,启动及暂停加密以及其他链接进程的进程。
进程具有Section 5.2
所定义的超时时间规则,终止进程可以在任意时候进行发起,即使其他链路层控制进程正在活动。对于其他的链路层控制进程,每个链接每个设备同时只能有一个链路层控制进程在链路层发起。新的链路层控制进程只有在上一个链路层控制进程完成之后才能发起。但是,除了本节中其他地方禁止的情况,链路层可以在响应对端设备发起的进程的时候发起链路层控制进程。
链路层控制进程的执行的顺序没有任何限制,除非在进入连接态之前没有可以执行的进程。例如,没有进程需要之前执行的不同的进程。
LL Control PDUs
和 LL Data PDUs
的优先级基于特定的实现,例如,Host不能假设挂起的数据在Host请求终止链接并不等待数据PDU完成并通知Host时被发送。
如果远端设备不支持一个进程,则链路层通常会收到一个LL_UNKNOWN_RSP
,其中UnkownType
字段设置为发起PDU的操作码。这种情况下,进程在收到LL_UNKNOWN_RSP PDU
时关闭。
5.1 链路层ACL控制进程
除了描述不支持某一特性的链路层行为的任何描述外,下面每一小结的要求只有在链路层支持相关特性时才适用。
5.1.1 链接更新进程
链路层的链接参数(connInterval,connSlaveLatency和connSupervisionTimeout
)可以在进入连接态以后进行更新。设备可以请求更改链接参数,如果这个做的话,需要应用下面的规则。
如果master和slave都支持链接参数请求进程(Section 5.1.7),则任何一个设备都可以使用这个进程。但是,如果salve拒绝了提供了链接参数,master可以使用连接更新进程。
如果master,slave或者两者都不支持连接参数请求进程,则master需要发送LL_CONNECTION_UPDATE_IND PDU
(slave不能发送这个PDU),slave需要使用L2CAP LE
信号信道(见Vol 3Part A,Section 4.20 和 Section 4.21
)。
如果一个设备支持连接参数请求进程但是不知道是否对端设备也支持(由于设备之前没有尝试这个进程或没有进行特性交换进程),则它需要发起连接参数请求进程,然后如果对端设备响应了LL_UNKNOWN_RSP PDU
则使用上一段中描述的策略。
master的链路层根据Host提供的间隔范围(connInterval
m
i
n
_{min}
min 和 connInterval
m
a
x
_{max}
max)决定connInterval
。但是,如果当前PHY为LE Coded PHY并且Controller支持LE数据包长度扩展特性,则新的链接间隔需要至少为connIntervalCodedMin us
。
链路层需要通知Host选择的间隔值。
Section 5.5
适用于LL_CONNECTION_UPDATE_IND PDU
。当slave在未来的instant
接收到这一PDU时,它需要监听connEventCount
等于这个instant
以及它前面的一个连接事件。
在这个instant
前使用的连接间隔叫做connInterval
O
L
D
_{OLD}
OLD,包含在LL_CONNECTION_UPDATE_IND PDU
中并在这个instant
以及之后使用的链接间隔叫做connInterval
N
E
W
_{NEW}
NEW。
在这个instant
前使用的从机链接延迟叫做connSlaveLatency
O
L
D
_{OLD}
OLD,包含在LL_CONNECTION_UPDATE_IND PDU
中并在这个instant
以及之后使用的从机链接延迟叫做connSlaveLatency
N
E
W
_{NEW}
NEW。
在这个instant
前使用的链接监控超时叫做connSupervisionTimeout
O
L
D
_{OLD}
OLD,包含在LL_CONNECTION_UPDATE_IND PDU
中并在这个instant
以及之后使用的链接监控超时叫做connSupervisionTimeout
N
E
W
_{NEW}
NEW。链接监控定时器需要再这个instant
进行重置。
例如,在这个instant
之前的链接事件到这个instant
之间的间隔为connInterval
O
L
D
_{OLD}
OLD,在这个instant
之后的链接事件及接下来的链接事件的间隔为connInterval
N
E
W
_{NEW}
NEW。
master需要在确定使用新的链接参数发送第一个数据包的时间的时候调整锚点。使用Section 4.5.3
中使用的发送窗口。发送窗口开始与这个instant
之前的链接事件的锚点之后的connInterval
O
L
D
_{OLD}
OLD+transmitWindowOffset。transmitWindowOffset
需要为1.25ms的倍数,并且范围在0到connInterval
N
E
W
_{NEW}
NEW。transmitWindowSize
为1.25ms的倍数,范围为1.25ms到10ms和(connInterval
N
E
W
_{NEW}
NEW - 1.25ms)的较小值。
注意:如果slave在这个instant
第一次接收到LL_CONNECTION_UPDATE_iND PDU
,则可以立即使用这个包作为新的锚点而不必使用transmitWindowOffset
和transmitWindowSize
。
master需要在Section 4.5.3
中定义的发送窗口之内发送第一个数据包,master的第一个数据包扩展到发送窗口之外是允许的。
这个instant
之后master发送的第一个数据包决定了链接事件的新的锚点,因此链接中的未来链接事件的时间也确定了。
发生在connInterval
O
L
D
_{OLD}
OLD之后以及transmitWindowOffset
之前时,所有的普通连接事件发送需要使用Section 4.5.1
中指定的规则。
在发送窗口的开始,链路层需要重置T L L c o n n S u p e r v i s i o n _{LLconnSupervision} LLconnSupervision。
如果master的链路层主动发送量LL_CONNECTION_UPDATE_IND PDU
,例如没有经过Host的请求,则从机延迟和监控超时参数不能进行改变,需要保持与最后一次LL_CONNECTION_UPDATE_iND,CONNECT_IND或 AUX_CONNECT_REQ PDU
中相同的值。任何其他的值(transmitWindowSize,transmitWindowOffset,connInterval,Instant
)可能在上述的限制范围内更改。
注意:主动更新可以应用于master由于其他活动需要更改链接的调度而更改锚点的情况。
链路层在这三个链接参数中任意一个改变的时候需要通知Host,如果没有链接参数变动,无需通知Host。这叫做锚点移动。
这个进程在这个instant
通过之后完成,然后使用新的连接事件参数。
5.1.2 信道图更新进程
链路层参数信道图channelMap
可以在进入连接态以后进行更新。master可以通过发送LL_CHANNEL_MAP_IND PDU
更新信道图。slave不能发送这个PDU。master的Controller可以在不经过Host请求的情况下更新信道图。
Section 5.5
需要应用于LL_CHANNEL_MAP_IND PDU
。
instant
之前的信道图叫做 channelMapOLD,包含在LL_CHANNEL_MAP_IND PDU
以及在Instant以及之后使用的信道图叫做channelMapNEW。
当connEventCount
等于Instant的字段时,channelMapNEW需要为当前channelMap
,lastUnmappedChannel
不能进行复位。如果unmappedChannel
为unused
信道,则channelMapNEW需要在重映射时使用。唯一改变的参数为channelMap
。
例如:
在链接建立时:
- 初始channelMapOLD :0x1FFFFFFFFF(所有信道都使能)。
- 初始
hopIncrement
:10(十进制)。
然后发出具有如下参数的LL_CHANNEL_MAP_IND PDU
:
Instant
:100(十进制),假设自链接开始以后没有发生连接事件计数。- channelMapNEW:0x1FFFFFF7FF(例如,除了通道11其他所有通道都使能)。
Used
信道:
- connEventCount 99 --> 数据通道索引1 (channelMapOLD)
- connEventCount 100 --> 数据通道索引12 (从信道11重映射)(channelMapNEW)
- connEventCount 101 --> 数据通道索引21 (channelMapNEW)
这个进程在Instant通过并且新的信道表应用到ACL上的时候完成,如果ACL有任何关联的CISes,新的信道表需要在这个instant之后开始的下一个CIS事件中开始的CIS中应用。
5.1.3 加密进程
链路层通过Host的请求进行此操作,可以使用加密启动进程在进入链接状态后启用数据包的加密。
一旦链接加密以后,链路层可以使用封装了加密过程的加密暂停进程来改变加密秘钥。
链路层在有已建立的与ACL相关联的未加密CIS的时不能发起加密启动进程。
5.1.3.1 加密启动进程
为了使能加密,必须交换两个参数,IV
和SKD
。两者都由两部分组成:master部分和slave部分,通过LL_ENC_REQ 和 LL_ENC_RSP PDUs
进行交换。在交换完成以及Host已经通知链路层长期秘钥(LTK
)在链接中使用时,加密可以使用三方握手的方式使用LL_START_ENC_REQ 和 LL_START_ENC_RSP PDUs
开始。
为了启动加密,master的链路层需要生成初始化向量(IVm
) 和 会话密钥(SKDm
)的master部分。IVm
为master的链路层生成的32位的随机数。SKDm
为master的链路层生成的64位随机数。所有的IVm
和SKDm
都需要按照Vol 2 Part H,Section 2
中定义的随机数生成要求生成。
在发送LL_ENC_REQ PDU
时,master的链路层需要完成当前数据物理信道PDU的发送以及可能完成Controller的队列中的附加数据物理信道PDU的发送。这些数据物理信道PDUs被应答以后,直到这个进程完成或者其他特殊情况,master的链路层只能发送Empty PDUs,LL_TERMINATE_IND PDUs 和 这个进程要求的PDUs
。
master的链路层需要发送LL_ENC_REQ PDU
,Rand
和 EDIV
字段由Host提供。在master收到LL_ENC_RSP PDU
应答后,只期望收到这个进程需要的PDUs。
如果slave的链路层不支持加密,slave的链路层需要发送ErrorCode
设置为Unsupport Remote Feature / unsupported LMP Feature (0x1A)
的LL_REJECT_IND 或 LL_REJECT_EXT_IND PDU
。收到LL_REJECT_IND 或 LL_REJECT_EXT_IND PDU
的master的链路层需要通知Host,master的链路层后面可以发送LL Data PDUs 和 LL Control PDUs
,这些数据包将不会被加密。这个进程在master端结束于master收到来自slave的LL_REJECT_IND 或 LL_REJECT_EXT_IND PDU
。这个进程在slave端结束语它发送LL_REJECT_IND 或 LL_REJECT_EXT_IND PDU
给到master。
除此之外,当slave的链路层接收到LL_ENC_REQ PDU
,slave的链路层需要生成初始化向量(IVm
) 和 会话密钥(SKDm
)的master部分。IVm
为slave的链路层生成的32位的随机数。SKDm
为的slave链路层生成的64位随机数。所有的IVm
和SKDm
都需要按照Vol 2 Part H,Section 2
中定义的随机数生成要求生成。
slave的链路层需要完成当前数据物理信道PDU的发送以及可能完成Controller的队列中的附加数据物理信道PDU的发送。这些数据物理信道PDUs被应答以后,直到这个进程完成或者其他特殊情况,slave的链路层只能发送Empty PDUs,LL_TERMINATE_IND PDUs 和 这个进程要求的PDUs
。
如果slave发送的任意数据物理信道PDU为LL Control PDU
,则加密启动进程完成后,链路层需要尽快回复任何未完成的进程。
slave的链路层需要发送LL_ENC_RSP PDU
,slave的链路层需要将EDIV
和Rand
字段通知给Host。发送完LL_ENC_RSP PDU
以后,slave的链路层可以收到对应于slave发送的LL Control PDU
的LL_UNKNOWN_RSP PDU
。这种情况下,slave不应该断开链接。
每个链路层需要按照下面方式合并初始向量部分以及会话密钥部分:
SKD = SKDm || SKDs
IV = IVm || IVs
SKDm 和 SKDs进行组合,SKDm的最低有效字节成为SKD的最低有效字节,SKDs的最高有效字节成为SKD的最高有效字节。
IVm 和 IVs进行组合,IVm的最低有效字节成为IV的最低有效字节,IVs的最高有效字节成为IV的最高有效字节。
长期秘钥(LTK)由Host提供给master和slave的链路层,应触发下面三种行为之一:
- 如果这个进程在暂停加密进程之后进行,并且Host没有提供LTK,则slave需要使用错误码
PIN or Missing (0x06)
来执行终止进程。 - 如果Host没有提供LTK,或者给到Host的事件被屏蔽掉或者Host指示秘钥不可用,则slave需要发送
ErrorCode
设置为PIN or Missing (0x06)
的LL_REJECT_IND
或RejectOpcode
设置为LL_ENC_REQ
并且ErrorCode
设置为PIN or Missing (0x06)
的LL_REJECT_EXT_IND PDU
。一旦接收到LL_REJECT_IND 或 LL_REJECT_EXT_IND PDU
,链路层需要通知Host。然后链路层可以发送LL Data PDUs 和 LL Control PDUs
,这些数据包将不会被加密。这个进程在master端结束于master收到来自slave的LL_REJECT_IND 或 LL_REJECT_EXT_IND PDU
。这个进程在slave端结束于它收到来自master的LL_REJECT_IND 或 LL_REJECT_EXT_IND PDU
的应答。 - 如果Host提供了LTK,slave的链路层需要使用以LTK为秘钥的加密引擎计算
sessionKey
,并且SKD作为明文输入,sessionKey
参数需要设置为加密引擎的数据。
sessionKey
应用作所有加密数据包的加密引擎的秘钥。
sessionKey
计算出来以后,slave的链路层需要发送LL_START_ENC_REQ PDU
,这个数据包不需要进行加密并且链路层应设置为接收应答的加密数据包。
当master的链路层接收到LL_START_ENC_REQ PDU
,需要发送LL_START_ENC_RSP PDU
。这个PDU需要时加密的并且链路层需要设置为接收加密后的应答数据包。
当slave的链路层收到LL_START_ENC_RSP PDU
后,它需要发送LL_START_ENC_RSP PDU
,这个数据包需要时加密的。
当master的链路层收到LL_START_ENC_RSP PDU
,则链路已经进行了加密。链路层现在可以发送LL Data PDU 和 LL Control PDUs
,这些PDUs都是加密的。
链路层需要通知Host链接已经被加密。
这个进程在master端结束于master收到来自slave的LL_START_ENC_RSP PDU
。在slave端结束于slave收到来自master的LL_START_ENC_RSP PDU
。
如果在加密启动进程中slave收到LL_ENC_REQ PDU
或master收到LL_ENC_RSP PDU
后的任意时间,master或者slave的链路层收到来自对端设备的预期之外的数据物理信道PDU,需要立刻退出链接状态进入待机状态,并且需要使用错误码Connection Terminated Due to MIC Failure (0x3D)
通知Host链接已经断开。
5.1.3.2 暂停加密进程
为了在不断开链接的情况下使用新的加密秘钥,加密必须被关闭并重新使能,在暂停期间,数据PDUs不能未加密进行发送便于保护数据。
master的链路层需要完成当前数据物理信道PDU的发送以及可能完成Controller的队列中的附加数据物理信道PDU的发送。这些数据物理信道PDUs被应答以后,直到这个进程完成或者其他特殊情况,master的链路层只能发送Empty PDUs,LL_TERMINATE_IND PDUs 和 这个进程要求的PDUs
。
master的链路层需要发送LL_PAUSE_ENC_REQ PDU
,在master收到LL_PAUSE_ENC_RSP PDU
应答后,只期望收到这个进程需要的PDUs。
当slave的链路层收到LL_PAUSE_ENC_REQ PDU
以后,slave的链路层需要完成当前数据物理信道PDU的发送以及可能完成Controller的队列中的附加数据物理信道PDU的发送。这些数据物理信道PDUs被应答以后,直到这个进程完成或者其他特殊情况,slave的链路层只能发送Empty PDUs,LL_TERMINATE_IND PDUs 和 这个进程要求的PDUs
。
如果slave发送的任意数据物理信道PDU为LL Control PDU
,则加密启动进程完成后,链路层需要尽快回复任何未完成的进程。
然后slave的链路层需要发送LL_PAUSE_ENC_RSP PDU
,这个数据包需要进行加密发送并且链路层需要设置为接收未加密的响应包。
当master的链路层接收到LL_PAUSE_ENC_RSP PDU
,链路层需要设置为发送和接收未加密的数据包,然后需要发送未加密的LL_PAUSE_ENC_RSP PDU
给到slave。
当slave的链路层收到LL_PAUSE_ENC_RSP PDU
后,同样需要设置为未加密的发送。
然后两个链路层应执行加密启动进程的步骤,以使用新的会话密钥重新启用加密。当这个封装的加密启动过程完成后,加密暂停进程就完成了。
如果在加密暂停进程中slave收到LL_PAUSE_ENC_REQ PDU
或master收到LL_PAUSE_ENC_RSP PDU
后的任意时间,master或者slave的链路层收到来自对端设备的预期之外的数据物理信道PDU,需要立刻退出链接状态进入待机状态,并且需要使用错误码Connection Terminated Due to MIC Failure (0x3D)
通知Host链接已经断开。
5.1.4 特性交换进程
链路层的当前支持特性集合(FeatureSet
)参数可以在进入链接状态以后进行交换。master和slave都可以发起这个进程。
FeatureSet
信息可以在单个连接或多个连接之间进行缓存。如果某个设备的FeatureSet
信息已经进行缓存,则链路层不能再在每个连接上请求这个信息。来自上一个连接缓存的设备FeatureSet
信息是没有权威性的,因此设备需要能接受在尝试使用对端设备当前不支持或使用的特性是返回的LL_UNKNOWN_RSP PDU
的情况。
FeatureSetM为master的链路层拥有的特性,按照Section 4.6
中定义的位掩码。
FeatureSetS为slave的链路层拥有的特性,按照Section 4.6
中定义的位掩码。
FeatureSetUSED为一个字节长度,为FeatureSetM[0]和FeatureSetS[0]的逻辑与
。
5.1.4.1 master发起的特性交换进程
master通过发送LL_FEATURE_REQ PDU
给slave来发起这个进程,这个可以由Host请求或者主动进行。当slave的链路层收到这个PDU时,需要通过发送LL_FEATURE_RSP PDU
进行响应。
master的链路层发送LL_FEATURE_REQ PDU
时,FeatureSet
字段需要设置为FeatureSetM。
slave的链路层发送LL_FEATURE_RSP PDU
时,FeatureSet
字段的字节0需要设置为FeatuteSetUSED,其他字节需要设置为FeatureSetS的相应字节。
master收到来自slave的LL_FEATURE_RSP PDU
时这个进程完成。
5.1.4.2 slave发起的特性交换进程
slave通过发送LL_SLAVE_FEATURE_REQ PDU
给master来发起这个进程,这个可以由Host请求或者主动进行。当master的链路层收到这个PDU时,需要通过发送LL_FEATURE_RSP PDU
进行响应。
slave的链路层发送LL_SLAVE_FEATURE_REQ PDU
时,FeatureSet
字段需要设置为FeatureSetS。
master的链路层发送LL_FEATURE_RSP PDU
时,FeatureSet
字段的字节0需要设置为FeatuteSetUSED,其他字节需要设置为FeatureSetM的相应字节。
如果LL_SLAVE_FEATURE_REQ PDU
是由Host发起的读取远端设备特性的过程(见[Vol 4] Part E, Section 7.8.21
),并且master不支持这个进程,则需要将ErrorCode
设置为Unsupported Remote Feature / Unsupported LMP Feature (0x1A).
来通知Host读取远端设备特性进程已经完成。
slave收到来自master的LL_FEATURE_RSP PDU
时这个进程完成。
5.1.5 版本交换进程
链路层的版本信息(如Section 2.4.2.13中定义的companyID,subVerNum,linkLayerVer
)参数可以在进入链接状态以后进行交换。master或者slave的链路层都可以通过发送LL_VERSION_IND PDU
来发起这个进程。这个进程需要在Host发起请求时使用,也可能由链路层主动发起这个进程。
链路层在一个连接期间最多只能让一个LL_VERSION_IND PDU
进入发送队列。
如果链路层在之前没有发送LL_VERSION_IND PDU
的时候收到LL_VERSION_IND PDU
,则链路层需要发送一个LL_VERSION_IND PDU
给对端设备。如果链路层在收到LL_VERSION_IND PDU
之前已经发送来LL_VERSION_IND PDU
,则不需要再发送LL_VERSION_IND PDU
给到对端设备。
这个进程在收到来自对端设备的LL_VERSION_IND PDU
后完成。
5.1.6 终止ACL进程
这个进程用于在连接状态主动终止ACL连接。主动终止发生在Host请求链路层终止连接的时候。master或者slave的链路层都可以通过发送LL_TERMINATE_IND PDU
来发起这个进程。这个终止进程在丢失连接的事件中不能使用,例如,链路监控超时或者进程超时。
链路层需要在LL_TERMINATE_IND PDU
进入发送队列的时候启动定时器 Tterminate。发起的链路层需要发送LL_TERMINATE_IND PDUs
直到收到应答或Tterminate定时器超时,这个时候需要退出连接状态进入待机状态。
Tterminate的初始值需要设置为connSupervisionTimeout
的值。
当链路层收到LL_TERMINATE_IND PDU
,需要发送应答,并退出连接状态进入待机状态。
一旦链路层接收到或发送队列中有LL_TERMINATE_IND PDU,则所有相关的CISes需要视为丢失(见Section 4.5.12
)。链路层不能在Host请求终止时单独发送LL_CIS_TERMINATE_IND PDUs
。
这个进程在收到应答或者Tterminate超时时完成。
5.1.7 连接参数请求进程
master或者slave可以发起连接参数请求进程,请求远端设备在进入连接状态以后任意时间更新连接的链路层参数(connInterval,connSlaveLatency 和 connSupervisionTimeout
)。
5.1.7.1 发出LL_CONNECTION_PARAM_REQ PDU
连接参数请求进行进程可以通过发送LL_CONNECTION_PARAM_REQ PDU
,可以通过Host发起的连接更新进程(见Vol 4 Part E,Section 7.8.18
)或链路层主动的来发起这个进程(也就是说,不需要Host进行请求)。
如果LL_CONNECTION_PARAM_REQ PDU
由Host发起的连接更新进程的slave的链路层发起并且master不支持这个进程,则需要使用ErrorCode
设置为Unsupported Remote Feature / Unsupported LMP Feature (0x1A)
来通知Host连接更新进程已经完成。
如果链路层作为Host发起的连接更新进程的结果来发起这个进程,则链路层:
- 需要设置
Interval_Min,Interval_Max,Timeout 和 Latency
字段为从Host接收到的值。
注意:链路层可以更改这些字段的值,比如,由于从master接收到的值会阻止链路层满足另一个网络的要求。 - 可以通过设置
PreferredPeriodicity
字段为非0的值来指示首选周期,如Section 2.4.2.16
所述。 - 可以设置
Offset0
到Offset5
字段为非0xFFFF的值,如Section 2.4.2.16
所述。如果一个或多个Offset0 到 Offset5
字段已经设置,则:ReferenceConnEventCount
字段需要设置用来指示Offset0 到 Offset5
字段至少一个时有效的,如果ReferenceConnEventCount
设置了,那么从PDU的第一次传输开始,它必须始终设置为将来小于32767个连接事件的连接事件的connEventCount
。
注意:重发PDU并被远端设备接收成功时,可能导致ReferenceConnEventCount
达到32767个事件。见Section 5.1.7.3.2
示例如何设置ReferenceConnEventCount
字段。- 如果
Interval_Min
不等于Interval_Max
,则PerferredPeriodicity
字段需要设置为非0的值。如果Interval_Min
等于Interval_Max
,则PerferredPeriodicity
字段需要设置为任意值并且接收者需要进行忽略。
如果链路层主动发起这个进程,则Latency
字段需要设置为connSlaveLatency
的当前值,Timeout
字段(单位为ms)需要设置为connSupervisionTimeout
的当前值。其他的任意字段(Interval_Min, Interval_Max, PreferredPeriodicity, ReferenceConnEventCount 和 Offset0 to Offset5
)都可以在上述的限制条件下进行更改。
链路层需要确保LL_CONNECTION_PARAM_REQ
中的参数不能导致监控超时。也就是说,链路层需要确保Timeout
(单位为ms)大于 2 x Interval_Max * (Latency + 1)
。
5.1.7.2 响应LL_CONNECTION_PARAM_REQ 和 LL_CONNECTION_PARAM_RSP PDUs
接收到LL_CONNECTION_PARAM_REQ PDU
后:
- slave需要使用
LL_CONNECTION_PARAM_RSP PDU
或LL_REJECT_EXT_IND PDU
进行应答。 - master需要使用
LL_CONNECTION_UPDATE_IND PDU
或LL_REJECT_EXT_IND PDU
进行应答。
接收到LL_CONNECTION_PARAM_RSP PDU
后,master需要使用LL_CONNECTION_UPDATE_IND PDU
或 LL_REJECT_EXT_IND PDU
进行应答。
master不能发送LL_CONNECTION_PARAM_RSP PDU
,slave只有在响应LL_CONNECTION_PARAM_REQ PDU
的时候才能发送LL_CONNECTION_PARAM_RSP PDU
。
如果接收到包含了链路层不可接受的参数的LL_CONNECTION_PARAM_REQ PDU
,则链路层需要按照下面之一的方式应答LL_CONNECTION_PARAM_REQ PDU
:
- 包含可选参数的
LL_CONNECTION_PARAM_RSP PDU
(如果链路层是连接的master)或LL_CONNECTION_UPDATE_iND PDU
(如果链路层是连接的master)。 - 使用
ErrorCode
为Unsupported LL Parameter Value (0x20)
的LL_REJECT_EXT_IND PDU
。
如果接收到的LL_CONNECTION_PARAM_REQ PDU
包含任意超过有效范围的字段,则链路层需要通过发出ErrorCode
设置为Invalid LL Parameters (0x1E).
的LL_REJECT_EXT_iND PDU
来拒绝LL_CONNECTION_PARAM_REQ PDU
。
如果LL_REJECT_EXT_IND PDU
在链接参数请求进程中发出,则这个进程在设备收到LL_REJECT_EXT_IND PDU
后完成,在发出LL_REJECT_EXT_IND PDU
的设备端接收到LL_REJECT_EXT_IND PDU
的应答后完成。
如果收到的LL_CONNECTION_PARAM_REQ PDU
只请求更改LE 链接的锚点,则链路层无需将这个请求指示给Host。
如果收到的LL_CONNECTION_PARAM_REQ PDU
请求改变connInterval, connSlaveLatency, 和 connSupervisionTimeout
的一个或多个值,并且链路层选择的这些值,分别在本地Host提供的对应的值的范围内,则链路层可能选择不提示Host这个请求并继续运行就像Host已经接受了远端设备的请求,否则不能屏蔽给到Host的事件,链路层需要通知这个请求给到Host。
如果本地Host没有提供connInterval, connSlaveLatency, 和 connSupervisionTimeout
的值的范围给到slave的链路层,则slave的链路层在收到请求的时候,如果Host没有屏蔽,需要将这个请求提示给Host。
如果请求被发送给Host并且给到Host的事件被屏蔽,则链路层需要发送ErrorCode
为Unsupported Remote Feature / Unsupported LMP Feature (0x1A)
的LL_REJECT_EXT_IND PDU
。
注意:设备可能是临时发出LL_REJECT_EXT_IND PDU
,因此发起设备可以进行重试。
注意:如果请求没有发送给Host,则事件是否被屏蔽可以忽略。
如果请求被指示给Host,Host需要接受或者拒绝这个请求。如果Host拒绝了这个请求,则设备需要发送ErrorCode
为Unacceptable Connection Parameters (0x3B)
的LL_REJECT_EXT_IND PDU
。
如果Host接受了请求或者请求没有被指示给Host:
- slave需要使用
LL_CONNECTION_PARAM_RSP PDU
来应答LL_CONNECTION_PARAM_REQ PDU
。LL_CONNECTION_PARAM_RSP PDU
各个字段的填充规则与LL_CONNECTION_PARAM_REQ PDU
各个字段的填充规则相同,如Section 5.1.7.1
所述。在master的链路层上处理接收LL_CONNECTION_PARAM_RSP PDU
的规则与本节前面描述的处理接收LL_CONNECTION_PARAM_REQ PDU
的规则相同。
master需要使用LL_CONNECTION_UNPDATE_IND PDU
来应答LL_CONNECTION_PARAM_REQ 或 LL_CONNECTION_PARAM_RSP PDU
。如果slave已经设置了LL_CONNECTION_PARAM_REQ 或 LL_CONNECTION_PARAM_RSP PDU
的PreferredPeriodicitiy
字段,master需要选择PreferredPeriodicitiy
的整数倍的间隔的值。但是如果当前PHY为LE Coded PHY并且Controller支持 LE 数据包长度扩展特性,则新的链接间隔需要最小设置为connIntervalCodedMin us
。master需要尝试选择WinOffset
和WinSize
的值以便于新链接事件的时间匹配slave发出的LL_CONNECTION_PARAM_REQ 或 LL_CONNECTION_PARAM_RSP PDU
的Offset0 到 Offset5
字段中的一个。LL_CONNECTION_UPDATE_IND PDU
的Instant
字段的设置如Section 5.1.1
。
一旦master发出LL_CONNECTION_UPDATE_IND PDU
,链接参数如Section 5.1.1
所描述的进行更新。
这个进程在instant
通过并且新的链接事件参数应用以后完成。
5.1.7.3 示例
5.1.7.3.1 slave发起锚点移动
下面示例展示了slave的链路层请求LE链接的链路层更改3.75ms。
slave的链路层发出带有以下参数的LL_CONNECTION_PARAM_REQ PDU
:
Interval_Min: connInterval
Interval_Max: connInterval
Latency: connSlaveLatency
Timeout: connSupervisionTimeout
PreferredPeriodicity: 0
ReferenceConnEventCount : 未来小于32767个连接事件的任何值
Offset0: 0x0003
Offset1: 0xFFFF
Offset2: 0xFFFF
Offset3: 0xFFFF
Offset4: 0xFFFF
Offset5: 0xFFFF
如果master的链路层接受了slave的请求,则它可以使用包含下面任意参数集合的LL_CONNECTION_UPDATE_IND PDU
进行应答。在所有集合中,interval
设置为connInterval
,Latency
设置为connSlaveLatency
,Timeout
设置为connSupervisionTimeout
,Instant
设置为未来小于32767个链接事件的任意值
。
- 选项1:master在
Instant
后发送的第一个数据包在传输窗口开始之后的3.75ms。- 3≤WiSize≤8
- WinOffset : 0
- 选项2:master在
Instant
后发送的第一个数据包在传输窗口开始之后的2.5ms。- 2≤WiSize≤8
- WinOffset : 1
- 选项3:master在
Instant
后发送的第一个数据包在传输窗口开始之后的1.25ms。- 1≤WiSize≤8
- WinOffset : 2
- 选项4:master在
Instant
后发送的第一个数据包在传输窗口开始之后的0ms。- 1≤WiSize≤8
- WinOffset : 3
5.1.7.3.2 ReferenceConnEventCount
图5.2 和 图 5.3展示了如何使用LL_CONNECTION_PARAM_REQ 和 LL_CONNECTION_PARAM_RSP PDU
的ReferenceConnEventCount 和 Offset0到Offset5
字段来指示使用新的链接参数的链接的锚点的可能位置。这个图只简单的展示了Offset0,没有用到Offset1到Offset5,这个图同样展示了更新连接参数应用的Instant
。实际的Instant
发生在使用旧连接参数传输的最后一个连接事件之后的connIntervalOLD,而LL_CONNECTION_UPDATE_IND PDU
中的Instant
字段被设置为使用旧连接参数传输的链接事件的connEventCount
。
ReferenceConnEventCount
被设置旧链接参数上的连接事件的connEventCount
,以便新链接参数上的下一个连接事件的开始距离ReferenceConnEventCount
链接事件的偏移为Offset0
。
图5.2展示了Instant
在ReferenceConnEventCount
之前的情况,图5.3展示了Instant
在ReferenceConnEventCount
之后的情况。想象使用就连接参数发送的连接事件已经超过了Instant
的范围,想象使用新链接参数的链接事件在Instant
之前。
在图5.2和5.3中,从Instant
到使用新的连接参数发送的第一个链接事件的开始之间的时间间隔Δt
可以用下面的方式计算:
注意:ReferenceConnEventCount
和 Instant
位于eventCount
环绕点的两侧的情况没有展示在上面的方程中。
基于计算出的Δt
,可以相应的设置LL_CONNECTION_UPDATE_IND PDU
的WinOffset
和 WinSize
字段。示例见Section 5.1.7.3.3
5.1.7.3.3 slave发起链接间隔和锚点移动
下面示例展示了slave的链路层请求改改链接间隔(通过指定一个PreferredPeriodicity
使得PreferredPeriodicity
和connIntervalOLD不是彼此的整数倍)和相对于ReferenceConnEventCount的LE连接的锚点变化3.75ms。
在这个示例中,connIntervalOLD为 0x0C(15 ms
),slave的链路层使用下面的参数发出LL_CONNECTION_PARAM_REQ PDU
:
Interval_Min: 0x16
Interval_Max: 0x20
Latency: connSlaveLatency
Timeout: connSupervisionTimeout
PreferredPeriodicity: 0x0A
ReferenceConnEventCount : 0x1F00
Offset0: 0x0003
Offset1: 0xFFFF
Offset2: 0xFFFF
Offset3: 0xFFFF
Offset4: 0xFFFF
Offset5: 0xFFFF
如果master的链路层接受了slave的请求,则它可以使用包含下面任意参数集合的LL_CONNECTION_UPDATE_IND PDU
进行应答。在所有集合中,新的链接间隔connIntervalNEW设置为 0x1E(37.5ms),Latency
设置为connSlaveLatency
,Timeout设置为connSupervisionTimeout
并且Instant
设置为0x1F06。
- 选项1:master在
Instant
后发送的第一个数据包在传输窗口开始之后的3.75ms。- 3≤WiSize≤8
- WinOffset : 18
- 选项2:master在
Instant
后发送的第一个数据包在传输窗口开始之后的2.5ms。- 2≤WiSize≤8
- WinOffset : 19
- 选项3:master在
Instant
后发送的第一个数据包在传输窗口开始之后的1.25ms。- 1≤WiSize≤8
- WinOffset : 20
- 选项4:master在
Instant
后发送的第一个数据包在传输窗口开始之后的0ms。- 1≤WiSize≤8
- WinOffset : 21
5.1.7.4 数据包传输时间限制
本章节仅适用于当前PHY为LE Coded PHY并且Controller支持LE数据包长度扩展特性。
在收到或发出减小链接间隔的LL_CONNECTION_UPDATE_IND PDU
以后,直到达到instant
之前,链路层不能发送将会花费超过connEffectiveMaxTxTime ms
时间来发送的数据包,在instant
之后使用计算出的链接间隔。
如果slave发送一个Interval_Min
小于当前链接间隔的LL_CONNECTION_PARAM_REQ 或 LL_CONNECTION_PARAM_RSP PDU
,直到它收到LL_CONNECTION_UPDATE_IND , LL_UNKNOW_RSP或LL_REJECT_EXT_IND PDU
作为应答之前,链路层不能发送将会花费超过connEffectiveMaxTxTime ms
时间来发送的数据包,计算出的连接间隔根据发送的PDU的Interval_Min
的值来确定。
如果connEffectiveMaxTxTime
的值在进程期间发生了改变,则上面的要求适用于LL Data PDU
进入到发送队列时的值。
注意:本章的要求为Section 4.5.10
的附加,而不是覆盖。
注意:如果链路层在进程开始的时候或者在进程中缓存了任意LL Data PDUs
,可能需要重新整理这些PDU,以满足这些要求。
5.1.8 LE Ping进程
支持LE PING
进程时,可以用来在链路层验证对端链路层的存在。这个进程同样可以通过强制对端设备发送包含合法MIC的LE ACL包来验证LE ACL逻辑传输上的消息完整性。
这个进程可以在对端链路层不支持的情况下使用。
master或slave的链路层可以在进入链接状态以后的任意时间发送LL_PING_REQ PDU
来发起这个进程,应答的链路层使用LL_PING_RSP PDU
进行应答。
支持这个特性的链路层在对端设备在Host设置的认证有效载荷超时时间内没有发出包含使用MIC保护的载荷(Vol 4 Part E,Section 7.3.94
)的数据包时需要发送LL_PING_REQ PDU
。链路层应该在认证有效负载超时到期之前提前发送一个LL_PING_REQ PDU
,以保证远程设备在超时到期之前用LL_PING_RSP PDU
进行响应的合理时间。
这个进程在收到LL_PING_RSP
的时候完成。
5.1.9 数据长度更新进程
Controller使用数据长度更新进程来发送当前接收的LL Data PDU Payload length 和 PDU Time (connMaxRxOctets 和connMaxRxTime)
和当前发送的 LL Data PDU Payload length and PDU Time (connMaxTxOctets and connMaxTxTime)
的最大值的最新的值给到对端设备。
master或slave的链路层可以在进入链接状态以后的任意时间发送LL_LENGTH_REQ PDU
来发起这个进程,在这些参数发生改变时,无论是链路层主动更改还是由Host请求更高,都需要由链路层发起此过程。但是如果这个进程已经由对端设备的Controller发起并且本地设备的Controller还没有进行应答,则可以使用应答代替重新发起这个进程来传输这个改变。
如果链路层接收到LL_LENGTH_REQ
或这对LL_LENGTH_REQ
的应答LL_LENGTH_RSP PDU
,则需要使用PDU中的值更新链接中的connRemoteMaxTxOctets, connRemoteMaxRxOctets, connRemoteMaxTxTime 和 connRemoteMaxRxTime
。它需要立即使用更新后的值发送传输队列中的新LL Data PDUs
,包括下一段中提到的任意应答。已在传输队列中的或至少发送一次的任意LL Data PDUs
的数据长度不能进行改变。
注意:由于链路层PDUs没有要求实时处理,是有可能出现本地Controller已经将LL_LENGTH_REQ PDU
放入发送队列但是没有发送的时候,收到对端设备的LL_LENGTH_REQ PDU
,这种情况下,每个设备正常进行应答,由此产生的冲突是无影响的。
一旦收到LL_LENGTH_REQ PDU
,链路层需要使用包含链接中它的connMaxTxOctets, connMaxRxOctets, connMaxTxTime 和 connMaxRxTime
参数的LL_LENGTH_RSP PDU
进行应答。
如果对端设备不支持LE Coded PHY
特性,则LL_LENGTH_REQ
和LL_LENGTH_RSP PDU
中的MaxRxTime
和MaxTxTime
字段需要设置为小于等于2128us的值。
5.1.10 PHY更新进程
当支持PHY更新进程时,用来改变ACL链接的发送或接收或者全部的PHYs。它不影响任意关联的同步连接流的发送或接收PHY。这个进程可以由链路层主动发起或者Host进行请求。master或slave可以在进入链接态的任意时间发起这个进程。链路层的PHY选择可以在链接中或者链接之间进行改变,因此对端设备不能缓存这个参数。
当这个进程由master发起时,master发送LL_PHY_REQ PDU
,slave使用LL_PHY_RSP PDU
进行应答,然后master使用LL_PHY_UPDATE_IND PDU
进行应答。
当这个进程由slave发起时,slave发送LL_PHY_REQ PDU
,然后master使用LL_PHY_UPDATE_IND PDU
进行应答。
LL_PHY_REQ 和 LL_PHY_RSP PDU
的TX_PHYS 和 RX_PHYS
字段用于指示发送者的链路层建议选择的值。如果发送者想要一个均衡的链接,则需要设置所有字段都同样的值,并且只指定一个单独的PHY。
LL_PHY_UPDATE_IND PDU
的M_TO_S_PHY 和 S_TO_M_PHY
字段指示instant
之后首先使用的PHYs。
如果master发起这个进程,需要根据LL_PHY_REQ 和 LL_PHY_RSP PDUs
的内容使用下面的规则确定在不同方向上的PHY:
LL_PHY_UPDATE_IND PDU
的M_TO_S_PHY
字段需要由master的TX_PHYs
字段和slave的RX_PHYs
字段决定。LL_PHY_UPDATE_IND PDU
的S_TO_M_PHY
字段需要由master的RX_PHYs
字段和slave的TX_PHYs
字段决定。
上面的每种情况下,使用下面的规则:
- 如果TX_PHYS和RX_PHYS字段至少一个对应的PHY位设置为1,master可以在这个方向上选择PHYs中任意的一个。
- 如果TX_PHYS和RX_PHYS字段没有对应的PHY位设置为1,master不能改变这个方向上的PHY。
如果slave发起这个进程,master需要根据LL_PHY_REQ 和 LL_PHY_RSP PDUs
的内容使用下面的规则确定在不同方向上的PHY:
LL_PHY_UPDATE_IND PDU
的M_TO_S_PHY
字段需要由slave的PDU的RX_PHYs
字段决定。LL_PHY_UPDATE_IND PDU
的S_TO_M_PHY
字段需要由slave的PDU的TX_PHYs
字段决定。
上面的每种情况下,使用下面的规则: