歡迎您光臨本站 註冊首頁

藍芽:Linux與手機

←手機掃碼閱讀     火星人 @ 2014-03-23 , reply:0

來點基礎
藍芽最早由瑞典Ericsson提出,其名稱是古代瑞典的一位國王,因為總吃某種詭異果品 (似乎是草莓的一個品種,不太了解植物學,錯了的話不要拍我),把牙齒弄得藍乎乎的,被稱作藍牙(bluetooth)。古代瑞典可不像現在的一樣,那時 的瑞典統治整個北歐,可氣派了,同樣有野心的愛立信於是使用BT這個名字來命名這個被他們寄予厚望的短距離互聯技術。

Bluetooth用於連接個人周邊的外圍設備,比如無線耳機、印表機、掃描儀、手機、計算機等等,在這些設備之間交換文件和數據,替代低速串列線的工作,常用用途包括

文件共享、傳輸
語音傳輸
遠程列印
RS-232串列口線替代
因 為Bluetooth的功能十分實用、一經提出,立刻有一種一呼百應的感覺,隨著成本的下降,藍芽的用途也越來越廣(當然了,這個過程也不是一帆風順的 了),大量的中低端手機也開始裝備上了這項技術,以其更豐富、完善的協議棧,略高的傳輸速率,以及相對於紅外線來說擺脫了必須毫無障礙的束縛,幾乎完全取 代了原來商務手機上普遍裝備的紅外介面。

藍芽來到中國,把「牙」替換成了更有東方美感的「芽」字。

藍芽實際上並不是一種簡單的協議,相反,十分複雜

從網路結構和組網方式講,藍芽在10米區域內形成一個網路,其中可以有1個主設備,7個從設備,一共8個激活的設備,當然睡覺的設備還可以有很多,不打呼嚕就行了。對於更多的設備,可以使用ad hoc的方式互聯,學網路的同學們看到這個來精神了吧,不過我可不打算講了。
從應用來看,BT支持語音通信和串列線模擬,並且通過Profile來支持各種周邊智能設備的應用,比如耳機、印表機……並且定義了一套服務發現和調用機制,還是瞞有意思的。
藍芽最有意思的模過於第2層互聯和應用層的Profile了,至於底層的跳頻什麼的倒是新意不大。另外就是,雖然藍芽使用的頻率和微波爐烹飪的頻率毫無二致,但發射功率還是很小的,基本不足以把我們這麼大塊的肉弄熟。

Linux下的藍芽協議棧
Linux 下有若干個藍芽協議棧,目前生存狀況比較健康的是bluez和affix,後者大概是Nokia支持的吧,前者則是目前藍芽的Linux官方版本,集成在 Linux內核之中,也就是說,如果你有一個比較新的2.6內核,那麼,你多半已經支持藍芽了,而如果還不支持的話,重新編譯一下也就好了。

不 要覺得Linux的協議棧比不上Windows裡面的,事實是,這裡風景獨好,bluez協議棧支持的硬體設備遠遠多於windows系統支持的。如果你 和我一樣只用Linux,那麼,買了藍芽適配器之後,大概就可以把臃腫的驅動光碟丟進垃圾桶,然後心情愉快的使用藍芽了,跟我來吧,

內核的協議棧支持主要包含這麼幾個部分:

HCI. 這個是最底層的了,稱為 Host Control Interface. 之所以稱為 HCI 是源於藍芽的應用模型的。藍芽是連接智能外設的無線介面,介面的一側是設備,另一側就是主機 (Host) 了,採用類似記法的還有 USB, IEEE1394,所以,從設計初衷來看,這幾個東東都是針對差不多的市場的,當然,各有所長了。一個藍芽適配器是否能被驅動起來,就看 HCI 的支持性了。最常見的藍芽適配器就是筆者持有的這類 USB 介面的了,對於大部分標準的藍芽設備,它的驅動模塊是: hci-usb,對於我們的 2.6 內核,插入這個適配器,該模塊就被自動載入了。

