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 <hardware_legacy/wifi_hal.h>
24 #include "common.h"
25 #include "cpp_bindings.h"
26 #include "llstatscommand.h"
27
28 //Singleton Static Instance
29 LLStatsCommand* LLStatsCommand::mLLStatsCommandInstance = NULL;
30
31 // This function implements creation of Vendor command
32 // For LLStats just call base Vendor command create
create()33 wifi_error LLStatsCommand::create() {
34 wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
35 if (ret != WIFI_SUCCESS)
36 return ret;
37
38 // insert the oui in the msg
39 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
40 if (ret != WIFI_SUCCESS)
41 return ret;
42
43 // insert the subcmd in the msg
44 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
45
46 return ret;
47 }
48
LLStatsCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)49 LLStatsCommand::LLStatsCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
50 : WifiVendorCommand(handle, id, vendor_id, subcmd)
51 {
52 memset(&mClearRspParams, 0,sizeof(LLStatsClearRspParams));
53 memset(&mResultsParams, 0,sizeof(LLStatsResultsParams));
54 memset(&mHandler, 0,sizeof(mHandler));
55 mRadioStatsSize = 0;
56 mNumRadios = 0;
57 mNumRadiosAllocated = 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 if (tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME])
843 pChStats->cca_busy_time -= nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME]);
844
845 }
846 return WIFI_SUCCESS;
847 }
848
getClearRspParams(u32 * stats_clear_rsp_mask,u8 * stop_rsp)849 void LLStatsCommand::getClearRspParams(u32 *stats_clear_rsp_mask, u8 *stop_rsp)
850 {
851 *stats_clear_rsp_mask = mClearRspParams.stats_clear_rsp_mask;
852 *stop_rsp = mClearRspParams.stop_rsp;
853 }
854
requestResponse()855 wifi_error LLStatsCommand::requestResponse()
856 {
857 return WifiCommand::requestResponse(mMsg);
858 }
859
notifyResponse()860 wifi_error LLStatsCommand::notifyResponse()
861 {
862 wifi_error ret = WIFI_SUCCESS;
863
864 /* Indicate stats to framework only if both radio and iface stats
865 * are present */
866 if (mResultsParams.radio_stat && mResultsParams.iface_stat) {
867 if (mNumRadios > mNumRadiosAllocated) {
868 ALOGE("%s: Force reset mNumRadios=%d to allocated=%d",
869 __FUNCTION__, mNumRadios, mNumRadiosAllocated);
870 mNumRadios = mNumRadiosAllocated;
871 }
872 mHandler.on_link_stats_results(mRequestId,
873 mResultsParams.iface_stat, mNumRadios,
874 mResultsParams.radio_stat);
875 } else {
876 ret = WIFI_ERROR_INVALID_ARGS;
877 }
878
879 clearStats();
880
881 return ret;
882 }
883
884
clearStats()885 void LLStatsCommand::clearStats()
886 {
887 if(mResultsParams.radio_stat)
888 {
889 wifi_radio_stat *radioStat = mResultsParams.radio_stat;
890 if (mNumRadios > mNumRadiosAllocated) {
891 ALOGE("%s: Force reset mNumRadios=%d to allocated=%d",
892 __FUNCTION__, mNumRadios, mNumRadiosAllocated);
893 mNumRadios = mNumRadiosAllocated;
894 }
895 for (u8 radio = 0; radio < mNumRadios; radio++) {
896 if (radioStat->tx_time_per_levels) {
897 free(radioStat->tx_time_per_levels);
898 radioStat->tx_time_per_levels = NULL;
899 }
900 radioStat = (wifi_radio_stat *)((u8 *)radioStat +
901 sizeof(wifi_radio_stat) + (sizeof(wifi_channel_stat) *
902 radioStat->num_channels));
903 }
904 free(mResultsParams.radio_stat);
905 mResultsParams.radio_stat = NULL;
906 mRadioStatsSize = 0;
907 mNumRadios = 0;
908 mNumRadiosAllocated = 0;
909 }
910 if(mResultsParams.iface_stat)
911 {
912 free(mResultsParams.iface_stat);
913 mResultsParams.iface_stat = NULL;
914 }
915 }
916
917
handleResponse(WifiEvent & reply)918 int LLStatsCommand::handleResponse(WifiEvent &reply)
919 {
920 unsigned i=0;
921 int status = WIFI_ERROR_NONE;
922 WifiVendorCommand::handleResponse(reply);
923
924 // Parse the vendordata and get the attribute
925
926 switch(mSubcmd)
927 {
928 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET:
929 {
930 u32 resultsBufSize = 0;
931 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
932 int rem;
933 wifi_radio_stat *radioStatsBuf;
934
935 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
936 (struct nlattr *)mVendorData,
937 mDataLen, NULL);
938
939 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE])
940 {
941 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE not found",
942 __FUNCTION__);
943 status = WIFI_ERROR_INVALID_ARGS;
944 goto cleanup;
945 }
946
947 switch(nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_TYPE]))
948 {
949 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_RADIO:
950 {
951 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS])
952 {
953 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS"
954 " not found", __FUNCTION__);
955 return WIFI_ERROR_INVALID_ARGS;
956 }
957 mNumRadios = nla_get_u32(tb_vendor[
958 QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS]);
959
960 if (!tb_vendor[
961 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS
962 ])
963 {
964 ALOGE("%s:"
965 "QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS"
966 " not found", __FUNCTION__);
967 status = WIFI_ERROR_INVALID_ARGS;
968 goto cleanup;
969 }
970
971 resultsBufSize += (nla_get_u32(tb_vendor[
972 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS])
973 * sizeof(wifi_channel_stat)
974 + sizeof(wifi_radio_stat));
975
976 radioStatsBuf = (wifi_radio_stat *)realloc(
977 mResultsParams.radio_stat,
978 mRadioStatsSize + resultsBufSize);
979 if (!radioStatsBuf)
980 {
981 ALOGE("%s: radio_stat: malloc Failed", __FUNCTION__);
982 status = WIFI_ERROR_OUT_OF_MEMORY;
983 goto cleanup;
984 }
985 mResultsParams.radio_stat = radioStatsBuf;
986
987 //Move the buffer to populate current radio stats
988 radioStatsBuf = (wifi_radio_stat *)(
989 (u8 *)mResultsParams.radio_stat
990 + mRadioStatsSize);
991 memset(radioStatsBuf, 0, resultsBufSize);
992 mRadioStatsSize += resultsBufSize;
993 mNumRadiosAllocated ++;
994
995 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS])
996 radioStatsBuf->num_tx_levels = nla_get_u32(tb_vendor[
997 QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_TX_LEVELS]);
998
999 wifi_channel_stat *pWifiChannelStats;
1000 status = get_wifi_radio_stats(radioStatsBuf,
1001 tb_vendor);
1002 if(status != WIFI_SUCCESS)
1003 {
1004 goto cleanup;
1005 }
1006 #ifdef QC_HAL_DEBUG
1007 ALOGV("radio :%u onTime :%u txTime :%u rxTime :%u"
1008 " onTimeScan :%u onTimeNbd :%u onTimeGscan :%u"
1009 " onTimeRoamScan :%u onTimePnoScan :%u"
1010 " onTimeHs20 :%u numChannels :%u num_tx_levels: %u",
1011 radioStatsBuf->radio,
1012 radioStatsBuf->on_time,
1013 radioStatsBuf->tx_time,
1014 radioStatsBuf->rx_time,
1015 radioStatsBuf->on_time_scan,
1016 radioStatsBuf->on_time_nbd,
1017 radioStatsBuf->on_time_gscan,
1018 radioStatsBuf->on_time_roam_scan,
1019 radioStatsBuf->on_time_pno_scan,
1020 radioStatsBuf->on_time_hs20,
1021 radioStatsBuf->num_channels,
1022 radioStatsBuf->num_tx_levels);
1023 #ifdef QC_HAL_DEBUG
1024 for (i = 0; i < radioStatsBuf->num_tx_levels; i++) {
1025 ALOGV("Power level: %u tx_time: %u", i,
1026 radioStatsBuf->tx_time_per_levels[i]);
1027 }
1028 #endif
1029 ALOGV("%5s | %10s | %11s | %11s | %6s | %11s", "width",
1030 "CenterFreq", "CenterFreq0", "CenterFreq1",
1031 "onTime", "ccaBusyTime");
1032 #endif
1033 for ( i=0; i < radioStatsBuf->num_channels; i++)
1034 {
1035 pWifiChannelStats =
1036 (wifi_channel_stat *) (
1037 (u8 *)radioStatsBuf->channels
1038 + (i * sizeof(wifi_channel_stat)));
1039
1040 #ifdef QC_HAL_DEBUG
1041 ALOGV("%5u | %10u | %11u | %11u | %6u | %11u",
1042 pWifiChannelStats->channel.width,
1043 pWifiChannelStats->channel.center_freq,
1044 pWifiChannelStats->channel.center_freq0,
1045 pWifiChannelStats->channel.center_freq1,
1046 pWifiChannelStats->on_time,
1047 pWifiChannelStats->cca_busy_time);
1048 #endif
1049 }
1050 }
1051 break;
1052
1053 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_IFACE:
1054 {
1055 resultsBufSize = sizeof(wifi_iface_stat);
1056 mResultsParams.iface_stat =
1057 (wifi_iface_stat *) malloc (resultsBufSize);
1058 if (!mResultsParams.iface_stat)
1059 {
1060 ALOGE("%s: iface_stat: malloc Failed", __FUNCTION__);
1061 status = WIFI_ERROR_OUT_OF_MEMORY;
1062 goto cleanup;
1063 }
1064 memset(mResultsParams.iface_stat, 0, resultsBufSize);
1065 status = get_wifi_interface_info(
1066 &mResultsParams.iface_stat->info, tb_vendor);
1067 if(status != WIFI_SUCCESS)
1068 {
1069 goto cleanup;
1070 }
1071 status = get_wifi_iface_stats(mResultsParams.iface_stat,
1072 tb_vendor);
1073 if(status != WIFI_SUCCESS)
1074 {
1075 goto cleanup;
1076 }
1077
1078 /* Driver/firmware might send this attribute when there
1079 * are no peers connected.
1080 * So that, the event
1081 * QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS can be
1082 * avoided.
1083 */
1084 if (tb_vendor[
1085 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])
1086 {
1087 mResultsParams.iface_stat->num_peers =
1088 nla_get_u32(tb_vendor[
1089 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]);
1090 #ifdef QC_HAL_DEBUG
1091 ALOGV("%s: numPeers is %u\n", __FUNCTION__,
1092 mResultsParams.iface_stat->num_peers);
1093 #endif
1094 }
1095 }
1096 break;
1097
1098 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_PEERS:
1099 {
1100 struct nlattr *peerInfo;
1101 wifi_iface_stat *pIfaceStat = NULL;
1102 u32 numPeers, num_rates = 0;
1103 if (!tb_vendor[
1104 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])
1105 {
1106 ALOGE("%s:QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS"
1107 " not found", __FUNCTION__);
1108 status = WIFI_ERROR_INVALID_ARGS;
1109 goto cleanup;
1110 }
1111 #ifdef QC_HAL_DEBUG
1112 ALOGV(" numPeers is %u in %s\n",
1113 nla_get_u32(tb_vendor[
1114 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]),
1115 __FUNCTION__);
1116 #endif
1117 if((numPeers = nla_get_u32(tb_vendor[
1118 QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])) > 0)
1119 {
1120 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO])
1121 {
1122 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO"
1123 " not found", __FUNCTION__);
1124 status = WIFI_ERROR_INVALID_ARGS;
1125 goto cleanup;
1126 }
1127 for (peerInfo = (struct nlattr *) nla_data(tb_vendor[
1128 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]),
1129 rem = nla_len(tb_vendor[
1130 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
1131 nla_ok(peerInfo, rem);
1132 peerInfo = nla_next(peerInfo, &(rem)))
1133 {
1134 struct nlattr *tb2[
1135 QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
1136
1137 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
1138 (struct nlattr *) nla_data(peerInfo),
1139 nla_len(peerInfo), NULL);
1140
1141 if (!tb2[
1142 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES])
1143 {
1144 ALOGE("%s:"
1145 "QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES"
1146 " not found", __FUNCTION__);
1147 status = WIFI_ERROR_INVALID_ARGS;
1148 goto cleanup;
1149 }
1150 num_rates += nla_get_u32(tb2[
1151 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
1152 }
1153 resultsBufSize += (numPeers * sizeof(wifi_peer_info)
1154 + num_rates * sizeof(wifi_rate_stat)
1155 + sizeof (wifi_iface_stat));
1156 pIfaceStat = (wifi_iface_stat *) malloc (
1157 resultsBufSize);
1158 if (!pIfaceStat)
1159 {
1160 ALOGE("%s: pIfaceStat: malloc Failed", __FUNCTION__);
1161 status = WIFI_ERROR_OUT_OF_MEMORY;
1162 goto cleanup;
1163 }
1164
1165 memset(pIfaceStat, 0, resultsBufSize);
1166 if(mResultsParams.iface_stat) {
1167 if(resultsBufSize >= sizeof(wifi_iface_stat)) {
1168 memcpy ( pIfaceStat, mResultsParams.iface_stat,
1169 sizeof(wifi_iface_stat));
1170 free (mResultsParams.iface_stat);
1171 mResultsParams.iface_stat = pIfaceStat;
1172 } else {
1173 ALOGE("%s: numPeers = %u, num_rates= %u, "
1174 "either numPeers or num_rates is invalid",
1175 __FUNCTION__,numPeers,num_rates);
1176 status = WIFI_ERROR_UNKNOWN;
1177 free(pIfaceStat);
1178 goto cleanup;
1179 }
1180 }
1181 wifi_peer_info *pPeerStats;
1182 pIfaceStat->num_peers = numPeers;
1183
1184 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO])
1185 {
1186 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO"
1187 " not found", __FUNCTION__);
1188 status = WIFI_ERROR_INVALID_ARGS;
1189 goto cleanup;
1190 }
1191 num_rates = 0;
1192 for (peerInfo = (struct nlattr *) nla_data(tb_vendor[
1193 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]),
1194 rem = nla_len(tb_vendor[
1195 QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
1196 nla_ok(peerInfo, rem);
1197 peerInfo = nla_next(peerInfo, &(rem)))
1198 {
1199 struct nlattr *tb2[
1200 QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
1201 pPeerStats = (wifi_peer_info *) (
1202 (u8 *)pIfaceStat->peer_info
1203 + (i++ * sizeof(wifi_peer_info))
1204 + (num_rates * sizeof(wifi_rate_stat)));
1205 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
1206 (struct nlattr *) nla_data(peerInfo),
1207 nla_len(peerInfo), NULL);
1208 status = get_wifi_peer_info(pPeerStats, tb2);
1209 if(status != WIFI_SUCCESS)
1210 {
1211 goto cleanup;
1212 }
1213 num_rates += pPeerStats->num_rate;
1214 }
1215 }
1216
1217 }
1218 break;
1219
1220 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_TYPE_INVALID:
1221 default:
1222 //error case should not happen print log
1223 ALOGE("%s: Wrong LLStats subcmd received %d", __FUNCTION__,
1224 mSubcmd);
1225 }
1226 }
1227 break;
1228
1229 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR:
1230 {
1231 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
1232 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
1233 (struct nlattr *)mVendorData,
1234 mDataLen, NULL);
1235
1236 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK])
1237 {
1238 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK not found", __FUNCTION__);
1239 return WIFI_ERROR_INVALID_ARGS;
1240 }
1241 ALOGI("Resp mask : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]));
1242
1243 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP])
1244 {
1245 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP not found", __FUNCTION__);
1246 return WIFI_ERROR_INVALID_ARGS;
1247 }
1248 ALOGI("STOP resp : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]));
1249
1250 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK])
1251 {
1252 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK not found", __FUNCTION__);
1253 return WIFI_ERROR_INVALID_ARGS;
1254 }
1255 mClearRspParams.stats_clear_rsp_mask = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]);
1256
1257 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP])
1258 {
1259 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP not found", __FUNCTION__);
1260 return WIFI_ERROR_INVALID_ARGS;
1261 }
1262 mClearRspParams.stop_rsp = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]);
1263 break;
1264 }
1265 default :
1266 ALOGE("%s: Wrong LLStats subcmd received %d", __FUNCTION__, mSubcmd);
1267 }
1268 return NL_SKIP;
1269
1270 cleanup:
1271 clearStats();
1272 return status;
1273 }
1274
1275 //Implementation of the functions exposed in linklayer.h
wifi_set_link_stats(wifi_interface_handle iface,wifi_link_layer_params params)1276 wifi_error wifi_set_link_stats(wifi_interface_handle iface,
1277 wifi_link_layer_params params)
1278 {
1279 wifi_error ret;
1280 LLStatsCommand *LLCommand;
1281 struct nlattr *nl_data;
1282 interface_info *iinfo = getIfaceInfo(iface);
1283 wifi_handle handle = getWifiHandle(iface);
1284
1285 ALOGI("mpdu_size_threshold : %u, aggressive_statistics_gathering : %u",
1286 params.mpdu_size_threshold, params.aggressive_statistics_gathering);
1287 LLCommand = LLStatsCommand::instance(handle);
1288 if (LLCommand == NULL) {
1289 ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
1290 return WIFI_ERROR_UNKNOWN;
1291 }
1292 LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
1293
1294 /* create the message */
1295 ret = LLCommand->create();
1296 if (ret != WIFI_SUCCESS)
1297 goto cleanup;
1298
1299 ret = LLCommand->set_iface_id(iinfo->name);
1300 if (ret != WIFI_SUCCESS)
1301 goto cleanup;
1302
1303 /*add the attributes*/
1304 nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1305 if (!nl_data)
1306 goto cleanup;
1307 /**/
1308 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD,
1309 params.mpdu_size_threshold);
1310 if (ret != WIFI_SUCCESS)
1311 goto cleanup;
1312 /**/
1313 ret = LLCommand->put_u32(
1314 QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING,
1315 params.aggressive_statistics_gathering);
1316 if (ret != WIFI_SUCCESS)
1317 goto cleanup;
1318 LLCommand->attr_end(nl_data);
1319
1320 ret = LLCommand->requestResponse();
1321 if (ret != WIFI_SUCCESS)
1322 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1323
1324 cleanup:
1325 return ret;
1326 }
1327
1328 //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)1329 wifi_error wifi_get_link_stats(wifi_request_id id,
1330 wifi_interface_handle iface,
1331 wifi_stats_result_handler handler)
1332 {
1333 wifi_error ret;
1334 LLStatsCommand *LLCommand;
1335 struct nlattr *nl_data;
1336 interface_info *iinfo = getIfaceInfo(iface);
1337 wifi_handle handle = getWifiHandle(iface);
1338
1339 LLCommand = LLStatsCommand::instance(handle);
1340 if (LLCommand == NULL) {
1341 ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
1342 return WIFI_ERROR_UNKNOWN;
1343 }
1344 LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET);
1345
1346 LLCommand->initGetContext(id);
1347
1348 LLCommand->setHandler(handler);
1349
1350 /* create the message */
1351 ret = LLCommand->create();
1352 if (ret != WIFI_SUCCESS)
1353 goto cleanup;
1354
1355 ret = LLCommand->set_iface_id(iinfo->name);
1356 if (ret != WIFI_SUCCESS)
1357 goto cleanup;
1358 /*add the attributes*/
1359 nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1360 if (!nl_data)
1361 goto cleanup;
1362 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID,
1363 id);
1364 if (ret != WIFI_SUCCESS)
1365 goto cleanup;
1366 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK,
1367 7);
1368 if (ret != WIFI_SUCCESS)
1369 goto cleanup;
1370
1371 /**/
1372 LLCommand->attr_end(nl_data);
1373
1374 ret = LLCommand->requestResponse();
1375 if (ret != WIFI_SUCCESS)
1376 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1377
1378 if (ret != WIFI_SUCCESS) {
1379 LLCommand->clearStats();
1380 goto cleanup;
1381 }
1382
1383 if (ret == WIFI_SUCCESS)
1384 ret = LLCommand->notifyResponse();
1385
1386 cleanup:
1387 return ret;
1388 }
1389
1390
1391 //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)1392 wifi_error wifi_clear_link_stats(wifi_interface_handle iface,
1393 u32 stats_clear_req_mask,
1394 u32 *stats_clear_rsp_mask,
1395 u8 stop_req, u8 *stop_rsp)
1396 {
1397 wifi_error ret;
1398 LLStatsCommand *LLCommand;
1399 struct nlattr *nl_data;
1400 interface_info *iinfo = getIfaceInfo(iface);
1401 wifi_handle handle = getWifiHandle(iface);
1402
1403 ALOGI("clear_req : %x, stop_req : %u", stats_clear_req_mask, stop_req);
1404 LLCommand = LLStatsCommand::instance(handle);
1405 if (LLCommand == NULL) {
1406 ALOGE("%s: Error LLStatsCommand NULL", __FUNCTION__);
1407 return WIFI_ERROR_UNKNOWN;
1408 }
1409 LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR);
1410
1411 /* create the message */
1412 ret = LLCommand->create();
1413 if (ret != WIFI_SUCCESS)
1414 goto cleanup;
1415
1416 ret = LLCommand->set_iface_id(iinfo->name);
1417 if (ret != WIFI_SUCCESS)
1418 goto cleanup;
1419 /*add the attributes*/
1420 nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1421 if (!nl_data)
1422 goto cleanup;
1423 /**/
1424 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK,
1425 stats_clear_req_mask);
1426 if (ret != WIFI_SUCCESS)
1427 goto cleanup;
1428 /**/
1429 ret = LLCommand->put_u8(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ,
1430 stop_req);
1431 if (ret != WIFI_SUCCESS)
1432 goto cleanup;
1433 LLCommand->attr_end(nl_data);
1434
1435 ret = LLCommand->requestResponse();
1436 if (ret != WIFI_SUCCESS)
1437 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret);
1438
1439 LLCommand->getClearRspParams(stats_clear_rsp_mask, stop_rsp);
1440
1441 cleanup:
1442 delete LLCommand;
1443 return ret;
1444 }
1445