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