1 #include <stdint.h> 2 #include <fcntl.h> 3 #include <sys/socket.h> 4 #include <netlink/genl/genl.h> 5 #include <netlink/genl/family.h> 6 #include <netlink/genl/ctrl.h> 7 #include <linux/rtnetlink.h> 8 #include <netpacket/packet.h> 9 #include <linux/filter.h> 10 #include <linux/errqueue.h> 11 #include <errno.h> 12 13 #include <linux/pkt_sched.h> 14 #include <netlink/object-api.h> 15 #include <netlink/netlink.h> 16 #include <netlink/socket.h> 17 #include <netlink/attr.h> 18 #include <netlink/handlers.h> 19 #include <netlink/msg.h> 20 21 #include <dirent.h> 22 #include <net/if.h> 23 24 #include "sync.h" 25 26 #define LOG_TAG "WifiHAL" 27 28 #include <utils/Log.h> 29 30 #include "wifi_hal.h" 31 #include "common.h" 32 #include "cpp_bindings.h" 33 #include "rtt.h" 34 /* 35 BUGBUG: normally, libnl allocates ports for all connections it makes; but 36 being a static library, it doesn't really know how many other netlink connections 37 are made by the same process, if connections come from different shared libraries. 38 These port assignments exist to solve that problem - temporarily. We need to fix 39 libnl to try and allocate ports across the entire process. 40 */ 41 42 #define WIFI_HAL_CMD_SOCK_PORT 644 43 #define WIFI_HAL_EVENT_SOCK_PORT 645 44 45 #define FEATURE_SET 0 46 #define FEATURE_SET_MATRIX 1 47 #define ATTR_NODFS_VALUE 3 48 #define ATTR_COUNTRY_CODE 4 49 50 static void internal_event_handler(wifi_handle handle, int events); 51 static int internal_no_seq_check(nl_msg *msg, void *arg); 52 static int internal_valid_message_handler(nl_msg *msg, void *arg); 53 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group); 54 static int wifi_add_membership(wifi_handle handle, const char *group); 55 static wifi_error wifi_init_interfaces(wifi_handle handle); 56 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle 57 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh); 58 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface); 59 60 typedef enum wifi_attr { 61 ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, 62 ANDR_WIFI_ATTRIBUTE_FEATURE_SET, 63 ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI 64 } wifi_attr_t; 65 66 enum wifi_rssi_monitor_attr { 67 RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, 68 RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, 69 RSSI_MONITOR_ATTRIBUTE_START, 70 }; 71 72 /* Initialize/Cleanup */ 73 74 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port) 75 { 76 uint32_t pid = getpid() & 0x3FFFFF; 77 nl_socket_set_local_port(sock, pid + (port << 22)); 78 } 79 80 static nl_sock * wifi_create_nl_socket(int port) 81 { 82 // ALOGI("Creating socket"); 83 struct nl_sock *sock = nl_socket_alloc(); 84 if (sock == NULL) { 85 ALOGE("Could not create handle"); 86 return NULL; 87 } 88 89 wifi_socket_set_local_port(sock, port); 90 91 struct sockaddr *addr = NULL; 92 // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl)); 93 94 // ALOGI("Connecting socket"); 95 if (nl_connect(sock, NETLINK_GENERIC)) { 96 ALOGE("Could not connect handle"); 97 nl_socket_free(sock); 98 return NULL; 99 } 100 101 // ALOGI("Making socket nonblocking"); 102 /* 103 if (nl_socket_set_nonblocking(sock)) { 104 ALOGE("Could make socket non-blocking"); 105 nl_socket_free(sock); 106 return NULL; 107 } 108 */ 109 110 return sock; 111 } 112 113 /*initialize function pointer table with Broadcom HHAL API*/ 114 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) 115 { 116 if (fn == NULL) { 117 return WIFI_ERROR_UNKNOWN; 118 } 119 fn->wifi_initialize = wifi_initialize; 120 fn->wifi_cleanup = wifi_cleanup; 121 fn->wifi_event_loop = wifi_event_loop; 122 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set; 123 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix; 124 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui; 125 fn->wifi_get_ifaces = wifi_get_ifaces; 126 fn->wifi_get_iface_name = wifi_get_iface_name; 127 fn->wifi_start_gscan = wifi_start_gscan; 128 fn->wifi_stop_gscan = wifi_stop_gscan; 129 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results; 130 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist; 131 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist; 132 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler; 133 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler; 134 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities; 135 fn->wifi_get_link_stats = wifi_get_link_stats; 136 fn->wifi_get_valid_channels = wifi_get_valid_channels; 137 fn->wifi_rtt_range_request = wifi_rtt_range_request; 138 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel; 139 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities; 140 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag; 141 fn->wifi_start_logging = wifi_start_logging; 142 fn->wifi_set_epno_list = wifi_set_epno_list; 143 fn->wifi_set_country_code = wifi_set_country_code; 144 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump; 145 fn->wifi_set_log_handler = wifi_set_log_handler; 146 fn->wifi_reset_log_handler = wifi_reset_log_handler; 147 fn->wifi_set_alert_handler = wifi_set_alert_handler; 148 fn->wifi_reset_alert_handler = wifi_reset_alert_handler; 149 fn->wifi_get_firmware_version = wifi_get_firmware_version; 150 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status; 151 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set; 152 fn->wifi_get_ring_data = wifi_get_ring_data; 153 fn->wifi_get_driver_version = wifi_get_driver_version; 154 fn->wifi_set_ssid_white_list = wifi_set_ssid_white_list; 155 fn->wifi_set_gscan_roam_params = wifi_set_gscan_roam_params; 156 fn->wifi_set_bssid_preference = wifi_set_bssid_preference; 157 fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist; 158 fn->wifi_enable_lazy_roam = wifi_enable_lazy_roam; 159 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring; 160 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring; 161 fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet; 162 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet; 163 return WIFI_SUCCESS; 164 } 165 166 wifi_error wifi_initialize(wifi_handle *handle) 167 { 168 srand(getpid()); 169 170 ALOGI("Initializing wifi"); 171 hal_info *info = (hal_info *)malloc(sizeof(hal_info)); 172 if (info == NULL) { 173 ALOGE("Could not allocate hal_info"); 174 return WIFI_ERROR_UNKNOWN; 175 } 176 177 memset(info, 0, sizeof(*info)); 178 179 ALOGI("Creating socket"); 180 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) { 181 ALOGE("Could not create cleanup sockets"); 182 return WIFI_ERROR_UNKNOWN; 183 } 184 185 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT); 186 if (cmd_sock == NULL) { 187 ALOGE("Could not create handle"); 188 return WIFI_ERROR_UNKNOWN; 189 } 190 191 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT); 192 if (event_sock == NULL) { 193 ALOGE("Could not create handle"); 194 nl_socket_free(cmd_sock); 195 return WIFI_ERROR_UNKNOWN; 196 } 197 198 struct nl_cb *cb = nl_socket_get_cb(event_sock); 199 if (cb == NULL) { 200 ALOGE("Could not create handle"); 201 return WIFI_ERROR_UNKNOWN; 202 } 203 204 // ALOGI("cb->refcnt = %d", cb->cb_refcnt); 205 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info); 206 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info); 207 nl_cb_put(cb); 208 209 info->cmd_sock = cmd_sock; 210 info->event_sock = event_sock; 211 info->clean_up = false; 212 info->in_event_loop = false; 213 214 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE); 215 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE; 216 info->num_event_cb = 0; 217 218 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE); 219 info->alloc_cmd = DEFAULT_CMD_SIZE; 220 info->num_cmd = 0; 221 222 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211"); 223 if (info->nl80211_family_id < 0) { 224 ALOGE("Could not resolve nl80211 familty id"); 225 nl_socket_free(cmd_sock); 226 nl_socket_free(event_sock); 227 free(info); 228 return WIFI_ERROR_UNKNOWN; 229 } 230 231 pthread_mutex_init(&info->cb_lock, NULL); 232 233 *handle = (wifi_handle) info; 234 235 wifi_add_membership(*handle, "scan"); 236 wifi_add_membership(*handle, "mlme"); 237 wifi_add_membership(*handle, "regulatory"); 238 wifi_add_membership(*handle, "vendor"); 239 240 wifi_init_interfaces(*handle); 241 // ALOGI("Found %d interfaces", info->num_interfaces); 242 243 244 ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR); 245 return WIFI_SUCCESS; 246 } 247 248 static int wifi_add_membership(wifi_handle handle, const char *group) 249 { 250 hal_info *info = getHalInfo(handle); 251 252 int id = wifi_get_multicast_id(handle, "nl80211", group); 253 if (id < 0) { 254 ALOGE("Could not find group %s", group); 255 return id; 256 } 257 258 int ret = nl_socket_add_membership(info->event_sock, id); 259 if (ret < 0) { 260 ALOGE("Could not add membership to group %s", group); 261 } 262 263 // ALOGI("Successfully added membership for group %s", group); 264 return ret; 265 } 266 267 static void internal_cleaned_up_handler(wifi_handle handle) 268 { 269 hal_info *info = getHalInfo(handle); 270 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler; 271 272 if (info->cmd_sock != 0) { 273 close(info->cleanup_socks[0]); 274 close(info->cleanup_socks[1]); 275 nl_socket_free(info->cmd_sock); 276 nl_socket_free(info->event_sock); 277 info->cmd_sock = NULL; 278 info->event_sock = NULL; 279 } 280 281 (*cleaned_up_handler)(handle); 282 pthread_mutex_destroy(&info->cb_lock); 283 free(info); 284 285 ALOGI("Internal cleanup completed"); 286 } 287 288 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler) 289 { 290 hal_info *info = getHalInfo(handle); 291 info->cleaned_up_handler = handler; 292 info->clean_up = true; 293 294 pthread_mutex_lock(&info->cb_lock); 295 296 int bad_commands = 0; 297 298 for (int i = 0; i < info->num_event_cb; i++) { 299 cb_info *cbi = &(info->event_cb[i]); 300 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; 301 ALOGE("Command left in event_cb %p:%s", cmd, cmd->getType()); 302 } 303 304 while (info->num_cmd > bad_commands) { 305 int num_cmd = info->num_cmd; 306 cmd_info *cmdi = &(info->cmd[bad_commands]); 307 WifiCommand *cmd = cmdi->cmd; 308 if (cmd != NULL) { 309 ALOGD("Cancelling command %p:%s", cmd, cmd->getType()); 310 pthread_mutex_unlock(&info->cb_lock); 311 cmd->cancel(); 312 pthread_mutex_lock(&info->cb_lock); 313 /* release reference added when command is saved */ 314 cmd->releaseRef(); 315 if (num_cmd == info->num_cmd) { 316 ALOGE("Cancelling command %p:%s did not work", cmd, cmd->getType()); 317 bad_commands++; 318 } 319 } 320 } 321 322 for (int i = 0; i < info->num_event_cb; i++) { 323 cb_info *cbi = &(info->event_cb[i]); 324 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; 325 ALOGE("Leaked command %p", cmd); 326 } 327 328 pthread_mutex_unlock(&info->cb_lock); 329 330 if (write(info->cleanup_socks[0], "T", 1) < 1) { 331 ALOGE("could not write to cleanup socket"); 332 } else { 333 ALOGI("Wifi cleanup completed"); 334 } 335 } 336 337 static int internal_pollin_handler(wifi_handle handle) 338 { 339 hal_info *info = getHalInfo(handle); 340 struct nl_cb *cb = nl_socket_get_cb(info->event_sock); 341 int res = nl_recvmsgs(info->event_sock, cb); 342 // ALOGD("nl_recvmsgs returned %d", res); 343 nl_cb_put(cb); 344 return res; 345 } 346 347 /* Run event handler */ 348 void wifi_event_loop(wifi_handle handle) 349 { 350 hal_info *info = getHalInfo(handle); 351 if (info->in_event_loop) { 352 return; 353 } else { 354 info->in_event_loop = true; 355 } 356 357 pollfd pfd[2]; 358 memset(&pfd[0], 0, sizeof(pollfd) * 2); 359 360 pfd[0].fd = nl_socket_get_fd(info->event_sock); 361 pfd[0].events = POLLIN; 362 pfd[1].fd = info->cleanup_socks[1]; 363 pfd[1].events = POLLIN; 364 365 char buf[2048]; 366 /* TODO: Add support for timeouts */ 367 368 do { 369 int timeout = -1; /* Infinite timeout */ 370 pfd[0].revents = 0; 371 pfd[1].revents = 0; 372 // ALOGI("Polling socket"); 373 int result = poll(pfd, 2, timeout); 374 if (result < 0) { 375 // ALOGE("Error polling socket"); 376 } else if (pfd[0].revents & POLLERR) { 377 ALOGE("POLL Error; error no = %d", errno); 378 int result2 = read(pfd[0].fd, buf, sizeof(buf)); 379 ALOGE("Read after POLL returned %d, error no = %d", result2, errno); 380 } else if (pfd[0].revents & POLLHUP) { 381 ALOGE("Remote side hung up"); 382 break; 383 } else if (pfd[0].revents & POLLIN) { 384 // ALOGI("Found some events!!!"); 385 internal_pollin_handler(handle); 386 } else if (pfd[1].revents & POLLIN) { 387 ALOGI("Got a signal to exit!!!"); 388 int result2 = read(pfd[1].fd, buf, sizeof(buf)); 389 ALOGE("Read after POLL returned %d, error no = %d", result2, errno); 390 } else { 391 ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents); 392 } 393 } while (!info->clean_up); 394 395 ALOGI("Cleaning up"); 396 internal_cleaned_up_handler(handle); 397 } 398 399 /////////////////////////////////////////////////////////////////////////////////////// 400 401 static int internal_no_seq_check(struct nl_msg *msg, void *arg) 402 { 403 return NL_OK; 404 } 405 406 static int internal_valid_message_handler(nl_msg *msg, void *arg) 407 { 408 // ALOGI("got an event"); 409 410 wifi_handle handle = (wifi_handle)arg; 411 hal_info *info = getHalInfo(handle); 412 413 WifiEvent event(msg); 414 int res = event.parse(); 415 if (res < 0) { 416 ALOGE("Failed to parse event: %d", res); 417 return NL_SKIP; 418 } 419 420 int cmd = event.get_cmd(); 421 uint32_t vendor_id = 0; 422 int subcmd = 0; 423 424 if (cmd == NL80211_CMD_VENDOR) { 425 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID); 426 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD); 427 ALOGV("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x", 428 event.get_cmdString(), vendor_id, subcmd); 429 } else { 430 // ALOGV("event received %s", event.get_cmdString()); 431 } 432 433 // ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id); 434 // event.log(); 435 436 bool dispatched = false; 437 438 pthread_mutex_lock(&info->cb_lock); 439 440 for (int i = 0; i < info->num_event_cb; i++) { 441 if (cmd == info->event_cb[i].nl_cmd) { 442 if (cmd == NL80211_CMD_VENDOR 443 && ((vendor_id != info->event_cb[i].vendor_id) 444 || (subcmd != info->event_cb[i].vendor_subcmd))) 445 { 446 /* event for a different vendor, ignore it */ 447 continue; 448 } 449 450 cb_info *cbi = &(info->event_cb[i]); 451 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func; 452 void *cb_arg = cbi->cb_arg; 453 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; 454 if (cmd != NULL) { 455 cmd->addRef(); 456 } 457 458 pthread_mutex_unlock(&info->cb_lock); 459 460 (*cb_func)(msg, cb_arg); 461 if (cmd != NULL) { 462 cmd->releaseRef(); 463 } 464 465 return NL_OK; 466 } 467 } 468 469 pthread_mutex_unlock(&info->cb_lock); 470 return NL_OK; 471 } 472 473 /////////////////////////////////////////////////////////////////////////////////////// 474 475 class GetMulticastIdCommand : public WifiCommand 476 { 477 private: 478 const char *mName; 479 const char *mGroup; 480 int mId; 481 public: 482 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group) 483 : WifiCommand("GetMulticastIdCommand", handle, 0) 484 { 485 mName = name; 486 mGroup = group; 487 mId = -1; 488 } 489 490 int getId() { 491 return mId; 492 } 493 494 virtual int create() { 495 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl"); 496 // ALOGI("ctrl family = %d", nlctrlFamily); 497 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0); 498 if (ret < 0) { 499 return ret; 500 } 501 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName); 502 return ret; 503 } 504 505 virtual int handleResponse(WifiEvent& reply) { 506 507 // ALOGI("handling reponse in %s", __func__); 508 509 struct nlattr **tb = reply.attributes(); 510 struct genlmsghdr *gnlh = reply.header(); 511 struct nlattr *mcgrp = NULL; 512 int i; 513 514 if (!tb[CTRL_ATTR_MCAST_GROUPS]) { 515 ALOGI("No multicast groups found"); 516 return NL_SKIP; 517 } else { 518 // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS])); 519 } 520 521 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { 522 523 // ALOGI("Processing group"); 524 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; 525 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp), 526 nla_len(mcgrp), NULL); 527 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) { 528 continue; 529 } 530 531 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]); 532 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]); 533 534 // ALOGI("Found group name %s", grpName); 535 536 if (strncmp(grpName, mGroup, grpNameLen) != 0) 537 continue; 538 539 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); 540 break; 541 } 542 543 return NL_SKIP; 544 } 545 546 }; 547 548 class SetPnoMacAddrOuiCommand : public WifiCommand { 549 550 private: 551 byte *mOui; 552 feature_set *fset; 553 feature_set *feature_matrix; 554 int *fm_size; 555 int set_size_max; 556 public: 557 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui) 558 : WifiCommand("SetPnoMacAddrOuiCommand", handle, 0) 559 { 560 mOui = scan_oui; 561 } 562 563 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) { 564 int result = request.create(GOOGLE_OUI, subcmd); 565 if (result < 0) { 566 return result; 567 } 568 569 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 570 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN); 571 if (result < 0) { 572 return result; 573 } 574 575 request.attr_end(data); 576 return WIFI_SUCCESS; 577 578 } 579 580 int start() { 581 ALOGD("Sending mac address OUI"); 582 WifiRequest request(familyId(), ifaceId()); 583 int result = createRequest(request, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, mOui); 584 if (result != WIFI_SUCCESS) { 585 ALOGE("failed to create request; result = %d", result); 586 return result; 587 } 588 589 result = requestResponse(request); 590 if (result != WIFI_SUCCESS) { 591 ALOGE("failed to set scanning mac OUI; result = %d", result); 592 } 593 594 return result; 595 } 596 protected: 597 virtual int handleResponse(WifiEvent& reply) { 598 ALOGD("Request complete!"); 599 /* Nothing to do on response! */ 600 return NL_SKIP; 601 } 602 }; 603 604 class SetNodfsCommand : public WifiCommand { 605 606 private: 607 u32 mNoDfs; 608 public: 609 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs) 610 : WifiCommand("SetNodfsCommand", handle, 0) { 611 mNoDfs = nodfs; 612 } 613 virtual int create() { 614 int ret; 615 616 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_NODFS_SET); 617 if (ret < 0) { 618 ALOGE("Can't create message to send to driver - %d", ret); 619 return ret; 620 } 621 622 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); 623 ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs); 624 if (ret < 0) { 625 return ret; 626 } 627 628 mMsg.attr_end(data); 629 return WIFI_SUCCESS; 630 } 631 }; 632 633 class SetCountryCodeCommand : public WifiCommand { 634 private: 635 const char *mCountryCode; 636 public: 637 SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code) 638 : WifiCommand("SetCountryCodeCommand", handle, 0) { 639 mCountryCode = country_code; 640 } 641 virtual int create() { 642 int ret; 643 644 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_COUNTRY_CODE); 645 if (ret < 0) { 646 ALOGE("Can't create message to send to driver - %d", ret); 647 return ret; 648 } 649 650 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); 651 ret = mMsg.put_string(ATTR_COUNTRY_CODE, mCountryCode); 652 if (ret < 0) { 653 return ret; 654 } 655 656 mMsg.attr_end(data); 657 return WIFI_SUCCESS; 658 659 } 660 }; 661 662 class SetRSSIMonitorCommand : public WifiCommand { 663 private: 664 s8 mMax_rssi; 665 s8 mMin_rssi; 666 wifi_rssi_event_handler mHandler; 667 public: 668 SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle, 669 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh) 670 : WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi 671 (min_rssi), mHandler(eh) 672 { 673 } 674 int createRequest(WifiRequest& request, int enable) { 675 int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR); 676 if (result < 0) { 677 return result; 678 } 679 680 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 681 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0)); 682 if (result < 0) { 683 return result; 684 } 685 ALOGD("create request"); 686 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0)); 687 if (result < 0) { 688 return result; 689 } 690 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable); 691 if (result < 0) { 692 return result; 693 } 694 request.attr_end(data); 695 return result; 696 } 697 698 int start() { 699 WifiRequest request(familyId(), ifaceId()); 700 int result = createRequest(request, 1); 701 if (result < 0) { 702 return result; 703 } 704 result = requestResponse(request); 705 if (result < 0) { 706 ALOGI("Failed to set RSSI Monitor, result = %d", result); 707 return result; 708 } 709 ALOGI("Successfully set RSSI monitoring"); 710 registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT); 711 712 713 if (result < 0) { 714 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT); 715 return result; 716 } 717 ALOGI("Done!"); 718 return result; 719 } 720 721 virtual int cancel() { 722 723 WifiRequest request(familyId(), ifaceId()); 724 int result = createRequest(request, 0); 725 if (result != WIFI_SUCCESS) { 726 ALOGE("failed to create request; result = %d", result); 727 } else { 728 result = requestResponse(request); 729 if (result != WIFI_SUCCESS) { 730 ALOGE("failed to stop RSSI monitoring = %d", result); 731 } 732 } 733 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT); 734 return WIFI_SUCCESS; 735 } 736 737 virtual int handleResponse(WifiEvent& reply) { 738 /* Nothing to do on response! */ 739 return NL_SKIP; 740 } 741 742 virtual int handleEvent(WifiEvent& event) { 743 ALOGI("Got a RSSI monitor event"); 744 745 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 746 int len = event.get_vendor_data_len(); 747 748 if (vendor_data == NULL || len == 0) { 749 ALOGI("RSSI monitor: No data"); 750 return NL_SKIP; 751 } 752 /* driver<->HAL event structure */ 753 #define RSSI_MONITOR_EVT_VERSION 1 754 typedef struct { 755 u8 version; 756 s8 cur_rssi; 757 mac_addr BSSID; 758 } rssi_monitor_evt; 759 760 rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data(); 761 762 if (data->version != RSSI_MONITOR_EVT_VERSION) { 763 ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION); 764 return NL_SKIP; 765 } 766 767 if (*mHandler.on_rssi_threshold_breached) { 768 (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi); 769 } else { 770 ALOGW("No RSSI monitor handler registered"); 771 } 772 773 return NL_SKIP; 774 } 775 776 }; 777 778 class GetFeatureSetCommand : public WifiCommand { 779 780 private: 781 int feature_type; 782 feature_set *fset; 783 feature_set *feature_matrix; 784 int *fm_size; 785 int set_size_max; 786 public: 787 GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set, 788 feature_set set_matrix[], int *size, int max_size) 789 : WifiCommand("GetFeatureSetCommand", handle, 0) 790 { 791 feature_type = feature; 792 fset = set; 793 feature_matrix = set_matrix; 794 fm_size = size; 795 set_size_max = max_size; 796 } 797 798 virtual int create() { 799 int ret; 800 801 if(feature_type == FEATURE_SET) { 802 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET); 803 } else if (feature_type == FEATURE_SET_MATRIX) { 804 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX); 805 } else { 806 ALOGE("Unknown feature type %d", feature_type); 807 return -1; 808 } 809 810 if (ret < 0) { 811 ALOGE("Can't create message to send to driver - %d", ret); 812 } 813 814 return ret; 815 } 816 817 protected: 818 virtual int handleResponse(WifiEvent& reply) { 819 820 ALOGV("In GetFeatureSetCommand::handleResponse"); 821 822 if (reply.get_cmd() != NL80211_CMD_VENDOR) { 823 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 824 return NL_SKIP; 825 } 826 827 int id = reply.get_vendor_id(); 828 int subcmd = reply.get_vendor_subcmd(); 829 830 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 831 int len = reply.get_vendor_data_len(); 832 833 ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len); 834 if (vendor_data == NULL || len == 0) { 835 ALOGE("no vendor data in GetFeatureSetCommand response; ignoring it"); 836 return NL_SKIP; 837 } 838 if(feature_type == FEATURE_SET) { 839 void *data = reply.get_vendor_data(); 840 if(!fset) { 841 ALOGE("Buffers pointers not set"); 842 return NL_SKIP; 843 } 844 memcpy(fset, data, min(len, (int) sizeof(*fset))); 845 } else { 846 int num_features_set = 0; 847 int i = 0; 848 849 if(!feature_matrix || !fm_size) { 850 ALOGE("Buffers pointers not set"); 851 return NL_SKIP; 852 } 853 854 for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 855 if (it.get_type() == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) { 856 num_features_set = it.get_u32(); 857 ALOGV("Got feature list with %d concurrent sets", num_features_set); 858 if(set_size_max && (num_features_set > set_size_max)) 859 num_features_set = set_size_max; 860 *fm_size = num_features_set; 861 } else if ((it.get_type() == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) && 862 i < num_features_set) { 863 feature_matrix[i] = it.get_u32(); 864 i++; 865 } else { 866 ALOGW("Ignoring invalid attribute type = %d, size = %d", 867 it.get_type(), it.get_len()); 868 } 869 } 870 871 } 872 return NL_OK; 873 } 874 875 }; 876 877 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group) 878 { 879 GetMulticastIdCommand cmd(handle, name, group); 880 int res = cmd.requestResponse(); 881 if (res < 0) 882 return res; 883 else 884 return cmd.getId(); 885 } 886 887 ///////////////////////////////////////////////////////////////////////// 888 889 static bool is_wifi_interface(const char *name) 890 { 891 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) { 892 /* not a wifi interface; ignore it */ 893 return false; 894 } else { 895 return true; 896 } 897 } 898 899 static int get_interface(const char *name, interface_info *info) 900 { 901 strcpy(info->name, name); 902 info->id = if_nametoindex(name); 903 // ALOGI("found an interface : %s, id = %d", name, info->id); 904 return WIFI_SUCCESS; 905 } 906 907 wifi_error wifi_init_interfaces(wifi_handle handle) 908 { 909 hal_info *info = (hal_info *)handle; 910 911 struct dirent *de; 912 913 DIR *d = opendir("/sys/class/net"); 914 if (d == 0) 915 return WIFI_ERROR_UNKNOWN; 916 917 int n = 0; 918 while ((de = readdir(d))) { 919 if (de->d_name[0] == '.') 920 continue; 921 if (is_wifi_interface(de->d_name) ) { 922 n++; 923 } 924 } 925 926 closedir(d); 927 928 d = opendir("/sys/class/net"); 929 if (d == 0) 930 return WIFI_ERROR_UNKNOWN; 931 932 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n); 933 934 int i = 0; 935 while ((de = readdir(d))) { 936 if (de->d_name[0] == '.') 937 continue; 938 if (is_wifi_interface(de->d_name)) { 939 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info)); 940 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) { 941 free(ifinfo); 942 continue; 943 } 944 ifinfo->handle = handle; 945 info->interfaces[i] = ifinfo; 946 i++; 947 } 948 } 949 950 closedir(d); 951 952 info->num_interfaces = n; 953 return WIFI_SUCCESS; 954 } 955 956 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces) 957 { 958 hal_info *info = (hal_info *)handle; 959 960 *interfaces = (wifi_interface_handle *)info->interfaces; 961 *num = info->num_interfaces; 962 963 return WIFI_SUCCESS; 964 } 965 966 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size) 967 { 968 interface_info *info = (interface_info *)handle; 969 strcpy(name, info->name); 970 return WIFI_SUCCESS; 971 } 972 973 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set) 974 { 975 GetFeatureSetCommand command(handle, FEATURE_SET, set, NULL, NULL, 1); 976 return (wifi_error) command.requestResponse(); 977 } 978 979 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max, 980 feature_set set[], int *set_size) 981 { 982 GetFeatureSetCommand command(handle, FEATURE_SET_MATRIX, NULL, set, set_size, set_size_max); 983 return (wifi_error) command.requestResponse(); 984 } 985 986 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui) 987 { 988 SetPnoMacAddrOuiCommand command(handle, scan_oui); 989 return (wifi_error)command.start(); 990 991 } 992 993 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs) 994 { 995 SetNodfsCommand command(handle, nodfs); 996 return (wifi_error) command.requestResponse(); 997 } 998 999 wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code) 1000 { 1001 SetCountryCodeCommand command(handle, country_code); 1002 return (wifi_error) command.requestResponse(); 1003 } 1004 1005 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle 1006 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh) 1007 { 1008 ALOGD("Start RSSI monitor %d", id); 1009 wifi_handle handle = getWifiHandle(iface); 1010 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh); 1011 wifi_register_cmd(handle, id, cmd); 1012 return (wifi_error)cmd->start(); 1013 } 1014 1015 1016 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface) 1017 { 1018 ALOGD("Stopping RSSI monitor"); 1019 1020 if(id == -1) { 1021 wifi_rssi_event_handler handler; 1022 s8 max_rssi = 0, min_rssi = 0; 1023 wifi_handle handle = getWifiHandle(iface); 1024 memset(&handler, 0, sizeof(handler)); 1025 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, 1026 max_rssi, min_rssi, handler); 1027 cmd->cancel(); 1028 cmd->releaseRef(); 1029 return WIFI_SUCCESS; 1030 } 1031 return wifi_cancel_cmd(id, iface); 1032 } 1033 1034 ///////////////////////////////////////////////////////////////////////////// 1035