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