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