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 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來進行設置的。
而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
Step 1. 首先,選擇要打開的HCI log,并選擇log類型為BtSnoop Files,即以*.log結尾的文件。
還有一種方式是將btsnoop_hci.log的后綴修改為btsnoop_hci.cfa,就可以直接用Capture File Viewer打開。
Step 2. 打開log文件后,選擇Frame Display就可以看到我們抓取的HCI log了
Step 3. Frame Display窗口中有很多Tab,將協議棧中各類協議分類顯示,例如:HCI相關的log放在HCI的Tab中,Hands-Free(HFP)屬于應用層的Bluetooth Profile,和HFP相關操作的log都放在Hands-Free這個Tab中。
-
Air sniff log
Android設備上抓取的HCI log只能分析Host和Control之間的問題,當Host和Control之間交互是正常的,那就可能就是傳輸的過程中(Air Interface)出了問題,此時就需要分析Air sniff log。Air sniff log能夠抓取的兩個藍牙設備在數據傳輸過程中的空中包,抓取Air sniff log需要專門的設備。
4. HCI log 案例 - 藍牙掃描設備過程分析
應用層在調用startDiscovery()進行設備掃描時,Host會通過HCI發送一個Inquiry HCI Command給Controller。接下來我們會通過分析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。
4.2 過濾Inquiry Command
Inquiry Command是Link Control command類型的command,通過查詢Bluetooth Core Specification的中Vol 2->Part E->7.1 LINK CONTROL COMMANDS小節,可知Link Control command的OCF值為0x0001。
因此,Inquiry Command的Opcode為 0x0001 << 6 + 0x01 = 0x0401 ,通過0x0401就確定某條command為Inquiry Command,該命令的名稱為HCI_Inquiry
ComProbe Protocol Analysis System支持過濾功能,通過設置filter可以過濾出Opcode為0x0401的log,設置方法如下圖:
4.3 掃描過程分析
1. 發送Inquiry請求
-
Host發送HCI_Inquiry Command
應用層要進行藍牙設備掃描啦,Host先發一條HCI_Inquiry的Command通知Controller
-
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。
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是一個耳機的圖標。