Home | History | Annotate | Download | only in wifi_hal
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "sync.h"
     18 
     19 #define LOG_TAG  "WifiHAL"
     20 
     21 #include <utils/Log.h>
     22 
     23 #include "wifi_hal.h"
     24 #include "common.h"
     25 #include "cpp_bindings.h"
     26 #include "llstatscommand.h"
     27 #include "vendor_definitions.h"
     28 
     29 //Singleton Static Instance
     30 LLStatsCommand* LLStatsCommand::mLLStatsCommandInstance  = NULL;
     31 
     32 // This function implements creation of Vendor command
     33 // For LLStats just call base Vendor command create
     34 int LLStatsCommand::create() {
     35     int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
     36     if (ret < 0) {
     37         return ret;
     38     }
     39     // insert the oui in the msg
     40     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
     41     if (ret < 0)
     42         goto out;
     43 
     44     // insert the subcmd in the msg
     45     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
     46     if (ret < 0)
     47         goto out;
     48 
     49 out:
     50     return ret;
     51 }
     52 
     53 LLStatsCommand::LLStatsCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
     54         : WifiVendorCommand(handle, id, vendor_id, subcmd)
     55 {
     56     memset(&mClearRspParams, 0,sizeof(LLStatsClearRspParams));
     57     memset(&mResultsParams, 0,sizeof(LLStatsResultsParams));
     58     memset(&mHandler, 0,sizeof(mHandler));
     59 }
     60 
     61 LLStatsCommand::~LLStatsCommand()
     62 {
     63     mLLStatsCommandInstance = NULL;
     64 }
     65 
     66 LLStatsCommand* LLStatsCommand::instance(wifi_handle handle)
     67 {
     68     if (handle == NULL) {
     69         ALOGE("Interface Handle is invalid");
     70         return NULL;
     71     }
     72     if (mLLStatsCommandInstance == NULL) {
     73         mLLStatsCommandInstance = new LLStatsCommand(handle, 0,
     74                 OUI_QCA,
     75                 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
     76         return mLLStatsCommandInstance;
     77     }
     78     else
     79     {
     80         if (handle != getWifiHandle(mLLStatsCommandInstance->mInfo))
     81         {
     82             /* upper layer must have cleaned up the handle and reinitialized,
     83                so we need to update the same */
     84             ALOGE("Handle different, update the handle");
     85             mLLStatsCommandInstance->mInfo = (hal_info *)handle;
     86         }
     87     }
     88     return mLLStatsCommandInstance;
     89 }
     90 
     91 void LLStatsCommand::initGetContext(u32 reqId)
     92 {
     93     mRequestId = reqId;
     94     memset(&mResultsParams, 0,sizeof(LLStatsResultsParams));
     95     memset(&mHandler, 0,sizeof(mHandler));
     96 }
     97 
     98 void LLStatsCommand::setSubCmd(u32 subcmd)
     99 {
    100     mSubcmd = subcmd;
    101 }
    102 
    103 void LLStatsCommand::setHandler(wifi_stats_result_handler handler)
    104 {
    105     mHandler = handler;
    106 }
    107 
    108 static wifi_error get_wifi_interface_info(wifi_interface_link_layer_info *stats,
    109                                           struct nlattr **tb_vendor)
    110 {
    111     u32 len = 0;
    112 
    113     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE])
    114     {
    115         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE not found", __FUNCTION__);
    116         return WIFI_ERROR_INVALID_ARGS;
    117     }
    118     stats->mode = (wifi_interface_mode)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE]);
    119 
    120 
    121     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR])
    122     {
    123         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR not found", __FUNCTION__);
    124         return WIFI_ERROR_INVALID_ARGS;
    125     }
    126     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR]);
    127     len = ((sizeof(stats->mac_addr) <= len) ? sizeof(stats->mac_addr) : len);
    128     memcpy(&stats->mac_addr[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR]), len);
    129 
    130     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE])
    131     {
    132         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE not found", __FUNCTION__);
    133         return WIFI_ERROR_INVALID_ARGS;
    134     }
    135     stats->state = (wifi_connection_state)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE]);
    136 
    137     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING])
    138     {
    139         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING not found", __FUNCTION__);
    140         return WIFI_ERROR_INVALID_ARGS;
    141     }
    142     stats->roaming = (wifi_roam_state)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING]);
    143 
    144     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES])
    145     {
    146         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES not found", __FUNCTION__);
    147         return WIFI_ERROR_INVALID_ARGS;
    148     }
    149     stats->capabilities = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES]);
    150 
    151     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID])
    152     {
    153         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID not found", __FUNCTION__);
    154         return WIFI_ERROR_INVALID_ARGS;
    155     }
    156     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID]);
    157     len = ((sizeof(stats->ssid) <= len) ? sizeof(stats->ssid) : len);
    158     memcpy(&stats->ssid[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID]), len);
    159 
    160     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID])
    161     {
    162         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID not found", __FUNCTION__);
    163         return WIFI_ERROR_INVALID_ARGS;
    164     }
    165     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID]);
    166     len = ((sizeof(stats->bssid) <= len) ? sizeof(stats->bssid) : len);
    167     memcpy(&stats->bssid[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID]), len);
    168 
    169     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR])
    170     {
    171         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR not found", __FUNCTION__);
    172         return WIFI_ERROR_INVALID_ARGS;
    173     }
    174     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR]);
    175     len = ((sizeof(stats->ap_country_str) <= len) ? sizeof(stats->ap_country_str) : len);
    176     memcpy(&stats->ap_country_str[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR]),
    177            len);
    178 
    179     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR])
    180     {
    181         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR not found", __FUNCTION__);
    182         return WIFI_ERROR_INVALID_ARGS;
    183     }
    184     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR]);
    185     len = ((sizeof(stats->country_str) < len) ? sizeof(stats->country_str) : len);
    186     memcpy(&stats->country_str[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR]),
    187            len);
    188 #if QC_HAL_DEBUG
    189     ALOGV("Mode : %d\n"
    190           "Mac addr : "
    191           MAC_ADDR_STR
    192           "\nState : %d\n"
    193           "Roaming : %d\n"
    194           "capabilities : %0x\n"
    195           "SSID :%s\n"
    196           "BSSID : "
    197           MAC_ADDR_STR
    198           "\nAP country str : %c%c%c\n"
    199           "Country String for this Association : %c%c%c",
    200           stats->mode,
    201           MAC_ADDR_ARRAY(stats->mac_addr),
    202           stats->state,
    203           stats->roaming,
    204           stats->capabilities,
    205           stats->ssid,
    206           MAC_ADDR_ARRAY(stats->bssid),
    207           stats->ap_country_str[0],
    208           stats->ap_country_str[1],
    209           stats->ap_country_str[2],
    210           stats->country_str[0],
    211           stats->country_str[1],
    212           stats->country_str[2]);
    213 #endif
    214     return WIFI_SUCCESS;
    215 }
    216 
    217 static wifi_error get_wifi_wmm_ac_stat(wifi_wmm_ac_stat *stats,
    218                                        struct nlattr **tb_vendor)
    219 {
    220 
    221     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC])
    222     {
    223         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC not found", __FUNCTION__);
    224         return WIFI_ERROR_INVALID_ARGS;
    225     }
    226     stats->ac                     = (wifi_traffic_ac)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC]);
    227 
    228     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU])
    229     {
    230         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU not found", __FUNCTION__);
    231         return WIFI_ERROR_INVALID_ARGS;
    232     }
    233     stats->tx_mpdu                = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU]);
    234 
    235     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU])
    236     {
    237         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU not found", __FUNCTION__);
    238         return WIFI_ERROR_INVALID_ARGS;
    239     }
    240     stats->rx_mpdu                = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU]);
    241 
    242     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST])
    243     {
    244         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST not found", __FUNCTION__);
    245         return WIFI_ERROR_INVALID_ARGS;
    246     }
    247     stats->tx_mcast               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST]);
    248 
    249     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST])
    250     {
    251         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST not found", __FUNCTION__);
    252         return WIFI_ERROR_INVALID_ARGS;
    253     }
    254     stats->rx_mcast               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST]);
    255 
    256     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU])
    257     {
    258         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU not found", __FUNCTION__);
    259         return WIFI_ERROR_INVALID_ARGS;
    260     }
    261     stats->rx_ampdu               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU]);
    262 
    263     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU])
    264     {
    265         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU not found", __FUNCTION__);
    266         return WIFI_ERROR_INVALID_ARGS;
    267     }
    268     stats->tx_ampdu               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU]);
    269 
    270     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST])
    271     {
    272         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST not found", __FUNCTION__);
    273         return WIFI_ERROR_INVALID_ARGS;
    274     }
    275     stats->mpdu_lost              = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST]);
    276 
    277     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES])
    278     {
    279         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES not found", __FUNCTION__);
    280         return WIFI_ERROR_INVALID_ARGS;
    281     }
    282     stats->retries                = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES]);
    283 
    284     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT])
    285     {
    286         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT not found", __FUNCTION__);
    287         return WIFI_ERROR_INVALID_ARGS;
    288     }
    289     stats->retries_short          = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT]);
    290 
    291     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG])
    292     {
    293         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG not found", __FUNCTION__);
    294         return WIFI_ERROR_INVALID_ARGS;
    295     }
    296     stats->retries_long           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG]);
    297 
    298     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN])
    299     {
    300         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN not found", __FUNCTION__);
    301         return WIFI_ERROR_INVALID_ARGS;
    302     }
    303     stats->contention_time_min    = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN]);
    304 
    305     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX])
    306     {
    307         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX not found", __FUNCTION__);
    308         return WIFI_ERROR_INVALID_ARGS;
    309     }
    310     stats->contention_time_max    = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX]);
    311 
    312     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG])
    313     {
    314         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG not found", __FUNCTION__);
    315         return WIFI_ERROR_INVALID_ARGS;
    316     }
    317     stats->contention_time_avg    = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG]);
    318 
    319     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES])
    320     {
    321         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES not found", __FUNCTION__);
    322         return WIFI_ERROR_INVALID_ARGS;
    323     }
    324     stats->contention_num_samples = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES]);
    325 #ifdef QC_HAL_DEBUG
    326     ALOGV("%4u | %6u | %6u | %7u | %7u | %7u |"
    327           " %7u | %8u | %7u | %12u |"
    328           " %11u | %17u | %17u |"
    329           " %17u | %20u",
    330           stats->ac,
    331           stats->tx_mpdu,
    332           stats->rx_mpdu,
    333           stats->tx_mcast,
    334           stats->rx_mcast,
    335           stats->rx_ampdu,
    336           stats->tx_ampdu,
    337           stats->mpdu_lost,
    338           stats->retries,
    339           stats->retries_short,
    340           stats->retries_long,
    341           stats->contention_time_min,
    342           stats->contention_time_max,
    343           stats->contention_time_avg,
    344           stats->contention_num_samples);
    345 #endif
    346     return WIFI_SUCCESS;
    347 }
    348 
    349 static wifi_error get_wifi_rate_stat(wifi_rate_stat *stats,
    350                                      struct nlattr **tb_vendor)
    351 {
    352 
    353     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE])
    354     {
    355         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE not found", __FUNCTION__);
    356         return WIFI_ERROR_INVALID_ARGS;
    357     }
    358     stats->rate.preamble        = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE]);
    359 
    360     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS])
    361     {
    362         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS not found", __FUNCTION__);
    363         return WIFI_ERROR_INVALID_ARGS;
    364     }
    365     stats->rate.nss             = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS]);
    366 
    367     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW])
    368     {
    369         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW not found", __FUNCTION__);
    370         return WIFI_ERROR_INVALID_ARGS;
    371     }
    372     stats->rate.bw              = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW]);
    373 
    374     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX])
    375     {
    376         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX not found", __FUNCTION__);
    377         return WIFI_ERROR_INVALID_ARGS;
    378     }
    379     stats->rate.rateMcsIdx      = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX]);
    380 
    381     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE])
    382     {
    383         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE not found", __FUNCTION__);
    384         return WIFI_ERROR_INVALID_ARGS;
    385     }
    386     stats->rate.bitrate         = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE]);
    387 
    388     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU])
    389     {
    390         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU not found", __FUNCTION__);
    391         return WIFI_ERROR_INVALID_ARGS;
    392     }
    393     stats->tx_mpdu              = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU]);
    394 
    395     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU])
    396     {
    397         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU not found", __FUNCTION__);
    398         return WIFI_ERROR_INVALID_ARGS;
    399     }
    400     stats->rx_mpdu              = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU]);
    401 
    402     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST])
    403     {
    404         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST not found", __FUNCTION__);
    405         return WIFI_ERROR_INVALID_ARGS;
    406     }
    407     stats->mpdu_lost            = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST]);
    408 
    409     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES])
    410     {
    411         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES not found", __FUNCTION__);
    412         return WIFI_ERROR_INVALID_ARGS;
    413     }
    414     stats->retries              = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES]);
    415 
    416     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT])
    417     {
    418         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT not found", __FUNCTION__);
    419         return WIFI_ERROR_INVALID_ARGS;
    420     }
    421     stats->retries_short        = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT]);
    422 
    423     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG])
    424     {
    425         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG not found", __FUNCTION__);
    426         return WIFI_ERROR_INVALID_ARGS;
    427     }
    428     stats->retries_long         = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG]);
    429 #ifdef QC_HAL_DEBUG
    430     ALOGV("%8u | %3u | %2u | %10u | %7u | %6u | %6u | %8u | %7u | %12u | %11u",
    431           stats->rate.preamble,
    432           stats->rate.nss,
    433           stats->rate.bw,
    434           stats->rate.rateMcsIdx,
    435           stats->rate.bitrate,
    436           stats->tx_mpdu,
    437           stats->rx_mpdu,
    438           stats->mpdu_lost,
    439           stats->retries,
    440           stats->retries_short,
    441           stats->retries_long);
    442 #endif
    443     return WIFI_SUCCESS;
    444 }
    445 
    446 static wifi_error get_wifi_peer_info(wifi_peer_info *stats,
    447                                      struct nlattr **tb_vendor)
    448 {
    449     u32 i = 0, len = 0;
    450     int rem;
    451     wifi_rate_stat * pRateStats;
    452     struct nlattr *rateInfo;
    453     wifi_error ret = WIFI_SUCCESS;
    454 
    455     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE])
    456     {
    457         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE not found", __FUNCTION__);
    458         return WIFI_ERROR_INVALID_ARGS;
    459     }
    460     stats->type                   = (wifi_peer_type)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE]);
    461 
    462     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS])
    463     {
    464         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS not found", __FUNCTION__);
    465         return WIFI_ERROR_INVALID_ARGS;
    466     }
    467     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]);
    468     len = ((sizeof(stats->peer_mac_address) <= len) ? sizeof(stats->peer_mac_address) : len);
    469     memcpy((void *)&stats->peer_mac_address[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]),
    470             len);
    471 
    472     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES])
    473     {
    474         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES not found", __FUNCTION__);
    475         return WIFI_ERROR_INVALID_ARGS;
    476     }
    477     stats->capabilities           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES]);
    478 
    479     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES])
    480     {
    481         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES not found", __FUNCTION__);
    482         return WIFI_ERROR_INVALID_ARGS;
    483     }
    484     stats->num_rate               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
    485 #ifdef QC_HAL_DEBUG
    486     ALOGV("numPeers %u  Peer MAC addr :" MAC_ADDR_STR " capabilities %0x numRate %u",
    487            stats->type, MAC_ADDR_ARRAY(stats->peer_mac_address),
    488            stats->capabilities, stats->num_rate);
    489 #endif
    490 
    491     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO])
    492     {
    493         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO not found", __FUNCTION__);
    494         return WIFI_ERROR_INVALID_ARGS;
    495     }
    496 #ifdef QC_HAL_DEBUG
    497     ALOGV("%8s | %3s | %2s | %10s | %7s | %6s | %6s | %8s | %7s | %12s | %11s",
    498           "preamble", "nss", "bw", "rateMcsIdx", "bitrate", "txMpdu", "rxMpdu", "mpduLost", "retries", "retriesShort", "retriesLong");
    499 #endif
    500     for (rateInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_RATE_INFO]);
    501             nla_ok(rateInfo, rem);
    502             rateInfo = nla_next(rateInfo, &(rem)))
    503     {
    504         struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
    505         pRateStats = (wifi_rate_stat *) ((u8 *)stats->rate_stats + (i++ * sizeof(wifi_rate_stat)));
    506 
    507         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(rateInfo), nla_len(rateInfo), NULL);
    508         ret = get_wifi_rate_stat(pRateStats, tb2);
    509         if(ret != WIFI_SUCCESS)
    510         {
    511             return ret;
    512         }
    513     }
    514     return WIFI_SUCCESS;
    515 }
    516 
    517 wifi_error LLStatsCommand::get_wifi_iface_stats(wifi_iface_stat *stats,
    518                                                 struct nlattr **tb_vendor)
    519 {
    520     struct nlattr *wmmInfo;
    521     wifi_wmm_ac_stat *pWmmStats;
    522     int i=0, rem;
    523     wifi_error ret = WIFI_SUCCESS;
    524 
    525     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX])
    526     {
    527         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX"
    528                 "not found", __FUNCTION__);
    529         return WIFI_ERROR_INVALID_ARGS;
    530     }
    531     stats->beacon_rx = nla_get_u32(tb_vendor[
    532             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX]);
    533 
    534     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET])
    535     {
    536         stats->average_tsf_offset = 0;
    537     } else {
    538         stats->average_tsf_offset = nla_get_u64(tb_vendor[
    539                 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_AVERAGE_TSF_OFFSET]);
    540     }
    541 
    542     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED])
    543     {
    544         stats->leaky_ap_detected = 0;
    545     } else {
    546         stats->leaky_ap_detected = nla_get_u32(tb_vendor[
    547                 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_DETECTED]);
    548     }
    549 
    550     if (!tb_vendor[
    551         QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED])
    552     {
    553         stats->leaky_ap_avg_num_frames_leaked = 0;
    554     } else {
    555         stats->leaky_ap_avg_num_frames_leaked = nla_get_u32(tb_vendor[
    556            QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_AVG_NUM_FRAMES_LEAKED]);
    557     }
    558 
    559     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME])
    560     {
    561         stats->leaky_ap_guard_time = 0;
    562     } else {
    563         stats->leaky_ap_guard_time = nla_get_u32(tb_vendor[
    564                 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_LEAKY_AP_GUARD_TIME]);
    565     }
    566 
    567     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX])
    568     {
    569         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX"
    570                 " not found", __FUNCTION__);
    571         return WIFI_ERROR_INVALID_ARGS;
    572     }
    573     stats->mgmt_rx         = nla_get_u32(tb_vendor[
    574             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX]);
    575 
    576     if (!tb_vendor[
    577             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX])
    578     {
    579         ALOGE("%s: "
    580                 "QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX"
    581                 " not found", __FUNCTION__);
    582         return WIFI_ERROR_INVALID_ARGS;
    583     }
    584     stats->mgmt_action_rx  = nla_get_u32(tb_vendor[
    585             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX]);
    586 
    587     if (!tb_vendor[
    588             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX])
    589     {
    590         ALOGE("%s: "
    591                 "QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX"
    592                 " not found", __FUNCTION__);
    593         return WIFI_ERROR_INVALID_ARGS;
    594     }
    595     stats->mgmt_action_tx  = nla_get_u32(tb_vendor[
    596             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX]);
    597 
    598     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT])
    599     {
    600         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT"
    601                 " not found", __FUNCTION__);
    602         return WIFI_ERROR_INVALID_ARGS;
    603     }
    604     stats->rssi_mgmt       = get_s32(tb_vendor[
    605             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT]);
    606 
    607     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA])
    608     {
    609         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA"
    610                 " not found", __FUNCTION__);
    611         return WIFI_ERROR_INVALID_ARGS;
    612     }
    613     stats->rssi_data       = get_s32(tb_vendor[
    614             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA]);
    615 
    616     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK])
    617     {
    618         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK"
    619                 " not found", __FUNCTION__);
    620         return WIFI_ERROR_INVALID_ARGS;
    621     }
    622     stats->rssi_ack        = get_s32(tb_vendor[
    623             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK]);
    624 #ifdef QC_HAL_DEBUG
    625     ALOGV("WMM STATS");
    626     ALOGV("beaconRx : %u "
    627           "mgmtRx : %u "
    628           "mgmtActionRx  : %u "
    629           "mgmtActionTx : %u "
    630           "rssiMgmt : %d "
    631           "rssiData : %d "
    632           "rssiAck  : %d ",
    633           stats->beacon_rx,
    634           stats->mgmt_rx,
    635           stats->mgmt_action_rx,
    636           stats->mgmt_action_tx,
    637           stats->rssi_mgmt,
    638           stats->rssi_data,
    639           stats->rssi_ack);
    640 #endif
    641     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO])
    642     {
    643         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO"
    644                 " not found", __FUNCTION__);
    645         return WIFI_ERROR_INVALID_ARGS;
    646     }
    647 #ifdef QC_HAL_DEBUG
    648     ALOGV("%4s | %6s | %6s | %7s | %7s | %7s |"
    649           " %7s | %8s | %7s | %12s |"
    650           " %11s | %17s | %17s |"
    651           " %17s | %20s",
    652           "ac","txMpdu", "rxMpdu", "txMcast", "rxMcast", "rxAmpdu",
    653           "txAmpdu", "mpduLost", "retries", "retriesShort",
    654           "retriesLong", "contentionTimeMin", "contentionTimeMax",
    655           "contentionTimeAvg", "contentionNumSamples");
    656 #endif
    657     for (wmmInfo = (struct nlattr *) nla_data(tb_vendor[
    658                 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]),
    659             rem = nla_len(tb_vendor[
    660                 QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]);
    661             nla_ok(wmmInfo, rem);
    662             wmmInfo = nla_next(wmmInfo, &(rem)))
    663     {
    664         struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
    665         pWmmStats = (wifi_wmm_ac_stat *) ((u8 *)stats->ac
    666                 + (i++ * sizeof(wifi_wmm_ac_stat)));
    667         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
    668                 (struct nlattr *) nla_data(wmmInfo),
    669                 nla_len(wmmInfo), NULL);
    670         ret = get_wifi_wmm_ac_stat(pWmmStats, tb2);
    671         if(ret != WIFI_SUCCESS)
    672         {
    673             return ret;
    674         }
    675     }
    676 
    677     return WIFI_SUCCESS;
    678 }
    679 
    680 static wifi_error get_wifi_radio_stats(wifi_radio_stat *stats,
    681                                        struct nlattr **tb_vendor)
    682 {
    683     u32 i = 0;
    684     struct nlattr *chInfo;
    685     wifi_channel_stat *pChStats;
    686     int rem;
    687 
    688     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID])
    689     {
    690         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID not found", __FUNCTION__);
    691         return WIFI_ERROR_INVALID_ARGS;
    692     }
    693     stats->radio             = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID]);
    694 
    695     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME])
    696     {
    697         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME not found", __FUNCTION__);
    698         return WIFI_ERROR_INVALID_ARGS;
    699     }
    700     stats->on_time           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME]);
    701 
    702     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME])
    703     {
    704         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME not found", __FUNCTION__);
    705         return WIFI_ERROR_INVALID_ARGS;
    706     }
    707     stats->tx_time           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME]);
    708 
    709     if (stats->num_tx_levels) {
    710         if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL]) {
    711             ALOGE("%s: num_tx_levels is %u but QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL not found", __func__, stats->num_tx_levels);
    712             stats->num_tx_levels = 0;
    713             return WIFI_ERROR_INVALID_ARGS;
    714         }
    715         stats->tx_time_per_levels =
    716                              (u32 *) malloc(sizeof(u32) * stats->num_tx_levels);
    717         if (!stats->tx_time_per_levels) {
    718             ALOGE("%s: radio_stat: tx_time_per_levels malloc Failed", __func__);
    719             stats->num_tx_levels = 0;
    720             return WIFI_ERROR_OUT_OF_MEMORY;
    721         }
    722 
    723         nla_memcpy(stats->tx_time_per_levels,
    724             tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME_PER_LEVEL],
    725             sizeof(u32) * stats->num_tx_levels);
    726     }
    727 
    728     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME])
    729     {
    730         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME not found", __FUNCTION__);
    731         return WIFI_ERROR_INVALID_ARGS;
    732     }
    733     stats->rx_time           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME]);
    734 
    735     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN])
    736     {
    737         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN not found", __FUNCTION__);
    738         return WIFI_ERROR_INVALID_ARGS;
    739     }
    740     stats->on_time_scan      = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN]);
    741 
    742     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD])
    743     {
    744         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD not found", __FUNCTION__);
    745         return WIFI_ERROR_INVALID_ARGS;
    746     }
    747     stats->on_time_nbd       = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD]);
    748 
    749     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN])
    750     {
    751         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN not found", __FUNCTION__);
    752         return WIFI_ERROR_INVALID_ARGS;
    753     }
    754     stats->on_time_gscan     = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN]);
    755 
    756     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN])
    757     {
    758         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN not found", __FUNCTION__);
    759         return WIFI_ERROR_INVALID_ARGS;
    760     }
    761     stats->on_time_roam_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN]);
    762 
    763     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN])
    764     {
    765         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN not found", __FUNCTION__);
    766         return WIFI_ERROR_INVALID_ARGS;
    767     }
    768     stats->on_time_pno_scan  = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN]);
    769 
    770     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20])
    771     {
    772         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20 not found", __FUNCTION__);
    773         return WIFI_ERROR_INVALID_ARGS;
    774     }
    775     stats->on_time_hs20      = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20]);
    776 
    777 
    778     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS])
    779     {
    780         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS not found", __FUNCTION__);
    781         return WIFI_ERROR_INVALID_ARGS;
    782     }
    783     stats->num_channels                           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]);
    784 
    785 
    786     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO])
    787     {
    788         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO not found", __FUNCTION__);
    789         return WIFI_ERROR_INVALID_ARGS;
    790     }
    791     for (chInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO]);
    792             nla_ok(chInfo, rem);
    793             chInfo = nla_next(chInfo, &(rem)))
    794     {
    795         struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
    796         pChStats = (wifi_channel_stat *) ((u8 *)stats->channels + (i++ * (sizeof(wifi_channel_stat))));
    797         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(chInfo), nla_len(chInfo), NULL);
    798 
    799         if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH])
    800         {
    801             ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH not found", __FUNCTION__);
    802             return WIFI_ERROR_INVALID_ARGS;
    803         }
    804         pChStats->channel.width                  = (wifi_channel_width)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH]);
    805 
    806         if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ])
    807         {
    808             ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ not found", __FUNCTION__);
    809             return WIFI_ERROR_INVALID_ARGS;
    810         }
    811         pChStats->channel.center_freq            = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ]);
    812 
    813         if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0])
    814         {
    815             ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0 not found", __FUNCTION__);
    816             return WIFI_ERROR_INVALID_ARGS;
    817         }
    818         pChStats->channel.center_freq0           = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0]);
    819 
    820         if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1])
    821         {
    822             ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1 not found", __FUNCTION__);
    823             return WIFI_ERROR_INVALID_ARGS;
    824         }
    825         pChStats->channel.center_freq1           = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1]);
    826 
    827         if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME])
    828         {
    829             ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME not found", __FUNCTION__);
    830             return WIFI_ERROR_INVALID_ARGS;
    831         }
    832         pChStats->on_time                = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME]);
    833 
    834         if (!tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME])
    835         {
    836             ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME not found", __FUNCTION__);
    837             return WIFI_ERROR_INVALID_ARGS;
    838         }
    839         pChStats->cca_busy_time          = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME]);
    840     }
    841     return WIFI_SUCCESS;
    842 }
    843 
    844 void LLStatsCommand::getClearRspParams(u32 *stats_clear_rsp_mask, u8 *stop_rsp)
    845 {
    846     *stats_clear_rsp_mask =  mClearRspParams.stats_clear_rsp_mask;
    847     *stop_rsp = mClearRspParams.stop_rsp;
    848 }
    849 
    850 int LLStatsCommand::requestResponse()
    851 {
    852     return WifiCommand::requestResponse(mMsg);
    853 }
    854 
    855 int LLStatsCommand::handleResponse(WifiEvent &reply)
    856 {
    857     unsigned i=0;
    858     int status = WIFI_ERROR_NONE;
    859     WifiVendorCommand::handleResponse(reply);
    860 
    861     // Parse the vendordata and get the attribute
    862 
    863     switch(mSubcmd)
    864     {
    865         case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET:
    866         {
    867             u32 resultsBufSize = 0;
    868             struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
    869             int rem;
    870 
    871             nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
    872                     (struct nlattr *)mVendorData,
    873                     mDataLen, NULL);
    874 
    875             if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE])
    876             {
    877                 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE not found",
    878                         __FUNCTION__);
    879                 status = WIFI_ERROR_INVALID_ARGS;
    880                 goto cleanup;
    881             }
    882 
    883             switch(nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE]))
    884             {
    885                 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_RADIO:
    886                 {
    887                     if (!tb_vendor[
    888                         QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS
    889                         ])
    890                     {
    891                         ALOGE("%s:"
    892                             "QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS"
    893                             " not found", __FUNCTION__);
    894                         status = WIFI_ERROR_INVALID_ARGS;
    895                         goto cleanup;
    896                     }
    897 
    898                     resultsBufSize += (nla_get_u32(tb_vendor[
    899                             QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS])
    900                             * sizeof(wifi_channel_stat)
    901                             + sizeof(wifi_radio_stat));
    902                     mResultsParams.radio_stat =
    903                             (wifi_radio_stat *)malloc(resultsBufSize);
    904                     if (!mResultsParams.radio_stat)
    905                     {
    906                         ALOGE("%s: radio_stat: malloc Failed", __FUNCTION__);
    907                         status = WIFI_ERROR_OUT_OF_MEMORY;
    908                         goto cleanup;
    909                     }
    910                     memset(mResultsParams.radio_stat, 0, resultsBufSize);
    911 
    912                     if (tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS])
    913                         mResultsParams.radio_stat->num_tx_levels = nla_get_u32(tb_vendor[
    914                                             QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS]);
    915 
    916                     wifi_channel_stat *pWifiChannelStats;
    917                     status = get_wifi_radio_stats(mResultsParams.radio_stat,
    918                               tb_vendor);
    919                     if(status != WIFI_SUCCESS)
    920                     {
    921                         goto cleanup;
    922                     }
    923 #ifdef QC_HAL_DEBUG
    924                     ALOGV("radio :%u onTime :%u txTime :%u rxTime :%u"
    925                           " onTimeScan :%u onTimeNbd :%u onTimeGscan :%u"
    926                           " onTimeRoamScan :%u onTimePnoScan :%u"
    927                           " onTimeHs20 :%u numChannels :%u num_tx_levels: %u",
    928                           mResultsParams.radio_stat->radio,
    929                           mResultsParams.radio_stat->on_time,
    930                           mResultsParams.radio_stat->tx_time,
    931                           mResultsParams.radio_stat->rx_time,
    932                           mResultsParams.radio_stat->on_time_scan,
    933                           mResultsParams.radio_stat->on_time_nbd,
    934                           mResultsParams.radio_stat->on_time_gscan,
    935                           mResultsParams.radio_stat->on_time_roam_scan,
    936                           mResultsParams.radio_stat->on_time_pno_scan,
    937                           mResultsParams.radio_stat->on_time_hs20,
    938                           mResultsParams.radio_stat->num_channels,
    939                           mResultsParams.radio_stat->num_tx_levels);
    940 #ifdef QC_HAL_DEBUG
    941                     for (i = 0; i < mResultsParams.radio_stat->num_tx_levels; i++) {
    942                         ALOGV("Power level: %u  tx_time: %u", i,
    943                               mResultsParams.radio_stat->tx_time_per_levels[i]);
    944                     }
    945 #endif
    946                     ALOGV("%5s | %10s | %11s | %11s | %6s | %11s", "width",
    947                           "CenterFreq", "CenterFreq0", "CenterFreq1",
    948                           "onTime", "ccaBusyTime");
    949 #endif
    950                     for ( i=0; i < mResultsParams.radio_stat->num_channels; i++)
    951                     {
    952                         pWifiChannelStats =
    953                             (wifi_channel_stat *) (
    954                                 (u8 *)mResultsParams.radio_stat->channels
    955                                 + (i * sizeof(wifi_channel_stat)));
    956 
    957 #ifdef QC_HAL_DEBUG
    958                         ALOGV("%5u | %10u | %11u | %11u | %6u | %11u",
    959                               pWifiChannelStats->channel.width,
    960                               pWifiChannelStats->channel.center_freq,
    961                               pWifiChannelStats->channel.center_freq0,
    962                               pWifiChannelStats->channel.center_freq1,
    963                               pWifiChannelStats->on_time,
    964                               pWifiChannelStats->cca_busy_time);
    965 #endif
    966                     }
    967                 }
    968                 break;
    969 
    970                 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_IFACE:
    971                 {
    972                     resultsBufSize = sizeof(wifi_iface_stat);
    973                     mResultsParams.iface_stat =
    974                         (wifi_iface_stat *) malloc (resultsBufSize);
    975                     if (!mResultsParams.iface_stat)
    976                     {
    977                         ALOGE("%s: iface_stat: malloc Failed", __FUNCTION__);
    978                         status = WIFI_ERROR_OUT_OF_MEMORY;
    979                         goto cleanup;
    980                     }
    981                     memset(mResultsParams.iface_stat, 0, resultsBufSize);
    982                     status = get_wifi_interface_info(
    983                             &mResultsParams.iface_stat->info, tb_vendor);
    984                     if(status != WIFI_SUCCESS)
    985                     {
    986                         goto cleanup;
    987                     }
    988                     status = get_wifi_iface_stats(mResultsParams.iface_stat,
    989                             tb_vendor);
    990                     if(status != WIFI_SUCCESS)
    991                     {
    992                         goto cleanup;
    993                     }
    994 
    995                     /* Driver/firmware might send this attribute when there
    996                      * are no peers connected.
    997                      * So that, the event
    998                      * QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS can be
    999                      * avoided.
   1000                      */
   1001                     if (tb_vendor[
   1002                         QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])
   1003                     {
   1004                         mResultsParams.iface_stat->num_peers =
   1005                             nla_get_u32(tb_vendor[
   1006                                 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]);
   1007 #ifdef QC_HAL_DEBUG
   1008                         ALOGV("%s: numPeers is %u\n", __FUNCTION__,
   1009                                 mResultsParams.iface_stat->num_peers);
   1010 #endif
   1011                         if(mResultsParams.iface_stat->num_peers == 0)
   1012                         {
   1013                             // Number of Radios are 1 for now
   1014                             mHandler.on_link_stats_results(mRequestId,
   1015                                     mResultsParams.iface_stat,
   1016                                     1,
   1017                                     mResultsParams.radio_stat);
   1018                             if(mResultsParams.radio_stat)
   1019                             {
   1020                                 if (mResultsParams.radio_stat->tx_time_per_levels)
   1021                                 {
   1022                                     free(mResultsParams.radio_stat->tx_time_per_levels);
   1023                                     mResultsParams.radio_stat->tx_time_per_levels = NULL;
   1024                                 }
   1025                                 free(mResultsParams.radio_stat);
   1026                                 mResultsParams.radio_stat = NULL;
   1027                             }
   1028                             free(mResultsParams.iface_stat);
   1029                             mResultsParams.iface_stat = NULL;
   1030                         }
   1031                     }
   1032                 }
   1033                 break;
   1034 
   1035                 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS:
   1036                 {
   1037                     struct nlattr *peerInfo;
   1038                     wifi_iface_stat *pIfaceStat = NULL;
   1039                     u32 numPeers, num_rates = 0;
   1040                     if (!tb_vendor[
   1041                             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])
   1042                     {
   1043                         ALOGE("%s:QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS"
   1044                               " not found", __FUNCTION__);
   1045                         status = WIFI_ERROR_INVALID_ARGS;
   1046                         goto cleanup;
   1047                     }
   1048 #ifdef QC_HAL_DEBUG
   1049                     ALOGV(" numPeers is %u in %s\n",
   1050                             nla_get_u32(tb_vendor[
   1051                             QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]),
   1052                             __FUNCTION__);
   1053 #endif
   1054                     if((numPeers = nla_get_u32(tb_vendor[
   1055                         QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])) > 0)
   1056                     {
   1057                         if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO])
   1058                         {
   1059                             ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO"
   1060                                     " not found", __FUNCTION__);
   1061                             status = WIFI_ERROR_INVALID_ARGS;
   1062                             goto cleanup;
   1063                         }
   1064                         for (peerInfo = (struct nlattr *) nla_data(tb_vendor[
   1065                              QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]),
   1066                              rem = nla_len(tb_vendor[
   1067                              QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
   1068                                 nla_ok(peerInfo, rem);
   1069                                 peerInfo = nla_next(peerInfo, &(rem)))
   1070                         {
   1071                             struct nlattr *tb2[
   1072                                 QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
   1073 
   1074                             nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
   1075                                     (struct nlattr *) nla_data(peerInfo),
   1076                                     nla_len(peerInfo), NULL);
   1077 
   1078                             if (!tb2[
   1079                              QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES])
   1080                             {
   1081                                 ALOGE("%s:"
   1082                              "QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES"
   1083                              " not found", __FUNCTION__);
   1084                                 status = WIFI_ERROR_INVALID_ARGS;
   1085                                 goto cleanup;
   1086                             }
   1087                             num_rates += nla_get_u32(tb2[
   1088                             QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
   1089                         }
   1090                         resultsBufSize += (numPeers * sizeof(wifi_peer_info)
   1091                                 + num_rates * sizeof(wifi_rate_stat)
   1092                                 + sizeof (wifi_iface_stat));
   1093                         pIfaceStat = (wifi_iface_stat *) malloc (
   1094                                 resultsBufSize);
   1095                         if (!pIfaceStat)
   1096                         {
   1097                             ALOGE("%s: pIfaceStat: malloc Failed", __FUNCTION__);
   1098                             status = WIFI_ERROR_OUT_OF_MEMORY;
   1099                             goto cleanup;
   1100                         }
   1101 
   1102                         memset(pIfaceStat, 0, resultsBufSize);
   1103                         if(mResultsParams.iface_stat) {
   1104                             memcpy ( pIfaceStat, mResultsParams.iface_stat,
   1105                                 sizeof(wifi_iface_stat));
   1106                             free (mResultsParams.iface_stat);
   1107                             mResultsParams.iface_stat = pIfaceStat;
   1108                         }
   1109                         wifi_peer_info *pPeerStats;
   1110                         pIfaceStat->num_peers = numPeers;
   1111 
   1112                         if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO])
   1113                         {
   1114                             ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO"
   1115                                   " not found", __FUNCTION__);
   1116                             status = WIFI_ERROR_INVALID_ARGS;
   1117                             goto cleanup;
   1118                         }
   1119                         for (peerInfo = (struct nlattr *) nla_data(tb_vendor[
   1120                             QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]),
   1121                             rem = nla_len(tb_vendor[
   1122                                 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
   1123                                 nla_ok(peerInfo, rem);
   1124                                 peerInfo = nla_next(peerInfo, &(rem)))
   1125                         {
   1126                             struct nlattr *tb2[
   1127                                 QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
   1128                             pPeerStats = (wifi_peer_info *) (
   1129                                            (u8 *)pIfaceStat->peer_info
   1130                                            + (i++ * sizeof(wifi_peer_info)));
   1131                             nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
   1132                                 (struct nlattr *) nla_data(peerInfo),
   1133                                 nla_len(peerInfo), NULL);
   1134                             status = get_wifi_peer_info(pPeerStats, tb2);
   1135                             if(status != WIFI_SUCCESS)
   1136                             {
   1137                                 goto cleanup;
   1138                             }
   1139                         }
   1140                     }
   1141 
   1142                     // Number of Radios are 1 for now
   1143                     mHandler.on_link_stats_results(mRequestId,
   1144                             mResultsParams.iface_stat, 1,
   1145                             mResultsParams.radio_stat);
   1146                     if(mResultsParams.radio_stat)
   1147                     {
   1148                         if (mResultsParams.radio_stat->tx_time_per_levels)
   1149                         {
   1150                             free(mResultsParams.radio_stat->tx_time_per_levels);
   1151                             mResultsParams.radio_stat->tx_time_per_levels = NULL;
   1152                         }
   1153                         free(mResultsParams.radio_stat);
   1154                         mResultsParams.radio_stat = NULL;
   1155                     }
   1156                     if(mResultsParams.iface_stat)
   1157                     {
   1158                         free(mResultsParams.iface_stat);
   1159                         mResultsParams.iface_stat = NULL;
   1160                     }
   1161                 }
   1162                 break;
   1163 
   1164                 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_INVALID:
   1165                 default:
   1166                     //error case should not happen print log
   1167                     ALOGE("%s: Wrong LLStats subcmd received %d", __FUNCTION__,
   1168                            mSubcmd);
   1169             }
   1170         }
   1171         break;
   1172 
   1173         case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR:
   1174         {
   1175             struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
   1176             nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
   1177                     (struct nlattr *)mVendorData,
   1178                     mDataLen, NULL);
   1179 
   1180             if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK])
   1181             {
   1182                 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK not found", __FUNCTION__);
   1183                 return WIFI_ERROR_INVALID_ARGS;
   1184             }
   1185             ALOGI("Resp mask : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]));
   1186 
   1187             if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP])
   1188             {
   1189                 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP not found", __FUNCTION__);
   1190                 return WIFI_ERROR_INVALID_ARGS;
   1191             }
   1192             ALOGI("STOP resp : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]));
   1193 
   1194             if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK])
   1195             {
   1196                 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK not found", __FUNCTION__);
   1197                 return WIFI_ERROR_INVALID_ARGS;
   1198             }
   1199             mClearRspParams.stats_clear_rsp_mask = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]);
   1200 
   1201             if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP])
   1202             {
   1203                 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP not found", __FUNCTION__);
   1204                 return WIFI_ERROR_INVALID_ARGS;
   1205             }
   1206             mClearRspParams.stop_rsp = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]);
   1207             break;
   1208         }
   1209         default :
   1210             ALOGE("%s: Wrong LLStats subcmd received %d", __FUNCTION__, mSubcmd);
   1211     }
   1212     return NL_SKIP;
   1213 
   1214 cleanup:
   1215     if(mResultsParams.radio_stat)
   1216     {
   1217         if (mResultsParams.radio_stat->tx_time_per_levels)
   1218         {
   1219             free(mResultsParams.radio_stat->tx_time_per_levels);
   1220             mResultsParams.radio_stat->tx_time_per_levels = NULL;
   1221         }
   1222         free(mResultsParams.radio_stat);
   1223         mResultsParams.radio_stat = NULL;
   1224     }
   1225 
   1226     if(mResultsParams.iface_stat)
   1227     {
   1228         free(mResultsParams.iface_stat);
   1229         mResultsParams.iface_stat = NULL;
   1230     }
   1231     return status;
   1232 }
   1233 
   1234 //Implementation of the functions exposed in linklayer.h
   1235 wifi_error wifi_set_link_stats(wifi_interface_handle iface,
   1236                                wifi_link_layer_params params)
   1237 {
   1238     int ret = 0;
   1239     LLStatsCommand *LLCommand;
   1240     struct nlattr *nl_data;
   1241     interface_info *iinfo = getIfaceInfo(iface);
   1242     wifi_handle handle = getWifiHandle(iface);
   1243 
   1244     ALOGI("mpdu_size_threshold : %u, aggressive_statistics_gathering : %u",
   1245           params.mpdu_size_threshold, params.aggressive_statistics_gathering);
   1246     LLCommand = LLStatsCommand::instance(handle);
   1247     if (LLCommand == NULL) {
   1248         ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
   1249         return WIFI_ERROR_UNKNOWN;
   1250     }
   1251     LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
   1252 
   1253     /* create the message */
   1254     ret = LLCommand->create();
   1255     if (ret < 0)
   1256         goto cleanup;
   1257 
   1258     ret = LLCommand->set_iface_id(iinfo->name);
   1259     if (ret < 0)
   1260         goto cleanup;
   1261 
   1262     /*add the attributes*/
   1263     nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1264     if (!nl_data)
   1265         goto cleanup;
   1266     /**/
   1267     ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD,
   1268                                   params.mpdu_size_threshold);
   1269     if (ret < 0)
   1270         goto cleanup;
   1271     /**/
   1272     ret = LLCommand->put_u32(
   1273                 QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING,
   1274                 params.aggressive_statistics_gathering);
   1275     if (ret < 0)
   1276         goto cleanup;
   1277     LLCommand->attr_end(nl_data);
   1278 
   1279     ret = LLCommand->requestResponse();
   1280     if (ret != 0) {
   1281         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
   1282     }
   1283 
   1284 cleanup:
   1285     return (wifi_error)ret;
   1286 }
   1287 
   1288 //Implementation of the functions exposed in LLStats.h
   1289 wifi_error wifi_get_link_stats(wifi_request_id id,
   1290                                wifi_interface_handle iface,
   1291                                wifi_stats_result_handler handler)
   1292 {
   1293     int ret = 0;
   1294     LLStatsCommand *LLCommand;
   1295     struct nlattr *nl_data;
   1296     interface_info *iinfo = getIfaceInfo(iface);
   1297     wifi_handle handle = getWifiHandle(iface);
   1298 
   1299     LLCommand = LLStatsCommand::instance(handle);
   1300     if (LLCommand == NULL) {
   1301         ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
   1302         return WIFI_ERROR_UNKNOWN;
   1303     }
   1304     LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET);
   1305 
   1306     LLCommand->initGetContext(id);
   1307 
   1308     LLCommand->setHandler(handler);
   1309 
   1310     /* create the message */
   1311     ret = LLCommand->create();
   1312     if (ret < 0)
   1313         goto cleanup;
   1314 
   1315     ret = LLCommand->set_iface_id(iinfo->name);
   1316     if (ret < 0)
   1317         goto cleanup;
   1318     /*add the attributes*/
   1319     nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1320     if (!nl_data)
   1321         goto cleanup;
   1322     ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID,
   1323                                   id);
   1324     if (ret < 0)
   1325         goto cleanup;
   1326     ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK,
   1327                                   7);
   1328     if (ret < 0)
   1329         goto cleanup;
   1330 
   1331     /**/
   1332     LLCommand->attr_end(nl_data);
   1333 
   1334     ret = LLCommand->requestResponse();
   1335     if (ret != 0) {
   1336         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
   1337     }
   1338     if (ret < 0)
   1339         goto cleanup;
   1340 
   1341 cleanup:
   1342     return (wifi_error)ret;
   1343 }
   1344 
   1345 
   1346 //Implementation of the functions exposed in LLStats.h
   1347 wifi_error wifi_clear_link_stats(wifi_interface_handle iface,
   1348                                  u32 stats_clear_req_mask,
   1349                                  u32 *stats_clear_rsp_mask,
   1350                                  u8 stop_req, u8 *stop_rsp)
   1351 {
   1352     int ret = 0;
   1353     LLStatsCommand *LLCommand;
   1354     struct nlattr *nl_data;
   1355     interface_info *iinfo = getIfaceInfo(iface);
   1356     wifi_handle handle = getWifiHandle(iface);
   1357 
   1358     ALOGI("clear_req : %x, stop_req : %u", stats_clear_req_mask, stop_req);
   1359     LLCommand = LLStatsCommand::instance(handle);
   1360     if (LLCommand == NULL) {
   1361         ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
   1362         return WIFI_ERROR_UNKNOWN;
   1363     }
   1364     LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR);
   1365 
   1366     /* create the message */
   1367     ret = LLCommand->create();
   1368     if (ret < 0)
   1369         goto cleanup;
   1370 
   1371     ret = LLCommand->set_iface_id(iinfo->name);
   1372     if (ret < 0)
   1373         goto cleanup;
   1374     /*add the attributes*/
   1375     nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1376     if (!nl_data)
   1377         goto cleanup;
   1378     /**/
   1379     ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK,
   1380                                   stats_clear_req_mask);
   1381     if (ret < 0)
   1382         goto cleanup;
   1383     /**/
   1384     ret = LLCommand->put_u8(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ,
   1385                                    stop_req);
   1386     if (ret < 0)
   1387         goto cleanup;
   1388     LLCommand->attr_end(nl_data);
   1389 
   1390     ret = LLCommand->requestResponse();
   1391     if (ret != 0) {
   1392         ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
   1393     }
   1394 
   1395     LLCommand->getClearRspParams(stats_clear_rsp_mask, stop_rsp);
   1396 
   1397 cleanup:
   1398     delete LLCommand;
   1399     return (wifi_error)ret;
   1400 }
   1401