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