当前位置:   article > 正文

BLE 技术(六)--- GATT Profile + ATT protocol + L2CAP(Core_v5.2)_ble generic attribute access

ble generic attribute access

前言

前篇博文Generic Access Profile介绍了蓝牙设备之间是如何发现彼此、建立连接、实现配对与绑定的,同时描述了设备如何实现无需连接的数据传输、如何实现等时同步数据传输、如何建立ACL和CIS 连接、如何加密认证通信链路等。

本篇文章主要介绍蓝牙设备建立连接后,如何提供或响应服务、如何发现或请求服务,这就要靠GATT(Generic Attribute Profile)来定义了,GATT 为蓝牙设备定义了Server role 和Client role 两种角色(角色并不固定在设备上,同一设备不同时刻充当的角色可能不同):

  • Server role:接收来自客户端的服务请求,并向客户端返回响应数据。GATT 中的角色与GAP 中的角色相互独立又相互兼容,GAP 中的Peripheral role 或Central role 都可以充当GATT 中的Server role;
  • Client role:向服务器发送服务请求,并接收来自服务器的响应数据。GATT 中的角色与GAP 中的角色相互独立又相互兼容,GAP 中的Peripheral role 或Central role 都可以充当GATT 中的Client role。

An example of a light state machine
Server 根据设计需求会实现并向外公开一个或多个服务,Client 则根据需要发现Server 公开的部分或全部服务。Client 发现Server 提供的服务后,就可以向其请求相应的服务数据(既可以读取服务器状态信息比如温度传感器的值,又可以改变服务器的状态比如控制LED灯的亮灭),Server 接收到服务请求后会向Client 响应对应的服务数据(Server 可能需要Client 通过认证与授权)。

BLE 采用“Server – Client” 架构,Server 专注于定义如何使用一个或多个属性来实现某种特定的服务(包括可以提供的状态信息、可以执行的状态切换等)以及如何访问并使用这些服务(比如客户端请求可读取/可写入状态信息、服务器可通知状态更新信息、访问服务是否需要加密/认证/授权等);Client 专注于定义如何使用一个或多个服务来满足某种特定的应用需求(比如可以使用光强感应服务、人体感应服务、照明服务等协同实现智能照明服务)。

Server 定义的每个单独服务十分简单、而且是原子化的(表示一种服务只执行不可分割的特定操作),可以让每个服务的行为更简单明确,同时让不同服务之间的组合更丰富多样。Client 使用不同的原子服务组合,可以满足丰富多样的场景需求,相同的服务可以在不同应用中复用,满足高内聚、低耦合的设计原则。

为何说明Client 请求服务、Server 响应服务的工作原理,下面扩展前篇博文谈到的用户场景:

用户购买的心率带设备为了安全传输心率数据,是可以被发现并连接的,对外公开的主要有心率服务、电池电量服务、设备名服务等。用户的智能手机通过GAP 规范发现并连接了心率带设备(可以通过公开的设备名服务从设备列表中选出目标设备),由于用户需求是获得心率值,心率带对外提供该服务,因此心率带处于Server role,智能手机处于Client role。

Client role 与Server role 建立连接后,Client role 首先需要知道Server role 能提供哪些服务,然后再根据应用规范去使用这些服务。Client role 发现Server role 公开服务的过程主要有四个:Primary Service Discovery(可以发现所有主要服务或者某一特定主要服务)、Relationship Discovery(该服务引用的其它服务)、Characteristic Discovery(可以发现所有特性或者某一特定特性)、Characteristic Descriptor Discovery。 智能手机先发现心率带公开的心率服务和电池电量服务,再发现心率服务引用的时间服务(Secondary Service),接着发现心率服务包含的HRM Characteristic(Heart Rate Measurement) 和BSL Characteristic(Body Sensor Location),最后发现HRM Characteristic 包含的CCCD(Client Characteristic Configuration Descriptor)。Heart Rate Service、Characteristic、Descriptor 之间的关系如下图示,每一行四个字段Handle、UUID、Permissions、Value 共同构成一个属性,Characteristic 与Descriptor 都是由一个或多个属性构成的。

