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 
     39 #define LOGGER_MEMDUMP_FILENAME "/proc/debug/fwdump"
     40 #define LOGGER_MEMDUMP_CHUNKSIZE (4 * 1024)
     41 
     42 char power_events_ring_name[] = "power_events_rb";
     43 char connectivity_events_ring_name[] = "connectivity_events_rb";
     44 char pkt_stats_ring_name[] = "pkt_stats_rb";
     45 char driver_prints_ring_name[] = "driver_prints_rb";
     46 char firmware_prints_ring_name[] = "firmware_prints_rb";
     47 
     48 static int get_ring_id(hal_info *info, char *ring_name)
     49 {
     50     int rb_id;
     51 
     52     for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
     53         if (is_rb_name_match(&info->rb_infos[rb_id], ring_name)) {
     54            return rb_id;
     55         }
     56     }
     57     return -1;
     58 }
     59 
     60 //Implementation of the functions exposed in wifi_logger.h
     61 
     62 /* Function to intiate logging */
     63 wifi_error wifi_start_logging(wifi_interface_handle iface,
     64                               u32 verbose_level, u32 flags,
     65                               u32 max_interval_sec, u32 min_data_size,
     66                               char *buffer_name)
     67 {
     68     int requestId, ret = 0;
     69     WifiLoggerCommand *wifiLoggerCommand = NULL;
     70     struct nlattr *nlData;
     71     interface_info *ifaceInfo = getIfaceInfo(iface);
     72     wifi_handle wifiHandle = getWifiHandle(iface);
     73     hal_info *info = getHalInfo(wifiHandle);
     74     int ring_id = 0;
     75 
     76     /*
     77      * No request id from caller, so generate one and pass it on to the driver.
     78      * Generate one randomly.
     79      */
     80     requestId = rand();
     81 
     82     if (buffer_name == NULL) {
     83         ALOGE("%s: Invalid Ring Name. \n", __FUNCTION__);
     84         return WIFI_ERROR_UNKNOWN;
     85     }
     86 
     87     ring_id = get_ring_id(info, buffer_name);
     88     if (ring_id < 0) {
     89         ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__);
     90         return WIFI_ERROR_UNKNOWN;
     91     }
     92 
     93     if ((ring_id == POWER_EVENTS_RB_ID) ||
     94         (ring_id == PKT_STATS_RB_ID)) {
     95         wifiLoggerCommand = new WifiLoggerCommand(
     96                                 wifiHandle,
     97                                 requestId,
     98                                 OUI_QCA,
     99                                 QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START);
    100 
    101         if (wifiLoggerCommand == NULL) {
    102            ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
    103            return WIFI_ERROR_UNKNOWN;
    104         }
    105         /* Create the NL message. */
    106         ret = wifiLoggerCommand->create();
    107 
    108         if (ret < 0)
    109             goto cleanup;
    110 
    111         /* Set the interface Id of the message. */
    112         ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
    113 
    114         if (ret < 0)
    115             goto cleanup;
    116 
    117         /* Add the vendor specific attributes for the NL command. */
    118         nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    119 
    120         if (!nlData)
    121             goto cleanup;
    122 
    123         if (wifiLoggerCommand->put_u32(
    124                     QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID, ring_id))
    125         {
    126             goto cleanup;
    127         }
    128         if (wifiLoggerCommand->put_u32(
    129                     QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL,
    130                     verbose_level))
    131         {
    132             goto cleanup;
    133         }
    134         if (wifiLoggerCommand->put_u32(
    135                     QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS,
    136                     flags))
    137         {
    138             goto cleanup;
    139         }
    140 
    141         wifiLoggerCommand->attr_end(nlData);
    142 
    143         /* Send the msg and wait for a response. */
    144         ret = wifiLoggerCommand->requestResponse();
    145         if (ret) {
    146             ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
    147         }
    148 
    149     }
    150     ALOGI("%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:%d 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     //TODO check locking
    202     if (info->on_alert) {
    203         info->on_alert(0, NULL, 0, reason_code);
    204     }
    205 }
    206 
    207 void WifiLoggerCommand::setFeatureSet(u32 *support) {
    208     mSupportedSet = support;
    209 }
    210 
    211 /*  Function to get the supported feature set for logging.*/
    212 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
    213                                                  u32 *support)
    214 {
    215 
    216     int requestId, ret = 0;
    217     WifiLoggerCommand *wifiLoggerCommand;
    218     struct nlattr *nlData;
    219     interface_info *ifaceInfo = getIfaceInfo(iface);
    220     wifi_handle wifiHandle = getWifiHandle(iface);
    221     hal_info *info = getHalInfo(wifiHandle);
    222 
    223     /* No request id from caller, so generate one and pass it on to the driver.
    224      * Generate one randomly.
    225      */
    226     requestId = rand();
    227 
    228     wifiLoggerCommand = new WifiLoggerCommand(
    229                             wifiHandle,
    230                             requestId,
    231                             OUI_QCA,
    232                             QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET);
    233 
    234     if (wifiLoggerCommand == NULL) {
    235         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
    236         return WIFI_ERROR_UNKNOWN;
    237     }
    238     /* Create the NL message. */
    239     ret = wifiLoggerCommand->create();
    240 
    241     if (ret < 0)
    242         goto cleanup;
    243 
    244     /* Set the interface Id of the message. */
    245     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
    246 
    247     if (ret < 0)
    248         goto cleanup;
    249 
    250     /* Add the vendor specific attributes for the NL command. */
    251     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    252 
    253     if (!nlData)
    254         goto cleanup;
    255 
    256     if (wifiLoggerCommand->put_u32(
    257                 QCA_WLAN_VENDOR_ATTR_FEATURE_SET, requestId))
    258     {
    259         goto cleanup;
    260     }
    261     wifiLoggerCommand->attr_end(nlData);
    262 
    263     wifiLoggerCommand->setFeatureSet(support);
    264 
    265     /* Send the msg and wait for a response. */
    266     ret = wifiLoggerCommand->requestResponse();
    267     if (ret) {
    268         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
    269     }
    270 
    271 cleanup:
    272     delete wifiLoggerCommand;
    273     return (wifi_error)ret;
    274 }
    275 
    276 /*  Function to get the data in each ring for the given ring ID.*/
    277 wifi_error wifi_get_ring_data(wifi_interface_handle iface,
    278                               char *ring_name)
    279 {
    280 
    281     int requestId, ret = 0;
    282     WifiLoggerCommand *wifiLoggerCommand;
    283     struct nlattr *nlData;
    284     interface_info *ifaceInfo = getIfaceInfo(iface);
    285     wifi_handle wifiHandle = getWifiHandle(iface);
    286     hal_info *info = getHalInfo(wifiHandle);
    287     int ring_id = 0;
    288 
    289     ring_id = get_ring_id(info, ring_name);
    290     if (ring_id < 0) {
    291         ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__);
    292         return WIFI_ERROR_UNKNOWN;
    293     }
    294 
    295     requestId = rand();
    296 
    297     wifiLoggerCommand = new WifiLoggerCommand(
    298                                 wifiHandle,
    299                                 requestId,
    300                                 OUI_QCA,
    301                                 QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA);
    302     if (wifiLoggerCommand == NULL) {
    303         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
    304         return WIFI_ERROR_UNKNOWN;
    305     }
    306     /* Create the NL message. */
    307     ret = wifiLoggerCommand->create();
    308 
    309     if (ret < 0)
    310         goto cleanup;
    311 
    312     /* Set the interface Id of the message. */
    313     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
    314 
    315     if (ret < 0)
    316         goto cleanup;
    317 
    318     /* Add the vendor specific attributes for the NL command. */
    319     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    320 
    321     if (!nlData)
    322         goto cleanup;
    323 
    324     if (wifiLoggerCommand->put_u32(
    325                 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID, ring_id))
    326     {
    327         goto cleanup;
    328     }
    329     wifiLoggerCommand->attr_end(nlData);
    330 
    331     //TBD  Is there requestResponse here
    332     /* Send the msg and wait for a response. */
    333     ret = wifiLoggerCommand->requestResponse();
    334     if (ret) {
    335         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
    336     }
    337 
    338 cleanup:
    339     delete wifiLoggerCommand;
    340     return (wifi_error)ret;
    341 }
    342 
    343 void WifiLoggerCommand::setVersionInfo(char *buffer, int buffer_size) {
    344     mVersion = buffer;
    345     mVersionLen = buffer_size;
    346 }
    347 
    348 /*  Function to send enable request to the wifi driver.*/
    349 wifi_error wifi_get_firmware_version(wifi_interface_handle iface,
    350                                      char *buffer, int buffer_size)
    351 {
    352     int requestId, ret = 0;
    353     WifiLoggerCommand *wifiLoggerCommand;
    354     struct nlattr *nlData;
    355     interface_info *ifaceInfo = getIfaceInfo(iface);
    356     wifi_handle wifiHandle = getWifiHandle(iface);
    357     hal_info *info = getHalInfo(wifiHandle);
    358 
    359     /* No request id from caller, so generate one and pass it on to the driver.
    360      * Generate one randomly.
    361      */
    362     requestId = rand();
    363 
    364     wifiLoggerCommand = new WifiLoggerCommand(
    365                                 wifiHandle,
    366                                 requestId,
    367                                 OUI_QCA,
    368                                 QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO);
    369     if (wifiLoggerCommand == NULL) {
    370         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
    371         return WIFI_ERROR_UNKNOWN;
    372     }
    373     /* Create the NL message. */
    374     ret = wifiLoggerCommand->create();
    375 
    376     if (ret < 0)
    377         goto cleanup;
    378 
    379     /* Set the interface Id of the message. */
    380     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
    381 
    382     if (ret < 0)
    383         goto cleanup;
    384 
    385     /* Add the vendor specific attributes for the NL command. */
    386     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    387 
    388     if (!nlData)
    389         goto cleanup;
    390 
    391     if (wifiLoggerCommand->put_u32(
    392                 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION, requestId))
    393     {
    394         goto cleanup;
    395     }
    396     wifiLoggerCommand->attr_end(nlData);
    397 
    398     wifiLoggerCommand->setVersionInfo(buffer, buffer_size);
    399 
    400     /* Send the msg and wait for a response. */
    401     ret = wifiLoggerCommand->requestResponse();
    402     if (ret) {
    403         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
    404     }
    405 cleanup:
    406     delete wifiLoggerCommand;
    407     return (wifi_error)ret;
    408 
    409 }
    410 
    411 /*  Function to get wlan driver version.*/
    412 wifi_error wifi_get_driver_version(wifi_interface_handle iface,
    413                                    char *buffer, int buffer_size)
    414 {
    415 
    416     int requestId, ret = 0;
    417     WifiLoggerCommand *wifiLoggerCommand;
    418     struct nlattr *nlData;
    419     interface_info *ifaceInfo = getIfaceInfo(iface);
    420     wifi_handle wifiHandle = getWifiHandle(iface);
    421     hal_info *info = getHalInfo(wifiHandle);
    422 
    423     /* No request id from caller, so generate one and pass it on to the driver.
    424      * Generate one randomly.
    425      */
    426     requestId = rand();
    427 
    428     wifiLoggerCommand = new WifiLoggerCommand(
    429                             wifiHandle,
    430                             requestId,
    431                             OUI_QCA,
    432                             QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO);
    433     if (wifiLoggerCommand == NULL) {
    434         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
    435         return WIFI_ERROR_UNKNOWN;
    436     }
    437     /* Create the NL message. */
    438     ret = wifiLoggerCommand->create();
    439 
    440     if (ret < 0)
    441         goto cleanup;
    442 
    443     /* Set the interface Id of the message. */
    444     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
    445 
    446     if (ret < 0)
    447         goto cleanup;
    448 
    449     /* Add the vendor specific attributes for the NL command. */
    450     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    451 
    452     if (!nlData)
    453         goto cleanup;
    454 
    455     if (wifiLoggerCommand->put_u32(
    456             QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION, requestId))
    457     {
    458         goto cleanup;
    459     }
    460     wifiLoggerCommand->attr_end(nlData);
    461 
    462     wifiLoggerCommand->setVersionInfo(buffer, buffer_size);
    463 
    464     /* Send the msg and wait for a response. */
    465     ret = wifiLoggerCommand->requestResponse();
    466     if (ret) {
    467         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
    468     }
    469 cleanup:
    470     delete wifiLoggerCommand;
    471     return (wifi_error)ret;
    472 }
    473 
    474 
    475 /* Function to get the Firmware memory dump. */
    476 wifi_error wifi_get_firmware_memory_dump(wifi_interface_handle iface,
    477                                 wifi_firmware_memory_dump_handler handler)
    478 {
    479     int requestId, ret = 0;
    480     WifiLoggerCommand *wifiLoggerCommand;
    481     struct nlattr *nlData;
    482     interface_info *ifaceInfo = getIfaceInfo(iface);
    483     wifi_handle wifiHandle = getWifiHandle(iface);
    484     hal_info *info = getHalInfo(wifiHandle);
    485 
    486     /* No request id from caller, so generate one and pass it on to the driver.
    487      * Generate one randomly.
    488      */
    489     requestId = rand();
    490 
    491     wifiLoggerCommand = new WifiLoggerCommand(
    492                             wifiHandle,
    493                             requestId,
    494                             OUI_QCA,
    495                             QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP);
    496     if (wifiLoggerCommand == NULL) {
    497         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
    498         return WIFI_ERROR_UNKNOWN;
    499     }
    500     /* Create the NL message. */
    501     ret = wifiLoggerCommand->create();
    502 
    503     if (ret < 0)
    504         goto cleanup;
    505 
    506     /* Set the interface Id of the message. */
    507     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
    508 
    509     if (ret < 0)
    510         goto cleanup;
    511 
    512     /* Add the vendor specific attributes for the NL command. */
    513     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    514 
    515     if (!nlData)
    516         goto cleanup;
    517 
    518     wifiLoggerCommand->attr_end(nlData);
    519 
    520     /* copy the callback into callback handler */
    521     WifiLoggerCallbackHandler callbackHandler;
    522     memset(&callbackHandler, 0, sizeof(callbackHandler));
    523     callbackHandler.on_firmware_memory_dump = \
    524         handler.on_firmware_memory_dump;
    525 
    526     ret = wifiLoggerCommand->setCallbackHandler(callbackHandler);
    527     if (ret < 0)
    528         goto cleanup;
    529 
    530     /* Send the msg and wait for the memory dump event */
    531     wifiLoggerCommand->waitForRsp(true);
    532     ret = wifiLoggerCommand->requestEvent();
    533     if (ret) {
    534         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
    535     }
    536 
    537 cleanup:
    538     delete wifiLoggerCommand;
    539     return (wifi_error)ret;
    540 }
    541 
    542 wifi_error wifi_set_log_handler(wifi_request_id id,
    543                                 wifi_interface_handle iface,
    544                                 wifi_ring_buffer_data_handler handler)
    545 {
    546     wifi_handle wifiHandle = getWifiHandle(iface);
    547     hal_info *info = getHalInfo(wifiHandle);
    548 
    549     info->on_ring_buffer_data = handler.on_ring_buffer_data;
    550     if (handler.on_ring_buffer_data == NULL) {
    551         ALOGE("Input handler is NULL");
    552         return WIFI_ERROR_UNKNOWN;
    553     }
    554     return WIFI_SUCCESS;
    555 }
    556 
    557 wifi_error wifi_reset_log_handler(wifi_request_id id,
    558                                   wifi_interface_handle iface)
    559 {
    560     wifi_handle wifiHandle = getWifiHandle(iface);
    561     hal_info *info = getHalInfo(wifiHandle);
    562 
    563     /* Some locking needs to be introduced here */
    564     info->on_ring_buffer_data = NULL;
    565     return WIFI_SUCCESS;
    566 }
    567 
    568 wifi_error wifi_set_alert_handler(wifi_request_id id,
    569                                   wifi_interface_handle iface,
    570                                   wifi_alert_handler handler)
    571 {
    572     wifi_handle wifiHandle = getWifiHandle(iface);
    573     hal_info *info = getHalInfo(wifiHandle);
    574 
    575     if (handler.on_alert) {
    576         ALOGE("Input handler is NULL");
    577         return WIFI_ERROR_UNKNOWN;
    578     }
    579     //TODO check locking
    580     info->on_alert = handler.on_alert;
    581     return WIFI_SUCCESS;
    582 }
    583 
    584 wifi_error wifi_reset_alert_handler(wifi_request_id id,
    585                                     wifi_interface_handle iface)
    586 {
    587     wifi_handle wifiHandle = getWifiHandle(iface);
    588     hal_info *info = getHalInfo(wifiHandle);
    589 
    590     /* Some locking needs to be introduced here */
    591     info->on_alert = NULL;
    592     return WIFI_SUCCESS;
    593 }
    594 
    595 WifiLoggerCommand::WifiLoggerCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
    596         : WifiVendorCommand(handle, id, vendor_id, subcmd)
    597 {
    598     ALOGV("WifiLoggerCommand %p constructed", this);
    599     mVersion = NULL;
    600     mVersionLen = 0;
    601     mRequestId = id;
    602     memset(&mHandler, 0,sizeof(mHandler));
    603     mWaitforRsp = false;
    604     mMoreData = false;
    605     mSupportedSet = NULL;
    606 }
    607 
    608 WifiLoggerCommand::~WifiLoggerCommand()
    609 {
    610     ALOGD("WifiLoggerCommand %p destructor", this);
    611     unregisterVendorHandler(mVendor_id, mSubcmd);
    612 }
    613 
    614 /* This function implements creation of Vendor command */
    615 int WifiLoggerCommand::create() {
    616     int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
    617     if (ret < 0) {
    618         return ret;
    619     }
    620 
    621     /* Insert the oui in the msg */
    622     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
    623     if (ret < 0)
    624         goto out;
    625     /* Insert the subcmd in the msg */
    626     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
    627     if (ret < 0)
    628         goto out;
    629 
    630      ALOGI("%s: mVendor_id = %d, Subcmd = %d.",
    631         __FUNCTION__, mVendor_id, mSubcmd);
    632 
    633 out:
    634     return ret;
    635 }
    636 
    637 void rb_timerhandler(hal_info *info)
    638 {
    639    struct timeval now;
    640    int rb_id;
    641 
    642    gettimeofday(&now,NULL);
    643    for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
    644        rb_check_for_timeout(&info->rb_infos[rb_id], &now);
    645    }
    646 }
    647 
    648 wifi_error wifi_logger_ring_buffers_init(hal_info *info)
    649 {
    650     wifi_error ret;
    651 
    652     ret = rb_init(info, &info->rb_infos[POWER_EVENTS_RB_ID],
    653                   POWER_EVENTS_RB_ID,
    654                   POWER_EVENTS_RB_BUF_SIZE,
    655                   POWER_EVENTS_NUM_BUFS,
    656                   power_events_ring_name);
    657     if (ret != WIFI_SUCCESS) {
    658         ALOGE("Failed to initialize power events ring buffer");
    659         goto cleanup;
    660     }
    661 
    662     ret = rb_init(info, &info->rb_infos[CONNECTIVITY_EVENTS_RB_ID],
    663                   CONNECTIVITY_EVENTS_RB_ID,
    664                   CONNECTIVITY_EVENTS_RB_BUF_SIZE,
    665                   CONNECTIVITY_EVENTS_NUM_BUFS,
    666                   connectivity_events_ring_name);
    667     if (ret != WIFI_SUCCESS) {
    668         ALOGE("Failed to initialize connectivity events ring buffer");
    669         goto cleanup;
    670     }
    671 
    672     ret = rb_init(info, &info->rb_infos[PKT_STATS_RB_ID],
    673                   PKT_STATS_RB_ID,
    674                   PKT_STATS_RB_BUF_SIZE,
    675                   PKT_STATS_NUM_BUFS,
    676                   pkt_stats_ring_name);
    677     if (ret != WIFI_SUCCESS) {
    678         ALOGE("Failed to initialize per packet stats ring buffer");
    679         goto cleanup;
    680     }
    681 
    682     ret = rb_init(info, &info->rb_infos[DRIVER_PRINTS_RB_ID],
    683                   DRIVER_PRINTS_RB_ID,
    684                   DRIVER_PRINTS_RB_BUF_SIZE,
    685                   DRIVER_PRINTS_NUM_BUFS,
    686                   driver_prints_ring_name);
    687     if (ret != WIFI_SUCCESS) {
    688         ALOGE("Failed to initialize driver prints ring buffer");
    689         goto cleanup;
    690     }
    691 
    692     ret = rb_init(info, &info->rb_infos[FIRMWARE_PRINTS_RB_ID],
    693                   FIRMWARE_PRINTS_RB_ID,
    694                   FIRMWARE_PRINTS_RB_BUF_SIZE,
    695                   FIRMWARE_PRINTS_NUM_BUFS,
    696                   firmware_prints_ring_name);
    697     if (ret != WIFI_SUCCESS) {
    698         ALOGE("Failed to initialize firmware prints ring buffer");
    699         goto cleanup;
    700     }
    701 
    702     return ret;
    703 
    704 cleanup:
    705     wifi_logger_ring_buffers_deinit(info);
    706     return ret;
    707 }
    708 
    709 void wifi_logger_ring_buffers_deinit(hal_info *info)
    710 {
    711     int i;
    712 
    713     for (i = 0; i < NUM_RING_BUFS; i++) {
    714         rb_deinit(&info->rb_infos[i]);
    715     }
    716 }
    717 
    718 
    719 /* Callback handlers registered for nl message send */
    720 static int error_handler_wifi_logger(struct sockaddr_nl *nla,
    721                                      struct nlmsgerr *err,
    722                                      void *arg)
    723 {
    724     struct sockaddr_nl *tmp;
    725     int *ret = (int *)arg;
    726     tmp = nla;
    727     *ret = err->error;
    728     ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret)));
    729     return NL_STOP;
    730 }
    731 
    732 /* Callback handlers registered for nl message send */
    733 static int ack_handler_wifi_logger(struct nl_msg *msg, void *arg)
    734 {
    735     int *ret = (int *)arg;
    736     struct nl_msg * a;
    737 
    738     ALOGE("%s: called", __FUNCTION__);
    739     a = msg;
    740     *ret = 0;
    741     return NL_STOP;
    742 }
    743 
    744 /* Callback handlers registered for nl message send */
    745 static int finish_handler_wifi_logger(struct nl_msg *msg, void *arg)
    746 {
    747   int *ret = (int *)arg;
    748   struct nl_msg * a;
    749 
    750   ALOGE("%s: called", __FUNCTION__);
    751   a = msg;
    752   *ret = 0;
    753   return NL_SKIP;
    754 }
    755 
    756 int WifiLoggerCommand::requestEvent()
    757 {
    758     int res = -1;
    759     struct nl_cb *cb;
    760 
    761     ALOGD("%s: Entry.", __FUNCTION__);
    762 
    763     cb = nl_cb_alloc(NL_CB_DEFAULT);
    764     if (!cb) {
    765         ALOGE("%s: Callback allocation failed",__FUNCTION__);
    766         res = -1;
    767         goto out;
    768     }
    769 
    770     /* Send message */
    771     res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
    772     if (res < 0)
    773         goto out;
    774     res = 1;
    775 
    776     nl_cb_err(cb, NL_CB_CUSTOM, error_handler_wifi_logger, &res);
    777     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_wifi_logger, &res);
    778     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_wifi_logger, &res);
    779 
    780     /* Err is populated as part of finish_handler. */
    781     while (res > 0){
    782          nl_recvmsgs(mInfo->cmd_sock, cb);
    783     }
    784 
    785     ALOGD("%s: Msg sent, res=%d, mWaitForRsp=%d", __FUNCTION__, res, mWaitforRsp);
    786     /* Only wait for the asynchronous event if HDD returns success, res=0 */
    787     if (!res && (mWaitforRsp == true)) {
    788         struct timespec abstime;
    789         abstime.tv_sec = 4;
    790         abstime.tv_nsec = 0;
    791         res = mCondition.wait(abstime);
    792         if (res == ETIMEDOUT)
    793         {
    794             ALOGE("%s: Time out happened.", __FUNCTION__);
    795         }
    796         ALOGD("%s: Command invoked return value:%d, mWaitForRsp=%d",
    797             __FUNCTION__, res, mWaitforRsp);
    798     }
    799 out:
    800     /* Cleanup the mMsg */
    801     mMsg.destroy();
    802     return res;
    803 }
    804 
    805 int WifiLoggerCommand::requestResponse()
    806 {
    807     return WifiCommand::requestResponse(mMsg);
    808 }
    809 
    810 int WifiLoggerCommand::handleResponse(WifiEvent &reply) {
    811     ALOGD("Received a WifiLogger response message from Driver");
    812     u32 status;
    813     int ret = WIFI_SUCCESS;
    814     int i = 0;
    815     int len = 0, version;
    816     char version_type[20];
    817     WifiVendorCommand::handleResponse(reply);
    818 
    819     switch(mSubcmd)
    820     {
    821         case QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO:
    822         {
    823             struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
    824 
    825             nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
    826                             (struct nlattr *)mVendorData, mDataLen, NULL);
    827 
    828             if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
    829                 len = nla_len(tb_vendor[
    830                         QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]);
    831                 memcpy(version_type, "Driver", strlen("Driver"));
    832                 version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION;
    833             } else if (
    834                 tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
    835                 len = nla_len(
    836                         tb_vendor[
    837                         QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]);
    838                 memcpy(version_type, "Firmware", strlen("Firmware"));
    839                 version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION;
    840             }
    841             if (len && mVersion && mVersionLen) {
    842                 memset(mVersion, 0, mVersionLen);
    843                 /* if len is greater than the incoming length then
    844                    accommodate 1 lesser than mVersionLen to have the
    845                    string terminated with '\0' */
    846                 len = (len > mVersionLen)? (mVersionLen - 1) : len;
    847                 memcpy(mVersion, nla_data(tb_vendor[version]), len);
    848                 ALOGD("%s: WLAN version len : %d", __FUNCTION__, len);
    849                 ALOGD("%s: WLAN %s version : %s ", __FUNCTION__,
    850                       version_type, mVersion);
    851             }
    852         }
    853         break;
    854         case QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET:
    855         {
    856             struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
    857 
    858             nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
    859                             (struct nlattr *)mVendorData, mDataLen, NULL);
    860 
    861             if (tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]) {
    862                 *mSupportedSet =
    863                 nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
    864                 ALOGD("%s: Supported Feature Set : val 0x%x",
    865                       __FUNCTION__, *mSupportedSet);
    866             }
    867         }
    868         break;
    869         default :
    870             ALOGE("%s: Wrong Wifi Logger subcmd response received %d",
    871                 __FUNCTION__, mSubcmd);
    872     }
    873 
    874     return NL_SKIP;
    875 }
    876 
    877 /* This function will be the main handler for incoming (from driver)
    878  * WIFI_LOGGER_SUBCMD.
    879  * Calls the appropriate callback handler after parsing the vendor data.
    880  */
    881 int WifiLoggerCommand::handleEvent(WifiEvent &event)
    882 {
    883     unsigned i = 0;
    884     u32 status;
    885     int ret = WIFI_SUCCESS;
    886     char* memBuffer = NULL;
    887     FILE* memDumpFilePtr = NULL;
    888 
    889     WifiVendorCommand::handleEvent(event);
    890 
    891     struct nlattr *tbVendor[
    892         QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX + 1];
    893     nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX,
    894             (struct nlattr *)mVendorData,
    895             mDataLen, NULL);
    896 
    897     switch(mSubcmd)
    898     {
    899         case QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP:
    900         {
    901             int id = 0;
    902             u32 memDumpSize = 0;
    903             int numRecordsRead = 0;
    904             u32 remaining = 0;
    905             char* buffer = NULL;
    906 
    907             if (!tbVendor[
    908                 QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_REQUEST_ID]) {
    909                 ALOGE("%s: LOGGER_RESULTS_REQUEST_ID not"
    910                     "found, continuing...", __func__);
    911             }
    912             else {
    913                 id = nla_get_u32(tbVendor[
    914                           QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_REQUEST_ID]
    915                       );
    916                 ALOGI("%s: Event has Req. ID:%d, ours:%d",
    917                     __func__, id, mRequestId);
    918             }
    919 
    920             if (!tbVendor[
    921                 QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE]) {
    922                 ALOGE("%s: LOGGER_RESULTS_MEMDUMP_SIZE not"
    923                     "found", __func__);
    924                 break;
    925             }
    926 
    927             memDumpSize = nla_get_u32(
    928                 tbVendor[QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE]
    929                 );
    930 
    931             /* Allocate the memory indicated in memDumpSize */
    932             memBuffer = (char*) malloc(sizeof(char) * memDumpSize);
    933             if (memBuffer == NULL) {
    934                 ALOGE("%s: No Memory for allocating Buffer ",
    935                       "size of %d", __func__, memDumpSize);
    936                 break;
    937             }
    938             memset(memBuffer, 0, sizeof(char) * memDumpSize);
    939 
    940             ALOGI("%s: Memory Dump size: %u", __func__,
    941                   memDumpSize);
    942 
    943             /* Open the proc or debugfs filesystem */
    944             memDumpFilePtr = fopen(LOGGER_MEMDUMP_FILENAME, "r");
    945             if (memDumpFilePtr == NULL) {
    946                 ALOGE("Failed to open %s file", LOGGER_MEMDUMP_FILENAME);
    947                 break;
    948             }
    949 
    950             /* Read the memDumpSize value at once */
    951             numRecordsRead = fread(memBuffer, 1, memDumpSize,
    952                                    memDumpFilePtr);
    953             if (numRecordsRead <= 0 ||
    954                 numRecordsRead != (int) memDumpSize) {
    955                 ALOGE("%s: Read %d failed for reading at once.",
    956                       __func__, numRecordsRead);
    957                 /* Lets try to read in chunks */
    958                 rewind(memDumpFilePtr);
    959                 remaining = memDumpSize;
    960                 buffer = memBuffer;
    961                 while (remaining) {
    962                     u32 readSize = 0;
    963                     if (remaining >= LOGGER_MEMDUMP_CHUNKSIZE) {
    964                         readSize = LOGGER_MEMDUMP_CHUNKSIZE;
    965                     }
    966                     else {
    967                         readSize = remaining;
    968                     }
    969                     numRecordsRead = fread(buffer, 1,
    970                                            readSize, memDumpFilePtr);
    971                     if (numRecordsRead) {
    972                         remaining -= readSize;
    973                         buffer += readSize;
    974                         ALOGI("%s: Read successful for size:%u "
    975                               "remaining:%u", __func__, readSize,
    976                               remaining);
    977                     }
    978                     else {
    979                         ALOGE("%s: Chunk read failed for size:%u",
    980                               __func__, readSize);
    981                         break;
    982                     }
    983                 }
    984             }
    985 
    986             /* After successful read, call the callback handler*/
    987             if (mHandler.on_firmware_memory_dump) {
    988                 mHandler.on_firmware_memory_dump(memBuffer,
    989                                                  memDumpSize);
    990 
    991             }
    992         }
    993         break;
    994 
    995        default:
    996            /* Error case should not happen print log */
    997            ALOGE("%s: Wrong subcmd received %d", __func__, mSubcmd);
    998            break;
    999     }
   1000 
   1001 cleanup:
   1002     /* free the allocated memory */
   1003     if (memBuffer) {
   1004         free(memBuffer);
   1005     }
   1006     return NL_SKIP;
   1007 }
   1008 
   1009 int WifiLoggerCommand::setCallbackHandler(WifiLoggerCallbackHandler nHandler)
   1010 {
   1011     int res = 0;
   1012     mHandler = nHandler;
   1013     res = registerVendorHandler(mVendor_id, mSubcmd);
   1014     if (res != 0) {
   1015         ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
   1016               __FUNCTION__, mVendor_id, mSubcmd);
   1017     }
   1018     return res;
   1019 }
   1020 
   1021 void WifiLoggerCommand::unregisterHandler(u32 subCmd)
   1022 {
   1023     unregisterVendorHandler(mVendor_id, subCmd);
   1024 }
   1025 
   1026 int WifiLoggerCommand::timed_wait(u16 wait_time)
   1027 {
   1028     struct timespec absTime;
   1029     int res;
   1030     absTime.tv_sec = wait_time;
   1031     absTime.tv_nsec = 0;
   1032     return mCondition.wait(absTime);
   1033 }
   1034 
   1035 void WifiLoggerCommand::waitForRsp(bool wait)
   1036 {
   1037     mWaitforRsp = wait;
   1038 }
   1039 
   1040