Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright 2008, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdlib.h>
     18 #include <fcntl.h>
     19 #include <errno.h>
     20 #include <string.h>
     21 #include <dirent.h>
     22 #include <sys/socket.h>
     23 #include <unistd.h>
     24 #include <poll.h>
     25 
     26 #include "hardware_legacy/wifi.h"
     27 #ifdef LIBWPA_CLIENT_EXISTS
     28 #include "libwpa_client/wpa_ctrl.h"
     29 #endif
     30 
     31 #define LOG_TAG "WifiHW"
     32 #include "cutils/log.h"
     33 #include "cutils/memory.h"
     34 #include "cutils/misc.h"
     35 #include "cutils/properties.h"
     36 #include "private/android_filesystem_config.h"
     37 #ifdef HAVE_LIBC_SYSTEM_PROPERTIES
     38 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
     39 #include <sys/_system_properties.h>
     40 #endif
     41 
     42 extern int do_dhcp();
     43 extern int ifc_init();
     44 extern void ifc_close();
     45 extern char *dhcp_lasterror();
     46 extern void get_dhcp_info();
     47 extern int init_module(void *, unsigned long, const char *);
     48 extern int delete_module(const char *, unsigned int);
     49 void wifi_close_sockets();
     50 
     51 #ifndef LIBWPA_CLIENT_EXISTS
     52 #define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
     53 struct wpa_ctrl {};
     54 void wpa_ctrl_cleanup(void) {}
     55 struct wpa_ctrl *wpa_ctrl_open(const char *ctrl_path) { return NULL; }
     56 void wpa_ctrl_close(struct wpa_ctrl *ctrl) {}
     57 int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
     58 	char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len))
     59 	{ return 0; }
     60 int wpa_ctrl_attach(struct wpa_ctrl *ctrl) { return 0; }
     61 int wpa_ctrl_detach(struct wpa_ctrl *ctrl) { return 0; }
     62 int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
     63 	{ return 0; }
     64 int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { return 0; }
     65 #endif
     66 
     67 static struct wpa_ctrl *ctrl_conn;
     68 static struct wpa_ctrl *monitor_conn;
     69 
     70 /* socket pair used to exit from a blocking read */
     71 static int exit_sockets[2];
     72 
     73 static char primary_iface[PROPERTY_VALUE_MAX];
     74 // TODO: use new ANDROID_SOCKET mechanism, once support for multiple
     75 // sockets is in
     76 
     77 #ifndef WIFI_DRIVER_MODULE_ARG
     78 #define WIFI_DRIVER_MODULE_ARG          ""
     79 #endif
     80 #ifndef WIFI_FIRMWARE_LOADER
     81 #define WIFI_FIRMWARE_LOADER		""
     82 #endif
     83 #define WIFI_TEST_INTERFACE		"sta"
     84 
     85 #ifndef WIFI_DRIVER_FW_PATH_STA
     86 #define WIFI_DRIVER_FW_PATH_STA		NULL
     87 #endif
     88 #ifndef WIFI_DRIVER_FW_PATH_AP
     89 #define WIFI_DRIVER_FW_PATH_AP		NULL
     90 #endif
     91 #ifndef WIFI_DRIVER_FW_PATH_P2P
     92 #define WIFI_DRIVER_FW_PATH_P2P		NULL
     93 #endif
     94 
     95 #ifndef WIFI_DRIVER_FW_PATH_PARAM
     96 #define WIFI_DRIVER_FW_PATH_PARAM	"/sys/module/wlan/parameters/fwpath"
     97 #endif
     98 
     99 #define WIFI_DRIVER_LOADER_DELAY	1000000
    100 
    101 static const char IFACE_DIR[]           = "/data/system/wpa_supplicant";
    102 #ifdef WIFI_DRIVER_MODULE_PATH
    103 static const char DRIVER_MODULE_NAME[]  = WIFI_DRIVER_MODULE_NAME;
    104 static const char DRIVER_MODULE_TAG[]   = WIFI_DRIVER_MODULE_NAME " ";
    105 static const char DRIVER_MODULE_PATH[]  = WIFI_DRIVER_MODULE_PATH;
    106 static const char DRIVER_MODULE_ARG[]   = WIFI_DRIVER_MODULE_ARG;
    107 #endif
    108 static const char FIRMWARE_LOADER[]     = WIFI_FIRMWARE_LOADER;
    109 static const char DRIVER_PROP_NAME[]    = "wlan.driver.status";
    110 static const char SUPPLICANT_NAME[]     = "wpa_supplicant";
    111 static const char SUPP_PROP_NAME[]      = "init.svc.wpa_supplicant";
    112 static const char P2P_SUPPLICANT_NAME[] = "p2p_supplicant";
    113 static const char P2P_PROP_NAME[]       = "init.svc.p2p_supplicant";
    114 static const char SUPP_CONFIG_TEMPLATE[]= "/system/etc/wifi/wpa_supplicant.conf";
    115 static const char SUPP_CONFIG_FILE[]    = "/data/misc/wifi/wpa_supplicant.conf";
    116 static const char P2P_CONFIG_FILE[]     = "/data/misc/wifi/p2p_supplicant.conf";
    117 static const char CONTROL_IFACE_PATH[]  = "/data/misc/wifi/sockets";
    118 static const char MODULE_FILE[]         = "/proc/modules";
    119 
    120 static const char IFNAME[]              = "IFNAME=";
    121 #define IFNAMELEN			(sizeof(IFNAME) - 1)
    122 static const char WPA_EVENT_IGNORE[]    = "CTRL-EVENT-IGNORE ";
    123 
    124 static const char SUPP_ENTROPY_FILE[]   = WIFI_ENTROPY_FILE;
    125 static unsigned char dummy_key[21] = { 0x02, 0x11, 0xbe, 0x33, 0x43, 0x35,
    126                                        0x68, 0x47, 0x84, 0x99, 0xa9, 0x2b,
    127                                        0x1c, 0xd3, 0xee, 0xff, 0xf1, 0xe2,
    128                                        0xf3, 0xf4, 0xf5 };
    129 
    130 /* Is either SUPPLICANT_NAME or P2P_SUPPLICANT_NAME */
    131 static char supplicant_name[PROPERTY_VALUE_MAX];
    132 /* Is either SUPP_PROP_NAME or P2P_PROP_NAME */
    133 static char supplicant_prop_name[PROPERTY_KEY_MAX];
    134 
    135 static int insmod(const char *filename, const char *args)
    136 {
    137     void *module;
    138     unsigned int size;
    139     int ret;
    140 
    141     module = load_file(filename, &size);
    142     if (!module)
    143         return -1;
    144 
    145     ret = init_module(module, size, args);
    146 
    147     free(module);
    148 
    149     return ret;
    150 }
    151 
    152 static int rmmod(const char *modname)
    153 {
    154     int ret = -1;
    155     int maxtry = 10;
    156 
    157     while (maxtry-- > 0) {
    158         ret = delete_module(modname, O_NONBLOCK | O_EXCL);
    159         if (ret < 0 && errno == EAGAIN)
    160             usleep(500000);
    161         else
    162             break;
    163     }
    164 
    165     if (ret != 0)
    166         ALOGD("Unable to unload driver module \"%s\": %s\n",
    167              modname, strerror(errno));
    168     return ret;
    169 }
    170 
    171 int do_dhcp_request(int *ipaddr, int *gateway, int *mask,
    172                     int *dns1, int *dns2, int *server, int *lease) {
    173     /* For test driver, always report success */
    174     if (strcmp(primary_iface, WIFI_TEST_INTERFACE) == 0)
    175         return 0;
    176 
    177     if (ifc_init() < 0)
    178         return -1;
    179 
    180     if (do_dhcp(primary_iface) < 0) {
    181         ifc_close();
    182         return -1;
    183     }
    184     ifc_close();
    185     get_dhcp_info(ipaddr, gateway, mask, dns1, dns2, server, lease);
    186     return 0;
    187 }
    188 
    189 const char *get_dhcp_error_string() {
    190     return dhcp_lasterror();
    191 }
    192 
    193 int is_wifi_driver_loaded() {
    194     char driver_status[PROPERTY_VALUE_MAX];
    195 #ifdef WIFI_DRIVER_MODULE_PATH
    196     FILE *proc;
    197     char line[sizeof(DRIVER_MODULE_TAG)+10];
    198 #endif
    199 
    200     if (!property_get(DRIVER_PROP_NAME, driver_status, NULL)
    201             || strcmp(driver_status, "ok") != 0) {
    202         return 0;  /* driver not loaded */
    203     }
    204 #ifdef WIFI_DRIVER_MODULE_PATH
    205     /*
    206      * If the property says the driver is loaded, check to
    207      * make sure that the property setting isn't just left
    208      * over from a previous manual shutdown or a runtime
    209      * crash.
    210      */
    211     if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
    212         ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno));
    213         property_set(DRIVER_PROP_NAME, "unloaded");
    214         return 0;
    215     }
    216     while ((fgets(line, sizeof(line), proc)) != NULL) {
    217         if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
    218             fclose(proc);
    219             return 1;
    220         }
    221     }
    222     fclose(proc);
    223     property_set(DRIVER_PROP_NAME, "unloaded");
    224     return 0;
    225 #else
    226     return 1;
    227 #endif
    228 }
    229 
    230 int wifi_load_driver()
    231 {
    232 #ifdef WIFI_DRIVER_MODULE_PATH
    233     char driver_status[PROPERTY_VALUE_MAX];
    234     int count = 100; /* wait at most 20 seconds for completion */
    235 
    236     if (is_wifi_driver_loaded()) {
    237         return 0;
    238     }
    239 
    240     if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
    241         return -1;
    242 
    243     if (strcmp(FIRMWARE_LOADER,"") == 0) {
    244         /* usleep(WIFI_DRIVER_LOADER_DELAY); */
    245         property_set(DRIVER_PROP_NAME, "ok");
    246     }
    247     else {
    248         property_set("ctl.start", FIRMWARE_LOADER);
    249     }
    250     sched_yield();
    251     while (count-- > 0) {
    252         if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
    253             if (strcmp(driver_status, "ok") == 0)
    254                 return 0;
    255             else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) {
    256                 wifi_unload_driver();
    257                 return -1;
    258             }
    259         }
    260         usleep(200000);
    261     }
    262     property_set(DRIVER_PROP_NAME, "timeout");
    263     wifi_unload_driver();
    264     return -1;
    265 #else
    266     property_set(DRIVER_PROP_NAME, "ok");
    267     return 0;
    268 #endif
    269 }
    270 
    271 int wifi_unload_driver()
    272 {
    273     usleep(200000); /* allow to finish interface down */
    274 #ifdef WIFI_DRIVER_MODULE_PATH
    275     if (rmmod(DRIVER_MODULE_NAME) == 0) {
    276         int count = 20; /* wait at most 10 seconds for completion */
    277         while (count-- > 0) {
    278             if (!is_wifi_driver_loaded())
    279                 break;
    280             usleep(500000);
    281         }
    282         usleep(500000); /* allow card removal */
    283         if (count) {
    284             return 0;
    285         }
    286         return -1;
    287     } else
    288         return -1;
    289 #else
    290     property_set(DRIVER_PROP_NAME, "unloaded");
    291     return 0;
    292 #endif
    293 }
    294 
    295 int ensure_entropy_file_exists()
    296 {
    297     int ret;
    298     int destfd;
    299 
    300     ret = access(SUPP_ENTROPY_FILE, R_OK|W_OK);
    301     if ((ret == 0) || (errno == EACCES)) {
    302         if ((ret != 0) &&
    303             (chmod(SUPP_ENTROPY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
    304             ALOGE("Cannot set RW to \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
    305             return -1;
    306         }
    307         return 0;
    308     }
    309     destfd = TEMP_FAILURE_RETRY(open(SUPP_ENTROPY_FILE, O_CREAT|O_RDWR, 0660));
    310     if (destfd < 0) {
    311         ALOGE("Cannot create \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
    312         return -1;
    313     }
    314 
    315     if (TEMP_FAILURE_RETRY(write(destfd, dummy_key, sizeof(dummy_key))) != sizeof(dummy_key)) {
    316         ALOGE("Error writing \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
    317         close(destfd);
    318         return -1;
    319     }
    320     close(destfd);
    321 
    322     /* chmod is needed because open() didn't set permisions properly */
    323     if (chmod(SUPP_ENTROPY_FILE, 0660) < 0) {
    324         ALOGE("Error changing permissions of %s to 0660: %s",
    325              SUPP_ENTROPY_FILE, strerror(errno));
    326         unlink(SUPP_ENTROPY_FILE);
    327         return -1;
    328     }
    329 
    330     if (chown(SUPP_ENTROPY_FILE, AID_SYSTEM, AID_WIFI) < 0) {
    331         ALOGE("Error changing group ownership of %s to %d: %s",
    332              SUPP_ENTROPY_FILE, AID_WIFI, strerror(errno));
    333         unlink(SUPP_ENTROPY_FILE);
    334         return -1;
    335     }
    336     return 0;
    337 }
    338 
    339 int ensure_config_file_exists(const char *config_file)
    340 {
    341     char buf[2048];
    342     int srcfd, destfd;
    343     struct stat sb;
    344     int nread;
    345     int ret;
    346 
    347     ret = access(config_file, R_OK|W_OK);
    348     if ((ret == 0) || (errno == EACCES)) {
    349         if ((ret != 0) &&
    350             (chmod(config_file, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
    351             ALOGE("Cannot set RW to \"%s\": %s", config_file, strerror(errno));
    352             return -1;
    353         }
    354         return 0;
    355     } else if (errno != ENOENT) {
    356         ALOGE("Cannot access \"%s\": %s", config_file, strerror(errno));
    357         return -1;
    358     }
    359 
    360     srcfd = TEMP_FAILURE_RETRY(open(SUPP_CONFIG_TEMPLATE, O_RDONLY));
    361     if (srcfd < 0) {
    362         ALOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
    363         return -1;
    364     }
    365 
    366     destfd = TEMP_FAILURE_RETRY(open(config_file, O_CREAT|O_RDWR, 0660));
    367     if (destfd < 0) {
    368         close(srcfd);
    369         ALOGE("Cannot create \"%s\": %s", config_file, strerror(errno));
    370         return -1;
    371     }
    372 
    373     while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) {
    374         if (nread < 0) {
    375             ALOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
    376             close(srcfd);
    377             close(destfd);
    378             unlink(config_file);
    379             return -1;
    380         }
    381         TEMP_FAILURE_RETRY(write(destfd, buf, nread));
    382     }
    383 
    384     close(destfd);
    385     close(srcfd);
    386 
    387     /* chmod is needed because open() didn't set permisions properly */
    388     if (chmod(config_file, 0660) < 0) {
    389         ALOGE("Error changing permissions of %s to 0660: %s",
    390              config_file, strerror(errno));
    391         unlink(config_file);
    392         return -1;
    393     }
    394 
    395     if (chown(config_file, AID_SYSTEM, AID_WIFI) < 0) {
    396         ALOGE("Error changing group ownership of %s to %d: %s",
    397              config_file, AID_WIFI, strerror(errno));
    398         unlink(config_file);
    399         return -1;
    400     }
    401     return 0;
    402 }
    403 
    404 int wifi_start_supplicant(int p2p_supported)
    405 {
    406     char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
    407     int count = 200; /* wait at most 20 seconds for completion */
    408 #ifdef HAVE_LIBC_SYSTEM_PROPERTIES
    409     const prop_info *pi;
    410     unsigned serial = 0, i;
    411 #endif
    412 
    413     if (p2p_supported) {
    414         strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
    415         strcpy(supplicant_prop_name, P2P_PROP_NAME);
    416 
    417         /* Ensure p2p config file is created */
    418         if (ensure_config_file_exists(P2P_CONFIG_FILE) < 0) {
    419             ALOGE("Failed to create a p2p config file");
    420             return -1;
    421         }
    422 
    423     } else {
    424         strcpy(supplicant_name, SUPPLICANT_NAME);
    425         strcpy(supplicant_prop_name, SUPP_PROP_NAME);
    426     }
    427 
    428     /* Check whether already running */
    429     if (property_get(supplicant_prop_name, supp_status, NULL)
    430             && strcmp(supp_status, "running") == 0) {
    431         return 0;
    432     }
    433 
    434     /* Before starting the daemon, make sure its config file exists */
    435     if (ensure_config_file_exists(SUPP_CONFIG_FILE) < 0) {
    436         ALOGE("Wi-Fi will not be enabled");
    437         return -1;
    438     }
    439 
    440     if (ensure_entropy_file_exists() < 0) {
    441         ALOGE("Wi-Fi entropy file was not created");
    442     }
    443 
    444     /* Clear out any stale socket files that might be left over. */
    445     wpa_ctrl_cleanup();
    446 
    447     /* Reset sockets used for exiting from hung state */
    448     exit_sockets[0] = exit_sockets[1] = -1;
    449 
    450 #ifdef HAVE_LIBC_SYSTEM_PROPERTIES
    451     /*
    452      * Get a reference to the status property, so we can distinguish
    453      * the case where it goes stopped => running => stopped (i.e.,
    454      * it start up, but fails right away) from the case in which
    455      * it starts in the stopped state and never manages to start
    456      * running at all.
    457      */
    458     pi = __system_property_find(supplicant_prop_name);
    459     if (pi != NULL) {
    460         serial = __system_property_serial(pi);
    461     }
    462 #endif
    463     property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE);
    464 
    465     property_set("ctl.start", supplicant_name);
    466     sched_yield();
    467 
    468     while (count-- > 0) {
    469 #ifdef HAVE_LIBC_SYSTEM_PROPERTIES
    470         if (pi == NULL) {
    471             pi = __system_property_find(supplicant_prop_name);
    472         }
    473         if (pi != NULL) {
    474             /*
    475              * property serial updated means that init process is scheduled
    476              * after we sched_yield, further property status checking is based on this */
    477             if (__system_property_serial(pi) != serial) {
    478                 __system_property_read(pi, NULL, supp_status);
    479                 if (strcmp(supp_status, "running") == 0) {
    480                     return 0;
    481                 } else if (strcmp(supp_status, "stopped") == 0) {
    482                     return -1;
    483                 }
    484             }
    485         }
    486 #else
    487         if (property_get(supplicant_prop_name, supp_status, NULL)) {
    488             if (strcmp(supp_status, "running") == 0)
    489                 return 0;
    490         }
    491 #endif
    492         usleep(100000);
    493     }
    494     return -1;
    495 }
    496 
    497 int wifi_stop_supplicant(int p2p_supported)
    498 {
    499     char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
    500     int count = 50; /* wait at most 5 seconds for completion */
    501 
    502     if (p2p_supported) {
    503         strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
    504         strcpy(supplicant_prop_name, P2P_PROP_NAME);
    505     } else {
    506         strcpy(supplicant_name, SUPPLICANT_NAME);
    507         strcpy(supplicant_prop_name, SUPP_PROP_NAME);
    508     }
    509 
    510     /* Check whether supplicant already stopped */
    511     if (property_get(supplicant_prop_name, supp_status, NULL)
    512         && strcmp(supp_status, "stopped") == 0) {
    513         return 0;
    514     }
    515 
    516     property_set("ctl.stop", supplicant_name);
    517     sched_yield();
    518 
    519     while (count-- > 0) {
    520         if (property_get(supplicant_prop_name, supp_status, NULL)) {
    521             if (strcmp(supp_status, "stopped") == 0)
    522                 return 0;
    523         }
    524         usleep(100000);
    525     }
    526     ALOGE("Failed to stop supplicant");
    527     return -1;
    528 }
    529 
    530 int wifi_connect_on_socket_path(const char *path)
    531 {
    532     char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
    533 
    534     /* Make sure supplicant is running */
    535     if (!property_get(supplicant_prop_name, supp_status, NULL)
    536             || strcmp(supp_status, "running") != 0) {
    537         ALOGE("Supplicant not running, cannot connect");
    538         return -1;
    539     }
    540 
    541     ctrl_conn = wpa_ctrl_open(path);
    542     if (ctrl_conn == NULL) {
    543         ALOGE("Unable to open connection to supplicant on \"%s\": %s",
    544              path, strerror(errno));
    545         return -1;
    546     }
    547     monitor_conn = wpa_ctrl_open(path);
    548     if (monitor_conn == NULL) {
    549         wpa_ctrl_close(ctrl_conn);
    550         ctrl_conn = NULL;
    551         return -1;
    552     }
    553     if (wpa_ctrl_attach(monitor_conn) != 0) {
    554         wpa_ctrl_close(monitor_conn);
    555         wpa_ctrl_close(ctrl_conn);
    556         ctrl_conn = monitor_conn = NULL;
    557         return -1;
    558     }
    559 
    560     if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) {
    561         wpa_ctrl_close(monitor_conn);
    562         wpa_ctrl_close(ctrl_conn);
    563         ctrl_conn = monitor_conn = NULL;
    564         return -1;
    565     }
    566 
    567     return 0;
    568 }
    569 
    570 /* Establishes the control and monitor socket connections on the interface */
    571 int wifi_connect_to_supplicant()
    572 {
    573     static char path[PATH_MAX];
    574 
    575     if (access(IFACE_DIR, F_OK) == 0) {
    576         snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);
    577     } else {
    578         snprintf(path, sizeof(path), "@android:wpa_%s", primary_iface);
    579     }
    580     return wifi_connect_on_socket_path(path);
    581 }
    582 
    583 int wifi_send_command(const char *cmd, char *reply, size_t *reply_len)
    584 {
    585     int ret;
    586     if (ctrl_conn == NULL) {
    587         ALOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
    588         return -1;
    589     }
    590     ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL);
    591     if (ret == -2) {
    592         ALOGD("'%s' command timed out.\n", cmd);
    593         /* unblocks the monitor receive socket for termination */
    594         TEMP_FAILURE_RETRY(write(exit_sockets[0], "T", 1));
    595         return -2;
    596     } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
    597         return -1;
    598     }
    599     if (strncmp(cmd, "PING", 4) == 0) {
    600         reply[*reply_len] = '\0';
    601     }
    602     return 0;
    603 }
    604 
    605 int wifi_supplicant_connection_active()
    606 {
    607     char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
    608 
    609     if (property_get(supplicant_prop_name, supp_status, NULL)) {
    610         if (strcmp(supp_status, "stopped") == 0)
    611             return -1;
    612     }
    613 
    614     return 0;
    615 }
    616 
    617 int wifi_ctrl_recv(char *reply, size_t *reply_len)
    618 {
    619     int res;
    620     int ctrlfd = wpa_ctrl_get_fd(monitor_conn);
    621     struct pollfd rfds[2];
    622 
    623     memset(rfds, 0, 2 * sizeof(struct pollfd));
    624     rfds[0].fd = ctrlfd;
    625     rfds[0].events |= POLLIN;
    626     rfds[1].fd = exit_sockets[1];
    627     rfds[1].events |= POLLIN;
    628     do {
    629         res = TEMP_FAILURE_RETRY(poll(rfds, 2, 30000));
    630         if (res < 0) {
    631             ALOGE("Error poll = %d", res);
    632             return res;
    633         } else if (res == 0) {
    634             /* timed out, check if supplicant is active
    635              * or not ..
    636              */
    637             res = wifi_supplicant_connection_active();
    638             if (res < 0)
    639                 return -2;
    640         }
    641     } while (res == 0);
    642 
    643     if (rfds[0].revents & POLLIN) {
    644         return wpa_ctrl_recv(monitor_conn, reply, reply_len);
    645     }
    646 
    647     /* it is not rfds[0], then it must be rfts[1] (i.e. the exit socket)
    648      * or we timed out. In either case, this call has failed ..
    649      */
    650     return -2;
    651 }
    652 
    653 int wifi_wait_on_socket(char *buf, size_t buflen)
    654 {
    655     size_t nread = buflen - 1;
    656     int result;
    657     char *match, *match2;
    658 
    659     if (monitor_conn == NULL) {
    660         return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
    661                         primary_iface, WPA_EVENT_TERMINATING);
    662     }
    663 
    664     result = wifi_ctrl_recv(buf, &nread);
    665 
    666     /* Terminate reception on exit socket */
    667     if (result == -2) {
    668         return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
    669                         primary_iface, WPA_EVENT_TERMINATING);
    670     }
    671 
    672     if (result < 0) {
    673         ALOGD("wifi_ctrl_recv failed: %s\n", strerror(errno));
    674         return snprintf(buf, buflen, "IFNAME=%s %s - recv error",
    675                         primary_iface, WPA_EVENT_TERMINATING);
    676     }
    677     buf[nread] = '\0';
    678     /* Check for EOF on the socket */
    679     if (result == 0 && nread == 0) {
    680         /* Fabricate an event to pass up */
    681         ALOGD("Received EOF on supplicant socket\n");
    682         return snprintf(buf, buflen, "IFNAME=%s %s - signal 0 received",
    683                         primary_iface, WPA_EVENT_TERMINATING);
    684     }
    685     /*
    686      * Events strings are in the format
    687      *
    688      *     IFNAME=iface <N>CTRL-EVENT-XXX
    689      *        or
    690      *     <N>CTRL-EVENT-XXX
    691      *
    692      * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
    693      * etc.) and XXX is the event name. The level information is not useful
    694      * to us, so strip it off.
    695      */
    696 
    697     if (strncmp(buf, IFNAME, IFNAMELEN) == 0) {
    698         match = strchr(buf, ' ');
    699         if (match != NULL) {
    700             if (match[1] == '<') {
    701                 match2 = strchr(match + 2, '>');
    702                 if (match2 != NULL) {
    703                     nread -= (match2 - match);
    704                     memmove(match + 1, match2 + 1, nread - (match - buf) + 1);
    705                 }
    706             }
    707         } else {
    708             return snprintf(buf, buflen, "%s", WPA_EVENT_IGNORE);
    709         }
    710     } else if (buf[0] == '<') {
    711         match = strchr(buf, '>');
    712         if (match != NULL) {
    713             nread -= (match + 1 - buf);
    714             memmove(buf, match + 1, nread + 1);
    715             ALOGV("supplicant generated event without interface - %s\n", buf);
    716         }
    717     } else {
    718         /* let the event go as is! */
    719         ALOGW("supplicant generated event without interface and without message level - %s\n", buf);
    720     }
    721 
    722     return nread;
    723 }
    724 
    725 int wifi_wait_for_event(char *buf, size_t buflen)
    726 {
    727     return wifi_wait_on_socket(buf, buflen);
    728 }
    729 
    730 void wifi_close_sockets()
    731 {
    732     if (ctrl_conn != NULL) {
    733         wpa_ctrl_close(ctrl_conn);
    734         ctrl_conn = NULL;
    735     }
    736 
    737     if (monitor_conn != NULL) {
    738         wpa_ctrl_close(monitor_conn);
    739         monitor_conn = NULL;
    740     }
    741 
    742     if (exit_sockets[0] >= 0) {
    743         close(exit_sockets[0]);
    744         exit_sockets[0] = -1;
    745     }
    746 
    747     if (exit_sockets[1] >= 0) {
    748         close(exit_sockets[1]);
    749         exit_sockets[1] = -1;
    750     }
    751 }
    752 
    753 void wifi_close_supplicant_connection()
    754 {
    755     char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
    756     int count = 50; /* wait at most 5 seconds to ensure init has stopped stupplicant */
    757 
    758     wifi_close_sockets();
    759 
    760     while (count-- > 0) {
    761         if (property_get(supplicant_prop_name, supp_status, NULL)) {
    762             if (strcmp(supp_status, "stopped") == 0)
    763                 return;
    764         }
    765         usleep(100000);
    766     }
    767 }
    768 
    769 int wifi_command(const char *command, char *reply, size_t *reply_len)
    770 {
    771     return wifi_send_command(command, reply, reply_len);
    772 }
    773 
    774 const char *wifi_get_fw_path(int fw_type)
    775 {
    776     switch (fw_type) {
    777     case WIFI_GET_FW_PATH_STA:
    778         return WIFI_DRIVER_FW_PATH_STA;
    779     case WIFI_GET_FW_PATH_AP:
    780         return WIFI_DRIVER_FW_PATH_AP;
    781     case WIFI_GET_FW_PATH_P2P:
    782         return WIFI_DRIVER_FW_PATH_P2P;
    783     }
    784     return NULL;
    785 }
    786 
    787 int wifi_change_fw_path(const char *fwpath)
    788 {
    789     int len;
    790     int fd;
    791     int ret = 0;
    792 
    793     if (!fwpath)
    794         return ret;
    795     fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY));
    796     if (fd < 0) {
    797         ALOGE("Failed to open wlan fw path param (%s)", strerror(errno));
    798         return -1;
    799     }
    800     len = strlen(fwpath) + 1;
    801     if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) {
    802         ALOGE("Failed to write wlan fw path param (%s)", strerror(errno));
    803         ret = -1;
    804     }
    805     close(fd);
    806     return ret;
    807 }
    808