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