美文网首页蓝牙BLEAndroid知识程序员
Android Bluetooth HCI log 详解

Android Bluetooth HCI log 详解

作者: 伤口不该结疤 | 来源:发表于2017-04-18 20:58 被阅读2448次

    0. 引子

    对于蓝牙开发者来说,通过HCI log可以帮助我们更好地分析问题,理解蓝牙协议,就好像网络开发一定要会使用Wireshark分析网络协议一样。

    本篇主要介绍HCI log的作用如何抓取一份HCI log,并结合一个实际的例子来说明如何分析HCI log

    1. HCI log 介绍

    1.1 HCI log 作用

    HCI log是用来分析蓝牙设备之间的交互行为是否符合预期是否符合蓝牙规范。在日常的开发中,通常使用HCI log来做这样几件事:

    • 分析Bug:蓝牙打开后搜索不到设备,或者搜索到的设备没有名称只有蓝牙地址;Android手机不能向苹果手机传输文件 ... ...

    • 需求分析:手机需要适配一款蓝牙自拍杆来控制拍照,通过HCI log可以观察竞品在实现这个功能时,使用的是什么Bluetooth Profile?只要知道了使用的Bluetooth Profile,我们就有了实现这个功能的思路。

    • 蓝牙协议学习:通过HCI log辅助学习蓝牙协议,就好像学习TCP/IP时,通过wireshark抓包来学习TCP协议

    1.2 蓝牙核心系统架构

    说了这么多HCI log的用处,要想更好地理解HCI log,我们需要先来看下HCI在整个蓝牙核心系统架构中所处的位置。为了理解起来更简单,我这边将蓝牙核心系统架构抽象为3层

    • User Application(Host):User Application即应用层,也被称为Host,我们调用Bluetooth API就属于应用层,例如,BluetoothAdapter中提供的接口。

    • HCI (Host controller Interface):上层在调用蓝牙API时,不会直接操作蓝牙底层(Controller)相关接口,而是通过HCI下发对应操作的Command给Controller,然后底层执行命令后返回执行结果,即Controller发送Event给HCI,HCI再通知给应用层,HCI起到了一个中间层的作用。

    • Controller:Controller是在最底层,可以理解为我们手机上的蓝牙芯片。

    抽象后的蓝牙架构

    完整的蓝牙核心系统架构比较复杂,这里我们就不再深入,感兴趣的同学可以参考蓝牙规范Core_v4.2.pdf,里面有详细的定义和介绍。我们后面在分析HCI log时,也会参考这个规范中定义的内容。

    完整的蓝牙架构

    2. 如何抓取HCI log

    在开发者选项中打开启用蓝牙HCI信息收集日志开关,Android系统就开始自动地收集HCI log并保存到手机上。

    启用蓝牙HCI信息收集日志

    不同的平台存放HCI log的路径会不一样,MTK存放HCI log的路径为/sdcard/mtklog/btlog/btsnoop_hci.log高通的存放路径为/sdcard/btsnoop_hci.log

    MTK:/ $ ls -l /sdcard/mtklog/btlog/
    total 816
    -rw-rw---- 1 root sdcard_rw 412258 2016-02-28 00:39 btsnoop_hci.log
    
    shell@Qualcomm:/ $ ls -l /sdcard/btsnoop_hci.log
    -rw-rw---- root     sdcard_rw    12744 2017-06-16 15:43 btsnoop_hci.log
    

    如果上面提到的路径下都没有HCI log,我们还可以通过手机上的蓝牙配置文件bt_stack.conf来查看路径,bt_stack.conf位于/etc/bluetooth/路径下。HCI log路径通过BtSnoopFileName=/sdcard/btsnoop_hci.log来进行设置的。

    HCI log在手机上的路径

    而bt_stack.conf是通过Android源码中的/system/bt/conf/bt_stack.conf来配置的。

    // /system/bt/conf/bt_stack.conf
    # BtSnoop log output file
    BtSnoopFileName=/sdcard/btsnoop_hci.log
    

    将抓取到的HCI log pull出来,直接用记事本打开,看到的都是乱码。我们还需要一个HCI log分析工具:Frontline ComProbe Protocol Analysis System

    C:\Windows\System32>adb pull /sdcard/mtklog/btlog/btsnoop_hci.log C:\Users\admin\Desktop\hci
    501 KB/s (4880 bytes in 0.009s)
    

    3. HCI log分析工具

    Frontline ComProbe Protocol Analysis System是Frontline提供的一款蓝牙协议log分析工具,Frontine这家公司主要是做抓取蓝牙Air sniff log设备的,我们后面再来说下什么是Air sniff log。购买他们的抓包工具就会附带log分析工具,也可以在Frontine官网上下载,下载的时候需要填一些信息,觉得麻烦的同学可以去其他非官网途径进行下载。

    安装完成后,在开始菜单中找到Frontline ComProbe Protocol Analysis System,使用Capture File Viewer可以打开HCI log


    ComProbe Protocol Analysis System

    Step 1. 首先,选择要打开的HCI log,并选择log类型为BtSnoop Files,即以*.log结尾的文件。
    还有一种方式是将btsnoop_hci.log的后缀修改为btsnoop_hci.cfa,就可以直接用Capture File Viewer打开。

    Step 1. 打开的HCI log 选择log类型

    Step 2. 打开log文件后,选择Frame Display就可以看到我们抓取的HCI log了

    Step 2 . 选择Frame Display Frame Display主界面

    Step 3. Frame Display窗口中有很多Tab,将协议栈中各类协议分类显示,例如:HCI相关的log放在HCI的Tab中,Hands-Free(HFP)属于应用层的Bluetooth Profile,和HFP相关操作的log都放在Hands-Free这个Tab中。

    Frame Display
    • Air sniff log
      Android设备上抓取的HCI log只能分析Host和Control之间的问题,当Host和Control之间交互是正常的,那就可能就是传输的过程中(Air Interface)出了问题,此时就需要分析Air sniff log。Air sniff log能够抓取的两个蓝牙设备在数据传输过程中的空中包,抓取Air sniff log需要专门的设备。
    Air sniff log

    4. HCI log 案例 - 蓝牙扫描设备过程分析

    应用层在调用startDiscovery()进行设备扫描时,Host会通过HCI发送一个Inquiry HCI CommandController。接下来我们会通过分析HCI log,来学习Inquiry 的流程。在分析HCI log前,我们先来学习下HCI Command数据包的结构。

    4.1 HCI Command 数据包结构

    HCI Command数据包结构定义在蓝牙核心协议规范Core_v4.2.pdf中。

    HCI Command数据包格式如下,开头的Opcode是区分不同类型的命令的唯一标识,Opcode由OpCode Group Field (OGF)OpCode Command Field (OCF)组成。根据OGF的值,可以将HCI commands进行分类。OpCode 的计算公式为:** OpCode = OGF << 6 + OCF 。有了OpCode计算的方式,我们就可以通过OpCode过滤**HCI log里面的指定类型的HCI Command。

    HCI Command Packet OpCode计算方法

    4.2 过滤Inquiry Command

    Inquiry CommandLink Control command类型的command,通过查询Bluetooth Core Specification的中Vol 2->Part E->7.1 LINK CONTROL COMMANDS小节,可知Link Control command的OCF值为0x0001

    Bluetooth Core Specification目录 For the Link Control commands, the OGF is defined as 0x01

    因此,Inquiry Command的Opcode为 0x0001 << 6 + 0x01 = 0x0401通过0x0401就确定某条command为Inquiry Command,该命令的名称为HCI_Inquiry

    Inquiry Command

    ComProbe Protocol Analysis System支持过滤功能,通过设置filter可以过滤出Opcode为0x0401的log,设置方法如下图:

    过滤HCI_Inquiry

    4.3 扫描过程分析

    1. 发送Inquiry请求

    • Host发送HCI_Inquiry Command
      应用层要进行蓝牙设备扫描啦,Host先发一条HCI_Inquiry的Command通知Controller
    Host: HCI_Inquiry
    • Controller回复HCI Event
      Controller在收到HCI_Inquiry这条Command后,会回复一条Command Status的HCI Event,来表示Controller执行HCI_Inquiry后的状态,即Status:Success。仔细观察可以发现这两条HCI log的Frame标号是挨着的,HCI_Inquiry的帧号是196,Command Status的帧号是197。
    Controller:Command_status、

    2. 扫描结果

    扫描完成后,Controller会发送Event:HCI Extended Inquiry Result。以列表中搜索到的Jabra Classic v0.5.3为例,它的HCI Extended Inquiry Result数据包中会包含它的设备名称、它所支持的Service的UUID,和设备类型Wearable Headset device,因此,Jabra Classic v0.5.3的Icon是一个耳机的图标

    扫描结果 Jabra Classic v0.5.3的HCI Extended Inquiry Result

    5. 参考

    相关文章

      网友评论

      • 31e7c0daca85:博主你好,貌似找到一处笔误,0x0001 << 6 + 0x01 = 0x0401 应该改为0x01<<6+0x0001=0x0401。另外想请教下这个公式博主是从是哪看到的,我在Core4.1上没找到。我大概知道OGF占据opcode的高6位,OCF占据低10位,但是对OGF<<6有点想不明白,如果OGF按照16进制表示,那么是不是需要左移10位才能到opcode的高6位呢?
        山青水秀123456:同问,这个计算公式写的不明白
      • 31e7c0daca85:试了下,真是学到了,很实用的工具。

      本文标题:Android Bluetooth HCI log 详解

      本文链接:https://www.haomeiwen.com/subject/wzjxwttx.html