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