bcm4330藍牙分析總結

     對於藍牙無論最底層的硬件驅動如何實現,都會在HCI層進行統一。也就是說,HCI在主機端的驅動主要是爲上層提供統一接口,讓上層協議不依賴於具體的硬件實現。HCI在硬件中的固件與HCI在主機端的驅動通信方式有多種,比如UART,USB和SDIO等。

       HCI層在所有的設備面前都被抽象爲一個hci_dev結構體,因此,無論實際的設備是哪種藍牙設備、通過什麼方式連接到主機,都需要向HCI層和藍牙核心層註冊一個hci_dev設備,註冊過程由hci_registe_dev()函數來完成,同時也可以通過hci_unregister_dev()函數卸載一個藍牙設備。

具體的藍牙驅動有很多,常用的在linux內核都自帶有驅動。比如:hci_vhci.c爲藍牙虛擬主控制器驅動程序,hci_uart.c(或者hci_ldisc.c/ hci_H4.C)爲串口接口主控制器驅動程序,btusb.cUSB接口主控制器驅動程序,btsdio.cSDIO主控制器驅動程序。

 

總結一下,藍牙驅動的三個步驟:

1, 串口驅動必須要先就緒(uart藍牙而言),這是cpu和藍牙模塊之間的橋樑。

2, 藍牙初始化,模塊上電和PSKEY的設置。

3, 通過hciattach建立串口和藍牙協議層之間的數據連接通道。

 

藍牙模塊上電

        一般是通過一個GPIO來控制的,通常是先高再低再高;

PSKEY的設置

        通過串口發送命令給藍牙模塊,對於串口必須要知道的是要能通訊,必須得設好波特率,另外一方面藍牙模塊的晶振頻率也必須要設,否則它不知道該怎麼跳了;當然不同的芯片可能初始化的過程也不一樣,也許還要下載firmware等等,一般是通過bccmd來完成的。

 

經過上面的設置基本上藍牙模塊以及可以正常工作了;

        但是還沒有和上面的協議層建立紐帶關係,也就是說從uart收到的數據還沒有傳給hci層;

        如何把uart也就是藍牙模塊傳上來的數據交給hci層,在驅動裏面是通過一個叫做disc的機制完成的,這個機制本意是用來做過濾或者限制收上來的字符的,但是在藍牙驅動裏面則直接把數據傳給了藍牙協議層,再也不回到串口的控制了;

Uart交給hci層的前面對比圖:

 

簡單總結一下,數據的流程,

基本上是:

1, uart口取得藍牙模塊的數據;

2, uart口通過ldisc傳給hci_uart;

3, hci_uart傳給在其上的bcsp

4, bcsp傳給hci層;

5, hci層傳給l2cap

6, l2cap層再傳給rfcomm

 

 

Rfkill平臺設備部分

static structresource nabi2_bcm4330_rfkill_resources[] = {

         {

                   .name   = "bcm4330_nshutdown_gpio",

                   .start  = TEGRA_GPIO_PD0,

                   .end    = TEGRA_GPIO_PD0,

                   .flags  = IORESOURCE_IO,

         },

         {

                   .name   = "bcm4330_nreset_gpio",

                   .start  = TEGRA_GPIO_PU0,

                   .end    = TEGRA_GPIO_PU0,

                   .flags  = IORESOURCE_IO,

         },

};

static structplatform_device nabi2_bcm4330_rfkill_device = {

         .name = "bcm4330_rfkill",

         .id             = -1,

         .num_resources  = ARRAY_SIZE(nabi2_bcm4330_rfkill_resources),

         .resource       = nabi2_bcm4330_rfkill_resources,

};

 

Rfkill平臺驅動部分(主要用來給藍牙上電和下電)

static intbcm4330_bt_rfkill_set_power(void *data, bool blocked)

{

模塊上電和下電操作。

         }

static const structrfkill_ops bcm4330_bt_rfkill_ops = {

         .set_block =bcm4330_bt_rfkill_set_power,

};

static int bcm4330_rfkill_probe(structplatform_device *pdev){

……

         bt_rfkill = rfkill_alloc("bcm4330Bluetooth", &pdev->dev,

                            RFKILL_TYPE_BLUETOOTH,&bcm4330_bt_rfkill_ops, NULL);

       rfkill_register(bt_rfkill);

……

}

static struct platform_driverbcm4330_rfkill_driver = {

