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