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