         .probe= bcm4330_rfkill_probe,

         .driver= {

                      .name = "bcm4330_rfkill",

                      .owner = THIS_MODULE,

         },

};

static int __init bcm4330_rfkill_init(void)

{

         returnplatform_driver_register(&bcm4330_rfkill_driver);

}

 

        Rfkill驅動很簡單,僅僅是註冊了一個bcm4330_rfkill_driver的平臺驅動。在彼配的時候會註冊一個rfkill_ops bcm4330_bt_rfkill_ops 函數集。當用戶操作/sys/class/rfkill/rfkill0/state時將會調用到bcm4330_bt_rfkill_set_power這個函數,用來給藍牙上電和關電。

 

        藍牙驅動在內核裏面有(個別產品有自己專門的驅動除外,即便如此專門的驅動實現架構也跟內核自帶的一模一樣),對於串口藍牙的驅動是:/kernel/drivers/Bluetooth/hci_ldisc.c

        這個驅動其實沒什麼好講的,hci提供了統一的接口函數,不管是藍牙模塊是usb,sdio,uart……都只需要實現這些接口就行了。

所有藍牙驅動都只是圍繞一個hci_dev結構體,然後完成下面這些函數就行了。

         hdev->open  = hci_uart_open;

         hdev->close = hci_uart_close;

         hdev->flush = hci_uart_flush;

         hdev->send  = hci_uart_send_frame;

         hdev->destruct = hci_uart_destruct;

所有的接口在hci層做了統一,hci層負責跟藍牙協議通信,所以你只要實現hci層提供的接口,協議你無需多管。

 

藍牙初始化XXX_init.rc文件添加如下:

 

……

# bluetooth

# bluetooth MAC address programming

         chown bluetooth bluetooth /system/etc/bluetooth   #設備該目錄有藍牙權限

         setprop ro.bt.bdaddr_path"/system/etc/bluetooth/bdaddr"  #設置藍牙地址路徑 

         chmod 0660/sys/class/rfkill/rfkill0/state                      #rfkill文件具有可讀可寫權限

         chmod 0660/sys/class/rfkill/rfkill0/type

         chown bluetooth bluetooth/sys/class/rfkill/rfkill0/state #rfkill文件具有藍牙權限

         chown bluetooth bluetooth/sys/class/rfkill/rfkill0/type

 

#BCM #bccmd 主要用來初始化藍牙,比如說上電,設置波特率,下載firmware……

       #具體參照brcm_patchram_plus.c這個文件有詳細的使用說明

service hciattach/system/bin/brcm_patchram_plus --enable_hci --scopcm=0,2,0,0,0,0,0,0,0,0 \

--baudrate 3000000 --patchram /etc/firmware/bcm4330.hcd--enable_lpm --tosleep=5000 --create_bdaddr /dev/ttyHS2 

#創建藍牙地址(因爲bcm4330沒有物理藍牙地址),使用uart2hci連接。

    user bluetooth

    group bluetooth net_bt_admin

disabled

 

……

 

藍牙驅動依賴是藍牙協議在android裏面已支持bluez協議,我們只需要要配製的時候選上bluez協議就可以了。

CONFIG_BT =y

CONFIG_BT_RFCOMM =y

CONFIG_BT_BNEP = y

CONFIG_BT_CMTP =y

CONFIG_BT_L2CAP=y

CONFIG_BT_SCO=y

如果是linux的話,或者你還需要自己再移植bluez協議。

 

好了,到這裏藍牙就可以使用了,進入藍牙測試。

1、  藍牙上電

# echo  1 >/sys/class/rfkill/rfkill0/state

2、  藍牙初始化

# XXX_init.rc裏面做好了。

3、  測試藍牙驅動

# hciconfig

      說明藍牙驅動已經正常初始化並加載了。

4、  激活藍牙

#hciconfig   hci0    up

# hciconfig

說明藍牙已經初激活了。

5、  查看藍牙地址

# hcitool   dev

6、  掃描周圍藍牙設備

# hcitool  scan

 

出現上面的類似畫面說明藍牙已經工作正常了。

 

7、上面是用命令測試,要在android上使用的話,還需要把藍牙配製上。

找到相對應的BoadConfig.mk文件設置BOARD_HAVE_BLUETOOTH

               BOARD_HAVE_BLUETOOTH:= true

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章