星期四, 13 08月 2020 08:27

蓝牙HCI command/event/acl/sco格式介绍

蓝牙协议栈跟蓝牙芯片都是使用统一的数据来交互的,由SIG规定(备注:部分芯片有HCI vendor命令),一般交互的有以下几种类型(注意:如果没有特别声明,所有的数据)

1) HCI command,由蓝牙协议栈给蓝牙芯片发送命令,来控制芯片行为,分几个OGF(Groups)在后面小节讲HCI command的时候会介绍。

2)HCI event,由蓝牙芯片上报事件给蓝牙协议栈的事件

3)HCI acl数据,蓝牙协议栈跟蓝牙芯片双向交互的L2CAP以及上层数据

4)HCI sco,蓝牙协议栈跟蓝牙芯片交互的SCO音频是数据

5)HCI iso,蓝牙协议栈跟蓝牙芯片交互的BLE audio的数据(Core 5.2才增加)

一. 声明


本专栏文章我们会以连载的方式持续更新,本专栏计划更新内容如下:

第一篇:蓝牙综合介绍 ,主要介绍蓝牙的一些概念,产生背景,发展轨迹,市面蓝牙介绍,以及蓝牙开发板介绍。

第二篇:Transport层介绍,主要介绍蓝牙协议栈跟蓝牙芯片之前的硬件传输协议,比如基于UART的H4,H5,BCSP,基于USB的H2等

第三篇:传统蓝牙controller介绍,主要介绍传统蓝牙芯片的介绍,包括射频层(RF),基带层(baseband),链路管理层(LMP)等

第四篇:传统蓝牙host介绍,主要介绍传统蓝牙的协议栈,比如HCI,L2CAP,SDP,RFCOMM,HFP,SPP,HID,AVDTP,AVCTP,A2DP,AVRCP,OBEX,PBAP,MAP等等一系列的协议吧。

第五篇:低功耗蓝牙controller介绍,主要介绍低功耗蓝牙芯片,包括物理层(PHY),链路层(LL)

第六篇:低功耗蓝牙host介绍,低功耗蓝牙协议栈的介绍,包括HCI,L2CAP,ATT,GATT,SM等

第七篇:蓝牙芯片介绍,主要介绍一些蓝牙芯片的初始化流程,基于HCI vendor command的扩展

第八篇:附录,主要介绍以上常用名词的介绍以及一些特殊流程的介绍等。

另外,开发板如下所示,对于想学习蓝牙协议栈的最好人手一套。以便更好的学习蓝牙协议栈,相信我,学完这一套视频你将拥有修改任何协议栈的能力(比如Linux下的bluez,Android下的bluedroid)。

------------------------------------------------------------------------------------------------------------------------------------------

CSDN学院链接(进入选择你想要学习的课程):https://edu.csdn.net/lecturer/5352?spm=1002.2001.3001.4144

蓝牙交流扣扣群:970324688

Github代码:https://github.com/sj15712795029/bluetooth_stack

入手开发板:https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-22329603896.18.5aeb41f973iStr&id=622836061708

------------------------------------------------------------------------------------------------------------------------------------------

二. 蓝牙Host(蓝牙协议栈)跟蓝牙Controller(蓝牙芯片)交互格式

蓝牙协议栈跟蓝牙芯片都是使用统一的数据来交互的,由SIG规定(备注:部分芯片有HCI vendor命令),一般交互的有以下几种类型(注意:如果没有特别声明,所有的数据)

1) HCI command,由蓝牙协议栈给蓝牙芯片发送命令,来控制芯片行为,分几个OGF(Groups)在后面小节讲HCI command的时候会介绍。

2)HCI event,由蓝牙芯片上报事件给蓝牙协议栈的事件

3)HCI acl数据,蓝牙协议栈跟蓝牙芯片双向交互的L2CAP以及上层数据

4)HCI sco,蓝牙协议栈跟蓝牙芯片交互的SCO音频是数据

5)HCI iso,蓝牙协议栈跟蓝牙芯片交互的BLE audio的数据(Core 5.2才增加)

三. HCI Command(HCI命令介绍)


HCI命令包用于从协议栈发送给芯片的命令。HCI命令包的格式如下图所示:

Opcode:每个命令被分配一个2字节的操作码(opcode),用来唯一地识别不同类型的命令,操作码(opcode)参数分为两个字段,称为操作码组字段(Opcode Group Field, OGF)和操作码命令字段(Opcode Command Field, OCF)。其中OGF占用高6bit字节,OCF占用低10bit字节。

共有以下几组OGF:

1)Link Control commands, the OGF is defined as 0x01.

2)Link Policy commands, the OGF is defined as 0x02

