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