Client role 已经发现了Server role 公开的所有Primary Service及其相关的Characteristic 和Descriptor,接下来看Client role 如何使用Server role 提供的服务。智能手机可通过特定APP向心率带发起服务请求读取心率值,心率带将当前采集到的心率值返回给智能手机(也可以配置为允许心率带主动通知智能手机当前的心率值),如果再为心率带增加时间服务,智能手机APP 就可以借助心率服务和时间服务为用户绘制心电图,并给出心率健康评估结果。Handle 0x0021 属性是Heart Rate Service 的declaration(声明服务类型为心率服务),Handle 0x0024 和0x002A 属性分别是HRM Characteristic 和BSL Characteristic 的declaration(声明特性性质为只读,特性数值属性句柄分别为0x0027和0x002C),Handle 0x0027 和0x002C 属性分别是HRM Characteristic 和BSL Characteristic 的Value(描述特性数值的表示格式,心率测量值单位bpm – beats per minute,身体测量位置为手指),Handle 0x0028 属性是HRM Characteristic 的Descriptor(客户端特性配置为启用通知,允许服务端主动通知客户端更新后的心率值)。

GATT Heart Rate Service

一、Generic Attribute Profile

GATT 使用属性协议定义了服务框架,方便Client 与Server 之间实现基于服务请求/响应的通信,简化了蓝牙设备应用程序的开发。一个服务通常包含多个属性,GATT 定义了如何使用属性协议来发现、读取、写入这些属性数据。
Protocol model
最上层的Application 应用层在Server 服务端主要是基于属性协议定义各种服务的GATT 规范,在Client 客户端主要是定义如何发现并使用这些服务来满足某种特定的应用需求或实现某种特定的业务逻辑,本文主要介绍如何定义、发现、使用服务的GATT 规范。Attribute protocol 相当于GATT 的承载层,GATT 定义的服务是由多个属性组成的,Attribute protocol 定义了属性的报文格式和支持的操作方法。L2CAP 逻辑链路控制适配协议定义了报文的分片重组、重传流控,上层GATT 或Attribute protocol 层数据封装为SDU(Service Data Unit),下层Controller 数据封装为PDU(Protocol Data Unit)。

1.1 UUID and Attributes

在继续介绍GATT Profile 之前,先介绍一个蓝牙协议中比较重要的两个概念UUID(Universally Unique Identifier) 和Attributes。

1.1.1 UUID

UUID(Universally Unique Identifier) 通用唯一识别码是一个128位(16字节)的数字,可以保证在所有空间和所有时间都是唯一的。除了蓝牙之外,UUID 还用于许多协议和应用中(特别是分布式计算领域),它们的格式、用法在IETF(Internet Engineering Task Force)公布的标准 RFC 4122 中定义(技术上等同于 ITU-T Rec. X.667 | ISO / IEC 9834-8:2005 规范)。

完整的UUID 需要占用16字节,这对于链路层27字节的有效数据载荷长度算是不小的负担,为了减轻存储、传输128位UUID 的负担,BLE 规范添加了两个附加的UUID 格式:16位UUID 和32位UUID。这些16位或32位的UUID 可以看作是基于Bluetooth Base UUID (00000000-0000-1000-8000-00805F9B34FB) 的偏移量,因此只能与Bluetooth 规范中定义的UUID 一起使用,也可以称为标准Bluetooth UUID。这些标准Bluetooth UUID 可以借助Bluetooth Base UUID 重建为完整的128位UUID,只需要经过如下的运算即可:

128_bit_value = 16_bit_value * 296 + Bluetooth_Base_UUID
128_bit_value = 32_bit_value * 296 + Bluetooth_Base_UUID

16位UUID 可以通过高位补零转换为32位UUID 格式,当UUID 包含在ATT PDU 中时,所有32位UUID 都应转换为128位UUID。

16位UUID 虽然已经比较简短了,为了增加可读性,通常不直接使用数值,而是起一个名称并加上书名号来表示,比如用《Include》 来表示数值为0x2802 的UUID。UUID 并没有定义自身的用法,为了增加人工调试时的可读性,BLE 常用的那部分UUID 被分为以下几组:

  • 0x1800 ~ 0x26FF 用作 Service UUIDs
  • 0x2700 ~ 0x27FF 用于标识计量单位 Units
  • 0x2800 ~ 0x28FF 用于区分 Attribute Types
  • 0x2900 ~ 0x29FF 用作 Characteristic Descriptors
  • 0x2A00 ~ 0x7FFF 用于区分 Characteristic Types

