For mini-box.com picoPC we want to support several USB and miniPCIWiFi dongles, this guide provides a step by step explanation ofwhat's involved in adding a new wifi driver and making wifi work ina custom Android build
Contents
0. Understand how Android WiFi works.
1. Enable building of wpa_supplicant in your BoardConfig.mk
2. (Optional) Enable debug for wpa_supplicant.
3. Provide a proper wpa_supplicant.conf for your device
4. Have the correct paths and permissions created frominit.rc
5. Make sure your wpa_supplicant and dhcpcd (optional) are startingfrom init.rc
6. Provide your driver either as a module or built in kernel andproper kernel support for it and modify Android source codeaccordingly.
7. Provide a firmware if your module needs it.
8. Make your driver work with Android custom wpa_supplicantcommands and SIOCSIWPRIV ioctl
Now onto details.
0. Understand how Android WiFi works.
Android uses a modified wpa_supplicant (external/wpa_supplicant)daemon for wifi support which is controlled through a socket byhardware/libhardware_legacy/wifi/wifi.c that gets controlled fromAndroid UI through android.net.wifi package fromframeworks/base/wifi/java/android/net/wifi/ and it's correspondingjni implementation inframeworks/base/core/jni/android_net_wifi_Wifi.cpp. Higher levelnetwork management is done inframeworks/base/core/java/android/net
1. Enable building of wpa_supplicant in your BoardConfig.mk
This is by simply adding: BOARD_WPA_SUPPLICANT_DRIVER := WEXT
to your BoardConfig.mk. This will set
external/wpa_supplicant/Android.mk enabling building ofdriver_wext.c
If you have a custom wpa_supplicant driver (like madwifi) you canset in BOARD_WPA_SUPPLICANT_DRIVER := MADWIFI.
2. (Optional) Enable debug for wpa_supplicant.
By default wpa_supplicant is set to MSG_INFO that doesn't tellmuch. To enable more messages:
3. Provide a proper wpa_supplicant.conf for your device
Providing a wpa_supplicant.conf it's important because the controlsocket for android is specified in this file (ctrl_interface= ).This file should be copied by your AndroidBoard.mk to$(TARGET_OUT_ETC)/wifi (basically/system/etc/wifi/wpa_supplicant.conf).
This location should be double checked on init.rc for servicewpa_supplicant as the wpa_supplicant config file.
Minimum required config options in wpa_supplicant.conf :
ctrl_interface=DIR=/data/system/wpa_supplicant GROUP=wifi
update_config=1
Depending on your driver you might also want to add:
ap_scan=1
If you have AP association problems with should change to ap_scan=0to let the driver do the association instead ofwpa_supplicant.
If you want to let wpa_supplicant connect to non-WPA or openwireless networks (by default it skips these kind) add:
network={
key_mgmt=NONE
}
4. Have the correct permissions and paths created frominit.rc
Incorrect permisions will result in wpa_supplicant not being ableto create/open the control socket andlibhardware_legacy/wifi/wifi.c won't connect.
Since Google modified wpa_supplicant to run as wifi user/group thedirectory structure and file ownership should belong to wifiuser/group (see os_program_init() function inwpa_supplicant/os_unix.c).
Otherwise errors like:
E/WifiHW
Also wpa_supplicant.conf should belong to user/group wifi becausewpa_supplicant will want to modify this file. If your system has/system as read-only use a location like/data/misc/wifi/wpa_supplicant.conf and modify wpa_supplicantservice in init.rc with new location.
Make sure the paths are correctly created in init.rc:
mkdir /system/etc/wifi 0770 wifi wifi
chmod 0770 /system/etc/wifi
chmod 0660 /system/etc/wifi/wpa_supplicant.conf
chown wifi wifi /system/etc/wifi/wpa_supplicant.conf
# wpa_supplicant socket
mkdir /data/system/wpa_supplicant 0771 wifi wifi
chmod 0771 /data/system/wpa_supplicant
#wpa_supplicant control socket for android wifi.c
mkdir /data/misc/wifi 0770 wifi wifi
mkdir /data/misc/wifi/sockets 0770 wifi wifi
chmod 0770 /data/misc/wifi
chmod 0660 /data/misc/wifi/wpa_supplicant.conf
5. Make sure your wpa_supplicant and dhcpcd are starting frominit.rc
For wpa_supplicant the init.rc startup like should be:
service wpa_supplicant /system/bin/wpa_supplicant -dd -Dwext-iwlan0 -c /system/etc/wifi/wpa_supplicant.conf
group system wifi inet
disabled
oneshot
If your wifi driver creates a wifi interface with other name thenwlan0 you will have to modify the above line accordingly.
You also should have dhcpcd starting from init.rc
service dhcpcd /system/bin/dhcpcd wlan0
group system dhcp
disabled
oneshot
6. Provide your driver either as a module or built in kernel andproper kernel support for it.
- As built in kernel:
setprop wifi.interface "wlan0"
setprop wlan.driver.status "ok"
setprop init.svc.wpa_supplicant "running"
If your driver needs a firmware you will have to copy this firmwarefile to /etc/firmware on your android build. Android doesn't use astandard hotplug binary (although there is an implementationavailable on android-x86 system/code/toolbox/hotplug.c) instead theinit process takes care of firmware events and loads the firmwarefile from /etc/firmware (see: system/core/init/devices.chandle_firmware_event() function).
Firmware file name is defined by the driver and might also containa folder like: RTL8192SU/rtl8192sfw.bin, entire file path should beavailable in /etc/firmware.
8. Make your driver work with Android custom wpa_supplicantcommands and SIOCSIWPRIV ioctl.
The errors from not having this ioctl implemented will looklike:
E/wpa_supplicant(
E/wpa_supplicant(
D/wpa_supplicant(
E/wpa_supplicant(
I/wpa_supplicant(
After 4, WEXT_NUMBER_SEQUENTIAL_ERRORS errors android will abortusing the device.
To quickly test your wifi from interface you can disable errorchecking in external/wpa_supplicant/driver_wext.c by simply makingret = 0; in wpa_driver_priv_driver_cmd() function after the ioctlcall. This will make all access points in android UI appear withoutsignal or MAC address.
To proper implement the ioctl you will need to modify your kerneldriver to reply to SIOCSIWPRIV ioctl with RSSI (signal strength)and MACADDR commands being the most important.
A better way is to add a custom driver_xxx.c to googleexternal/wpa_supplicant/ implementing wpa_driver_priv_driver_cmd()function that will take care of RSSI and MACADDR
Below is a link to a patch for wpa_supplicant that I did formini-box.com picoPC Android build. It creates a new driver awextwhich "emulates" android driver commands using wireless extensionsioctls.
How to use the new driver:
1. In your BoardConfig.mk define: BOARD_WPA_SUPPLICANT_DRIVER :=AWEXT
2. Change init.rc wpa_supplicant service command line by replacind-Dwext with -Dawext
Patch download:
【接下篇】