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 
     28 //Singleton Static Instance
     29 LLStatsCommand* LLStatsCommand::mLLStatsCommandInstance  = NULL;
     30 
     31 // This function implements creation of Vendor command
     32 // For LLStats just call base Vendor command create
     33 int LLStatsCommand::create() {
     34     int ifindex;
     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     ALOGI("mVendor_id = %d, Subcmd = %d in  %s:%d\n", mVendor_id, mSubcmd, __func__, __LINE__);
     50 out:
     51     return ret;
     52 }
     53 
     54 LLStatsCommand::LLStatsCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
     55         : WifiVendorCommand(handle, id, vendor_id, subcmd)
     56 {
     57     ALOGV("LLStatsCommand %p constructed", this);
     58     memset(&mClearRspParams, 0,sizeof(LLStatsClearRspParams));
     59     memset(&mResultsParams, 0,sizeof(LLStatsResultsParams));
     60     memset(&mHandler, 0,sizeof(mHandler));
     61 }
     62 
     63 LLStatsCommand::~LLStatsCommand()
     64 {
     65     ALOGW("LLStatsCommand %p distructor", this);
     66     mLLStatsCommandInstance = NULL;
     67     unregisterVendorHandler(mVendor_id, mSubcmd);
     68 }
     69 
     70 LLStatsCommand* LLStatsCommand::instance(wifi_handle handle)
     71 {
     72     if (handle == NULL) {
     73         ALOGE("Interface Handle is invalid");
     74         return NULL;
     75     }
     76     if (mLLStatsCommandInstance == NULL) {
     77         mLLStatsCommandInstance = new LLStatsCommand(handle, 0,
     78                 OUI_QCA,
     79                 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
     80         ALOGV("LLStatsCommand %p created", mLLStatsCommandInstance);
     81         return mLLStatsCommandInstance;
     82     }
     83     else
     84     {
     85         if (handle != getWifiHandle(mLLStatsCommandInstance->mInfo))
     86         {
     87             ALOGE("Handle different");
     88             return NULL;
     89         }
     90     }
     91     ALOGV("LLStatsCommand %p created already", mLLStatsCommandInstance);
     92     return mLLStatsCommandInstance;
     93 }
     94 
     95 void LLStatsCommand::initGetContext(u32 reqId)
     96 {
     97     mRequestId = reqId;
     98     memset(&mResultsParams, 0,sizeof(LLStatsResultsParams));
     99     memset(&mHandler, 0,sizeof(mHandler));
    100 }
    101 
    102 void LLStatsCommand::setSubCmd(u32 subcmd)
    103 {
    104     mSubcmd = subcmd;
    105 }
    106 //callback handlers registered for nl message send
    107 static int error_handler_LLStats(struct sockaddr_nl *nla, struct nlmsgerr *err,
    108                          void *arg)
    109 {
    110     struct sockaddr_nl * tmp;
    111     int *ret = (int *)arg;
    112     tmp = nla;
    113     *ret = err->error;
    114     ALOGE("%s: Error code:%d (%s)", __func__, *ret, strerror(-(*ret)));
    115     return NL_STOP;
    116 }
    117 
    118 //callback handlers registered for nl message send
    119 static int ack_handler_LLStats(struct nl_msg *msg, void *arg)
    120 {
    121     int *ret = (int *)arg;
    122     struct nl_msg * a;
    123 
    124     ALOGE("%s: called", __func__);
    125     a = msg;
    126     *ret = 0;
    127     return NL_STOP;
    128 }
    129 
    130 //callback handlers registered for nl message send
    131 static int finish_handler_LLStats(struct nl_msg *msg, void *arg)
    132 {
    133   int *ret = (int *)arg;
    134   struct nl_msg * a;
    135 
    136   ALOGE("%s: called", __func__);
    137   a = msg;
    138   *ret = 0;
    139   return NL_SKIP;
    140 }
    141 
    142 static void get_wifi_interface_info(wifi_interface_link_layer_info *stats, struct nlattr **tb_vendor)
    143 {
    144     u32 len = 0;
    145     u8 *data;
    146 
    147     stats->mode = (wifi_interface_mode)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE]);
    148     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR]);
    149     len = ((sizeof(stats->mac_addr) <= len) ? sizeof(stats->mac_addr) : len);
    150     memcpy(&stats->mac_addr[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR]), len);
    151     stats->state = (wifi_connection_state)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE]);
    152     stats->roaming = (wifi_roam_state)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING]);
    153     stats->capabilities = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES]);
    154 
    155     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID]);
    156     len = ((sizeof(stats->ssid) <= len) ? sizeof(stats->ssid) : len);
    157     memcpy(&stats->ssid[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID]), len);
    158 
    159     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID]);
    160     len = ((sizeof(stats->bssid) <= len) ? sizeof(stats->bssid) : len);
    161     memcpy(&stats->bssid[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID]), len);
    162     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR]);
    163     len = ((sizeof(stats->ap_country_str) <= len) ? sizeof(stats->ap_country_str) : len);
    164     memcpy(&stats->ap_country_str[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR]),
    165            len);
    166     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR]);
    167     len = ((sizeof(stats->country_str) < len) ? sizeof(stats->country_str) : len);
    168     memcpy(&stats->country_str[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR]),
    169            len);
    170 
    171     ALOGI("STATS IFACE: Mode %d", stats->mode);
    172     ALOGI("STATS IFACE: MAC %pM", stats->mac_addr);
    173     ALOGI("STATS IFACE: State %d ", stats->state);
    174     ALOGI("STATS IFACE: Roaming %d ", stats->roaming);
    175     ALOGI("STATS IFACE: capabilities %0x ", stats->capabilities);
    176     ALOGI("STATS IFACE: SSID %s ", stats->ssid);
    177     ALOGI("STATS IFACE: BSSID %pM ", stats->bssid);
    178     ALOGI("STATS IFACE: AP country str %c%c%c ", stats->ap_country_str[0],
    179             stats->ap_country_str[1], stats->ap_country_str[2]);
    180     ALOGI("STATS IFACE:Country String for this Association %c%c%c", stats->country_str[0],
    181             stats->country_str[1], stats->country_str[2]);
    182 }
    183 
    184 static void get_wifi_wmm_ac_stat(wifi_wmm_ac_stat *stats, struct nlattr **tb_vendor)
    185 {
    186     stats->ac                     = (wifi_traffic_ac)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC]);
    187     stats->tx_mpdu                = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU]);
    188     stats->rx_mpdu                = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU]);
    189     stats->tx_mcast               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST]);
    190     stats->rx_mcast               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST]);
    191     stats->rx_ampdu               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU]);
    192     stats->tx_ampdu               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU]);
    193     stats->mpdu_lost              = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST]);
    194     stats->retries                = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES]);
    195     stats->retries_short          = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT]);
    196     stats->retries_long           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG]);
    197     stats->contention_time_min    = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN]);
    198     stats->contention_time_max    = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX]);
    199     stats->contention_time_avg    = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG]);
    200     stats->contention_num_samples = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES]);
    201 
    202     ALOGI("STATS IFACE: ac  %u ", stats->ac);
    203     ALOGI("STATS IFACE: txMpdu  %u ", stats->tx_mpdu) ;
    204     ALOGI("STATS IFACE: rxMpdu  %u ", stats->rx_mpdu);
    205     ALOGI("STATS IFACE: txMcast  %u ", stats->tx_mcast);
    206     ALOGI("STATS IFACE: rxMcast  %u ", stats->rx_mcast);
    207     ALOGI("STATS IFACE: rxAmpdu  %u ", stats->rx_ampdu);
    208     ALOGI("STATS IFACE: txAmpdu  %u ", stats->tx_ampdu);
    209     ALOGI("STATS IFACE: mpduLost  %u ", stats->mpdu_lost);
    210     ALOGI("STATS IFACE: retries %u  ", stats->retries);
    211     ALOGI("STATS IFACE: retriesShort  %u ",
    212             stats->retries_short);
    213     ALOGI("STATS IFACE: retriesLong  %u  ",
    214             stats->retries_long);
    215     ALOGI("STATS IFACE: contentionTimeMin  %u ",
    216             stats->contention_time_min);
    217     ALOGI("STATS IFACE: contentionTimeMax  %u ",
    218             stats->contention_time_max);
    219     ALOGI("STATS IFACE: contentionTimeAvg  %u ",
    220             stats->contention_time_avg);
    221     ALOGI("STATS IFACE: contentionNumSamples  %u ",
    222             stats->contention_num_samples);
    223 }
    224 
    225 static void get_wifi_rate_stat(wifi_rate_stat *stats, struct nlattr **tb_vendor)
    226 {
    227     stats->rate.preamble        = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE]);
    228     stats->rate.nss             = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS]);
    229     stats->rate.bw              = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW]);
    230     stats->rate.rateMcsIdx      = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX]);
    231     stats->rate.bitrate         = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE]);
    232 
    233     stats->tx_mpdu              = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU]);
    234     stats->rx_mpdu              = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU]);
    235     stats->mpdu_lost            = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST]);
    236     stats->retries              = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES]);
    237     stats->retries_short        = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT]);
    238     stats->retries_long         = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG]);
    239 
    240 
    241     ALOGI("STATS PEER_ALL : preamble  %u", stats->rate.preamble);
    242     ALOGI("STATS PEER_ALL : nss %u", stats->rate.nss);
    243     ALOGI("STATS PEER_ALL : bw %u", stats->rate.bw);
    244     ALOGI("STATS PEER_ALL : rateMcsIdx  %u", stats->rate.rateMcsIdx);
    245     ALOGI("STATS PEER_ALL : bitrate %u", stats->rate.bitrate);
    246 
    247     ALOGI("STATS PEER_ALL : txMpdu %u", stats->tx_mpdu);
    248     ALOGI("STATS PEER_ALL : rxMpdu %u", stats->rx_mpdu);
    249     ALOGI("STATS PEER_ALL : mpduLost %u", stats->mpdu_lost);
    250     ALOGI("STATS PEER_ALL : retries %u", stats->retries);
    251     ALOGI("STATS PEER_ALL : retriesShort %u", stats->retries_short);
    252     ALOGI("STATS PEER_ALL : retriesLong %u", stats->retries_long);
    253 }
    254 
    255 static void get_wifi_peer_info(wifi_peer_info *stats, struct nlattr **tb_vendor)
    256 {
    257     u32 i = 0, len = 0;
    258     int rem;
    259     wifi_rate_stat * pRateStats;
    260     struct nlattr *rateInfo;
    261     stats->type                   = (wifi_peer_type)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE]);
    262     len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]);
    263     len = ((sizeof(stats->peer_mac_address) <= len) ? sizeof(stats->peer_mac_address) : len);
    264     memcpy((void *)&stats->peer_mac_address[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]),
    265             len);
    266     stats->capabilities           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES]);
    267 
    268     stats->num_rate               = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
    269 
    270     ALOGI("STATS PEER_ALL : numPeers %u", stats->type);
    271     ALOGI("STATS PEER_ALL : peerMacAddress  %0x:%0x:%0x:%0x:%0x:%0x ",
    272             stats->peer_mac_address[0], stats->peer_mac_address[1],
    273             stats->peer_mac_address[2],stats->peer_mac_address[3],
    274             stats->peer_mac_address[4],stats->peer_mac_address[5]);
    275     ALOGI("STATS PEER_ALL : capabilities %0x", stats->capabilities);
    276     ALOGI("STATS PEER_ALL :  numRate %u", stats->num_rate);
    277     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]);
    278             nla_ok(rateInfo, rem);
    279             rateInfo = nla_next(rateInfo, &(rem)))
    280     {
    281         struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
    282         pRateStats = (wifi_rate_stat *) ((u8 *)stats->rate_stats + (i++ * sizeof(wifi_rate_stat)));
    283 
    284         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(rateInfo), nla_len(rateInfo), NULL);
    285         get_wifi_rate_stat(pRateStats, tb2);
    286     }
    287 }
    288 
    289 static void get_wifi_iface_stats(wifi_iface_stat *stats, struct nlattr **tb_vendor)
    290 {
    291     struct nlattr *wmmInfo;
    292     wifi_wmm_ac_stat *pWmmStats;
    293     int i=0, rem;
    294 
    295     stats->beacon_rx       = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX]);
    296     stats->mgmt_rx         = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX]);
    297     stats->mgmt_action_rx  = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX]);
    298     stats->mgmt_action_tx  = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX]);
    299     stats->rssi_mgmt       = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT]);
    300     stats->rssi_data       = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA]);
    301     stats->rssi_ack        = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK]);
    302 
    303     ALOGI("STATS IFACE: beaconRx : %u ", stats->beacon_rx);
    304     ALOGI("STATS IFACE: mgmtRx %u ", stats->mgmt_rx);
    305     ALOGI("STATS IFACE: mgmtActionRx  %u ", stats->mgmt_action_rx);
    306     ALOGI("STATS IFACE: mgmtActionTx %u ", stats->mgmt_action_tx);
    307     ALOGI("STATS IFACE: rssiMgmt %u ", stats->rssi_mgmt);
    308     ALOGI("STATS IFACE: rssiData %u ", stats->rssi_data);
    309     ALOGI("STATS IFACE: rssiAck  %u ", stats->rssi_ack);
    310     for (wmmInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]);
    311             nla_ok(wmmInfo, rem);
    312             wmmInfo = nla_next(wmmInfo, &(rem)))
    313     {
    314         struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
    315         pWmmStats = (wifi_wmm_ac_stat *) ((u8 *)stats->ac + (i * sizeof(wifi_wmm_ac_stat)));
    316         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(wmmInfo), nla_len(wmmInfo), NULL);
    317         get_wifi_wmm_ac_stat(pWmmStats, tb2);
    318     }
    319 }
    320 
    321 static void get_wifi_radio_stats(wifi_radio_stat *stats, struct nlattr **tb_vendor)
    322 {
    323     u32 i = 0;
    324     struct nlattr *chInfo;
    325     wifi_channel_stat *pChStats;
    326     int rem;
    327                     printf("sunil %d : %s \n",__LINE__,__func__);
    328 
    329     stats->radio             = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID]);
    330                     printf("sunil %d : %s \n",__LINE__,__func__);
    331     stats->on_time           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME]);
    332                     printf("sunil %d : %s \n",__LINE__,__func__);
    333     stats->tx_time           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME]);
    334                     printf("sunil %d : %s \n",__LINE__,__func__);
    335     stats->rx_time           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME]);
    336     ALOGI("<<<< rxTime is %u ", stats->rx_time);
    337     stats->on_time_scan      = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN]);
    338     stats->on_time_nbd       = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD]);
    339     stats->on_time_gscan     = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN]);
    340     stats->on_time_roam_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN]);
    341     stats->on_time_pno_scan  = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN]);
    342     stats->on_time_hs20      = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20]);
    343 
    344     stats->num_channels                           = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]);
    345 
    346     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]);
    347             nla_ok(chInfo, rem);
    348             chInfo = nla_next(chInfo, &(rem)))
    349     {
    350         struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
    351         pChStats = (wifi_channel_stat *) ((u8 *)stats->channels + (i++ * (sizeof(wifi_channel_stat))));
    352         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(chInfo), nla_len(chInfo), NULL);
    353         pChStats->channel.width                  = (wifi_channel_width)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH]);
    354         pChStats->channel.center_freq            = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ]);
    355         pChStats->channel.center_freq0           = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0]);
    356         pChStats->channel.center_freq1           = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1]);
    357         pChStats->on_time                = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME]);
    358         pChStats->cca_busy_time          = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME]);
    359     }
    360 }
    361 
    362 // This function will be the main handler for incoming event LLStats_SUBCMD
    363 //Call the appropriate callback handler after parsing the vendor data.
    364 int LLStatsCommand::handleEvent(WifiEvent &event)
    365 {
    366     ALOGI("Got a LLStats message from Driver");
    367     unsigned i=0;
    368     u32 status;
    369     WifiVendorCommand::handleEvent(event);
    370 
    371     // Parse the vendordata and get the attribute
    372 
    373     switch(mSubcmd)
    374     {
    375         case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS:
    376             {
    377                 wifi_request_id id;
    378                 u32 resultsBufSize = 0;
    379                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
    380                 int rem;
    381                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
    382                         (struct nlattr *)mVendorData,
    383                         mDataLen, NULL);
    384                 resultsBufSize += (nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]) * sizeof(wifi_channel_stat)
    385                         + sizeof(wifi_radio_stat));
    386                 mResultsParams.radio_stat = (wifi_radio_stat *)malloc(resultsBufSize);
    387                 memset(mResultsParams.radio_stat, 0, resultsBufSize);
    388                 ALOGI(" rxTime is %u\n ", mResultsParams.radio_stat->rx_time);
    389                 ALOGI(" NumChan is %d\n ",
    390                         nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]));
    391 
    392                 if(mResultsParams.radio_stat){
    393                     wifi_channel_stat *pWifiChannelStats;
    394                     u32 i =0;
    395                     printf("sunil %d : %s \n",__LINE__,__func__);
    396                     get_wifi_radio_stats(mResultsParams.radio_stat, tb_vendor);
    397 
    398                     ALOGI(" radio is %u ", mResultsParams.radio_stat->radio);
    399                     ALOGI(" onTime is %u ", mResultsParams.radio_stat->on_time);
    400                     ALOGI(" txTime is %u ", mResultsParams.radio_stat->tx_time);
    401                     ALOGI(" rxTime is %u ", mResultsParams.radio_stat->rx_time);
    402                     ALOGI(" onTimeScan is %u ", mResultsParams.radio_stat->on_time_scan);
    403                     ALOGI(" onTimeNbd is %u ", mResultsParams.radio_stat->on_time_nbd);
    404                     ALOGI(" onTimeGscan is %u ", mResultsParams.radio_stat->on_time_gscan);
    405                     ALOGI(" onTimeRoamScan is %u", mResultsParams.radio_stat->on_time_roam_scan);
    406                     ALOGI(" onTimePnoScan is %u ", mResultsParams.radio_stat->on_time_pno_scan);
    407                     ALOGI(" onTimeHs20 is %u ", mResultsParams.radio_stat->on_time_hs20);
    408                     ALOGI(" numChannels is %u ", mResultsParams.radio_stat->num_channels);
    409                     for ( i=0; i < mResultsParams.radio_stat->num_channels; i++)
    410                     {
    411                         pWifiChannelStats = (wifi_channel_stat *) ((u8 *)mResultsParams.radio_stat->channels + (i * sizeof(wifi_channel_stat)));
    412 
    413                         ALOGI("  width is %u ", pWifiChannelStats->channel.width);
    414                         ALOGI("  CenterFreq %u ", pWifiChannelStats->channel.center_freq);
    415                         ALOGI("  CenterFreq0 %u ", pWifiChannelStats->channel.center_freq0);
    416                         ALOGI("  CenterFreq1 %u ", pWifiChannelStats->channel.center_freq1);
    417                         ALOGI("  onTime %u ", pWifiChannelStats->on_time);
    418                         ALOGI("  ccaBusyTime %u ", pWifiChannelStats->cca_busy_time);
    419                     }
    420                     ALOGI(" rxTime is %u in %s:%d\n", mResultsParams.radio_stat->rx_time, __func__, __LINE__);
    421                 }
    422             }
    423             break;
    424 
    425         case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS:
    426             {
    427                 wifi_request_id id;
    428                 u32 resultsBufSize = 0;
    429                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
    430                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
    431                         (struct nlattr *)mVendorData,
    432                         mDataLen, NULL);
    433 
    434                 resultsBufSize = sizeof(wifi_iface_stat);   // Do we need no.of peers here??
    435                 mResultsParams.iface_stat = (wifi_iface_stat *) malloc (sizeof (wifi_iface_stat));
    436                 get_wifi_interface_info(&mResultsParams.iface_stat->info, tb_vendor);
    437                 get_wifi_iface_stats(mResultsParams.iface_stat, tb_vendor);
    438             }
    439             break;
    440 
    441         case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS:
    442             {
    443                 wifi_request_id id;
    444                 u32 resultsBufSize = 0, i=0, num_rates = 0;
    445                 u32 numPeers;
    446                 int rem;
    447                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
    448                 struct nlattr *peerInfo;
    449                 wifi_iface_stat *pIfaceStat;
    450                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
    451                         (struct nlattr *)mVendorData,
    452                         mDataLen, NULL);
    453 
    454                 ALOGI(" rxTime is %u in %s:%d\n", mResultsParams.radio_stat->rx_time, __func__, __LINE__);
    455                 ALOGI(" numPeers is %u in %s:%d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]), __func__, __LINE__);
    456                 ALOGI(" rxTe is %u in %s:%d\n", mResultsParams.radio_stat->rx_time, __func__, __LINE__);
    457                 if((numPeers = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])) > 0)
    458                 {
    459 
    460                     for (peerInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
    461                             nla_ok(peerInfo, rem);
    462                             peerInfo = nla_next(peerInfo, &(rem)))
    463                     {
    464                         struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
    465                         nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(peerInfo), nla_len(peerInfo), NULL);
    466                         num_rates += nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
    467                     }
    468                     resultsBufSize += (numPeers * sizeof(wifi_peer_info)
    469                             + num_rates * sizeof(wifi_rate_stat) + sizeof (wifi_iface_stat));
    470                     pIfaceStat = (wifi_iface_stat *) malloc (resultsBufSize);
    471 
    472                     if(pIfaceStat){
    473                         memcpy ( pIfaceStat, mResultsParams.iface_stat , sizeof(wifi_iface_stat));
    474                         wifi_peer_info *pPeerStats;
    475                         pIfaceStat->num_peers = numPeers;
    476                         for (peerInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
    477                                 nla_ok(peerInfo, rem);
    478                                 peerInfo = nla_next(peerInfo, &(rem)))
    479                         {
    480                             struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
    481                             pPeerStats = (wifi_peer_info *) ((u8 *)pIfaceStat->peer_info + (i++ * sizeof(wifi_peer_info)));
    482                             nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(peerInfo), nla_len(peerInfo), NULL);
    483                             get_wifi_peer_info(pPeerStats, tb2);
    484                         }
    485                     }
    486                     if(mResultsParams.iface_stat)
    487                         free (mResultsParams.iface_stat);
    488                     mResultsParams.iface_stat = pIfaceStat;
    489                 }
    490                 // Number of Radios are 1 for now : TODO get this info from the driver
    491                 mHandler.on_link_stats_results(mRequestId,
    492                                                mResultsParams.iface_stat, 1, mResultsParams.radio_stat);
    493                 if(mResultsParams.radio_stat)
    494                 {
    495                     free(mResultsParams.radio_stat);
    496                     mResultsParams.radio_stat = NULL;
    497                 }
    498                 if(mResultsParams.iface_stat)
    499                 {
    500                     free(mResultsParams.iface_stat);
    501                     mResultsParams.iface_stat = NULL;
    502                 }
    503             }
    504             break;
    505 
    506         default:
    507             //error case should not happen print log
    508             ALOGE("%s: Wrong LLStats subcmd received %d", __func__, mSubcmd);
    509     }
    510 
    511     return NL_SKIP;
    512 }
    513 
    514 int LLStatsCommand::setCallbackHandler(LLStatsCallbackHandler nHandler, u32 event)
    515 {
    516     int res = 0;
    517     mHandler = nHandler;
    518     res = registerVendorHandler(mVendor_id, event);
    519     if (res != 0) {
    520         //error case should not happen print log
    521         ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
    522               __func__, mVendor_id, mSubcmd);
    523     }
    524     return res;
    525 }
    526 
    527 void LLStatsCommand::unregisterHandler(u32 subCmd)
    528 {
    529     unregisterVendorHandler(mVendor_id, subCmd);
    530 }
    531 
    532 void LLStatsCommand::getClearRspParams(u32 *stats_clear_rsp_mask, u8 *stop_rsp)
    533 {
    534     *stats_clear_rsp_mask =  mClearRspParams.stats_clear_rsp_mask;
    535     *stop_rsp = mClearRspParams.stop_rsp;
    536 }
    537 
    538 int LLStatsCommand::requestResponse()
    539 {
    540     return WifiCommand::requestResponse(mMsg);
    541 }
    542 
    543 int LLStatsCommand::handleResponse(WifiEvent &reply)
    544 {
    545     ALOGI("Got a LLStats message from Driver");
    546     unsigned i=0;
    547     u32 status;
    548     WifiVendorCommand::handleResponse(reply);
    549 
    550     // Parse the vendordata and get the attribute
    551 
    552     switch(mSubcmd)
    553     {
    554         case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR:
    555             {
    556                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
    557                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
    558                         (struct nlattr *)mVendorData,
    559                         mDataLen, NULL);
    560                 ALOGI("Resp mask : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]));
    561                 ALOGI("STOP resp : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]));
    562                 mClearRspParams.stats_clear_rsp_mask = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]);
    563                 mClearRspParams.stop_rsp = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]);
    564                 break;
    565             }
    566         default :
    567             ALOGE("%s: Wrong LLStats subcmd received %d", __func__, mSubcmd);
    568     }
    569     return NL_SKIP;
    570 }
    571 
    572 //Implementation of the functions exposed in linklayer.h
    573 wifi_error wifi_set_link_stats(wifi_interface_handle iface,
    574                                wifi_link_layer_params params)
    575 {
    576     int ret = 0;
    577     LLStatsCommand *LLCommand;
    578     struct nlattr *nl_data;
    579     interface_info *iinfo = getIfaceInfo(iface);
    580     wifi_handle handle = getWifiHandle(iface);
    581     LLCommand = LLStatsCommand::instance(handle);
    582     if (LLCommand == NULL) {
    583         ALOGE("%s: Error LLStatsCommand NULL", __func__);
    584         return WIFI_ERROR_UNKNOWN;
    585     }
    586     LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
    587 
    588     /* create the message */
    589     ret = LLCommand->create();
    590     if (ret < 0)
    591         goto cleanup;
    592 
    593     ret = LLCommand->set_iface_id(iinfo->name);
    594     if (ret < 0)
    595         goto cleanup;
    596 
    597     /*add the attributes*/
    598     nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    599     if (!nl_data)
    600         goto cleanup;
    601     /**/
    602     ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD,
    603                                   params.mpdu_size_threshold);
    604     if (ret < 0)
    605         goto cleanup;
    606     /**/
    607     ret = LLCommand->put_u32(
    608                 QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING,
    609                 params.aggressive_statistics_gathering);
    610     if (ret < 0)
    611         goto cleanup;
    612     LLCommand->attr_end(nl_data);
    613 
    614     ret = LLCommand->requestResponse();
    615     if (ret != 0) {
    616         ALOGE("%s: requestResponse Error:%d",__func__, ret);
    617     }
    618 
    619 cleanup:
    620     return (wifi_error)ret;
    621 }
    622 
    623 //Implementation of the functions exposed in LLStats.h
    624 wifi_error wifi_get_link_stats(wifi_request_id id,
    625                                wifi_interface_handle iface,
    626                                wifi_stats_result_handler handler)
    627 {
    628     int ret = 0;
    629     LLStatsCommand *LLCommand;
    630     struct nlattr *nl_data;
    631     interface_info *iinfo = getIfaceInfo(iface);
    632     wifi_handle handle = getWifiHandle(iface);
    633     pthread_t tid;
    634 
    635     LLCommand = LLStatsCommand::instance(handle);
    636     if (LLCommand == NULL) {
    637         ALOGE("%s: Error LLStatsCommand NULL", __func__);
    638         return WIFI_ERROR_UNKNOWN;
    639     }
    640     LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET);
    641 
    642     LLCommand->initGetContext(id);
    643 
    644     LLStatsCallbackHandler callbackHandler =
    645     {
    646         .on_link_stats_results = handler.on_link_stats_results
    647     };
    648 
    649     /* create the message */
    650     ret = LLCommand->create();
    651     if (ret < 0)
    652         goto cleanup;
    653 
    654     ret = LLCommand->set_iface_id(iinfo->name);
    655     if (ret < 0)
    656         goto cleanup;
    657     /*add the attributes*/
    658     nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    659     if (!nl_data)
    660         goto cleanup;
    661     ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID,
    662                                   id);
    663     if (ret < 0)
    664         goto cleanup;
    665     ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK,
    666                                   7);
    667     if (ret < 0)
    668         goto cleanup;
    669 
    670     /**/
    671     LLCommand->attr_end(nl_data);
    672 
    673     ret = LLCommand->requestResponse();
    674     if (ret != 0) {
    675         ALOGE("%s: requestResponse Error:%d",__func__, ret);
    676     }
    677     if (ret < 0)
    678         goto cleanup;
    679 
    680     ret = LLCommand->setCallbackHandler(callbackHandler, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS);
    681     if (ret < 0)
    682         goto cleanup;
    683     ret = LLCommand->setCallbackHandler(callbackHandler, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS);
    684     if (ret < 0)
    685         goto cleanup;
    686     ret = LLCommand->setCallbackHandler(callbackHandler, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS);
    687     if (ret < 0)
    688         goto cleanup;
    689 cleanup:
    690     return (wifi_error)ret;
    691 }
    692 
    693 
    694 //Implementation of the functions exposed in LLStats.h
    695 wifi_error wifi_clear_link_stats(wifi_interface_handle iface,
    696                                  u32 stats_clear_req_mask,
    697                                  u32 *stats_clear_rsp_mask,
    698                                  u8 stop_req, u8 *stop_rsp)
    699 {
    700     int ret = 0;
    701     LLStatsCommand *LLCommand;
    702     struct nlattr *nl_data;
    703     interface_info *iinfo = getIfaceInfo(iface);
    704     wifi_handle handle = getWifiHandle(iface);
    705 
    706     LLCommand = LLStatsCommand::instance(handle);
    707     if (LLCommand == NULL) {
    708         ALOGE("%s: Error LLStatsCommand NULL", __func__);
    709         return WIFI_ERROR_UNKNOWN;
    710     }
    711     LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR);
    712 
    713     /* create the message */
    714     ret = LLCommand->create();
    715     if (ret < 0)
    716         goto cleanup;
    717 
    718     ret = LLCommand->set_iface_id(iinfo->name);
    719     if (ret < 0)
    720         goto cleanup;
    721     /*add the attributes*/
    722     nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    723     if (!nl_data)
    724         goto cleanup;
    725     /**/
    726     ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK,
    727                                   stats_clear_req_mask);
    728     if (ret < 0)
    729         goto cleanup;
    730     /**/
    731     ret = LLCommand->put_u8(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ,
    732                                    stop_req);
    733     if (ret < 0)
    734         goto cleanup;
    735     LLCommand->attr_end(nl_data);
    736 
    737     ret = LLCommand->requestResponse();
    738     if (ret != 0) {
    739         ALOGE("%s: requestResponse Error:%d",__func__, ret);
    740     }
    741 
    742     LLCommand->getClearRspParams(stats_clear_rsp_mask, stop_rsp);
    743 
    744 cleanup:
    745     LLCommand->unregisterHandler(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS);
    746     LLCommand->unregisterHandler(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS);
    747     LLCommand->unregisterHandler(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS);
    748     delete LLCommand;
    749     return (wifi_error)ret;
    750 }
    751 
    752