1.1.2 Attributes

Attribute 是ATT(Attribute protocol)定义的最小数据实体,也是构成GATT 中Service、Characteristic、Descriptor 的基本元素。每个Attribute 都包含有关属性本身的信息和实际数据,客户端与服务器之间进行的服务交互,最终都是对这些属性的操作访问。从前文GATT Heart Rate Service 图示了解到,Attribute 由Handle、UUID、Permissions、Value 四部分构成,其逻辑表示如下:
Logical attribute representation

  • Attribute handle:属性句柄是特定GATT服务器上每个属性的唯一16位标识符,便于区分并寻址某个属性。有效的句柄范围是0x0001 ~ 0xFFFF,可以把属性句柄看作该属性资源的内存地址或者指向该属性资源的指针;
  • Attribute type:使用UUID 区分并标识每种属性的类型,比如温度、压强、体积、距离、功率、时间、充电状态、开关状态等可公开数据的类型,属性协议为每种类型都分配了一个UUID(16位标准Bluetooth UUID 或完整的128位UUID);
  • Attribute value:表示设备公开的状态信息,可以是固定长度或可变长度的八位字节数组,最大长度为512字节。属性值字段不仅可以表示状态信息,还对上层的GATT Profile 层级结构的定义有重要作用,比如定义Service 声明的属性值为Service UUID、Characteristic 声明的属性值为<Characteristic Properties | Characteristic Value Attribute Handle | Characteristic UUID>;
  • Attribute permissions:表示每个属性的访问限制或许可,属性限制可分为四个类型:Readable / writable 的访问权限、Encryption / No encryption required 的加密权限、Authentication / No Authentication required 的认证权限、Authorization / No Authorization required 的授权权限等,也可以使用上述多个类型的组合权限。

下面给出某BLE 设备属性服务器定义的部分属性供参考,支持的服务属性包括:GAP Service、GATT Service、Battery State Service、Thermometer Humidity Service、Weight Service、Position Service、Alert Service、Manufacturer Service和Vendor Specific Service等(下图用《》括起来的名字是UUID 的另一种表示方式,Attribute Value 中被{ } 括起来的部分表示该属性值由多个字段组成,被“ ” 括起来的部分表示字符串)。
Examples of attribute server attributes

1.2 GATT Profile hierarchy

GATT 中定义了的Profile 由一个或多个Service 组成,每个Service 可以看作是完成特定功能或特性的数据和相关行为的集合,由一个或多个Characteristic 构成。每个Characteristic 一般都包含一个数据或者一个公开行为,以及该数据的单位或者公开行为的单位。GATT Profile 的数据层级结构如下图示:
GATT Profile hierarchy

  • Service:完成特定功能或特性的数据和相关行为的集合,由一个或多个Characteristic 构成。可分为Primary Service 和Secondary Service 两种类型:Primary Service 是公开此设备主要可用功能的服务(主要服务类型的16位UUID 值0x2800);Secondary Service 是为设备提供额外辅助信息,但跟设备公开的功能无关的服务,一般被包含在主要服务或另一个辅助服务中(辅助服务类型的16位UUID 值0x2801)。Service declaration 属性访问权限为只读且不需要认证授权,属性值为具体的服务种类,比如Heart Rate Service 的16为UUID 值为0x180D;
    Service declaration
  • Include Service:将服务器上存在的另一种服务定义引用到要定义的服务中,是一种重用其它服务的方法。当某一个服务被包含到当前服务中,当前服务就可以使用被包含服务定义的数据和行为,但不能更改被包含服务的数据和行为。Include declaration 的属性值包含三个字段:被包含服务声明的属性句柄、被包含服务属性组合中的最后一个属性句柄、被包含服务的UUID,比如前面给出的示例属性列表中的《Include》属性值为{0x0500, 0x0504, «Manufacturer Service»};
    Include declaration
  • Characteristic:包含服务中使用的数据信息,包括如何访问该数据的属性方法、如何表示或显示该数据的格式信息等。Characteristic declaration 属性值也包括三个字段:特征访问方法、特征值属性句柄、特征的UUID,比如本文开头Heart Rate Service 中的HRM Characteristic declaration 的属性值为{Notify, 0x0027, 0x2A37},其中0x2A37 是Heart Rate Measurement 的16位UUID;
    Characteristic declaration
  • Characteristic Properties:包含当前Characteristic 支持的访问方法信息,支持的特征访问方法有Broadcast、Read、Write、Notify、Indicate、Authenticated Signed Writes等,比如本文开头Heart Rate Service 中的HRM Characteristic Properties 为Notify,BSL Characteristic Properties 为Read;
    Characteristic Properties bit field
  • Characteristic Value:包含当前Characteristic 定义的数据数值信息,比如本文开头Heart Rate Service 中的HRM Characteristic Value declaration 的属性类型为Heart Rate Measurement 的UUID也即0x2A37,属性值为实际测得的心率值;
    Characteristic Value declaration
  • Characteristic Descriptor:包含当前Characteristic 的描述信息、配置信息、表示格式信息等,比如本文开头Heart Rate Service 中的HRM Characteristic 包含了一个CCCD(Client Characteristic Configuration Descriptor),该CCCD declaration 的属性访问权限为可读写,属性值为0x0001,也即Bit Number 0 位Notification被置 1,表示为HRM Characteristic 启用通知功能,Server 心率带测量到的心率值以通知形式主动发送给Client 智能手机;
    Characteristic descriptor declarations

