Hi,
While working on a chrooted Android (the host distribution being a Debian one) stored in a tmpfs (in RAM), I noticed that, sometimes, enabling WLAN fails (the button goes straight from "On" to "Off"). On the console, the module was loaded ("CW1200 WSM init done"), but logcat showed that wpa_supplicant could not find the interface: E/wpa_supplicant( 8015): Could not read interface wlan0 flags: No such device E/wpa_supplicant( 8015): WEXT: Could not set interface 'wlan0' UP E/wpa_supplicant( 8015): wlan0: Failed to initialize driver interface D/wpa_supplicant( 8015): Failed to add interface wlan0 E/WifiStateMachine( 2292): Failed to start supplicant!
When I put udev (in the host system) in charge of firmware loading, this bug always happens ; when I disable udev and let uevent (in the Android chroot) do the job, it only happens one time out of fifteen I would say.
The problem seems to be that libhardware_legacy does not wait for the interface to be created to state that the driver has been loaded, leading the Wifi state machine in Android to load the supplicant before the interface was created. The patch at the end of this mail (concerning libhardware_legacy) enables libhardware_legacy to wait for the interface to be created in /sys/class/net, thus solving the problem.
However, since this problem only occurs in rare cases when not using Linaro Android as intended (from emmc or sd card), I do not know if this is worth having a look at.
Regards, Yann Benigot
PATCH: diff --git a/wifi/wifi.c b/wifi/wifi.c index 301d91b..c2661f2 100644 --- a/wifi/wifi.c +++ b/wifi/wifi.c @@ -200,6 +200,8 @@ int wifi_load_driver() #ifdef WIFI_DRIVER_MODULE_PATH char driver_status[PROPERTY_VALUE_MAX]; int count = 100; /* wait at most 20 seconds for completion */ + DIR *ifaceDir; + char ifaceDirPath[16+PROPERTY_VALUE_MAX];
if (is_wifi_driver_loaded()) { return 0; @@ -218,10 +220,21 @@ int wifi_load_driver() property_set("ctl.start", FIRMWARE_LOADER); } sched_yield(); + property_get("wifi.interface", iface, WIFI_TEST_INTERFACE); + sprintf(ifaceDirPath, "/sys/class/net/%s", iface); while (count-- > 0) { if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) { if (strcmp(driver_status, "ok") == 0) - return 0; + { + ifaceDir = opendir(ifaceDirPath); + if(ifaceDir != NULL) { + closedir(ifaceDir); + return 0; + } + else { + LOGI("%s not found, waiting for wifi driver to complete initialization. Will try again %d times.", ifaceDirPath, count-1); + } + } else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) { wifi_unload_driver(); return -1;