Home | History | Annotate | Download | only in wifi_hal
      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