1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Portions copyright (C) 2017 Broadcom Limited 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #include <stdint.h> 20 #include <fcntl.h> 21 #include <sys/socket.h> 22 #include <netlink/genl/genl.h> 23 #include <netlink/genl/family.h> 24 #include <netlink/genl/ctrl.h> 25 #include <linux/rtnetlink.h> 26 #include <netpacket/packet.h> 27 #include <linux/filter.h> 28 #include <linux/errqueue.h> 29 #include <errno.h> 30 31 #include <linux/pkt_sched.h> 32 #include <netlink/object-api.h> 33 #include <netlink/netlink.h> 34 #include <netlink/socket.h> 35 #include <netlink/attr.h> 36 #include <netlink/handlers.h> 37 #include <netlink/msg.h> 38 39 #include <dirent.h> 40 #include <net/if.h> 41 42 #include "sync.h" 43 44 #define LOG_TAG "WifiHAL" 45 46 #include <log/log.h> 47 48 #include "wifi_hal.h" 49 #include "common.h" 50 #include "cpp_bindings.h" 51 #include "rtt.h" 52 /* 53 BUGBUG: normally, libnl allocates ports for all connections it makes; but 54 being a static library, it doesn't really know how many other netlink connections 55 are made by the same process, if connections come from different shared libraries. 56 These port assignments exist to solve that problem - temporarily. We need to fix 57 libnl to try and allocate ports across the entire process. 58 */ 59 60 #define WIFI_HAL_CMD_SOCK_PORT 644 61 #define WIFI_HAL_EVENT_SOCK_PORT 645 62 63 /* 64 * Defines for wifi_wait_for_driver_ready() 65 * Specify durations between polls and max wait time 66 */ 67 #define POLL_DRIVER_DURATION_US (100000) 68 #define POLL_DRIVER_MAX_TIME_MS (10000) 69 70 static void internal_event_handler(wifi_handle handle, int events); 71 static int internal_no_seq_check(nl_msg *msg, void *arg); 72 static int internal_valid_message_handler(nl_msg *msg, void *arg); 73 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group); 74 static int wifi_add_membership(wifi_handle handle, const char *group); 75 static wifi_error wifi_init_interfaces(wifi_handle handle); 76 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle 77 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh); 78 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface); 79 static wifi_error wifi_set_packet_filter(wifi_interface_handle handle, 80 const u8 *program, u32 len); 81 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle, 82 u32 *version, u32 *max_len); 83 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, u8 enable); 84 85 typedef enum wifi_attr { 86 ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, 87 ANDR_WIFI_ATTRIBUTE_FEATURE_SET, 88 ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, 89 ANDR_WIFI_ATTRIBUTE_NODFS_SET, 90 ANDR_WIFI_ATTRIBUTE_COUNTRY, 91 ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE 92 // Add more attribute here 93 } wifi_attr_t; 94 95 enum wifi_rssi_monitor_attr { 96 RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, 97 RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, 98 RSSI_MONITOR_ATTRIBUTE_START, 99 }; 100 101 enum wifi_apf_attr { 102 APF_ATTRIBUTE_VERSION, 103 APF_ATTRIBUTE_MAX_LEN, 104 APF_ATTRIBUTE_PROGRAM, 105 APF_ATTRIBUTE_PROGRAM_LEN 106 }; 107 108 enum apf_request_type { 109 GET_APF_CAPABILITIES, 110 SET_APF_PROGRAM 111 }; 112 113 /* Initialize/Cleanup */ 114 115 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port) 116 { 117 uint32_t pid = getpid() & 0x3FFFFF; 118 nl_socket_set_local_port(sock, pid + (port << 22)); 119 } 120 121 static nl_sock * wifi_create_nl_socket(int port) 122 { 123 // ALOGI("Creating socket"); 124 struct nl_sock *sock = nl_socket_alloc(); 125 if (sock == NULL) { 126 ALOGE("Could not create handle"); 127 return NULL; 128 } 129 130 wifi_socket_set_local_port(sock, port); 131 132 struct sockaddr *addr = NULL; 133 // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl)); 134 135 // ALOGI("Connecting socket"); 136 if (nl_connect(sock, NETLINK_GENERIC)) { 137 ALOGE("Could not connect handle"); 138 nl_socket_free(sock); 139 return NULL; 140 } 141 142 // ALOGI("Making socket nonblocking"); 143 /* 144 if (nl_socket_set_nonblocking(sock)) { 145 ALOGE("Could make socket non-blocking"); 146 nl_socket_free(sock); 147 return NULL; 148 } 149 */ 150 151 return sock; 152 } 153 154 /*initialize function pointer table with Broadcom HHAL API*/ 155 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) 156 { 157 if (fn == NULL) { 158 return WIFI_ERROR_UNKNOWN; 159 } 160 fn->wifi_initialize = wifi_initialize; 161 fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready; 162 fn->wifi_cleanup = wifi_cleanup; 163 fn->wifi_event_loop = wifi_event_loop; 164 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set; 165 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix; 166 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui; 167 fn->wifi_get_ifaces = wifi_get_ifaces; 168 fn->wifi_get_iface_name = wifi_get_iface_name; 169 fn->wifi_start_gscan = wifi_start_gscan; 170 fn->wifi_stop_gscan = wifi_stop_gscan; 171 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results; 172 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist; 173 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist; 174 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler; 175 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler; 176 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities; 177 fn->wifi_get_link_stats = wifi_get_link_stats; 178 fn->wifi_set_link_stats = wifi_set_link_stats; 179 fn->wifi_clear_link_stats = wifi_clear_link_stats; 180 fn->wifi_get_valid_channels = wifi_get_valid_channels; 181 fn->wifi_rtt_range_request = wifi_rtt_range_request; 182 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel; 183 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities; 184 fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info; 185 fn->wifi_enable_responder = wifi_enable_responder; 186 fn->wifi_disable_responder = wifi_disable_responder; 187 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag; 188 fn->wifi_start_logging = wifi_start_logging; 189 fn->wifi_set_epno_list = wifi_set_epno_list; 190 fn->wifi_reset_epno_list = wifi_reset_epno_list; 191 fn->wifi_set_country_code = wifi_set_country_code; 192 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump; 193 fn->wifi_set_log_handler = wifi_set_log_handler; 194 fn->wifi_reset_log_handler = wifi_reset_log_handler; 195 fn->wifi_set_alert_handler = wifi_set_alert_handler; 196 fn->wifi_reset_alert_handler = wifi_reset_alert_handler; 197 fn->wifi_get_firmware_version = wifi_get_firmware_version; 198 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status; 199 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set; 200 fn->wifi_get_ring_data = wifi_get_ring_data; 201 fn->wifi_get_driver_version = wifi_get_driver_version; 202 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring; 203 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring; 204 fn->wifi_configure_nd_offload = wifi_configure_nd_offload; 205 fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet; 206 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet; 207 fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring; 208 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates; 209 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates; 210 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities; 211 fn->wifi_set_packet_filter = wifi_set_packet_filter; 212 return WIFI_SUCCESS; 213 } 214 215 wifi_error wifi_initialize(wifi_handle *handle) 216 { 217 srand(getpid()); 218 219 ALOGI("Initializing wifi"); 220 hal_info *info = (hal_info *)malloc(sizeof(hal_info)); 221 if (info == NULL) { 222 ALOGE("Could not allocate hal_info"); 223 return WIFI_ERROR_UNKNOWN; 224 } 225 226 memset(info, 0, sizeof(*info)); 227 228 ALOGI("Creating socket"); 229 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) { 230 ALOGE("Could not create cleanup sockets"); 231 free(info); 232 return WIFI_ERROR_UNKNOWN; 233 } 234 235 struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT); 236 if (cmd_sock == NULL) { 237 ALOGE("Could not create handle"); 238 free(info); 239 return WIFI_ERROR_UNKNOWN; 240 } 241 242 struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT); 243 if (event_sock == NULL) { 244 ALOGE("Could not create handle"); 245 nl_socket_free(cmd_sock); 246 free(info); 247 return WIFI_ERROR_UNKNOWN; 248 } 249 250 struct nl_cb *cb = nl_socket_get_cb(event_sock); 251 if (cb == NULL) { 252 ALOGE("Could not create handle"); 253 nl_socket_free(cmd_sock); 254 nl_socket_free(event_sock); 255 free(info); 256 return WIFI_ERROR_UNKNOWN; 257 } 258 259 // ALOGI("cb->refcnt = %d", cb->cb_refcnt); 260 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info); 261 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info); 262 nl_cb_put(cb); 263 264 info->cmd_sock = cmd_sock; 265 info->event_sock = event_sock; 266 info->clean_up = false; 267 info->in_event_loop = false; 268 269 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE); 270 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE; 271 info->num_event_cb = 0; 272 273 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE); 274 info->alloc_cmd = DEFAULT_CMD_SIZE; 275 info->num_cmd = 0; 276 277 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211"); 278 if (info->nl80211_family_id < 0) { 279 ALOGE("Could not resolve nl80211 familty id"); 280 nl_socket_free(cmd_sock); 281 nl_socket_free(event_sock); 282 free(info); 283 return WIFI_ERROR_UNKNOWN; 284 } 285 286 pthread_mutex_init(&info->cb_lock, NULL); 287 288 *handle = (wifi_handle) info; 289 290 if (wifi_init_interfaces(*handle) != WIFI_SUCCESS) { 291 ALOGE("No wifi interface found"); 292 nl_socket_free(cmd_sock); 293 nl_socket_free(event_sock); 294 pthread_mutex_destroy(&info->cb_lock); 295 free(info); 296 return WIFI_ERROR_NOT_AVAILABLE; 297 } 298 299 if ((wifi_add_membership(*handle, "scan") < 0) || 300 (wifi_add_membership(*handle, "mlme") < 0) || 301 (wifi_add_membership(*handle, "regulatory") < 0) || 302 (wifi_add_membership(*handle, "vendor") < 0)) { 303 ALOGE("Add membership failed"); 304 nl_socket_free(cmd_sock); 305 nl_socket_free(event_sock); 306 pthread_mutex_destroy(&info->cb_lock); 307 free(info); 308 return WIFI_ERROR_NOT_AVAILABLE; 309 } 310 311 // ALOGI("Found %d interfaces", info->num_interfaces); 312 313 ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR); 314 return WIFI_SUCCESS; 315 } 316 317 wifi_error wifi_wait_for_driver_ready(void) 318 { 319 // This function will wait to make sure basic client netdev is created 320 // Function times out after 10 seconds 321 int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US; 322 FILE *fd; 323 324 do { 325 if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) { 326 fclose(fd); 327 return WIFI_SUCCESS; 328 } 329 usleep(POLL_DRIVER_DURATION_US); 330 } while(--count > 0); 331 332 ALOGE("Timed out waiting on Driver ready ... "); 333 return WIFI_ERROR_TIMED_OUT; 334 } 335 336 static int wifi_add_membership(wifi_handle handle, const char *group) 337 { 338 hal_info *info = getHalInfo(handle); 339 340 int id = wifi_get_multicast_id(handle, "nl80211", group); 341 if (id < 0) { 342 ALOGE("Could not find group %s", group); 343 return id; 344 } 345 346 int ret = nl_socket_add_membership(info->event_sock, id); 347 if (ret < 0) { 348 ALOGE("Could not add membership to group %s", group); 349 } 350 351 // ALOGI("Successfully added membership for group %s", group); 352 return ret; 353 } 354 355 static void internal_cleaned_up_handler(wifi_handle handle) 356 { 357 hal_info *info = getHalInfo(handle); 358 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler; 359 360 if (info->cmd_sock != 0) { 361 close(info->cleanup_socks[0]); 362 close(info->cleanup_socks[1]); 363 nl_socket_free(info->cmd_sock); 364 nl_socket_free(info->event_sock); 365 info->cmd_sock = NULL; 366 info->event_sock = NULL; 367 } 368 369 (*cleaned_up_handler)(handle); 370 pthread_mutex_destroy(&info->cb_lock); 371 free(info); 372 373 ALOGI("Internal cleanup completed"); 374 } 375 376 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler) 377 { 378 hal_info *info = getHalInfo(handle); 379 char buf[64]; 380 381 info->cleaned_up_handler = handler; 382 if (TEMP_FAILURE_RETRY(write(info->cleanup_socks[0], "Exit", 4)) < 1) { 383 // As a fallback set the cleanup flag to TRUE 384 ALOGE("could not write to the cleanup socket"); 385 } else { 386 // Listen to the response 387 // Hopefully we dont get errors or get hung up 388 // Not much can be done in that case, but assume that 389 // it has rx'ed the Exit message to exit the thread. 390 // As a fallback set the cleanup flag to TRUE 391 memset(buf, 0, sizeof(buf)); 392 ssize_t result = TEMP_FAILURE_RETRY(read(info->cleanup_socks[0], buf, sizeof(buf))); 393 ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__, 394 result, errno, strerror(errno)); 395 if (strncmp(buf, "Done", 4) == 0) { 396 ALOGE("Event processing terminated"); 397 } else { 398 ALOGD("Rx'ed %s", buf); 399 } 400 } 401 info->clean_up = true; 402 pthread_mutex_lock(&info->cb_lock); 403 404 int bad_commands = 0; 405 406 for (int i = 0; i < info->num_event_cb; i++) { 407 cb_info *cbi = &(info->event_cb[i]); 408 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; 409 ALOGI("Command left in event_cb %p:%s", cmd, (cmd ? cmd->getType(): "")); 410 } 411 412 while (info->num_cmd > bad_commands) { 413 int num_cmd = info->num_cmd; 414 cmd_info *cmdi = &(info->cmd[bad_commands]); 415 WifiCommand *cmd = cmdi->cmd; 416 if (cmd != NULL) { 417 ALOGI("Cancelling command %p:%s", cmd, cmd->getType()); 418 pthread_mutex_unlock(&info->cb_lock); 419 cmd->cancel(); 420 pthread_mutex_lock(&info->cb_lock); 421 if (num_cmd == info->num_cmd) { 422 ALOGI("Cancelling command %p:%s did not work", cmd, (cmd ? cmd->getType(): "")); 423 bad_commands++; 424 } 425 /* release reference added when command is saved */ 426 cmd->releaseRef(); 427 } 428 } 429 430 for (int i = 0; i < info->num_event_cb; i++) { 431 cb_info *cbi = &(info->event_cb[i]); 432 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; 433 ALOGE("Leaked command %p", cmd); 434 } 435 pthread_mutex_unlock(&info->cb_lock); 436 internal_cleaned_up_handler(handle); 437 } 438 439 static int internal_pollin_handler(wifi_handle handle) 440 { 441 hal_info *info = getHalInfo(handle); 442 struct nl_cb *cb = nl_socket_get_cb(info->event_sock); 443 int res = nl_recvmsgs(info->event_sock, cb); 444 // ALOGD("nl_recvmsgs returned %d", res); 445 nl_cb_put(cb); 446 return res; 447 } 448 449 /* Run event handler */ 450 void wifi_event_loop(wifi_handle handle) 451 { 452 hal_info *info = getHalInfo(handle); 453 if (info->in_event_loop) { 454 return; 455 } else { 456 info->in_event_loop = true; 457 } 458 459 pollfd pfd[2]; 460 memset(&pfd[0], 0, sizeof(pollfd) * 2); 461 462 pfd[0].fd = nl_socket_get_fd(info->event_sock); 463 pfd[0].events = POLLIN; 464 pfd[1].fd = info->cleanup_socks[1]; 465 pfd[1].events = POLLIN; 466 467 char buf[2048]; 468 /* TODO: Add support for timeouts */ 469 470 do { 471 int timeout = -1; /* Infinite timeout */ 472 pfd[0].revents = 0; 473 pfd[1].revents = 0; 474 // ALOGI("Polling socket"); 475 int result = TEMP_FAILURE_RETRY(poll(pfd, 2, timeout)); 476 if (result < 0) { 477 // ALOGE("Error polling socket"); 478 } else if (pfd[0].revents & POLLERR) { 479 ALOGE("POLL Error; error no = %d (%s)", errno, strerror(errno)); 480 ssize_t result2 = TEMP_FAILURE_RETRY(read(pfd[0].fd, buf, sizeof(buf))); 481 ALOGE("Read after POLL returned %zd, error no = %d (%s)", result2, 482 errno, strerror(errno)); 483 } else if (pfd[0].revents & POLLHUP) { 484 ALOGE("Remote side hung up"); 485 break; 486 } else if (pfd[0].revents & POLLIN) { 487 // ALOGI("Found some events!!!"); 488 internal_pollin_handler(handle); 489 } else if (pfd[1].revents & POLLIN) { 490 memset(buf, 0, sizeof(buf)); 491 ssize_t result2 = TEMP_FAILURE_RETRY(read(pfd[1].fd, buf, sizeof(buf))); 492 ALOGE("%s: Read after POLL returned %zd, error no = %d (%s)", __FUNCTION__, 493 result2, errno, strerror(errno)); 494 if (strncmp(buf, "Exit", 4) == 0) { 495 ALOGD("Got a signal to exit!!!"); 496 if (TEMP_FAILURE_RETRY(write(pfd[1].fd, "Done", 4)) < 1) { 497 ALOGE("could not write to the cleanup socket"); 498 } 499 break; 500 } else { 501 ALOGD("Rx'ed %s on the cleanup socket\n", buf); 502 } 503 } else { 504 ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents); 505 } 506 } while (!info->clean_up); 507 ALOGI("Exit %s", __FUNCTION__); 508 } 509 510 /////////////////////////////////////////////////////////////////////////////////////// 511 512 static int internal_no_seq_check(struct nl_msg *msg, void *arg) 513 { 514 return NL_OK; 515 } 516 517 static int internal_valid_message_handler(nl_msg *msg, void *arg) 518 { 519 // ALOGI("got an event"); 520 521 wifi_handle handle = (wifi_handle)arg; 522 hal_info *info = getHalInfo(handle); 523 524 WifiEvent event(msg); 525 int res = event.parse(); 526 if (res < 0) { 527 ALOGE("Failed to parse event: %d", res); 528 return NL_SKIP; 529 } 530 531 int cmd = event.get_cmd(); 532 uint32_t vendor_id = 0; 533 int subcmd = 0; 534 535 if (cmd == NL80211_CMD_VENDOR) { 536 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID); 537 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD); 538 ALOGV("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x", 539 event.get_cmdString(), vendor_id, subcmd); 540 } else { 541 // ALOGV("event received %s", event.get_cmdString()); 542 } 543 544 // ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id); 545 // event.log(); 546 547 bool dispatched = false; 548 549 pthread_mutex_lock(&info->cb_lock); 550 551 for (int i = 0; i < info->num_event_cb; i++) { 552 if (cmd == info->event_cb[i].nl_cmd) { 553 if (cmd == NL80211_CMD_VENDOR 554 && ((vendor_id != info->event_cb[i].vendor_id) 555 || (subcmd != info->event_cb[i].vendor_subcmd))) 556 { 557 /* event for a different vendor, ignore it */ 558 continue; 559 } 560 561 cb_info *cbi = &(info->event_cb[i]); 562 nl_recvmsg_msg_cb_t cb_func = cbi->cb_func; 563 void *cb_arg = cbi->cb_arg; 564 WifiCommand *cmd = (WifiCommand *)cbi->cb_arg; 565 if (cmd != NULL) { 566 cmd->addRef(); 567 } 568 pthread_mutex_unlock(&info->cb_lock); 569 if (cb_func) 570 (*cb_func)(msg, cb_arg); 571 if (cmd != NULL) { 572 cmd->releaseRef(); 573 } 574 575 return NL_OK; 576 } 577 } 578 579 pthread_mutex_unlock(&info->cb_lock); 580 return NL_OK; 581 } 582 583 /////////////////////////////////////////////////////////////////////////////////////// 584 585 class GetMulticastIdCommand : public WifiCommand 586 { 587 private: 588 const char *mName; 589 const char *mGroup; 590 int mId; 591 public: 592 GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group) 593 : WifiCommand("GetMulticastIdCommand", handle, 0) 594 { 595 mName = name; 596 mGroup = group; 597 mId = -1; 598 } 599 600 int getId() { 601 return mId; 602 } 603 604 virtual int create() { 605 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl"); 606 // ALOGI("ctrl family = %d", nlctrlFamily); 607 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0); 608 if (ret < 0) { 609 return ret; 610 } 611 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName); 612 return ret; 613 } 614 615 virtual int handleResponse(WifiEvent& reply) { 616 617 // ALOGI("handling reponse in %s", __func__); 618 619 struct nlattr **tb = reply.attributes(); 620 struct genlmsghdr *gnlh = reply.header(); 621 struct nlattr *mcgrp = NULL; 622 int i; 623 624 if (!tb[CTRL_ATTR_MCAST_GROUPS]) { 625 ALOGI("No multicast groups found"); 626 return NL_SKIP; 627 } else { 628 // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS])); 629 } 630 631 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { 632 633 // ALOGI("Processing group"); 634 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; 635 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp), 636 nla_len(mcgrp), NULL); 637 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) { 638 continue; 639 } 640 641 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]); 642 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]); 643 644 // ALOGI("Found group name %s", grpName); 645 646 if (strncmp(grpName, mGroup, grpNameLen) != 0) 647 continue; 648 649 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); 650 break; 651 } 652 653 return NL_SKIP; 654 } 655 656 }; 657 658 class SetPnoMacAddrOuiCommand : public WifiCommand { 659 660 private: 661 byte *mOui; 662 feature_set *fset; 663 feature_set *feature_matrix; 664 int *fm_size; 665 int set_size_max; 666 public: 667 SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui) 668 : WifiCommand("SetPnoMacAddrOuiCommand", handle, 0) 669 { 670 mOui = scan_oui; 671 } 672 673 int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) { 674 int result = request.create(GOOGLE_OUI, subcmd); 675 if (result < 0) { 676 return result; 677 } 678 679 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 680 result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN); 681 if (result < 0) { 682 return result; 683 } 684 685 request.attr_end(data); 686 return WIFI_SUCCESS; 687 688 } 689 690 int start() { 691 ALOGD("Sending mac address OUI"); 692 WifiRequest request(familyId(), ifaceId()); 693 int result = createRequest(request, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, mOui); 694 if (result != WIFI_SUCCESS) { 695 ALOGE("failed to create request; result = %d", result); 696 return result; 697 } 698 699 result = requestResponse(request); 700 if (result != WIFI_SUCCESS) { 701 ALOGE("failed to set scanning mac OUI; result = %d", result); 702 } 703 704 return result; 705 } 706 protected: 707 virtual int handleResponse(WifiEvent& reply) { 708 ALOGD("Request complete!"); 709 /* Nothing to do on response! */ 710 return NL_SKIP; 711 } 712 }; 713 714 class SetNodfsCommand : public WifiCommand { 715 716 private: 717 u32 mNoDfs; 718 public: 719 SetNodfsCommand(wifi_interface_handle handle, u32 nodfs) 720 : WifiCommand("SetNodfsCommand", handle, 0) { 721 mNoDfs = nodfs; 722 } 723 virtual int create() { 724 int ret; 725 726 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_NODFS_SET); 727 if (ret < 0) { 728 ALOGE("Can't create message to send to driver - %d", ret); 729 return ret; 730 } 731 732 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); 733 ret = mMsg.put_u32(ANDR_WIFI_ATTRIBUTE_NODFS_SET, mNoDfs); 734 if (ret < 0) { 735 return ret; 736 } 737 738 mMsg.attr_end(data); 739 return WIFI_SUCCESS; 740 } 741 }; 742 743 class SetCountryCodeCommand : public WifiCommand { 744 private: 745 const char *mCountryCode; 746 public: 747 SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code) 748 : WifiCommand("SetCountryCodeCommand", handle, 0) { 749 mCountryCode = country_code; 750 } 751 virtual int create() { 752 int ret; 753 754 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_COUNTRY_CODE); 755 if (ret < 0) { 756 ALOGE("Can't create message to send to driver - %d", ret); 757 return ret; 758 } 759 760 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); 761 ret = mMsg.put_string(ANDR_WIFI_ATTRIBUTE_COUNTRY, mCountryCode); 762 if (ret < 0) { 763 return ret; 764 } 765 766 mMsg.attr_end(data); 767 return WIFI_SUCCESS; 768 769 } 770 }; 771 772 class SetRSSIMonitorCommand : public WifiCommand { 773 private: 774 s8 mMax_rssi; 775 s8 mMin_rssi; 776 wifi_rssi_event_handler mHandler; 777 public: 778 SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle, 779 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh) 780 : WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi 781 (min_rssi), mHandler(eh) 782 { 783 } 784 int createRequest(WifiRequest& request, int enable) { 785 int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR); 786 if (result < 0) { 787 return result; 788 } 789 790 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 791 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0)); 792 if (result < 0) { 793 return result; 794 } 795 ALOGD("create request"); 796 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0)); 797 if (result < 0) { 798 return result; 799 } 800 result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable); 801 if (result < 0) { 802 return result; 803 } 804 request.attr_end(data); 805 return result; 806 } 807 808 int start() { 809 WifiRequest request(familyId(), ifaceId()); 810 int result = createRequest(request, 1); 811 if (result < 0) { 812 return result; 813 } 814 result = requestResponse(request); 815 if (result < 0) { 816 ALOGI("Failed to set RSSI Monitor, result = %d", result); 817 return result; 818 } 819 ALOGI("Successfully set RSSI monitoring"); 820 registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT); 821 822 823 if (result < 0) { 824 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT); 825 return result; 826 } 827 ALOGI("Done!"); 828 return result; 829 } 830 831 virtual int cancel() { 832 833 WifiRequest request(familyId(), ifaceId()); 834 int result = createRequest(request, 0); 835 if (result != WIFI_SUCCESS) { 836 ALOGE("failed to create request; result = %d", result); 837 } else { 838 result = requestResponse(request); 839 if (result != WIFI_SUCCESS) { 840 ALOGE("failed to stop RSSI monitoring = %d", result); 841 } 842 } 843 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT); 844 return WIFI_SUCCESS; 845 } 846 847 virtual int handleResponse(WifiEvent& reply) { 848 /* Nothing to do on response! */ 849 return NL_SKIP; 850 } 851 852 virtual int handleEvent(WifiEvent& event) { 853 ALOGI("Got a RSSI monitor event"); 854 855 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 856 int len = event.get_vendor_data_len(); 857 858 if (vendor_data == NULL || len == 0) { 859 ALOGI("RSSI monitor: No data"); 860 return NL_SKIP; 861 } 862 /* driver<->HAL event structure */ 863 #define RSSI_MONITOR_EVT_VERSION 1 864 typedef struct { 865 u8 version; 866 s8 cur_rssi; 867 mac_addr BSSID; 868 } rssi_monitor_evt; 869 870 rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data(); 871 872 if (data->version != RSSI_MONITOR_EVT_VERSION) { 873 ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION); 874 return NL_SKIP; 875 } 876 877 if (*mHandler.on_rssi_threshold_breached) { 878 (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi); 879 } else { 880 ALOGW("No RSSI monitor handler registered"); 881 } 882 883 return NL_SKIP; 884 } 885 886 }; 887 888 class AndroidPktFilterCommand : public WifiCommand { 889 private: 890 const u8* mProgram; 891 u32 mProgramLen; 892 u32* mVersion; 893 u32* mMaxLen; 894 int mReqType; 895 public: 896 AndroidPktFilterCommand(wifi_interface_handle handle, 897 u32* version, u32* max_len) 898 : WifiCommand("AndroidPktFilterCommand", handle, 0), 899 mVersion(version), mMaxLen(max_len), 900 mReqType(GET_APF_CAPABILITIES) 901 { 902 } 903 904 AndroidPktFilterCommand(wifi_interface_handle handle, 905 const u8* program, u32 len) 906 : WifiCommand("AndroidPktFilterCommand", handle, 0), 907 mProgram(program), mProgramLen(len), 908 mReqType(SET_APF_PROGRAM) 909 { 910 } 911 912 int createRequest(WifiRequest& request) { 913 if (mReqType == SET_APF_PROGRAM) { 914 ALOGI("\n%s: APF set program request\n", __FUNCTION__); 915 return createSetPktFilterRequest(request); 916 } else if (mReqType == GET_APF_CAPABILITIES) { 917 ALOGI("\n%s: APF get capabilities request\n", __FUNCTION__); 918 return createGetPktFilterCapabilitesRequest(request); 919 } else { 920 ALOGE("\n%s Unknown APF request\n", __FUNCTION__); 921 return WIFI_ERROR_NOT_SUPPORTED; 922 } 923 return WIFI_SUCCESS; 924 } 925 926 int createSetPktFilterRequest(WifiRequest& request) { 927 u8 *program = new u8[mProgramLen]; 928 NULL_CHECK_RETURN(program, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 929 int result = request.create(GOOGLE_OUI, APF_SUBCMD_SET_FILTER); 930 if (result < 0) { 931 return result; 932 } 933 934 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 935 result = request.put_u32(APF_ATTRIBUTE_PROGRAM_LEN, mProgramLen); 936 if (result < 0) { 937 return result; 938 } 939 memcpy(program, mProgram, mProgramLen); 940 result = request.put(APF_ATTRIBUTE_PROGRAM, program, mProgramLen); 941 if (result < 0) { 942 return result; 943 } 944 request.attr_end(data); 945 delete[] program; 946 return result; 947 } 948 949 int createGetPktFilterCapabilitesRequest(WifiRequest& request) { 950 int result = request.create(GOOGLE_OUI, APF_SUBCMD_GET_CAPABILITIES); 951 if (result < 0) { 952 return result; 953 } 954 955 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 956 request.attr_end(data); 957 return result; 958 } 959 960 int start() { 961 WifiRequest request(familyId(), ifaceId()); 962 int result = createRequest(request); 963 if (result < 0) { 964 return result; 965 } 966 result = requestResponse(request); 967 if (result < 0) { 968 ALOGI("Request Response failed for APF, result = %d", result); 969 return result; 970 } 971 ALOGI("Done!"); 972 return result; 973 } 974 975 int cancel() { 976 return WIFI_SUCCESS; 977 } 978 979 int handleResponse(WifiEvent& reply) { 980 ALOGD("In SetAPFCommand::handleResponse"); 981 982 if (reply.get_cmd() != NL80211_CMD_VENDOR) { 983 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 984 return NL_SKIP; 985 } 986 987 int id = reply.get_vendor_id(); 988 int subcmd = reply.get_vendor_subcmd(); 989 990 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 991 int len = reply.get_vendor_data_len(); 992 993 ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len); 994 if (vendor_data == NULL || len == 0) { 995 ALOGE("no vendor data in SetAPFCommand response; ignoring it"); 996 return NL_SKIP; 997 } 998 if( mReqType == SET_APF_PROGRAM) { 999 ALOGD("Response recieved for set packet filter command\n"); 1000 } else if (mReqType == GET_APF_CAPABILITIES) { 1001 *mVersion = 0; 1002 *mMaxLen = 0; 1003 ALOGD("Response recieved for get packet filter capabilities command\n"); 1004 for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 1005 if (it.get_type() == APF_ATTRIBUTE_VERSION) { 1006 *mVersion = it.get_u32(); 1007 ALOGI("APF version is %d\n", *mVersion); 1008 } else if (it.get_type() == APF_ATTRIBUTE_MAX_LEN) { 1009 *mMaxLen = it.get_u32(); 1010 ALOGI("APF max len is %d\n", *mMaxLen); 1011 } else { 1012 ALOGE("Ignoring invalid attribute type = %d, size = %d", 1013 it.get_type(), it.get_len()); 1014 } 1015 } 1016 } 1017 return NL_OK; 1018 } 1019 1020 int handleEvent(WifiEvent& event) { 1021 /* No Event to recieve for APF commands */ 1022 return NL_SKIP; 1023 } 1024 }; 1025 1026 class SetNdoffloadCommand : public WifiCommand { 1027 1028 private: 1029 u8 mEnable; 1030 public: 1031 SetNdoffloadCommand(wifi_interface_handle handle, u8 enable) 1032 : WifiCommand("SetNdoffloadCommand", handle, 0) { 1033 mEnable = enable; 1034 } 1035 virtual int create() { 1036 int ret; 1037 1038 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_CONFIG_ND_OFFLOAD); 1039 if (ret < 0) { 1040 ALOGE("Can't create message to send to driver - %d", ret); 1041 return ret; 1042 } 1043 1044 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); 1045 ret = mMsg.put_u8(ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE, mEnable); 1046 if (ret < 0) { 1047 return ret; 1048 } 1049 1050 mMsg.attr_end(data); 1051 return WIFI_SUCCESS; 1052 } 1053 }; 1054 1055 class GetFeatureSetCommand : public WifiCommand { 1056 1057 private: 1058 int feature_type; 1059 feature_set *fset; 1060 feature_set *feature_matrix; 1061 int *fm_size; 1062 int set_size_max; 1063 public: 1064 GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set, 1065 feature_set set_matrix[], int *size, int max_size) 1066 : WifiCommand("GetFeatureSetCommand", handle, 0) 1067 { 1068 feature_type = feature; 1069 fset = set; 1070 feature_matrix = set_matrix; 1071 fm_size = size; 1072 set_size_max = max_size; 1073 } 1074 1075 virtual int create() { 1076 int ret; 1077 1078 if(feature_type == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) { 1079 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET); 1080 } else if (feature_type == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) { 1081 ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX); 1082 } else { 1083 ALOGE("Unknown feature type %d", feature_type); 1084 return -1; 1085 } 1086 1087 if (ret < 0) { 1088 ALOGE("Can't create message to send to driver - %d", ret); 1089 } 1090 1091 return ret; 1092 } 1093 1094 protected: 1095 virtual int handleResponse(WifiEvent& reply) { 1096 1097 ALOGV("In GetFeatureSetCommand::handleResponse"); 1098 1099 if (reply.get_cmd() != NL80211_CMD_VENDOR) { 1100 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 1101 return NL_SKIP; 1102 } 1103 1104 int id = reply.get_vendor_id(); 1105 int subcmd = reply.get_vendor_subcmd(); 1106 1107 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 1108 int len = reply.get_vendor_data_len(); 1109 1110 ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len); 1111 if (vendor_data == NULL || len == 0) { 1112 ALOGE("no vendor data in GetFeatureSetCommand response; ignoring it"); 1113 return NL_SKIP; 1114 } 1115 if(feature_type == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) { 1116 void *data = reply.get_vendor_data(); 1117 if(!fset) { 1118 ALOGE("Buffers pointers not set"); 1119 return NL_SKIP; 1120 } 1121 memcpy(fset, data, min(len, (int) sizeof(*fset))); 1122 } else { 1123 int num_features_set = 0; 1124 int i = 0; 1125 1126 if(!feature_matrix || !fm_size) { 1127 ALOGE("Buffers pointers not set"); 1128 return NL_SKIP; 1129 } 1130 1131 for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 1132 if (it.get_type() == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) { 1133 num_features_set = it.get_u32(); 1134 ALOGV("Got feature list with %d concurrent sets", num_features_set); 1135 if(set_size_max && (num_features_set > set_size_max)) 1136 num_features_set = set_size_max; 1137 *fm_size = num_features_set; 1138 } else if ((it.get_type() == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) && 1139 i < num_features_set) { 1140 feature_matrix[i] = it.get_u32(); 1141 i++; 1142 } else { 1143 ALOGW("Ignoring invalid attribute type = %d, size = %d", 1144 it.get_type(), it.get_len()); 1145 } 1146 } 1147 1148 } 1149 return NL_OK; 1150 } 1151 1152 }; 1153 1154 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group) 1155 { 1156 GetMulticastIdCommand cmd(handle, name, group); 1157 int res = cmd.requestResponse(); 1158 if (res < 0) 1159 return res; 1160 else 1161 return cmd.getId(); 1162 } 1163 1164 ///////////////////////////////////////////////////////////////////////// 1165 1166 static bool is_wifi_interface(const char *name) 1167 { 1168 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) { 1169 /* not a wifi interface; ignore it */ 1170 return false; 1171 } else { 1172 return true; 1173 } 1174 } 1175 1176 static int get_interface(const char *name, interface_info *info) 1177 { 1178 strcpy(info->name, name); 1179 info->id = if_nametoindex(name); 1180 // ALOGI("found an interface : %s, id = %d", name, info->id); 1181 return WIFI_SUCCESS; 1182 } 1183 1184 wifi_error wifi_init_interfaces(wifi_handle handle) 1185 { 1186 hal_info *info = (hal_info *)handle; 1187 1188 struct dirent *de; 1189 1190 DIR *d = opendir("/sys/class/net"); 1191 if (d == 0) 1192 return WIFI_ERROR_UNKNOWN; 1193 1194 int n = 0; 1195 while ((de = readdir(d))) { 1196 if (de->d_name[0] == '.') 1197 continue; 1198 if (is_wifi_interface(de->d_name) ) { 1199 n++; 1200 } 1201 } 1202 1203 closedir(d); 1204 1205 if (n == 0) 1206 return WIFI_ERROR_NOT_AVAILABLE; 1207 1208 d = opendir("/sys/class/net"); 1209 if (d == 0) 1210 return WIFI_ERROR_UNKNOWN; 1211 1212 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n); 1213 1214 int i = 0; 1215 while ((de = readdir(d))) { 1216 if (de->d_name[0] == '.') 1217 continue; 1218 if (is_wifi_interface(de->d_name)) { 1219 interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info)); 1220 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) { 1221 free(ifinfo); 1222 continue; 1223 } 1224 ifinfo->handle = handle; 1225 info->interfaces[i] = ifinfo; 1226 i++; 1227 } 1228 } 1229 1230 closedir(d); 1231 1232 info->num_interfaces = n; 1233 return WIFI_SUCCESS; 1234 } 1235 1236 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces) 1237 { 1238 hal_info *info = (hal_info *)handle; 1239 1240 *interfaces = (wifi_interface_handle *)info->interfaces; 1241 *num = info->num_interfaces; 1242 1243 return WIFI_SUCCESS; 1244 } 1245 1246 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size) 1247 { 1248 interface_info *info = (interface_info *)handle; 1249 strcpy(name, info->name); 1250 return WIFI_SUCCESS; 1251 } 1252 1253 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set) 1254 { 1255 GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, set, NULL, NULL, 1); 1256 return (wifi_error) command.requestResponse(); 1257 } 1258 1259 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max, 1260 feature_set set[], int *set_size) 1261 { 1262 GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, NULL, 1263 set, set_size, set_size_max); 1264 return (wifi_error) command.requestResponse(); 1265 } 1266 1267 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui) 1268 { 1269 SetPnoMacAddrOuiCommand command(handle, scan_oui); 1270 return (wifi_error)command.start(); 1271 1272 } 1273 1274 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs) 1275 { 1276 SetNodfsCommand command(handle, nodfs); 1277 return (wifi_error) command.requestResponse(); 1278 } 1279 1280 wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code) 1281 { 1282 SetCountryCodeCommand command(handle, country_code); 1283 return (wifi_error) command.requestResponse(); 1284 } 1285 1286 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle 1287 iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh) 1288 { 1289 ALOGD("Start RSSI monitor %d", id); 1290 wifi_handle handle = getWifiHandle(iface); 1291 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh); 1292 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1293 wifi_error result = wifi_register_cmd(handle, id, cmd); 1294 if (result != WIFI_SUCCESS) { 1295 cmd->releaseRef(); 1296 return result; 1297 } 1298 result = (wifi_error)cmd->start(); 1299 if (result != WIFI_SUCCESS) { 1300 wifi_unregister_cmd(handle, id); 1301 cmd->releaseRef(); 1302 return result; 1303 } 1304 return result; 1305 } 1306 1307 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface) 1308 { 1309 ALOGD("Stopping RSSI monitor"); 1310 1311 if(id == -1) { 1312 wifi_rssi_event_handler handler; 1313 s8 max_rssi = 0, min_rssi = 0; 1314 wifi_handle handle = getWifiHandle(iface); 1315 memset(&handler, 0, sizeof(handler)); 1316 SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, 1317 max_rssi, min_rssi, handler); 1318 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1319 cmd->cancel(); 1320 cmd->releaseRef(); 1321 return WIFI_SUCCESS; 1322 } 1323 return wifi_cancel_cmd(id, iface); 1324 } 1325 1326 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle, 1327 u32 *version, u32 *max_len) 1328 { 1329 ALOGD("Getting APF capabilities, halHandle = %p\n", handle); 1330 AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, version, max_len); 1331 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1332 wifi_error result = (wifi_error)cmd->start(); 1333 if (result == WIFI_SUCCESS) { 1334 ALOGD("Getting APF capability, version = %d, max_len = %d\n", *version, *max_len); 1335 } 1336 cmd->releaseRef(); 1337 return result; 1338 } 1339 1340 static wifi_error wifi_set_packet_filter(wifi_interface_handle handle, 1341 const u8 *program, u32 len) 1342 { 1343 ALOGD("Setting APF program, halHandle = %p\n", handle); 1344 AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, program, len); 1345 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1346 wifi_error result = (wifi_error)cmd->start(); 1347 cmd->releaseRef(); 1348 return result; 1349 } 1350 1351 static wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable) 1352 { 1353 SetNdoffloadCommand command(handle, enable); 1354 return (wifi_error) command.requestResponse(); 1355 } 1356 1357 ///////////////////////////////////////////////////////////////////////////// 1358