1. 程式人生 > >Freescale i.MX 6 MNC平臺移植BT/WIFI驅動

Freescale i.MX 6 MNC平臺移植BT/WIFI驅動

       此專案之前移植到Android6.0.1版本。基本系統可以起來了。現在要調一下WiFi和Bluetooth。此板上用的是Broadcom BCM89335的WiFi和Bluetooth二合一晶片。WiFi通過4線SDIO和SoC相連線,Bluetooth通過UART和SoC相連線。晶片的框圖如下:

       WiFi部分的電路圖如下:

       SoC側接的是SD3的SD3_DAT0 ~SD3_DAT3, SD3_CLK及SD3_CMD。

       根據電路圖,WL_REG_ON接到SoC的A19(NANDF_D4)PIN,查IOMux_Tool,此PIN對應的GPIO為GPIO2_4。

配置WiFi 相關的DTS及Kernel

       有了以上資料,就可以開始配置DTS檔案了。修改/kernel_imx/arch/arm/boot/imx6dq-sabresd.dtsi檔案。找到WL_REG_ON的配置wlreg_on,修改gpio的值為gpio2_4。

              wlreg_on:[email protected] {

                     compatible= "regulator-fixed";

                     regulator-min-microvolt= <5000000>;

                     regulator-max-microvolt= <5000000>;

                     regulator-name= "wlreg_on";

-            gpio = <&gpio4 7 0>;

+            gpio = <&gpio2 4 0>;

           startup-delay-us = <100>;

           enable-active-high;

      };

       找到SDIO 3的PIN配置pinctl_usdhc3,把DAT4~DAT7刪除,增加GPIO2_4為GPIO模式。

              pinctrl_usdhc3:usdhc3grp {

                     fsl,pins= <

                            MX6QDL_PAD_SD3_CMD__SD3_CMD           0x17059

                            MX6QDL_PAD_SD3_CLK__SD3_CLK             0x10059

                            MX6QDL_PAD_SD3_DAT0__SD3_DATA0       0x17059

                            MX6QDL_PAD_SD3_DAT1__SD3_DATA1       0x17059

                            MX6QDL_PAD_SD3_DAT2__SD3_DATA2       0x17059

                            MX6QDL_PAD_SD3_DAT3__SD3_DATA3       0x17059

-               MX6QDL_PAD_SD3_DAT4__SD3_DATA4         0x17059

-               MX6QDL_PAD_SD3_DAT5__SD3_DATA5         0x17059

-               MX6QDL_PAD_SD3_DAT6__SD3_DATA6         0x17059

-                MX6QDL_PAD_SD3_DAT7__SD3_DATA7          0x17059

+               MX6QDL_PAD_NANDF_D4__GPIO2_IO04       0x13069  /* WL_REG_ON */

          >;

       找到SDIO3 的配置usdhc3,把bus-width改為4,增加wifi-host。

&usdhc3 {

       pinctrl-names= "default";

       pinctrl-0= <&pinctrl_usdhc3>;

-    bus-width = <8>;

+    bus-width = <4>;

       cd-gpios= <&gpio2 0 0>;

       wp-gpios= <&gpio2 1 0>;

       no-1-8-v;

+     wifi-host;

+     pm-ignore-notify;

       keep-power-in-suspend;

       enable-sdio-wakeup;

       status= "okay";

};

       另外搜尋到usdhc5中也寫了wifi-host,把它刪除。

&uart5 {

    pinctrl-names = "default";

    pinctrl-0 = <&pinctrl_uart5_1>;

@@ -1070,25 +1084,25 @@

       cd-gpios = <&gpio2 2 0>;

       wp-gpios = <&gpio2 3 0>;

       no-1-8-v;

-       wifi-host;

-       pm-ignore-notify;

       keep-power-in-suspend;

        enable-sdio-wakeup;

-       status = "okay";

+       status = "disabled";

 };

       wifi-host標誌是驅動程式用來識別此SDIO是否連線有WiFi模組的標誌。具體程式碼可參考drivers/mmc/host/sdhci-esdhc-imx.c檔案中的sdhci_esdhc_imx_probe_dt()函式。

       if (of_get_property(np, "wifi-host",NULL)) {

                wifi_mmc_host = host->mmc;

                dev_info(mmc_dev(host->mmc),"assigned as wifi host\n");

       }

       if (of_get_property(np, "pm-ignore-notify", NULL)) {

                host->mmc->pm_caps |=MMC_PM_IGNORE_PM_NOTIFY;

        }

       所以為了避免出現干擾,系統中只保留了一個wifi-host的SDIO配置。

       配置Kernel配置檔案arch/arm/comfigs/imx_v7_android_defconfig檔案。把CONFIG_BCMDHD開啟,其它的沒用的關閉。

CONFIG_USB_NET_CDC_EEM=y

-CONFIG_ATH_CARDS=m

-CONFIG_ATH6KL=m

-CONFIG_ATH6KL_SDIO=m

-# CONFIG_BCMDHD is notset

+# CONFIG_ATH_CARDSis not set

+# CONFIG_ATH6KL isnot set

+# CONFIG_ATH6KL_SDIOis not set

+CONFIG_BCMDHD=y

 CONFIG_BCMDHD_SDIO=y

 CONFIG_BCMDHD_FW_PATH="/system/etc/firmware/bcm/fw_bcmdhd.bin"

 CONFIG_BCMDHD_NVRAM_PATH="/system/etc/firmware/bcm/bcmdhd.cal"

-CONFIG_BRCMFMAC=m

-CONFIG_RTL8821AS=m

+CONFIG_BRCMFMAC=y

+# CONFIG_RTL8821ASis not set

 #CONFIG_INPUT_MOUSEDEV_PSAUX is not set

       至此,Kernel部分的配置算完成了。接下來需要移植驅動了。

移植Supplicant

       從Broadcom網上下載了最新的驅動檔案包BCM89335_DHD_141_91_FW_AARD01SRC41_6_37_39_38_Supp_126_wapi.7z,解開看了一下,主要分兩部分,Supplicant和Driver,決定先移植Supplicant。

       Supplicant也分為兩類,一種是支援WAPI的,另一個是不支援的,為了簡單起見,選擇了HOSTAP_REL_0_8_0_126.tar.gz這個不支援WAPI的版本。解開移到external目錄下。

       tar zxvf HOSTAP_REL_0_8_0_126.tar.gz

       mv HOSTAP_REL_0_8_0_126  external/

       看了一下里面的移植說明,建立符號連結

       cd external/HOSTAP_REL_0_8_0_126/libbcmhd

       ln -s ../src .

       因為原先系統中已經有了一份wpa_supplicant,所以預設應該不會被編譯到,或者會把模組重定義,所以需要先把系統中老的wpa_supplicant遮蔽掉。修改external/wpa_supplicant/Android.mk檔案。註釋掉編譯。

--- a/external/wpa_supplicant_8/Android.mk

+++ b/external/wpa_supplicant_8/Android.mk

@@ -1,9 +1,9 @@

 LOCAL_PATH:= $(call my-dir)

-ifndefWPA_SUPPLICANT_VERSION

-WPA_SUPPLICANT_VERSION:= VER_0_8_X

-endif

-ifeq($(WPA_SUPPLICANT_VERSION),$(filter$(WPA_SUPPLICANT_VERSION),VER_0_8_X VER_0_8_UNITE))

+#ifndefWPA_SUPPLICANT_VERSION

+#WPA_SUPPLICANT_VERSION:= VER_0_8_X

+##endif

+ifneq($(WPA_SUPPLICANT_VERSION),$(filter$(WPA_SUPPLICANT_VERSION),VER_0_8_X VER_0_8_UNITE))

 #The order of the 2 Android.mks does matter!

 #TODO: Clean up the Android.mks, reset all the temporary variables at the

 #end of each Android.mk, so that one Android.mk doesn't depend on variables

       編譯,報錯,提示keystore-engine什麼的沒有定義,搜了一下,發現此函式在/system/security/keystore-engine下定義。根據這個Android.mk,會生成libkeystore-engine.so檔案。

ifeq($(OPENSSL_FLAVOR),BoringSSL)

 LOCAL_MODULE := libkeystore-engine

 LOCAL_SRC_FILES := \

       android_engine.cpp

else

 LOCAL_MODULE := libkeystore

 LOCAL_MODULE_RELATIVE_PATH := ssl/engines

 LOCAL_SRC_FILES := \

       eng_keystore.cpp \

       keyhandle.cpp \

       ecdsa_meth.cpp \

       dsa_meth.cpp \

       rsa_meth.cpp

 LOCAL_C_INCLUDES += \

       external/openssl/include \

       external/openssl

endif

LOCAL_MODULE_TAGS := optional

LOCAL_CFLAGS := -fvisibility=hidden -Wall-Werror

LOCAL_SHARED_LIBRARIES += \

       libcrypto \

       liblog \

       libcutils \

       libutils \

       libbinder \

       libkeystore_binder

LOCAL_ADDITIONAL_DEPENDENCIES :=$(LOCAL_PATH)/Android.mk

include$(BUILD_SHARED_LIBRARY)

       找了一下OPENSSL_FLAVOR這個定義,發現在external/boringssl/flavor.mk中定義為BoringSSL了。

external/boringssl/flavor.mk:4:OPENSSL_FLAVOR=BoringSSL

       另外在out目錄下搜尋了一下,發現這個.so檔案已經生成了。那應該把它Link增加此庫就可以了。

       修改external/HOSTAP_REL_0_8_0_126/wpa_supplicant/Android.mk檔案。開啟這檔案一看,發現問題了。此Makefile最高只支援到Android 5.1,Android 6.0.1還沒有在此支援列表中,看來Broadcom 也是夠懶的。那就自己改吧。

       查詢此檔案中所以帶ifneq($(findstring 5.1,$(PLATFORM_VERSION)),)的部分,拷貝一份,把5.1改為6.0,另外,在連結庫的地方增加我們所需要的keystore-engine。改完後如下。

--- a/external/HOSTAP_REL_0_8_0_126/wpa_supplicant/Android.mk

+++b/external/HOSTAP_REL_0_8_0_126/wpa_supplicant/Android.mk

@@ -169,6 +169,10 @@ ifneq ($(findstring5.1,$(PLATFORM_VERSION)),)

 #for lollipop

 L_CFLAGS += -DLP

 endif

+ifneq ($(findstring6.0,$(PLATFORM_VERSION)),)

+# for lollipop

+L_CFLAGS += -DLP

+endif

 INCLUDES = $(LOCAL_PATH)

 INCLUDES += $(LOCAL_PATH)/src

@@ -1775,6 +1779,9 @@LOCAL_SHARED_LIBRARIES += $(LIB_SHARED_EAP_PROXY)

 endif

 ifeq($(CONFIG_TLS), openssl)

 LOCAL_SHARED_LIBRARIES += libcrypto libssl

+ifneq ($(findstring6.0,$(PLATFORM_VERSION)),)

+LOCAL_SHARED_LIBRARIES+= libkeystore_binder libkeystore-engine

+endif

       再編譯,通過了,已經生成了wpa_supplicant、wpa_cli及libwpa_client.so檔案。

拷貝配置檔案

       還需要把新的配置檔案及bin拷貝到系統的指定目錄下,供wpa_supplicant啟動時使用。修改device/fsl/sabresd_6dq/BoardConfig.mk檔案,增加相關檔案拷貝:

--- a/device/fsl/sabresd_6dq/BoardConfig.mk

+++ b/device/fsl/sabresd_6dq/BoardConfig.mk

@@ -47,7 +47,8 @@ PRODUCT_MODEL :=SABRESD-MX6DQ

 TARGET_RELEASETOOLS_EXTENSIONS :=device/fsl/imx6

 #UNITE is a virtual device support both atheros and realtek wifi(ar6103 andrtl8723as)

 BOARD_WLAN_DEVICE            := UNITE

-WPA_SUPPLICANT_VERSION       := VER_0_8_UNITE

+#WPA_SUPPLICANT_VERSION       := VER_0_8_UNITE

+WPA_SUPPLICANT_VERSION       := VER_0_8_X

 BOARD_WPA_SUPPLICANT_DRIVER  := NL80211

 BOARD_HOSTAPD_DRIVER         := NL80211

@@ -137,3 +138,33 @@ BOARD_SEPOLICY_DIRS :=\

 PRODUCT_PROPERTY_OVERRIDES += \

    sys.def_screen_time=-1

+

+#wifi

+PRODUCT_PACKAGES +=\

+       bcm4339_mfg.bin \

+       bcm4339_sta_p2p.bin \

+       bcmdhd_apsta.bin \

+       nvram.txt \

+       bcmdhd.ko \

+       cfg80211.ko \

+       compat.ko \

+       hostapd.conf \

+       p2p_supplicant.conf \

+       wpa_supplicant.conf \

+       hostapd \

+       wpa_supplicant \

+       insmod_ap.sh \

+       insmod_stap2p.sh \

+       bcmdhd.cal \

+       wl

+

+PRODUCT_COPY_FILES+=  \

+      device/fsl/sabresd_6dq/wifi/wpa_supplicant_ap.conf:system/etc/wifi/wpa_supplicant_ap.conf\

+       device/fsl/sabresd_6dq/wifi/wpa_supplicant.conf:system/etc/wifi/wpa_supplicant.conf\

+      device/fsl/sabresd_6dq/wifi/p2p_supplicant.conf:system/etc/wifi/p2p_supplicant.conf\

+      device/fsl/sabresd_6dq/wifi/sta.conf:system/etc/wifi/sta.conf \

+      device/fsl/sabresd_6dq/wifi/fw_bcmdhd_hu.bin:system/etc/wifi/firmware/fw_bcmdhd_hu.bin\

+      device/fsl/sabresd_6dq/wifi/fw_bcmdhd_hu_acs.bin:system/etc/wifi/firmware/fw_bcmdhd_hu_acs.bin\

+      device/fsl/sabresd_6dq/wifi/fw_bcmdhd_mfgtest.bin:system/etc/wifi/firmware/fw_bcmdhd_mfgtest.bin\

+      device/fsl/sabresd_6dq/wifi/fw_bcmdhd_rse.bin:system/etc/wifi/firmware/fw_bcmdhd_rse.bin\

+      #device/fsl/sabresd_6dq/modules/bcmdhd.ko:system/lib/modules/bcmdhd.ko

       把相關檔案conf,bin 拷貝到device/fsl/sabresd_6dq/wifi目錄下。

       編譯好系統,下載到裝置中,Wifi已經可以開啟工作了。但驅動還沒有更新。

更新WiFi Driver

       雖然已經可以用了,但Driver還是老的,最好同步更新一下。

       解開bcmdhd檔案,拷貝到kernel_imx/drivers/net/wireless目錄下同名目錄。

       編譯出錯。__DATE__, __TIME__不認識。開啟bdmdhd/dhd_common.c檔案,註釋掉

const char dhd_version[] = "DongleHost Driver, version " EPI_VERSION_STR;

       //DHD_COMPILED" on " __DATE__ " at " __TIME__;

       編譯通過,下載後發現Wifi不能工作了。看了一下Log,提示找不到platform_data,開啟bcmdhd/dhd_linux_platdev.c檔案。看了一下,需要開啟CONFIG_DTS。

       對比了一下bdmdhd/Makefile檔案,把不同的地方仔細看了一下。又參考了一下Porting Guide,主要有:

CONFIG_DTS: 表明系統是用dts還是老式的platform_data;在示例的dts程式碼中,還有一個GPIO是用於中斷的。由於本系統中沒有此GPIO,所以可以在dts檔案中隨便寫一個不用的GPIO或者在bcmdhd/dhd_linux_platdev.c檔案中wifi_plat_dev_drv_probe()函式中把相關的部分註釋掉:

#if 0

       /* This is to get the irq for the OOB */

       gpio = of_get_gpio(pdev->dev.of_node,0);

       if (gpio < 0) {

              DHD_ERROR(("%s gpioinformation is incorrect\n", __FUNCTION__));

              return -1;

       }

       irq = gpio_to_irq(gpio);

       if (irq < 0) {

              DHD_ERROR(("%s irqinformation is incorrect\n", __FUNCTION__));

              return -1;

       }

       adapter->irq_num = irq;

       /* need to change the flags according toour requirement */

       adapter->intr_flags = IORESOURCE_IRQ |IORESOURCE_IRQ_HIGHLEVEL |

              IORESOURCE_IRQ_SHAREABLE;

#endif

另外由於沒有中斷GPIO,所以在Makefile中把_DOOB_INTR_ONLY及-DHW_OOB去掉,加上-DSDIO_ISR_THREAD。

       由於Kernel版本是v3.14.52,所以需要增加wl_cfgvendor.c檔案到Makefile檔案中。

       以上修改完成,編譯沒有錯誤了,下載到裝置中,沒找到裝置。看來是檢測Wifi裝置的程式碼有問題,檢視bcmdhd/dhd_linux_platdev.c檔案中的wifi_platform_bus_enumerate()這個函式,檢測硬體是在此進行的。看了一下程式碼,還是根據platform_data來進行的,現在DTS方式的話就不行了。

intwifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present)

