1. 程式人生 > >ARM平臺上藍芽協議棧Bluez的移植使用和配置(寫的狠不錯) .

ARM平臺上藍芽協議棧Bluez的移植使用和配置(寫的狠不錯) .

目錄(?)[-]

  1. 相關說明
    1. 網站資源
    2. 工作環境
  2. 編譯
    1. 核心
    2. Bluez Lib / Utils
  3. 藍芽硬體初始化及基礎服務啟動
    1. 何謂硬體初始化
    2. 硬體初始化步驟
      1. 關於PSKEY的獲取
    3. Daemon程序的啟動
  4. Paring配對
    1. Passkey_agent
    2. 關於自動配對和請求的發起
  5. A2DP
    1. 配置
    2. 問題
  6. DUN的使用
    1. 系統配置
    2. 連線步驟
  7. Bluez相關的各種tools的使用
    1. Bccmd
    2. Hciattach
    3. 其它
      1. Hcidump
      2. Hcitool
      3. Sdptool
      4. Hciconfig
    4. 雜項
      1. 使用Dbus-send進行測試
      2. HCI、H4、USB、BCSP 之間的關係
      3. BCSP資料包結構
      4. Hid / Serial / HF / OBEX
      5. 總的遺留問題

BLOG:

http://blog.csdn.net/colorant/

 

Bluez作為當前最成熟的開源藍芽協議棧,在Linux的各大發行版中已經得到了廣泛的應用。在桌面環境下,使用Bluez應該已經沒有太大的問題,本文的主要目的是介紹在嵌入式平臺上,搭建和配置Bluez的各個Profile執行所需做的工作,討論可能遇到的問題,介紹一些工具的使用和工作原理。因為本人的能力和測試時間有限,可能下文中有些理解、分析不一定準確,歡迎聯絡指正。

 

 

1         相關說明

1.1        網站資源

Bluez的官方網址:http://www.bluez.org/ 這裡提供最新的原始碼下載,最近伺服器崩潰了一次,有些東西沒了。。。。

Bluez的Wiki:http://wiki.bluez.org/wiki/ 這裡提供Bluez相關的Howto等文件資源

相關郵件列表:

https://lists.sourceforge.net/lists/listinfo/bluez-users 關於如何使用和配置Bluez,多數是在討論PC環境下的問題。。。。

https://lists.sourceforge.net/lists/listinfo/bluez-devel Bluez開發者活動的地方,有什麼Bug之類的懷疑,還有程式設計介面之類的問題,就發到這裡吧。

 

1.2        工作環境

個人感覺,使用Bluez最大的問題就是文件的欠缺,除了Wiki上的有限資料以外,很難找到其它有用的文件。

由於Bluez的程式碼實現更新變化得很快,網上的許多文件介紹的都是早期版本的使用,再有的文章多數是基於成熟的Linux發行版,來討論藍芽裝置的配置和使用,對於嵌入系統開發,自己編譯,搭建和配置相關環境的文章很少。此外和具體藍芽晶片相關的資料也很難找到。

 

這裡我不打算也沒有能力寫一個完整的指南,只能基於前段時間在自己的板子上所做的工作,總結一下相關的步驟和所遇到的各類問題以及這期間所掌握的各種相關知識。希望能給有類似開發需求的朋友一些有益的幫助,下面是這篇文章所基於的工作環境:

 

Ø       硬體平臺:基於ARM的嵌入式板子

Ø       藍芽晶片:CSR BC4 ROM 版本晶片,不帶eeprom

Ø       軟體環境:Linux 2.6.21 ,自制檔案系統

Ø       Bluez版本:bluez-libs 3.22  bluez-utils 3.22

 

2         編譯

2.1        核心

相信多數人使用的都是2.6的核心了,在2.6的核心中要支援Bluez,只要你的核心版本不是太舊,無需打Patch,直接配置好就OK了,核心裡面的程式碼相對比較穩定了。當然,Bluez對一些Bluetooth協議棧新特性的支援,還是需要更新kernel程式碼的。你應該確認你使用的kernel版本是否以及包含了對應的支援。

 

核心的配置,基本上把 networking下 --- Bluetooth subsystem support 裡的以下幾項全部選上即可:

 

