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