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