此项目之前移植到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:fixedregulator@100 {
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() - returningcom.android.bluetooth.btservice.AdapterService@620e2af
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部分没有加入,所以不清楚是否可用。以后有需求时还需要移植一下。