L2CAP protocol support

SCO links support

RFCOMM protocol support

RFCOMM TTY support

BNEP protocol support

HIDP protocol support

 

此外,在Bluetooth device drivers裡選上你所需要支援的Bluetooth裝置。我使用的CSR的chip是我們直接build在板子上,通過串列埠和cpu通訊的,晶片預設使用BCSP作為通訊協議,所以我選擇了:

 

HCI UART driver

BCSP protocol support

 

如果你是通過usb介面使用藍芽介面卡,需要選擇

HCI USB driver

 

2.2        Bluez Lib / Utils

 

Bluez Lib的編譯比較簡單,而Bluez-Utils所依賴的庫就比較多了,大體包括 dbus alsa hal gstreamer openobex xml等等,仔細觀察./configure 的輸出,將所需要的包先安裝或者build好。

值得注意的一點是:

如果你需要開啟所有的功能模組的支援,需要在 ./configure 引數中新增 --enable-all  --enable-audio --enable-input --enable-network –enable-serial 等,在3.22版本中 --enable-all 居然不包括 audio等相關模組的service的編譯,不知道是否是因為還保留了daemon和service等不同方案的緣故。不過,這至少與他的configure --help 對於 --enable-all 的描述是不符合的。

 

3         藍芽硬體初始化及基礎服務啟動

 

如果在PC環境下,使用Ubuntu,呼叫 /etc/init.d/bluetooth start 應該就能完成這一步的工作了。下面敘述一下在我的嵌入式環境下,如何手動完成這一步驟。

 

3.1        何謂硬體初始化

硬體初始化,指的是配置藍芽晶片,將其置於一個能夠正常通訊的狀態。

 

對於CSR的晶片來說,就是通過設定PSKEY,設定其晶振頻率,UART波特率等等一些關鍵引數。 如果使用的是USB形式的介面卡,因為其EEPROM儲存了相關的預設引數,這一步很可能不需要做,而我使用的是不帶EEPROM的ROM版本晶片,如何正確完成初始化工作著實讓我折騰了一陣。

 

對於其它晶片,沒有太多研究,不過,據我有限的瞭解,TI的晶片在hciattach時也需要完成一些額外的初始化工作,其它如ST的晶片則可能需要下載firmware。

 

3.2        硬體初始化步驟

通常藍芽晶片的初始化和協議繫結可以通過 hciattach 來完成(通過配置bluez的啟動指令碼,可以不需要使用hciattach,標準發行版應該都是不用hciattach,如何配置,還沒有研究 。。。 8 )

 

Hciattach 需要的引數主要包括 TTY節點,裝置型別,波特率等。多數型別的裝置的初始化工作,在選擇了正確的裝置型別引數後,都由hciattach在init_uart函式中呼叫具體的初始化函式所完成。

 

很遺憾的是,因為要重新設定晶振頻率和波特率,並同步BCSP協議,這種方式好像處理不了我所使用的晶片(不排除我沒有找到正確的解決方案的可能性),我最終的解決辦法是在hciattach之前,使用Bluez-utils裡的BCCMD工具先完成這些PSKEY的設定工作。

 

具體命令是:

bccmd -t bcsp -d /dev/ttyS1 psload -r csr.psr

 

在這時,由於HCI介面還沒有啟動,所以只能使用BCSP協議來進行通訊,我的裝置是暴露在ttyS1下,你的可能不一樣,-r引數指明在psload完成 PSKEY的批量載入操作之後,對晶片進行Warmreset,否則這些引數的修改不會起作用。

 

Csr.psr的內容取決與你的晶片,我的大致如下:

 

// PSKEY_ANA_FREQ

&01fe = 9C40 // 相當於40M的晶振

// PSKEY_UART_BAUD_RATE

&01be = 0EBF // 921600的波特率

// PSKEY_UART_SEQ_WINSIZE

&0407 = 0006

// BDADDR

&0001 = 1122 3344 5566 7788

。。。

 

這裡有個問題,你會發現,通過bccmd -t bcsp psset 命令理論上應該是可以單步設定每一個PSKEY的,但是從我實踐看來,單步的操作在兩次對bccmd的呼叫過程中,上一次對PSKEY的修改,都會在下一次呼叫之前被複位,從程式碼上看估計和BCSP協議的同步過程有關。

