How to Support New WiFi Card in Android

Document created by waterzhou Employee on Oct 10, 2012Last modified by Jodi Paul on May 9, 2013
Version 10Show Document
  • View in full screen mode



This guide provides a step by step explanation of what is involved in adding a new WiFi driver and making a new WiFi card work well in a custom Android build. (This guide was written for Android 4.1 but should be applicable to previous Android releases and hopefully future releases.)



    1. Understand how Android WiFi works
    2. Port WiFi driver.
    3. Compile a proper wpa_supplicant in your
    4. Modify your wifi.c in HAL.
    5. Launch wpa_supplicant and dhcpcd services in init.rc.
    6. Several debug tips.


Understand How Android WiFi Works


As the following figure, Android wireless architecture can be divided into three parts:

Java Framework(WifiManager, WifiMonitor etc..),


kernel space modules(wireless stack, wifi drivers)

Java Framework communicate with wpa_supplicant using native interface (wifi.c). Wpa_supplicant and netd uses wireless extension or nl80211 to control WiFi drivers.




Port WiFi driver


Usually WiFi driver is provided as a kernel module. There are mainly two types of Android WiFi architecture:nl80211 and wext. With the implementation of nl80211/cfg80211 many wireless drivers in main line kernel  support nl80211 interface instead of wireless extension.


For different vendors’ WiFi drivers, writing one to add its compile into Android is what you should do. Here take atheros’s AR6kl as an example:

ath6kl_module_file :=drivers/net/wireless/ath/ath6kl/ath6kl_sdio.ko

$(ATH_ANDROID_SRC_BASE)/$(ath6kl_module_file):$(mod_cleanup) $(TARGET_PREBUILT_KERNEL) $(ACP)



        $(ACP) -fpt $(ATH_ANDROID_SRC_BASE)/compat/compat.ko $(TARGET_OUT)/lib/modules/

        $(ACP) -fpt $(ATH_ANDROID_SRC_BASE)/net/wireless/cfg80211.ko $(TARGET_OUT)/lib/modules/


include $(CLEAR_VARS)

LOCAL_MODULE := ath6kl_sdio.ko




LOCAL_SRC_FILES := $(ath6kl_module_file)


Compile a proper wpa_supplicant in your


In Android’s external directory, there are two wpa_supplicant_* projects. For wext-based wifi driver, wpa_supplicant_6 can be used. For nl80211-based WiFi driver, wpa_supplicnat_8 can only be used. But if WiFi vendors supply their own customized wpa_supplicant, it will be much easier to debug the communication between wpa_supplicant and WiFi drivers. No matter which supplicant  you choose, just control their compile in your


Take atheros’s ath6kl as an example:



BOARD_WLAN_DEVICE                        := ar6003

BOARD_HAS_ATH_WLAN                      := true


WIFI_DRIVER_MODULE_PATH                  := "/system/lib/modules/ath6kl_sdio.ko"

WIFI_DRIVER_MODULE_NAME                  := "ath6kl_sdio"

WIFI_DRIVER_MODULE_ARG                  := "suspend_mode=3 wow_mode=2 ar6k_clock=26000000 ath6kl_p2p=1"

WIFI_DRIVER_P2P_MODULE_ARG              := "suspend_mode=3 wow_mode=2 ar6k_clock=26000000 ath6kl_p2p=1 debug_mask=0x2413"

WIFI_SDIO_IF_DRIVER_MODULE_PATH          := "/system/lib/modules/cfg80211.ko"

WIFI_SDIO_IF_DRIVER_MODULE_NAME          := "cfg80211"


WIFI_COMPAT_MODULE_PATH                  := "/system/lib/modules/compat.ko"

WIFI_COMPAT_MODULE_NAME                  := "compat"

WIFI_COMPAT_MODULE_ARG                  := ""



then you need to provide a proper wpa_supplicant.conf  for your device. wpa_supplicant.conf  is very important because the control socket for android is specified in this file(ctrl_interface=). This file should be copied to /system/etc/wifi.
Minimum required config options in wpa_supplicant.conf :

There are two different ways in which wpa_supplicant can be configured, one is to use a "private" socket in android namespace, created by socket_local_client_connect() function in wpa_ctrl.c and another is by using a standard UNIX socket.


Android private socket




- Unix standard socket


ctrl_interface=DIR=/data/system/wpa_supplicant GROUP=wifi


Modify your wifi.c in HAL


Here what you should do is modifying some codes like wifi_load_driver and wifi_unload_driver.

For Broadcom or CSR’s wifi driver, you can directly use the original wifi.c. But for atheros’s ath6kl driver, there are total three  .ko modules to install. So some micro variables and codes need to be changed to adapt it.


Launch wpa_supplicant and dhcpcd services in init.rc


If you have configured to use android private socket, you should do like this:


service wpa_supplicant /system/bin/wpa_supplicant -Dwext -iwlan0 -c / data/misc/wifi /wpa_supplicant.conf
socket wpa_wlan0 dgram 660 wifi wifi

or if you have configured to use unix standard socket, you should do like this:

service wpa_supplicant /system/bin/wpa_supplicant -Dwext -iwlan0  -c/data/misc/wifi/wpa_supplicant.conf

If WiFi driver is not “wext” but “nl80211”, you should change it to –Dnl80211.


For dhcpcd, you should lunch it like the following:


service dhcpcd_wlan0 /system/bin/dhcpcd -ABKL

    class late_start



The parameters “-ABKL” can largely enhance wifi connection speed.  About what “ABKL” stand for, you can refer to dhcpcd’s GNU manual.


Several debug tips


    1. Incorrect permissions will result in wpa_supplicant not being able to create/open the control socket andlibhardware_legacy/wifi/wifi.c won't connect.
      Since Google modified wpa_supplicant to run as wifi user/group the directory structure and file ownership should belong to wifi user/group (see os_program_init() function in wpa_supplicant/os_unix.c ).

      Otherwise errors like:
      E/WifiHW  (  ): Unable to open connection to supplicant on "/data/system/wpa_supplicant/wlan0": No such file or directory will appear.

      Also wpa_supplicant.conf should belong to wifi user/group because wpa_supplicant will want to modify this file.
    2. How to Enable debug for wpa_supplicant.

              By default wpa_supplicant is set to MSG_INFO that doesn't tell much.     
              To enable more messages:
                modify common.c and set wpa_debug_level = MSG_DEBUG

                modify common.h and change #define wpa_printf from if ((level) >= MSG_INFO) to if ((level) >= MSG_DEBUG)


        3. WiFi driver’s softmac.

              For most vendors’ WiFi driver, the mac address is fixed. We should add one softmac rule to let WiFi driver’s mac is unique for each board.

3 people found this helpful