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