在S3C2410上移植bluetooth(藍牙)(一)

admin @ 2014-03-25 , reply:0

    最近兩天在HHARM2410-R3上移植了USB藍牙設備和BlueZ 藍牙協議棧,呵呵,藍牙果然是個很好的東西,協議棧內容很豐富,掛上去以後可以使用很多功能。我現在就可以用它來接收GPS數據以及和用手機上網。我是在做車載的,所以特別有用。積累了一些關於藍牙的知識,但是算是初步的,把我的經驗發上來,各位做過藍牙的大哥請多指導。

    先介紹一下硬體,我用的是電腦賣場裡面隨便買到的USB藍牙適配器,價格在80元左右,應該是台產的,沒有牌子,像一個小一點的U盤。買之前叫賣家在windows下測試一下,帶一個帶藍牙的手機過去試試看,確認能用再買。

    linux上的藍牙協議棧有好幾個,官方的藍牙協議棧是Bluez,在www.bluez.org上能找到所有的說明文檔和源代碼。我先是在自己的pc上安裝了bluez的協議棧,然後又把它移植到了華恆HHARM2410-R3上。

(一) 在Red hat 9上安裝Bluez

   在pc 上的安裝我參考了O'Reilly的Linux Unwired一書,chapter 7中詳細地介紹了linux下的bluetooth的基礎知識、安裝、配置和使用。安裝前必須了解一下bluez的基本結構,直接位於發射傳輸協議之上的協議是HCI(host control interface),我的手機和藍牙GPS用到的高層協議是服務發現協議SDP和模擬串口的協議RFCOMM,中間那一層協議是L2CAP,應該是處理邏輯鏈路的吧,我並不是很清楚,請參考bluez的官方文檔。
HHARM2410-R3上用到內核版本是2.4.18,於是我在pc上安裝 bluez時也使用了2.4.18的內核。使用bluez必須要對內核打patch的,於是到www.kernel.org上下載了linux- 2.4.18.tar.bz2後到http://www.bluez.org/patches.html上下載針對2.4.18的patch,patch -2.4.18-mh15.gz。於是,解壓,打patch:
# tar xjvf linux-2.4.18.tar.bz2
# cd linux/
# gzip -dc ../patch-2.4.18-mh15.gz | patch -p1
注意一下這時的patch的輸出,在源代碼方面的patch是針對driver/、include/、net/目錄下的代碼的修改,並沒有修改到內核部分的內容,應該沒有修改到linux核心的東西,在移植到S3C2410時應該不會有太大的問題。
下面就是編譯內核,在config的時候關於bluez我的配置是這樣的:
#
# Bluetooth support
#

CONFIG_BLUEZ=m
CONFIG_BLUEZ_L2CAP=m
CONFIG_BLUEZ_SCO=m
CONFIG_BLUEZ_RFCOMM=m
CONFIG_BLUEZ_RFCOMM_TTY=y
CONFIG_BLUEZ_BNEP=m
CONFIG_BLUEZ_BNEP_MC_FILTER=y
CONFIG_BLUEZ_BNEP_PROTO_FILTER=y


#
# Bluetooth device drivers
#
CONFIG_BLUEZ_HCIUSB=m
# CONFIG_BLUEZ_HCIUSB_SCO is not set
CONFIG_BLUEZ_HCIUART=m
CONFIG_BLUEZ_HCIUART_H4=m
CONFIG_BLUEZ_HCIUART_BCSP=m
# CONFIG_BLUEZ_HCIUART_BCSP_TXCRC is not set
# CONFIG_BLUEZ_HCIBFUSB is not set
CONFIG_BLUEZ_HCIDTL1=m
CONFIG_BLUEZ_HCIBT3C=m
CONFIG_BLUEZ_HCIBLUECARD=m
CONFIG_BLUEZ_HCIBTUART=m
CONFIG_BLUEZ_HCIVHCI=m
    供大家參考,Linux Unwired一書中有詳細的說明,注意如果使用make menuconfig,一定要打開一下.config文件看看CONFIG_BLUEZ_RFCOMM_TTY=y,不能為n或者m。還有注意 CONFIG_USB_BLUETOOTH一定不能選(在USB support下),否則會影響到bluez的運行的。
    內核編譯好了就開始準備 bluez的庫和工具了。到http://www.bluez.org/download.html上下載最新的bluez程序包,我只下載了bluez -libs-2.20.tar.gz,bluez-utils-2.20.tar.gz,bluez-pin-0.25.tar.gz三個包,分別是庫,工具集和由bluez提供的一個pin_helper。由於在pc下,安裝的過程沒什麼好說的,解壓,./configure,make,make install。
    然後就是注意一下默認配置目錄/etc/bluetooth/下的hcid.conf配置文件,這是用來配置後台daemon進程hcid的。如果把這台pc機器+藍牙適配器看成是一個藍牙設備的話,進程hcid就管理這個藍牙設備的基本配置信息,例如名稱,class,地址, feature等等。還有當設備與其他藍牙設備Bonding/Pairing即所謂的配對時,處理PIN code的程序也是hcid,而在hcid.conf腳本中比較重要的一項就是pin_helper,默認的配置是pin_helper= /usr/bin/bluepin,這個是python寫的用來讀取用戶輸入的PIN code的程序,安裝bluez-pin包的時候裝在/usr/bin下的。
