zoukankan      html  css  js  c++  java
  • 蓝牙LMP概述

    LMP 全称是Link Manager Protocol,我们还是要一张图,说明LMP 在哪里?

    他是在HCI 以下,baseband 以上,实现在蓝牙控制器中。

     按照协议规范,我们分几个部分来分别介绍LMP

    1. introduction
    2. general rules
    3. device features
    4. procedure rules

    下面我们先来看看 整体的介绍部分:

    Introduction

    LMP是用来控制和协商两个设备连接行为的协议,涉及的方面包括逻辑传输连接的建立和控制,以及对于物理链路的控制等等,它是两个设备的LMP模块之前的交流,其消息是传输在ACL-C 的逻辑链路上,对于这一点,我们在baseband的概述中已经提过:

    这里需要注意的一点是,LMP 是实现在控制器里面,其消息并不会经过HCI 接口传输到HOST 端,其架构如下图:

    我们可以看到其是 两个设备的LMP 模块之前的通信。

    General rules

     2.1 Message Transport

     这里描述的就是三个点:

    1. LMP的消息的交互是传输在ACL-C 逻辑链路上的,他和ACL-U的区别是通过LLID 来区分的。
    2. ACL-C有更高的优先级,一般控制信号都会有较高的优先级
    3. LMP消息本身没有携带额外的数据错误检测的信息

    2.2 Synchronization

       LMP 传输在ACL-C的逻辑链路上面,但这并不能保证传输的时间的以及对方ack的及时性。

     2.3Packet Format

     LMP 的数据包的格式有两种,一种是7bit的opcode,另外一种是15bit的opcode

    我们发现除了opcode,在最低位还有一个TID,他是transtransaction ID,当它是0 的时候,说明这个LMP message是 master 发起的,当它是1的是时候说明是slave 发起的。

    上图中是 header的最低位是0,代表是Transaction ID Initiated by master。

    2.4Transactions

     transaction 就是一次完整的打成某种目的的传输。所有属于同一个transaction 的单次传输的transaction ID 都是想同的。

    比如下面:

    LMP version exchange 的Transaction ID 都是 Initiated by slave

    另外LMP_setup_complete 是一个 独立PDU,它自己形成一个transaction,

     

    上面两个OpCode LMP_setup_complete 的transaction ID 是不同的,他们是独立的PDU

    LMP response的timeout 时间是30s

     2.5ERROR HANDLING

    关于出错处理,每一个错误都分配了一个错误码,常见的错误如下:

    1. Unknown opcode(0x19)
    2. Invalid parameters(0x1E)
    3. PDU is not allowed(0x24)
    4. PDU not supported(0x1A)
    5. Transaction Collision / LL Procedure Collision(0x23)
    6. Different Transaction Collision(0x2A)

    2.6GENERAL RESPONSE MESSAGES

     general response  在很多的procedure中,被用来对于各种流程的应答消息,如果opcode是7bit,那么应该使用前两种 PDU,如果opcode 是15bit,那么应答的PDU 应该使用后两种。

    DEVICE FEATURES

    device feature,顾名思义,这里面定义了很多的设备的特性,并且这些特定是可以用特定的LMP message 来获取的。那么这些feature 是如何传输的呢?其实就是定义了一些bit 位来代表相应的feature,当这些位被设置为1的时候,就说明支持该feature,这个我们在程序代码实现中经常见到这样的技巧。

     这些feature 定义在两个page 上面,page1 里面使用8个字节,64bit 定义了64个feature,page2用2个字节定义了12个feature,其中包括2个reserved 位。

    这里简单列举几个feature:

     PROCEDURE RULES

     这里包含了很多的基本流程,主要有如下的项目:

    1. Connection control

    2. Information Requests
    3. Role Switch
    4. Modes of Operation
    5. Logical Transports

     我们下面分别看看这几个流程:

    4.1Connection control 

    这里每一个流程都有很多的子流程,这里只简单介绍下Connection establishment和Detach的流程:

    下面先看一下Connection establishment的流程图

    在经过了page的流程之后,可能的行为是请求时钟的偏移量,LMP的版本,对端支持的feature请求,对端的name请求,以及可能的deteach行为。

    之后如果要建立连接的话,paging的设备就会发送LMP_host_connection_req,对端如果同意建立连接就会回复LMP_accepted 否则就是LMP_not_accepted

    后续可能走得关于认证和加密的流程,最后是LMP_setup_complete,下面我们来看一个例子:

     下面的建立连接的PDU:

     下面我们看看detach 的流程:

    我们发现关于detach 是没有LMP response 的消息的过来的,从实际的air log 中,也的确没有detach response 回复,对端设置只会简单的ack 该 消息:

    下面我们看看 从设备的host 端 去断开对端设备的 LMP 与HCI 的message 流向:

    我们发现是 A设备再收到了对端的ACK 之后就会向host 端上传断开完成事件。

    关于 验证和加密的部分,会在分析配对的文章中专门讲述。

    下面我们我们看看

    4.2Information Requests

     这一类的message 交互都是 信息请求类型的,具体的有如下几种:

    1. Timing accuracy

    2. Clock offset
    3. LMP version
    4. Supported features
    5. Name request

    这几个流程也是非常的类型,我们也是挑选其中一个来 看一下:

    我们看看lmp version 的流程:

    其交互流程很简单,发起端发起一个LMP_version_req,对端回应一个LMP_version_res

    涉及到的PDU的包如下:

    这里我们发现,发起这个LMP version请求的时候,还会携带本端的LMP version,Company ID 以及Sub Version Number,这个Sub Version Number 应该是公司内部的编号了,那这样一来,一个request,一个response,就完成了LMP 相关版本信息的交互。我们看看air log 关于这交互的消息:

    response 如下:

     这里需要提一点就是LMP 数据包的payload header 里面也是有流控相关的,但是这个流控对于LMP 是不起作用的。其应该是主要针对ACL-U的数据。

    这里再简单名字的获取的流程,当没有建立物理link的时候,获取名字和已经建立了link的获取的名字的流程有点区别。我们先下有link的时候 流程:

    有link的时候,很简单,直接是在LMP 层进行LMP_name_req的交互,收到对方的应答之后,通过HCI接口上报的到host端,如果是没有link的话,那么是要先建立一个临时的link,其流程见下图:

    我们可以看到两个设备经过page 之后,会先进行LMP feature exchange以及extend feature exchange,然后上报到host 端,接下来才进行LMP_name_req 的交互,最后是detach 这个临时的link,

    我们看看 air log 中实际的交互情况:

    实际情况和上面的流程也是非常的吻合,最后会把这个 临时建立起来的获取名字的link断开。

    下面我们看看role switch 相关的

    4.3Role switch

     关于role switch ,因为我们平常在debug 中会遇到,值得仔细讲一下:

    role switch的执行需要符合几个条件:

    1. 设备要处于active mode
    2. 加密的流程被终止或者已经关闭
    3. 在当前的link上面,没有sco数据在传输
    4. 需要停掉当前link所有的ACL-U 数据流

    role switch 从字面含义上来看,非常的简单,就是交互角色,我们知道两个设备连接之后,一开始发起配对的那个设备在建立连接之后就是master,这样一种默认模式不能总是符合应用场景,所以经常在两个设备之后需要交互角色。

    role switch 是master 和slave 都可以发起的,我们先看一下,master 发起的角色交换的流程:

    LMP 层面的交互很简单,就三个指令。下面我们详细讲一下LMP_switch_req和LMP_slot_offset的 作用。

    我们看出 LMP_slot_offset 携带两个关键的信息,一个slot offset,另外一个 蓝牙设备地址。这个地址是当前 slave 地址,也是role switch 之后master的地址。这个slot offset 是干嘛的呢?

    这个在specification中原话是“The slot offset shall be the time in microseconds between the start of a master transmission in the current piconet to the start of the next following master transmission in the piconet where the BD_ADDR device (normally the slave) is master at the time that the request is interpreted by the BD_ADDR device.

     其含义就是,当前网络的master的开始传输的时机(时钟上升沿)到交换后的网络master 进行传输的时机(时钟上升沿)的时间间隔,次时间是用ms 来描述的。

     

    从这里,我们能够觉悟出,slot offset 应该都是由当前网络的slave(role switch 之后的master) 来发送,而不管是 哪一端的设备先发起的,下面我们看看slave 端发起的role switch的交互流程:

    我们发现,slot offset,的确是由slave端送出,之后才送出 LMP_switch_req,现在我们看看一下LMP_switch_req这个命令:

    我们可以设想一下,蓝牙设备之间的交互是要保持时钟同步的,否则就会“失去联系”,那么我们在进行role swtich 之后还是要保持时钟同步才能继续通信,那在什么样的时机进行role switch呢?

    我们先看下LMP_switch_req的参数:

     我们发现其有一个参数是 switch instant ,这就是 描述 具体在哪一个时间点进行TDD switch。

    这个instant 应该是一个未来的时间,如果是过去的时间,那么当接受者受到这个instant的时候,并不会接受这样的参数,会回复 LMP_not_accepted PDU with the error code Instant Passed (0x28)。

    当role switch 完成的时候,两个设备都要向各自的host 上报HCI_Role_Change event,如下图:

     Modes of Operation

     hold mode 很少遇到,这里主要讲一下 sniff mode ,

    sniff mode 就是呼吸模式,主要是为了省电而应用的,比如一些蓝牙设备,比如键盘鼠标,当他们在active mode的时候,每一个master to slave  slot,设备都要去监听master是否有数据发过来。而当他们不使用的时候,如果还是一直处于active mode 的话,那么这段时间的消耗的电量就浪费了,而进入到sniff mode 可以使得设备进入了类似睡眠的状态,只是定期去监听master 的封包,这样可以节省电量。

    我们先看看 进入sniff mode  的流程图:

    我们这里主要着眼于LMP层面,当host端有进入sniff mode的命令下来,那么控制器 将向对方发出LMP_sniff_req的请求,对方如果同意,那么回复LMP_accepted。因为这是一个协商的过程,上图只显示了一次协商的过程,其实可能存在有发多次的LMP_sniff_req的情况。现在我们看看 LMP_sniff_req的参数:

    Dsniff = Clock_Value (bits 26-1) mod Tsniff

    Tsniff  是 sniff interval,就是每次起来监听的时间间隔

    Tsniff 就是 相邻的两个sniff anchor point的时间间隔。

    sniff attempt 是 每次起来之后 尝试去监听的次数,如果监听了sniff  attempt 次数之后发现master 没有发数据过来,那么再次进入到睡眠的状态。

    sniff timeout 是 在slave 去监听master 的封包的时候,如果有封包发过来,那么就要继续监听额外的sniff timeout 个master to slave slot。

    我们这里说一下Sniff 第一个锚点的计算方法:Dsniff = Clock_Value (bits 26-1) mod Tsniff 

     这里Dsniff 和Tsniff  是参数已经给出的,那么就是根据上面的公式去反推第一个锚点的clk的值。我们这里举一个例子来说明:

    其当前的clk值是Clock[27-0] 0x04301E02  这里的Dsniff 的值是0,

    bit27  = 0,我们先看看当前的clk是0x04301E02,那么下一个锚点一定是 大于当前值而小于(0x04301E02+800*2)

    我们先看看当前的Clock_Value (bits 26-1) mod Tsniff  = (0x04301E02>>1)mod(800) = 737

    那么下一个锚点的clk = ((800-737)+ (0x04301E02>>1))*2 = 0x4301E80  

     那么关于LMP 的概述就先介绍到这里。 

  • 相关阅读:
    hdu 1455 N个短木棒 拼成长度相等的几根长木棒 (DFS)
    hdu 1181 以b开头m结尾的咒语 (DFS)
    hdu 1258 从n个数中找和为t的组合 (DFS)
    hdu 4707 仓鼠 记录深度 (BFS)
    LightOJ 1140 How Many Zeroes? (数位DP)
    HDU 3709 Balanced Number (数位DP)
    HDU 3652 B-number (数位DP)
    HDU 5900 QSC and Master (区间DP)
    HDU 5901 Count primes (模板题)
    CodeForces 712C Memory and De-Evolution (贪心+暴力)
  • 原文地址:https://www.cnblogs.com/libs-liu/p/9496440.html
Copyright © 2011-2022 走看看