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 return WIFI_SUCCESS;
842 }
843
getClearRspParams(u32 * stats_clear_rsp_mask,u8 * stop_rsp)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
requestResponse()850 wifi_error LLStatsCommand::requestResponse()
851 {
852 return WifiCommand::requestResponse(mMsg);
853 }
854
notifyResponse()855 wifi_error LLStatsCommand::notifyResponse()
856 {
857 wifi_error ret = WIFI_SUCCESS;
858
859 /* Indicate stats to framework only if both radio and iface stats
860 * are present */
861 if (mResultsParams.radio_stat && mResultsParams.iface_stat) {
862 mHandler.on_link_stats_results(mRequestId,
863 mResultsParams.iface_stat, mNumRadios,
864 mResultsParams.radio_stat);
865 } else {
866 ret = WIFI_ERROR_INVALID_ARGS;
867 }
868
869 clearStats();
870
871 return ret;
872 }
873
874
clearStats()875 void LLStatsCommand::clearStats()
876 {
877 if(mResultsParams.radio_stat)
878 {
879 wifi_radio_stat *radioStat = mResultsParams.radio_stat;
880 for (u8 radio = 0; radio < mNumRadios; radio++) {
881 if (radioStat->tx_time_per_levels) {
882 free(radioStat->tx_time_per_levels);
883 radioStat->tx_time_per_levels = NULL;
884 }
885 radioStat = (wifi_radio_stat *)((u8 *)radioStat +
886 sizeof(wifi_radio_stat) + (sizeof(wifi_channel_stat) *
887 radioStat->num_channels));
888 }
889 free(mResultsParams.radio_stat);
890 mResultsParams.radio_stat = NULL;
891 mRadioStatsSize = 0;
892 mNumRadios = 0;
893 }
894 if(mResultsParams.iface_stat)
895 {
896 free(mResultsParams.iface_stat);
897 mResultsParams.iface_stat = NULL;
898 }
899 }
900
901
handleResponse(WifiEvent & reply)902 int LLStatsCommand::handleResponse(WifiEvent &reply)
903 {
904 unsigned i=0;
905 int status = WIFI_ERROR_NONE;
906 WifiVendorCommand::handleResponse(reply);
907
908 // Parse the vendordata and get the attribute
909
910 switch(mSubcmd)
911 {
912 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET:
913 {
914 u32 resultsBufSize = 0;
915 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
916 int rem;
917 wifi_radio_stat *radioStatsBuf;
918
919 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
920 (struct nlattr *)mVendorData,
921 mDataLen, NULL);
922
923 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE])
924 {
925 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE not found",
926 __FUNCTION__);
927 status = WIFI_ERROR_INVALID_ARGS;
928 goto cleanup;
929 }
930
931 switch(nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE]))
932 {
933 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_RADIO:
934 {
935 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS])
936 {
937 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS"
938 " not found", __FUNCTION__);
939 return WIFI_ERROR_INVALID_ARGS;
940 }
941 mNumRadios = nla_get_u32(tb_vendor[
942 QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS]);
943
944 if (!tb_vendor[
945 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS
946 ])
947 {
948 ALOGE("%s:"
949 "QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS"
950 " not found", __FUNCTION__);
951 status = WIFI_ERROR_INVALID_ARGS;
952 goto cleanup;
953 }
954
955 resultsBufSize += (nla_get_u32(tb_vendor[
956 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS])
957 * sizeof(wifi_channel_stat)
958 + sizeof(wifi_radio_stat));
959
960 radioStatsBuf = (wifi_radio_stat *)realloc(
961 mResultsParams.radio_stat,
962 mRadioStatsSize + resultsBufSize);
963 if (!radioStatsBuf)
964 {
965 ALOGE("%s: radio_stat: malloc Failed", __FUNCTION__);
966 status = WIFI_ERROR_OUT_OF_MEMORY;
967 goto cleanup;
968 }
969 mResultsParams.radio_stat = radioStatsBuf;
970
971 //Move the buffer to populate current radio stats
972 radioStatsBuf = (wifi_radio_stat *)(
973 (u8 *)mResultsParams.radio_stat
974 + mRadioStatsSize);
975 memset(radioStatsBuf, 0, resultsBufSize);
976 mRadioStatsSize += resultsBufSize;
977
978 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS])
979 radioStatsBuf->num_tx_levels = nla_get_u32(tb_vendor[
980 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS]);
981
982 wifi_channel_stat *pWifiChannelStats;
983 status = get_wifi_radio_stats(radioStatsBuf,
984 tb_vendor);
985 if(status != WIFI_SUCCESS)
986 {
987 goto cleanup;
988 }
989 #ifdef QC_HAL_DEBUG
990 ALOGV("radio :%u onTime :%u txTime :%u rxTime :%u"
991 " onTimeScan :%u onTimeNbd :%u onTimeGscan :%u"
992 " onTimeRoamScan :%u onTimePnoScan :%u"
993 " onTimeHs20 :%u numChannels :%u num_tx_levels: %u",
994 radioStatsBuf->radio,
995 radioStatsBuf->on_time,
996 radioStatsBuf->tx_time,
997 radioStatsBuf->rx_time,
998 radioStatsBuf->on_time_scan,
999 radioStatsBuf->on_time_nbd,
1000 radioStatsBuf->on_time_gscan,
1001 radioStatsBuf->on_time_roam_scan,
1002 radioStatsBuf->on_time_pno_scan,
1003 radioStatsBuf->on_time_hs20,
1004 radioStatsBuf->num_channels,
1005 radioStatsBuf->num_tx_levels);
1006 #ifdef QC_HAL_DEBUG
1007 for (i = 0; i < radioStatsBuf->num_tx_levels; i++) {
1008 ALOGV("Power level: %u tx_time: %u", i,
1009 radioStatsBuf->tx_time_per_levels[i]);
1010 }
1011 #endif
1012 ALOGV("%5s | %10s | %11s | %11s | %6s | %11s", "width",
1013 "CenterFreq", "CenterFreq0", "CenterFreq1",
1014 "onTime", "ccaBusyTime");
1015 #endif
1016 for ( i=0; i < radioStatsBuf->num_channels; i++)
1017 {
1018 pWifiChannelStats =
1019 (wifi_channel_stat *) (
1020 (u8 *)radioStatsBuf->channels
1021 + (i * sizeof(wifi_channel_stat)));
1022
1023 #ifdef QC_HAL_DEBUG
1024 ALOGV("%5u | %10u | %11u | %11u | %6u | %11u",
1025 pWifiChannelStats->channel.width,
1026 pWifiChannelStats->channel.center_freq,
1027 pWifiChannelStats->channel.center_freq0,
1028 pWifiChannelStats->channel.center_freq1,
1029 pWifiChannelStats->on_time,
1030 pWifiChannelStats->cca_busy_time);
1031 #endif
1032 }
1033 }
1034 break;
1035
1036 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_IFACE:
1037 {
1038 resultsBufSize = sizeof(wifi_iface_stat);
1039 mResultsParams.iface_stat =
1040 (wifi_iface_stat *) malloc (resultsBufSize);
1041 if (!mResultsParams.iface_stat)
1042 {
1043 ALOGE("%s: iface_stat: malloc Failed", __FUNCTION__);
1044 status = WIFI_ERROR_OUT_OF_MEMORY;
1045 goto cleanup;
1046 }
1047 memset(mResultsParams.iface_stat, 0, resultsBufSize);
1048 status = get_wifi_interface_info(
1049 &mResultsParams.iface_stat->info, tb_vendor);
1050 if(status != WIFI_SUCCESS)
1051 {
1052 goto cleanup;
1053 }
1054 status = get_wifi_iface_stats(mResultsParams.iface_stat,
1055 tb_vendor);
1056 if(status != WIFI_SUCCESS)
1057 {
1058 goto cleanup;
1059 }
1060
1061 /* Driver/firmware might send this attribute when there
1062 * are no peers connected.
1063 * So that, the event
1064 * QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS can be
1065 * avoided.
1066 */
1067 if (tb_vendor[
1068 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])
1069 {
1070 mResultsParams.iface_stat->num_peers =
1071 nla_get_u32(tb_vendor[
1072 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]);
1073 #ifdef QC_HAL_DEBUG
1074 ALOGV("%s: numPeers is %u\n", __FUNCTION__,
1075 mResultsParams.iface_stat->num_peers);
1076 #endif
1077 }
1078 }
1079 break;
1080
1081 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS:
1082 {
1083 struct nlattr *peerInfo;
1084 wifi_iface_stat *pIfaceStat = NULL;
1085 u32 numPeers, num_rates = 0;
1086 if (!tb_vendor[
1087 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])
1088 {
1089 ALOGE("%s:QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS"
1090 " not found", __FUNCTION__);
1091 status = WIFI_ERROR_INVALID_ARGS;
1092 goto cleanup;
1093 }
1094 #ifdef QC_HAL_DEBUG
1095 ALOGV(" numPeers is %u in %s\n",
1096 nla_get_u32(tb_vendor[
1097 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]),
1098 __FUNCTION__);
1099 #endif
1100 if((numPeers = nla_get_u32(tb_vendor[
1101 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])) > 0)
1102 {
1103 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO])
1104 {
1105 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO"
1106 " not found", __FUNCTION__);
1107 status = WIFI_ERROR_INVALID_ARGS;
1108 goto cleanup;
1109 }
1110 for (peerInfo = (struct nlattr *) nla_data(tb_vendor[
1111 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]),
1112 rem = nla_len(tb_vendor[
1113 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
1114 nla_ok(peerInfo, rem);
1115 peerInfo = nla_next(peerInfo, &(rem)))
1116 {
1117 struct nlattr *tb2[
1118 QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
1119
1120 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
1121 (struct nlattr *) nla_data(peerInfo),
1122 nla_len(peerInfo), NULL);
1123
1124 if (!tb2[
1125 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES])
1126 {
1127 ALOGE("%s:"
1128 "QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES"
1129 " not found", __FUNCTION__);
1130 status = WIFI_ERROR_INVALID_ARGS;
1131 goto cleanup;
1132 }
1133 num_rates += nla_get_u32(tb2[
1134 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
1135 }
1136 resultsBufSize += (numPeers * sizeof(wifi_peer_info)
1137 + num_rates * sizeof(wifi_rate_stat)
1138 + sizeof (wifi_iface_stat));
1139 pIfaceStat = (wifi_iface_stat *) malloc (
1140 resultsBufSize);
1141 if (!pIfaceStat)
1142 {
1143 ALOGE("%s: pIfaceStat: malloc Failed", __FUNCTION__);
1144 status = WIFI_ERROR_OUT_OF_MEMORY;
1145 goto cleanup;
1146 }
1147
1148 memset(pIfaceStat, 0, resultsBufSize);
1149 if(mResultsParams.iface_stat) {
1150 memcpy ( pIfaceStat, mResultsParams.iface_stat,
1151 sizeof(wifi_iface_stat));
1152 free (mResultsParams.iface_stat);
1153 mResultsParams.iface_stat = pIfaceStat;
1154 }
1155 wifi_peer_info *pPeerStats;
1156 pIfaceStat->num_peers = numPeers;
1157
1158 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO])
1159 {
1160 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO"
1161 " not found", __FUNCTION__);
1162 status = WIFI_ERROR_INVALID_ARGS;
1163 goto cleanup;
1164 }
1165 for (peerInfo = (struct nlattr *) nla_data(tb_vendor[
1166 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]),
1167 rem = nla_len(tb_vendor[
1168 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
1169 nla_ok(peerInfo, rem);
1170 peerInfo = nla_next(peerInfo, &(rem)))
1171 {
1172 struct nlattr *tb2[
1173 QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
1174 pPeerStats = (wifi_peer_info *) (
1175 (u8 *)pIfaceStat->peer_info
1176 + (i++ * sizeof(wifi_peer_info)));
1177 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
1178 (struct nlattr *) nla_data(peerInfo),
1179 nla_len(peerInfo), NULL);
1180 status = get_wifi_peer_info(pPeerStats, tb2);
1181 if(status != WIFI_SUCCESS)
1182 {
1183 goto cleanup;
1184 }
1185 }
1186 }
1187
1188 }
1189 break;
1190
1191 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_INVALID:
1192 default:
1193 //error case should not happen print log
1194 ALOGE("%s: Wrong LLStats subcmd received %d", __FUNCTION__,
1195 mSubcmd);
1196 }
1197 }
1198 break;
1199
1200 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR:
1201 {
1202 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
1203 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
1204 (struct nlattr *)mVendorData,
1205 mDataLen, NULL);
1206
1207 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK])
1208 {
1209 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK not found", __FUNCTION__);
1210 return WIFI_ERROR_INVALID_ARGS;
1211 }
1212 ALOGI("Resp mask : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]));
1213
1214 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP])
1215 {
1216 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP not found", __FUNCTION__);
1217 return WIFI_ERROR_INVALID_ARGS;
1218 }
1219 ALOGI("STOP resp : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]));
1220
1221 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK])
1222 {
1223 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK not found", __FUNCTION__);
1224 return WIFI_ERROR_INVALID_ARGS;
1225 }
1226 mClearRspParams.stats_clear_rsp_mask = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]);
1227
1228 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP])
1229 {
1230 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP not found", __FUNCTION__);
1231 return WIFI_ERROR_INVALID_ARGS;
1232 }
1233 mClearRspParams.stop_rsp = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]);
1234 break;
1235 }
1236 default :
1237 ALOGE("%s: Wrong LLStats subcmd received %d", __FUNCTION__, mSubcmd);
1238 }
1239 return NL_SKIP;
1240
1241 cleanup:
1242 clearStats();
1243 return status;
1244 }
1245
1246 //Implementation of the functions exposed in linklayer.h
wifi_set_link_stats(wifi_interface_handle iface,wifi_link_layer_params params)1247 wifi_error wifi_set_link_stats(wifi_interface_handle iface,
1248 wifi_link_layer_params params)
1249 {
1250 wifi_error ret;
1251 LLStatsCommand *LLCommand;
1252 struct nlattr *nl_data;
1253 interface_info *iinfo = getIfaceInfo(iface);
1254 wifi_handle handle = getWifiHandle(iface);
1255
1256 ALOGI("mpdu_size_threshold : %u, aggressive_statistics_gathering : %u",
1257 params.mpdu_size_threshold, params.aggressive_statistics_gathering);
1258 LLCommand = LLStatsCommand::instance(handle);
1259 if (LLCommand == NULL) {
1260 ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
1261 return WIFI_ERROR_UNKNOWN;
1262 }
1263 LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
1264
1265 /* create the message */
1266 ret = LLCommand->create();
1267 if (ret != WIFI_SUCCESS)
1268 goto cleanup;
1269
1270 ret = LLCommand->set_iface_id(iinfo->name);
1271 if (ret != WIFI_SUCCESS)
1272 goto cleanup;
1273
1274 /*add the attributes*/
1275 nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1276 if (!nl_data)
1277 goto cleanup;
1278 /**/
1279 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD,
1280 params.mpdu_size_threshold);
1281 if (ret != WIFI_SUCCESS)
1282 goto cleanup;
1283 /**/
1284 ret = LLCommand->put_u32(
1285 QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING,
1286 params.aggressive_statistics_gathering);
1287 if (ret != WIFI_SUCCESS)
1288 goto cleanup;
1289 LLCommand->attr_end(nl_data);
1290
1291 ret = LLCommand->requestResponse();
1292 if (ret != WIFI_SUCCESS)
1293 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1294
1295 cleanup:
1296 return ret;
1297 }
1298
1299 //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)1300 wifi_error wifi_get_link_stats(wifi_request_id id,
1301 wifi_interface_handle iface,
1302 wifi_stats_result_handler handler)
1303 {
1304 wifi_error ret;
1305 LLStatsCommand *LLCommand;
1306 struct nlattr *nl_data;
1307 interface_info *iinfo = getIfaceInfo(iface);
1308 wifi_handle handle = getWifiHandle(iface);
1309
1310 LLCommand = LLStatsCommand::instance(handle);
1311 if (LLCommand == NULL) {
1312 ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
1313 return WIFI_ERROR_UNKNOWN;
1314 }
1315 LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET);
1316
1317 LLCommand->initGetContext(id);
1318
1319 LLCommand->setHandler(handler);
1320
1321 /* create the message */
1322 ret = LLCommand->create();
1323 if (ret != WIFI_SUCCESS)
1324 goto cleanup;
1325
1326 ret = LLCommand->set_iface_id(iinfo->name);
1327 if (ret != WIFI_SUCCESS)
1328 goto cleanup;
1329 /*add the attributes*/
1330 nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1331 if (!nl_data)
1332 goto cleanup;
1333 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID,
1334 id);
1335 if (ret != WIFI_SUCCESS)
1336 goto cleanup;
1337 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK,
1338 7);
1339 if (ret != WIFI_SUCCESS)
1340 goto cleanup;
1341
1342 /**/
1343 LLCommand->attr_end(nl_data);
1344
1345 ret = LLCommand->requestResponse();
1346 if (ret != WIFI_SUCCESS)
1347 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1348
1349 if (ret != WIFI_SUCCESS) {
1350 LLCommand->clearStats();
1351 goto cleanup;
1352 }
1353
1354 if (ret == WIFI_SUCCESS)
1355 ret = LLCommand->notifyResponse();
1356
1357 cleanup:
1358 return ret;
1359 }
1360
1361
1362 //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)1363 wifi_error wifi_clear_link_stats(wifi_interface_handle iface,
1364 u32 stats_clear_req_mask,
1365 u32 *stats_clear_rsp_mask,
1366 u8 stop_req, u8 *stop_rsp)
1367 {
1368 wifi_error ret;
1369 LLStatsCommand *LLCommand;
1370 struct nlattr *nl_data;
1371 interface_info *iinfo = getIfaceInfo(iface);
1372 wifi_handle handle = getWifiHandle(iface);
1373
1374 ALOGI("clear_req : %x, stop_req : %u", stats_clear_req_mask, stop_req);
1375 LLCommand = LLStatsCommand::instance(handle);
1376 if (LLCommand == NULL) {
1377 ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
1378 return WIFI_ERROR_UNKNOWN;
1379 }
1380 LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR);
1381
1382 /* create the message */
1383 ret = LLCommand->create();
1384 if (ret != WIFI_SUCCESS)
1385 goto cleanup;
1386
1387 ret = LLCommand->set_iface_id(iinfo->name);
1388 if (ret != WIFI_SUCCESS)
1389 goto cleanup;
1390 /*add the attributes*/
1391 nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1392 if (!nl_data)
1393 goto cleanup;
1394 /**/
1395 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK,
1396 stats_clear_req_mask);
1397 if (ret != WIFI_SUCCESS)
1398 goto cleanup;
1399 /**/
1400 ret = LLCommand->put_u8(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ,
1401 stop_req);
1402 if (ret != WIFI_SUCCESS)
1403 goto cleanup;
1404 LLCommand->attr_end(nl_data);
1405
1406 ret = LLCommand->requestResponse();
1407 if (ret != WIFI_SUCCESS)
1408 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1409
1410 LLCommand->getClearRspParams(stats_clear_rsp_mask, stop_rsp);
1411
1412 cleanup:
1413 delete LLCommand;
1414 return ret;
1415 }
1416