3.2.1          關於PSKEY的獲取

如何獲得正確的完整的PSKEY引數,大概會有幾個途徑:

Ø       通過CSR的網站下載boot_strap包,這是CSR自己的BCHS協議棧所使用的初始化程式碼,在裡面找到你所需要的pskey值。

Ø       下載CSR的bluesuite工具,裡面包含了一個叫pstool的工具,可以用它來讀寫CSR的Casira開發板或其它BT裝置的PSKEY設定,試驗並找出你能用的引數。

Ø       找CSR或模組廠商支援 8 )

 

不過,基本上來說,如果只是要讓晶片通過串列埠能夠和Bluez協議棧正常通訊上,只需要設定PSKEY_ANA_FREQ 和 PSKEY_UART_BAUD_RATE 這兩個PSKEY就可以了。

 

3.3        Daemon程序的啟動

早先的版本里,Bluez的Daemon很多,但是最近的版本,很多daemon都轉為service的形式來做了,3.22 裡面包括了以下這幾個Service,其它profile貌似還保留著daemon的形式。

bluetoothd-service-serial

bluetoothd-service-network

bluetoothd-service-audio

bluetoothd-service-input

這幾個Service的啟動依賴於hcid的啟動以及相關的配置檔案

主要配置檔案位於:/etc/bluetooth/

此外,通常還需要啟動SDP來提供服務查詢,另外,Bluez本身還依賴於Dbus daemon的執行。

 

所以,整體上來說,我的手動啟動Bluez的全過程如下:(其中核心程式碼是以模組形式編譯的)

 

insmod bluetooth.ko

insmod hci_uart.ko

insmod l2cap.ko

insmod rfcomm.ko

insmod sco.ko

insmod hidp.ko

 

/etc/rc2.d/S20dbus start

bccmd -t bcsp -d /dev/ttyS1 psload -r csr.psr

hciattach -s 921600 /dev/ttyS1 bcsp 921600

hciconfig hci0 up

sdpd

hcid –d

 

4         Paring配對

4.1        Passkey_agent

在正常使用一個藍芽裝置前,通常都需要對該裝置進行配對繫結的操作。

Bluez的配對機制貌似也修改了幾次,2.x版本中通過pin_helper來處理pin code的應答,3.22版本里使用的配對機制,其API是基於Dbus來實現的,需要向dbus註冊一個agent,PC的發行版通常都會有一些基於各種圖形庫的passkey_agent,對於嵌入式系統,這部分程式碼可以想象,應該是要按照相應的API自己實現一個,為了測試,我直接使用了bluez-utils/daemon 目錄下的passkey-agent

這是一個命令列下的可以使用預先設定的pin code進行配對的程式

 

為了使用它,我的檔案系統裡 /etc/Bluetooth/hcid.conf 中 option一節類似如下 :

 

# HCId options

options {

        # Automatically initialize new devices

        autoinit yes;

 

        # Security Manager mode

        #   none - Security manager disabled

        #   auto - Use local PIN for incoming connections

        #   user - Always ask user for a PIN

        #

        security user;

 

        # Pairing mode

        pairing multi;

 

        # Do the same as "hciconfig hci0 down" when SetMode("off")

        # is called.

        offmode devdown;

 

        # Default PIN code for incoming connections

        passkey "1234";

}

 

4.2        關於自動配對和請求的發起

 

配對的發起,這裡主要是從請求的發起者是誰的角度來說。

 

通常可能不需要關心配對請求是由本地還是由遠端發起的,使用passkey_agent都能夠正確處理。

 

不過如果在hcid.conf中將 Security Manager mode 設定為 auto,則Bluez會將passkey後面的字串作為預設的Pin code,自動答覆遠端發起的配對請求。這是在沒有使用passkey_agent的情況下的一種配對方式。

 

在這種情況下,Bluez可以處理遠端的配對請求,但是對於本地發起的配對請求,將無法正確處理,我沒有仔細的分析原因,或許是程式碼特意設計成這種工作方式。所以在無法明確知道誰將會主動先發起配對請求的情況下,使用Atuo模式,可能就會出現有些時候裝置能繫結有些時候不能繫結的現象。

 

