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