From 3674b8ab31a628c5d0834890ba3549bf8badf4ea Mon Sep 17 00:00:00 2001 From: Dedy Lansky Date: Fri, 11 Sep 2015 01:39:13 +0300 Subject: wifi: introduce wifi_fst module New wifi_fst module is responsible for: 1. insmod/rmmod of 2nd Wifi driver used for Fast Session Transfer (FST) rate upgrade. 2. start/stop FST Manager service. wifi_fst functionality is controlled by system property persist.fst.rate.upgrade.en. Existing module wifi.c calls into wifi_fst upon wifi_load/unload_driver and upon start/stop supplicant Change-Id: I8b4eddf26ab345b9e1e60e4850eaa081f8b89641 --- include/hardware_legacy/wifi.h | 14 + include/hardware_legacy/wifi_fst.h | 136 ++---- wifi/Android.mk | 12 +- wifi/wifi.c | 19 +- wifi/wifi_fst.c | 836 +++++-------------------------------- 5 files changed, 183 insertions(+), 834 deletions(-) diff --git a/include/hardware_legacy/wifi.h b/include/hardware_legacy/wifi.h index a60718d..e4aa93c 100644 --- a/include/hardware_legacy/wifi.h +++ b/include/hardware_legacy/wifi.h @@ -22,6 +22,20 @@ extern "C" { #endif /** + * Load kernel module + * + * @return 0 on success, < 0 on failure. + */ +int insmod(const char *filename, const char *args); + +/** +* Unload kernel module +* +* @return 0 on success, < 0 on failure. +*/ +int rmmod(const char *modname); + +/** * Load the Wi-Fi driver. * * @return 0 on success, < 0 on failure. diff --git a/include/hardware_legacy/wifi_fst.h b/include/hardware_legacy/wifi_fst.h index a60718d..952f132 100644 --- a/include/hardware_legacy/wifi_fst.h +++ b/include/hardware_legacy/wifi_fst.h @@ -1,4 +1,7 @@ /* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Not a Contribution. * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,149 +17,66 @@ * limitations under the License. */ -#ifndef _WIFI_H -#define _WIFI_H +#ifndef _WIFI_FST_H +#define _WIFI_FST_H #if __cplusplus extern "C" { #endif /** - * Load the Wi-Fi driver. + * returns whether FST is enabled or not according to + * persist.fst.rate.upgrade.en system property * - * @return 0 on success, < 0 on failure. + * @return 1 if FST enabled. */ -int wifi_load_driver(); +int is_fst_enabled(); /** - * Unload the Wi-Fi driver. - * - * @return 0 on success, < 0 on failure. - */ -int wifi_unload_driver(); - -/** - * Check if the Wi-Fi driver is loaded. - * Check if the Wi-Fi driver is loaded. - - * @return 0 on success, < 0 on failure. - */ -int is_wifi_driver_loaded(); - +* returns whether FST Soft AP is enabled or not according to +* persist.fst.softap.en system property +* +* @return 1 if FST Soft AP enabled. +*/ +int is_fst_softap_enabled(); /** - * Start supplicant. + * Load the Wi-Fi driver for FST rate upgrade. * * @return 0 on success, < 0 on failure. */ -int wifi_start_supplicant(int p2pSupported); +int wifi_fst_load_driver(); /** - * Stop supplicant. + * Unload the Wi-Fi driver for FST rate upgrade. * * @return 0 on success, < 0 on failure. */ -int wifi_stop_supplicant(int p2pSupported); +int wifi_fst_unload_driver(); /** - * Open a connection to supplicant - * - * @return 0 on success, < 0 on failure. - */ -int wifi_connect_to_supplicant(); + * Check if the Wi-Fi driver for FST rate upgrade is loaded. -/** - * Close connection to supplicant - * * @return 0 on success, < 0 on failure. */ -void wifi_close_supplicant_connection(); - -/** - * wifi_wait_for_event() performs a blocking call to - * get a Wi-Fi event and returns a string representing - * a Wi-Fi event when it occurs. - * - * @param buf is the buffer that receives the event - * @param len is the maximum length of the buffer - * - * @returns number of bytes in buffer, 0 if no - * event (for instance, no connection), and less than 0 - * if there is an error. - */ -int wifi_wait_for_event(char *buf, size_t len); +int is_fst_driver_loaded(); /** - * wifi_command() issues a command to the Wi-Fi driver. + * Start FST Manager. * - * Android extends the standard commands listed at - * /link http://hostap.epitest.fi/wpa_supplicant/devel/ctrl_iface_page.html - * to include support for sending commands to the driver: - * - * See wifi/java/android/net/wifi/WifiNative.java for the details of - * driver commands that are supported - * - * @param command is the string command (preallocated with 32 bytes) - * @param commandlen is command buffer length - * @param reply is a buffer to receive a reply string - * @param reply_len on entry, this is the maximum length of - * the reply buffer. On exit, the number of - * bytes in the reply buffer. - * - * @return 0 if successful, < 0 if an error. + * @return 0 on success, < 0 on failure. */ -int wifi_command(const char *command, char *reply, size_t *reply_len); +int wifi_start_fstman(int softap_mode); /** - * do_dhcp_request() issues a dhcp request and returns the acquired - * information. - * - * All IPV4 addresses/mask are in network byte order. - * - * @param ipaddr return the assigned IPV4 address - * @param gateway return the gateway being used - * @param mask return the IPV4 mask - * @param dns1 return the IPV4 address of a DNS server - * @param dns2 return the IPV4 address of a DNS server - * @param server return the IPV4 address of DHCP server - * @param lease return the length of lease in seconds. + * Stop FST Manager. * - * @return 0 if successful, < 0 if error. - */ -int do_dhcp_request(int *ipaddr, int *gateway, int *mask, - int *dns1, int *dns2, int *server, int *lease); - -/** - * Return the error string of the last do_dhcp_request(). - */ -const char *get_dhcp_error_string(); - -/** - * Return the path to requested firmware - */ -#define WIFI_GET_FW_PATH_STA 0 -#define WIFI_GET_FW_PATH_AP 1 -#define WIFI_GET_FW_PATH_P2P 2 -const char *wifi_get_fw_path(int fw_type); - -/** - * Change the path to firmware for the wlan driver - */ -int wifi_change_fw_path(const char *fwpath); - -/** - * Check and create if necessary initial entropy file + * @return 0 on success, < 0 on failure. */ -#define WIFI_ENTROPY_FILE "/data/misc/wifi/entropy.bin" -int ensure_entropy_file_exists(); - -/** -* Check and create if necessary the desired configuration file -*/ -int ensure_config_file_exists(const char *config_file, const char *config_file_template); +int wifi_stop_fstman(int softap_mode); #if __cplusplus }; // extern "C" #endif -#endif // _WIFI_H +#endif // _WIFI_FST_H diff --git a/wifi/Android.mk b/wifi/Android.mk index ed59b40..6421b4a 100644 --- a/wifi/Android.mk +++ b/wifi/Android.mk @@ -35,7 +35,17 @@ ifdef WIFI_DRIVER_STATE_OFF LOCAL_CFLAGS += -DWIFI_DRIVER_STATE_OFF=\"$(WIFI_DRIVER_STATE_OFF)\" endif -LOCAL_SRC_FILES += wifi/wifi.c +ifdef WIFI_FST_DRIVER_MODULE_PATH +LOCAL_CFLAGS += -DWIFI_FST_DRIVER_MODULE_PATH=\"$(WIFI_FST_DRIVER_MODULE_PATH)\" +endif +ifdef WIFI_FST_DRIVER_MODULE_ARG +LOCAL_CFLAGS += -DWIFI_FST_DRIVER_MODULE_ARG=\"$(WIFI_FST_DRIVER_MODULE_ARG)\" +endif +ifdef WIFI_FST_DRIVER_MODULE_NAME +LOCAL_CFLAGS += -DWIFI_FST_DRIVER_MODULE_NAME=\"$(WIFI_FST_DRIVER_MODULE_NAME)\" +endif + +LOCAL_SRC_FILES += wifi/wifi.c wifi/wifi_fst.c ifdef WPA_SUPPLICANT_VERSION LOCAL_CFLAGS += -DLIBWPA_CLIENT_EXISTS diff --git a/wifi/wifi.c b/wifi/wifi.c index 89e9397..7ee355a 100644 --- a/wifi/wifi.c +++ b/wifi/wifi.c @@ -25,6 +25,7 @@ #include #include "hardware_legacy/wifi.h" +#include "hardware_legacy/wifi_fst.h" #ifdef LIBWPA_CLIENT_EXISTS #include "libwpa_client/wpa_ctrl.h" #endif @@ -132,7 +133,7 @@ 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 insmod(const char *filename, const char *args) +int insmod(const char *filename, const char *args) { void *module; unsigned int size; @@ -149,7 +150,7 @@ static int insmod(const char *filename, const char *args) return ret; } -static int rmmod(const char *modname) +int rmmod(const char *modname) { int ret = -1; int maxtry = 10; @@ -240,7 +241,7 @@ int is_wifi_driver_loaded() { while ((fgets(line, sizeof(line), proc)) != NULL) { if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) { fclose(proc); - return 1; + return is_fst_driver_loaded(); } } fclose(proc); @@ -275,7 +276,7 @@ int wifi_load_driver() while (count-- > 0) { if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) { if (strcmp(driver_status, "ok") == 0) - return 0; + return wifi_fst_load_driver(); else if (strcmp(driver_status, "failed") == 0) { wifi_unload_driver(); return -1; @@ -303,6 +304,9 @@ int wifi_load_driver() int wifi_unload_driver() { usleep(200000); /* allow to finish interface down */ + + wifi_fst_unload_driver(); + #ifdef WIFI_DRIVER_MODULE_PATH if (rmmod(DRIVER_MODULE_NAME) == 0) { int count = 20; /* wait at most 10 seconds for completion */ @@ -446,6 +450,10 @@ int wifi_start_supplicant(int p2p_supported) const prop_info *pi; unsigned serial = 0, i; + if (wifi_start_fstman(0)) { + return -1; + } + if (p2p_supported) { strcpy(supplicant_name, P2P_SUPPLICANT_NAME); strcpy(supplicant_prop_name, P2P_PROP_NAME); @@ -537,6 +545,7 @@ int wifi_stop_supplicant(int p2p_supported) /* Check whether supplicant already stopped */ if (property_get(supplicant_prop_name, supp_status, NULL) && strcmp(supp_status, "stopped") == 0) { + wifi_stop_fstman(0); return 0; } @@ -546,11 +555,13 @@ int wifi_stop_supplicant(int p2p_supported) while (count-- > 0) { if (property_get(supplicant_prop_name, supp_status, NULL)) { if (strcmp(supp_status, "stopped") == 0) + wifi_stop_fstman(0); return 0; } usleep(100000); } ALOGE("Failed to stop supplicant"); + wifi_stop_fstman(0); return -1; } diff --git a/wifi/wifi_fst.c b/wifi/wifi_fst.c index 89e9397..3950ba5 100644 --- a/wifi/wifi_fst.c +++ b/wifi/wifi_fst.c @@ -1,4 +1,7 @@ /* + * Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * Not a Contribution. * Copyright 2008, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,820 +18,211 @@ */ #include -#include #include #include -#include -#include -#include -#include -#include - -#include "hardware_legacy/wifi.h" -#ifdef LIBWPA_CLIENT_EXISTS -#include "libwpa_client/wpa_ctrl.h" -#endif -#define LOG_TAG "WifiHW" +#define LOG_TAG "WifiFST" #include "cutils/log.h" -#include "cutils/memory.h" -#include "cutils/misc.h" #include "cutils/properties.h" -#include "private/android_filesystem_config.h" #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include -extern int do_dhcp(); -extern int ifc_init(); -extern void ifc_close(); -extern char *dhcp_lasterror(); -extern void get_dhcp_info(); -extern int init_module(void *, unsigned long, const char *); -extern int delete_module(const char *, unsigned int); -void wifi_close_sockets(); - -#ifndef LIBWPA_CLIENT_EXISTS -#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING " -struct wpa_ctrl {}; -void wpa_ctrl_cleanup(void) {} -struct wpa_ctrl *wpa_ctrl_open(const char *ctrl_path) { return NULL; } -void wpa_ctrl_close(struct wpa_ctrl *ctrl) {} -int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, - char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len)) - { return 0; } -int wpa_ctrl_attach(struct wpa_ctrl *ctrl) { return 0; } -int wpa_ctrl_detach(struct wpa_ctrl *ctrl) { return 0; } -int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) - { return 0; } -int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { return 0; } -#endif - -static struct wpa_ctrl *ctrl_conn; -static struct wpa_ctrl *monitor_conn; - -/* socket pair used to exit from a blocking read */ -static int exit_sockets[2]; - -static char primary_iface[PROPERTY_VALUE_MAX]; -// TODO: use new ANDROID_SOCKET mechanism, once support for multiple -// sockets is in - -#ifndef WIFI_DRIVER_MODULE_ARG -#define WIFI_DRIVER_MODULE_ARG "" -#endif -#ifndef WIFI_FIRMWARE_LOADER -#define WIFI_FIRMWARE_LOADER "" -#endif -#define WIFI_TEST_INTERFACE "sta" +#include "hardware_legacy/wifi.h" -#ifndef WIFI_DRIVER_FW_PATH_STA -#define WIFI_DRIVER_FW_PATH_STA NULL +#ifndef WIFI_FST_DRIVER_MODULE_PATH +#define WIFI_FST_DRIVER_MODULE_PATH "" #endif -#ifndef WIFI_DRIVER_FW_PATH_AP -#define WIFI_DRIVER_FW_PATH_AP NULL +#ifndef WIFI_FST_DRIVER_MODULE_ARG +#define WIFI_FST_DRIVER_MODULE_ARG "" #endif -#ifndef WIFI_DRIVER_FW_PATH_P2P -#define WIFI_DRIVER_FW_PATH_P2P NULL +#ifndef WIFI_FST_DRIVER_MODULE_NAME +#define WIFI_FST_DRIVER_MODULE_NAME "" #endif -#ifndef WIFI_DRIVER_FW_PATH_PARAM -#define WIFI_DRIVER_FW_PATH_PARAM "/sys/module/wlan/parameters/fwpath" -#endif +static const char WIFI_FST_DRIVER_MODULE_TAG[] = WIFI_FST_DRIVER_MODULE_NAME " "; +static const char FST_DRIVER_PROP_NAME[] = "wlan.fst.driver.status"; -#define WIFI_DRIVER_LOADER_DELAY 1000000 +static const char SUPPLICANT_GLOBAL_CTRL_IFACE[] = "@android:wpa_wlan0"; +static const char FSTMAN_NAME[] = "fstman"; +static const char FSTMAN_START_PROP_NAME[] = "netd.fstman.start"; +static const char FSTMAN_PROP_NAME[] = "init.svc.fstman"; +static const char FSTMAN_CONFIG_TEMPLATE[] = "/system/etc/wifi/fstman.ini"; +static const char FSTMAN_CONFIG_FILE[] = "/data/misc/wifi/fstman.ini"; +static const char FST_RATE_UPGRADE_ENABLED_PROP_NAME[] = "persist.fst.rate.upgrade.en"; +static const char FST_SOFTAP_ENABLED_PROP_NAME[] = "persist.fst.softap.en"; -static const char IFACE_DIR[] = "/data/system/wpa_supplicant"; -#ifdef WIFI_DRIVER_MODULE_PATH -static const char DRIVER_MODULE_NAME[] = WIFI_DRIVER_MODULE_NAME; -static const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " "; -static const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH; -static const char DRIVER_MODULE_ARG[] = WIFI_DRIVER_MODULE_ARG; -#endif -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 IFNAME[] = "IFNAME="; -#define IFNAMELEN (sizeof(IFNAME) - 1) -static const char WPA_EVENT_IGNORE[] = "CTRL-EVENT-IGNORE "; - -static const char SUPP_ENTROPY_FILE[] = WIFI_ENTROPY_FILE; -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 insmod(const char *filename, const char *args) -{ - void *module; - unsigned int size; - int ret; +static const char MODULE_FILE[] = "/proc/modules"; - module = load_file(filename, &size); - if (!module) - return -1; - - ret = init_module(module, size, args); - - free(module); - - return ret; -} - -static int rmmod(const char *modname) +int is_fst_enabled() { - int ret = -1; - int maxtry = 10; - - while (maxtry-- > 0) { - ret = delete_module(modname, O_NONBLOCK | O_EXCL); - if (ret < 0 && errno == EAGAIN) - usleep(500000); - else - break; + char prop_value[PROPERTY_VALUE_MAX] = { '\0' }; + + if (property_get(FST_RATE_UPGRADE_ENABLED_PROP_NAME, prop_value, NULL) && + strcmp(prop_value, "1") == 0) { + return 1; } - if (ret != 0) - ALOGD("Unable to unload driver module \"%s\": %s\n", - modname, strerror(errno)); - return ret; + return 0; } -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(primary_iface, WIFI_TEST_INTERFACE) == 0) - return 0; +int is_fst_softap_enabled() { + char prop_value[PROPERTY_VALUE_MAX] = { '\0' }; - if (ifc_init() < 0) - return -1; - - if (do_dhcp(primary_iface) < 0) { - ifc_close(); - return -1; + if (is_fst_enabled() && + property_get(FST_SOFTAP_ENABLED_PROP_NAME, prop_value, NULL) && + strcmp(prop_value, "1") == 0) { + return 1; } - ifc_close(); - get_dhcp_info(ipaddr, gateway, mask, dns1, dns2, server, lease); - return 0; -} -const char *get_dhcp_error_string() { - return dhcp_lasterror(); + return 0; } -#ifdef WIFI_DRIVER_STATE_CTRL_PARAM -int wifi_change_driver_state(const char *state) +int is_fst_driver_loaded() { - int len; - int fd; - int ret = 0; - - if (!state) - return -1; - fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY)); - if (fd < 0) { - ALOGE("Failed to open driver state control param (%s)", strerror(errno)); - return -1; - } - len = strlen(state) + 1; - if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) { - ALOGE("Failed to write driver state control param (%s)", strerror(errno)); - ret = -1; - } - close(fd); - return ret; -} -#endif - -int is_wifi_driver_loaded() { char driver_status[PROPERTY_VALUE_MAX]; -#ifdef WIFI_DRIVER_MODULE_PATH FILE *proc; - char line[sizeof(DRIVER_MODULE_TAG)+10]; -#endif + char line[sizeof(WIFI_FST_DRIVER_MODULE_TAG)+10]; + + if (!is_fst_enabled()) + return 1; - if (!property_get(DRIVER_PROP_NAME, driver_status, NULL) - || strcmp(driver_status, "ok") != 0) { + if (!property_get(FST_DRIVER_PROP_NAME, driver_status, NULL) || + strcmp(driver_status, "ok") != 0) return 0; /* driver not loaded */ - } -#ifdef WIFI_DRIVER_MODULE_PATH + /* - * If the property says the driver is loaded, check to - * make sure that the property setting isn't just left - * over from a previous manual shutdown or a runtime - * crash. - */ + * If the property says the driver is loaded, check to + * make sure that the property setting isn't just left + * over from a previous manual shutdown or a runtime + * crash. + */ if ((proc = fopen(MODULE_FILE, "r")) == NULL) { ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno)); - property_set(DRIVER_PROP_NAME, "unloaded"); + property_set(FST_DRIVER_PROP_NAME, "unloaded"); return 0; } - while ((fgets(line, sizeof(line), proc)) != NULL) { - if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) { + while ((fgets(line, sizeof(line), proc)) != NULL) + if (strncmp(line, WIFI_FST_DRIVER_MODULE_TAG, + strlen(WIFI_FST_DRIVER_MODULE_TAG)) == 0) { fclose(proc); return 1; } - } + fclose(proc); - property_set(DRIVER_PROP_NAME, "unloaded"); + property_set(FST_DRIVER_PROP_NAME, "unloaded"); return 0; -#else - return 1; -#endif } -int wifi_load_driver() +int wifi_fst_load_driver() { -#ifdef WIFI_DRIVER_MODULE_PATH - char driver_status[PROPERTY_VALUE_MAX]; - int count = 100; /* wait at most 20 seconds for completion */ + if (!is_fst_enabled()) + return 0; - if (is_wifi_driver_loaded()) { + if (is_fst_driver_loaded()) return 0; - } - if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) + if (insmod(WIFI_FST_DRIVER_MODULE_PATH, WIFI_FST_DRIVER_MODULE_ARG) < 0) return -1; - if (strcmp(FIRMWARE_LOADER,"") == 0) { - /* usleep(WIFI_DRIVER_LOADER_DELAY); */ - property_set(DRIVER_PROP_NAME, "ok"); - } - else { - property_set("ctl.start", FIRMWARE_LOADER); - } - sched_yield(); - while (count-- > 0) { - if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) { - if (strcmp(driver_status, "ok") == 0) - return 0; - else if (strcmp(driver_status, "failed") == 0) { - wifi_unload_driver(); - return -1; - } - } - usleep(200000); - } - property_set(DRIVER_PROP_NAME, "timeout"); - wifi_unload_driver(); - return -1; -#else -#ifdef WIFI_DRIVER_STATE_CTRL_PARAM - if (is_wifi_driver_loaded()) { - return 0; - } + property_set(FST_DRIVER_PROP_NAME, "ok"); - if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) - return -1; -#endif - property_set(DRIVER_PROP_NAME, "ok"); return 0; -#endif } -int wifi_unload_driver() +int wifi_fst_unload_driver() { - usleep(200000); /* allow to finish interface down */ -#ifdef WIFI_DRIVER_MODULE_PATH - if (rmmod(DRIVER_MODULE_NAME) == 0) { - int count = 20; /* wait at most 10 seconds for completion */ - while (count-- > 0) { - if (!is_wifi_driver_loaded()) - break; - usleep(500000); - } - usleep(500000); /* allow card removal */ - if (count) { - return 0; - } - return -1; - } else - return -1; -#else -#ifdef WIFI_DRIVER_STATE_CTRL_PARAM - if (is_wifi_driver_loaded()) { - if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0) - return -1; - } -#endif - property_set(DRIVER_PROP_NAME, "unloaded"); - return 0; -#endif -} + int count = 20; /* wait at most 10 seconds for completion */ -int ensure_entropy_file_exists() -{ - int ret; - int destfd; - - ret = access(SUPP_ENTROPY_FILE, R_OK|W_OK); - if ((ret == 0) || (errno == EACCES)) { - if ((ret != 0) && - (chmod(SUPP_ENTROPY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) { - ALOGE("Cannot set RW to \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno)); - return -1; - } + if (!is_fst_enabled()) return 0; - } - destfd = TEMP_FAILURE_RETRY(open(SUPP_ENTROPY_FILE, O_CREAT|O_RDWR, 0660)); - if (destfd < 0) { - ALOGE("Cannot create \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno)); - return -1; - } - 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); + if (rmmod(WIFI_FST_DRIVER_MODULE_NAME) != 0) return -1; - } - close(destfd); - - /* chmod is needed because open() didn't set permisions properly */ - if (chmod(SUPP_ENTROPY_FILE, 0660) < 0) { - 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) { - ALOGE("Error changing group ownership of %s to %d: %s", - SUPP_ENTROPY_FILE, AID_WIFI, strerror(errno)); - unlink(SUPP_ENTROPY_FILE); - return -1; + while (count-- > 0) { + if (!is_fst_driver_loaded()) + break; + usleep(500000); } - return 0; -} - -int ensure_config_file_exists(const char *config_file, const char *config_file_template) -{ - char buf[2048]; - int srcfd, destfd; - struct stat sb; - int nread; - int ret; - - ret = access(config_file, R_OK|W_OK); - if ((ret == 0) || (errno == EACCES)) { - if ((ret != 0) && - (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; - } + usleep(500000); /* allow card removal */ + if (count) return 0; - } else if (errno != ENOENT) { - ALOGE("Cannot access \"%s\": %s", config_file, strerror(errno)); - return -1; - } - - srcfd = TEMP_FAILURE_RETRY(open(config_file_template, O_RDONLY)); - if (srcfd < 0) { - ALOGE("Cannot open \"%s\": %s", config_file_template, strerror(errno)); - return -1; - } - destfd = TEMP_FAILURE_RETRY(open(config_file, O_CREAT|O_RDWR, 0660)); - if (destfd < 0) { - close(srcfd); - ALOGE("Cannot create \"%s\": %s", config_file, strerror(errno)); - return -1; - } - - while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) { - if (nread < 0) { - ALOGE("Error reading \"%s\": %s", config_file_template, strerror(errno)); - close(srcfd); - close(destfd); - unlink(config_file); - return -1; - } - TEMP_FAILURE_RETRY(write(destfd, buf, nread)); - } - - close(destfd); - close(srcfd); - - /* chmod is needed because open() didn't set permisions properly */ - 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(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 -1; } -int wifi_start_supplicant(int p2p_supported) +int wifi_start_fstman(int softap_mode) { - char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; - int count = 200; /* wait at most 20 seconds for completion */ - const prop_info *pi; - unsigned serial = 0, i; - - 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, SUPP_CONFIG_TEMPLATE) < 0) { - ALOGE("Failed to create a p2p config file"); - return -1; - } - - } else { - strcpy(supplicant_name, SUPPLICANT_NAME); - strcpy(supplicant_prop_name, SUPP_PROP_NAME); - } + char fstman_status[PROPERTY_VALUE_MAX] = { '\0' }; + char fstman_start_cmd[PROPERTY_VALUE_MAX] = { '\0' }; + int count = 50; /* wait at most 5 seconds for completion */ - /* Check whether already running */ - if (property_get(supplicant_prop_name, supp_status, NULL) - && strcmp(supp_status, "running") == 0) { + if (!is_fst_enabled()) return 0; - } - /* Before starting the daemon, make sure its config file exists */ - if (ensure_config_file_exists(SUPP_CONFIG_FILE, SUPP_CONFIG_TEMPLATE) < 0) { - ALOGE("Wi-Fi will not be enabled"); + if (ensure_config_file_exists(FSTMAN_CONFIG_FILE, FSTMAN_CONFIG_TEMPLATE) < 0) { + ALOGE("Failed to create fstman config file"); return -1; } - if (ensure_entropy_file_exists() < 0) { - ALOGE("Wi-Fi entropy file was not created"); - } - - /* Clear out any stale socket files that might be left over. */ - wpa_ctrl_cleanup(); - - /* Reset sockets used for exiting from hung state */ - exit_sockets[0] = exit_sockets[1] = -1; + /* Check whether already running */ + if (property_get(FSTMAN_PROP_NAME, fstman_status, NULL) && + strcmp(fstman_status, "running") == 0) + return 0; - /* - * Get a reference to the status property, so we can distinguish - * the case where it goes stopped => running => stopped (i.e., - * it start up, but fails right away) from the case in which - * it starts in the stopped state and never manages to start - * running at all. - */ - pi = __system_property_find(supplicant_prop_name); - if (pi != NULL) { - serial = __system_property_serial(pi); + ALOGD("Starting FST Manager"); + /* when invoked from netd, use different property because of different + selinux permissions */ + if (softap_mode) { + property_set(FSTMAN_START_PROP_NAME, "true"); + } else { + snprintf(fstman_start_cmd, sizeof(fstman_start_cmd), "%s:%s", + FSTMAN_NAME, SUPPLICANT_GLOBAL_CTRL_IFACE); + property_set("ctl.start", fstman_start_cmd); } - property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE); - - property_set("ctl.start", supplicant_name); sched_yield(); while (count-- > 0) { - if (pi == NULL) { - pi = __system_property_find(supplicant_prop_name); - } - if (pi != NULL) { - /* - * property serial updated means that init process is scheduled - * after we sched_yield, further property status checking is based on this */ - if (__system_property_serial(pi) != serial) { - __system_property_read(pi, NULL, supp_status); - if (strcmp(supp_status, "running") == 0) { - return 0; - } else if (strcmp(supp_status, "stopped") == 0) { - return -1; - } - } - } + if (property_get(FSTMAN_PROP_NAME, fstman_status, NULL) && + strcmp(fstman_status, "running") == 0) + return 0; usleep(100000); } + + ALOGE("Failed to start FST Manager"); return -1; } -int wifi_stop_supplicant(int p2p_supported) +int wifi_stop_fstman(int softap_mode) { - char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; + char fstman_status[PROPERTY_VALUE_MAX] = { '\0' }; int count = 50; /* wait at most 5 seconds for completion */ - if (p2p_supported) { - strcpy(supplicant_name, P2P_SUPPLICANT_NAME); - strcpy(supplicant_prop_name, P2P_PROP_NAME); - } else { - strcpy(supplicant_name, SUPPLICANT_NAME); - strcpy(supplicant_prop_name, SUPP_PROP_NAME); - } + if (!is_fst_enabled()) + return 0; - /* Check whether supplicant already stopped */ - if (property_get(supplicant_prop_name, supp_status, NULL) - && strcmp(supp_status, "stopped") == 0) { + /* Check whether already stopped */ + if (property_get(FSTMAN_PROP_NAME, fstman_status, NULL) && + strcmp(fstman_status, "stopped") == 0) return 0; - } - property_set("ctl.stop", supplicant_name); + ALOGD("Stopping FST Manager"); + /* when invoked from netd, use different property because of different + selinux permissions */ + if (softap_mode) + property_set(FSTMAN_START_PROP_NAME, "false"); + else + property_set("ctl.stop", FSTMAN_NAME); sched_yield(); while (count-- > 0) { - if (property_get(supplicant_prop_name, supp_status, NULL)) { - if (strcmp(supp_status, "stopped") == 0) + if (property_get(FSTMAN_PROP_NAME, fstman_status, NULL) && + strcmp(fstman_status, "stopped") == 0) return 0; - } usleep(100000); } - ALOGE("Failed to stop supplicant"); - return -1; -} - -int wifi_connect_on_socket_path(const char *path) -{ - char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; - - /* Make sure supplicant is running */ - if (!property_get(supplicant_prop_name, supp_status, NULL) - || strcmp(supp_status, "running") != 0) { - ALOGE("Supplicant not running, cannot connect"); - return -1; - } - - ctrl_conn = wpa_ctrl_open(path); - if (ctrl_conn == NULL) { - ALOGE("Unable to open connection to supplicant on \"%s\": %s", - path, strerror(errno)); - return -1; - } - monitor_conn = wpa_ctrl_open(path); - if (monitor_conn == NULL) { - wpa_ctrl_close(ctrl_conn); - ctrl_conn = 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; - return -1; - } - if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) { - wpa_ctrl_close(monitor_conn); - wpa_ctrl_close(ctrl_conn); - ctrl_conn = monitor_conn = NULL; - return -1; - } - - return 0; -} - -/* Establishes the control and monitor socket connections on the interface */ -int wifi_connect_to_supplicant() -{ - static char path[PATH_MAX]; - - if (access(IFACE_DIR, F_OK) == 0) { - snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface); - } else { - snprintf(path, sizeof(path), "@android:wpa_%s", primary_iface); - } - return wifi_connect_on_socket_path(path); -} - -int wifi_send_command(const char *cmd, char *reply, size_t *reply_len) -{ - int ret; - if (ctrl_conn == NULL) { - ALOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd); - return -1; - } - ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL); - if (ret == -2) { - ALOGD("'%s' command timed out.\n", cmd); - /* unblocks the monitor receive socket for termination */ - TEMP_FAILURE_RETRY(write(exit_sockets[0], "T", 1)); - return -2; - } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) { - return -1; - } - if (strncmp(cmd, "PING", 4) == 0) { - reply[*reply_len] = '\0'; - } - return 0; -} - -int wifi_supplicant_connection_active() -{ - char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; - - if (property_get(supplicant_prop_name, supp_status, NULL)) { - if (strcmp(supp_status, "stopped") == 0) - return -1; - } - - return 0; -} - -int wifi_ctrl_recv(char *reply, size_t *reply_len) -{ - int res; - int ctrlfd = wpa_ctrl_get_fd(monitor_conn); - struct pollfd rfds[2]; - - memset(rfds, 0, 2 * sizeof(struct pollfd)); - rfds[0].fd = ctrlfd; - rfds[0].events |= POLLIN; - rfds[1].fd = exit_sockets[1]; - rfds[1].events |= POLLIN; - do { - res = TEMP_FAILURE_RETRY(poll(rfds, 2, 30000)); - if (res < 0) { - ALOGE("Error poll = %d", res); - return res; - } else if (res == 0) { - /* timed out, check if supplicant is active - * or not .. - */ - res = wifi_supplicant_connection_active(); - if (res < 0) - return -2; - } - } while (res == 0); - - if (rfds[0].revents & POLLIN) { - return wpa_ctrl_recv(monitor_conn, reply, reply_len); - } - - /* it is not rfds[0], then it must be rfts[1] (i.e. the exit socket) - * or we timed out. In either case, this call has failed .. - */ - return -2; -} - -int wifi_wait_on_socket(char *buf, size_t buflen) -{ - size_t nread = buflen - 1; - int result; - char *match, *match2; - - if (monitor_conn == NULL) { - return snprintf(buf, buflen, "IFNAME=%s %s - connection closed", - primary_iface, WPA_EVENT_TERMINATING); - } - - result = wifi_ctrl_recv(buf, &nread); - - /* Terminate reception on exit socket */ - if (result == -2) { - return snprintf(buf, buflen, "IFNAME=%s %s - connection closed", - primary_iface, WPA_EVENT_TERMINATING); - } - - if (result < 0) { - ALOGD("wifi_ctrl_recv failed: %s\n", strerror(errno)); - return snprintf(buf, buflen, "IFNAME=%s %s - recv error", - primary_iface, WPA_EVENT_TERMINATING); - } - buf[nread] = '\0'; - /* Check for EOF on the socket */ - if (result == 0 && nread == 0) { - /* Fabricate an event to pass up */ - ALOGD("Received EOF on supplicant socket\n"); - return snprintf(buf, buflen, "IFNAME=%s %s - signal 0 received", - primary_iface, WPA_EVENT_TERMINATING); - } - /* - * Events strings are in the format - * - * IFNAME=iface CTRL-EVENT-XXX - * or - * CTRL-EVENT-XXX - * - * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG, - * etc.) and XXX is the event name. The level information is not useful - * to us, so strip it off. - */ - - if (strncmp(buf, IFNAME, IFNAMELEN) == 0) { - match = strchr(buf, ' '); - if (match != NULL) { - if (match[1] == '<') { - match2 = strchr(match + 2, '>'); - if (match2 != NULL) { - nread -= (match2 - match); - memmove(match + 1, match2 + 1, nread - (match - buf) + 1); - } - } - } else { - return snprintf(buf, buflen, "%s", WPA_EVENT_IGNORE); - } - } else if (buf[0] == '<') { - match = strchr(buf, '>'); - if (match != NULL) { - nread -= (match + 1 - buf); - memmove(buf, match + 1, nread + 1); - ALOGV("supplicant generated event without interface - %s\n", buf); - } - } else { - /* let the event go as is! */ - ALOGW("supplicant generated event without interface and without message level - %s\n", buf); - } - - return nread; -} - -int wifi_wait_for_event(char *buf, size_t buflen) -{ - return wifi_wait_on_socket(buf, buflen); -} - -void wifi_close_sockets() -{ - 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 (exit_sockets[0] >= 0) { - close(exit_sockets[0]); - exit_sockets[0] = -1; - } - - if (exit_sockets[1] >= 0) { - close(exit_sockets[1]); - exit_sockets[1] = -1; - } -} - -void wifi_close_supplicant_connection() -{ - char supp_status[PROPERTY_VALUE_MAX] = {'\0'}; - int count = 50; /* wait at most 5 seconds to ensure init has stopped stupplicant */ - - wifi_close_sockets(); - - while (count-- > 0) { - if (property_get(supplicant_prop_name, supp_status, NULL)) { - if (strcmp(supp_status, "stopped") == 0) - return; - } - usleep(100000); - } -} - -int wifi_command(const char *command, char *reply, size_t *reply_len) -{ - return wifi_send_command(command, reply, reply_len); -} - -const char *wifi_get_fw_path(int fw_type) -{ - switch (fw_type) { - case WIFI_GET_FW_PATH_STA: - return WIFI_DRIVER_FW_PATH_STA; - case WIFI_GET_FW_PATH_AP: - return WIFI_DRIVER_FW_PATH_AP; - case WIFI_GET_FW_PATH_P2P: - return WIFI_DRIVER_FW_PATH_P2P; - } - return NULL; -} - -int wifi_change_fw_path(const char *fwpath) -{ - int len; - int fd; - int ret = 0; - - if (!fwpath) - return ret; - fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY)); - if (fd < 0) { - ALOGE("Failed to open wlan fw path param (%s)", strerror(errno)); - return -1; - } - len = strlen(fwpath) + 1; - if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) { - ALOGE("Failed to write wlan fw path param (%s)", strerror(errno)); - ret = -1; - } - close(fd); - return ret; + ALOGE("Failed to stop fstman"); + return -1; } -- cgit v1.1