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