通常如果是由本地裝置搜尋發現的新裝置,配對繫結的操作應該也是由本地發起。

 

另外可以觀察到,對遠端一個非PC類的藍芽裝置,如藍芽耳機,如果上次繫結過,在耳機啟動時會主動發起連線請求,如果本地的link key丟失了,也就會再走一次繫結的流程,這種情況下配對請求就是由遠端裝置發起的。

 

 

5         A2DP

A2DP藍芽立體聲應該是藍芽最常見的Profile之一。

2.x版本的Bluez,對A2DP的支援是通過BTSCO來實現的,3.22的版本通過bluetoothd-service-audio來支援。

對Bluez A2DP profile的支援,還依賴於Alsa或Gstreamer。

5.1        配置

測試A2DP的時候,我使用的是aplay,同時在相關的配置檔案裡面寫死了藍芽耳機的地址

主要的配置檔案包括:

 

/etc/asound.conf :

 

pcm.bluetooth{

        type bluetooth

        device 00:02:5B:00:C1:A0

        profile "hifi"

}

 

/etc/bluetooth/audio.conf :

 

[General]

# disable=Sink

SCORouting=PCM

 

[Headset]

DisableHFP=true

 

[A2DP]

SourceCount=2

 

配置好這些以後,使用 aplay -D bluetooth sample.wav 進行測試。

 

值得注意的是,使用Aplay開啟藍芽裝置進行播放,需要有如下兩個Alsa的plugin:

 

/usr/lib/alsa-lib/libasound_module_pcm_bluetooth.so

/usr/lib/alsa-lib/libasound_module_ctl_bluetooth.so

 

這兩個so檔案可以在bluez-utils 裡面找到。需要注意他們和libasound 的版本匹配。

 

5.2        問題

在測試中發現,如果連線的耳機是由PC上的藍芽介面卡提供的AV耳機服務,那麼配對可以完成,但是連線會失敗,真正的耳機則沒有這個問題,不知道是否是因為以上的方法還存在缺陷?嘗試使用由DBUS發起命令的形式來連線PC的AV耳機服務,也是一樣的問題。是否連線PC模擬的AV耳機服務,首先要切換裝置的role?

 

沒有測試Ctl介面

 

如何動態選擇不同的耳機,而不是寫死在腳本里?(這個想來估計是要自己基於Alsa的API程式設計處理,aplay無法直接完成測試)

 

播放大檔案會出現under run錯誤,需要測試是由與波特率設定不夠高造成,還是SBC編碼效率不夠,還是這個版本里存在的bug。

 

6         DUN的使用

Dun profile運行於rfcomm之上,主要是通過藍芽介面暴露一個Modem的介面,用於提供撥號上網服務。

在這裡所討論的不是提供撥號上網服務本身,而是使用外部裝置所提供的這個服務,進行網路連線。

6.1        系統配置

通常為了使用DUN,或者任何一個其它型別的Modem,我們會通過PPP協議來撥號和建立網路連線。

首先需要核心的支援,可以簡單的把 device drivers -> Network device support 下面的PPP相關的內容全部選上。

其次,要編譯應用層的PPP包,我的測試是基於ppp-2.4.4

 

主要的兩個ppp配置檔案:

 

/etc/ppp/peers/gprs:

 

/dev/rfcomm0

115200

defaultroute

usepeerdns

nodetach

noauth

local

debug

connect "/usr/sbin/chat -v -f /etc/ppp/chat-gprs"

 

/etc/ppp/chat-gprs:

 

TIMEOUT 10

ABORT 'BUSY'

ABORT 'NO ANSWER'

ABORT 'ERROR'

"" 'ATZ'

SAY 'Init..../n'

OK 'AT+CGDCONT=1,"IP","CMWAP"'

ABORT 'NO CARRIER'

SAY 'Dialing..../n'

OK 'ATD*99***1#'

CONNECT ''

 

前面一個配置檔案基本就是那樣了,後面一個,這兩句要根據你的SIM卡的實際情況來處理:

 