上述介绍的构成GATT Profile 的Service、Include Service、Characteristic、Characteristic Descriptor 等元素的属性汇总如下:
Summary of GATT Profile attribute types

1.3 GATT feature and procedure

前面介绍了如何使用Attribute 构成GATT Profile 数据层级结构,这里介绍如何使用Attribute protocol 来完成GATT Profile 定义的各种功能。GATT Profile 主要定义了如下11 个功能(feature),每个功能都映射到过程(procedure)和子过程(sub-procedure),这些过程和子过程描述了如何使用Attribute protocol 来完成相应的功能(下表中的M:Mandatory,O:Optional )。
GATT feature mapping to procedures

  • Server Configuration:Client 使用Exchange MTU (Maximum Transmission Unit) 过程与Server 交换双方支持的MTU,仅当Client 或Server 可以处理的MTU 超过默认值23 字节(LE 链路层支持的普通报文payload 为27 字节,L2CAP Header 占用4 字节,所以ATT_MTU 默认为23 字节)时才会使用该过程(该过程对连接双方都是可选的);
    Exchange MTU
  • Primary / Include Service Discovery:Client 使用Discover All Primary Services 或Discover Primary Services By Service UUID 子过程发现Server 公开的主要服务(可以发现所有主要服务或通过UUID 发现某个特定主要服务)。待Client 发现主要服务后,可以通过Find Included Services 过程发现该主要服务所包含的其它服务,两个过程可以让Client 了解Server 公开的所有主要服务与辅助服务;
    Discover All Primary and Include Service
  • Characteristic / Descriptor Discovery:Client 使用Discover All Characteristic of a Service 或Discover Characteristic by UUID 子过程发现Server 公开的某服务的Characteristic(可以发现某服务包含的所有Characteristic或者通过UUID 发现某个特定的Characteristic,通过UUID 发现某个特征实际上是发现所有特征后丢弃掉与UUID 不匹配的结果)。待Client 发现Characteristic 后,可以通过Discover All Characteristic Descriptors 过程发现该Characteristic 包含的所有Descriptors。Characteristic 和Characteristic Descriptors 是构成Service 的基本元素,也是读写Server 公开数据或状态信息的载体;
    Discover All Characteristic and Characteristic Descriptors
  • Characteristic Value Read:当Client 知道想要读取的某个Characteristic 的特征值属性句柄时,使用Read Characteristic Value 子过程从Server 读取该特征值,如果Server 响应的特征值长度大于(ATT_MTU - 1)字节则只能返回特征值的前半部分,Client 可以使用Read Long Characteristic Values 子过程读取完整的特征值。当Client 知道想要读取的一组特征值句柄集时,可以使用Read Multiple Characteristic Values 子过程读取该组的多个特征值。当Client 只知道想要读取的特征类型UUID 而不知道特征值句柄时,可以使用Read Using Characteristic UUID 子过程读取已发现该特征类型的所有特征值;
    Read Characteristic Value
  • Characteristic Value Write:当Client 知道想要写入的某个Characteristic 的特征值属性句柄时,使用Write Characteristic Value 子过程向Server 写入一个特征值,如果要写入的特征值长度大于 (ATT_MTU – 3) 字节则应使用Write Long Characteristic Values 子过程向Server 写入一个比较长的完整特征值。当Client 不需要确认写入是否成功执行时,可以使用Write Without Response 子过程向Server 写入特征值,该过程可以即时发送而不受流控约束,若Server 无法处理则静默丢弃。当Client 需要在单个操作中按顺序写入多个值时,可以使用Characteristic Value Reliable Writes 子过程向Server 传输要准备写入的多个特征值,待Client 验证服务器响应的数据无误后,对已传输到Server 上且经过检验的全部特征值执行写入操作;
    Write Characteristic Value
  • Characteristic Descriptor Value Read / Write:Client 读取或写入Characteristic Descriptor Value 跟前面介绍的读取或写入Characteristic Value 类似,当Client 知道想要读取或写入的Characteristic Descriptor 属性句柄时,使用Read Characteristic Descriptors 或Write Characteristic Descriptors 子过程从Server 读取或向Server 写入特征描述符。如果特征描述符的长度大于单个请求报文容纳的上限,Client 可以使用Read Long Characteristic Descriptors 或Write Long Characteristic Descriptors 子过程从Server 读取或向Server 写入比较长的完整特征描述符;
    Characteristic Descriptor Value Read / Write
  • Characteristic Value Notifications:当Server 被配置为向Client 通知特征值,且不需要确认是否成功接收到通知时,使用Notifications 子过程向Client 通知特定属性句柄及其对应的特征值。当Server 被配置为向Client 通知多个特征值时,可以使用Multiple Variable Length Notifications 子过程;
    Characteristic Value Notifications
  • Characteristic Value Indication:当Server 被配置为向Client 指示特征值,并期望属性协议层确认已成功接收到指示时,使用Indications 子过程向Client 指示特定属性句柄及其对应的特征值,后续会受到来自Client 的确认信息。
    Characteristic Value Indication

