1. 程式人生 > >USB wifi模組mt7601U移植至imx 6q android 6.0平臺

USB wifi模組mt7601U移植至imx 6q android 6.0平臺

        最近公司使用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和,最後下載了他們的驅動程式碼(下載地址: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,因為我用不上,所以最後採用了大神的程式碼)。

【驅動載入】

        為了驗證驅動是可用的,我首先使用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