1 /* Copyright (c) 2015, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions 5 * are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "sync.h" 30 31 #include "wifi_hal.h" 32 #include "common.h" 33 #include "cpp_bindings.h" 34 #include <errno.h> 35 #include <utils/Log.h> 36 #include "wifiloggercmd.h" 37 #include "rb_wrapper.h" 38 #include <stdlib.h> 39 40 #define LOGGER_MEMDUMP_FILENAME "/proc/debug/fwdump" 41 #define DRIVER_MEMDUMP_FILENAME "/proc/debugdriver/driverdump" 42 #define LOGGER_MEMDUMP_CHUNKSIZE (4 * 1024) 43 #define DRIVER_MEMDUMP_MAX_FILESIZE (16 * 1024) 44 45 char power_events_ring_name[] = "power_events_rb"; 46 char connectivity_events_ring_name[] = "connectivity_events_rb"; 47 char pkt_stats_ring_name[] = "pkt_stats_rb"; 48 char driver_prints_ring_name[] = "driver_prints_rb"; 49 char firmware_prints_ring_name[] = "firmware_prints_rb"; 50 51 static int get_ring_id(hal_info *info, char *ring_name) 52 { 53 int rb_id; 54 55 for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) { 56 if (is_rb_name_match(&info->rb_infos[rb_id], ring_name)) { 57 return rb_id; 58 } 59 } 60 return -1; 61 } 62 63 //Implementation of the functions exposed in wifi_logger.h 64 65 /* Function to intiate logging */ 66 wifi_error wifi_start_logging(wifi_interface_handle iface, 67 u32 verbose_level, u32 flags, 68 u32 max_interval_sec, u32 min_data_size, 69 char *buffer_name) 70 { 71 int requestId, ret = 0; 72 WifiLoggerCommand *wifiLoggerCommand = NULL; 73 struct nlattr *nlData; 74 interface_info *ifaceInfo = getIfaceInfo(iface); 75 wifi_handle wifiHandle = getWifiHandle(iface); 76 hal_info *info = getHalInfo(wifiHandle); 77 int ring_id = 0; 78 79 /* 80 * No request id from caller, so generate one and pass it on to the driver. 81 * Generate one randomly. 82 */ 83 requestId = get_requestid(); 84 85 if (buffer_name == NULL) { 86 ALOGE("%s: Invalid Ring Name. \n", __FUNCTION__); 87 return WIFI_ERROR_UNKNOWN; 88 } 89 90 ring_id = get_ring_id(info, buffer_name); 91 if (ring_id < 0) { 92 ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__); 93 return WIFI_ERROR_UNKNOWN; 94 } 95 96 wifiLoggerCommand = new WifiLoggerCommand( 97 wifiHandle, 98 requestId, 99 OUI_QCA, 100 QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START); 101 102 if (wifiLoggerCommand == NULL) { 103 ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__); 104 return WIFI_ERROR_UNKNOWN; 105 } 106 /* Create the NL message. */ 107 ret = wifiLoggerCommand->create(); 108 109 if (ret < 0) 110 goto cleanup; 111 112 /* Set the interface Id of the message. */ 113 ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name); 114 115 if (ret < 0) 116 goto cleanup; 117 118 /* Add the vendor specific attributes for the NL command. */ 119 nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 120 121 if (!nlData) 122 goto cleanup; 123 124 if (wifiLoggerCommand->put_u32( 125 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID, ring_id)) 126 { 127 goto cleanup; 128 } 129 if (wifiLoggerCommand->put_u32( 130 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL, 131 verbose_level)) 132 { 133 goto cleanup; 134 } 135 if (wifiLoggerCommand->put_u32( 136 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS, 137 flags)) 138 { 139 goto cleanup; 140 } 141 142 wifiLoggerCommand->attr_end(nlData); 143 144 /* Send the msg and wait for a response. */ 145 ret = wifiLoggerCommand->requestResponse(); 146 if (ret) { 147 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret); 148 } 149 150 ALOGV("%s: Logging Started for %s.", __FUNCTION__, buffer_name); 151 rb_start_logging(&info->rb_infos[ring_id], verbose_level, 152 flags, max_interval_sec, min_data_size); 153 cleanup: 154 if (wifiLoggerCommand) 155 delete wifiLoggerCommand; 156 return (wifi_error)ret; 157 158 } 159 160 /* Function to get each ring related info */ 161 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface, 162 u32 *num_buffers, 163 wifi_ring_buffer_status *status) 164 { 165 int ret = 0; 166 wifi_handle wifiHandle = getWifiHandle(iface); 167 hal_info *info = getHalInfo(wifiHandle); 168 wifi_ring_buffer_status *rbs; 169 struct rb_info *rb_info; 170 int rb_id; 171 172 if ((*num_buffers) < NUM_RING_BUFS) { 173 ALOGE("%s: Input num_buffers:%u cannot be accommodated, " 174 "Total ring buffer num:%d", __FUNCTION__, *num_buffers, 175 NUM_RING_BUFS); 176 *num_buffers = 0; 177 return WIFI_ERROR_OUT_OF_MEMORY; 178 } 179 for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) { 180 rb_info = &info->rb_infos[rb_id]; 181 rbs = status + rb_id; 182 183 get_rb_status(rb_info, rbs); 184 } 185 *num_buffers = NUM_RING_BUFS; 186 return (wifi_error)ret; 187 } 188 189 void push_out_all_ring_buffers(hal_info *info) 190 { 191 int rb_id; 192 193 for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) { 194 push_out_rb_data(&info->rb_infos[rb_id]); 195 } 196 } 197 198 void send_alert(hal_info *info, int reason_code) 199 { 200 wifi_alert_handler handler; 201 202 pthread_mutex_lock(&info->ah_lock); 203 handler.on_alert = info->on_alert; 204 pthread_mutex_unlock(&info->ah_lock); 205 206 if (handler.on_alert) { 207 handler.on_alert(0, NULL, 0, reason_code); 208 } 209 } 210 211 void WifiLoggerCommand::setFeatureSet(u32 *support) { 212 mSupportedSet = support; 213 } 214 215 /* Function to get the supported feature set for logging.*/ 216 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface, 217 u32 *support) 218 { 219 220 int requestId, ret = 0; 221 WifiLoggerCommand *wifiLoggerCommand; 222 struct nlattr *nlData; 223 interface_info *ifaceInfo = getIfaceInfo(iface); 224 wifi_handle wifiHandle = getWifiHandle(iface); 225 226 /* No request id from caller, so generate one and pass it on to the driver. 227 * Generate one randomly. 228 */ 229 requestId = get_requestid(); 230 231 wifiLoggerCommand = new WifiLoggerCommand( 232 wifiHandle, 233 requestId, 234 OUI_QCA, 235 QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET); 236 237 if (wifiLoggerCommand == NULL) { 238 ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__); 239 return WIFI_ERROR_UNKNOWN; 240 } 241 /* Create the NL message. */ 242 ret = wifiLoggerCommand->create(); 243 244 if (ret < 0) 245 goto cleanup; 246 247 /* Set the interface Id of the message. */ 248 ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name); 249 250 if (ret < 0) 251 goto cleanup; 252 253 /* Add the vendor specific attributes for the NL command. */ 254 nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 255 256 if (!nlData) 257 goto cleanup; 258 259 if (wifiLoggerCommand->put_u32( 260 QCA_WLAN_VENDOR_ATTR_FEATURE_SET, requestId)) 261 { 262 goto cleanup; 263 } 264 wifiLoggerCommand->attr_end(nlData); 265 266 wifiLoggerCommand->setFeatureSet(support); 267 268 /* Send the msg and wait for a response. */ 269 ret = wifiLoggerCommand->requestResponse(); 270 if (ret) { 271 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret); 272 } 273 274 cleanup: 275 delete wifiLoggerCommand; 276 return (wifi_error)ret; 277 } 278 279 /* Function to get the data in each ring for the given ring ID.*/ 280 wifi_error wifi_get_ring_data(wifi_interface_handle iface, 281 char *ring_name) 282 { 283 284 int requestId, ret = 0; 285 WifiLoggerCommand *wifiLoggerCommand; 286 struct nlattr *nlData; 287 interface_info *ifaceInfo = getIfaceInfo(iface); 288 wifi_handle wifiHandle = getWifiHandle(iface); 289 hal_info *info = getHalInfo(wifiHandle); 290 int ring_id = 0; 291 292 ring_id = get_ring_id(info, ring_name); 293 if (ring_id < 0) { 294 ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__); 295 return WIFI_ERROR_UNKNOWN; 296 } 297 298 requestId = get_requestid(); 299 300 wifiLoggerCommand = new WifiLoggerCommand( 301 wifiHandle, 302 requestId, 303 OUI_QCA, 304 QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA); 305 if (wifiLoggerCommand == NULL) { 306 ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__); 307 return WIFI_ERROR_UNKNOWN; 308 } 309 /* Create the NL message. */ 310 ret = wifiLoggerCommand->create(); 311 312 if (ret < 0) 313 goto cleanup; 314 315 /* Set the interface Id of the message. */ 316 ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name); 317 318 if (ret < 0) 319 goto cleanup; 320 321 /* Add the vendor specific attributes for the NL command. */ 322 nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 323 324 if (!nlData) 325 goto cleanup; 326 327 if (wifiLoggerCommand->put_u32( 328 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID, ring_id)) 329 { 330 goto cleanup; 331 } 332 wifiLoggerCommand->attr_end(nlData); 333 334 /* Send the msg and wait for a response. */ 335 ret = wifiLoggerCommand->requestResponse(); 336 if (ret) { 337 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret); 338 } 339 340 cleanup: 341 delete wifiLoggerCommand; 342 return (wifi_error)ret; 343 } 344 345 void WifiLoggerCommand::setVersionInfo(char *buffer, int buffer_size) { 346 mVersion = buffer; 347 mVersionLen = buffer_size; 348 } 349 350 /* Function to send enable request to the wifi driver.*/ 351 wifi_error wifi_get_firmware_version(wifi_interface_handle iface, 352 char *buffer, int buffer_size) 353 { 354 int requestId, ret = 0; 355 WifiLoggerCommand *wifiLoggerCommand; 356 struct nlattr *nlData; 357 interface_info *ifaceInfo = getIfaceInfo(iface); 358 wifi_handle wifiHandle = getWifiHandle(iface); 359 360 /* No request id from caller, so generate one and pass it on to the driver. 361 * Generate one randomly. 362 */ 363 requestId = get_requestid(); 364 365 wifiLoggerCommand = new WifiLoggerCommand( 366 wifiHandle, 367 requestId, 368 OUI_QCA, 369 QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO); 370 if (wifiLoggerCommand == NULL) { 371 ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__); 372 return WIFI_ERROR_UNKNOWN; 373 } 374 /* Create the NL message. */ 375 ret = wifiLoggerCommand->create(); 376 377 if (ret < 0) 378 goto cleanup; 379 380 /* Set the interface Id of the message. */ 381 ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name); 382 383 if (ret < 0) 384 goto cleanup; 385 386 /* Add the vendor specific attributes for the NL command. */ 387 nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 388 389 if (!nlData) 390 goto cleanup; 391 392 if (wifiLoggerCommand->put_u32( 393 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION, requestId)) 394 { 395 goto cleanup; 396 } 397 wifiLoggerCommand->attr_end(nlData); 398 399 wifiLoggerCommand->setVersionInfo(buffer, buffer_size); 400 401 /* Send the msg and wait for a response. */ 402 ret = wifiLoggerCommand->requestResponse(); 403 if (ret) { 404 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret); 405 } 406 cleanup: 407 delete wifiLoggerCommand; 408 return (wifi_error)ret; 409 410 } 411 412 /* Function to get wlan driver version.*/ 413 wifi_error wifi_get_driver_version(wifi_interface_handle iface, 414 char *buffer, int buffer_size) 415 { 416 417 int requestId, ret = 0; 418 WifiLoggerCommand *wifiLoggerCommand; 419 struct nlattr *nlData; 420 interface_info *ifaceInfo = getIfaceInfo(iface); 421 wifi_handle wifiHandle = getWifiHandle(iface); 422 423 /* No request id from caller, so generate one and pass it on to the driver. 424 * Generate one randomly. 425 */ 426 requestId = get_requestid(); 427 428 wifiLoggerCommand = new WifiLoggerCommand( 429 wifiHandle, 430 requestId, 431 OUI_QCA, 432 QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO); 433 if (wifiLoggerCommand == NULL) { 434 ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__); 435 return WIFI_ERROR_UNKNOWN; 436 } 437 /* Create the NL message. */ 438 ret = wifiLoggerCommand->create(); 439 440 if (ret < 0) 441 goto cleanup; 442 443 /* Set the interface Id of the message. */ 444 ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name); 445 446 if (ret < 0) 447 goto cleanup; 448 449 /* Add the vendor specific attributes for the NL command. */ 450 nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 451 452 if (!nlData) 453 goto cleanup; 454 455 if (wifiLoggerCommand->put_u32( 456 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION, requestId)) 457 { 458 goto cleanup; 459 } 460 wifiLoggerCommand->attr_end(nlData); 461 462 wifiLoggerCommand->setVersionInfo(buffer, buffer_size); 463 464 /* Send the msg and wait for a response. */ 465 ret = wifiLoggerCommand->requestResponse(); 466 if (ret) { 467 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret); 468 } 469 cleanup: 470 delete wifiLoggerCommand; 471 return (wifi_error)ret; 472 } 473 474 475 /* Function to get the Firmware memory dump. */ 476 wifi_error wifi_get_firmware_memory_dump(wifi_interface_handle iface, 477 wifi_firmware_memory_dump_handler handler) 478 { 479 int requestId, ret = 0; 480 WifiLoggerCommand *wifiLoggerCommand; 481 struct nlattr *nlData; 482 interface_info *ifaceInfo = getIfaceInfo(iface); 483 wifi_handle wifiHandle = getWifiHandle(iface); 484 485 /* No request id from caller, so generate one and pass it on to the driver. 486 * Generate one randomly. 487 */ 488 requestId = get_requestid(); 489 490 wifiLoggerCommand = new WifiLoggerCommand( 491 wifiHandle, 492 requestId, 493 OUI_QCA, 494 QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP); 495 if (wifiLoggerCommand == NULL) { 496 ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__); 497 return WIFI_ERROR_UNKNOWN; 498 } 499 /* Create the NL message. */ 500 ret = wifiLoggerCommand->create(); 501 502 if (ret < 0) 503 goto cleanup; 504 505 /* Set the interface Id of the message. */ 506 ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name); 507 508 if (ret < 0) 509 goto cleanup; 510 511 /* Add the vendor specific attributes for the NL command. */ 512 nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 513 514 if (!nlData) 515 goto cleanup; 516 517 wifiLoggerCommand->attr_end(nlData); 518 519 /* copy the callback into callback handler */ 520 WifiLoggerCallbackHandler callbackHandler; 521 memset(&callbackHandler, 0, sizeof(callbackHandler)); 522 callbackHandler.on_firmware_memory_dump = \ 523 handler.on_firmware_memory_dump; 524 525 ret = wifiLoggerCommand->setCallbackHandler(callbackHandler); 526 if (ret < 0) 527 goto cleanup; 528 529 /* Send the msg and wait for the memory dump response */ 530 ret = wifiLoggerCommand->requestResponse(); 531 if (ret) { 532 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret); 533 } 534 535 cleanup: 536 delete wifiLoggerCommand; 537 return (wifi_error)ret; 538 } 539 540 wifi_error wifi_set_log_handler(wifi_request_id id, 541 wifi_interface_handle iface, 542 wifi_ring_buffer_data_handler handler) 543 { 544 wifi_handle wifiHandle = getWifiHandle(iface); 545 hal_info *info = getHalInfo(wifiHandle); 546 547 pthread_mutex_lock(&info->lh_lock); 548 info->on_ring_buffer_data = handler.on_ring_buffer_data; 549 pthread_mutex_unlock(&info->lh_lock); 550 if (handler.on_ring_buffer_data == NULL) { 551 ALOGE("Set log handler is NULL"); 552 return WIFI_ERROR_UNKNOWN; 553 } 554 return WIFI_SUCCESS; 555 } 556 557 wifi_error wifi_reset_log_handler(wifi_request_id id, 558 wifi_interface_handle iface) 559 { 560 wifi_handle wifiHandle = getWifiHandle(iface); 561 hal_info *info = getHalInfo(wifiHandle); 562 563 pthread_mutex_lock(&info->lh_lock); 564 info->on_ring_buffer_data = NULL; 565 pthread_mutex_unlock(&info->lh_lock); 566 return WIFI_SUCCESS; 567 } 568 569 wifi_error wifi_set_alert_handler(wifi_request_id id, 570 wifi_interface_handle iface, 571 wifi_alert_handler handler) 572 { 573 wifi_handle wifiHandle = getWifiHandle(iface); 574 hal_info *info = getHalInfo(wifiHandle); 575 576 if (handler.on_alert == NULL) { 577 ALOGE("Set alert handler is NULL"); 578 return WIFI_ERROR_UNKNOWN; 579 } 580 pthread_mutex_lock(&info->ah_lock); 581 info->on_alert = handler.on_alert; 582 pthread_mutex_unlock(&info->ah_lock); 583 return WIFI_SUCCESS; 584 } 585 586 wifi_error wifi_reset_alert_handler(wifi_request_id id, 587 wifi_interface_handle iface) 588 { 589 wifi_handle wifiHandle = getWifiHandle(iface); 590 hal_info *info = getHalInfo(wifiHandle); 591 592 pthread_mutex_lock(&info->ah_lock); 593 info->on_alert = NULL; 594 pthread_mutex_unlock(&info->ah_lock); 595 return WIFI_SUCCESS; 596 } 597 598 599 /** 600 API to start packet fate monitoring. 601 - Once stared, monitoring should remain active until HAL is unloaded. 602 - When HAL is unloaded, all packet fate buffers should be cleared. 603 */ 604 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle iface) 605 { 606 wifi_handle wifiHandle = getWifiHandle(iface); 607 hal_info *info = getHalInfo(wifiHandle); 608 609 if (info->fate_monitoring_enabled == true) { 610 ALOGV("Packet monitoring is already enabled"); 611 return WIFI_SUCCESS; 612 } 613 614 info->pkt_fate_stats = (packet_fate_monitor_info *) malloc ( 615 sizeof(packet_fate_monitor_info)); 616 if (info->pkt_fate_stats == NULL) { 617 ALOGE("Failed to allocate memory for : %zu bytes", 618 sizeof(packet_fate_monitor_info)); 619 return WIFI_ERROR_OUT_OF_MEMORY; 620 } 621 memset(info->pkt_fate_stats, 0, sizeof(packet_fate_monitor_info)); 622 623 pthread_mutex_lock(&info->pkt_fate_stats_lock); 624 info->fate_monitoring_enabled = true; 625 pthread_mutex_unlock(&info->pkt_fate_stats_lock); 626 627 return WIFI_SUCCESS; 628 } 629 630 631 /** 632 API to retrieve fates of outbound packets. 633 - HAL implementation should fill |tx_report_bufs| with fates of 634 _first_ min(n_requested_fates, actual packets) frames 635 transmitted for the most recent association. The fate reports 636 should follow the same order as their respective packets. 637 - Packets reported by firmware, but not recognized by driver 638 should be included. However, the ordering of the corresponding 639 reports is at the discretion of HAL implementation. 640 - Framework may call this API multiple times for the same association. 641 - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|. 642 - Framework will allocate and free the referenced storage. 643 */ 644 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle iface, 645 wifi_tx_report *tx_report_bufs, 646 size_t n_requested_fates, 647 size_t *n_provided_fates) 648 { 649 wifi_handle wifiHandle = getWifiHandle(iface); 650 hal_info *info = getHalInfo(wifiHandle); 651 wifi_tx_report_i *tx_fate_stats; 652 size_t i; 653 654 if (info->fate_monitoring_enabled != true) { 655 ALOGE("Packet monitoring is not yet triggered"); 656 return WIFI_ERROR_UNINITIALIZED; 657 } 658 pthread_mutex_lock(&info->pkt_fate_stats_lock); 659 660 tx_fate_stats = &info->pkt_fate_stats->tx_fate_stats[0]; 661 662 *n_provided_fates = min(n_requested_fates, 663 info->pkt_fate_stats->n_tx_stats_collected); 664 665 for (i=0; i < *n_provided_fates; i++) { 666 memcpy(tx_report_bufs[i].md5_prefix, 667 tx_fate_stats[i].md5_prefix, MD5_PREFIX_LEN); 668 tx_report_bufs[i].fate = tx_fate_stats[i].fate; 669 tx_report_bufs[i].frame_inf.payload_type = 670 tx_fate_stats[i].frame_inf.payload_type; 671 tx_report_bufs[i].frame_inf.driver_timestamp_usec = 672 tx_fate_stats[i].frame_inf.driver_timestamp_usec; 673 tx_report_bufs[i].frame_inf.firmware_timestamp_usec = 674 tx_fate_stats[i].frame_inf.firmware_timestamp_usec; 675 tx_report_bufs[i].frame_inf.frame_len = 676 tx_fate_stats[i].frame_inf.frame_len; 677 678 if (tx_report_bufs[i].frame_inf.payload_type == FRAME_TYPE_ETHERNET_II) 679 memcpy(tx_report_bufs[i].frame_inf.frame_content.ethernet_ii_bytes, 680 tx_fate_stats[i].frame_inf.frame_content, 681 min(tx_fate_stats[i].frame_inf.frame_len, 682 MAX_FRAME_LEN_ETHERNET)); 683 else if (tx_report_bufs[i].frame_inf.payload_type == 684 FRAME_TYPE_80211_MGMT) 685 memcpy( 686 tx_report_bufs[i].frame_inf.frame_content.ieee_80211_mgmt_bytes, 687 tx_fate_stats[i].frame_inf.frame_content, 688 min(tx_fate_stats[i].frame_inf.frame_len, 689 MAX_FRAME_LEN_80211_MGMT)); 690 else 691 /* Currently framework is interested only two types( 692 * FRAME_TYPE_ETHERNET_II and FRAME_TYPE_80211_MGMT) of packets, so 693 * ignore the all other types of packets received from driver */ 694 ALOGI("Unknown format packet"); 695 } 696 pthread_mutex_unlock(&info->pkt_fate_stats_lock); 697 698 return WIFI_SUCCESS; 699 } 700 701 /** 702 API to retrieve fates of inbound packets. 703 - HAL implementation should fill |rx_report_bufs| with fates of 704 _first_ min(n_requested_fates, actual packets) frames 705 received for the most recent association. The fate reports 706 should follow the same order as their respective packets. 707 - Packets reported by firmware, but not recognized by driver 708 should be included. However, the ordering of the corresponding 709 reports is at the discretion of HAL implementation. 710 - Framework may call this API multiple times for the same association. 711 - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|. 712 - Framework will allocate and free the referenced storage. 713 */ 714 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle iface, 715 wifi_rx_report *rx_report_bufs, 716 size_t n_requested_fates, 717 size_t *n_provided_fates) 718 { 719 wifi_handle wifiHandle = getWifiHandle(iface); 720 hal_info *info = getHalInfo(wifiHandle); 721 wifi_rx_report_i *rx_fate_stats; 722 size_t i; 723 724 if (info->fate_monitoring_enabled != true) { 725 ALOGE("Packet monitoring is not yet triggered"); 726 return WIFI_ERROR_UNINITIALIZED; 727 } 728 pthread_mutex_lock(&info->pkt_fate_stats_lock); 729 730 rx_fate_stats = &info->pkt_fate_stats->rx_fate_stats[0]; 731 732 *n_provided_fates = min(n_requested_fates, 733 info->pkt_fate_stats->n_rx_stats_collected); 734 735 for (i=0; i < *n_provided_fates; i++) { 736 memcpy(rx_report_bufs[i].md5_prefix, 737 rx_fate_stats[i].md5_prefix, MD5_PREFIX_LEN); 738 rx_report_bufs[i].fate = rx_fate_stats[i].fate; 739 rx_report_bufs[i].frame_inf.payload_type = 740 rx_fate_stats[i].frame_inf.payload_type; 741 rx_report_bufs[i].frame_inf.driver_timestamp_usec = 742 rx_fate_stats[i].frame_inf.driver_timestamp_usec; 743 rx_report_bufs[i].frame_inf.firmware_timestamp_usec = 744 rx_fate_stats[i].frame_inf.firmware_timestamp_usec; 745 rx_report_bufs[i].frame_inf.frame_len = 746 rx_fate_stats[i].frame_inf.frame_len; 747 748 if (rx_report_bufs[i].frame_inf.payload_type == FRAME_TYPE_ETHERNET_II) 749 memcpy(rx_report_bufs[i].frame_inf.frame_content.ethernet_ii_bytes, 750 rx_fate_stats[i].frame_inf.frame_content, 751 min(rx_fate_stats[i].frame_inf.frame_len, 752 MAX_FRAME_LEN_ETHERNET)); 753 else if (rx_report_bufs[i].frame_inf.payload_type == 754 FRAME_TYPE_80211_MGMT) 755 memcpy( 756 rx_report_bufs[i].frame_inf.frame_content.ieee_80211_mgmt_bytes, 757 rx_fate_stats[i].frame_inf.frame_content, 758 min(rx_fate_stats[i].frame_inf.frame_len, 759 MAX_FRAME_LEN_80211_MGMT)); 760 else 761 /* Currently framework is interested only two types( 762 * FRAME_TYPE_ETHERNET_II and FRAME_TYPE_80211_MGMT) of packets, so 763 * ignore the all other types of packets received from driver */ 764 ALOGI("Unknown format packet"); 765 } 766 pthread_mutex_unlock(&info->pkt_fate_stats_lock); 767 768 return WIFI_SUCCESS; 769 } 770 771 WifiLoggerCommand::WifiLoggerCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd) 772 : WifiVendorCommand(handle, id, vendor_id, subcmd) 773 { 774 mVersion = NULL; 775 mVersionLen = 0; 776 mRequestId = id; 777 memset(&mHandler, 0,sizeof(mHandler)); 778 mWaitforRsp = false; 779 mMoreData = false; 780 mSupportedSet = NULL; 781 } 782 783 WifiLoggerCommand::~WifiLoggerCommand() 784 { 785 unregisterVendorHandler(mVendor_id, mSubcmd); 786 } 787 788 /* This function implements creation of Vendor command */ 789 int WifiLoggerCommand::create() { 790 int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0); 791 if (ret < 0) { 792 return ret; 793 } 794 795 /* Insert the oui in the msg */ 796 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id); 797 if (ret < 0) 798 goto out; 799 /* Insert the subcmd in the msg */ 800 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd); 801 if (ret < 0) 802 goto out; 803 804 ALOGV("%s: mVendor_id = %d, Subcmd = %d.", 805 __FUNCTION__, mVendor_id, mSubcmd); 806 807 out: 808 return ret; 809 } 810 811 void rb_timerhandler(hal_info *info) 812 { 813 struct timeval now; 814 int rb_id; 815 816 gettimeofday(&now,NULL); 817 for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) { 818 rb_check_for_timeout(&info->rb_infos[rb_id], &now); 819 } 820 } 821 822 wifi_error wifi_logger_ring_buffers_init(hal_info *info) 823 { 824 wifi_error ret; 825 826 ret = rb_init(info, &info->rb_infos[POWER_EVENTS_RB_ID], 827 POWER_EVENTS_RB_ID, 828 POWER_EVENTS_RB_BUF_SIZE, 829 POWER_EVENTS_NUM_BUFS, 830 power_events_ring_name); 831 if (ret != WIFI_SUCCESS) { 832 ALOGE("Failed to initialize power events ring buffer"); 833 goto cleanup; 834 } 835 836 ret = rb_init(info, &info->rb_infos[CONNECTIVITY_EVENTS_RB_ID], 837 CONNECTIVITY_EVENTS_RB_ID, 838 CONNECTIVITY_EVENTS_RB_BUF_SIZE, 839 CONNECTIVITY_EVENTS_NUM_BUFS, 840 connectivity_events_ring_name); 841 if (ret != WIFI_SUCCESS) { 842 ALOGE("Failed to initialize connectivity events ring buffer"); 843 goto cleanup; 844 } 845 846 ret = rb_init(info, &info->rb_infos[PKT_STATS_RB_ID], 847 PKT_STATS_RB_ID, 848 PKT_STATS_RB_BUF_SIZE, 849 PKT_STATS_NUM_BUFS, 850 pkt_stats_ring_name); 851 if (ret != WIFI_SUCCESS) { 852 ALOGE("Failed to initialize per packet stats ring buffer"); 853 goto cleanup; 854 } 855 856 ret = rb_init(info, &info->rb_infos[DRIVER_PRINTS_RB_ID], 857 DRIVER_PRINTS_RB_ID, 858 DRIVER_PRINTS_RB_BUF_SIZE, 859 DRIVER_PRINTS_NUM_BUFS, 860 driver_prints_ring_name); 861 if (ret != WIFI_SUCCESS) { 862 ALOGE("Failed to initialize driver prints ring buffer"); 863 goto cleanup; 864 } 865 866 ret = rb_init(info, &info->rb_infos[FIRMWARE_PRINTS_RB_ID], 867 FIRMWARE_PRINTS_RB_ID, 868 FIRMWARE_PRINTS_RB_BUF_SIZE, 869 FIRMWARE_PRINTS_NUM_BUFS, 870 firmware_prints_ring_name); 871 if (ret != WIFI_SUCCESS) { 872 ALOGE("Failed to initialize firmware prints ring buffer"); 873 goto cleanup; 874 } 875 876 pthread_mutex_init(&info->lh_lock, NULL); 877 pthread_mutex_init(&info->ah_lock, NULL); 878 879 return ret; 880 881 cleanup: 882 wifi_logger_ring_buffers_deinit(info); 883 return ret; 884 } 885 886 void wifi_logger_ring_buffers_deinit(hal_info *info) 887 { 888 int i; 889 890 for (i = 0; i < NUM_RING_BUFS; i++) { 891 rb_deinit(&info->rb_infos[i]); 892 } 893 pthread_mutex_destroy(&info->lh_lock); 894 pthread_mutex_destroy(&info->ah_lock); 895 } 896 897 898 /* Callback handlers registered for nl message send */ 899 static int error_handler_wifi_logger(struct sockaddr_nl *nla, 900 struct nlmsgerr *err, 901 void *arg) 902 { 903 struct sockaddr_nl *tmp; 904 int *ret = (int *)arg; 905 tmp = nla; 906 *ret = err->error; 907 ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret))); 908 return NL_STOP; 909 } 910 911 /* Callback handlers registered for nl message send */ 912 static int ack_handler_wifi_logger(struct nl_msg *msg, void *arg) 913 { 914 int *ret = (int *)arg; 915 struct nl_msg * a; 916 917 a = msg; 918 *ret = 0; 919 return NL_STOP; 920 } 921 922 /* Callback handlers registered for nl message send */ 923 static int finish_handler_wifi_logger(struct nl_msg *msg, void *arg) 924 { 925 int *ret = (int *)arg; 926 struct nl_msg * a; 927 928 a = msg; 929 *ret = 0; 930 return NL_SKIP; 931 } 932 933 int WifiLoggerCommand::requestEvent() 934 { 935 int res = -1; 936 struct nl_cb *cb; 937 938 cb = nl_cb_alloc(NL_CB_DEFAULT); 939 if (!cb) { 940 ALOGE("%s: Callback allocation failed",__FUNCTION__); 941 res = -1; 942 goto out; 943 } 944 945 /* Send message */ 946 res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage()); 947 if (res < 0) 948 goto out; 949 res = 1; 950 951 nl_cb_err(cb, NL_CB_CUSTOM, error_handler_wifi_logger, &res); 952 nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_wifi_logger, &res); 953 nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_wifi_logger, &res); 954 955 /* Err is populated as part of finish_handler. */ 956 while (res > 0){ 957 nl_recvmsgs(mInfo->cmd_sock, cb); 958 } 959 960 ALOGV("%s: Msg sent, res=%d, mWaitForRsp=%d", __FUNCTION__, res, mWaitforRsp); 961 /* Only wait for the asynchronous event if HDD returns success, res=0 */ 962 if (!res && (mWaitforRsp == true)) { 963 struct timespec abstime; 964 abstime.tv_sec = 4; 965 abstime.tv_nsec = 0; 966 res = mCondition.wait(abstime); 967 if (res == ETIMEDOUT) 968 { 969 ALOGE("%s: Time out happened.", __FUNCTION__); 970 } 971 ALOGV("%s: Command invoked return value:%d, mWaitForRsp=%d", 972 __FUNCTION__, res, mWaitforRsp); 973 } 974 out: 975 /* Cleanup the mMsg */ 976 mMsg.destroy(); 977 return res; 978 } 979 980 int WifiLoggerCommand::requestResponse() 981 { 982 return WifiCommand::requestResponse(mMsg); 983 } 984 985 int WifiLoggerCommand::handleResponse(WifiEvent &reply) { 986 int len = 0, version; 987 char version_type[20]; 988 char* memBuffer = NULL; 989 FILE* memDumpFilePtr = NULL; 990 WifiVendorCommand::handleResponse(reply); 991 992 memset(version_type, 0, 20); 993 switch(mSubcmd) 994 { 995 case QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO: 996 { 997 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1]; 998 999 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX, 1000 (struct nlattr *)mVendorData, mDataLen, NULL); 1001 1002 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) { 1003 len = nla_len(tb_vendor[ 1004 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]); 1005 memcpy(version_type, "Driver", strlen("Driver")); 1006 version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION; 1007 } else if ( 1008 tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) { 1009 len = nla_len( 1010 tb_vendor[ 1011 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]); 1012 memcpy(version_type, "Firmware", strlen("Firmware")); 1013 version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION; 1014 } 1015 if (len && mVersion && mVersionLen) { 1016 memset(mVersion, 0, mVersionLen); 1017 /* if len is greater than the incoming length then 1018 accommodate 1 lesser than mVersionLen to have the 1019 string terminated with '\0' */ 1020 len = (len > mVersionLen)? (mVersionLen - 1) : len; 1021 memcpy(mVersion, nla_data(tb_vendor[version]), len); 1022 ALOGV("%s: WLAN %s version : %s ", __FUNCTION__, 1023 version_type, mVersion); 1024 } 1025 } 1026 break; 1027 case QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET: 1028 { 1029 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1]; 1030 1031 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX, 1032 (struct nlattr *)mVendorData, mDataLen, NULL); 1033 1034 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]) { 1035 *mSupportedSet = 1036 nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]); 1037 #ifdef QC_HAL_DEBUG 1038 ALOGV("%s: Supported Feature Set : val 0x%x", 1039 __FUNCTION__, *mSupportedSet); 1040 #endif 1041 } 1042 } 1043 break; 1044 1045 case QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP: 1046 { 1047 u32 memDumpSize = 0; 1048 int numRecordsRead = 0; 1049 u32 remaining = 0; 1050 char* buffer = NULL; 1051 struct nlattr *tbVendor[ 1052 QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX + 1]; 1053 1054 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX, 1055 (struct nlattr *)mVendorData, 1056 mDataLen, NULL); 1057 1058 if (!tbVendor[ 1059 QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE]) { 1060 ALOGE("%s: LOGGER_RESULTS_MEMDUMP_SIZE not" 1061 "found", __FUNCTION__); 1062 break; 1063 } 1064 1065 memDumpSize = nla_get_u32( 1066 tbVendor[QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE] 1067 ); 1068 1069 /* Allocate the memory indicated in memDumpSize */ 1070 memBuffer = (char*) malloc(sizeof(char) * memDumpSize); 1071 if (memBuffer == NULL) { 1072 ALOGE("%s: No Memory for allocating Buffer ", 1073 "size of %d", __func__, memDumpSize); 1074 break; 1075 } 1076 memset(memBuffer, 0, sizeof(char) * memDumpSize); 1077 1078 ALOGI("%s: Memory Dump size: %u", __func__, 1079 memDumpSize); 1080 1081 /* Open the proc or debugfs filesystem */ 1082 memDumpFilePtr = fopen(LOGGER_MEMDUMP_FILENAME, "r"); 1083 if (memDumpFilePtr == NULL) { 1084 ALOGE("Failed to open %s file", LOGGER_MEMDUMP_FILENAME); 1085 break; 1086 } 1087 1088 /* Read the memDumpSize value at once */ 1089 numRecordsRead = fread(memBuffer, 1, memDumpSize, 1090 memDumpFilePtr); 1091 if (numRecordsRead <= 0 || 1092 numRecordsRead != (int) memDumpSize) { 1093 ALOGE("%s: Read %d failed for reading at once.", 1094 __func__, numRecordsRead); 1095 /* Lets try to read in chunks */ 1096 rewind(memDumpFilePtr); 1097 remaining = memDumpSize; 1098 buffer = memBuffer; 1099 while (remaining) { 1100 u32 readSize = 0; 1101 if (remaining >= LOGGER_MEMDUMP_CHUNKSIZE) { 1102 readSize = LOGGER_MEMDUMP_CHUNKSIZE; 1103 } 1104 else { 1105 readSize = remaining; 1106 } 1107 numRecordsRead = fread(buffer, 1, 1108 readSize, memDumpFilePtr); 1109 if (numRecordsRead) { 1110 remaining -= readSize; 1111 buffer += readSize; 1112 ALOGV("%s: Read successful for size:%u " 1113 "remaining:%u", __func__, readSize, 1114 remaining); 1115 } 1116 else { 1117 ALOGE("%s: Chunk read failed for size:%u", 1118 __func__, readSize); 1119 break; 1120 } 1121 } 1122 } 1123 1124 /* After successful read, call the callback handler*/ 1125 if (mHandler.on_firmware_memory_dump) { 1126 mHandler.on_firmware_memory_dump(memBuffer, 1127 memDumpSize); 1128 1129 } 1130 } 1131 break; 1132 case QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS: 1133 { 1134 struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_MAX +1]; 1135 1136 /* parse and extract wake reason stats */ 1137 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_WAKE_STATS_MAX, 1138 (struct nlattr *)mVendorData, 1139 mDataLen, NULL); 1140 1141 if (!tbVendor[ 1142 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE]) { 1143 ALOGE("%s: TOTAL_CMD_EVENT_WAKE not found", __FUNCTION__); 1144 break; 1145 } 1146 mGetWakeStats->total_cmd_event_wake = nla_get_u32( 1147 tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE]); 1148 1149 if (mGetWakeStats->total_cmd_event_wake && 1150 mGetWakeStats->cmd_event_wake_cnt) { 1151 if (!tbVendor[ 1152 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR]) { 1153 ALOGE("%s: CMD_EVENT_WAKE_CNT_PTR not found", __FUNCTION__); 1154 break; 1155 } 1156 len = nla_len(tbVendor[ 1157 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR]); 1158 mGetWakeStats->cmd_event_wake_cnt_used = 1159 (len < mGetWakeStats->cmd_event_wake_cnt_sz) ? len : 1160 mGetWakeStats->cmd_event_wake_cnt_sz; 1161 memcpy(mGetWakeStats->cmd_event_wake_cnt, 1162 nla_data(tbVendor[ 1163 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR]), 1164 (mGetWakeStats->cmd_event_wake_cnt_used * sizeof(int))); 1165 } else 1166 mGetWakeStats->cmd_event_wake_cnt_used = 0; 1167 1168 if (!tbVendor[ 1169 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE]) 1170 { 1171 ALOGE("%s: TOTAL_DRIVER_FW_LOCAL_WAKE not found", __FUNCTION__); 1172 break; 1173 } 1174 mGetWakeStats->total_driver_fw_local_wake = nla_get_u32(tbVendor[ 1175 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE]); 1176 1177 if (mGetWakeStats->total_driver_fw_local_wake && 1178 mGetWakeStats->driver_fw_local_wake_cnt) { 1179 if (!tbVendor[ 1180 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR]) 1181 { 1182 ALOGE("%s: DRIVER_FW_LOCAL_WAKE_CNT_PTR not found", 1183 __FUNCTION__); 1184 break; 1185 } 1186 len = nla_len(tbVendor[ 1187 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR]); 1188 mGetWakeStats->driver_fw_local_wake_cnt_used = 1189 (len < mGetWakeStats->driver_fw_local_wake_cnt_sz) ? len : 1190 mGetWakeStats->driver_fw_local_wake_cnt_sz; 1191 1192 memcpy(mGetWakeStats->driver_fw_local_wake_cnt, 1193 nla_data(tbVendor[ 1194 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR]), 1195 (mGetWakeStats->driver_fw_local_wake_cnt_used * sizeof(int))); 1196 } else 1197 mGetWakeStats->driver_fw_local_wake_cnt_used = 0; 1198 1199 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE]) { 1200 ALOGE("%s: TOTAL_RX_DATA_WAKE not found", __FUNCTION__); 1201 break; 1202 } 1203 mGetWakeStats->total_rx_data_wake = nla_get_u32(tbVendor[ 1204 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE]); 1205 1206 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT]) { 1207 ALOGE("%s: RX_UNICAST_CNT not found", __FUNCTION__); 1208 break; 1209 } 1210 mGetWakeStats->rx_wake_details.rx_unicast_cnt = nla_get_u32( 1211 tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT]); 1212 1213 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT]) { 1214 ALOGE("%s: RX_MULTICAST_CNT not found", __FUNCTION__); 1215 break; 1216 } 1217 mGetWakeStats->rx_wake_details.rx_multicast_cnt = nla_get_u32( 1218 tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT]); 1219 1220 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT]) { 1221 ALOGE("%s: RX_BROADCAST_CNT not found", __FUNCTION__); 1222 break; 1223 } 1224 mGetWakeStats->rx_wake_details.rx_broadcast_cnt = nla_get_u32( 1225 tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT]); 1226 1227 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT]) { 1228 ALOGE("%s: ICMP_PKT not found", __FUNCTION__); 1229 break; 1230 } 1231 mGetWakeStats->rx_wake_pkt_classification_info.icmp_pkt = 1232 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT]); 1233 1234 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT]) { 1235 ALOGE("%s: ICMP6_PKT not found", __FUNCTION__); 1236 break; 1237 } 1238 mGetWakeStats->rx_wake_pkt_classification_info.icmp6_pkt = 1239 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT]); 1240 1241 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA]) { 1242 ALOGE("%s: ICMP6_RA not found", __FUNCTION__); 1243 break; 1244 } 1245 mGetWakeStats->rx_wake_pkt_classification_info.icmp6_ra = 1246 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA]); 1247 1248 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA]) { 1249 ALOGE("%s: ICMP6_NA not found", __FUNCTION__); 1250 break; 1251 } 1252 mGetWakeStats->rx_wake_pkt_classification_info.icmp6_na = 1253 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA]); 1254 1255 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS]) { 1256 ALOGE("%s: ICMP6_NS not found", __FUNCTION__); 1257 break; 1258 } 1259 mGetWakeStats->rx_wake_pkt_classification_info.icmp6_ns = 1260 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS]); 1261 1262 if (!tbVendor[ 1263 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT]) { 1264 ALOGE("%s: ICMP4_RX_MULTICAST_CNT not found", __FUNCTION__); 1265 break; 1266 } 1267 mGetWakeStats->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt = 1268 nla_get_u32(tbVendor[ 1269 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT]); 1270 1271 if (!tbVendor[ 1272 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT]) { 1273 ALOGE("%s: ICMP6_RX_MULTICAST_CNT not found", __FUNCTION__); 1274 break; 1275 } 1276 mGetWakeStats->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt = 1277 nla_get_u32(tbVendor[ 1278 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT]); 1279 1280 if (!tbVendor[ 1281 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT]) { 1282 ALOGE("%s: OTHER_RX_MULTICAST_CNT not found", __FUNCTION__); 1283 break; 1284 } 1285 mGetWakeStats->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt = 1286 nla_get_u32(tbVendor[ 1287 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT]); 1288 1289 } 1290 break; 1291 1292 default : 1293 ALOGE("%s: Wrong Wifi Logger subcmd response received %d", 1294 __FUNCTION__, mSubcmd); 1295 } 1296 1297 /* free the allocated memory */ 1298 if (memBuffer) { 1299 free(memBuffer); 1300 } 1301 if (memDumpFilePtr) { 1302 fclose(memDumpFilePtr); 1303 } 1304 return NL_SKIP; 1305 } 1306 1307 /* This function will be the main handler for incoming (from driver) 1308 * WIFI_LOGGER_SUBCMD. 1309 * Calls the appropriate callback handler after parsing the vendor data. 1310 */ 1311 int WifiLoggerCommand::handleEvent(WifiEvent &event) 1312 { 1313 WifiVendorCommand::handleEvent(event); 1314 1315 switch(mSubcmd) 1316 { 1317 default: 1318 /* Error case should not happen print log */ 1319 ALOGE("%s: Wrong subcmd received %d", __func__, mSubcmd); 1320 break; 1321 } 1322 1323 return NL_SKIP; 1324 } 1325 1326 int WifiLoggerCommand::setCallbackHandler(WifiLoggerCallbackHandler nHandler) 1327 { 1328 int res = 0; 1329 mHandler = nHandler; 1330 res = registerVendorHandler(mVendor_id, mSubcmd); 1331 if (res != 0) { 1332 ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u", 1333 __FUNCTION__, mVendor_id, mSubcmd); 1334 } 1335 return res; 1336 } 1337 1338 void WifiLoggerCommand::unregisterHandler(u32 subCmd) 1339 { 1340 unregisterVendorHandler(mVendor_id, subCmd); 1341 } 1342 1343 int WifiLoggerCommand::timed_wait(u16 wait_time) 1344 { 1345 struct timespec absTime; 1346 absTime.tv_sec = wait_time; 1347 absTime.tv_nsec = 0; 1348 return mCondition.wait(absTime); 1349 } 1350 1351 void WifiLoggerCommand::waitForRsp(bool wait) 1352 { 1353 mWaitforRsp = wait; 1354 } 1355 1356 /* Function to get Driver memory dump */ 1357 wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface, 1358 wifi_driver_memory_dump_callbacks callback) 1359 { 1360 FILE *fp; 1361 size_t fileSize, remaining, readSize; 1362 size_t numRecordsRead; 1363 char *memBuffer = NULL, *buffer = NULL; 1364 1365 /* Open File */ 1366 fp = fopen(DRIVER_MEMDUMP_FILENAME, "r"); 1367 if (fp == NULL) { 1368 ALOGE("Failed to open %s file", DRIVER_MEMDUMP_FILENAME); 1369 return WIFI_ERROR_UNKNOWN; 1370 } 1371 1372 memBuffer = (char *) malloc(DRIVER_MEMDUMP_MAX_FILESIZE); 1373 if (memBuffer == NULL) { 1374 ALOGE("%s: malloc failed for size %d", __FUNCTION__, 1375 DRIVER_MEMDUMP_MAX_FILESIZE); 1376 fclose(fp); 1377 return WIFI_ERROR_OUT_OF_MEMORY; 1378 } 1379 1380 /* Read the DRIVER_MEMDUMP_MAX_FILESIZE value at once */ 1381 numRecordsRead = fread(memBuffer, 1, DRIVER_MEMDUMP_MAX_FILESIZE, fp); 1382 if (feof(fp)) 1383 fileSize = numRecordsRead; 1384 else if (numRecordsRead == DRIVER_MEMDUMP_MAX_FILESIZE) { 1385 ALOGE("%s: Reading only first %zu bytes from file", __FUNCTION__, 1386 numRecordsRead); 1387 fileSize = numRecordsRead; 1388 } else { 1389 ALOGE("%s: Read failed for reading at once, ret: %zu. Trying to read in" 1390 "chunks", __FUNCTION__, numRecordsRead); 1391 /* Lets try to read in chunks */ 1392 rewind(fp); 1393 remaining = DRIVER_MEMDUMP_MAX_FILESIZE; 1394 buffer = memBuffer; 1395 fileSize = 0; 1396 while (remaining) { 1397 readSize = 0; 1398 if (remaining >= LOGGER_MEMDUMP_CHUNKSIZE) 1399 readSize = LOGGER_MEMDUMP_CHUNKSIZE; 1400 else 1401 readSize = remaining; 1402 1403 numRecordsRead = fread(buffer, 1, readSize, fp); 1404 fileSize += numRecordsRead; 1405 if (feof(fp)) 1406 break; 1407 else if (numRecordsRead == readSize) { 1408 remaining -= readSize; 1409 buffer += readSize; 1410 ALOGV("%s: Read successful for size:%zu remaining:%zu", 1411 __FUNCTION__, readSize, remaining); 1412 } else { 1413 ALOGE("%s: Chunk read failed for size:%zu", __FUNCTION__, 1414 readSize); 1415 free(memBuffer); 1416 memBuffer = NULL; 1417 fclose(fp); 1418 return WIFI_ERROR_UNKNOWN; 1419 } 1420 } 1421 } 1422 ALOGV("%s filename: %s fileSize: %zu", __FUNCTION__, DRIVER_MEMDUMP_FILENAME, 1423 fileSize); 1424 /* After successful read, call the callback function*/ 1425 callback.on_driver_memory_dump(memBuffer, fileSize); 1426 1427 /* free the allocated memory */ 1428 free(memBuffer); 1429 fclose(fp); 1430 return WIFI_SUCCESS; 1431 } 1432 1433 /* Function to get wake lock stats */ 1434 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface, 1435 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt) 1436 { 1437 int requestId, ret = WIFI_SUCCESS; 1438 WifiLoggerCommand *wifiLoggerCommand; 1439 struct nlattr *nlData; 1440 interface_info *ifaceInfo = getIfaceInfo(iface); 1441 wifi_handle wifiHandle = getWifiHandle(iface); 1442 1443 /* No request id from caller, so generate one and pass it on to the driver. 1444 * Generate it randomly. 1445 */ 1446 requestId = get_requestid(); 1447 1448 if (!wifi_wake_reason_cnt) { 1449 ALOGE("%s: Invalid buffer provided. Exit.", 1450 __FUNCTION__); 1451 return WIFI_ERROR_INVALID_ARGS; 1452 } 1453 1454 wifiLoggerCommand = new WifiLoggerCommand( 1455 wifiHandle, 1456 requestId, 1457 OUI_QCA, 1458 QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS); 1459 if (wifiLoggerCommand == NULL) { 1460 ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__); 1461 return WIFI_ERROR_UNKNOWN; 1462 } 1463 1464 /* Create the NL message. */ 1465 ret = wifiLoggerCommand->create(); 1466 if (ret < 0) 1467 goto cleanup; 1468 1469 /* Set the interface Id of the message. */ 1470 ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name); 1471 if (ret < 0) 1472 goto cleanup; 1473 1474 wifiLoggerCommand->getWakeStatsRspParams(wifi_wake_reason_cnt); 1475 1476 /* Add the vendor specific attributes for the NL command. */ 1477 nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1478 if (!nlData) 1479 goto cleanup; 1480 1481 if (wifiLoggerCommand->put_u32( 1482 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ, 1483 wifi_wake_reason_cnt->cmd_event_wake_cnt_sz)) 1484 { 1485 goto cleanup; 1486 } 1487 1488 if (wifiLoggerCommand->put_u32( 1489 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ, 1490 wifi_wake_reason_cnt->driver_fw_local_wake_cnt_sz)) 1491 { 1492 goto cleanup; 1493 } 1494 wifiLoggerCommand->attr_end(nlData); 1495 1496 /* Send the msg and wait for a response. */ 1497 ret = wifiLoggerCommand->requestResponse(); 1498 if (ret) { 1499 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret); 1500 } 1501 1502 cleanup: 1503 delete wifiLoggerCommand; 1504 return (wifi_error)ret; 1505 } 1506 1507 void WifiLoggerCommand::getWakeStatsRspParams( 1508 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt) 1509 { 1510 mGetWakeStats = wifi_wake_reason_cnt; 1511 } 1512