{

       interr = 0;

       structwifi_platform_data *plat_data;

       if(!adapter || !adapter->wifi_plat_data)

              return-EINVAL;

       plat_data= adapter->wifi_plat_data;

       DHD_ERROR(("%sdevice present %d\n", __FUNCTION__, device_present));

       if(plat_data->set_carddetect) {

              err= plat_data->set_carddetect(device_present);

       }

       returnerr;

}

       參考了一下之前的程式碼,改成如下:

intwifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present)

{

       interr = 0;

       structwifi_platform_data *plat_data;

       if (!adapter) {

              pr_err("!!!!%s: failed!  adapter variable isNULL!!!!!\n", __FUNCTION__);

              return-EINVAL;

       }

       DHD_ERROR(("%sdevice present %d\n", __FUNCTION__, device_present));

       if (!adapter->wifi_plat_data) {

              wifi_card_detect(); /* hook for card_detect */

       }else {

              plat_data= adapter->wifi_plat_data;

              if(plat_data->set_carddetect)

                     err= plat_data->set_carddetect(device_present);

       }

       return0; /* force success status returned */

}

       呼叫wifi_card_detect()函式來檢測硬體,此函式定義在之前寫dts時提到過的drivers/mmc/host/sdhci-esdhc-imx.c檔案中。

       重新編譯下載,再測試,WiFi就一切正常了。WiFi驅動移植算基本完成。

       現在遺留的問題是WAPI驅動沒有整合,因為手上沒有WAPI測試裝置,另外加上WAPI的話,以後每臺還需要付License費用的。所以暫時就不加了。

