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