3)HCI Control and Baseband commands, the OGF is defined as 0x03

4)Informational Parameters commands, the OGF is defined as 0x04

5)status parameters commands, the OGF is defined as 0x05

6)Testing commands, the OGF is defined as 0x06

7)LE Controller commands, the OGF code is defined as 0x08

8)vendor-specific debug commands,the OGF code is defined as 0x3F,此部分是vendor定义的,也就是芯片厂商为了扩展core文档的HCI command定义

OCF众多,在每个OGF下都有一堆的OCF定义,我们在下个小节进行详细介绍

Parameter Total Length后续参数的长度

Parameter:每个command的para不同,下个小节做说明

注意:HCI Command Packet的长度不能超过255(包括HCI Command包头)

下面我们来截图举例下,我们以HCI reset为例,在介绍前,我们先看下HCI reset的command,

这个命令是上电第一条发给芯片的command(bcsp,h5 transport除外)

HCI reset的OGF为3,OCF也为3,根据以上算法我们算下:

Opcode[0] = OCF & 0xff = 0x03

Opcode[1] = (OCF >> 8) | (OGF 2) = 0x0c

也就是0x03 0x0c ,见截图

我们在组合封包的时候代码如下:

  1.  
    struct bt_pbuf_t *hci_cmd_ass(struct bt_pbuf_t *p, uint8_t ocf, uint8_t ogf, uint8_t len)
  2.  
    {
  3.  
    ((uint8_t *)p->payload)[0] = (ocf & 0xff); /* OCF & OGF */
  4.  
    ((uint8_t *)p->payload)[1] = (ocf >> 8)|(ogf 2);
  5.  
    ((uint8_t *)p->payload)[2] = len-HCI_CMD_HDR_LEN; /* Param len = plen - cmd hdr */
  6.  
    if(pcb->numcmd != 0)
  7.  
    {
  8.  
    --pcb->numcmd; /* Reduce number of cmd packets that the host controller can buffer */
  9.  
    }
  10.  
    return p;
  11.  
    }

四. HCI Event(HCI事件介绍)

HCI event是蓝牙芯片发送给协议栈的事件。HCI事件包的格式如下图所示:

Event code:唯一event编码,在后续的小节会介绍(是固定的)

Parameter Total Length:后续参数的长度

Parameter:event参数。

Event header结构体代码如下:

  1.  
    struct hci_event_hdr_t
  2.  
    {
  3.  
    uint8_t code; /* Event code */
  4.  
    uint8_t len; /* Parameter total length */
  5.  
    } BT_PACK_END;

以一个event来做说明,event在后续的小节会介绍,在这里大概了解下就OK了

以HCI_Command_Complete格式为例,格式如下:

参数解释如下:

Btsnoop如下:

raw data分析:

0x0E -> command complete event code

0x04 -> para len,也就是后面参数的长度

0x01 -> num HCI command pacekets

0x03 0x0c -> HCI reset command opcode

0x00 -> status success

五.HCI acl(蓝牙芯片跟蓝牙协议栈交互的L2CAP以及上层数据)

HCI acl用于从协议栈跟蓝牙芯片双向交互上层协议的数据。HCI acl的格式如下图所示:

Handle:连接句柄,用于蓝牙连接后跟remote交互acl数据用

PB flag:此部分就是用于上层数据(L2CAP),是否是分隔数据,具体bit的定义如下

BC flag:此部分定义是是否为广播,每个bit定义如下:

Data total length:后续payload的长度。

举一个例子:

0x4c 0x20就是acl前两个byte,解析为connection handle:0x04c,pb_flag为2 BC flag是0x0

六.HCI sco(用于蓝牙协议栈跟蓝牙芯片的音频交互数据)

HCI sco用于从协议栈跟蓝牙芯片双向交户音频数据。HCI sco的格式如下图所示:

Handle:连接句柄,用于蓝牙连接后跟remote交互sco数据用

Packet_Status_Flag:The Host shall set the Packet_Status_Flag bits to 0b00. If the Erroneous_Data_Reporting parameter was set to disabled when the synchronous connection was created, the Controller shall set the Packet_Status_Flag bits to 0b00 and whether or not data is provided for cases when a valid (e)SCO packet was not received is unspecified.If the Erroneous_Data_Reporting parameter was set to enabled when the synchronous connection was created, the Controller shall set the Packet_Status_Flag according to the following table.

Data_Total_Length:SCO数据长度

我个人是没有做过SCO数据走UART的芯片,所以没有btsnoop的例子

另外,HCI ISO是BLE audio的,市面上现在还没有芯片,所以这部分略

 

查看 10424