上述介绍的每个GATT 功能及其子过程到ATT 属性协议操作指令之间的映射关系汇总如下(属性协议操作指令将会在下文介绍):
GATT procedure mapping to ATT protocol opcodes

二、Attribute protocol

前面已经介绍了Attribute 的逻辑结构,这里主要介绍Attribute 的报文格式和支持的操作指令或方法。

2.1 Attribute PDU Format

Attribute PDU 包含三个部分:1 字节长度的指令操作码、可变长度的属性参数、可选的12 字节长度认证签名信息,属性PDU 格式如下:
Attribute protocol PDU
Attribute PDU 中的Attribute Parameters 字段通常包含前面介绍的属性逻辑结构中Attribute Handle、Attribute Type、Attribute Value、Attribute Permissions 四个字段中的零个或多个,只有Server 与Client 之间需要交互的字段信息才会包含在Attribute PDU 中。

2.2 Attribute protocol methods

GATT Profile 的Procedure 描述了如何使用Attribute protocol 来完成相应的Feature,Client 通过Attribute protocol 可以发现并获取或更改属性服务器上的属性。按照Client 与Server 之间的交互方式划分,Attribute protocol 由以下六种基本操作构成(也即Attribute PDU 有六种基本类型,由后缀区分):
Attribute PDUs

  • Request / Response:Client 向Server 发送ATT Request,以要求服务器执行相关操作并返回ATT Response。Client 一次只能发送一条Request,也即只能在收到上一条请求的Response 后才能继续发送下一条Request,这降低了构建属性服务器的复杂度。Server 返回给Client 的响应可能是与请求直接相关的响应,也可能是说明请求为何失败的错误响应;
    An Attribute Protocol request
  • Command:Client 向Server 发送ATT Command,让服务器执行某种操作,但不需要Server 返回响应。Client 可以连续向Server 发送多条命令而不受流控约束,当Server 无法响应命令时可直接忽略,Client 不知道Command的执行结果也不会收到错误响应,因此ATT Command 的执行是不可靠的;
    An Attribute Protocol command
  • Indication / Confirmation:Server 向Client 发送ATT Indication,让客户端获知某属性的数值,Client 需要返回给Server 一个ATT Confirmation。Server 一次也只能发送一条Indication,也即只能在收到上一条指示的Confirmation 后才能发送下一条Indication;
    An Attribute Protocol indication
  • Notification:Server 向Client 发送ATT Notification,以告知客户端某属性的数值,但不需要Client 返回确认信息。Server 也可以连续向Client 发送多条命令而不受流控约束,Client 来不及处理的通知也将直接丢弃,Server 不知道Notification 的执行结果也不会收到错误信息,因此ATT Notification 的执行也是不可靠的。
    An Attribute Protocol notification

