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