1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdint.h> 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <sys/socket.h> 21 #include <netlink/genl/genl.h> 22 #include <netlink/genl/family.h> 23 #include <netlink/genl/ctrl.h> 24 #include <linux/rtnetlink.h> 25 #include <netpacket/packet.h> 26 #include <linux/filter.h> 27 #include <linux/errqueue.h> 28 29 #include <linux/pkt_sched.h> 30 #include <netlink/object-api.h> 31 #include <netlink/netlink.h> 32 #include <netlink/socket.h> 33 #include <netlink-types.h> 34 35 #include "nl80211_copy.h" 36 37 #include <dirent.h> 38 #include <net/if.h> 39 #include <netinet/in.h> 40 41 #include "sync.h" 42 43 #define LOG_TAG "WifiHAL" 44 45 #include "hardware_legacy/wifi.h" 46 47 #include "wifi_hal.h" 48 #include "common.h" 49 #include "cpp_bindings.h" 50 #include "ifaceeventhandler.h" 51 #include "wifiloggercmd.h" 52 #include "vendor_definitions.h" 53 54 /* 55 BUGBUG: normally, libnl allocates ports for all connections it makes; but 56 being a static library, it doesn't really know how many other netlink 57 connections are made by the same process, if connections come from different 58 shared libraries. These port assignments exist to solve that 59 problem - temporarily. We need to fix libnl to try and allocate ports across 60 the entire process. 61 */ 62 63 #define WIFI_HAL_CMD_SOCK_PORT 644 64 #define WIFI_HAL_EVENT_SOCK_PORT 645 65 66 static void internal_event_handler(wifi_handle handle, int events, 67 struct nl_sock *sock); 68 static int internal_valid_message_handler(nl_msg *msg, void *arg); 69 static int user_sock_message_handler(nl_msg *msg, void *arg); 70 static int wifi_get_multicast_id(wifi_handle handle, const char *name, 71 const char *group); 72 static int wifi_add_membership(wifi_handle handle, const char *group); 73 static wifi_error wifi_init_interfaces(wifi_handle handle); 74 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface, 75 const u8 *program, u32 len); 76 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle, 77 u32 *version, u32 *max_len); 78 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, 79 u8 enable); 80 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface, 81 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt); 82 83 /* Initialize/Cleanup */ 84 85 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name) 86 { 87 hal_info *info = (hal_info *)handle; 88 for (int i=0;i<info->num_interfaces;i++) 89 { 90 if (!strcmp(info->interfaces[i]->name, name)) 91 { 92 return ((wifi_interface_handle )(info->interfaces)[i]); 93 } 94 } 95 return NULL; 96 } 97 98 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port) 99 { 100 /* Release local port pool maintained by libnl and assign a own port 101 * identifier to the socket. 102 */ 103 nl_socket_set_local_port(sock, ((uint32_t)getpid() & 0x3FFFFFU) | (port << 22)); 104 } 105 106 static nl_sock * wifi_create_nl_socket(int port, int protocol) 107 { 108 // ALOGI("Creating socket"); 109 struct nl_sock *sock = nl_socket_alloc(); 110 if (sock == NULL) { 111 ALOGE("Failed to create NL socket"); 112 return NULL; 113 } 114 115 wifi_socket_set_local_port(sock, port); 116 117 if (nl_connect(sock, protocol)) { 118 ALOGE("Could not connect handle"); 119 nl_socket_free(sock); 120 return NULL; 121 } 122 123 return sock; 124 } 125 126 int ack_handler(struct nl_msg *msg, void *arg) 127 { 128 int *err = (int *)arg; 129 *err = 0; 130 return NL_STOP; 131 } 132 133 int finish_handler(struct nl_msg *msg, void *arg) 134 { 135 int *ret = (int *)arg; 136 *ret = 0; 137 return NL_SKIP; 138 } 139 140 int error_handler(struct sockaddr_nl *nla, 141 struct nlmsgerr *err, void *arg) 142 { 143 int *ret = (int *)arg; 144 *ret = err->error; 145 146 ALOGV("%s invoked with error: %d", __func__, err->error); 147 return NL_SKIP; 148 } 149 static int no_seq_check(struct nl_msg *msg, void *arg) 150 { 151 return NL_OK; 152 } 153 154 static wifi_error acquire_supported_features(wifi_interface_handle iface, 155 feature_set *set) 156 { 157 int ret = 0; 158 interface_info *iinfo = getIfaceInfo(iface); 159 wifi_handle handle = getWifiHandle(iface); 160 *set = 0; 161 162 WifihalGeneric supportedFeatures(handle, 0, 163 OUI_QCA, 164 QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES); 165 166 /* create the message */ 167 ret = supportedFeatures.create(); 168 if (ret < 0) 169 goto cleanup; 170 171 ret = supportedFeatures.set_iface_id(iinfo->name); 172 if (ret < 0) 173 goto cleanup; 174 175 ret = supportedFeatures.requestResponse(); 176 if (ret != 0) { 177 ALOGE("%s: requestResponse Error:%d",__func__, ret); 178 goto cleanup; 179 } 180 181 supportedFeatures.getResponseparams(set); 182 183 cleanup: 184 return (wifi_error)ret; 185 } 186 187 static wifi_error get_firmware_bus_max_size_supported( 188 wifi_interface_handle iface) 189 { 190 int ret = 0; 191 interface_info *iinfo = getIfaceInfo(iface); 192 wifi_handle handle = getWifiHandle(iface); 193 hal_info *info = (hal_info *)handle; 194 195 WifihalGeneric busSizeSupported(handle, 0, 196 OUI_QCA, 197 QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE); 198 199 /* create the message */ 200 ret = busSizeSupported.create(); 201 if (ret < 0) 202 goto cleanup; 203 204 ret = busSizeSupported.set_iface_id(iinfo->name); 205 if (ret < 0) 206 goto cleanup; 207 208 ret = busSizeSupported.requestResponse(); 209 if (ret != 0) { 210 ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret); 211 goto cleanup; 212 } 213 info->firmware_bus_max_size = busSizeSupported.getBusSize(); 214 215 cleanup: 216 return (wifi_error)ret; 217 } 218 219 static wifi_error wifi_init_user_sock(hal_info *info) 220 { 221 struct nl_sock *user_sock = 222 wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK); 223 if (user_sock == NULL) { 224 ALOGE("Could not create diag sock"); 225 return WIFI_ERROR_UNKNOWN; 226 } 227 228 /* Set the socket buffer size */ 229 if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) { 230 ALOGE("Could not set size for user_sock: %s", 231 strerror(errno)); 232 /* continue anyway with the default (smaller) buffer */ 233 } 234 else { 235 ALOGV("nl_socket_set_buffer_size successful for user_sock"); 236 } 237 238 struct nl_cb *cb = nl_socket_get_cb(user_sock); 239 if (cb == NULL) { 240 ALOGE("Could not get cb"); 241 return WIFI_ERROR_UNKNOWN; 242 } 243 244 info->user_sock_arg = 1; 245 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); 246 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg); 247 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg); 248 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg); 249 250 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info); 251 nl_cb_put(cb); 252 253 int ret = nl_socket_add_membership(user_sock, 1); 254 if (ret < 0) { 255 ALOGE("Could not add membership"); 256 return WIFI_ERROR_UNKNOWN; 257 } 258 259 info->user_sock = user_sock; 260 ALOGV("Initiialized diag sock successfully"); 261 return WIFI_SUCCESS; 262 } 263 264 /*initialize function pointer table with Qualcomm HAL API*/ 265 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) { 266 if (fn == NULL) { 267 return WIFI_ERROR_UNKNOWN; 268 } 269 270 fn->wifi_initialize = wifi_initialize; 271 fn->wifi_cleanup = wifi_cleanup; 272 fn->wifi_event_loop = wifi_event_loop; 273 fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set; 274 fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix; 275 fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui; 276 fn->wifi_get_ifaces = wifi_get_ifaces; 277 fn->wifi_get_iface_name = wifi_get_iface_name; 278 fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler; 279 fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler; 280 fn->wifi_start_gscan = wifi_start_gscan; 281 fn->wifi_stop_gscan = wifi_stop_gscan; 282 fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results; 283 fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist; 284 fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist; 285 fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler; 286 fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler; 287 fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities; 288 fn->wifi_set_link_stats = wifi_set_link_stats; 289 fn->wifi_get_link_stats = wifi_get_link_stats; 290 fn->wifi_clear_link_stats = wifi_clear_link_stats; 291 fn->wifi_get_valid_channels = wifi_get_valid_channels; 292 fn->wifi_rtt_range_request = wifi_rtt_range_request; 293 fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel; 294 fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities; 295 fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info; 296 fn->wifi_enable_responder = wifi_enable_responder; 297 fn->wifi_disable_responder = wifi_disable_responder; 298 fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag; 299 fn->wifi_start_logging = wifi_start_logging; 300 fn->wifi_set_epno_list = wifi_set_epno_list; 301 fn->wifi_reset_epno_list = wifi_reset_epno_list; 302 fn->wifi_set_country_code = wifi_set_country_code; 303 fn->wifi_enable_tdls = wifi_enable_tdls; 304 fn->wifi_disable_tdls = wifi_disable_tdls; 305 fn->wifi_get_tdls_status = wifi_get_tdls_status; 306 fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities; 307 fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump; 308 fn->wifi_set_log_handler = wifi_set_log_handler; 309 fn->wifi_reset_log_handler = wifi_reset_log_handler; 310 fn->wifi_set_alert_handler = wifi_set_alert_handler; 311 fn->wifi_reset_alert_handler = wifi_reset_alert_handler; 312 fn->wifi_get_firmware_version = wifi_get_firmware_version; 313 fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status; 314 fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set; 315 fn->wifi_get_ring_data = wifi_get_ring_data; 316 fn->wifi_get_driver_version = wifi_get_driver_version; 317 fn->wifi_set_passpoint_list = wifi_set_passpoint_list; 318 fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list; 319 fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist; 320 fn->wifi_set_lci = wifi_set_lci; 321 fn->wifi_set_lcr = wifi_set_lcr; 322 fn->wifi_start_sending_offloaded_packet = 323 wifi_start_sending_offloaded_packet; 324 fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet; 325 fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring; 326 fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring; 327 fn->wifi_nan_enable_request = nan_enable_request; 328 fn->wifi_nan_disable_request = nan_disable_request; 329 fn->wifi_nan_publish_request = nan_publish_request; 330 fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request; 331 fn->wifi_nan_subscribe_request = nan_subscribe_request; 332 fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request; 333 fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request; 334 fn->wifi_nan_stats_request = nan_stats_request; 335 fn->wifi_nan_config_request = nan_config_request; 336 fn->wifi_nan_tca_request = nan_tca_request; 337 fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request; 338 fn->wifi_nan_register_handler = nan_register_handler; 339 fn->wifi_nan_get_version = nan_get_version; 340 fn->wifi_set_packet_filter = wifi_set_packet_filter; 341 fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities; 342 fn->wifi_nan_get_capabilities = nan_get_capabilities; 343 fn->wifi_configure_nd_offload = wifi_configure_nd_offload; 344 fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump; 345 fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats; 346 fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring; 347 fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates; 348 fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates; 349 350 return WIFI_SUCCESS; 351 } 352 353 wifi_error wifi_initialize(wifi_handle *handle) 354 { 355 int err = 0; 356 bool driver_loaded = false; 357 wifi_error ret = WIFI_SUCCESS; 358 wifi_interface_handle iface_handle; 359 struct nl_sock *cmd_sock = NULL; 360 struct nl_sock *event_sock = NULL; 361 struct nl_cb *cb = NULL; 362 363 ALOGI("Initializing wifi"); 364 hal_info *info = (hal_info *)malloc(sizeof(hal_info)); 365 if (info == NULL) { 366 ALOGE("Could not allocate hal_info"); 367 return WIFI_ERROR_OUT_OF_MEMORY; 368 } 369 370 memset(info, 0, sizeof(*info)); 371 372 cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT, 373 NETLINK_GENERIC); 374 if (cmd_sock == NULL) { 375 ALOGE("Failed to create command socket port"); 376 ret = WIFI_ERROR_UNKNOWN; 377 goto unload; 378 } 379 380 /* Set the socket buffer size */ 381 if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) { 382 ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s", 383 strerror(errno)); 384 /* continue anyway with the default (smaller) buffer */ 385 } 386 387 event_sock = 388 wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC); 389 if (event_sock == NULL) { 390 ALOGE("Failed to create event socket port"); 391 ret = WIFI_ERROR_UNKNOWN; 392 goto unload; 393 } 394 395 /* Set the socket buffer size */ 396 if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) { 397 ALOGE("Could not set nl_socket RX buffer size for event_sock: %s", 398 strerror(errno)); 399 /* continue anyway with the default (smaller) buffer */ 400 } 401 402 cb = nl_socket_get_cb(event_sock); 403 if (cb == NULL) { 404 ALOGE("Failed to get NL control block for event socket port"); 405 ret = WIFI_ERROR_UNKNOWN; 406 goto unload; 407 } 408 409 err = 1; 410 nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL); 411 nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); 412 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); 413 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); 414 415 nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, 416 info); 417 nl_cb_put(cb); 418 419 info->cmd_sock = cmd_sock; 420 info->event_sock = event_sock; 421 info->clean_up = false; 422 info->in_event_loop = false; 423 424 info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE); 425 if (info->event_cb == NULL) { 426 ALOGE("Could not allocate event_cb"); 427 ret = WIFI_ERROR_OUT_OF_MEMORY; 428 goto unload; 429 } 430 info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE; 431 info->num_event_cb = 0; 432 433 info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE); 434 if (info->cmd == NULL) { 435 ALOGE("Could not allocate cmd info"); 436 ret = WIFI_ERROR_OUT_OF_MEMORY; 437 goto unload; 438 } 439 info->alloc_cmd = DEFAULT_CMD_SIZE; 440 info->num_cmd = 0; 441 442 info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211"); 443 if (info->nl80211_family_id < 0) { 444 ALOGE("Could not resolve nl80211 familty id"); 445 ret = WIFI_ERROR_UNKNOWN; 446 goto unload; 447 } 448 449 pthread_mutex_init(&info->cb_lock, NULL); 450 pthread_mutex_init(&info->pkt_fate_stats_lock, NULL); 451 452 *handle = (wifi_handle) info; 453 454 wifi_add_membership(*handle, "scan"); 455 wifi_add_membership(*handle, "mlme"); 456 wifi_add_membership(*handle, "regulatory"); 457 wifi_add_membership(*handle, "vendor"); 458 459 ret = wifi_init_user_sock(info); 460 if (ret != WIFI_SUCCESS) { 461 ALOGE("Failed to alloc user socket"); 462 goto unload; 463 } 464 465 if (!is_wifi_driver_loaded()) { 466 ret = (wifi_error)wifi_load_driver(); 467 if(ret != WIFI_SUCCESS) { 468 ALOGE("%s Failed to load wifi driver : %d\n", __func__, ret); 469 goto unload; 470 } 471 driver_loaded = true; 472 } 473 474 ret = wifi_init_interfaces(*handle); 475 if (ret != WIFI_SUCCESS) { 476 ALOGE("Failed to init interfaces"); 477 goto unload; 478 } 479 480 if (info->num_interfaces == 0) { 481 ALOGE("No interfaces found"); 482 ret = WIFI_ERROR_UNINITIALIZED; 483 goto unload; 484 } 485 486 iface_handle = wifi_get_iface_handle((info->interfaces[0])->handle, 487 (info->interfaces[0])->name); 488 if (iface_handle == NULL) { 489 int i; 490 for (i = 0; i < info->num_interfaces; i++) 491 { 492 free(info->interfaces[i]); 493 } 494 ALOGE("%s no iface with %s\n", __func__, info->interfaces[0]->name); 495 goto unload; 496 } 497 498 ret = acquire_supported_features(iface_handle, 499 &info->supported_feature_set); 500 if (ret != WIFI_SUCCESS) { 501 ALOGI("Failed to get supported feature set : %d", ret); 502 //acquire_supported_features failure is acceptable condition as legacy 503 //drivers might not support the required vendor command. So, do not 504 //consider it as failure of wifi_initialize 505 ret = WIFI_SUCCESS; 506 } 507 508 ret = get_firmware_bus_max_size_supported(iface_handle); 509 if (ret != WIFI_SUCCESS) { 510 ALOGE("Failed to get supported bus size, error : %d", ret); 511 info->firmware_bus_max_size = 1520; 512 } 513 514 ret = wifi_logger_ring_buffers_init(info); 515 if (ret != WIFI_SUCCESS) { 516 ALOGE("Wifi Logger Ring Initialization Failed"); 517 goto unload; 518 } 519 520 info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s)); 521 if (!info->pkt_stats) { 522 ALOGE("%s: malloc Failed for size: %zu", 523 __FUNCTION__, sizeof(struct pkt_stats_s)); 524 ret = WIFI_ERROR_OUT_OF_MEMORY; 525 goto unload; 526 } 527 528 info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU 529 * PKT_STATS_BUF_SIZE; 530 531 info->rx_aggr_pkts = 532 (wifi_ring_buffer_entry *)malloc(info->rx_buf_size_allocated); 533 if (!info->rx_aggr_pkts) { 534 ALOGE("%s: malloc Failed for size: %d", 535 __FUNCTION__, info->rx_buf_size_allocated); 536 ret = WIFI_ERROR_OUT_OF_MEMORY; 537 info->rx_buf_size_allocated = 0; 538 goto unload; 539 } 540 memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated); 541 542 info->exit_sockets[0] = -1; 543 info->exit_sockets[1] = -1; 544 545 if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) { 546 ALOGE("Failed to create exit socket pair"); 547 ret = WIFI_ERROR_UNKNOWN; 548 goto unload; 549 } 550 551 ALOGV("Initializing Gscan Event Handlers"); 552 ret = initializeGscanHandlers(info); 553 if (ret != WIFI_SUCCESS) { 554 ALOGE("Initializing Gscan Event Handlers Failed"); 555 goto unload; 556 } 557 558 ret = initializeRSSIMonitorHandler(info); 559 if (ret != WIFI_SUCCESS) { 560 ALOGE("Initializing RSSI Event Handler Failed"); 561 goto unload; 562 } 563 564 ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported" 565 " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set); 566 567 unload: 568 if (ret != WIFI_SUCCESS) { 569 if (cmd_sock) 570 nl_socket_free(cmd_sock); 571 if (event_sock) 572 nl_socket_free(event_sock); 573 if (info) { 574 if (info->cmd) free(info->cmd); 575 if (info->event_cb) free(info->event_cb); 576 if (info->user_sock) nl_socket_free(info->user_sock); 577 if (info->pkt_stats) free(info->pkt_stats); 578 if (info->rx_aggr_pkts) free(info->rx_aggr_pkts); 579 cleanupGscanHandlers(info); 580 cleanupRSSIMonitorHandler(info); 581 free(info); 582 } 583 } 584 585 if (driver_loaded) 586 wifi_unload_driver(); 587 return ret; 588 } 589 590 static int wifi_add_membership(wifi_handle handle, const char *group) 591 { 592 hal_info *info = getHalInfo(handle); 593 594 int id = wifi_get_multicast_id(handle, "nl80211", group); 595 if (id < 0) { 596 ALOGE("Could not find group %s", group); 597 return id; 598 } 599 600 int ret = nl_socket_add_membership(info->event_sock, id); 601 if (ret < 0) { 602 ALOGE("Could not add membership to group %s", group); 603 } 604 605 return ret; 606 } 607 608 static void internal_cleaned_up_handler(wifi_handle handle) 609 { 610 hal_info *info = getHalInfo(handle); 611 wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler; 612 613 if (info->cmd_sock != 0) { 614 nl_socket_free(info->cmd_sock); 615 nl_socket_free(info->event_sock); 616 info->cmd_sock = NULL; 617 info->event_sock = NULL; 618 } 619 620 if (info->user_sock != 0) { 621 nl_socket_free(info->user_sock); 622 info->user_sock = NULL; 623 } 624 625 if (info->pkt_stats) 626 free(info->pkt_stats); 627 if (info->rx_aggr_pkts) 628 free(info->rx_aggr_pkts); 629 wifi_logger_ring_buffers_deinit(info); 630 cleanupGscanHandlers(info); 631 cleanupRSSIMonitorHandler(info); 632 633 if (info->exit_sockets[0] >= 0) { 634 close(info->exit_sockets[0]); 635 info->exit_sockets[0] = -1; 636 } 637 638 if (info->exit_sockets[1] >= 0) { 639 close(info->exit_sockets[1]); 640 info->exit_sockets[1] = -1; 641 } 642 643 if (info->pkt_fate_stats) { 644 free(info->pkt_fate_stats); 645 info->pkt_fate_stats = NULL; 646 } 647 648 (*cleaned_up_handler)(handle); 649 pthread_mutex_destroy(&info->cb_lock); 650 pthread_mutex_destroy(&info->pkt_fate_stats_lock); 651 free(info); 652 } 653 654 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler) 655 { 656 if (!handle) { 657 ALOGE("Handle is null"); 658 return; 659 } 660 661 hal_info *info = getHalInfo(handle); 662 info->cleaned_up_handler = handler; 663 info->clean_up = true; 664 665 TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1)); 666 ALOGI("Sent msg on exit sock to unblock poll()"); 667 } 668 669 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock) 670 { 671 struct nl_cb *cb = nl_socket_get_cb(sock); 672 673 int res = nl_recvmsgs(sock, cb); 674 if(res) 675 ALOGE("Error :%d while reading nl msg", res); 676 nl_cb_put(cb); 677 return res; 678 } 679 680 static void internal_event_handler(wifi_handle handle, int events, 681 struct nl_sock *sock) 682 { 683 if (events & POLLERR) { 684 ALOGE("Error reading from socket"); 685 internal_pollin_handler(handle, sock); 686 } else if (events & POLLHUP) { 687 ALOGE("Remote side hung up"); 688 } else if (events & POLLIN) { 689 //ALOGI("Found some events!!!"); 690 internal_pollin_handler(handle, sock); 691 } else { 692 ALOGE("Unknown event - %0x", events); 693 } 694 } 695 696 /* Run event handler */ 697 void wifi_event_loop(wifi_handle handle) 698 { 699 hal_info *info = getHalInfo(handle); 700 if (info->in_event_loop) { 701 return; 702 } else { 703 info->in_event_loop = true; 704 } 705 706 pollfd pfd[3]; 707 memset(&pfd, 0, 3*sizeof(pfd[0])); 708 709 pfd[0].fd = nl_socket_get_fd(info->event_sock); 710 pfd[0].events = POLLIN; 711 712 pfd[1].fd = nl_socket_get_fd(info->user_sock); 713 pfd[1].events = POLLIN; 714 715 pfd[2].fd = info->exit_sockets[1]; 716 pfd[2].events = POLLIN; 717 718 /* TODO: Add support for timeouts */ 719 720 do { 721 pfd[0].revents = 0; 722 pfd[1].revents = 0; 723 pfd[2].revents = 0; 724 //ALOGI("Polling sockets"); 725 int result = poll(pfd, 3, -1); 726 if (result < 0) { 727 ALOGE("Error polling socket"); 728 } else { 729 if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) { 730 internal_event_handler(handle, pfd[0].revents, info->event_sock); 731 } 732 if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) { 733 internal_event_handler(handle, pfd[1].revents, info->user_sock); 734 } 735 } 736 rb_timerhandler(info); 737 } while (!info->clean_up); 738 internal_cleaned_up_handler(handle); 739 } 740 741 static int user_sock_message_handler(nl_msg *msg, void *arg) 742 { 743 wifi_handle handle = (wifi_handle)arg; 744 hal_info *info = getHalInfo(handle); 745 746 diag_message_handler(info, msg); 747 748 return NL_OK; 749 } 750 751 static int internal_valid_message_handler(nl_msg *msg, void *arg) 752 { 753 wifi_handle handle = (wifi_handle)arg; 754 hal_info *info = getHalInfo(handle); 755 756 WifiEvent event(msg); 757 int res = event.parse(); 758 if (res < 0) { 759 ALOGE("Failed to parse event: %d", res); 760 return NL_SKIP; 761 } 762 763 int cmd = event.get_cmd(); 764 uint32_t vendor_id = 0; 765 int subcmd = 0; 766 767 if (cmd == NL80211_CMD_VENDOR) { 768 vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID); 769 subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD); 770 /* Restrict printing GSCAN_FULL_RESULT which is causing lot 771 of logs in bug report */ 772 if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) { 773 ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x", 774 event.get_cmdString(), vendor_id, subcmd); 775 } 776 } else { 777 ALOGV("event received %s", event.get_cmdString()); 778 } 779 780 // event.log(); 781 782 bool dispatched = false; 783 784 pthread_mutex_lock(&info->cb_lock); 785 786 for (int i = 0; i < info->num_event_cb; i++) { 787 if (cmd == info->event_cb[i].nl_cmd) { 788 if (cmd == NL80211_CMD_VENDOR 789 && ((vendor_id != info->event_cb[i].vendor_id) 790 || (subcmd != info->event_cb[i].vendor_subcmd))) 791 { 792 /* event for a different vendor, ignore it */ 793 continue; 794 } 795 796 cb_info *cbi = &(info->event_cb[i]); 797 pthread_mutex_unlock(&info->cb_lock); 798 if (cbi->cb_func) { 799 (*(cbi->cb_func))(msg, cbi->cb_arg); 800 dispatched = true; 801 } 802 return NL_OK; 803 } 804 } 805 806 #ifdef QC_HAL_DEBUG 807 if (!dispatched) { 808 ALOGI("event ignored!!"); 809 } 810 #endif 811 812 pthread_mutex_unlock(&info->cb_lock); 813 return NL_OK; 814 } 815 816 //////////////////////////////////////////////////////////////////////////////// 817 818 class GetMulticastIdCommand : public WifiCommand 819 { 820 private: 821 const char *mName; 822 const char *mGroup; 823 int mId; 824 public: 825 GetMulticastIdCommand(wifi_handle handle, const char *name, 826 const char *group) : WifiCommand(handle, 0) 827 { 828 mName = name; 829 mGroup = group; 830 mId = -1; 831 } 832 833 int getId() { 834 return mId; 835 } 836 837 virtual int create() { 838 int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl"); 839 // ALOGI("ctrl family = %d", nlctrlFamily); 840 int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0); 841 if (ret < 0) { 842 return ret; 843 } 844 ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName); 845 return ret; 846 } 847 848 virtual int handleResponse(WifiEvent& reply) { 849 850 // ALOGI("handling reponse in %s", __func__); 851 852 struct nlattr **tb = reply.attributes(); 853 struct nlattr *mcgrp = NULL; 854 int i; 855 856 if (!tb[CTRL_ATTR_MCAST_GROUPS]) { 857 ALOGI("No multicast groups found"); 858 return NL_SKIP; 859 } else { 860 // ALOGI("Multicast groups attr size = %d", 861 // nla_len(tb[CTRL_ATTR_MCAST_GROUPS])); 862 } 863 864 for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) { 865 866 // ALOGI("Processing group"); 867 struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1]; 868 nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp), 869 nla_len(mcgrp), NULL); 870 if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) 871 { 872 continue; 873 } 874 875 char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]); 876 int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]); 877 878 // ALOGI("Found group name %s", grpName); 879 880 if (strncmp(grpName, mGroup, grpNameLen) != 0) 881 continue; 882 883 mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]); 884 break; 885 } 886 887 return NL_SKIP; 888 } 889 890 }; 891 892 static int wifi_get_multicast_id(wifi_handle handle, const char *name, 893 const char *group) 894 { 895 GetMulticastIdCommand cmd(handle, name, group); 896 int res = cmd.requestResponse(); 897 if (res < 0) 898 return res; 899 else 900 return cmd.getId(); 901 } 902 903 ///////////////////////////////////////////////////////////////////////// 904 905 static bool is_wifi_interface(const char *name) 906 { 907 if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) { 908 /* not a wifi interface; ignore it */ 909 return false; 910 } else { 911 return true; 912 } 913 } 914 915 static int get_interface(const char *name, interface_info *info) 916 { 917 strlcpy(info->name, name, (IFNAMSIZ + 1)); 918 info->id = if_nametoindex(name); 919 // ALOGI("found an interface : %s, id = %d", name, info->id); 920 return WIFI_SUCCESS; 921 } 922 923 wifi_error wifi_init_interfaces(wifi_handle handle) 924 { 925 hal_info *info = (hal_info *)handle; 926 927 struct dirent *de; 928 929 DIR *d = opendir("/sys/class/net"); 930 if (d == 0) 931 return WIFI_ERROR_UNKNOWN; 932 933 int n = 0; 934 while ((de = readdir(d))) { 935 if (de->d_name[0] == '.') 936 continue; 937 if (is_wifi_interface(de->d_name) ) { 938 n++; 939 } 940 } 941 942 closedir(d); 943 944 d = opendir("/sys/class/net"); 945 if (d == 0) 946 return WIFI_ERROR_UNKNOWN; 947 948 info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n); 949 if (info->interfaces == NULL) { 950 ALOGE("%s: Error info->interfaces NULL", __func__); 951 return WIFI_ERROR_OUT_OF_MEMORY; 952 } 953 954 int i = 0; 955 while ((de = readdir(d))) { 956 if (de->d_name[0] == '.') 957 continue; 958 if (is_wifi_interface(de->d_name)) { 959 interface_info *ifinfo 960 = (interface_info *)malloc(sizeof(interface_info)); 961 if (ifinfo == NULL) { 962 ALOGE("%s: Error ifinfo NULL", __func__); 963 while (i > 0) { 964 free(info->interfaces[i-1]); 965 i--; 966 } 967 free(info->interfaces); 968 return WIFI_ERROR_OUT_OF_MEMORY; 969 } 970 if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) { 971 free(ifinfo); 972 continue; 973 } 974 ifinfo->handle = handle; 975 info->interfaces[i] = ifinfo; 976 i++; 977 } 978 } 979 980 closedir(d); 981 982 info->num_interfaces = n; 983 984 return WIFI_SUCCESS; 985 } 986 987 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, 988 wifi_interface_handle **interfaces) 989 { 990 hal_info *info = (hal_info *)handle; 991 992 *interfaces = (wifi_interface_handle *)info->interfaces; 993 *num = info->num_interfaces; 994 995 return WIFI_SUCCESS; 996 } 997 998 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, 999 size_t size) 1000 { 1001 interface_info *info = (interface_info *)handle; 1002 strlcpy(name, info->name, size); 1003 return WIFI_SUCCESS; 1004 } 1005 1006 /* Get the supported Feature set */ 1007 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface, 1008 feature_set *set) 1009 { 1010 int ret = 0; 1011 wifi_handle handle = getWifiHandle(iface); 1012 *set = 0; 1013 hal_info *info = getHalInfo(handle); 1014 1015 ret = acquire_supported_features(iface, set); 1016 if (ret != WIFI_SUCCESS) { 1017 *set = info->supported_feature_set; 1018 ALOGV("Supported feature set acquired at initialization : %x", *set); 1019 } else { 1020 info->supported_feature_set = *set; 1021 ALOGV("Supported feature set acquired : %x", *set); 1022 } 1023 return WIFI_SUCCESS; 1024 } 1025 1026 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, 1027 int set_size_max, 1028 feature_set set[], int *set_size) 1029 { 1030 int ret = 0; 1031 struct nlattr *nlData; 1032 WifihalGeneric *vCommand = NULL; 1033 interface_info *ifaceInfo = getIfaceInfo(handle); 1034 wifi_handle wifiHandle = getWifiHandle(handle); 1035 1036 if (set == NULL) { 1037 ALOGE("%s: NULL set pointer provided. Exit.", 1038 __func__); 1039 return WIFI_ERROR_INVALID_ARGS; 1040 } 1041 1042 vCommand = new WifihalGeneric(wifiHandle, 0, 1043 OUI_QCA, 1044 QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX); 1045 if (vCommand == NULL) { 1046 ALOGE("%s: Error vCommand NULL", __func__); 1047 return WIFI_ERROR_OUT_OF_MEMORY; 1048 } 1049 1050 /* Create the message */ 1051 ret = vCommand->create(); 1052 if (ret < 0) 1053 goto cleanup; 1054 1055 ret = vCommand->set_iface_id(ifaceInfo->name); 1056 if (ret < 0) 1057 goto cleanup; 1058 1059 /* Add the vendor specific attributes for the NL command. */ 1060 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1061 if (!nlData) 1062 goto cleanup; 1063 1064 if (vCommand->put_u32( 1065 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX, 1066 set_size_max)) 1067 { 1068 goto cleanup; 1069 } 1070 vCommand->attr_end(nlData); 1071 1072 /* Populate the input received from caller/framework. */ 1073 vCommand->setMaxSetSize(set_size_max); 1074 vCommand->setSizePtr(set_size); 1075 vCommand->setConcurrencySet(set); 1076 1077 ret = vCommand->requestResponse(); 1078 if (ret) { 1079 ALOGE("%s: requestResponse() error: %d", __func__, ret); 1080 } 1081 1082 cleanup: 1083 delete vCommand; 1084 if (ret) { 1085 *set_size = 0; 1086 } 1087 return (wifi_error)ret; 1088 } 1089 1090 1091 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs) 1092 { 1093 int ret = 0; 1094 struct nlattr *nlData; 1095 WifiVendorCommand *vCommand = NULL; 1096 interface_info *ifaceInfo = getIfaceInfo(handle); 1097 wifi_handle wifiHandle = getWifiHandle(handle); 1098 1099 vCommand = new WifiVendorCommand(wifiHandle, 0, 1100 OUI_QCA, 1101 QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG); 1102 if (vCommand == NULL) { 1103 ALOGE("%s: Error vCommand NULL", __func__); 1104 return WIFI_ERROR_OUT_OF_MEMORY; 1105 } 1106 1107 /* Create the message */ 1108 ret = vCommand->create(); 1109 if (ret < 0) 1110 goto cleanup; 1111 1112 ret = vCommand->set_iface_id(ifaceInfo->name); 1113 if (ret < 0) 1114 goto cleanup; 1115 1116 /* Add the vendor specific attributes for the NL command. */ 1117 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1118 if (!nlData) 1119 goto cleanup; 1120 1121 /* Add the fixed part of the mac_oui to the nl command */ 1122 if (vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs)) { 1123 goto cleanup; 1124 } 1125 1126 vCommand->attr_end(nlData); 1127 1128 ret = vCommand->requestResponse(); 1129 /* Don't check response since we aren't expecting one */ 1130 1131 cleanup: 1132 delete vCommand; 1133 return (wifi_error)ret; 1134 } 1135 1136 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id, 1137 wifi_interface_handle iface, 1138 u8 *ip_packet, 1139 u16 ip_packet_len, 1140 u8 *src_mac_addr, 1141 u8 *dst_mac_addr, 1142 u32 period_msec) 1143 { 1144 int ret = WIFI_SUCCESS; 1145 struct nlattr *nlData; 1146 WifiVendorCommand *vCommand = NULL; 1147 1148 ret = initialize_vendor_cmd(iface, id, 1149 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS, 1150 &vCommand); 1151 if (ret != WIFI_SUCCESS) { 1152 ALOGE("%s: Initialization failed", __func__); 1153 return (wifi_error)ret; 1154 } 1155 1156 ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len); 1157 hexdump(ip_packet, ip_packet_len); 1158 ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR 1159 "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr), 1160 MAC_ADDR_ARRAY(dst_mac_addr), period_msec); 1161 1162 /* Add the vendor specific attributes for the NL command. */ 1163 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1164 if (!nlData) 1165 goto cleanup; 1166 1167 if (vCommand->put_u32( 1168 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL, 1169 QCA_WLAN_OFFLOADED_PACKETS_SENDING_START) || 1170 vCommand->put_u32( 1171 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID, 1172 id) || 1173 vCommand->put_bytes( 1174 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET, 1175 (const char *)ip_packet, ip_packet_len) || 1176 vCommand->put_addr( 1177 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR, 1178 src_mac_addr) || 1179 vCommand->put_addr( 1180 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR, 1181 dst_mac_addr) || 1182 vCommand->put_u32( 1183 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD, 1184 period_msec)) 1185 { 1186 goto cleanup; 1187 } 1188 1189 vCommand->attr_end(nlData); 1190 1191 ret = vCommand->requestResponse(); 1192 if (ret < 0) 1193 goto cleanup; 1194 1195 cleanup: 1196 delete vCommand; 1197 return (wifi_error)ret; 1198 } 1199 1200 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id, 1201 wifi_interface_handle iface) 1202 { 1203 int ret = WIFI_SUCCESS; 1204 struct nlattr *nlData; 1205 WifiVendorCommand *vCommand = NULL; 1206 1207 ret = initialize_vendor_cmd(iface, id, 1208 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS, 1209 &vCommand); 1210 if (ret != WIFI_SUCCESS) { 1211 ALOGE("%s: Initialization failed", __func__); 1212 return (wifi_error)ret; 1213 } 1214 1215 /* Add the vendor specific attributes for the NL command. */ 1216 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1217 if (!nlData) 1218 goto cleanup; 1219 1220 if (vCommand->put_u32( 1221 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL, 1222 QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP) || 1223 vCommand->put_u32( 1224 QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID, 1225 id)) 1226 { 1227 goto cleanup; 1228 } 1229 1230 1231 vCommand->attr_end(nlData); 1232 1233 ret = vCommand->requestResponse(); 1234 if (ret < 0) 1235 goto cleanup; 1236 1237 cleanup: 1238 delete vCommand; 1239 return (wifi_error)ret; 1240 } 1241 1242 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface, 1243 const u8 *program, u32 len) 1244 { 1245 int ret = WIFI_SUCCESS; 1246 struct nlattr *nlData; 1247 WifiVendorCommand *vCommand = NULL; 1248 u32 current_offset = 0; 1249 wifi_handle wifiHandle = getWifiHandle(iface); 1250 hal_info *info = getHalInfo(wifiHandle); 1251 1252 /* len=0 clears the filters in driver/firmware */ 1253 if (len != 0 && program == NULL) { 1254 ALOGE("%s: No valid program provided. Exit.", 1255 __func__); 1256 return WIFI_ERROR_INVALID_ARGS; 1257 } 1258 1259 do { 1260 ret = initialize_vendor_cmd(iface, get_requestid(), 1261 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER, 1262 &vCommand); 1263 if (ret != WIFI_SUCCESS) { 1264 ALOGE("%s: Initialization failed", __FUNCTION__); 1265 return (wifi_error)ret; 1266 } 1267 1268 /* Add the vendor specific attributes for the NL command. */ 1269 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1270 if (!nlData) 1271 goto cleanup; 1272 1273 if (vCommand->put_u32( 1274 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD, 1275 QCA_WLAN_SET_PACKET_FILTER) || 1276 vCommand->put_u32( 1277 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID, 1278 PACKET_FILTER_ID) || 1279 vCommand->put_u32( 1280 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH, 1281 len) || 1282 vCommand->put_u32( 1283 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET, 1284 current_offset)) { 1285 ALOGE("%s: failed to put subcmd/program", __FUNCTION__); 1286 goto cleanup; 1287 } 1288 1289 if (len) { 1290 if(vCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM, 1291 (char *)&program[current_offset], 1292 min(info->firmware_bus_max_size, 1293 len-current_offset))) { 1294 ALOGE("%s: failed to put subcmd", __FUNCTION__); 1295 goto cleanup; 1296 } 1297 } 1298 1299 vCommand->attr_end(nlData); 1300 1301 ret = vCommand->requestResponse(); 1302 if (ret < 0) { 1303 ALOGE("%s: requestResponse Error:%d",__func__, ret); 1304 goto cleanup; 1305 } 1306 1307 /* destroy the object after sending each fragment to driver */ 1308 delete vCommand; 1309 vCommand = NULL; 1310 1311 current_offset += min(info->firmware_bus_max_size, len); 1312 } while (current_offset < len); 1313 1314 cleanup: 1315 if (vCommand) 1316 delete vCommand; 1317 return (wifi_error)ret; 1318 } 1319 1320 static wifi_error wifi_get_packet_filter_capabilities( 1321 wifi_interface_handle handle, u32 *version, u32 *max_len) 1322 { 1323 int ret = 0; 1324 struct nlattr *nlData; 1325 WifihalGeneric *vCommand = NULL; 1326 interface_info *ifaceInfo = getIfaceInfo(handle); 1327 wifi_handle wifiHandle = getWifiHandle(handle); 1328 1329 if (version == NULL || max_len == NULL) { 1330 ALOGE("%s: NULL version/max_len pointer provided. Exit.", 1331 __FUNCTION__); 1332 return WIFI_ERROR_INVALID_ARGS; 1333 } 1334 1335 vCommand = new WifihalGeneric(wifiHandle, 0, 1336 OUI_QCA, 1337 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER); 1338 if (vCommand == NULL) { 1339 ALOGE("%s: Error vCommand NULL", __FUNCTION__); 1340 return WIFI_ERROR_OUT_OF_MEMORY; 1341 } 1342 1343 /* Create the message */ 1344 ret = vCommand->create(); 1345 if (ret < 0) 1346 goto cleanup; 1347 1348 ret = vCommand->set_iface_id(ifaceInfo->name); 1349 if (ret < 0) 1350 goto cleanup; 1351 1352 /* Add the vendor specific attributes for the NL command. */ 1353 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1354 if (!nlData) 1355 goto cleanup; 1356 1357 if (vCommand->put_u32( 1358 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD, 1359 QCA_WLAN_GET_PACKET_FILTER_SIZE)) 1360 { 1361 goto cleanup; 1362 } 1363 vCommand->attr_end(nlData); 1364 1365 ret = vCommand->requestResponse(); 1366 if (ret) { 1367 ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret); 1368 if (ret == -ENOTSUP) { 1369 /* Packet filtering is not supported currently, so return version 1370 * and length as 0 1371 */ 1372 ALOGI("Packet filtering is not supprted"); 1373 *version = 0; 1374 *max_len = 0; 1375 ret = WIFI_SUCCESS; 1376 } 1377 goto cleanup; 1378 } 1379 1380 *version = vCommand->getFilterVersion(); 1381 *max_len = vCommand->getFilterLength(); 1382 cleanup: 1383 delete vCommand; 1384 return (wifi_error)ret; 1385 } 1386 1387 1388 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, 1389 u8 enable) 1390 { 1391 int ret = WIFI_SUCCESS; 1392 struct nlattr *nlData; 1393 WifiVendorCommand *vCommand = NULL; 1394 1395 ret = initialize_vendor_cmd(iface, get_requestid(), 1396 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD, 1397 &vCommand); 1398 if (ret != WIFI_SUCCESS) { 1399 ALOGE("%s: Initialization failed", __func__); 1400 return (wifi_error)ret; 1401 } 1402 1403 ALOGV("ND offload : %s", enable?"Enable":"Disable"); 1404 1405 /* Add the vendor specific attributes for the NL command. */ 1406 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1407 if (!nlData) 1408 goto cleanup; 1409 1410 if (vCommand->put_u8( 1411 QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, 1412 enable)) 1413 { 1414 goto cleanup; 1415 } 1416 1417 vCommand->attr_end(nlData); 1418 1419 ret = vCommand->requestResponse(); 1420 1421 cleanup: 1422 delete vCommand; 1423 return (wifi_error)ret; 1424 } 1425