OK 'AT+CGDCONT=1,"IP","CMWAP"'

OK 'ATD*99***1#'

 

這裡我設定的是使用中國移動的CMWAP。

 

此外,使用CMWAP還需要設定你的瀏覽器的代理伺服器:10.0.0.172 埠9201

 

6.2        連線步驟

首先是要查詢提供dun服務的裝置,將服務提供在哪個channel通道上。這可以通過sdptool來檢視,在我的裝置上查詢的結果是在channel 1上:

 

~ # ./sdptool browse 00:08:C6:77:A0:6C

 

Browsing 00:08:C6:77:A0:6C ...

Service Name: Dial-upnetworking

Service RecHandle: 0x10000

Service Class ID List:

  "Dialup Networking" (0x1103)

  "Generic Networking" (0x1201)

Protocol Descriptor List:

  "L2CAP" (0x0100)

  "RFCOMM" (0x0003)

    Channel: 1

Profile Descriptor List:

  "Dialup Networking" (0x1103)

    Version: 0x0100

 

其次,如果rfcomm所需裝置節點不存在,將其建立:

 

mknod -m 666 /dev/rfcomm0 c 216 0

 

然後就是撥號了,如果該裝置之前沒有繫結,這過程中會自動發起繫結操作:

 

pppd debug dump call gprs &

 

完成以後就可以看到 ppp0這樣一個網路介面了。

 

~ # ifconfig

ppp0      Link encap:Point-to-Point Protocol 

          inet addr:10.154.76.82  P-t-P:192.200.1.21  Mask:255.255.255.255

          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1

          RX packets:4 errors:0 dropped:0 overruns:0 frame:0

          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0

          collisions:0 txqueuelen:3

          RX bytes:64 (64.0 B)  TX bytes:101 (101.0 B)

 

7         Bluez相關的各種tools的使用

在這一段折騰Bluez的時間裡,越來越發現Bluez相關的許多工具做得還是挺好用的,主要在Bluez-utils/tools 目錄下。只是有一點讓我很遺憾,除了man以外很難找到更多的幫助文件,而man文件本身對一些功能的描述也不是很詳細。

其中有些選項,如果你不瞭解藍芽協議棧,或者沒有查閱過相關藍芽晶片的一些文件,很難搞明白是什麼意思,甚至有些選項的具體引數值的設定,如果不讀原始碼你都無從得知有哪些備選值。。。。

 

能力有限,下面所寫的只是我所用過的有限的幾個工具的一些使用經驗,希望能有所幫助。

7.1        Bccmd

Bccmd是用來和CSR的晶片進行BCCMD(Bluecore command protocol)通訊的一個工具。BCCMD並非藍芽協議棧的標準,而是CSR晶片的專屬協議

Bccmd的呼叫格式為:bccmd [-t <transport>] [-d <device>] <command> [<args>]

 

Tansport型別包括 HCI USB BCSP H4等,常用的估計就是HCI和BCSP兩種。需要注意一下他們的使用場合:

HCI是一個抽象的標準的藍芽通訊介面,在基於HCI協議呼叫BCCMD時,需要在Bluez已經建立好hci介面的基礎上使用。

BCSP(Bluecore Serial Protocol)是CSR自己制定的傳輸層協議,主要目的是用來加強在沒有使用CTS、RTS進行流量控制的情況下進行可靠的資料傳輸的能力。其概念是相對H3 , H4而言,(具體分析,請參考下面雜項一章中相應的小節 )

 

BCCMD的主要用途就是用來讀寫pskey,這裡以 psset 這個command來介紹一下格式:

Psset 格式如下: psset [-r] [-s <stores>] <key> <value>

其它都好理解,關鍵是-s引數之後跟的store具體的含義。這個引數可以是數值也可以是字串

查詢CSR的BCCMD相關的文件,可以找到具體的含義如下:

 

0x0000 Default

0x0008 psram

0x0001 psi

0x0002 psf

0x0004 psrom

0x0003 psi then psf

0x0007 psi, psf then psrom

0x0009 psram then psi

0x000b psram, psi then psf

0x000f psram, psi, psf then psrom

 

