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