關於編譯成模組ko的問題

       之前為了方便除錯,想把驅動編譯成ko檔案,但在Kernel配置檔案中把CONFIG_BCMDHD改為m,編譯完成後根本沒有生成ko檔案。一開始以為是有其它依賴關係引起的,但另一個平臺如此修改就能夠正常生成,後來對比了一下,發現kernel/drivers/net/wireless/bcmdhd/Makefile中有一行。

##########################

# driver type

# m: module type driver

# y: built-in type driver

##########################

DRIVER_TYPE ?= y

       需要把它改為

DRIVER_TYPE ?= m

       這也算是一個小插曲吧。

Bluetooth部分原理圖

       接下來要除錯Bluetooth了。Freescale的驅動包裡Bluetooth部分完全是空白。文件也沒有,程式碼也沒有。估計現系統中的程式碼應該是可用的。要不然就麻煩大了。還是先查原理圖。音訊部分暫時先不管,只看通訊部分的。

       Bluetooth部分重要的幾根線是UART、BT_REG_ON、BT_DEV_WAKE、BT_HOST_WAKE,兩根WAKE腳在本系統中沒有控制,直接連到低電平或懸空。

Bluetooth部分DTS及Kernel配置

看來我們需要配置的只有BT_RST PIN及UART,和之前一樣,修改/kernel_imx/arch/arm/boot/imx6dq-sabresd.dtsi檔案。

       BT_REG_ON在此dts檔案中是作為bt_rfkill來配置的,找到相應部分,BT_RST連線到的是D17(NANDF_D3),相對應的GPIO為GPIO2_3。

    bt_rfkill {

                 compatible ="fsl,mxc_bt_rfkill";

-                        bt-power-gpios = <&gpio1 2 0>;

+                        bt-power-gpios =<&gpio2 3 0>;

                                 status="okay";

    };

       找到NAND中的配置,把相應PIN的配置註釋掉。

       再看UART部分,連線到的是系統的UART3,由於Bluetooth要求有流控,所以需要配置CTS/DTS。找到pinctrl_uart3

       TX連線到F22(EIM_D24),RX連線到G22(EIM_D25),CTS連線到J20(EIM_D30),RTS連線到D15(SD3_D15)。原配置中TX/RX配置是正確的,需要更換CTS/RTS的配置。修改為:

               pinctrl_uart3: uart3grp {

                        fsl,pins = <

                               MX6QDL_PAD_EIM_D24__UART3_TX_DATA      0x1b0b1

                               MX6QDL_PAD_EIM_D25__UART3_RX_DATA      0x1b0b1

-                              MX6QDL_PAD_EIM_EB3__UART3_RTS_B 0x1b0b1

-                              MX6QDL_PAD_EIM_D23__UART3_CTS_B 0x1b0b1

+                               MX6QDL_PAD_SD3_RST__UART3_RTS_B 0x1b0b1

+                              MX6QDL_PAD_EIM_D30__UART3_CTS_B 0x1b0b1

                       >;

               };

       再修改uart3配置,增加rtscts部分。

