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