Attribute protocol 支持的操作指令汇总如下(对照GATT procedure 到ATT protocol opcodes 的映射关系更容易理解):
Attribute protocol summary

  • Error handling:指令ATT_ERROR_RSP 用于返回请求执行失败的原因,返回的属性参数包括产生此错误的请求的属性操作码、产生该错误的原始请求中的属性句柄、表示产生此错误的原因的错误码等;
  • MTU exchange:在BLE 连接中,属性协议默认的MTU 长度是23 字节,如果设备想发送更大的数据包,可以通过ATT_EXCHANGE_MTU_REQ 和ATT_EXCHANGE_MTU_RSP 指令协商一个更长的MTU。一般由Client 发起交换MTU 的请求,协商结果为Client / Server 二者可接收的MTU 长度中的较小值;
  • Find information:查找信息请求有两种:一种是Client 发送ATT_FIND_INFORMATION_REQ 指令,请求给定属性句柄集合内的所有属性信息,比如前面介绍的Discover All Characteristic Descriptors 过程;另一种是Client 发送ATT_FIND_BY_TYPE_VALUE_REQ 指令,请求符合特性属性类型UUID 的所有属性信息,比如前面介绍的Discover Primary Services By Service UUID 过程;
  • Reading attributes:读取属性值请求有五种:一、ATT_READ_BY_TYPE_REQ 指令按属性类型UUID 读取属性值;二、ATT_READ_REQ 指令按属性句柄Handle 读取属性值;三、ATT_READ_BLOB_REQ 指令按属性句柄Handle 配合偏移量Offset 读取长属性值;四、ATT_READ_MULTIPLE_REQ 和ATT_READ_MULTIPLE_VARIABLE_REQ 指令按属性句柄集合Set Of Handles 读取多个属性值;五、ATT_READ_BY_GROUP_TYPE_REQ 指令按属性组类型UUID 读取一组属性值;
  • Writing attributes:普通的写入属性值请求有两种:一、ATT_WRITE_REQ 指令按属性句柄Handle 写入属性值,需要接收到响应信息;二、ATT_WRITE_CMD 和ATT_SIGNED_WRITE_CMD 指令也是按属性句柄Handle 写入属性值,但不需要返回任何响应信息;
  • Queued writes:排队写入属性值请求分为两个阶段:第一阶段是准备写入请求,也即Client 通过ATT_PREPARE_WRITE_REQ 指令将要写入的一个或多个属性值发送到Server,并通过ATT_PREPARE_WRITE_RSP 指令确认Server 接收到的属性值无误;第二阶段是执行写入请求,也即Client 通过ATT_EXECUTE_WRITE_REQ 指令将之前发送给Server 并经确认无误的属性值立即写入到对应的属性中。比如前面介绍的Write Long Characteristic Values 或Characteristic Value Reliable Writes 过程;
  • Server initiated:服务器启动更新请求实际上是从Server 向Client 发送属性信息的方式,服务器上属性值有更新时可以及时将更新后的属性值发送给客户端,这样客户端就不需要定期轮询属性值,从而节省了功率和带宽。服务器启动更新过程也有两种方式:一、Server 发送ATT_HANDLE_VALUE_IND 指令,让Client 获知特定属性句柄及其对应的属性值,且需要客户端返回ATT_HANDLE_VALUE_CFM 确认指令;二、Server 发送ATT_HANDLE_VALUE_NTF 指令,让Client 获知特定属性句柄及其对应的属性值,但不需要客户端返回确认信息,Server 还可以通过发送ATT_MULTIPLE_HANDLE_VALUE_NTF 指令,让Client 一次性获知多个属性句柄的属性值。

