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