&uart3 {

       pinctrl-names = "default";

      pinctrl-0 = <&pinctrl_uart3>;

+     fsl,uart-has-rtscts;

       status = "okay";

+       /* for DTE mode, add below change */

+       /* fsl,dte-mode; */

+       /* pinctrl-0 =<&pinctrl_uart3dte_1>; */

 };

       Kernel配置檔案部分,開啟kernel_imx/arch/arm/configs/imx_v7_android_defconfig檔案看了一下,Bluetooth相關部分都是開啟的,看來不需要動。

CONFIG_BT=y

CONFIG_BT_RFCOMM=y

CONFIG_BT_RFCOMM_TTY=y

CONFIG_BT_BNEP=y

CONFIG_BT_BNEP_MC_FILTER=y

CONFIG_BT_BNEP_PROTO_FILTER=y

CONFIG_BT_HIDP=y

CONFIG_BT_HCIBTUSB=y

CONFIG_BT_HCIUART=y

CONFIG_BT_HCIUART_H4=y

CONFIG_BT_HCIUART_BCSP=y

CONFIG_BT_HCIUART_ATH3K=y

CONFIG_BT_HCIBCM203X=y

Bluetooth串列埠配置檔案

       編譯沒有出錯,下載開機測試,打不開,看Log,發現以下內容:

