X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=wifi%2Fwifi.c;h=5a42e2d481654d4ea10807775670eb9eb3c4b96b;hb=584c285492a04c711c6339720c6f9bc84895201b;hp=5afefdc70e117791b0b3ad39f24caba35006bf82;hpb=2f3aa31fa29a7afc44ba017f37543830625ea550;p=android-x86%2Fhardware-libhardware_legacy.git diff --git a/wifi/wifi.c b/wifi/wifi.c index 5afefdc..5a42e2d 100644 --- a/wifi/wifi.c +++ b/wifi/wifi.c @@ -19,6 +19,9 @@ #include #include #include +#include +#include +#include #include "hardware_legacy/wifi.h" #include "libwpa_client/wpa_ctrl.h" @@ -34,8 +37,21 @@ #include #endif -static struct wpa_ctrl *ctrl_conn; -static struct wpa_ctrl *monitor_conn; +/* PRIMARY refers to the connection on the primary interface + * SECONDARY refers to an optional connection on a p2p interface + * + * For concurrency, we only support one active p2p connection and + * one active STA connection at a time + */ +#define PRIMARY 0 +#define SECONDARY 1 +#define MAX_CONNS 2 + +static struct wpa_ctrl *ctrl_conn[MAX_CONNS]; +static struct wpa_ctrl *monitor_conn[MAX_CONNS]; + +/* socket pair used to exit from a blocking read */ +static int exit_sockets[MAX_CONNS][2]; extern int do_dhcp(); extern int ifc_init(); @@ -45,7 +61,7 @@ extern void get_dhcp_info(); extern int init_module(void *, unsigned long, const char *); extern int delete_module(const char *, unsigned int); -static char iface[PROPERTY_VALUE_MAX]; +static char primary_iface[PROPERTY_VALUE_MAX]; // TODO: use new ANDROID_SOCKET mechanism, once support for multiple // sockets is in @@ -84,15 +100,34 @@ static const char FIRMWARE_LOADER[] = WIFI_FIRMWARE_LOADER; static const char DRIVER_PROP_NAME[] = "wlan.driver.status"; static const char SUPPLICANT_NAME[] = "wpa_supplicant"; static const char SUPP_PROP_NAME[] = "init.svc.wpa_supplicant"; +static const char P2P_SUPPLICANT_NAME[] = "p2p_supplicant"; +static const char P2P_PROP_NAME[] = "init.svc.p2p_supplicant"; static const char SUPP_CONFIG_TEMPLATE[]= "/system/etc/wifi/wpa_supplicant.conf"; static const char SUPP_CONFIG_FILE[] = "/data/misc/wifi/wpa_supplicant.conf"; +static const char P2P_CONFIG_FILE[] = "/data/misc/wifi/p2p_supplicant.conf"; +static const char CONTROL_IFACE_PATH[] = "/data/misc/wifi/sockets"; static const char MODULE_FILE[] = "/proc/modules"; static const char SUPP_ENTROPY_FILE[] = WIFI_ENTROPY_FILE; -static unsigned char dummy_key[20] = { 0x11, 0xbe, 0x33, 0x43, 0x35, - 0x68, 0x47, 0x84, 0x99, 0xa9, - 0x2b, 0x1c, 0xd3, 0xee, 0xff, - 0xf1, 0xe2, 0xf3, 0xf4, 0xf5 }; +static unsigned char dummy_key[21] = { 0x02, 0x11, 0xbe, 0x33, 0x43, 0x35, + 0x68, 0x47, 0x84, 0x99, 0xa9, 0x2b, + 0x1c, 0xd3, 0xee, 0xff, 0xf1, 0xe2, + 0xf3, 0xf4, 0xf5 }; + +/* Is either SUPPLICANT_NAME or P2P_SUPPLICANT_NAME */ +static char supplicant_name[PROPERTY_VALUE_MAX]; +/* Is either SUPP_PROP_NAME or P2P_PROP_NAME */ +static char supplicant_prop_name[PROPERTY_KEY_MAX]; + +static int is_primary_interface(const char *ifname) +{ + //Treat NULL as primary interface to allow control + //on STA without an interface + if (ifname == NULL || !strncmp(ifname, primary_iface, strlen(primary_iface))) { + return 1; + } + return 0; +} static int insmod(const char *filename, const char *args) { @@ -125,7 +160,7 @@ static int rmmod(const char *modname) } if (ret != 0) - LOGD("Unable to unload driver module \"%s\": %s\n", + ALOGD("Unable to unload driver module \"%s\": %s\n", modname, strerror(errno)); return ret; } @@ -133,13 +168,13 @@ static int rmmod(const char *modname) int do_dhcp_request(int *ipaddr, int *gateway, int *mask, int *dns1, int *dns2, int *server, int *lease) { /* For test driver, always report success */ - if (strcmp(iface, WIFI_TEST_INTERFACE) == 0) + if (strcmp(primary_iface, WIFI_TEST_INTERFACE) == 0) return 0; if (ifc_init() < 0) return -1; - if (do_dhcp(iface) < 0) { + if (do_dhcp(primary_iface) < 0) { ifc_close(); return -1; } @@ -171,7 +206,7 @@ int is_wifi_driver_loaded() { * crash. */ if ((proc = fopen(MODULE_FILE, "r")) == NULL) { - LOGW("Could not open %s: %s", MODULE_FILE, strerror(errno)); + ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno)); property_set(DRIVER_PROP_NAME, "unloaded"); return 0; } @@ -263,19 +298,19 @@ int ensure_entropy_file_exists() if ((ret == 0) || (errno == EACCES)) { if ((ret != 0) && (chmod(SUPP_ENTROPY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) { - LOGE("Cannot set RW to \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno)); + ALOGE("Cannot set RW to \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno)); return -1; } return 0; } - destfd = open(SUPP_ENTROPY_FILE, O_CREAT|O_RDWR, 0660); + destfd = TEMP_FAILURE_RETRY(open(SUPP_ENTROPY_FILE, O_CREAT|O_RDWR, 0660)); if (destfd < 0) { - LOGE("Cannot create \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno)); + ALOGE("Cannot create \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno)); return -1; } - if (write(destfd, dummy_key, sizeof(dummy_key)) != sizeof(dummy_key)) { - LOGE("Error writing \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno)); + if (TEMP_FAILURE_RETRY(write(destfd, dummy_key, sizeof(dummy_key))) != sizeof(dummy_key)) { + ALOGE("Error writing \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno)); close(destfd); return -1; } @@ -283,14 +318,14 @@ int ensure_entropy_file_exists() /* chmod is needed because open() didn't set permisions properly */ if (chmod(SUPP_ENTROPY_FILE, 0660) < 0) { - LOGE("Error changing permissions of %s to 0660: %s", + ALOGE("Error changing permissions of %s to 0660: %s", SUPP_ENTROPY_FILE, strerror(errno)); unlink(SUPP_ENTROPY_FILE); return -1; } if (chown(SUPP_ENTROPY_FILE, AID_SYSTEM, AID_WIFI) < 0) { - LOGE("Error changing group ownership of %s to %d: %s", + ALOGE("Error changing group ownership of %s to %d: %s", SUPP_ENTROPY_FILE, AID_WIFI, strerror(errno)); unlink(SUPP_ENTROPY_FILE); return -1; @@ -298,115 +333,133 @@ int ensure_entropy_file_exists() return 0; } -int ensure_config_file_exists() -{ - char buf[2048]; +int update_ctrl_interface(const char *config_file) { + + int srcfd, destfd; + int nread; char ifc[PROPERTY_VALUE_MAX]; - char *sptr; char *pbuf; + char *sptr; + struct stat sb; + + if (stat(config_file, &sb) != 0) + return -1; + + pbuf = malloc(sb.st_size + PROPERTY_VALUE_MAX); + if (!pbuf) + return 0; + srcfd = TEMP_FAILURE_RETRY(open(config_file, O_RDONLY)); + if (srcfd < 0) { + ALOGE("Cannot open \"%s\": %s", config_file, strerror(errno)); + free(pbuf); + return 0; + } + nread = TEMP_FAILURE_RETRY(read(srcfd, pbuf, sb.st_size)); + close(srcfd); + if (nread < 0) { + ALOGE("Cannot read \"%s\": %s", config_file, strerror(errno)); + free(pbuf); + return 0; + } + + if (!strcmp(config_file, SUPP_CONFIG_FILE)) { + property_get("wifi.interface", ifc, WIFI_TEST_INTERFACE); + } else { + strcpy(ifc, CONTROL_IFACE_PATH); + } + if ((sptr = strstr(pbuf, "ctrl_interface="))) { + char *iptr = sptr + strlen("ctrl_interface="); + int ilen = 0; + int mlen = strlen(ifc); + int nwrite; + if (strncmp(ifc, iptr, mlen) != 0) { + ALOGE("ctrl_interface != %s", ifc); + while (((ilen + (iptr - pbuf)) < nread) && (iptr[ilen] != '\n')) + ilen++; + mlen = ((ilen >= mlen) ? ilen : mlen) + 1; + memmove(iptr + mlen, iptr + ilen + 1, nread - (iptr + ilen + 1 - pbuf)); + memset(iptr, '\n', mlen); + memcpy(iptr, ifc, strlen(ifc)); + destfd = TEMP_FAILURE_RETRY(open(config_file, O_RDWR, 0660)); + if (destfd < 0) { + ALOGE("Cannot update \"%s\": %s", config_file, strerror(errno)); + free(pbuf); + return -1; + } + TEMP_FAILURE_RETRY(write(destfd, pbuf, nread + mlen - ilen -1)); + close(destfd); + } + } + free(pbuf); + return 0; +} + +int ensure_config_file_exists(const char *config_file) +{ + char buf[2048]; int srcfd, destfd; struct stat sb; int nread; int ret; - ret = access(SUPP_CONFIG_FILE, R_OK|W_OK); + ret = access(config_file, R_OK|W_OK); if ((ret == 0) || (errno == EACCES)) { if ((ret != 0) && - (chmod(SUPP_CONFIG_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) { - LOGE("Cannot set RW to \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno)); + (chmod(config_file, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) { + ALOGE("Cannot set RW to \"%s\": %s", config_file, strerror(errno)); return -1; } /* return if filesize is at least 10 bytes */ - if (stat(SUPP_CONFIG_FILE, &sb) == 0 && sb.st_size > 10) { - pbuf = malloc(sb.st_size + PROPERTY_VALUE_MAX); - if (!pbuf) - return 0; - srcfd = open(SUPP_CONFIG_FILE, O_RDONLY); - if (srcfd < 0) { - LOGE("Cannot open \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno)); - free(pbuf); - return 0; - } - nread = read(srcfd, pbuf, sb.st_size); - close(srcfd); - if (nread < 0) { - LOGE("Cannot read \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno)); - free(pbuf); - return 0; - } - property_get("wifi.interface", ifc, WIFI_TEST_INTERFACE); - if ((sptr = strstr(pbuf, "ctrl_interface="))) { - char *iptr = sptr + strlen("ctrl_interface="); - int ilen = 0; - int mlen = strlen(ifc); - if (strncmp(ifc, iptr, mlen) != 0) { - LOGE("ctrl_interface != %s", ifc); - while (((ilen + (iptr - pbuf)) < nread) && (iptr[ilen] != '\n')) - ilen++; - mlen = ((ilen >= mlen) ? ilen : mlen) + 1; - memmove(iptr + mlen, iptr + ilen + 1, nread - (iptr + ilen + 1 - pbuf)); - memset(iptr, '\n', mlen); - memcpy(iptr, ifc, strlen(ifc)); - destfd = open(SUPP_CONFIG_FILE, O_RDWR, 0660); - if (destfd < 0) { - LOGE("Cannot update \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno)); - free(pbuf); - return -1; - } - write(destfd, pbuf, nread); - close(destfd); - } - } - free(pbuf); - return 0; + if (stat(config_file, &sb) == 0 && sb.st_size > 10) { + return update_ctrl_interface(config_file); } } else if (errno != ENOENT) { - LOGE("Cannot access \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno)); + ALOGE("Cannot access \"%s\": %s", config_file, strerror(errno)); return -1; } - srcfd = open(SUPP_CONFIG_TEMPLATE, O_RDONLY); + srcfd = TEMP_FAILURE_RETRY(open(SUPP_CONFIG_TEMPLATE, O_RDONLY)); if (srcfd < 0) { - LOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno)); + ALOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno)); return -1; } - destfd = open(SUPP_CONFIG_FILE, O_CREAT|O_RDWR, 0660); + destfd = TEMP_FAILURE_RETRY(open(config_file, O_CREAT|O_RDWR, 0660)); if (destfd < 0) { close(srcfd); - LOGE("Cannot create \"%s\": %s", SUPP_CONFIG_FILE, strerror(errno)); + ALOGE("Cannot create \"%s\": %s", config_file, strerror(errno)); return -1; } - while ((nread = read(srcfd, buf, sizeof(buf))) != 0) { + while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) { if (nread < 0) { - LOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno)); + ALOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno)); close(srcfd); close(destfd); - unlink(SUPP_CONFIG_FILE); + unlink(config_file); return -1; } - write(destfd, buf, nread); + TEMP_FAILURE_RETRY(write(destfd, buf, nread)); } close(destfd); close(srcfd); /* chmod is needed because open() didn't set permisions properly */ - if (chmod(SUPP_CONFIG_FILE, 0660) < 0) { - LOGE("Error changing permissions of %s to 0660: %s", - SUPP_CONFIG_FILE, strerror(errno)); - unlink(SUPP_CONFIG_FILE); + if (chmod(config_file, 0660) < 0) { + ALOGE("Error changing permissions of %s to 0660: %s", + config_file, strerror(errno)); + unlink(config_file); return -1; } - if (chown(SUPP_CONFIG_FILE, AID_SYSTEM, AID_WIFI) < 0) { - LOGE("Error changing group ownership of %s to %d: %s", - SUPP_CONFIG_FILE, AID_WIFI, strerror(errno)); - unlink(SUPP_CONFIG_FILE); + if (chown(config_file, AID_SYSTEM, AID_WIFI) < 0) { + ALOGE("Error changing group ownership of %s to %d: %s", + config_file, AID_WIFI, strerror(errno)); + unlink(config_file); return -1; } - return 0; + return update_ctrl_interface(config_file); } /** @@ -448,35 +501,54 @@ void wifi_wpa_ctrl_cleanup(void) closedir(dir); } -int wifi_start_supplicant() +int wifi_start_supplicant(int p2p_supported) { - char daemon_cmd[PROPERTY_VALUE_MAX]; char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; int count = 200; /* wait at most 20 seconds for completion */ #ifdef HAVE_LIBC_SYSTEM_PROPERTIES const prop_info *pi; - unsigned serial = 0; + unsigned serial = 0, i; #endif + if (p2p_supported) { + strcpy(supplicant_name, P2P_SUPPLICANT_NAME); + strcpy(supplicant_prop_name, P2P_PROP_NAME); + + /* Ensure p2p config file is created */ + if (ensure_config_file_exists(P2P_CONFIG_FILE) < 0) { + ALOGE("Failed to create a p2p config file"); + return -1; + } + + } else { + strcpy(supplicant_name, SUPPLICANT_NAME); + strcpy(supplicant_prop_name, SUPP_PROP_NAME); + } + /* Check whether already running */ - if (property_get(SUPP_PROP_NAME, supp_status, NULL) + if (property_get(supplicant_name, supp_status, NULL) && strcmp(supp_status, "running") == 0) { return 0; } /* Before starting the daemon, make sure its config file exists */ - if (ensure_config_file_exists() < 0) { - LOGE("Wi-Fi will not be enabled"); + if (ensure_config_file_exists(SUPP_CONFIG_FILE) < 0) { + ALOGE("Wi-Fi will not be enabled"); return -1; } if (ensure_entropy_file_exists() < 0) { - LOGE("Wi-Fi entropy file was not created"); + ALOGE("Wi-Fi entropy file was not created"); } /* Clear out any stale socket files that might be left over. */ wifi_wpa_ctrl_cleanup(); + /* Reset sockets used for exiting from hung state */ + for (i=0; iserial; } #endif - property_get("wifi.interface", iface, WIFI_TEST_INTERFACE); - snprintf(daemon_cmd, PROPERTY_VALUE_MAX, "%s:-i%s", SUPPLICANT_NAME, iface); - property_set("ctl.start", daemon_cmd); + property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE); + + property_set("ctl.start", supplicant_name); sched_yield(); while (count-- > 0) { #ifdef HAVE_LIBC_SYSTEM_PROPERTIES if (pi == NULL) { - pi = __system_property_find(SUPP_PROP_NAME); + pi = __system_property_find(supplicant_prop_name); } if (pi != NULL) { __system_property_read(pi, NULL, supp_status); @@ -510,7 +582,7 @@ int wifi_start_supplicant() } } #else - if (property_get(SUPP_PROP_NAME, supp_status, NULL)) { + if (property_get(supplicant_prop_name, supp_status, NULL)) { if (strcmp(supp_status, "running") == 0) return 0; } @@ -526,16 +598,16 @@ int wifi_stop_supplicant() int count = 50; /* wait at most 5 seconds for completion */ /* Check whether supplicant already stopped */ - if (property_get(SUPP_PROP_NAME, supp_status, NULL) + if (property_get(supplicant_prop_name, supp_status, NULL) && strcmp(supp_status, "stopped") == 0) { return 0; } - property_set("ctl.stop", SUPPLICANT_NAME); + property_set("ctl.stop", supplicant_name); sched_yield(); while (count-- > 0) { - if (property_get(SUPP_PROP_NAME, supp_status, NULL)) { + if (property_get(supplicant_prop_name, supp_status, NULL)) { if (strcmp(supp_status, "stopped") == 0) return 0; } @@ -544,56 +616,77 @@ int wifi_stop_supplicant() return -1; } -int wifi_connect_to_supplicant() +int wifi_connect_on_socket_path(int index, const char *path) { - char ifname[256]; char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; /* Make sure supplicant is running */ - if (!property_get(SUPP_PROP_NAME, supp_status, NULL) + if (!property_get(supplicant_prop_name, supp_status, NULL) || strcmp(supp_status, "running") != 0) { - LOGE("Supplicant not running, cannot connect"); + ALOGE("Supplicant not running, cannot connect"); return -1; } - if (access(IFACE_DIR, F_OK) == 0) { - snprintf(ifname, sizeof(ifname), "%s/%s", IFACE_DIR, iface); - } else { - strlcpy(ifname, iface, sizeof(ifname)); + ctrl_conn[index] = wpa_ctrl_open(path); + if (ctrl_conn[index] == NULL) { + ALOGE("Unable to open connection to supplicant on \"%s\": %s", + path, strerror(errno)); + return -1; } - - ctrl_conn = wpa_ctrl_open(ifname); - if (ctrl_conn == NULL) { - LOGE("Unable to open connection to supplicant on \"%s\": %s", - ifname, strerror(errno)); + monitor_conn[index] = wpa_ctrl_open(path); + if (monitor_conn[index] == NULL) { + wpa_ctrl_close(ctrl_conn[index]); + ctrl_conn[index] = NULL; return -1; } - monitor_conn = wpa_ctrl_open(ifname); - if (monitor_conn == NULL) { - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; + if (wpa_ctrl_attach(monitor_conn[index]) != 0) { + wpa_ctrl_close(monitor_conn[index]); + wpa_ctrl_close(ctrl_conn[index]); + ctrl_conn[index] = monitor_conn[index] = NULL; return -1; } - if (wpa_ctrl_attach(monitor_conn) != 0) { - wpa_ctrl_close(monitor_conn); - wpa_ctrl_close(ctrl_conn); - ctrl_conn = monitor_conn = NULL; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets[index]) == -1) { + wpa_ctrl_close(monitor_conn[index]); + wpa_ctrl_close(ctrl_conn[index]); + ctrl_conn[index] = monitor_conn[index] = NULL; return -1; } + return 0; } -int wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_t *reply_len) +/* Establishes the control and monitor socket connections on the interface */ +int wifi_connect_to_supplicant(const char *ifname) +{ + char path[256]; + + if (is_primary_interface(ifname)) { + if (access(IFACE_DIR, F_OK) == 0) { + snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface); + } else { + strlcpy(path, primary_iface, sizeof(path)); + } + return wifi_connect_on_socket_path(PRIMARY, path); + } else { + sprintf(path, "%s/%s", CONTROL_IFACE_PATH, ifname); + return wifi_connect_on_socket_path(SECONDARY, path); + } +} + +int wifi_send_command(int index, const char *cmd, char *reply, size_t *reply_len) { int ret; - if (ctrl_conn == NULL) { - LOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd); + if (ctrl_conn[index] == NULL) { + ALOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd); return -1; } - ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL); + ret = wpa_ctrl_request(ctrl_conn[index], cmd, strlen(cmd), reply, reply_len, NULL); if (ret == -2) { - LOGD("'%s' command timed out.\n", cmd); + ALOGD("'%s' command timed out.\n", cmd); + /* unblocks the monitor receive socket for termination */ + TEMP_FAILURE_RETRY(write(exit_sockets[index][0], "T", 1)); return -2; } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) { return -1; @@ -604,7 +697,31 @@ int wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_ return 0; } -int wifi_wait_for_event(char *buf, size_t buflen) +int wifi_ctrl_recv(int index, char *reply, size_t *reply_len) +{ + int res; + int ctrlfd = wpa_ctrl_get_fd(monitor_conn[index]); + struct pollfd rfds[2]; + + memset(rfds, 0, 2 * sizeof(struct pollfd)); + rfds[0].fd = ctrlfd; + rfds[0].events |= POLLIN; + rfds[1].fd = exit_sockets[index][1]; + rfds[1].events |= POLLIN; + res = TEMP_FAILURE_RETRY(poll(rfds, 2, -1)); + if (res < 0) { + ALOGE("Error poll = %d", res); + return res; + } + if (rfds[0].revents & POLLIN) { + return wpa_ctrl_recv(monitor_conn[index], reply, reply_len); + } else { + return -2; + } + return 0; +} + +int wifi_wait_on_socket(int index, char *buf, size_t buflen) { size_t nread = buflen - 1; int fd; @@ -613,26 +730,33 @@ int wifi_wait_for_event(char *buf, size_t buflen) struct timeval tval; struct timeval *tptr; - if (monitor_conn == NULL) { - LOGD("Connection closed\n"); + if (monitor_conn[index] == NULL) { + ALOGD("Connection closed\n"); + strncpy(buf, WPA_EVENT_TERMINATING " - connection closed", buflen-1); + buf[buflen-1] = '\0'; + return strlen(buf); + } + + result = wifi_ctrl_recv(index, buf, &nread); + + /* Terminate reception on exit socket */ + if (result == -2) { strncpy(buf, WPA_EVENT_TERMINATING " - connection closed", buflen-1); buf[buflen-1] = '\0'; return strlen(buf); } - result = wpa_ctrl_recv(monitor_conn, buf, &nread); if (result < 0) { - LOGD("wpa_ctrl_recv failed: %s\n", strerror(errno)); + ALOGD("wifi_ctrl_recv failed: %s\n", strerror(errno)); strncpy(buf, WPA_EVENT_TERMINATING " - recv error", buflen-1); buf[buflen-1] = '\0'; return strlen(buf); } buf[nread] = '\0'; - /* LOGD("wait_for_event: result=%d nread=%d string=\"%s\"\n", result, nread, buf); */ /* Check for EOF on the socket */ if (result == 0 && nread == 0) { /* Fabricate an event to pass up */ - LOGD("Received EOF on supplicant socket\n"); + ALOGD("Received EOF on supplicant socket\n"); strncpy(buf, WPA_EVENT_TERMINATING " - signal 0 received", buflen-1); buf[buflen-1] = '\0'; return strlen(buf); @@ -653,25 +777,62 @@ int wifi_wait_for_event(char *buf, size_t buflen) memmove(buf, match+1, nread+1); } } + return nread; } -void wifi_close_supplicant_connection() +int wifi_wait_for_event(const char *ifname, char *buf, size_t buflen) +{ + if (is_primary_interface(ifname)) { + return wifi_wait_on_socket(PRIMARY, buf, buflen); + } else { + return wifi_wait_on_socket(SECONDARY, buf, buflen); + } +} + +void wifi_close_sockets(int index) +{ + if (ctrl_conn[index] != NULL) { + wpa_ctrl_close(ctrl_conn[index]); + ctrl_conn[index] = NULL; + } + + if (monitor_conn[index] != NULL) { + wpa_ctrl_close(monitor_conn[index]); + monitor_conn[index] = NULL; + } + + if (exit_sockets[index][0] >= 0) { + close(exit_sockets[index][0]); + exit_sockets[index][0] = -1; + } + + if (exit_sockets[index][1] >= 0) { + close(exit_sockets[index][1]); + exit_sockets[index][1] = -1; + } +} + +void wifi_close_supplicant_connection(const char *ifname) { char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; int count = 50; /* wait at most 5 seconds to ensure init has stopped stupplicant */ - if (ctrl_conn != NULL) { - wpa_ctrl_close(ctrl_conn); - ctrl_conn = NULL; - } - if (monitor_conn != NULL) { - wpa_ctrl_close(monitor_conn); - monitor_conn = NULL; + if (is_primary_interface(ifname)) { + wifi_close_sockets(PRIMARY); + } else { + /* p2p socket termination needs unblocking the monitor socket + * STA connection does not need it since supplicant gets shutdown + */ + TEMP_FAILURE_RETRY(write(exit_sockets[SECONDARY][0], "T", 1)); + wifi_close_sockets(SECONDARY); + //closing p2p connection does not need a wait on + //supplicant stop + return; } while (count-- > 0) { - if (property_get(SUPP_PROP_NAME, supp_status, NULL)) { + if (property_get(supplicant_prop_name, supp_status, NULL)) { if (strcmp(supp_status, "stopped") == 0) return; } @@ -679,9 +840,13 @@ void wifi_close_supplicant_connection() } } -int wifi_command(const char *command, char *reply, size_t *reply_len) +int wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len) { - return wifi_send_command(ctrl_conn, command, reply, reply_len); + if (is_primary_interface(ifname)) { + return wifi_send_command(PRIMARY, command, reply, reply_len); + } else { + return wifi_send_command(SECONDARY, command, reply, reply_len); + } } const char *wifi_get_fw_path(int fw_type) @@ -705,14 +870,14 @@ int wifi_change_fw_path(const char *fwpath) if (!fwpath) return ret; - fd = open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY); + fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY)); if (fd < 0) { - LOGE("Failed to open wlan fw path param (%s)", strerror(errno)); + ALOGE("Failed to open wlan fw path param (%s)", strerror(errno)); return -1; } len = strlen(fwpath) + 1; - if (write(fd, fwpath, len) != len) { - LOGE("Failed to write wlan fw path param (%s)", strerror(errno)); + if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) { + ALOGE("Failed to write wlan fw path param (%s)", strerror(errno)); ret = -1; } close(fd);