這裡有必要了解一下配對的過程,我感覺就是兩個設備互相通密碼建立相互之間連接的過程。我看了hcid部分的代碼,了解的大致是這樣:比如兩個藍牙設備A和B,A先發送要求配對的請求給B,B由用戶設置好配對的密碼即 PIN code,然後回一個消息給A,說你想配對可以呀,知道我的密碼嗎?然後A就發送PIN code過去,B看和自己的密碼相符合,就發送一個replyOK的消息給A,這樣兩者就建立起來了信任關係。
在pc+藍牙適配器這個藍牙設備A 上,如果這個設備先發送配對請求給另一個遠程設備B,那麼當B發送詢問密碼請求過來時,在A上運行的hcid後台進程就通過一個pin_helper的程序讀取PIN code,併發送回給B;如果遠程設備B先發送配對請求給A,hcid上用作驗證的PIN code就是/etc/bluetooth/pin的內容,如果讀取失敗程序在啟動的時候會默認地設置一個密碼的,代碼在bluez- utils/hcid/security.c中的init_security_data函數中,默認的是BlueZ。為了和我的手機相配,我把它改成了 123,手機只能輸入數字。
關於其他hcid.conf的設置,請man hcid.conf。
設置好以後,換上新內核,啟動 linux。插入USB藍牙適配器,# dmesg | tail會發現有usb.c: USB device 2 (vend/prod 0x1131/0x1001) is not claimed by any active driver.這個問題,不管它,只要有usb.c: registered new driver hci_usb的消息就可以,然後 # lsmod 會發現hci_usb的模塊被安裝了,再# modprobe rfcomm,這樣基本上所有的模塊都安裝齊了。
# hciconfig hci0 up
# hcid -f /etc/bluetooth/hcid.conf
啟動hci設備和hcid精靈進程
# hciconfig -a
hci0:   Type: USB
       BD Address: 00:11:67:0F:BB:A1 ACL MTU: 678:8 SCO MTU: 48:10
       UP RUNNING PSCAN ISCAN
       RX bytes:115 acl:0 sco:0 events:15 errors:0
       TX bytes:313 acl:0 sco:0 commands:15 errors:0
       Features: 0xff 0xff 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: SLAVE ACCEPT
       Name: 'BlueZ (0)'
       Class: 0x000100
       Service Classes: Unspecified
       Device Class: Computer, Uncategorized
       HCI Ver: 1.2 (0x2) HCI Rev: 0x1ae LMP Ver: 1.2 (0x2) LMP Subver: 0x1ae
       Manufacturer: Integrated System Solution Corp. (57)
可以看到目前設備的配置情況,有些是從hcid.conf中讀取的,有些是從設備中讀取的。
下面,打開手機上的藍牙,啟動藍牙GPS
# hcitool scan
Scanning ...
       00:0E:07:58:1A:33       T628
       00:08:1B:C0:D1:3C       HOLUX GR-231
這樣就看到了兩個設備了,我用的是索愛的T628和HOLUX的藍牙GPS,前面的一串應該是藍牙設備唯一的地址。
#sdptool browse                 可以看到每個設備所提供的服務
Inquiring ...
Browsing 00:0E:07:58:1A:33 ...
Service Name: Dial-up Networking
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

.............

Service Name: Serial Port 1
Service RecHandle: 0x10003
Service Class ID List:
 "Serial Port" (0x1101)
Protocol Descriptor List:
 "L2CAP" (0x0100)
 "RFCOMM" (0x0003)
   Channel: 4

............

Service Name: OBEX Object Push
Service RecHandle: 0x10005
Service Class ID List:
 "OBEX Object Push" (0x1105)
Protocol Descriptor List:
 "L2CAP" (0x0100)
 "RFCOMM" (0x0003)
   Channel: 10
 "OBEX" (0x0008)
Profile Descriptor List:
 "OBEX Object Push" (0x1105)
   Version: 0x0100
 
Browsing 00:08:1B:C0:D1:3C ...

手機上綁定了很多的服務,有撥號服務,音頻服務,串口服務,文件交換服務(OBEX)...在SDP協議下,每個服務綁定到一個Channel上。GPS上沒有綁定服務,它只作為虛擬串口設備來使用。
利用實用工具rfcomm可以把遵循RFCOMM的服務bind到一個類似的串口設備上。在綁定之前,必須確保/dev下有rfcomm*的設備,如果沒有,就自己建立:
# mknod -m 666 /dev/rfcommX c 216 X (X是數字)
這樣就可以綁定了,比如我需要用手機撥號上網的功能,看到它的Channel 1是RFCOMM的Dialup Networking功能,則:
# rfcomm bind 0 00:0E:07:58:1A:33 1
即將00:0E:07:58:1A:33設備的Channel 1服務綁定到/dev/rfcomm0上,這樣,就相當於建立了一個虛擬的串列連接到一個可以撥號的無線modem上了,打開minicom,設置串口為 /dev/rfcomm0,波特率19200,8N1,鍵入atz,返回OK。用ppp就可以撥號上網了,第一次連接時手機會彈出個輸入框問PIN code,以後就不用了。
GPS設備只是作為串口來用的,也很簡單:
# rfcomm bind 1 00:08:1B:C0:D1:3C
打開minicom設置波特率為4800就可以讀GPS數據了,大功告成!
另外,sdpd程序是本設備提供給對外的看到的服務,可以通過sdptool add --channel=X SP來增加對外的服務,我沒有研究過。還有對於文件傳輸OBEX和個人區域網BNEQ還需要繼續學習。

--同濟大學高性能計算中心 Dennis
歡迎各位發郵件給我和我討論 dennis.he.2005@gmail.com




[admin via 研發互助社區 ] 在S3C2410上移植bluetooth(藍牙)(一)已經有2116次圍觀

http://cocdig.com/docs/show-post-42789.html