在 HCI 之上是 L2CAP,Logical Link Control and Adaptation Protocal 這一層的功能承上啟下,向上層提供非同步數據傳輸的鏈路控制功能,所謂非同步,就是不存在一個主時鐘來同步所有傳輸的一種傳輸方式,通常用於數據的傳輸;與之相反,同步傳輸是完全與時鐘同步的,通常用在諸如語音或是多媒體通話之中,在藍芽中,語音同步傳輸也是被支持的,bluez 協議棧中的 SCO 就是支持同步模式的。

L2CAP之上有兩個協議被較廣地使用著:RFCOMM和BNEP,前者用於取代傳統的串列口,包括串列口上的各種應用,比如,傳真和撥號上網、印表機、文件圖片等數據傳輸;後者則可以提供一個乙太網介面,更適於計算機組網。自然地,對於手機和計算機之間,RFCOMM 總是更常被用到。

截止到這裡就是內核提供的幾乎所有藍芽協議棧了,不過,僅有這些,藍芽還不足以為我所用,只有有了用戶態的協議棧和工具相配合,才有幸福的藍芽生活 :)

用戶空間中的藍芽協議棧與相關工具
接著剛才的協議棧,這次勢在用戶空間實現的了:

在最上層,藍芽定義了很多的Profile,每個Profile對應著一種應用,比如列印、耳機(Headset)、文件傳輸、Fax/Modem撥號功能等。其中,文件交換對應著Obex協議,這是一個基於藍芽、紅外(IrDA)、串口等介質的文件(對象)交換協議,這幾種介質被列到一起一點也不會讓人感到意外,畢竟前兩個都是用來在某種意義上取代串口的。當然,有些Profile,比如一些人機交互設備 (鍵盤滑鼠之類的) 的profile 是在內核中實現的。

實 際上,我們還有一個重要的協議沒有介紹,這就是SDP --- 服務發現協議,這個協議可以認為和RFCOMM處於統一層次,因為它並不承載於RFCOMM之上,不過,這個協議卻十分特殊而重要,通過它,我們才能識別 出某一藍芽設備提供了哪些服務(Profile),從而為我所用。

嗯,協議棧已經有了,那我們怎麼使用藍芽呢? 回憶一下怎麼把大象放到冰箱里吧:

打開冰箱門
把大象放進冰箱
關上冰箱門
就是這麼簡單,一個藍芽服務也是這麼容易:

找到藍芽設備,這是HCI層負責的,使用 bluez-utils 包提供的 hcitool 來找到藍芽設備;

找到服務,RFCOMM 是通過不同的頻道 (channel) 來提供不同的Profile的,所以,我們需要找到我們要用的服務在設備上的哪個頻道上,這是通過同一個軟體包里的 sdptool 來完成的,沒錯,就是 SDP,服務發現協議。

連接恰當的服務,使用藍芽的特點就是如上所屬的那些了,而用戶態的工具所要完成的任務就是:

發現服務
使用服務
啟動 HCI 設備
首 先,我們需要啟動 hcid,讓 HCI 層的通信可以進行,對於 Debian 用戶來說,你需要安裝 bluez-utils 包,並啟動 hcid。如果你運行了 bluetooth 服務,並在 /etc/default/bluetooth 之中設置啟動了 HCID 的話

HIDD_ENABLED=1

插入 USB 適配器后,你的 hcid 就已經在運行了,看看相關信息吧:

inspiration:/etc/bluetooth# hciconfig -a
hci0: Type: USB
BD Address: 11:11:11:11:11:11 ACL MTU: 678:8 SCO MTU: 48:10
UP RUNNING PSCAN ISCAN
RX bytes:413 acl:0 sco:0 events:19 errors:0
TX bytes:323 acl:0 sco:0 commands:19 errors:0
Features: 0xbf 0xfe 0x8d 0x78 0x08 0x18 0x00 0x00
Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3
Link policy: RSWITCH HOLD SNIFF PARK
Link mode: MASTER
Name: 'inspiration-0'
Class: 0x3e0100
Service Classes: Networking, Rendering, Capturing, Object Transfer, Audio
Device Class: Computer, Uncategorized
HCI Ver: 1.2 (0x2) HCI Rev: 0x1fe LMP Ver: 1.2 (0x2) LMP Subver: 0x1fe
Manufacturer: Integrated System Solution Corp. (57)
這個過程是自動的,當然,你也可以用 hciconfig (8) 來手工控制。