三、L2CAP Protocol

3.1 L2CAP Overview

本文开头已经介绍了在Attribute protocol 与LE Controller 之间还有一层L2CAP(Logical Link Control and Adaptation Protocol and Adaptation Protocol) 协议层,L2CAP 协议层的功能架构图如下(可以将L2CAP 协议与TCP 协议对比理解):
L2CAP architectural blocks

  • Protocol/channel multiplexing:L2CAP 上层不止承载一个协议,比如ATT 属性协议、SMP 安全管理协议等报文都需要经L2CAP 路由到LE Controller,这里L2CAP 起到协议多路复用器的作用,L2CAP 为上层每个协议分配一个逻辑信道,多个逻辑信道可以复用下层LE Controller 的同一个物理信道,来传输不同的协议报文;
  • Segmentation and reassembly:L2CAP 上层的应用数据包或服务数据包SDU(Service Data Unit) 通常比较大(最大可达到64 KB),下层LE Controller 可接受的报文PDU(Protocol Data Unit)容量较小(有效负载最大为27 Bytes,扩展报文最大为 251 Bytes),中间的L2CAP 可以起到数据包分段重组的作用,将上层Application 较大的SDU 分段为较小的PDU 后发送给LE Controller,或将从LE Controller 接收到的多个PDU 重组为完整的SDU 再递交给上层Application 处理;
  • Flow control per L2CAP channel:为了避免空中传输链路堵塞,导致数据传输错误或丢失,L2CAP 协议为每个L2CAP channel 提供了基于窗口的流量控制机制;
  • Error control and retransmissions:空中传输链路容易受到干扰,导致数据传输错误或丢失,L2CAP 协议为传输的数据提供错误校验和重新传输机制,当发现传输的数据包错误时,请求对方重新传输错误的数据包,跟流量控制机制一起保证蓝牙无线传输的可靠;
  • Support for Streaming:蓝牙音频服务是一个很重要的应用场景,像音频这类数据流传输对时延比较敏感,对偶尔出现的少量错误是可以容忍的,L2CAP 协议为Streaming 流数据传输提供了相应的L2CAP channel,而且不对其使用流量控制和错误重传机制,尽可能保证流数据传输的及时同步。

3.2 L2CAP PDU Format

L2CAP 既然起到多协议复用器的作用,可以将多个逻辑信道映射到同一个物理信道,为了便于区分不同的逻辑信道,L2CAP 报文需要包含Channel ID 字段,下面给出L2CAP 的基本报文格式如下(为了实现更多上述功能,L2CAP 还有更复杂的报文格式):
L2CAP PDU format in Basic L2CAP mode
BLE 协议栈中L2CAP 支持的CID (Channel ID) 类型如下:
CID name space on LE-U logical link
上述CID 主要分为两类:一类是固定信道,比如为Attribute protocol 分配的CID 是0x0004、为L2CAP LE Signaling channel 分配的CID 是0x0005、为Security Manager protocol 分配的CID 是0x0006;另一类是使用过程中动态分配的可变信道。下文将分别对BLE 支持的三个L2CAP 固定信道报文及指令做简单介绍。

前面介绍的只是Basic L2CAP Mode下的报文格式,L2CAP 为Flow Control Mode、(Enhanced) Retransmission Mode、Streaming Mode、LE (Enhanced) Credit Based Flow Control Mode 提供了更复杂的报文结构如下(本文不展开介绍了,可以参考Core_v5.2 手册的[Vol 3] Part A, Section 3 ):
L2CAP PDU formats in other modes

3.2.1 L2CAP PDU format on a signaling channel

