1. gzyueqian
      18529173453
      首頁 > 新聞中心 > > 正文

      藍牙模塊在HHARM2410上的移植

      更新時間: 2007-06-22 10:28:58來源: 粵嵌教育瀏覽量:781

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

        一切版權歸bluez的作者---同濟大學高性能計算中心 Dennis

        歡迎各位發郵件給我和我討論 dennis.he.2005@gmail.com
        先介紹一下硬件,我用的是電腦賣場里面隨便買到的 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還需要繼續學習。

      (二)在HHARM2410-R3上的移植
        完成了在普通red hat上的安裝,熟悉了藍牙協議棧一些基本的東西,下面的任務就是把協議棧搬到開發板上了。
        步當然是內核了,由于華恒的內核代碼改過,我也不知道從bluez上下載的patch能不能使用,試試看了,只好。
      # cd /HHARM2410/kernel
      # gzip -dc ~/patch-2.4.18-mh15.gz | patch -p1
      # find ./ -name '*rej'
      ./fs/cramfs/inode.c.rej
        不好,有文件不能patch,看看是針對cramfs文件系統的patch,我也不清楚為什么bluez的patch會修改到cramfs,不過我想問題應該不大。內核源代碼關于bluetooth的部分華恒應該沒有改過,因此patch的主要部分應該是沒有問題的。如果內核編譯后發生問題,我想大概也只有把內核代碼翻出來看了。
      先就這樣了,用用試試看好了。與普通pc上的類似,只不過有些是m的現在統統為y了。我的配置關于Bluez的部分設置為:
      #
      # Bluetooth support
      #
      CONFIG_BLUEZ=y
      CONFIG_BLUEZ_L2CAP=y
      # CONFIG_BLUEZ_SCO is not set
      CONFIG_BLUEZ_RFCOMM=y
      CONFIG_BLUEZ_RFCOMM_TTY=y
      CONFIG_BLUEZ_BNEP=y
      CONFIG_BLUEZ_BNEP_MC_FILTER=y
      CONFIG_BLUEZ_BNEP_PROTO_FILTER=y
      # CONFIG_BLUEZ_HIDP is not set
      #
      # Bluetooth device drivers
      #
      CONFIG_BLUEZ_HCIUSB=y
      # CONFIG_BLUEZ_HCIUSB_SCO is not set
      # CONFIG_BLUEZ_HCIUART is not set
      # CONFIG_BLUEZ_HCIBFUSB is not set
      # CONFIG_BLUEZ_HCIDTL1 is not set
      # CONFIG_BLUEZ_HCIBT3C is not set
      # CONFIG_BLUEZ_HCIBLUECARD is not set
      # CONFIG_BLUEZ_HCIBTUART is not set
      # CONFIG_BLUEZ_HCIVHCI is not set

        device部分就設了個USB的,其他的就不設置了。
        下面繼續make dep;make zImage的常規過程,OK,沒有發生編譯問題,可以稍微舒口氣了。
      下面要移植Bluez的基礎庫了,在Redhat 9下執行
      # ldd /usr/lib/libbluetooth.so.1.0.17
      libc.so.6 => /lib/libc.so.6 (0x4002c000)
      /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000)
        發現沒有依賴什么莫名其妙的庫,應該換個編譯器就可以了,configure一下就可以了。我的配置命令很簡單:
      # ./configure --host=armv4l --prefix=/HHARM2410/applications/bluezport/libs CC=/opt/host/armv4l/bin/armv4l-unknown-linux-gcc CPP=/opt/host/armv4l/bin/armv4l-unknown-linux-cpp AR=/opt/host/armv4l/bin/armv4l-unknown-linux-ar STRIP=/opt/host/armv4l/bin/armv4l-unknown-linux-strip RANLIB=/opt/host/armv4l/bin/armv4l-unknown-linux-ranlib
      LD=/opt/host/armv4l/bin/armv4l-unknown-linux-ld
      # make
      # make install
        OK了,到了/HHARM2410/applications/bluezport/libs下看看,我也不清楚為什么,居然只有.a和.la的靜態庫,沒有動態庫。只好自己動手,到bluz-libs-2.17/src/下,自己編譯動態庫:
      # /opt/host/armv4l/bin/armv4l-unknown-linux-gcc -shared -o libbluetooth.so.1.0.17 bluetooth.o hci.o sdp.o
      再做兩個符號連接
      # ln -s libbluetooth.so.1.0.17 libbluetooth.so
      # ln -s libbluetooth.so.1.0.17 libbluetooth.so.1
        好了,庫交叉編譯完畢,mv到/HHARM2410/application/bluezport/libs/lib文件夾下就可以了。

        接著移植Bluez的工具集。與庫類似,先看一下各個程序需要用到什么庫,比如:
      #ldd /usr/sbin/hcid
      libbluetooth.so.1 => /usr/lib/libbluetooth.so.1 (0x40035000)
      libc.so.6 => /lib/libc.so.6 (0x40042000)
      /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
        挨個試試需要用的工具,發現需要的庫華恒和Bluez都提供了,應該換個編譯器編譯一下就可以了。編譯之前我為了到板子上與我自己的手機連接方便修改了bluez-utils-2.17/hcid/security.c文件,在init_security_data函數中的設置默認的密碼,非常簡單地改了兩行:
      strcpy(hcid.pin_code, "123");
      hcid.pin_len = 3;
        然后configure我想就行了,我的configure設置為:
      # ./configure --prefix=/HHARM2410-R3/applications/bluezport/utils --includedir=/HHARM2410-R3/applications/bluezport/libs/include --libdir=/HHARM2410-R3/applications/bluezport/libs/lib --with-bluez=/HHARM2410-R3/applications/bluezport/libs --disable-test --disable-cups --disable-pcmia --host=armv4l CC=/opt/host/armv4l/bin/armv4l-unknown-linux-gcc CPP=/opt/host/armv4l/bin/armv4l-unknown-linux-cpp AR=/opt/host/armv4l/bin/armv4l-unknown-linux-ar STRIP=/opt/host/armv4l/bin/armv4l-unknown-linux-strip RANLIB=/opt/host/armv4l/bin/armv4l-unknown-linux-ranlib LD=/opt/host/armv4l/bin/armv4l-unknown-linux-ld
      # make
        我在這步make的時候出現了一點小錯誤,好像是說PATH_MAX沒有定義,這個是LINUX設置的存放路徑名緩沖區的長度。應該是少包含了一個頭文件造成的。我沒有去仔細考究,就在當前文件下的config.h中添加了三行:
      #ifndef PATH_MAX
      #define PATH_MAX 4095/* PAGE_SIZE - 1 */
      #endif
        采用簡單粗魯的添加定義的方式。再make,通過。
      # make install
        好了,工具集都在/HHARM2410-R3/applications/bluezport/util下了
      ,由于在PC的LINUX下的默認pin_helper /usr/bin/bluepin是用python寫的代碼,在2410上當然不能用了,所以要自己寫一個pin_helper的程序。翻翻/usr/bin/bluepin的代碼以及hcid/security.c的代碼,事實上hcid進程在驗證PIN code的時候開了一個pipe指向pin_helper進程的標準輸出,pin_helper進程向用戶詢問PIN code,如果用戶輸入密碼XXXX就以"PIN:XXXX"的形式寫到標準輸出中去,如果用戶reject就寫個"ERR"回去。
        我以一種簡單的方式實現pin_helper程序,即固定地寫一個code回去,比如123,犧牲安全性。
      用腳本實現就是:
      #!/bin/sh

      echo "PIN:123"
      用C實現一個就是:
      #include <stdio.h>

      int main(int argc, char* argv[])
      {
      printf("PIN:123");
      }
        交叉編譯成my_pin_helper再放到板子的/usr/bin下,那么就可以把板子的hcid.conf修改成:
      pin_helper /usr/pin/my_pin_helper
        后來,我在板子上也用MiniGUI寫了一個pin_helper,也挺簡單的。

        好了,一切準備完畢,做好ramdisk,記得在/dev下mknod幾個rfcomm,放到板子上,可以運行!
      插上USB適配器,連模塊都不用probe
      # hciconfig hci0 up
      # hcid -f /etc/bluetooth/hcid.conf
      # hciconfig -a
      看到設備了,其他的運行都OK。結合ppp就可以用手機上網了~~

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 亚洲一区二区三区香蕉 | 亚洲一级在线播放a | 亚洲欧美色一区二区三区 | 亚洲综合一区精品一区 | 午夜性爱大全在线视频播放 | 亚洲制服丝袜精品久久100部 |