CSR的藍芽晶片中,PSKEY可能儲存在 rom flash eeprom ram等介質裡,這裡的數值指明瞭psset/get命令操作PSKEY時所針對的儲存介質及其優先順序,通常我們會用 –s 0x0 或 –s “default” 來使用該命令,0x0的含義與0xf一樣。

 

值得注意的是,哪個引數是有效的,還取決於哪一類的儲存介質實際存在於藍芽晶片中,此外,只讀類的介質對寫操作類的命令也是無效的。

 

基本上來說,所修改的都是位於psram中的pskey,此外,pskey修改以後要起作用,還要一併使用–r引數,或直接用warmreset命令將藍芽晶片進行warm reset。

 

 

7.2        Hciattach

Hciattach主要用來初始化藍芽裝置,它的命令格式如下:

 

hciattach [-n] [-p] [-b] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]

 

其中最重要的引數就是 type和speed,type決定了要初始化的裝置的型號,可以使用 hciattach –l 來列出所支援的裝置型號。

並不是所有的引數對所有的裝置都是適用的,有些裝置會忽略一些引數設定,例如:檢視hciattach的程式碼就可以看到,多數裝置都忽略bdaddr引數。

 

Hciattach命令內部的工作步驟是:首先開啟制定的tty裝置,然後做一些通用的設定,如flow等,然後設定波特率為initial_speed,然後根據type呼叫各自的初始化程式碼,最後將波特率重新設定為speed。所以呼叫hciattach時,要根據你的實際情況,設定好initial_speed和speed。

 

對於type BCSP來說,它的初始化程式碼只做了一件事,就是完成BCSP協議的同步操作,它並不對藍芽晶片做任何的pskey的設定。同步操作的具體流程和規範可以參考CSR的相關文件: BCSP Link Establishment Protocol

 

7.3        其它

下面幾個,使用了,但是沒有太多研究

7.3.1          Hcidump

Hcidump不在bluez-utils包裡,而是在單獨的hcidump包裡。主要用來分析捕獲和分析HCI資料包,如果使用bluez過程中出了什麼問題,用hcidump往往可以發現一些出錯的線索,原因。 引數很多,基本上hcidump –X –V 就可以幫你獲得詳細的經過格式解析的資料包。

7.3.2          Hcitool

主要用hcitool來scan遠端的裝置,顯示裝置地址,名稱等。

例如:Hcitool scan, hcitool inq

 

7.3.3          Sdptool

主要用來瀏覽遠端裝置SDP服務,或者管理本地的SDPD維護的資料庫。

常用的應該就是查詢遠端裝置的服務了

例如:

sdptool browse 00:02:72:B0:00:26 瀏覽地址為00:02:72:B0:00:26的裝置所提供的服務

sdptool search 0x1112 00:02:72:B0:00:26 查詢地址為00:02:72:B0:00:26的裝置上的Headset Audio Gateway服務。

 

./sdptool search 0x1112 00:02:72:B0:00:26

Class 0x1112

Inquiring ...

Searching for 0x1112 on 00:02:72:B0:00:26 ...

Service Name: Headset Audio Gateway

Service RecHandle: 0x1001d

Service Class ID List:

  "Headset Audio Gateway" (0x1112)

  "Generic Audio" (0x1203)

。。。

 

7.3.4          Hciconfig

這個就不用多說了,格式上很類似於ifconfig,用來設定HCI裝置的引數

例如

hciconfig hci0 up 啟動hci0介面

hciconfig hci0 iscan 使能位於hci0介面的藍芽晶片的inquery scan模式(使得裝置能被其它藍芽裝置發現)

 

 

8         雜項

8.1        使用Dbus-send進行測試

由於Bluez使用dbus進行程序間通訊,所以我們可以使用dbus-send命令直接傳送命令進行一些查詢,試驗的工作。

Bluez每個Daemon或service所支援的Dbus介面API描述文字,可以在各自的目錄下找到,例如Audio的API寫在 audio/audio-api.txt中。

以Audio為例,可以參考 http://wiki.bluez.org/wiki/HOWTO/AudioDevices 中的描述

 

 

8.2        HCI、H4、USB、BCSP 之間的關係

個人理解,嚴格的說HCI和其它幾種protocol並不是可以對比的同一層次的東西。