从L2CAP architectural blocks 图中可以看到两种数据流:红色的Controls frame 和黑色的Data/packet flow,其中Controls frame 用于L2CAP 信道管理,传输Controls frame 信道为signaling channel,在signaling channel 上传输的Controls frame(C-frame) 格式如下:
L2CAP PDU format on a signaling channel and Command format
对于BLE 协议,在signaling channel 上传输的Controls frame 的CID 为0x0005(对于BR/EDR 协议,C-frame 的CID 为0x0001)。Controls frame 的Information payload 部分是signaling command format,包括信令操作码Code、信令标识符Identifier、数据长度Length、数据信息data 四个部分,这里只列出BLE 协议常用的信令操作码及其描述如下(这里删去了BR/EDR支持而BLE不支持的信令操作码):
Signaling command codes

  • Command Reject:当设备收到了不支持或不理解的命令时,或者接收到的命令超过MTU 而溢出时,可以返回L2CAP_COMMAND_REJECT_RSP 报文告知对方拒绝执行命令的原因;
  • Create an L2CAP channel:通过发送L2CAP_LE_CREDIT_BASED_CONNECTION_REQ 或L2CAP_CREDIT_BASED_CONNECTION_REQ 命令,在两个设备之间创建并配置L2CAP Channel;
  • Connection Parameters Update:在BLE 连接中,如果Slave 希望修改当前的连接参数可以使用L2CAP_CONNECTION_PARAMETER_UPDATE_REQ 命令向Master 发起连接参数更新请求。Master 可以接受或者拒绝Slave 请求的连接参数,并通过相应的响应报文告知Slave 结果;
  • Reconfigure MTU or MPS:当设备支持的MTU(Maximum Transmission Unit) 或MPS(Maximum PDU Payload Size) 值变化时,可以发送L2CAP_CREDIT_BASED_RECONFIGURE_REQ 命令重新配置MTU 或MPS 的值;
  • Flow Control:当设备还能接收Credit-based frame (K-frame)时,通过发送L2CAP_FLOW_CONTROL_CREDIT_IND 告知对方可以继续发送的K-frame 数量,用于流量控制;
  • Terminating an L2CAP channel:设备可以发送L2CAP_DISCONNECTION_REQ 命令来终止特定的L2CAP Channel。

3.2.2 L2CAP PDU format on Security Manager protocol

前篇博文介绍了Security Manager protocol 的配对过程,两个设备之间要完成配对也需要双方交互相关的指令或报文,SMP 配对和安全管理相关的指令或报文格式如下:
L2CAP PDU format on Security Manager protocol
L2CAP 为Security Manager protocol 分配的Channel ID 为0x0006,SMP command Information payload 包含指令操作码Code 和数据Data 两部分,这里列出BLE 支持的SMP 指令操作码如下:
SMP command codes
下面依然按照BLE 配对过程的三个阶段简单介绍SMP 指令:

  • Phase 1(Pairing Feature Exchange):Master 使用Pairing Request 报文开始配对功能交换过程,Slave 也可以使用Security Request 命令请求Master 开始配对过程。如果配对过程中出现问题(包括下面两个阶段中出现的问题),则通过Pairing Failed 报文告知对方配对失败的原因;
    Slave security request, master initiated pairing
  • Phase 2(Long Term Key Generation):双方成功完成配对功能交换后,通过Pairing Public Key 报文交换本设备的Public Key(如果Slave 有键盘输入能力,可通过Keypress Notification 报文通知Master 输入的配对码),通过Pairing Confirm 和Pairing Random 报文交换Confirm value 和Random value, 然后开始计算并生成LTK。LTK 计算完成后,双方通过Pairing DHKey Check 报文生成并相互验证DHKey value,如果验证成功则表示生成LTK 的过程没有问题;
    Long Term Key Generation
  • Phase 3(Transport Specific Key Distribution):双方建立加密连接后,开始生成并分发一些专用的密钥。比如使用Encryption Information 报文分发LTK(用于加密会话信息),使用Master Identification 分发EDIV(Encrypted Diversifier) 和Rand(用于计算并生成LTK),使用Identity Information 报文分发IRK(Identity Resolving Key,用于生成或解析设备的resolvable private address),使用Identity Address Information 报文分发设备的public device address 或static random address,使用Signing Information 报文分发CSRK(Connection Signature Resolving Key,用于对数据进行签名或验证接收数据的签名信息)。
    Transport specific key distribution

3.2.3 L2CAP PDU format on Attribute protocol

Attribute protocol 的报文格式前面已经介绍过了,在L2CAP 层加上一个L2CAP Header,其中Channel ID 为0x0004,报文格式如下:
L2CAP PDU format on Attribute protocol
Attribute protocol 支持的操作指令前面已经介绍过了,这里不再赘述。

更多文章:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/192130
推荐阅读
相关标签
  

闽ICP备14008679号