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