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