尋找藍芽設備
HCI 已經啟動了,現在就可以用它來尋找藍芽設備了,當然,一定要先開啟藍芽設備的藍芽功能,這個不是廢話,手機的藍芽是默認關閉的,只有在手動控制之下才會發 送信號,允許被掃描到,不過設備的個體差異性太大了,這裡就沒法介紹了,我假設你已經自己摸索或參照說明書打開了設備的藍芽電源,現在,找找看吧

inspiration:/home/gnawux# hcitool scan
Scanning ...
00:17:00:7B:18:B8 Motorola SLVR

命令一出,略等片刻,藍芽設備就會被順利地找到。

查看設備提供的服務
利用 SDP 協議,我們還可以查看每個設備都有功能,能提供什麼服務,每種基於 RFCOMM 的服務都使用某種協議,佔據一個「頻道 (channel)」,這是我們使用服務時的一個重要參數

下面是例子,先看看自己:

[email protected]:~$ sdptool browse localBrowsing FF:FF:FF:00:00:00 ...Service Name: OBEX Object PushService RecHandle: 0x10000Service Class ID List: "OBEX Object Push" (0x1105)Protocol Descriptor List: "L2CAP" (0x0100) "RFCOMM" (0x0003) Channel: 9 "OBEX" (0x0008)Profile Descriptor List: "OBEX Object Push" (0x1105) Version: 0x0100
再看看別人 (手機)

[email protected]:~$ sdptool browse 00:17:00:7B:18:B8
Browsing 00:17:00:7B:18:B8 ...
Service RecHandle: 0x0
Service Class ID List:
"SDP Server" (0x1000)
Protocol Descriptor List:
"L2CAP" (0x0100)
"SDP" (0x0001)
Profile Descriptor List:
"SDP Server" (0x1000)
Version: 0x0100
Service Name: Dialup Networking Gateway
Service Description: Dialup Networking Gateway
Service Provider: Motorola
Service RecHandle: 0x10001
Service Class ID List:
"Dialup Networking" (0x1103)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 1
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
code_ISO639: 0x7a68
encoding: 0x6a
base_offset: 0xc800
Profile Descriptor List:
"Dialup Networking" (0x1103)
Version: 0x0100
Service Name: Voice Gateway
Service Description: Headset Audio Gateway
Service Provider: Motorola
Service RecHandle: 0x10003
Service Class ID List:
"Headset Audio Gateway" (0x1112)
"Generic Audio" (0x1203)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 3
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
code_ISO639: 0x7a68
encoding: 0x6a
base_offset: 0xc800
Profile Descriptor List:
"Headset" (0x1108)
Version: 0x0100
Service Name: Handsfree Voice Gateway
Service Description: Handsfree Voice Gateway
Service Provider: Motorola
Service RecHandle: 0x10007
Service Class ID List:
"Handfree Audio Gateway" (0x111f)
"Generic Audio" (0x1203)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 7
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
code_ISO639: 0x7a68
encoding: 0x6a
base_offset: 0xc800
Profile Descriptor List:
"Handsfree" (0x111e)
Version: 0x0101
Service Name: OBEX Object Push
Service Description: OBEX Object Push
Service Provider: Motorola
Service RecHandle: 0x10008
Service Class ID List:
"OBEX Object Push" (0x1105)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 8
"OBEX" (0x0008)
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
code_ISO639: 0x7a68
encoding: 0x6a
base_offset: 0xc800
Profile Descriptor List:
"OBEX Object Push" (0x1105)
Version: 0x0100
Service Name: OBEX File Transfer
Service Description: OBEX File Transfer
Service Provider: Motorola
Service RecHandle: 0x10009
Service Class ID List:
"OBEX File Transfer" (0x1106)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 9
"OBEX" (0x0008)
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
code_ISO639: 0x7a68
encoding: 0x6a
base_offset: 0xc800
Profile Descriptor List:
"OBEX File Transfer" (0x1106)
Version: 0x0100
Service Name: Image Push
Service Description: Image Push
Service Provider: Motorola
Service RecHandle: 0x1000a
Service Class ID List:
"Imaging Responder" (0x111b)
Protocol Descriptor List:
"L2CAP" (0x0100)
"RFCOMM" (0x0003)
Channel: 10
"OBEX" (0x0008)
Language Base Attr List:
code_ISO639: 0x656e
encoding: 0x6a
base_offset: 0x100
code_ISO639: 0x7a68
encoding: 0x6a
base_offset: 0xc800
Profile Descriptor List:
"Imaging" (0x111a)
Version: 0x0100
手機的比較多,我也沒有截短,方便大家看看手機可能提供的豐富藍芽功能。下一節我們將介紹幾個利用藍芽可以做的事情:

