blob: 2fbe4cd3a40d4defad9cd77b4493a788990e9288 [file] [log] [blame]
The Android Open Source Projectcc490162009-03-03 19:32:14 -08001/*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <fcntl.h>
19#include <errno.h>
20#include <string.h>
Dmitry Shmidteea19f12011-03-25 13:37:18 -070021#include <dirent.h>
Dmitry Shmidt45bf8a62011-09-27 17:20:11 -070022#include <sys/socket.h>
Mark Salyzyn2263e472015-04-01 07:33:14 -070023#include <sys/stat.h>
Kenny Rootcf449e12012-03-15 13:10:19 -070024#include <unistd.h>
Dmitry Shmidt45bf8a62011-09-27 17:20:11 -070025#include <poll.h>
The Android Open Source Projectcc490162009-03-03 19:32:14 -080026
27#include "hardware_legacy/wifi.h"
Dedy Lansky3674b8a2015-09-11 01:39:13 +030028#include "hardware_legacy/wifi_fst.h"
Dmitry Shmidt41d81d12013-11-22 15:54:27 -080029#ifdef LIBWPA_CLIENT_EXISTS
The Android Open Source Projectcc490162009-03-03 19:32:14 -080030#include "libwpa_client/wpa_ctrl.h"
Dmitry Shmidt41d81d12013-11-22 15:54:27 -080031#endif
The Android Open Source Projectcc490162009-03-03 19:32:14 -080032
33#define LOG_TAG "WifiHW"
34#include "cutils/log.h"
35#include "cutils/memory.h"
36#include "cutils/misc.h"
37#include "cutils/properties.h"
38#include "private/android_filesystem_config.h"
Elliott Hughes7a070c62015-01-12 11:38:56 -080039
The Android Open Source Projectcc490162009-03-03 19:32:14 -080040#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
41#include <sys/_system_properties.h>
The Android Open Source Projectcc490162009-03-03 19:32:14 -080042
Jean-Baptiste Queru445591d2010-06-21 13:15:01 -070043extern int do_dhcp();
44extern int ifc_init();
45extern void ifc_close();
46extern char *dhcp_lasterror();
47extern void get_dhcp_info();
The Android Open Source Projectcc490162009-03-03 19:32:14 -080048extern int init_module(void *, unsigned long, const char *);
49extern int delete_module(const char *, unsigned int);
Vinit Deshapnde0f330482013-08-08 10:39:25 -070050void wifi_close_sockets();
The Android Open Source Projectcc490162009-03-03 19:32:14 -080051
Dmitry Shmidt41d81d12013-11-22 15:54:27 -080052#ifndef LIBWPA_CLIENT_EXISTS
53#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING "
54struct wpa_ctrl {};
55void wpa_ctrl_cleanup(void) {}
56struct wpa_ctrl *wpa_ctrl_open(const char *ctrl_path) { return NULL; }
57void wpa_ctrl_close(struct wpa_ctrl *ctrl) {}
58int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
59 char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len))
60 { return 0; }
61int wpa_ctrl_attach(struct wpa_ctrl *ctrl) { return 0; }
62int wpa_ctrl_detach(struct wpa_ctrl *ctrl) { return 0; }
63int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
64 { return 0; }
65int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) { return 0; }
66#endif
67
68static struct wpa_ctrl *ctrl_conn;
69static struct wpa_ctrl *monitor_conn;
70
71/* socket pair used to exit from a blocking read */
72static int exit_sockets[2];
73
Irfan Sheriffda529302011-12-27 13:50:07 -080074static char primary_iface[PROPERTY_VALUE_MAX];
The Android Open Source Projectcc490162009-03-03 19:32:14 -080075// TODO: use new ANDROID_SOCKET mechanism, once support for multiple
76// sockets is in
77
Dmitry Shmidt243af8b2009-04-20 09:06:40 -070078#ifndef WIFI_DRIVER_MODULE_ARG
79#define WIFI_DRIVER_MODULE_ARG ""
80#endif
81#ifndef WIFI_FIRMWARE_LOADER
82#define WIFI_FIRMWARE_LOADER ""
83#endif
84#define WIFI_TEST_INTERFACE "sta"
85
Dmitry Shmidt4b7ffa02011-07-01 11:03:43 -070086#ifndef WIFI_DRIVER_FW_PATH_STA
87#define WIFI_DRIVER_FW_PATH_STA NULL
88#endif
89#ifndef WIFI_DRIVER_FW_PATH_AP
90#define WIFI_DRIVER_FW_PATH_AP NULL
91#endif
92#ifndef WIFI_DRIVER_FW_PATH_P2P
93#define WIFI_DRIVER_FW_PATH_P2P NULL
94#endif
95
Dmitry Shmidt29a4d4d2011-07-19 15:59:13 -070096#ifndef WIFI_DRIVER_FW_PATH_PARAM
97#define WIFI_DRIVER_FW_PATH_PARAM "/sys/module/wlan/parameters/fwpath"
98#endif
99
Dmitry Shmidted848722010-02-25 12:34:42 -0800100#define WIFI_DRIVER_LOADER_DELAY 1000000
101
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800102static const char IFACE_DIR[] = "/data/system/wpa_supplicant";
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700103#ifdef WIFI_DRIVER_MODULE_PATH
Dmitry Shmidt243af8b2009-04-20 09:06:40 -0700104static const char DRIVER_MODULE_NAME[] = WIFI_DRIVER_MODULE_NAME;
105static const char DRIVER_MODULE_TAG[] = WIFI_DRIVER_MODULE_NAME " ";
106static const char DRIVER_MODULE_PATH[] = WIFI_DRIVER_MODULE_PATH;
107static const char DRIVER_MODULE_ARG[] = WIFI_DRIVER_MODULE_ARG;
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700108#endif
Dmitry Shmidt243af8b2009-04-20 09:06:40 -0700109static const char FIRMWARE_LOADER[] = WIFI_FIRMWARE_LOADER;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800110static const char DRIVER_PROP_NAME[] = "wlan.driver.status";
111static const char SUPPLICANT_NAME[] = "wpa_supplicant";
112static const char SUPP_PROP_NAME[] = "init.svc.wpa_supplicant";
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800113static const char P2P_SUPPLICANT_NAME[] = "p2p_supplicant";
114static const char P2P_PROP_NAME[] = "init.svc.p2p_supplicant";
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800115static const char SUPP_CONFIG_TEMPLATE[]= "/system/etc/wifi/wpa_supplicant.conf";
116static const char SUPP_CONFIG_FILE[] = "/data/misc/wifi/wpa_supplicant.conf";
Irfan Sheriff67ba2272011-08-26 14:39:38 -0700117static const char P2P_CONFIG_FILE[] = "/data/misc/wifi/p2p_supplicant.conf";
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800118static const char CONTROL_IFACE_PATH[] = "/data/misc/wifi/sockets";
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800119static const char MODULE_FILE[] = "/proc/modules";
120
Dmitry Shmidtec057602013-05-29 10:34:39 -0700121static const char IFNAME[] = "IFNAME=";
122#define IFNAMELEN (sizeof(IFNAME) - 1)
123static const char WPA_EVENT_IGNORE[] = "CTRL-EVENT-IGNORE ";
124
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700125static const char SUPP_ENTROPY_FILE[] = WIFI_ENTROPY_FILE;
Dmitry Shmidt07a629e2011-10-06 13:28:32 -0700126static unsigned char dummy_key[21] = { 0x02, 0x11, 0xbe, 0x33, 0x43, 0x35,
127 0x68, 0x47, 0x84, 0x99, 0xa9, 0x2b,
128 0x1c, 0xd3, 0xee, 0xff, 0xf1, 0xe2,
129 0xf3, 0xf4, 0xf5 };
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700130
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800131/* Is either SUPPLICANT_NAME or P2P_SUPPLICANT_NAME */
132static char supplicant_name[PROPERTY_VALUE_MAX];
133/* Is either SUPP_PROP_NAME or P2P_PROP_NAME */
134static char supplicant_prop_name[PROPERTY_KEY_MAX];
135
Dedy Lansky3674b8a2015-09-11 01:39:13 +0300136int insmod(const char *filename, const char *args)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800137{
138 void *module;
139 unsigned int size;
140 int ret;
141
142 module = load_file(filename, &size);
143 if (!module)
144 return -1;
145
Dmitry Shmidt243af8b2009-04-20 09:06:40 -0700146 ret = init_module(module, size, args);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800147
148 free(module);
149
150 return ret;
151}
152
Dedy Lansky3674b8a2015-09-11 01:39:13 +0300153int rmmod(const char *modname)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800154{
155 int ret = -1;
156 int maxtry = 10;
157
158 while (maxtry-- > 0) {
159 ret = delete_module(modname, O_NONBLOCK | O_EXCL);
160 if (ret < 0 && errno == EAGAIN)
161 usleep(500000);
162 else
163 break;
164 }
165
166 if (ret != 0)
Steve Blockb381b932011-12-20 16:25:34 +0000167 ALOGD("Unable to unload driver module \"%s\": %s\n",
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800168 modname, strerror(errno));
169 return ret;
170}
171
Jean-Baptiste Queru445591d2010-06-21 13:15:01 -0700172int do_dhcp_request(int *ipaddr, int *gateway, int *mask,
173 int *dns1, int *dns2, int *server, int *lease) {
174 /* For test driver, always report success */
Irfan Sheriffda529302011-12-27 13:50:07 -0800175 if (strcmp(primary_iface, WIFI_TEST_INTERFACE) == 0)
Jean-Baptiste Queru445591d2010-06-21 13:15:01 -0700176 return 0;
177
178 if (ifc_init() < 0)
179 return -1;
180
Irfan Sheriffda529302011-12-27 13:50:07 -0800181 if (do_dhcp(primary_iface) < 0) {
Jean-Baptiste Queru445591d2010-06-21 13:15:01 -0700182 ifc_close();
183 return -1;
184 }
185 ifc_close();
186 get_dhcp_info(ipaddr, gateway, mask, dns1, dns2, server, lease);
187 return 0;
188}
189
190const char *get_dhcp_error_string() {
191 return dhcp_lasterror();
192}
193
Maddest Changda1c7fa2015-07-10 19:39:05 +0800194#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
195int wifi_change_driver_state(const char *state)
196{
197 int len;
198 int fd;
199 int ret = 0;
200
201 if (!state)
202 return -1;
203 fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_STATE_CTRL_PARAM, O_WRONLY));
204 if (fd < 0) {
205 ALOGE("Failed to open driver state control param (%s)", strerror(errno));
206 return -1;
207 }
208 len = strlen(state) + 1;
209 if (TEMP_FAILURE_RETRY(write(fd, state, len)) != len) {
210 ALOGE("Failed to write driver state control param (%s)", strerror(errno));
211 ret = -1;
212 }
213 close(fd);
214 return ret;
215}
216#endif
217
Irfan Sheriff2bb990b2010-07-27 12:16:08 -0700218int is_wifi_driver_loaded() {
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800219 char driver_status[PROPERTY_VALUE_MAX];
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700220#ifdef WIFI_DRIVER_MODULE_PATH
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800221 FILE *proc;
222 char line[sizeof(DRIVER_MODULE_TAG)+10];
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700223#endif
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800224
225 if (!property_get(DRIVER_PROP_NAME, driver_status, NULL)
226 || strcmp(driver_status, "ok") != 0) {
227 return 0; /* driver not loaded */
228 }
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700229#ifdef WIFI_DRIVER_MODULE_PATH
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800230 /*
231 * If the property says the driver is loaded, check to
232 * make sure that the property setting isn't just left
233 * over from a previous manual shutdown or a runtime
234 * crash.
235 */
236 if ((proc = fopen(MODULE_FILE, "r")) == NULL) {
Steve Block64cca042012-01-05 23:27:53 +0000237 ALOGW("Could not open %s: %s", MODULE_FILE, strerror(errno));
Dmitry Shmidt243af8b2009-04-20 09:06:40 -0700238 property_set(DRIVER_PROP_NAME, "unloaded");
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800239 return 0;
240 }
241 while ((fgets(line, sizeof(line), proc)) != NULL) {
242 if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0) {
243 fclose(proc);
Dedy Lansky3674b8a2015-09-11 01:39:13 +0300244 return is_fst_driver_loaded();
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800245 }
246 }
247 fclose(proc);
248 property_set(DRIVER_PROP_NAME, "unloaded");
249 return 0;
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700250#else
251 return 1;
252#endif
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800253}
254
255int wifi_load_driver()
256{
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700257#ifdef WIFI_DRIVER_MODULE_PATH
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800258 char driver_status[PROPERTY_VALUE_MAX];
259 int count = 100; /* wait at most 20 seconds for completion */
260
Irfan Sheriff2bb990b2010-07-27 12:16:08 -0700261 if (is_wifi_driver_loaded()) {
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800262 return 0;
263 }
264
Dmitry Shmidt243af8b2009-04-20 09:06:40 -0700265 if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800266 return -1;
Dmitry Shmidt243af8b2009-04-20 09:06:40 -0700267
268 if (strcmp(FIRMWARE_LOADER,"") == 0) {
Dmitry Shmidt8fb5f742010-09-14 15:11:22 -0700269 /* usleep(WIFI_DRIVER_LOADER_DELAY); */
Dmitry Shmidt243af8b2009-04-20 09:06:40 -0700270 property_set(DRIVER_PROP_NAME, "ok");
271 }
272 else {
273 property_set("ctl.start", FIRMWARE_LOADER);
274 }
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800275 sched_yield();
276 while (count-- > 0) {
277 if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
278 if (strcmp(driver_status, "ok") == 0)
Dedy Lansky3674b8a2015-09-11 01:39:13 +0300279 return wifi_fst_load_driver();
Ajay Dudani85bff332015-05-03 17:32:49 -0700280 else if (strcmp(driver_status, "failed") == 0) {
Dmitry Shmidt7b436992009-07-28 11:03:31 -0700281 wifi_unload_driver();
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800282 return -1;
Dmitry Shmidt7b436992009-07-28 11:03:31 -0700283 }
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800284 }
285 usleep(200000);
286 }
287 property_set(DRIVER_PROP_NAME, "timeout");
Dmitry Shmidt7b436992009-07-28 11:03:31 -0700288 wifi_unload_driver();
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800289 return -1;
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700290#else
Maddest Changda1c7fa2015-07-10 19:39:05 +0800291#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
292 if (is_wifi_driver_loaded()) {
293 return 0;
294 }
295
296 if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0)
297 return -1;
298#endif
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700299 property_set(DRIVER_PROP_NAME, "ok");
300 return 0;
301#endif
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800302}
303
304int wifi_unload_driver()
305{
Dmitry Shmidt4c1a1fe2011-06-13 10:32:08 -0700306 usleep(200000); /* allow to finish interface down */
Dedy Lansky3674b8a2015-09-11 01:39:13 +0300307
308 wifi_fst_unload_driver();
309
Dmitry Shmidt953c1142011-08-23 15:44:23 -0700310#ifdef WIFI_DRIVER_MODULE_PATH
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800311 if (rmmod(DRIVER_MODULE_NAME) == 0) {
Dmitry Shmidt953c1142011-08-23 15:44:23 -0700312 int count = 20; /* wait at most 10 seconds for completion */
Dmitry Shmidt0e9f4882011-01-04 16:35:18 -0800313 while (count-- > 0) {
314 if (!is_wifi_driver_loaded())
315 break;
316 usleep(500000);
317 }
Dmitry Shmidt953c1142011-08-23 15:44:23 -0700318 usleep(500000); /* allow card removal */
Dmitry Shmidt0e9f4882011-01-04 16:35:18 -0800319 if (count) {
320 return 0;
321 }
322 return -1;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800323 } else
324 return -1;
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700325#else
Maddest Changda1c7fa2015-07-10 19:39:05 +0800326#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
327 if (is_wifi_driver_loaded()) {
328 if (wifi_change_driver_state(WIFI_DRIVER_STATE_OFF) < 0)
329 return -1;
330 }
331#endif
Dmitry Shmidtd301cb72011-06-29 16:22:28 -0700332 property_set(DRIVER_PROP_NAME, "unloaded");
333 return 0;
334#endif
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800335}
336
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700337int ensure_entropy_file_exists()
338{
339 int ret;
340 int destfd;
341
342 ret = access(SUPP_ENTROPY_FILE, R_OK|W_OK);
343 if ((ret == 0) || (errno == EACCES)) {
344 if ((ret != 0) &&
345 (chmod(SUPP_ENTROPY_FILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
Steve Block5efbd422012-01-08 10:18:02 +0000346 ALOGE("Cannot set RW to \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700347 return -1;
348 }
349 return 0;
350 }
Kenny Rootcf449e12012-03-15 13:10:19 -0700351 destfd = TEMP_FAILURE_RETRY(open(SUPP_ENTROPY_FILE, O_CREAT|O_RDWR, 0660));
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700352 if (destfd < 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000353 ALOGE("Cannot create \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700354 return -1;
355 }
356
Kenny Rootcf449e12012-03-15 13:10:19 -0700357 if (TEMP_FAILURE_RETRY(write(destfd, dummy_key, sizeof(dummy_key))) != sizeof(dummy_key)) {
Steve Block5efbd422012-01-08 10:18:02 +0000358 ALOGE("Error writing \"%s\": %s", SUPP_ENTROPY_FILE, strerror(errno));
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700359 close(destfd);
360 return -1;
361 }
362 close(destfd);
363
364 /* chmod is needed because open() didn't set permisions properly */
365 if (chmod(SUPP_ENTROPY_FILE, 0660) < 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000366 ALOGE("Error changing permissions of %s to 0660: %s",
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700367 SUPP_ENTROPY_FILE, strerror(errno));
368 unlink(SUPP_ENTROPY_FILE);
369 return -1;
370 }
371
372 if (chown(SUPP_ENTROPY_FILE, AID_SYSTEM, AID_WIFI) < 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000373 ALOGE("Error changing group ownership of %s to %d: %s",
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700374 SUPP_ENTROPY_FILE, AID_WIFI, strerror(errno));
375 unlink(SUPP_ENTROPY_FILE);
376 return -1;
377 }
378 return 0;
379}
380
Dedy Lansky69e94ce2015-09-10 17:09:49 +0300381int ensure_config_file_exists(const char *config_file, const char *config_file_template)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800382{
383 char buf[2048];
384 int srcfd, destfd;
Irfan Sheriff8a5b1972010-12-16 16:17:29 -0800385 struct stat sb;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800386 int nread;
Dmitry Shmidt89ae7032011-03-07 15:30:53 -0800387 int ret;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800388
Irfan Sheriff67ba2272011-08-26 14:39:38 -0700389 ret = access(config_file, R_OK|W_OK);
Dmitry Shmidt89ae7032011-03-07 15:30:53 -0800390 if ((ret == 0) || (errno == EACCES)) {
391 if ((ret != 0) &&
Irfan Sheriff67ba2272011-08-26 14:39:38 -0700392 (chmod(config_file, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) != 0)) {
Steve Block5efbd422012-01-08 10:18:02 +0000393 ALOGE("Cannot set RW to \"%s\": %s", config_file, strerror(errno));
Dmitry Shmidt89ae7032011-03-07 15:30:53 -0800394 return -1;
395 }
Dmitry Shmidtc6bb3b52013-10-04 15:49:11 -0700396 return 0;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800397 } else if (errno != ENOENT) {
Steve Block5efbd422012-01-08 10:18:02 +0000398 ALOGE("Cannot access \"%s\": %s", config_file, strerror(errno));
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800399 return -1;
400 }
401
Dedy Lansky69e94ce2015-09-10 17:09:49 +0300402 srcfd = TEMP_FAILURE_RETRY(open(config_file_template, O_RDONLY));
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800403 if (srcfd < 0) {
Dedy Lansky69e94ce2015-09-10 17:09:49 +0300404 ALOGE("Cannot open \"%s\": %s", config_file_template, strerror(errno));
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800405 return -1;
406 }
407
Kenny Rootcf449e12012-03-15 13:10:19 -0700408 destfd = TEMP_FAILURE_RETRY(open(config_file, O_CREAT|O_RDWR, 0660));
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800409 if (destfd < 0) {
410 close(srcfd);
Steve Block5efbd422012-01-08 10:18:02 +0000411 ALOGE("Cannot create \"%s\": %s", config_file, strerror(errno));
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800412 return -1;
413 }
414
Kenny Rootcf449e12012-03-15 13:10:19 -0700415 while ((nread = TEMP_FAILURE_RETRY(read(srcfd, buf, sizeof(buf)))) != 0) {
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800416 if (nread < 0) {
Dedy Lansky69e94ce2015-09-10 17:09:49 +0300417 ALOGE("Error reading \"%s\": %s", config_file_template, strerror(errno));
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800418 close(srcfd);
419 close(destfd);
Irfan Sheriff67ba2272011-08-26 14:39:38 -0700420 unlink(config_file);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800421 return -1;
422 }
Kenny Rootcf449e12012-03-15 13:10:19 -0700423 TEMP_FAILURE_RETRY(write(destfd, buf, nread));
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800424 }
425
426 close(destfd);
427 close(srcfd);
428
Dmitry Shmidt24bf7fc2010-08-09 11:04:49 -0700429 /* chmod is needed because open() didn't set permisions properly */
Irfan Sheriff67ba2272011-08-26 14:39:38 -0700430 if (chmod(config_file, 0660) < 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000431 ALOGE("Error changing permissions of %s to 0660: %s",
Irfan Sheriff67ba2272011-08-26 14:39:38 -0700432 config_file, strerror(errno));
433 unlink(config_file);
Dmitry Shmidt24bf7fc2010-08-09 11:04:49 -0700434 return -1;
435 }
436
Irfan Sheriff67ba2272011-08-26 14:39:38 -0700437 if (chown(config_file, AID_SYSTEM, AID_WIFI) < 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000438 ALOGE("Error changing group ownership of %s to %d: %s",
Irfan Sheriff67ba2272011-08-26 14:39:38 -0700439 config_file, AID_WIFI, strerror(errno));
440 unlink(config_file);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800441 return -1;
442 }
Dmitry Shmidtc6bb3b52013-10-04 15:49:11 -0700443 return 0;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800444}
445
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800446int wifi_start_supplicant(int p2p_supported)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800447{
448 char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
449 int count = 200; /* wait at most 20 seconds for completion */
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800450 const prop_info *pi;
Irfan Sheriffda529302011-12-27 13:50:07 -0800451 unsigned serial = 0, i;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800452
Dedy Lansky3674b8a2015-09-11 01:39:13 +0300453 if (wifi_start_fstman(0)) {
454 return -1;
455 }
456
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800457 if (p2p_supported) {
458 strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
459 strcpy(supplicant_prop_name, P2P_PROP_NAME);
460
461 /* Ensure p2p config file is created */
Dedy Lansky69e94ce2015-09-10 17:09:49 +0300462 if (ensure_config_file_exists(P2P_CONFIG_FILE, SUPP_CONFIG_TEMPLATE) < 0) {
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800463 ALOGE("Failed to create a p2p config file");
464 return -1;
465 }
466
467 } else {
468 strcpy(supplicant_name, SUPPLICANT_NAME);
469 strcpy(supplicant_prop_name, SUPP_PROP_NAME);
470 }
471
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800472 /* Check whether already running */
Jonathan DE CESCOeed817e2012-11-20 18:59:34 +0100473 if (property_get(supplicant_prop_name, supp_status, NULL)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800474 && strcmp(supp_status, "running") == 0) {
475 return 0;
476 }
477
478 /* Before starting the daemon, make sure its config file exists */
Dedy Lansky69e94ce2015-09-10 17:09:49 +0300479 if (ensure_config_file_exists(SUPP_CONFIG_FILE, SUPP_CONFIG_TEMPLATE) < 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000480 ALOGE("Wi-Fi will not be enabled");
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800481 return -1;
482 }
483
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700484 if (ensure_entropy_file_exists() < 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000485 ALOGE("Wi-Fi entropy file was not created");
Dmitry Shmidt3ab3e662011-07-25 10:46:00 -0700486 }
487
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800488 /* Clear out any stale socket files that might be left over. */
Dmitry Shmidtde9abff2013-05-22 16:45:57 -0700489 wpa_ctrl_cleanup();
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800490
Irfan Sheriffda529302011-12-27 13:50:07 -0800491 /* Reset sockets used for exiting from hung state */
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700492 exit_sockets[0] = exit_sockets[1] = -1;
Irfan Sheriffda529302011-12-27 13:50:07 -0800493
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800494 /*
495 * Get a reference to the status property, so we can distinguish
496 * the case where it goes stopped => running => stopped (i.e.,
497 * it start up, but fails right away) from the case in which
498 * it starts in the stopped state and never manages to start
499 * running at all.
500 */
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800501 pi = __system_property_find(supplicant_prop_name);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800502 if (pi != NULL) {
Colin Cross14c02f22013-02-04 12:34:20 -0800503 serial = __system_property_serial(pi);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800504 }
Irfan Sheriffda529302011-12-27 13:50:07 -0800505 property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE);
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800506
507 property_set("ctl.start", supplicant_name);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800508 sched_yield();
509
510 while (count-- > 0) {
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800511 if (pi == NULL) {
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800512 pi = __system_property_find(supplicant_prop_name);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800513 }
514 if (pi != NULL) {
jiaguo4431a1c2014-03-13 18:49:14 +0800515 /*
516 * property serial updated means that init process is scheduled
517 * after we sched_yield, further property status checking is based on this */
518 if (__system_property_serial(pi) != serial) {
519 __system_property_read(pi, NULL, supp_status);
520 if (strcmp(supp_status, "running") == 0) {
521 return 0;
522 } else if (strcmp(supp_status, "stopped") == 0) {
523 return -1;
524 }
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800525 }
526 }
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800527 usleep(100000);
528 }
529 return -1;
530}
531
Irfan Sheriff745e7fd2012-11-03 23:21:39 -0700532int wifi_stop_supplicant(int p2p_supported)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800533{
534 char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
535 int count = 50; /* wait at most 5 seconds for completion */
536
Irfan Sheriff745e7fd2012-11-03 23:21:39 -0700537 if (p2p_supported) {
538 strcpy(supplicant_name, P2P_SUPPLICANT_NAME);
539 strcpy(supplicant_prop_name, P2P_PROP_NAME);
540 } else {
541 strcpy(supplicant_name, SUPPLICANT_NAME);
542 strcpy(supplicant_prop_name, SUPP_PROP_NAME);
543 }
544
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800545 /* Check whether supplicant already stopped */
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800546 if (property_get(supplicant_prop_name, supp_status, NULL)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800547 && strcmp(supp_status, "stopped") == 0) {
Dedy Lansky3674b8a2015-09-11 01:39:13 +0300548 wifi_stop_fstman(0);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800549 return 0;
550 }
551
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800552 property_set("ctl.stop", supplicant_name);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800553 sched_yield();
554
555 while (count-- > 0) {
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800556 if (property_get(supplicant_prop_name, supp_status, NULL)) {
Hu Wangc9195132016-01-07 13:26:33 +0800557 if (strcmp(supp_status, "stopped") == 0) {
Dedy Lansky3674b8a2015-09-11 01:39:13 +0300558 wifi_stop_fstman(0);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800559 return 0;
Hu Wangc9195132016-01-07 13:26:33 +0800560 }
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800561 }
562 usleep(100000);
563 }
Irfan Sheriff745e7fd2012-11-03 23:21:39 -0700564 ALOGE("Failed to stop supplicant");
Dedy Lansky3674b8a2015-09-11 01:39:13 +0300565 wifi_stop_fstman(0);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800566 return -1;
567}
568
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700569int wifi_connect_on_socket_path(const char *path)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800570{
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800571 char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
572
573 /* Make sure supplicant is running */
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800574 if (!property_get(supplicant_prop_name, supp_status, NULL)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800575 || strcmp(supp_status, "running") != 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000576 ALOGE("Supplicant not running, cannot connect");
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800577 return -1;
578 }
579
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700580 ctrl_conn = wpa_ctrl_open(path);
581 if (ctrl_conn == NULL) {
Steve Block5efbd422012-01-08 10:18:02 +0000582 ALOGE("Unable to open connection to supplicant on \"%s\": %s",
Irfan Sheriffda529302011-12-27 13:50:07 -0800583 path, strerror(errno));
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800584 return -1;
585 }
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700586 monitor_conn = wpa_ctrl_open(path);
587 if (monitor_conn == NULL) {
588 wpa_ctrl_close(ctrl_conn);
589 ctrl_conn = NULL;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800590 return -1;
591 }
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700592 if (wpa_ctrl_attach(monitor_conn) != 0) {
593 wpa_ctrl_close(monitor_conn);
594 wpa_ctrl_close(ctrl_conn);
595 ctrl_conn = monitor_conn = NULL;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800596 return -1;
597 }
Irfan Sheriff025321a2011-09-19 15:03:45 -0700598
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700599 if (socketpair(AF_UNIX, SOCK_STREAM, 0, exit_sockets) == -1) {
600 wpa_ctrl_close(monitor_conn);
601 wpa_ctrl_close(ctrl_conn);
602 ctrl_conn = monitor_conn = NULL;
Irfan Sheriff025321a2011-09-19 15:03:45 -0700603 return -1;
604 }
605
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800606 return 0;
607}
608
Irfan Sheriffda529302011-12-27 13:50:07 -0800609/* Establishes the control and monitor socket connections on the interface */
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700610int wifi_connect_to_supplicant()
Irfan Sheriffda529302011-12-27 13:50:07 -0800611{
Dmitry Shmidtec057602013-05-29 10:34:39 -0700612 static char path[PATH_MAX];
Irfan Sheriffda529302011-12-27 13:50:07 -0800613
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700614 if (access(IFACE_DIR, F_OK) == 0) {
615 snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);
Irfan Sheriffda529302011-12-27 13:50:07 -0800616 } else {
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700617 snprintf(path, sizeof(path), "@android:wpa_%s", primary_iface);
Irfan Sheriffda529302011-12-27 13:50:07 -0800618 }
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700619 return wifi_connect_on_socket_path(path);
Irfan Sheriffda529302011-12-27 13:50:07 -0800620}
621
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700622int wifi_send_command(const char *cmd, char *reply, size_t *reply_len)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800623{
624 int ret;
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700625 if (ctrl_conn == NULL) {
Steve Block6a705182011-10-20 11:56:19 +0100626 ALOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800627 return -1;
628 }
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700629 ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800630 if (ret == -2) {
Steve Blockb381b932011-12-20 16:25:34 +0000631 ALOGD("'%s' command timed out.\n", cmd);
Irfan Sheriff025321a2011-09-19 15:03:45 -0700632 /* unblocks the monitor receive socket for termination */
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700633 TEMP_FAILURE_RETRY(write(exit_sockets[0], "T", 1));
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800634 return -2;
635 } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
636 return -1;
637 }
638 if (strncmp(cmd, "PING", 4) == 0) {
639 reply[*reply_len] = '\0';
640 }
641 return 0;
642}
643
Maheshff6902d2014-05-14 18:56:15 +0530644int wifi_supplicant_connection_active()
645{
646 char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
647
648 if (property_get(supplicant_prop_name, supp_status, NULL)) {
649 if (strcmp(supp_status, "stopped") == 0)
650 return -1;
651 }
652
653 return 0;
654}
655
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700656int wifi_ctrl_recv(char *reply, size_t *reply_len)
Irfan Sheriff025321a2011-09-19 15:03:45 -0700657{
658 int res;
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700659 int ctrlfd = wpa_ctrl_get_fd(monitor_conn);
Dmitry Shmidt45bf8a62011-09-27 17:20:11 -0700660 struct pollfd rfds[2];
Irfan Sheriff025321a2011-09-19 15:03:45 -0700661
Dmitry Shmidt45bf8a62011-09-27 17:20:11 -0700662 memset(rfds, 0, 2 * sizeof(struct pollfd));
663 rfds[0].fd = ctrlfd;
664 rfds[0].events |= POLLIN;
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700665 rfds[1].fd = exit_sockets[1];
Dmitry Shmidt45bf8a62011-09-27 17:20:11 -0700666 rfds[1].events |= POLLIN;
Maheshff6902d2014-05-14 18:56:15 +0530667 do {
668 res = TEMP_FAILURE_RETRY(poll(rfds, 2, 30000));
669 if (res < 0) {
670 ALOGE("Error poll = %d", res);
671 return res;
672 } else if (res == 0) {
673 /* timed out, check if supplicant is active
674 * or not ..
675 */
676 res = wifi_supplicant_connection_active();
677 if (res < 0)
678 return -2;
679 }
680 } while (res == 0);
681
Dmitry Shmidt45bf8a62011-09-27 17:20:11 -0700682 if (rfds[0].revents & POLLIN) {
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700683 return wpa_ctrl_recv(monitor_conn, reply, reply_len);
Irfan Sheriff025321a2011-09-19 15:03:45 -0700684 }
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700685
686 /* it is not rfds[0], then it must be rfts[1] (i.e. the exit socket)
687 * or we timed out. In either case, this call has failed ..
688 */
Irfan Sheriff897f6dd2012-10-10 15:41:13 -0700689 return -2;
Irfan Sheriff025321a2011-09-19 15:03:45 -0700690}
691
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700692int wifi_wait_on_socket(char *buf, size_t buflen)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800693{
694 size_t nread = buflen - 1;
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800695 int result;
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700696 char *match, *match2;
Dmitry Shmidt0e9f4882011-01-04 16:35:18 -0800697
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700698 if (monitor_conn == NULL) {
Mahesh0ef9a332014-05-13 13:59:05 +0530699 return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
700 primary_iface, WPA_EVENT_TERMINATING);
Irfan Sheriff2631f992010-01-27 15:35:28 -0800701 }
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800702
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700703 result = wifi_ctrl_recv(buf, &nread);
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800704
705 /* Terminate reception on exit socket */
706 if (result == -2) {
Mahesh0ef9a332014-05-13 13:59:05 +0530707 return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
708 primary_iface, WPA_EVENT_TERMINATING);
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800709 }
710
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800711 if (result < 0) {
Steve Blockb381b932011-12-20 16:25:34 +0000712 ALOGD("wifi_ctrl_recv failed: %s\n", strerror(errno));
Mahesh0ef9a332014-05-13 13:59:05 +0530713 return snprintf(buf, buflen, "IFNAME=%s %s - recv error",
714 primary_iface, WPA_EVENT_TERMINATING);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800715 }
716 buf[nread] = '\0';
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800717 /* Check for EOF on the socket */
718 if (result == 0 && nread == 0) {
719 /* Fabricate an event to pass up */
Steve Blockb381b932011-12-20 16:25:34 +0000720 ALOGD("Received EOF on supplicant socket\n");
Mahesh0ef9a332014-05-13 13:59:05 +0530721 return snprintf(buf, buflen, "IFNAME=%s %s - signal 0 received",
722 primary_iface, WPA_EVENT_TERMINATING);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800723 }
724 /*
725 * Events strings are in the format
726 *
Dmitry Shmidtec057602013-05-29 10:34:39 -0700727 * IFNAME=iface <N>CTRL-EVENT-XXX
728 * or
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800729 * <N>CTRL-EVENT-XXX
730 *
731 * where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
732 * etc.) and XXX is the event name. The level information is not useful
733 * to us, so strip it off.
734 */
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700735
Dmitry Shmidtec057602013-05-29 10:34:39 -0700736 if (strncmp(buf, IFNAME, IFNAMELEN) == 0) {
737 match = strchr(buf, ' ');
738 if (match != NULL) {
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700739 if (match[1] == '<') {
740 match2 = strchr(match + 2, '>');
741 if (match2 != NULL) {
742 nread -= (match2 - match);
743 memmove(match + 1, match2 + 1, nread - (match - buf) + 1);
744 }
Dmitry Shmidtec057602013-05-29 10:34:39 -0700745 }
Dmitry Shmidtec057602013-05-29 10:34:39 -0700746 } else {
747 return snprintf(buf, buflen, "%s", WPA_EVENT_IGNORE);
748 }
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700749 } else if (buf[0] == '<') {
Dmitry Shmidtec057602013-05-29 10:34:39 -0700750 match = strchr(buf, '>');
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800751 if (match != NULL) {
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700752 nread -= (match + 1 - buf);
753 memmove(buf, match + 1, nread + 1);
754 ALOGV("supplicant generated event without interface - %s\n", buf);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800755 }
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700756 } else {
757 /* let the event go as is! */
758 ALOGW("supplicant generated event without interface and without message level - %s\n", buf);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800759 }
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800760
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800761 return nread;
762}
763
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700764int wifi_wait_for_event(char *buf, size_t buflen)
Irfan Sheriffda529302011-12-27 13:50:07 -0800765{
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700766 return wifi_wait_on_socket(buf, buflen);
767}
768
769void wifi_close_sockets()
770{
771 if (ctrl_conn != NULL) {
772 wpa_ctrl_close(ctrl_conn);
773 ctrl_conn = NULL;
774 }
775
776 if (monitor_conn != NULL) {
777 wpa_ctrl_close(monitor_conn);
778 monitor_conn = NULL;
779 }
780
781 if (exit_sockets[0] >= 0) {
782 close(exit_sockets[0]);
783 exit_sockets[0] = -1;
784 }
785
786 if (exit_sockets[1] >= 0) {
787 close(exit_sockets[1]);
788 exit_sockets[1] = -1;
Irfan Sheriffda529302011-12-27 13:50:07 -0800789 }
790}
791
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700792void wifi_close_supplicant_connection()
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800793{
Irfan Sheriff5a8a2d22011-08-22 13:27:56 -0700794 char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
795 int count = 50; /* wait at most 5 seconds to ensure init has stopped stupplicant */
796
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700797 wifi_close_sockets();
Irfan Sheriff025321a2011-09-19 15:03:45 -0700798
Irfan Sheriff5a8a2d22011-08-22 13:27:56 -0700799 while (count-- > 0) {
Irfan Sheriff096e49c2012-01-10 16:24:51 -0800800 if (property_get(supplicant_prop_name, supp_status, NULL)) {
Irfan Sheriff5a8a2d22011-08-22 13:27:56 -0700801 if (strcmp(supp_status, "stopped") == 0)
802 return;
803 }
804 usleep(100000);
805 }
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800806}
807
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700808int wifi_command(const char *command, char *reply, size_t *reply_len)
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800809{
Vinit Deshapnde0f330482013-08-08 10:39:25 -0700810 return wifi_send_command(command, reply, reply_len);
The Android Open Source Projectcc490162009-03-03 19:32:14 -0800811}
Dmitry Shmidt4b7ffa02011-07-01 11:03:43 -0700812
813const char *wifi_get_fw_path(int fw_type)
814{
815 switch (fw_type) {
816 case WIFI_GET_FW_PATH_STA:
817 return WIFI_DRIVER_FW_PATH_STA;
818 case WIFI_GET_FW_PATH_AP:
819 return WIFI_DRIVER_FW_PATH_AP;
820 case WIFI_GET_FW_PATH_P2P:
821 return WIFI_DRIVER_FW_PATH_P2P;
822 }
823 return NULL;
824}
Dmitry Shmidt29a4d4d2011-07-19 15:59:13 -0700825
826int wifi_change_fw_path(const char *fwpath)
827{
828 int len;
829 int fd;
830 int ret = 0;
831
832 if (!fwpath)
833 return ret;
Kenny Rootcf449e12012-03-15 13:10:19 -0700834 fd = TEMP_FAILURE_RETRY(open(WIFI_DRIVER_FW_PATH_PARAM, O_WRONLY));
Dmitry Shmidt29a4d4d2011-07-19 15:59:13 -0700835 if (fd < 0) {
Steve Block5efbd422012-01-08 10:18:02 +0000836 ALOGE("Failed to open wlan fw path param (%s)", strerror(errno));
Dmitry Shmidt29a4d4d2011-07-19 15:59:13 -0700837 return -1;
838 }
839 len = strlen(fwpath) + 1;
Kenny Rootcf449e12012-03-15 13:10:19 -0700840 if (TEMP_FAILURE_RETRY(write(fd, fwpath, len)) != len) {
Steve Block5efbd422012-01-08 10:18:02 +0000841 ALOGE("Failed to write wlan fw path param (%s)", strerror(errno));
Dmitry Shmidt29a4d4d2011-07-19 15:59:13 -0700842 ret = -1;
843 }
844 close(fd);
845 return ret;
846}