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