鄭春芳,鄭靈翔,石江宏
(廈門大學(xué) 信息科學(xué)與技術(shù)學(xué)院 ATR實驗室,福建 廈門 361005)
隨著無線技術(shù)的不斷發(fā)展,藍(lán)牙產(chǎn)品逐漸走入人們的生活。目前藍(lán)牙在PC端支持良好,應(yīng)用比較廣泛。但在嵌入式系統(tǒng)中,由于藍(lán)牙接口的兼容性問題,使其在嵌入式領(lǐng)域的應(yīng)用大打折扣。因此,如何在嵌入式系統(tǒng)中支持藍(lán)牙設(shè)備成為當(dāng)前嵌入式領(lǐng)域的研究熱點。
作為通用串行總線標(biāo)準(zhǔn),USB接口以其連接方便、兼容性好和傳輸速度快等特點被更多的硬件系統(tǒng)支持。針對USB藍(lán)牙適配器在嵌入式Linux下的應(yīng)用,開發(fā)其驅(qū)動程序,為藍(lán)牙設(shè)備在嵌入式Linux下進(jìn)一步應(yīng)用提供前提條件。本文詳細(xì)闡述USB藍(lán)牙設(shè)備的HCI傳輸層,給出實現(xiàn)方案中關(guān)鍵的函數(shù)和數(shù)據(jù)結(jié)構(gòu),并在MP2530上實現(xiàn)。
該嵌入系統(tǒng)采用Linux-2.6.20內(nèi)核版本,采用在X86架構(gòu)的PC機(jī)端上交叉編譯,在目標(biāo)板MP2530上運行。目標(biāo)板MP2530是專門為嵌入式多媒體處理器MMSP2+設(shè)計的開發(fā)平臺,其內(nèi)部集成有ARM926EJ和ARM946E的雙核,帶有2D和3D的圖形加速器。此外,MP2530還提供豐富的外圍數(shù)據(jù)接口,包含6路UART通道,USB主機(jī) 、USB設(shè)備2.0、SD卡讀寫通道、以太網(wǎng)控制器等。MP2530支持基于通用串行總線1.1版本和開放式主機(jī)控制器1.0版本,支持高、低速USB設(shè)備。
按照藍(lán)牙協(xié)議的邏輯功能,整個藍(lán)牙協(xié)議棧分為3個部分[1],如圖1所示。
圖1 藍(lán)牙協(xié)議棧體系結(jié)構(gòu)
底層硬件實塊包括射頻 RF(Rodio Fraquency)、基帶BB(Base Band)和鏈路管理 LMP(Link Manager Protocol);中間層協(xié)議包括邏輯鏈路控制和適應(yīng)協(xié)議L2CAP(Logical Link Control and Adaptation Layer protocol)、服務(wù)發(fā)現(xiàn)協(xié)議 SDP(Service Discovery Protocol)、串口仿真協(xié)議 RFCOMM和電話通信協(xié)議TCS-BIN;高層應(yīng)用包括撥號網(wǎng)絡(luò)、耳機(jī)、局域網(wǎng)訪問、文件傳輸?shù)龋謩e對應(yīng)一種應(yīng)用模式。
在BB與LMP上和L2CAP之間還有一個主機(jī)控制接口HCI(Host Controller Interface)層,它提供對下層基帶控制器、鏈路管理器的命令接口,以及對硬件狀態(tài)和控制注冊成員的訪問。該接口還提供對藍(lán)牙基帶的統(tǒng)一訪問模式。
Linux藍(lán)牙協(xié)議棧又稱BlueZ,是一個開放性的協(xié)議。BlueZ采用模塊化設(shè)計,其組織結(jié)構(gòu)如圖2所示。它包含內(nèi)核和用戶態(tài)2大模塊。其中內(nèi)核模塊是由設(shè)備驅(qū)動層、藍(lán)牙核心及主機(jī)控制接口 HCI(Host Control Interface)層、Bluetooth協(xié)議核心、邏輯鏈路控制和適配協(xié)議L2CAP(Logical Link Control and Adaptation Protocol)、SCO 音頻層、其他Bluetooth服務(wù)組成。而用戶態(tài)模塊則包括BlueZ工具集和藍(lán)牙應(yīng)用程序。
圖2 BlueZ組織結(jié)構(gòu)
對于USB設(shè)備,其傳輸層即USB傳輸子層是介于主機(jī)和主控制器之間,負(fù)責(zé)主機(jī)與主控制器間的數(shù)據(jù)傳輸。
從藍(lán)牙的協(xié)議層模型可以看出HCI位于藍(lán)牙系統(tǒng)的上層(L2CAP,SDP 和 RFCOMM)和鏈路管理層(LMP)及基帶之間,它為這些上層提供進(jìn)行LM和BB的統(tǒng)一接口方式。USB藍(lán)牙設(shè)備通過模塊內(nèi)的USB設(shè)備控制器和總線與主機(jī)控制器相連,負(fù)責(zé)與主機(jī)的數(shù)據(jù)交換,它在USB固件的控制下,將接收到的HCI協(xié)議分組交給HCI固件處理或?qū)碜枣溌饭芾砥骱突鶐Э刂破鞯臄?shù)據(jù)傳送至主機(jī)。HCI固件負(fù)責(zé)解釋從主機(jī)接收到的HCI分組并交給鏈路管理器和基帶控制器處理,或采集藍(lán)牙模塊各部件的狀態(tài)信息并遞交給主機(jī)。主機(jī)與藍(lán)牙USB模塊關(guān)系如圖3所示。
1)HCI終端要求 USB藍(lán)牙設(shè)備可看作高速設(shè)備,其固件配置由2個接口組成。接口0為固定設(shè)置,包含BULK和中斷終端;接口1提供可擴(kuò)展的同步帶寬占用方式。接口1提供4種設(shè)置,以提供基于同步帶寬需求的占用方式。其缺省接口為空,可使設(shè)備支持非同步帶寬。當(dāng)通過選擇接口呼叫調(diào)整同步帶寬占用方式時,終端可自由選擇2種接口,因此任何未處理的BULK或中斷事務(wù)都無需中止或重新提交。
圖3 主機(jī)與藍(lán)牙USB模塊關(guān)系
2)控制終端要求 任何USB藍(lán)牙設(shè)備都有一個用于配置和控制該設(shè)備控制終端—終端0。終端0允許主機(jī)向主控制器發(fā)送HCI指令。當(dāng)USB固件在具有藍(lán)牙類別碼的終端上接收一個分組時,它應(yīng)將該分組視為一個HCI指令分組。
3)BULK終端要求 BULK終端用來傳輸ACL數(shù)據(jù),由于數(shù)據(jù)完整性及帶寬請求,因此需用到BULK終端。BULK具有檢錯和糾錯能力。Linux下的藍(lán)牙設(shè)備允許連接多個ACL鏈路,因此經(jīng)過此通道的數(shù)據(jù)流可能來自或發(fā)往1個或多個設(shè)備數(shù)據(jù)。為避免阻塞,主控制器采用類似于共享終端模型的流控制模型。默認(rèn)狀態(tài)下,BULK最大分組尺寸為64字節(jié),因此BULK通過總線1 ms傳輸1個或多個64字節(jié)的分組幀。
4)中斷終端要求 中斷終端能夠保證事件以可預(yù)測并及時的方式傳遞。事件分組可在一定允許延時條件下通過USB發(fā)送。對于藍(lán)牙設(shè)備,中斷終端的時間間隔為1 ms。USB軟件和固件無需對傳送到主控制器的事件充分了解。
5)同步終端要求 同步終端用于傳遞SCO數(shù)據(jù),主要是音視頻數(shù)據(jù)。時間是該數(shù)據(jù)類型的重要因素。它允許數(shù)據(jù)損壞或丟失,但必須保證有恒定的數(shù)據(jù)流。USB固件以固定速率將數(shù)據(jù)內(nèi)容傳遞到主控制器的SCO先進(jìn)先出隊列(FIFO)。如果FIFO滿,則新數(shù)據(jù)將覆蓋原有數(shù)據(jù)。藍(lán)牙設(shè)備可以支持3個64 kb/s語音信道,可以接收不同編碼方式的數(shù)據(jù)―8 bit或16 bit的線性音頻編碼。默認(rèn)狀態(tài)下,同步終端的最大分組尺寸為64字節(jié)。如果無需支持3條16 bit編碼的語音信道,最大分組尺寸為32字節(jié)。
4.1.1 結(jié)構(gòu)體hci_dev
在嵌入式Linux系統(tǒng)中,任何一種設(shè)備在HCI層都被抽象為hci_dev結(jié)構(gòu)體。當(dāng)藍(lán)牙設(shè)備接入系統(tǒng)時,不論以何種方式接入,都要向HCI層或藍(lán)牙核心層注冊為一個hci_dev設(shè)備。hci_dev結(jié)構(gòu)體主要包含:
1)設(shè)備名稱(name)、設(shè)備地址(bdaddr)、設(shè)備標(biāo)志(flags)、設(shè)備類型(type)等設(shè)備屬性;
2)分組類型(pkt_type)、鏈接策略(link_policy)、鏈接模式(link_mode);
3)3 種類型任務(wù)隊列:CMD任務(wù)、發(fā)送任務(wù)、接收任務(wù);
4)7 種設(shè)備操作, 包括 open,close,flush,send,destruct,notify 和 ioctl。
另外還有設(shè)備查詢狀態(tài)、查詢返回結(jié)果、設(shè)備鎖等。
4.1.2 結(jié)構(gòu)體hci_usb
hci_usb結(jié)構(gòu)體定義了指向hci_dev和usb_device的2個指針。usb_device定義藍(lán)牙usb設(shè)備,這樣通過這2個指針可將HCI層與藍(lán)牙設(shè)備聯(lián)系起來。hci_usb還定義HCI操作USB設(shè)備時所用到的其他數(shù)據(jù),諸如數(shù)據(jù)緩存大小、USB接口、主機(jī)端的端點描述符和隊列等。
4.1.3 結(jié)構(gòu)體bt_usb_data
結(jié)構(gòu)體bt_usb_data描述USB接口藍(lán)牙模塊的數(shù)據(jù)結(jié)構(gòu),包含傳送數(shù)據(jù)的緩沖區(qū)、I/O端點、消息隊列以及緩沖區(qū)的消息串和消息串讀寫位置索引、傳送緩沖區(qū)的指針以及表示設(shè)備是否被激活、是否存在、是否打開等狀態(tài)標(biāo)志位。
在嵌入式Linux系統(tǒng)中,所有設(shè)備驅(qū)動程序,都必須向內(nèi)核注冊其設(shè)備驅(qū)動。對于藍(lán)牙USB設(shè)備驅(qū)動注冊,該過程首先創(chuàng)建一個指向usb_dirvier類型的結(jié)構(gòu)體hci_usb_driver,具體內(nèi)容包括指定驅(qū)動程序的名字(hci_usb)、探測函數(shù)(hci_usb_probe)、斷開函數(shù)(hci_usb_disconnect)、 中斷函數(shù) (hci_usb_suspend)、 恢復(fù)函數(shù)(hci_usb_resume)、所支持藍(lán)牙設(shè)備列表(bluetooth_ids)。 并由函數(shù)module_init、hci_usb_init、usb_register 依次 執(zhí) 行 ,usb_register最 終 調(diào) 用usb_register_driver完成驅(qū)動向內(nèi)核注冊。
當(dāng)卸載驅(qū)動程序時,要在內(nèi)核中注銷驅(qū)動程序,釋放其占有的資源。該過 程 與 驅(qū) 動 注 冊 類 似 , 由 module_exit、hci_usb_exit、usb_deregister依次執(zhí)行,最終 usb_deregister調(diào)用usb_deregister_driver完成驅(qū)動注銷。
當(dāng)USB設(shè)備插入主機(jī)時,主機(jī)控制器HCI使用控制通道枚舉,并給其分配唯一設(shè)備地址(1~127),同時讀取該設(shè)備的class,subclass和protocol等設(shè)備描述符。
如果讀取到的設(shè)備描述符信息與hci_usb驅(qū)動程序注冊到USB核心的信息相匹配,則將設(shè)備與相應(yīng)的驅(qū)動程序進(jìn)行綁定。調(diào)用hci_usb_driver中指定的探測函數(shù)hci_usb_probe,初始化結(jié)構(gòu)體hci_usb中部分?jǐn)?shù)據(jù),并注冊HCI設(shè)備。藍(lán)牙設(shè)備探測函數(shù)hci_usb_probe具體探測過程如圖4所示。
當(dāng)藍(lán)牙設(shè)備斷開連接時,通過調(diào)用hci_usb_driver中指定的斷開函數(shù)hci_usb_disconnect完成。其過程主要包括清空設(shè)備的驅(qū)動數(shù)據(jù),關(guān)閉設(shè)備,釋放與設(shè)備相關(guān)的資源,并注銷內(nèi)核中相應(yīng)的HCI設(shè)備及釋放所占用的資源。
如果要中斷藍(lán)牙設(shè)備連接 (只是暫時中斷,未釋放資源),則通過調(diào)用中斷函數(shù)hci_usb_suspend來完成。其過程是保存hci_dev數(shù)據(jù)信息,中斷HCI與設(shè)備連接,互斥訪問設(shè)備等待隊列并把數(shù)據(jù)信息加入設(shè)備等待隊列的尾部。如果要恢復(fù)被中斷過的藍(lán)牙設(shè)備的連接,可通過調(diào)用恢復(fù)函數(shù)hci_usb_resume來完成。其過程是互斥訪問設(shè)備等待隊列,取出隊列頭的hci_dev數(shù)據(jù),恢復(fù)HCI與設(shè)備的連接。若錯誤,則返回I/O error。
把交叉編譯過的藍(lán)牙USB設(shè)備驅(qū)動程序以及必要的程序和庫移到根文件系統(tǒng)中,啟動開發(fā)板,在板上USB接口處插上USB藍(lán)牙設(shè)備。
加載USB藍(lán)牙驅(qū)動,執(zhí)行hciconfig,可以看到當(dāng)然藍(lán)牙USB設(shè)備使用狀態(tài),如圖5所示。
圖5 加載后USB藍(lán)牙設(shè)備狀態(tài)
本文在硬件平臺MP2530上開發(fā)實現(xiàn)嵌入式Linux下藍(lán)牙USB設(shè)備驅(qū)動程序。實驗結(jié)果顯示,基于該驅(qū)動的USB藍(lán)牙設(shè)備可與其他藍(lán)牙設(shè)備正常通訊,其速度比以K單位計算的串口要快得多。USB藍(lán)牙設(shè)備驅(qū)動程序的開發(fā),為藍(lán)牙設(shè)備與其他硬件設(shè)備的連接提供了一種高效便捷的途徑,同時大大拓展了藍(lán)牙設(shè)備的應(yīng)用。
[1]金 純,許光辰,孫 睿.藍(lán)牙技術(shù)[M].北京:電子工業(yè)出版社,2001.
[2]梁軍學(xué),郁 濱.Linux藍(lán)牙協(xié)議棧的USB設(shè)備驅(qū)動[J].計算機(jī)工程,2008(5):274-275.
[3]錢志鴻,楊 帆,周求湛.藍(lán)牙技術(shù)原理、開發(fā)與應(yīng)用[M].北京:北京航空航天大學(xué)出版社,2006.
[4]吳艷瑋,任長明.藍(lán)牙HCI USB傳輸層規(guī)范[J].計算機(jī)工程,2002(2):235-236.
[5]梁正平,毋國慶,肖 敬.Linux中USB設(shè)備驅(qū)動程序研究[J].計算機(jī)應(yīng)用研究,2004,21(6):70-72.
[6]巍 騖,張煥強(qiáng),方貴明.基于Linux的USB驅(qū)動程序?qū)崿F(xiàn)[J].計算機(jī)應(yīng)用,2002,22(8):17-19.