01-01 00:37:44.221  1726  1741 I bt_vnd_conf: Attempt to load conf from/etc/bluetooth/bt_vendor.conf

01-01 00:37:44.222  1726 1741 D bt_vendor: op for 0

01-01 00:37:44.225  1726 1741 D bt_vendor: op for 0

01-01 00:37:45.730  1726 1741 D bt_hci  : start_up startingasync portion

01-01 00:37:45.730  1726 1748 I bt_hci  : event_finish_startup

01-01 00:37:45.730  1726 1748 I bt_hci_h4: hal_open

01-01 00:37:45.730  1726 1748 D bt_vendor: op for 3

01-01 00:37:45.730  1726  1748 I bt_userial_vendor: userial vendoropen: opening /dev/ttymxc4

       看到試圖去開啟的是串列埠ttymxc4,這是之前系統的配置,看來不是自動通過DTS檔案來識別的。找到hardware/broadcom/libbt/conf/fsl/sabresd_6dq/bt_vendor.conf檔案。裡面果然有串列埠的配置,修改為:

--- a/hardware/broadcom/libbt/conf/fsl/sabresd_6dq/bt_vendor.conf

+++ b/hardware/broadcom/libbt/conf/fsl/sabresd_6dq/bt_vendor.conf

@@ -1,5 +1,5 @@

 # UART device port whereBluetooth controller is attached

-UartPort = /dev/ttymxc4

+UartPort = /dev/ttymxc2

 # Firmware patch filelocation

 FwPatchFilePath =/etc/firmware/bcm/

       另外發現一個avc許可權錯誤。

type=1400 audit(1466056103.290:5): avc:denied { dac_override } for pid=215 comm="sh" capability=1scontext=u:r:shell:s0 tcontext=u:r:shell:s0 tclass=capability

       也不清楚是否和Bluetooth相關,修改了再說。

--- a/external/sepolicy/app.te

+++ b/external/sepolicy/app.te

@@ -213,7 +213,7 @@selinux_check_context(appdomain)

 #Superuser capabilities.

 #bluetooth requires net_admin and wake_alarm.

-neverallow { appdomain-bluetooth } self:capability *;

