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