1cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project/*
2cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Copyright 2008, The Android Open Source Project
3cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
4cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * you may not use this file except in compliance with the License.
6cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * You may obtain a copy of the License at
7cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
8cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
9cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project *
10cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * See the License for the specific language governing permissions and
14cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project * limitations under the License.
15cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project */
16cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
17cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <stdlib.h>
18cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <fcntl.h>
19cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <errno.h>
20cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <string.h>
21eea19f1d855b9434313fbb9447a23caf8123aa58Dmitry Shmidt#include <dirent.h>
2245bf8a6f0bbf148ca5a1a626ab1c5c38a0855e13Dmitry Shmidt#include <sys/socket.h>
232263e479a544e7f4d547abcb747fe5896afb9de8Mark Salyzyn#include <sys/stat.h>
24cf449e140874e4f57f120a88411c7b642172ecf2Kenny Root#include <unistd.h>
2545bf8a6f0bbf148ca5a1a626ab1c5c38a0855e13Dmitry Shmidt#include <poll.h>
26cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
27cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "hardware_legacy/wifi.h"
2841d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt#ifdef LIBWPA_CLIENT_EXISTS
29cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "libwpa_client/wpa_ctrl.h"
3041d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt#endif
31cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
32cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#define LOG_TAG "WifiHW"
33cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "cutils/log.h"
34cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "cutils/memory.h"
35cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "cutils/misc.h"
36cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "cutils/properties.h"
37cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include "private/android_filesystem_config.h"
387a070c610002a81583c9a42f3b629507b61fa6d8Elliott Hughes
39cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
40cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project#include <sys/_system_properties.h>
41cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
42445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queruextern int do_dhcp();
43445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queruextern int ifc_init();
44445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queruextern void ifc_close();
45445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queruextern char *dhcp_lasterror();
46445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queruextern void get_dhcp_info();
47cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern int init_module(void *, unsigned long, const char *);
48cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectextern int delete_module(const char *, unsigned int);
490f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndevoid wifi_close_sockets();
50cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
5141d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt#ifndef LIBWPA_CLIENT_EXISTS
5241d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
5341d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtstruct wpa_ctrl {};
5441d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtvoid wpa_ctrl_cleanup(void) {}
5541d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtstruct wpa_ctrl *wpa_ctrl_open(const char *ctrl_path) { return NULL; }
5641d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtvoid wpa_ctrl_close(struct wpa_ctrl *ctrl) {}
5741d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtint wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
5841d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt	char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len))
5941d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt	{ return 0; }
6041d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtint wpa_ctrl_attach(struct wpa_ctrl *ctrl) { return 0; }
6141d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtint wpa_ctrl_detach(struct wpa_ctrl *ctrl) { return 0; }
6241d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtint wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
6341d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt	{ return 0; }
6441d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtint wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { return 0; }
6541d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt#endif
6641d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt
6741d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtstatic struct wpa_ctrl *ctrl_conn;
6841d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtstatic struct wpa_ctrl *monitor_conn;
6941d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt
7041d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt/* socket pair used to exit from a blocking read */
7141d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidtstatic int exit_sockets[2];
7241d81d174858ca39ead245e12a8e2547e0314201Dmitry Shmidt
73da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriffstatic char primary_iface[PROPERTY_VALUE_MAX];
74cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project// TODO: use new ANDROID_SOCKET mechanism, once support for multiple
75cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project// sockets is in
76cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
77243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#ifndef WIFI_DRIVER_MODULE_ARG
78243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#define WIFI_DRIVER_MODULE_ARG          ""
79243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#endif
80243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#ifndef WIFI_FIRMWARE_LOADER
81243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#define WIFI_FIRMWARE_LOADER		""
82243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#endif
83243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt#define WIFI_TEST_INTERFACE		"sta"
84243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt
854b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt#ifndef WIFI_DRIVER_FW_PATH_STA
864b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt#define WIFI_DRIVER_FW_PATH_STA		NULL
874b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt#endif
884b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt#ifndef WIFI_DRIVER_FW_PATH_AP
894b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt#define WIFI_DRIVER_FW_PATH_AP		NULL
904b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt#endif
914b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt#ifndef WIFI_DRIVER_FW_PATH_P2P
924b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt#define WIFI_DRIVER_FW_PATH_P2P		NULL
934b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt#endif
944b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt
9529a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt#ifndef WIFI_DRIVER_FW_PATH_PARAM
9629a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt#define WIFI_DRIVER_FW_PATH_PARAM	"/sys/module/wlan/parameters/fwpath"
9729a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt#endif
9829a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt
99ed8487244b1c9f72fb5d22c7a18918ac34063ceeDmitry Shmidt#define WIFI_DRIVER_LOADER_DELAY	1000000
100ed8487244b1c9f72fb5d22c7a18918ac34063ceeDmitry Shmidt
101cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char IFACE_DIR[]           = "/data/system/wpa_supplicant";
102d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#ifdef WIFI_DRIVER_MODULE_PATH
103243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char DRIVER_MODULE_NAME[]  = WIFI_DRIVER_MODULE_NAME;
104243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char DRIVER_MODULE_TAG[]   = WIFI_DRIVER_MODULE_NAME " ";
105243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char DRIVER_MODULE_PATH[]  = WIFI_DRIVER_MODULE_PATH;
106243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char DRIVER_MODULE_ARG[]   = WIFI_DRIVER_MODULE_ARG;
107d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#endif
108243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic const char FIRMWARE_LOADER[]     = WIFI_FIRMWARE_LOADER;
109cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char DRIVER_PROP_NAME[]    = "wlan.driver.status";
110cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char SUPPLICANT_NAME[]     = "wpa_supplicant";
111cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char SUPP_PROP_NAME[]      = "init.svc.wpa_supplicant";
112096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriffstatic const char P2P_SUPPLICANT_NAME[] = "p2p_supplicant";
113096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriffstatic const char P2P_PROP_NAME[]       = "init.svc.p2p_supplicant";
114cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char SUPP_CONFIG_TEMPLATE[]= "/system/etc/wifi/wpa_supplicant.conf";
115cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char SUPP_CONFIG_FILE[]    = "/data/misc/wifi/wpa_supplicant.conf";
11667ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriffstatic const char P2P_CONFIG_FILE[]     = "/data/misc/wifi/p2p_supplicant.conf";
117096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriffstatic const char CONTROL_IFACE_PATH[]  = "/data/misc/wifi/sockets";
118cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic const char MODULE_FILE[]         = "/proc/modules";
119cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
120ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidtstatic const char IFNAME[]              = "IFNAME=";
121ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt#define IFNAMELEN			(sizeof(IFNAME) - 1)
122ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidtstatic const char WPA_EVENT_IGNORE[]    = "CTRL-EVENT-IGNORE ";
123ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt
1243ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidtstatic const char SUPP_ENTROPY_FILE[]   = WIFI_ENTROPY_FILE;
12507a629e27cc35868e2b7601983c7044cf8df0709Dmitry Shmidtstatic unsigned char dummy_key[21] = { 0x02, 0x11, 0xbe, 0x33, 0x43, 0x35,
12607a629e27cc35868e2b7601983c7044cf8df0709Dmitry Shmidt                                       0x68, 0x47, 0x84, 0x99, 0xa9, 0x2b,
12707a629e27cc35868e2b7601983c7044cf8df0709Dmitry Shmidt                                       0x1c, 0xd3, 0xee, 0xff, 0xf1, 0xe2,
12807a629e27cc35868e2b7601983c7044cf8df0709Dmitry Shmidt                                       0xf3, 0xf4, 0xf5 };
1293ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt
130096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff/* Is either SUPPLICANT_NAME or P2P_SUPPLICANT_NAME */
131096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriffstatic char supplicant_name[PROPERTY_VALUE_MAX];
132096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff/* Is either SUPP_PROP_NAME or P2P_PROP_NAME */
133096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriffstatic char supplicant_prop_name[PROPERTY_KEY_MAX];
134096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff
135243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidtstatic int insmod(const char *filename, const char *args)
136cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
137cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    void *module;
138cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    unsigned int size;
139cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int ret;
140cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
141cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    module = load_file(filename, &size);
142cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (!module)
143cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
144cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
145243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    ret = init_module(module, size, args);
146cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
147cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    free(module);
148cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
149cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return ret;
150cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
151cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
152cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectstatic int rmmod(const char *modname)
153cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
154cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int ret = -1;
155cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int maxtry = 10;
156cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
157cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while (maxtry-- > 0) {
158cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        ret = delete_module(modname, O_NONBLOCK | O_EXCL);
159cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (ret < 0 && errno == EAGAIN)
160cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            usleep(500000);
161cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        else
162cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            break;
163cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
164cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
165cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ret != 0)
166b381b932acfa441da5607f37ac4ef6573ed5be96Steve Block        ALOGD("Unable to unload driver module \"%s\": %s\n",
167cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project             modname, strerror(errno));
168cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return ret;
169cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
170cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
171445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queruint do_dhcp_request(int *ipaddr, int *gateway, int *mask,
172445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru                    int *dns1, int *dns2, int *server, int *lease) {
173445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru    /* For test driver, always report success */
174da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    if (strcmp(primary_iface, WIFI_TEST_INTERFACE) == 0)
175445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru        return 0;
176445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru
177445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru    if (ifc_init() < 0)
178445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru        return -1;
179445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru
180da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    if (do_dhcp(primary_iface) < 0) {
181445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru        ifc_close();
182445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru        return -1;
183445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru    }
184445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru    ifc_close();
185445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru    get_dhcp_info(ipaddr, gateway, mask, dns1, dns2, server, lease);
186445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru    return 0;
187445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru}
188445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru
189445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queruconst char *get_dhcp_error_string() {
190445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru    return dhcp_lasterror();
191445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru}
192445591dded5753cf72dcf329a56af732776de97dJean-Baptiste Queru
193da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
194da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Changint wifi_change_driver_state(const char *state)
195da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang{
196da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    int len;
197da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    int fd;
198da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    int ret = 0;
199da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang
200da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    if (!state)
201da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang        return -1;
202da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
203da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    if (fd < 0) {
204da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang        ALOGE("Failed to open driver state control param (%s)", strerror(errno));
205da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang        return -1;
206da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    }
207da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    len = strlen(state) + 1;
208da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
209da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang        ALOGE("Failed to write driver state control param (%s)", strerror(errno));
210da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang        ret = -1;
211da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    }
212da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    close(fd);
213da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    return ret;
214da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang}
215da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang#endif
216da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang
2172bb990bfd2580f9be93a413e3a5325057977a828Irfan Sheriffint is_wifi_driver_loaded() {
218cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char driver_status[PROPERTY_VALUE_MAX];
219d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#ifdef WIFI_DRIVER_MODULE_PATH
220cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    FILE *proc;
221cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char line[sizeof(DRIVER_MODULE_TAG)+10];
222d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#endif
223cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
224cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (!property_get(DRIVER_PROP_NAME, driver_status, NULL)
225cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            || strcmp(driver_status, "ok") != 0) {
226cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;  /* driver not loaded */
227cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
228d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#ifdef WIFI_DRIVER_MODULE_PATH
229cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /*
230cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * If the property says the driver is loaded, check to
231cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * make sure that the property setting isn't just left
232cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * over from a previous manual shutdown or a runtime
233cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * crash.
234cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     */
235cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
23664cca04dcbf4e21a51131224b9d0f0c596f876d4Steve Block        ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno));
237243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt        property_set(DRIVER_PROP_NAME, "unloaded");
238cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
239cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
240cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while ((fgets(line, sizeof(line), proc)) != NULL) {
241cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
242cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            fclose(proc);
243cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            return 1;
244cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
245cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
246cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    fclose(proc);
247cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    property_set(DRIVER_PROP_NAME, "unloaded");
248cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
249d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#else
250d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt    return 1;
251d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#endif
252cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
253cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
254cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_load_driver()
255cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
256d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#ifdef WIFI_DRIVER_MODULE_PATH
257cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char driver_status[PROPERTY_VALUE_MAX];
258cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int count = 100; /* wait at most 20 seconds for completion */
259cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
2602bb990bfd2580f9be93a413e3a5325057977a828Irfan Sheriff    if (is_wifi_driver_loaded()) {
261cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
262cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
263cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
264243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
265cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
266243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt
267243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    if (strcmp(FIRMWARE_LOADER,"") == 0) {
2688fb5f74df7b25051e007a67eea22b984ef7dc76aDmitry Shmidt        /* usleep(WIFI_DRIVER_LOADER_DELAY); */
269243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt        property_set(DRIVER_PROP_NAME, "ok");
270243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    }
271243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    else {
272243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt        property_set("ctl.start", FIRMWARE_LOADER);
273243af8b84968ec4f5afb628c43a2c541c4feee7bDmitry Shmidt    }
274cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    sched_yield();
275cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while (count-- > 0) {
276cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
277cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            if (strcmp(driver_status, "ok") == 0)
278cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return 0;
27985bff332cc3b8ba33e66246052647ca1a546dc42Ajay Dudani            else if (strcmp(driver_status, "failed") == 0) {
2807b43699180e593b19092eb2a091c4bca105aca77Dmitry Shmidt                wifi_unload_driver();
281cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return -1;
2827b43699180e593b19092eb2a091c4bca105aca77Dmitry Shmidt            }
283cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
284cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        usleep(200000);
285cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
286cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    property_set(DRIVER_PROP_NAME, "timeout");
2877b43699180e593b19092eb2a091c4bca105aca77Dmitry Shmidt    wifi_unload_driver();
288cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return -1;
289d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#else
290da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
291da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    if (is_wifi_driver_loaded()) {
292da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang        return 0;
293da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    }
294da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang
295da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0)
296da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang        return -1;
297da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang#endif
298d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt    property_set(DRIVER_PROP_NAME, "ok");
299d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt    return 0;
300d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#endif
301cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
302cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
303cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Projectint wifi_unload_driver()
304cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
3054c1a1fedd632791580c4b483c31abc4e583eae16Dmitry Shmidt    usleep(200000); /* allow to finish interface down */
306953c1140659ae935e4718d4fd48662db178814f6Dmitry Shmidt#ifdef WIFI_DRIVER_MODULE_PATH
307cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (rmmod(DRIVER_MODULE_NAME) == 0) {
308953c1140659ae935e4718d4fd48662db178814f6Dmitry Shmidt        int count = 20; /* wait at most 10 seconds for completion */
3090e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt        while (count-- > 0) {
3100e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt            if (!is_wifi_driver_loaded())
3110e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt                break;
3120e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt            usleep(500000);
3130e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt        }
314953c1140659ae935e4718d4fd48662db178814f6Dmitry Shmidt        usleep(500000); /* allow card removal */
3150e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt        if (count) {
3160e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt            return 0;
3170e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt        }
3180e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt        return -1;
319cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    } else
320cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
321d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#else
322da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
323da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    if (is_wifi_driver_loaded()) {
324da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang        if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0)
325da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang            return -1;
326da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang    }
327da1c7fa2901ad0d6158412d35d3c2b67f4c54518Maddest Chang#endif
328d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt    property_set(DRIVER_PROP_NAME, "unloaded");
329d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt    return 0;
330d301cb7a5e76f82d265f8a7d408bec3159614f0bDmitry Shmidt#endif
331cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
332cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
3333ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidtint ensure_entropy_file_exists()
3343ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt{
3353ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    int ret;
3363ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    int destfd;
3373ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt
3383ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    ret = access(SUPP_ENTROPY_FILE, R_OK|W_OK);
3393ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    if ((ret == 0) || (errno == EACCES)) {
3403ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        if ((ret != 0) &&
3413ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt            (chmod(SUPP_ENTROPY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
3425efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block            ALOGE("Cannot set RW to \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
3433ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt            return -1;
3443ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        }
3453ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        return 0;
3463ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    }
347cf449e140874e4f57f120a88411c7b642172ecf2Kenny Root    destfd = TEMP_FAILURE_RETRY(open(SUPP_ENTROPY_FILE, O_CREAT|O_RDWR, 0660));
3483ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    if (destfd < 0) {
3495efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Cannot create \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
3503ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        return -1;
3513ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    }
3523ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt
353cf449e140874e4f57f120a88411c7b642172ecf2Kenny Root    if (TEMP_FAILURE_RETRY(write(destfd, dummy_key, sizeof(dummy_key))) != sizeof(dummy_key)) {
3545efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Error writing \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
3553ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        close(destfd);
3563ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        return -1;
3573ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    }
3583ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    close(destfd);
3593ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt
3603ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    /* chmod is needed because open() didn't set permisions properly */
3613ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    if (chmod(SUPP_ENTROPY_FILE, 0660) < 0) {
3625efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Error changing permissions of %s to 0660: %s",
3633ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt             SUPP_ENTROPY_FILE, strerror(errno));
3643ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        unlink(SUPP_ENTROPY_FILE);
3653ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        return -1;
3663ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    }
3673ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt
3683ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    if (chown(SUPP_ENTROPY_FILE, AID_SYSTEM, AID_WIFI) < 0) {
3695efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Error changing group ownership of %s to %d: %s",
3703ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt             SUPP_ENTROPY_FILE, AID_WIFI, strerror(errno));
3713ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        unlink(SUPP_ENTROPY_FILE);
3723ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt        return -1;
3733ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    }
3743ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    return 0;
3753ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt}
3763ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt
37767ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriffint ensure_config_file_exists(const char *config_file)
37867ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff{
37967ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff    char buf[2048];
380cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int srcfd, destfd;
3818a5b197b3d5878e3f1cf49c9c38c090456107e87Irfan Sheriff    struct stat sb;
382cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int nread;
38389ae703cd6d4b2bc86c4bd281a8e460fd5679891Dmitry Shmidt    int ret;
384cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
38567ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff    ret = access(config_file, R_OK|W_OK);
38689ae703cd6d4b2bc86c4bd281a8e460fd5679891Dmitry Shmidt    if ((ret == 0) || (errno == EACCES)) {
38789ae703cd6d4b2bc86c4bd281a8e460fd5679891Dmitry Shmidt        if ((ret != 0) &&
38867ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff            (chmod(config_file, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
3895efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block            ALOGE("Cannot set RW to \"%s\": %s", config_file, strerror(errno));
39089ae703cd6d4b2bc86c4bd281a8e460fd5679891Dmitry Shmidt            return -1;
39189ae703cd6d4b2bc86c4bd281a8e460fd5679891Dmitry Shmidt        }
392c6bb3b5e1e06aa7798342f4ca8d4cc6364f5ec9aDmitry Shmidt        return 0;
393cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    } else if (errno != ENOENT) {
3945efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Cannot access \"%s\": %s", config_file, strerror(errno));
395cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
396cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
397cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
398cf449e140874e4f57f120a88411c7b642172ecf2Kenny Root    srcfd = TEMP_FAILURE_RETRY(open(SUPP_CONFIG_TEMPLATE, O_RDONLY));
399cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (srcfd < 0) {
4005efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Cannot open \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
401cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
402cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
403cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
404cf449e140874e4f57f120a88411c7b642172ecf2Kenny Root    destfd = TEMP_FAILURE_RETRY(open(config_file, O_CREAT|O_RDWR, 0660));
405cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (destfd < 0) {
406cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        close(srcfd);
4075efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Cannot create \"%s\": %s", config_file, strerror(errno));
408cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
409cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
410cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
411cf449e140874e4f57f120a88411c7b642172ecf2Kenny Root    while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) {
412cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (nread < 0) {
4135efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block            ALOGE("Error reading \"%s\": %s", SUPP_CONFIG_TEMPLATE, strerror(errno));
414cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            close(srcfd);
415cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            close(destfd);
41667ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff            unlink(config_file);
417cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            return -1;
418cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
419cf449e140874e4f57f120a88411c7b642172ecf2Kenny Root        TEMP_FAILURE_RETRY(write(destfd, buf, nread));
420cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
421cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
422cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    close(destfd);
423cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    close(srcfd);
424cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
42524bf7fc4e02b552650f299d16303eca0825dd8c8Dmitry Shmidt    /* chmod is needed because open() didn't set permisions properly */
42667ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff    if (chmod(config_file, 0660) < 0) {
4275efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Error changing permissions of %s to 0660: %s",
42867ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff             config_file, strerror(errno));
42967ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff        unlink(config_file);
43024bf7fc4e02b552650f299d16303eca0825dd8c8Dmitry Shmidt        return -1;
43124bf7fc4e02b552650f299d16303eca0825dd8c8Dmitry Shmidt    }
43224bf7fc4e02b552650f299d16303eca0825dd8c8Dmitry Shmidt
43367ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff    if (chown(config_file, AID_SYSTEM, AID_WIFI) < 0) {
4345efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Error changing group ownership of %s to %d: %s",
43567ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff             config_file, AID_WIFI, strerror(errno));
43667ba2276b9a5232685e14d416fea0b1250515594Irfan Sheriff        unlink(config_file);
437cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
438cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
439c6bb3b5e1e06aa7798342f4ca8d4cc6364f5ec9aDmitry Shmidt    return 0;
440cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
441cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
442096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriffint wifi_start_supplicant(int p2p_supported)
443cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
444cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
445cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int count = 200; /* wait at most 20 seconds for completion */
446cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    const prop_info *pi;
447da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    unsigned serial = 0, i;
448cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
449096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    if (p2p_supported) {
450096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff        strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
451096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff        strcpy(supplicant_prop_name, P2P_PROP_NAME);
452096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff
453096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff        /* Ensure p2p config file is created */
454096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff        if (ensure_config_file_exists(P2P_CONFIG_FILE) < 0) {
455096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff            ALOGE("Failed to create a p2p config file");
456096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff            return -1;
457096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff        }
458096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff
459096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    } else {
460096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff        strcpy(supplicant_name, SUPPLICANT_NAME);
461096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff        strcpy(supplicant_prop_name, SUPP_PROP_NAME);
462096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    }
463096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff
464cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Check whether already running */
465eed817e46ee7351f21673118eda9a5960a483120Jonathan DE CESCO    if (property_get(supplicant_prop_name, supp_status, NULL)
466cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            && strcmp(supp_status, "running") == 0) {
467cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
468cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
469cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
470cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Before starting the daemon, make sure its config file exists */
471096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    if (ensure_config_file_exists(SUPP_CONFIG_FILE) < 0) {
4725efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Wi-Fi will not be enabled");
473cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
474cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
475cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
4763ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    if (ensure_entropy_file_exists() < 0) {
4775efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Wi-Fi entropy file was not created");
4783ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt    }
4793ab3e6696757541c098a251981c074fc980f4dc7Dmitry Shmidt
480cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Clear out any stale socket files that might be left over. */
481de9abffc3815449cbd8d756937030cb0353fb9f2Dmitry Shmidt    wpa_ctrl_cleanup();
482cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
483da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    /* Reset sockets used for exiting from hung state */
4840f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    exit_sockets[0] = exit_sockets[1] = -1;
485da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff
486cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /*
487cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * Get a reference to the status property, so we can distinguish
488cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * the case where it goes stopped => running => stopped (i.e.,
489cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * it start up, but fails right away) from the case in which
490cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * it starts in the stopped state and never manages to start
491cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * running at all.
492cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     */
493096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    pi = __system_property_find(supplicant_prop_name);
494cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (pi != NULL) {
49514c02f245e56687b765487d25a034d71196d33b6Colin Cross        serial = __system_property_serial(pi);
496cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
497da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE);
498096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff
499096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    property_set("ctl.start", supplicant_name);
500cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    sched_yield();
501cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
502cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while (count-- > 0) {
503cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (pi == NULL) {
504096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff            pi = __system_property_find(supplicant_prop_name);
505cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
506cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (pi != NULL) {
5074431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo            /*
5084431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo             * property serial updated means that init process is scheduled
5094431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo             * after we sched_yield, further property status checking is based on this */
5104431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo            if (__system_property_serial(pi) != serial) {
5114431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo                __system_property_read(pi, NULL, supp_status);
5124431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo                if (strcmp(supp_status, "running") == 0) {
5134431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo                    return 0;
5144431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo                } else if (strcmp(supp_status, "stopped") == 0) {
5154431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo                    return -1;
5164431a1c34d1a9c36b7251217a2783d09ee1a7ac3jiaguo                }
517cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            }
518cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
519cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        usleep(100000);
520cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
521cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return -1;
522cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
523cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
524745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriffint wifi_stop_supplicant(int p2p_supported)
525cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
526cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
527cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int count = 50; /* wait at most 5 seconds for completion */
528cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
529745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriff    if (p2p_supported) {
530745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriff        strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
531745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriff        strcpy(supplicant_prop_name, P2P_PROP_NAME);
532745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriff    } else {
533745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriff        strcpy(supplicant_name, SUPPLICANT_NAME);
534745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriff        strcpy(supplicant_prop_name, SUPP_PROP_NAME);
535745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriff    }
536745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriff
537cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Check whether supplicant already stopped */
538096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    if (property_get(supplicant_prop_name, supp_status, NULL)
539cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        && strcmp(supp_status, "stopped") == 0) {
540cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return 0;
541cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
542cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
543096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    property_set("ctl.stop", supplicant_name);
544cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    sched_yield();
545cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
546cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    while (count-- > 0) {
547096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff        if (property_get(supplicant_prop_name, supp_status, NULL)) {
548cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            if (strcmp(supp_status, "stopped") == 0)
549cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project                return 0;
550cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
551cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        usleep(100000);
552cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
553745e7fd4e09db2b47371338ee54c54255e286473Irfan Sheriff    ALOGE("Failed to stop supplicant");
554cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return -1;
555cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
556cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
5570f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndeint wifi_connect_on_socket_path(const char *path)
558cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
559cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
560cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
561cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Make sure supplicant is running */
562096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    if (!property_get(supplicant_prop_name, supp_status, NULL)
563cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project            || strcmp(supp_status, "running") != 0) {
5645efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Supplicant not running, cannot connect");
565cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
566cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
567cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
5680f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    ctrl_conn = wpa_ctrl_open(path);
5690f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (ctrl_conn == NULL) {
5705efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Unable to open connection to supplicant on \"%s\": %s",
571da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff             path, strerror(errno));
572cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
573cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
5740f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    monitor_conn = wpa_ctrl_open(path);
5750f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (monitor_conn == NULL) {
5760f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        wpa_ctrl_close(ctrl_conn);
5770f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        ctrl_conn = NULL;
578cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
579cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
5800f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (wpa_ctrl_attach(monitor_conn) != 0) {
5810f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        wpa_ctrl_close(monitor_conn);
5820f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        wpa_ctrl_close(ctrl_conn);
5830f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        ctrl_conn = monitor_conn = NULL;
584cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
585cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
586025321a09dbe7820870125acf771e1da02684605Irfan Sheriff
5870f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) {
5880f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        wpa_ctrl_close(monitor_conn);
5890f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        wpa_ctrl_close(ctrl_conn);
5900f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        ctrl_conn = monitor_conn = NULL;
591025321a09dbe7820870125acf771e1da02684605Irfan Sheriff        return -1;
592025321a09dbe7820870125acf771e1da02684605Irfan Sheriff    }
593025321a09dbe7820870125acf771e1da02684605Irfan Sheriff
594cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
595cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
596cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
597da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff/* Establishes the control and monitor socket connections on the interface */
5980f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndeint wifi_connect_to_supplicant()
599da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff{
600ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt    static char path[PATH_MAX];
601da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff
6020f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (access(IFACE_DIR, F_OK) == 0) {
6030f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);
604da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    } else {
6050f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        snprintf(path, sizeof(path), "@android:wpa_%s", primary_iface);
606da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    }
6070f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    return wifi_connect_on_socket_path(path);
608da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff}
609da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff
6100f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndeint wifi_send_command(const char *cmd, char *reply, size_t *reply_len)
611cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
612cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int ret;
6130f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (ctrl_conn == NULL) {
6146a70518b93928d1c91457ff805e375c82d76b0e5Steve Block        ALOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
615cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
616cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
6170f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL);
618cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (ret == -2) {
619b381b932acfa441da5607f37ac4ef6573ed5be96Steve Block        ALOGD("'%s' command timed out.\n", cmd);
620025321a09dbe7820870125acf771e1da02684605Irfan Sheriff        /* unblocks the monitor receive socket for termination */
6210f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        TEMP_FAILURE_RETRY(write(exit_sockets[0], "T", 1));
622cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -2;
623cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
624cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        return -1;
625cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
626cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (strncmp(cmd, "PING", 4) == 0) {
627cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        reply[*reply_len] = '\0';
628cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
629cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return 0;
630cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
631cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
632ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Maheshint wifi_supplicant_connection_active()
633ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh{
634ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
635ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh
636ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh    if (property_get(supplicant_prop_name, supp_status, NULL)) {
637ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh        if (strcmp(supp_status, "stopped") == 0)
638ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh            return -1;
639ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh    }
640ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh
641ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh    return 0;
642ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh}
643ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh
6440f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndeint wifi_ctrl_recv(char *reply, size_t *reply_len)
645025321a09dbe7820870125acf771e1da02684605Irfan Sheriff{
646025321a09dbe7820870125acf771e1da02684605Irfan Sheriff    int res;
6470f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    int ctrlfd = wpa_ctrl_get_fd(monitor_conn);
64845bf8a6f0bbf148ca5a1a626ab1c5c38a0855e13Dmitry Shmidt    struct pollfd rfds[2];
64945bf8a6f0bbf148ca5a1a626ab1c5c38a0855e13Dmitry Shmidt
65045bf8a6f0bbf148ca5a1a626ab1c5c38a0855e13Dmitry Shmidt    memset(rfds, 0, 2 * sizeof(struct pollfd));
65145bf8a6f0bbf148ca5a1a626ab1c5c38a0855e13Dmitry Shmidt    rfds[0].fd = ctrlfd;
65245bf8a6f0bbf148ca5a1a626ab1c5c38a0855e13Dmitry Shmidt    rfds[0].events |= POLLIN;
6530f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    rfds[1].fd = exit_sockets[1];
65445bf8a6f0bbf148ca5a1a626ab1c5c38a0855e13Dmitry Shmidt    rfds[1].events |= POLLIN;
655ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh    do {
656ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh        res = TEMP_FAILURE_RETRY(poll(rfds, 2, 30000));
657ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh        if (res < 0) {
658ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh            ALOGE("Error poll = %d", res);
659ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh            return res;
660ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh        } else if (res == 0) {
661ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh            /* timed out, check if supplicant is active
662ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh             * or not ..
663ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh             */
664ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh            res = wifi_supplicant_connection_active();
665ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh            if (res < 0)
666ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh                return -2;
667ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh        }
668ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh    } while (res == 0);
669ff6902dc4f034d67d6c3cbdddbe04f61913d5b79Mahesh
67045bf8a6f0bbf148ca5a1a626ab1c5c38a0855e13Dmitry Shmidt    if (rfds[0].revents & POLLIN) {
6710f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        return wpa_ctrl_recv(monitor_conn, reply, reply_len);
672025321a09dbe7820870125acf771e1da02684605Irfan Sheriff    }
6730f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde
6740f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    /* it is not rfds[0], then it must be rfts[1] (i.e. the exit socket)
6750f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde     * or we timed out. In either case, this call has failed ..
6760f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde     */
677897f6dd64224d22c22c8f7a497331bf5bc335e4cIrfan Sheriff    return -2;
678025321a09dbe7820870125acf771e1da02684605Irfan Sheriff}
679025321a09dbe7820870125acf771e1da02684605Irfan Sheriff
6800f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndeint wifi_wait_on_socket(char *buf, size_t buflen)
681cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
682cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    size_t nread = buflen - 1;
683cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    int result;
6840f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    char *match, *match2;
6850e9f488e672abf0d14580261998cfd9c7211c112Dmitry Shmidt
6860f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (monitor_conn == NULL) {
6870ef9a33a471c239824bb3958a99a9dea8a89ee69Mahesh        return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
6880ef9a33a471c239824bb3958a99a9dea8a89ee69Mahesh                        primary_iface, WPA_EVENT_TERMINATING);
6892631f993753d726c8c6a85ab66a83db79e54f0bbIrfan Sheriff    }
690cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
6910f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    result = wifi_ctrl_recv(buf, &nread);
692096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff
693096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    /* Terminate reception on exit socket */
694096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    if (result == -2) {
6950ef9a33a471c239824bb3958a99a9dea8a89ee69Mahesh        return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
6960ef9a33a471c239824bb3958a99a9dea8a89ee69Mahesh                        primary_iface, WPA_EVENT_TERMINATING);
697096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff    }
698096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff
699cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (result < 0) {
700b381b932acfa441da5607f37ac4ef6573ed5be96Steve Block        ALOGD("wifi_ctrl_recv failed: %s\n", strerror(errno));
7010ef9a33a471c239824bb3958a99a9dea8a89ee69Mahesh        return snprintf(buf, buflen, "IFNAME=%s %s - recv error",
7020ef9a33a471c239824bb3958a99a9dea8a89ee69Mahesh                        primary_iface, WPA_EVENT_TERMINATING);
703cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
704cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    buf[nread] = '\0';
705cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /* Check for EOF on the socket */
706cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    if (result == 0 && nread == 0) {
707cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        /* Fabricate an event to pass up */
708b381b932acfa441da5607f37ac4ef6573ed5be96Steve Block        ALOGD("Received EOF on supplicant socket\n");
7090ef9a33a471c239824bb3958a99a9dea8a89ee69Mahesh        return snprintf(buf, buflen, "IFNAME=%s %s - signal 0 received",
7100ef9a33a471c239824bb3958a99a9dea8a89ee69Mahesh                        primary_iface, WPA_EVENT_TERMINATING);
711cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
712cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    /*
713cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * Events strings are in the format
714cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     *
715ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt     *     IFNAME=iface <N>CTRL-EVENT-XXX
716ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt     *        or
717cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     *     <N>CTRL-EVENT-XXX
718cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     *
719cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
720cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * etc.) and XXX is the event name. The level information is not useful
721cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     * to us, so strip it off.
722cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project     */
7230f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde
724ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt    if (strncmp(buf, IFNAME, IFNAMELEN) == 0) {
725ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt        match = strchr(buf, ' ');
726ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt        if (match != NULL) {
7270f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde            if (match[1] == '<') {
7280f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde                match2 = strchr(match + 2, '>');
7290f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde                if (match2 != NULL) {
7300f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde                    nread -= (match2 - match);
7310f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde                    memmove(match + 1, match2 + 1, nread - (match - buf) + 1);
7320f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde                }
733ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt            }
734ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt        } else {
735ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt            return snprintf(buf, buflen, "%s", WPA_EVENT_IGNORE);
736ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt        }
7370f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    } else if (buf[0] == '<') {
738ec0576034bb5c1b0aed1b23120b71f9599d2bb73Dmitry Shmidt        match = strchr(buf, '>');
739cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        if (match != NULL) {
7400f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde            nread -= (match + 1 - buf);
7410f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde            memmove(buf, match + 1, nread + 1);
7420f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde            ALOGV("supplicant generated event without interface - %s\n", buf);
743cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project        }
7440f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    } else {
7450f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        /* let the event go as is! */
7460f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        ALOGW("supplicant generated event without interface and without message level - %s\n", buf);
747cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
748096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff
749cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    return nread;
750cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
751cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
7520f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndeint wifi_wait_for_event(char *buf, size_t buflen)
753cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
7540f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    return wifi_wait_on_socket(buf, buflen);
755da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff}
7565a8a2d2b130644f0f4abad8586f0a245e4c15be8Irfan Sheriff
7570f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndevoid wifi_close_sockets()
758da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff{
7590f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (ctrl_conn != NULL) {
7600f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        wpa_ctrl_close(ctrl_conn);
7610f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        ctrl_conn = NULL;
762cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
763da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff
7640f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (monitor_conn != NULL) {
7650f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        wpa_ctrl_close(monitor_conn);
7660f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        monitor_conn = NULL;
767da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    }
768da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff
7690f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (exit_sockets[0] >= 0) {
7700f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        close(exit_sockets[0]);
7710f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        exit_sockets[0] = -1;
772cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project    }
7735a8a2d2b130644f0f4abad8586f0a245e4c15be8Irfan Sheriff
7740f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    if (exit_sockets[1] >= 0) {
7750f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        close(exit_sockets[1]);
7760f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde        exit_sockets[1] = -1;
777025321a09dbe7820870125acf771e1da02684605Irfan Sheriff    }
778da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff}
779da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff
7800f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndevoid wifi_close_supplicant_connection()
781da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff{
782da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
783da52930b89bb0e03948f3981e75f8727ea023587Irfan Sheriff    int count = 50; /* wait at most 5 seconds to ensure init has stopped stupplicant */
784025321a09dbe7820870125acf771e1da02684605Irfan Sheriff
7850f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    wifi_close_sockets();
786025321a09dbe7820870125acf771e1da02684605Irfan Sheriff
7875a8a2d2b130644f0f4abad8586f0a245e4c15be8Irfan Sheriff    while (count-- > 0) {
788096e49c869cdb297f1ea99289ae44c2a0e487fcfIrfan Sheriff        if (property_get(supplicant_prop_name, supp_status, NULL)) {
7895a8a2d2b130644f0f4abad8586f0a245e4c15be8Irfan Sheriff            if (strcmp(supp_status, "stopped") == 0)
7905a8a2d2b130644f0f4abad8586f0a245e4c15be8Irfan Sheriff                return;
7915a8a2d2b130644f0f4abad8586f0a245e4c15be8Irfan Sheriff        }
7925a8a2d2b130644f0f4abad8586f0a245e4c15be8Irfan Sheriff        usleep(100000);
7935a8a2d2b130644f0f4abad8586f0a245e4c15be8Irfan Sheriff    }
794cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
795cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project
7960f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapndeint wifi_command(const char *command, char *reply, size_t *reply_len)
797cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project{
7980f330488afcfff031bc0ba88de826f998f7cfaf9Vinit Deshapnde    return wifi_send_command(command, reply, reply_len);
799cc490161f6af9e4a6842ee827e4bfc43bc4509d5The Android Open Source Project}
8004b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt
8014b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidtconst char *wifi_get_fw_path(int fw_type)
8024b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt{
8034b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt    switch (fw_type) {
8044b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt    case WIFI_GET_FW_PATH_STA:
8054b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt        return WIFI_DRIVER_FW_PATH_STA;
8064b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt    case WIFI_GET_FW_PATH_AP:
8074b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt        return WIFI_DRIVER_FW_PATH_AP;
8084b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt    case WIFI_GET_FW_PATH_P2P:
8094b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt        return WIFI_DRIVER_FW_PATH_P2P;
8104b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt    }
8114b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt    return NULL;
8124b7ffa08be8d58932841c52ce253ae6ca886a4f2Dmitry Shmidt}
81329a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt
81429a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidtint wifi_change_fw_path(const char *fwpath)
81529a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt{
81629a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    int len;
81729a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    int fd;
81829a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    int ret = 0;
81929a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt
82029a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    if (!fwpath)
82129a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt        return ret;
822cf449e140874e4f57f120a88411c7b642172ecf2Kenny Root    fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY));
82329a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    if (fd < 0) {
8245efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Failed to open wlan fw path param (%s)", strerror(errno));
82529a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt        return -1;
82629a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    }
82729a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    len = strlen(fwpath) + 1;
828cf449e140874e4f57f120a88411c7b642172ecf2Kenny Root    if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) {
8295efbd421e0029d6fc44b1cc65c0e5e0d85e5161fSteve Block        ALOGE("Failed to write wlan fw path param (%s)", strerror(errno));
83029a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt        ret = -1;
83129a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    }
83229a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    close(fd);
83329a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt    return ret;
83429a4d4d74b512e450a7d2ae97d4222c24a13b87eDmitry Shmidt}
835