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