藍芽應用
上一節,通過 sdptool,我們看到筆者的手機提供了撥號、耳機、文件傳輸等功能,現在我們就來試試看。

利用藍芽傳輸文件

利用藍芽傳送文件使用的都是前面提到的 Obex 協議,這裡介紹幾個用法。

與手機互相推送文件
這是使用手機或計算機提供的"OBEX Object Push" (0x1105)服務,由另一方向其推送文件。使用的工具是 openobex-apps 包里的 obex_test工具

首先是向手機推送,對於我的手機,推送服務在頻道8:

[email protected]:~$ obex_test -b 00:17:00:7B:18:B8 8
Using Bluetooth RFCOMM transport
OBEX Interactive test client/server.
> c
Connect OK!
Version: 0x10. Flags: 0x00
> p wangxu.jpg me.jpg
PUT file (local, remote)> name=wangxu.jpg, size=34177
Going to send 34177 bytes
Made some progress...
Made some progress...
Made some progress...
Made some progress...
Made some progress...
PUT successful!
> q
可 以看到,執行完 obex_test 之後,進入一個交互狀態,首先建立連接,然後傳送文件 (本地文件名是 wangxu.jpg,存在手機上叫 me.jpg,這個是我隨便取的),最後,退出。這個過程需要看著點手機屏幕,可能要你確認是否連接,文件存放在哪裡,當然,這個和手機有關。

現在也可以看看手機向計算機推送,首先應該讓手機進入接收狀態,如果本地沒有啟動 Object PUSH 服務,己把它加上:

[email protected]:~$ sdptool add OPUSH
OBEX Object Push service registered
現在進入接收狀態,注意要使用計算機 (local) 的地址和頻道號:

[email protected]:~$ obex_test -b FF:FF:FF:00:00:00 9
Using Bluetooth RFCOMM transport
OBEX Interactive test client/server.
> s
現在,計算機進入了接收模式,在手機側發送文件到計算機就可以了。

使用 obexftp 上傳下載
使用"OBEX File Transfer" (0x1106)服務的 obexftp 是一個方便的工具,我們可以查看手機上的內容,並進行上傳下載,對於我的手機,對應的頻道是 9 (參考上面的 sdptool browse 的結果)。


看看有哪些目錄:

[email protected]:~$ obexftp -b 00:17:00:7B:18:B8 -B 9 -l
Browsing 00:17:00:7B:18:B8 ...
Channel: 9
Connecting...done
Receiving "(null)"...|








done
Disconnecting...done
可以看到,有四個有讀寫 (RW) 許可權的目錄,現在,再看看 audio 裡面有什麼

[email protected]:~$ obexftp -b 00:17:00:7B:18:B8 -B 9 -l audio
Browsing 00:17:00:7B:18:B8 ...
Channel: 9
Connecting...done
Receiving "audio"...|





done
Disconnecting...done
可以看到,這裡有一個 mp3 文件,我們把它取下來

[email protected]:~$ obexftp -b 00:17:00:7B:18:B8 -B 9 -c audio -g a.mp3
Browsing 00:17:00:7B:18:B8 ...
Channel: 9
Connecting...done
Sending "audio"...done
Receiving "a.mp3"...-done
Disconnecting...done


經過一段漫長的等待,傳送終於完成了,有點後悔選擇這麼大的文件進行傳輸。現在,再把 wangxu.jpg 放到 picture 目錄去


[email protected]:~$ obexftp -b 00:17:00:7B:18:B8 -B 9 -c picture -p wangxu.jpg
Browsing 00:17:00:7B:18:B8 ...
Channel: 9
Connecting...done
Sending "picture"... done
Sending "wangxu.jpg"...\done
Disconnecting...done
其他 obexftp(1) 的用法,大家自己學習文檔吧 :)