HCI protocol 並不考慮在實際傳輸載體以及其中的糾錯等問題,只是一個抽象的傳輸層或叫做介面。USB,H3,H4等才是具體的transport layer(此外還有SD Transport layer)。HCI資料包需要附著在這些具體的Transport Layer的協議包中。

以BCSP為例,4種類型的HCI資料包各自使用了一個BCSP通道,做為這些通道的payload封裝在BCSP的協議包裡,需要通過TTY的lldsic層走一次,並由hci_uart模組做相應的封裝工作。而BCSP還通過其它通道支援其它的一些自定的Protocol。BCSP作為一個具體的傳輸層協議,還支援了校驗,同步等功能。

H4機制類似,SD和USB transport好像區別比較大一點。具體可以參考 Bluetooth Specification Volume 4.

 

8.3        BCSP資料包結構

HCI資料包的結構,在bluetooth的spec裡面有詳細定義,不過,CSR自己的BCSP,BCCMD等一系列協議,又添加了一堆的東西,其中,HCI資料包是作為BCSP的payload,而BCCMD又是作為HCI的payload,所以測試過程中,發覺要分析清楚bluez通過kernel最後到底往藍芽晶片的串列埠傳送了什麼資料,特別是想要自己手工構建一串資料,著實要看上一堆spec,拼湊起來才能完成。

要具體學習分析一串命令,最好的辦法,我能想到的就是修改bccmd的程式碼,將它傳給串列埠的每一個字串都打印出來,這樣對照這spec看,事半功倍。

 

例如下面這條,是使用我修改後的bccmd指令。所做的操作是讀取串列埠波特率的pskey:

 

./bccmd.dbg -t bcsp -d /dev/ttyS1 psget -s 0x0 0x01be

 

cmd : 00 fc 13 c2 00 00 09 00 01 00 03 70 00 00 be 01 01 00 00 00 00 00

c0 d1 65 01 c8 00 fc 13 c2 00 00 09 00 01 00 03 70 00 00 be 01 01 00 00 00 00 69 a6 c0

 

在這裡 HCI的資料包是第一行,具體解釋一下:

 

頭4個位元組是HCI Head,其中

00 fc :整體代表這是一個製造商自定義的命令。

13 :HCI命令長度為0x13。

C2 :包的內容是唯一的一個BCCMD資料包。

 

後面是BCCMD的Head

00 00 :這是一個GetReq命令

09 00 :BCCMD的命令9個word長度,及18位元組

01 00 :seqno, 包的順序標記 包1

03 70 :varid 7003, 表示這是對PSKEY的操作

00 00 :狀態標誌

再下來是BCCMD的payload

be 01 :0x01be 波特率PSKEY的index

01 00 :該PSKEY的長度為1

00 00 :strore 為 00

00 00 :該PSKEY的值,這裡是傳送讀命令,所以填0

 

第二行的資料是將HCI包封裝在了BCSP資料包裡:

前面部分:c0 d1 65 01 c8 :

C0 :是BCSP資料包的分割符

D1 :型別為可靠連結資料流,有CRC校驗

65 01 :channel 5 ( HCI CMD ), 長度為0x16

C8 :包頭的校驗

後面部分:69 a6 c0:

69 a6 :整個BCSP包的CRC校驗

C0 :分隔符

 

其它命令類似的分析可得。

 

如果只是希望看到HCI命令本身,也可以用hcidump來看。這是上面的讀pskey操作通過HCI介面操作的dump:

 

< HCI Command: Vendor (0x3f|0x0000) plen 19

    BCCMD: Get req: len 9 seqno 1 varid 0x7003 status 0

      PSKEY: key 0x01be len 1 stores 0x0000

        UART_BAUDRATE: value 0 (0x0000)

 

8.4        Hid / Serial / HF / OBEX

這幾個比較常用的profile,還沒測試哪。。。。。。誰給我買個藍芽滑鼠玩玩?!

 

8.5        總的遺留問題

整體上,PC上實現的自動識別,自動啟動服務的一整套指令碼,還沒有仔細研究。

 

 

轉自:https://blog.csdn.net/myxmu/article/details/11833869