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