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