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