最近公司使用imx6q开发新产品,我们没有经验,选了最新的android 6.0平台来做开发。而硬件给我们提供的wifi模块竟然是使用USB外接的wifi模块,没错,就是淘宝上买的那种小型无线网卡,不是嵌入式wifi模块(不想说硬件兄弟坑我们了,没办法,小公司就是这样),当然附带的光盘里面的驱动是windows驱动,不过挺良心的还有linux驱动代码,这多少让我感到有些安慰,以为有驱动应该好办。不说其他的,进入正题。
【调试驱动】
光盘附带的linux驱动代码,确实是ralink的原厂驱动,网上一搜mt7601U驱动,找了很多,确实跟光盘附带的一样,不外乎以下两个:
MT7601U_LinuxAP_3.0.0.1_20130802.tar.bz2
DPA_MT7601U_LinuxSTA_3.0.0.4_20130916.tar.bz2
所以,暂时相信它是可用的,拷贝出来放到unbuntu 14.04系统上编译(因为我们没有android开发经验,选了android 6.0.1版本,linux内核是3.14,而安装的ubuntu编译环境内核是3.13版本的,比较相近),首先试试驱动在PC机上能不能用,结果悲剧了,驱动代码编不过。本来想尝试修改下编不过的驱动代码,不过改了一个,又出现更多错误,想想还是放弃了,因为驱动代码毕竟不了解,即使最后编过了,也可能不能用。
好在天无绝人之路,把目光转向依赖开源驱动。感谢github上的大神terence-deng和SunlionLM,最后下载了他们的驱动代码(下载地址:https://github.com/terence-deng/mt7601u 和 https://github.com/2421/mt7601u_driver_linux),终于在我的平台上验证能够编译通过。
虽然折腾了点,但是这说明了前期的技术预研很有必要,技术预研要做到什么程度也需要考虑。我们没有预研,没有考虑软硬件版本兼容,乱选android版本和wifi硬件外设,导致走了弯路。
最终驱动代码需要交叉编译,才能在imx6q平台使用,因此需要修改Makefile。修改如下:
1、Makefile修改:
默认平台是PC,定义一个我自己的平台
PLATFORM = IMX6DQ
然后添加交叉编译链
ifeq ($(PLATFORM),IMX6DQ)
LINUX_SRC = /home/1-trunk/kernel_imx
CROSS_COMPILE= /home/1-trunk/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-
ARCH = arm
export ARCH
endif
2、os/linux/config.mk修改:
添加下列选项
ifeq ($(PLATFORM),IMX6DQ)
EXTRA_CFLAGS := $(WFLAGS) -D__KERNEL__ -DMODULE -fno-pic -Wno-error=date-time
endif
因为我是在android平台使用,所以也添加了以下选项
HAS_WPA_SUPPLICANT=y
HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y
#Support for android
HAS_ANDROID_SUPPORT=y
这样修改完成以后,就可以编译出mt7601Usta.ko。(terence-deng大神的代码编译出来是三个ko:mtutil7601Usta.ko、mt7601Usta.ko、mtnet7601Usta.ko,因为我用不上,所以最后采用了SunlionLM大神的代码)。
【驱动加载】
为了验证驱动是可用的,我首先使用iwpriv来测试是否可以连上AP。android上并没有wireless_tools,所以要先去下载一下wireless_tools.29,然后添加Android.mk(可以参考http://blog.csdn.net/armeasy/article/details/6566462),
修改\1-trunk\build\target\product\base.mk,在PRODUCT_PACKAGES后面添加
iwpriv \
iwconfig \
iwlist
这样,就把wireless_tools编译到目标文件中了。
先手动加载驱动
insmod /system/lib/modules/mt7601Usta.ko
然后
ifconfig wlan0 up
iwpriv wlan0 set Channel=auto
iwpriv wlan0 set AutoReconnect=1
iwpriv wlan0 set AuthMode=OPEN
iwpriv wlan0 set EncrypType=NONE
iwpriv wlan0 set SSID=ssid-xxx
连无密码的AP可以连上,但是奇怪的是我连有密码的AP却死活连不上(参数反复确认是正确的),命令如下:
iwpriv wlan0 set Channel=auto
iwpriv wlan0 set AutoReconnect=1
iwpriv wlan0 set AuthMode=WPA2PSK
iwpriv wlan0 set EncrypType=AES
iwpriv wlan0 set SSID="TP-LINK_9792"
iwpriv wlan0 set WPAPSK="1234567890"
iwpriv wlan0 set SSID="TP-LINK_9792"
但是连不上,不知道什么原因,不知道是不是驱动的问题。后面为了赶进度就没有研究为什么连不上有密码AP了,接着调试android使用wpa_supplicant_8启动wifi。
【android wpa_supplicant_8调试】
android源码里面默认支持的设备是broadcom的,因此要修改支持的设备
1、\1-trunk\device\fsl\sabresd_6dq\BoardConfig.mk 修改
BOARD_WLAN_DEVICE := UNITE
改为:
BOARD_WLAN_DEVICE := MediaTek
WPA_SUPPLICANT_VERSION := VER_0_8_UNITE
改为:
WPA_SUPPLICANT_VERSION := VER_0_8_X
并添加
BOARD_WLAN_VENDOR := MediaTek
2、1-trunk\device\fsl\imx6\sabresd_6dq.mk 修改
PRODUCT_COPY_FILES后面添加
kernel_imx/drivers/net/wireless/mt7601u-master-terence-deng/src/os/linux/mt7601Usta.ko:system/lib/modules/mt7601Usta.ko \
kernel_imx/drivers/net/wireless/mt7601u-master-terence-deng/etc/Wireless/RT2870AP/RT2870STA.dat:system/etc/Wireless/RT2870STA/RT2870STA.dat
insmod mt7601Usta.ko出现内存分配错误,要在uboot启动参数cmdline后面加上coherent_pool=2M
RT2870STA.dat这个文件一定要拷贝到板子上,否则,执行ifconfig会出现Operation not permitted 错误
3、创建目录1-trunk\hardware\mediatek\wlan\wpa_supplicant_8_lib,并在该目录下添加driver_cmd_nl80211.c和driver_cmd_wext.c
这两个源文件我是从1-trunk\hardware\realtek\wlan\wpa_supplicant_8_lib直接拷贝过来使用的,因为我买的模块是成品,卖家根本没有提供。幸运的是,直接拷贝的这两个文件是能用的。然后修改下Android.mk,把这两个文件编入lib_driver_cmd_MediaTek.so
LOCAL_MODULE := lib_driver_cmd_MediaTek
4、1-trunk\frameworks\opt\net\wifi\service\Android.mk 修改
ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
LIB_WIFI_HAL := libwifi-hal-bcm
else ifeq ($(BOARD_WLAN_DEVICE), qcwcn)
LIB_WIFI_HAL := libwifi-hal-qcom
else ifeq ($(BOARD_WLAN_DEVICE), mrvl)
# this is commented because none of the nexus devices
# that sport Marvell's wifi have support for HAL
# LIB_WIFI_HAL := libwifi-hal-mrvl
else ifeq ($(BOARD_WLAN_DEVICE), MediaTek)
# support MTK WIFI HAL
LIB_WIFI_HAL := libwifi-hal-mt66xx
endif
改为:
ifeq ($(BOARD_WLAN_DEVICE), bcmdhd)
LIB_WIFI_HAL := libwifi-hal-bcm
else ifeq ($(BOARD_WLAN_DEVICE), qcwcn)
LIB_WIFI_HAL := libwifi-hal-qcom
else ifeq ($(BOARD_WLAN_DEVICE), mrvl)
# this is commented because none of the nexus devices
# that sport Marvell's wifi have support for HAL
# LIB_WIFI_HAL := libwifi-hal-mrvl
else ifeq ($(BOARD_WLAN_DEVICE), MediaTek)
# support MTK WIFI HAL
LIB_WIFI_HAL := libwifi-hal
endif
freescale给的源码里面居然有MediaTek分支,可能是freescale调试过mediatek的芯片,但是同样的,卖家没有给我libwifi-hal-mt66xx库,所以hal库只好改成默认的。好像也没有什么影响。
5、1-trunk\hardware\libhardware_legacy\wifi\Android.mk中添加
else ifeq ($(BOARD_WLAN_VENDOR), MediaTek)
LOCAL_SRC_FILES += wifi/wifi_mediatek.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../external/wpa_supplicant_8/src/common
然后将wifi_mediatek.c 拷贝到目录(1-trunk\hardware\libhardware_legacy\wifi)底下,这个是编译到libhardware_legacy.so库,最终在wifi-service中提供JNI调用,供android层调用。这里面实现的接口主要是:
wifi_load_driver (加载驱动)
wifi_unload_driver (卸载驱动)
wifi_start_supplicant (启动wpa_supplicant服务)
wifi_stop_supplicant (关闭wpa_supplicant服务)
......
参照一下原有的wifi.c文件,改成mt7601u可用的就行了,并命名为wifi_mediatek.c
6、启动脚本修改
1-trunk\device\fsl\sabresd_6dq\init.rc 修改
service wpa_supplicant /system/bin/wpa_supplicant \
-iwlan0 -Dwext -c/system/etc/wifi/wpa_supplicant.conf \
-I/system/etc/wifi/wpa_supplicant_overlay.conf
因为现在多数wifi支持的是nl80211 driver,但是github上大神提供的驱动并不支持这个,因此上wpa_supplicant官网上看了,后来改成wext driver方式试试,发现的确是可以使用。
1-trunk\system\core\rootdir\init.rc 修改
添加以下语句
# Prepare for wifi
chmod 777 /data/misc/keystore
mkdir /data/misc/dhcp 0770 dhcp dhcp
chown dhcp dhcp /data/misc/dhcp
mkdir /system/etc/wifi 0777 wifi wifi
chmod 777 /system/etc/wifi
chmod 777 /system/etc/wifi/wpa_supplicant.conf
chown wifi wifi /system/etc/wifi/wpa_supplicant.conf
mkdir /data/misc/wifi 0777 wifi wifi
mkdir /data/misc/wifi/sockets 0770 wifi wifi
chmod 777 /data/misc/wifi
chmod 777 /data/misc/wifi/wpa_supplicant.conf
chmod 777 /data/misc/wifi/p2p_supplicant.conf
chown wifi wifi /data/misc/wifi
chown wifi wifi /data/misc/wifi/wpa_supplicant.conf
否则android启动wpa_supplicant服务时会有权限问题,导致服务起不来
这一切都修改好以后,直接编译固件,下载到板子上,在设置--wifi选项中直接点开toggle,就可以看到模块搜索到附近的AP,选一个可用的连上OK。
参考资料:
http://blog.csdn.net/armeasy/article/details/6566462