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