+#neverallow {appdomain -bluetooth } self:capability *;

 neverallow { appdomain -bluetooth }self:capability2 *;

--- a/external/sepolicy/shell.te

+++ b/external/sepolicy/shell.te

@@ -84,3 +84,10 @@ allow shellbootchart_data_file:file create_file_perms;

 #bugs, so we want to ensure the shell user never has this

 #capability.

 neverallow shell file_type:file link;

+

+allow shellself:capability { sys_ptrace dac_override };

--- a/external/sepolicy/domain.te

+++ b/external/sepolicy/domain.te

@@ -177,15 +177,15 @@ neverallow { domain-init -recovery } unlabeled:dir_file_class_set create;

 #Limit ability to ptrace or read sensitive /proc/pid files of processes

 #with other UIDs to these whitelisted domains.

-neverallow {

-  domain

-  -debuggold

-  -vold

-  -dumpstate

-  -system_server

-  userdebug_or_eng(`-procrank')

-  userdebug_or_eng(`-perfprofd')

-} self:capability sys_ptrace;

+#neverallow {

+#  domain

+#  -debuggold

+#  -vold

+#  -dumpstate

+#  -system_server

+#  userdebug_or_eng(`-procrank')

+#  userdebug_or_eng(`-perfprofd')

+#} self:capabilitysys_ptrace;

       編譯重新下載後,再看Log,已經變成開啟/dev/ttymcx2了。

01-01 00:37:44.221  1726  1741 I bt_vnd_conf: Attempt to load conf from/etc/bluetooth/bt_vendor.conf

01-01 00:37:44.222  1726 1741 D bt_vendor: op for 0

01-01 00:37:44.225  1726 1741 D bt_vendor: op for 0

01-01 00:37:45.730  1726 1741 D bt_hci  : start_up startingasync portion

01-01 00:37:45.730  1726 1748 I bt_hci  :event_finish_startup

01-01 00:37:45.730  1726 1748 I bt_hci_h4: hal_open

01-01 00:37:45.730  1726 1748 D bt_vendor: op for 3

01-01 00:37:45.730  1726  1748 I bt_userial_vendor: userial vendoropen: opening /dev/ttymxc2

01-01 00:14:21.100  1999 2016 E bt_hci  : startup_timer_expired

01-01 00:14:21.100  1999  2014 E bt_core_module: module_start_up failedto start up "hci_module"

01-01 00:14:21.101  1999 2023 I bt_btu  : btu_task pendingfor preload complete event

01-01 00:14:21.101  1999 2023 I bt_btu_task: Bluetooth chip preload is complete

01-0100:14:21.101  1999  2023 I bt_btu : btu_task received preload complete event             

古怪的CTS/RTS

       串列埠應該是打開了,但從Log上看,傳送訊息後沒有迴應,所以startup超時了,然後啟動流程重新開始,不停的如此迴圈。

       拿示波器測量一下Bluetooth模組這邊的訊號,發現RX端週期性的有訊號,但TX端一直是高電平,沒有任何訊號。又測量了RTS訊號有變化,有時會低,失敗後拉高。從Log上看,失敗後,系統會把BT_REG_EN PIN置低再置高,所以應該是Bluetooth模組復位時把RTS拉高了,初始化完成後再置為低。CTS這個PIN一直是高電平。測量了一下BT_REG_ON這個PIN,和我們想的一增,正常拉高,如果失敗了就會拉低一段時間,應該就是復位。

       從Kernel 的Log上可以看到下面的內容

rfkill: BT RFgoing to : off

rfkill: BT RFgoing to : on

mxc_bt_rfkill_reset

rfkill: BT RFgoing to : off

rfkill: BT RFgoing to : on

mxc_bt_rfkill_reset

       從UART通訊協議來看,CTS為高的話,對方不允許傳送,也就是說SoC不允許Bluetooth這邊傳送資料,所以TX沒有變化。為什麼CTS為一直高,太奇怪了。

檢視Broadcom 的資料手冊,Bluetooth部分的啟動時序如下:

       從上圖看的話,如果CTS一直為高的話,Bluetooth模組應該不會正確初始化的。查Freescale的Datasheet,關於UART口的說明也是一頭霧水。分DTE和DCE兩種模式。

       在這裡,按一般理解SoC應該屬於DTE裝置,之後就凌亂了,開始亂試,亂配,把其它UART配置都關掉,把UART3的CTS/RTS配置反置、把UART設定為dte模式,在Bluetooth的驅動libbt/src/userial_vendor.c中把開啟串列埠時設定為無CTS/RTS,又去找其它系統的uart部分驅動drivers/tty/serial,一通亂合併,總之是試了N種方法,但TX線就是紋絲不動。

       這一下了花了兩天時間,想想軟體沒什麼辦法了,就考慮動硬體,把CTS腳和SoC斷開,直接接地,居然也不行。後來聽到有人說Freescale的串列埠CTS/RTS比較怪,需要CTS接CTS,RTS接RTS,和一般的系統不同。就試著把兩根線互換了一下。果然通過了。

1-01 00:37:44.221  1726  1741 I bt_vnd_conf: Attempt to load conf from/etc/bluetooth/bt_vendor.conf

01-01 00:37:44.222  1726 1741 D bt_vendor: op for 0

01-01 00:37:44.225  1726 1741 D bt_vendor: op for 0

01-01 00:37:45.730  1726 1741 D bt_hci  : start_up startingasync portion

01-01 00:37:45.730  1726 1748 I bt_hci  :event_finish_startup

01-01 00:37:45.730  1726 1748 I bt_hci_h4: hal_open

01-01 00:37:45.730  1726 1748 D bt_vendor: op for 3

01-01 00:37:45.730  1726  1748 I bt_userial_vendor: userial vendoropen: opening /dev/ttymxc2

01-01 00:37:45.735  1726 1748 I bt_userial_vendor: device fd = 53 open

01-01 00:37:45.735  1726 1748 D bt_vendor: op for 1

01-01 00:37:45.760  1726 1748 I bt_hwcfg: bt vendor lib: set UART baud 3000000

01-01 00:37:45.787  1726 1748 D bt_hwcfg: Chipset BCM4335C0

01-01 00:37:45.787  1726 1748 D bt_hwcfg: Target name = [BCM4335C0]

01-01 00:37:45.787  1726 1748 I bt_hwcfg: FW patchfile: /etc/firmware/bcm/Type_ZP.hcd

01-01 00:37:46.537   228  485 W audio_hw_primary: do_out_standby... -1240931008

01-01 00:37:49.145  1726 1748 I bt_hwcfg: bt vendor lib: set UART baud 115200

01-01 00:37:49.145  1726 1748 D bt_hwcfg: Settlement delay -- 100 ms

01-01 00:37:49.145  1726 1748 I bt_hwcfg: Setting fw settlement delay to 100

01-01 00:37:49.260  1726 1748 I bt_hwcfg: bt vendor lib: set UART baud 3000000

01-01 00:37:49.260  1726 1748 I bt_hwcfg: Setting local bd addr to 22:22:FE:19:1B:62

01-01 00:37:49.286  1726 1748 I bt_hwcfg: vendor lib fwcfg completed

01-01 00:37:49.286  1726 1748 I bt_vendor: firmware callback

01-01 00:37:49.286  1726 1748 I bt_hci  :firmware_config_callback

01-01 00:37:49.293  1726 1750 I bt_btu  : btu_task pendingfor preload complete event

       但始終不理解,為什麼會需要這麼接,這種接法即不屬於DCE模式,也不屬於DTE模式,真不明白Freescale把一個簡單的串列埠搞的這麼複雜難懂。

signal11 (SIGSEGV)錯誤

       串列埠通了,在Settings->Bluetooth中試圖找開Bluetooth時,很快就報錯Settings出錯了。看了一下Log。出現在signal 11錯誤。

01-0100:37:50.080  1726  1744 F libc   : Fatal signal 11 (SIGSEGV), code 1, fault addr 0x100486 in tid 1744 (BTService Call)

01-0100:37:50.134  1726  1726 D BluetoothAdapterService:getAdapterService() - [email protected]

01-0100:37:50.137   532   532 D BluetoothA2dp: Proxy object connected

01-0100:37:50.140  1726  1726 D A2dpService: Received start request.Starting profile...

01-0100:37:50.155  1726  1726 I BluetoothAvrcpServiceJni:classInitNative: succeeds

01-0100:37:50.156  1726  1726 I bt_bluedroid: get_profile_interfaceavrcp

01-0100:37:50.189   226   226 I SELinux : SELinux: Loadedfile_contexts contexts from /file_contexts.

01-0100:37:50.192   226   226 F DEBUG  : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***

01-0100:37:50.192   226   226 F DEBUG  : Build fingerprint:'Freescale/sabresd_6dq/sabresd_6dq:6.0.1/1.0.0-ga-rc6/20160331:eng/release-keys'

01-0100:37:50.192   226   226 F DEBUG  : Revision: '0'

01-0100:37:50.193   226   226 F DEBUG  : ABI: 'arm'

01-0100:37:50.193   226   226 F DEBUG  : pid: 1726, tid: 1744, name: BT Service Call  >>> com.android.bluetooth<<<

01-01 00:37:50.193   226  226 F DEBUG   : signal 11(SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x100486

01-0100:37:50.214   226   226 F DEBUG  :     r0 af8518c0  r1 00100486 r2 00000023  r3 00000000

01-0100:37:50.214   226   226 F DEBUG  :     r4 af8518c0  r5 9ae6723c r6 00000000  r7 00000020

01-0100:37:50.215   226   226 F DEBUG  :     r8 00000036  r9 00030367 sl 00000009  fp af85c554

01-0100:37:50.215   226   226 F DEBUG  :     ip 9b3b2e38  sp 9ae67208 lr 9b2e076f  pc b6d573ea  cpsr 20070030

01-01 00:37:50.248   226  226 F DEBUG   :

01-0100:37:50.248   226   226 F DEBUG  : backtrace:

01-0100:37:50.248   226   226 F DEBUG  :     #00 pc 000353ea  /system/lib/libc.so (strncpy+5)

01-0100:37:50.249   226   226 F DEBUG  :     #01 pc 0007976b  /system/lib/hw/bluetooth.default.so(BTA_AgRegister+78)

01-0100:37:50.249   226   226 F DEBUG  :     #02 pc 0004b9d5  /system/lib/hw/bluetooth.default.so(btif_hf_execute_service+60)

01-0100:37:50.249   226   226 F DEBUG  :     #03 pc 0003ebaf  /system/lib/hw/bluetooth.default.so(btif_in_execute_service_request+58)

01-0100:37:50.250   226   226 F DEBUG  :     #04 pc 0003fcbb  /system/lib/hw/bluetooth.default.so(btif_dm_execute_service_request+22)

01-0100:37:50.250   226   226 F DEBUG  :     #05 pc 0003c18d  /system/lib/hw/bluetooth.default.so

01-0100:37:50.250   226   226 F DEBUG  :     #06 pc 000f5639  /system/lib/hw/bluetooth.default.so

01-0100:37:50.250   226   226 F DEBUG  :     #07 pc 000f462b  /system/lib/hw/bluetooth.default.so

01-0100:37:50.250   226  226 F DEBUG   :     #08 pc 000f558b  /system/lib/hw/bluetooth.default.so

01-0100:37:50.251   226   226 F DEBUG  :     #09 pc 0003f8c3  /system/lib/libc.so(__pthread_start(void*)+30)

01-0100:37:50.251   226   226 F DEBUG  :     #10 pc 00019e55  /system/lib/libc.so (__start_thread+6)

SIGSEGV錯誤一般是非法記憶體訪問。看了一下backtrace,找到BTA_AgRegister()函式。在檔案system/bt/bta/ag/bta_ag_api.c檔案中。在呼叫strncpy時出錯。應該就是這一行了。

BCM_STRNCPY_S(p_buf->p_name[i],BTA_SERVICE_NAME_LEN+1, p_service_names[i], BTA_SERVICE_NAME_LEN);

       涉及到兩個指標,不清楚那個出錯了,應該是0x100486這個地址非法,這個地址太小了,應該不是正常的驅動或應用可能申請到的地址,把兩個地址打印出來,發現是p_service_names[i]這個地址。

       雖然不清楚為什麼會傳一個非法值進來,不過可以先簡單的處理一下,正確的值應該在2G以上地址。所以改為:

if ( p_service_names[i] &&(int)p_service_names[i] < 0x40000000 ) { // Address < 2G, illegal

  APPL_TRACE_ERROR ("BTA_AgRegister: service %d, %d, invalid address%x.",BTA_SERVICE_NAME_LEN,i,p_service_names[i]);

  p_buf->p_name[i][0] = 0;

} else if ( p_service_names[i] ) {

  BCM_STRNCPY_S(p_buf->p_name[i], BTA_SERVICE_NAME_LEN+1,p_service_names[i], BTA_SERVICE_NAME_LEN);

  p_buf->p_name[i][BTA_SERVICE_NAME_LEN] = 0;

}

else

{

  p_buf->p_name[i][0] = 0;

}

       重新編譯下載,開啟Bluetooth,不出錯了,搜尋到了其它裝置,連線到其它裝置,傳送一個檔案過來,接收正常。

修改裝置名稱

       在其它裝置檢視裝置時,此裝置名稱為iMX6,簡單,把它改為專案名稱。device/fsl/sabresd_6dq/bluetooth/bdroid_buildcfg.h

---a/device/fsl/sabresd_6dq/bluetooth/bdroid_buildcfg.h

+++b/device/fsl/sabresd_6dq/bluetooth/bdroid_buildcfg.h

@@ -19,7 +19,7 @@

 #ifndef _BDROID_BUILDCFG_H

 #define _BDROID_BUILDCFG_H

-#define BTM_DEF_LOCAL_NAME"iMX6"

+#define BTM_DEF_LOCAL_NAME"Prince"

一些個人體會

       前後花了一個星期,移植了WiFi/BT驅動,之前沒有移植過WiFi/BT驅動,所以遇到了很多問題,不過總體還算順利。

       在Freescale平臺中,WiFi的SDIO口識別是通過dts檔案中增加wifi-host來區分的。

       而Bluetooth的串列埠是通過在bt_vendor.conf檔案中配置的。

       Broadcom的驅動程式碼更新的比較慢,或者說比較脫節,2016年下的最新的驅動,居然預設還沒有支援Android 6.0系統。移植是需要注意檢查Makefile看是否加上對應平臺的編譯開關了。

待解問題

       Freescale平臺的RTS/CTS始終不明白,為什麼需要CTS接CTS,RTS接RTS,和一般的理解不同,不清楚是不是Bluetooth這邊標錯了,因為此係統中只有Bluetooth連線需要CTS/RTS,所以沒法論證,以後有機會一定要確認一下。

       bt_rfkill應該是用於WiFi/BTCOEX的, 目前沒有去確認一起開啟時,會不會有問題,功能工作是否正常。

       WiFiWAPI部分沒有加入,所以不清楚是否可用。以後有需求時還需要移植一下。