其他obex工具
還有 obexserver, qobex (qt based) 等工具,使用起來更為簡單,就不介紹了。



利用藍芽手機撥號

我們說過,藍芽的一個幾本功能就是模仿串口,串口的重要作用之一 (可能是最重要的了) 就是撥號,傳統的 DTE 也就是 Modem 嘛。實際上,通過 rfcomm,藍芽連接可以反映在 /dev/rfcomm0 這樣的字元設備上,像串口一樣操作。當然,我們最好先定義 /etc/bluetooth/rfcomm.conf,裡面根據手機的設備號和頻道號寫上

rfcomm0 {
# Automatically bind the device at startup
bind yes;

# Bluetooth address of the device
device 00:17:00:7B:18:B8;

# RFCOMM channel for the connection
channel 1;

# Description of the connection
comment "Motorola SLVR L7";
}
這樣,在啟動 bluetooth 服務的時候,就已經自動連接上了,而不需要使用rfcomm (1) 命令自己費力氣了。現在,可以使用任意一個喜歡的串口程序 (minicom, gtkterm 等等) 來對 /dev/rfcomm0 進行撥號了

輸入 AT 命令的第一個命令:

AT

OK

試著播一下號

ATD139012345;

這個是隨便寫的號碼,大家找認識的號碼播哦 (故意少寫了兩位,省得萬一試到人家頭上,呵呵),當然,也可以連接GPRS,這裡,我們藉助於最基本的撥號程序pppd 來實現,實際也是通過AT Command來實現的。

inspiration:/home/gnawux# cat /etc/ppp/peers/gprs
rfcomm1
115200
debug
noauth
defaultroute
usepeerdns
connect-delay 10000
crtscts
lock
lcp-echo-failure 4
lcp-echo-interval 65535
connect '/usr/sbin/chat -v -t3 -f /etc/ppp/peers/gprs_chat'


根據這個文件的內容,pppd 將利用 gprs_chat 這個文件的內容,在串口 rfcomm1 (也就是到我的L7手機的藍芽連接) 上進行交互,建立ppp連接,這個chat 文件的內容就是一些 AT Command 的交互:

inspiration:/home/gnawux# cat /etc/ppp/peers/gprs_chat
ABORT 'NO CARRIER'
ABORT 'ERROR'
ABORT 'NO DIALTONE'
ABORT 'BUSY'
ABORT 'NO ANSWER'
'' 'ATZ'
'OK' 'ATE0V1'
'OK' 'AT+CGDCONT=1,"IP","cmwap.cmcc.com","0.0.0.0",0,0'
'OK' 'ATD*99***1#'

上面就是一個GPRS建立需要的幾條 AT Command,文件建立之後,需要的操作很簡單,只要運行

pppd call gprs

就可以建立連接了,這是 ifconfig 得到的信息

ppp0 Link encap:Point-to-Point Protocol
inet addr:10.14.7.136 P-t-P:192.168.100.101 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:4 errors:1 dropped:0 overruns:0 frame:0
TX packets:13 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
RX bytes:64 (64.0 b) TX bytes:543 (543.0 b)
這是路由表和DNS設置:

inspiration:/etc/ppp/peers# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.100.101 * 255.255.255.255 UH 0 0 0 ppp0
default * 0.0.0.0 U 0 0 0 ppp0

inspiration:/etc/ppp/peers# cat /etc/resolv.conf
nameserver 221.130.33.52
nameserver 221.130.33.60

呵呵,非常簡單吧。

小結
至此,Linux與藍芽手機的全部內容,理論到操作已經全部完成了,基於的操作系統是使用 2.6 內核的 Debian GNU Linux,測試的手機包括 Motorola SLVR L7 和 Nokia N-Gage QD 各一部,藍芽適配器晶元是 Integrated System Solution Corp. KY-BT100 Bluetooth Adapter,所有測試都非常順利,也祝讀者朋友玩得開心。

[火星人 ] 藍芽:Linux與手機已經有812次圍觀

http://coctec.com/docs/linux/show-post-116120.html