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
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 int LLStatsCommand::create() {
34 int ifindex;
35 int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
36 if (ret < 0) {
37 return ret;
38 }
39 // insert the oui in the msg
40 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
41 if (ret < 0)
42 goto out;
43
44 // insert the subcmd in the msg
45 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
46 if (ret < 0)
47 goto out;
48
49 ALOGI("mVendor_id = %d, Subcmd = %d in %s:%d\n", mVendor_id, mSubcmd, __func__, __LINE__);
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 ALOGV("LLStatsCommand %p constructed", this);
58 memset(&mClearRspParams, 0,sizeof(LLStatsClearRspParams));
59 memset(&mResultsParams, 0,sizeof(LLStatsResultsParams));
60 memset(&mHandler, 0,sizeof(mHandler));
61 }
62
~LLStatsCommand()63 LLStatsCommand::~LLStatsCommand()
64 {
65 ALOGW("LLStatsCommand %p distructor", this);
66 mLLStatsCommandInstance = NULL;
67 unregisterVendorHandler(mVendor_id, mSubcmd);
68 }
69
instance(wifi_handle handle)70 LLStatsCommand* LLStatsCommand::instance(wifi_handle handle)
71 {
72 if (handle == NULL) {
73 ALOGE("Interface Handle is invalid");
74 return NULL;
75 }
76 if (mLLStatsCommandInstance == NULL) {
77 mLLStatsCommandInstance = new LLStatsCommand(handle, 0,
78 OUI_QCA,
79 QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
80 ALOGV("LLStatsCommand %p created", mLLStatsCommandInstance);
81 return mLLStatsCommandInstance;
82 }
83 else
84 {
85 if (handle != getWifiHandle(mLLStatsCommandInstance->mInfo))
86 {
87 ALOGE("Handle different");
88 return NULL;
89 }
90 }
91 ALOGV("LLStatsCommand %p created already", mLLStatsCommandInstance);
92 return mLLStatsCommandInstance;
93 }
94
initGetContext(u32 reqId)95 void LLStatsCommand::initGetContext(u32 reqId)
96 {
97 mRequestId = reqId;
98 memset(&mResultsParams, 0,sizeof(LLStatsResultsParams));
99 memset(&mHandler, 0,sizeof(mHandler));
100 }
101
setSubCmd(u32 subcmd)102 void LLStatsCommand::setSubCmd(u32 subcmd)
103 {
104 mSubcmd = subcmd;
105 }
106 //callback handlers registered for nl message send
error_handler_LLStats(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)107 static int error_handler_LLStats(struct sockaddr_nl *nla, struct nlmsgerr *err,
108 void *arg)
109 {
110 struct sockaddr_nl * tmp;
111 int *ret = (int *)arg;
112 tmp = nla;
113 *ret = err->error;
114 ALOGE("%s: Error code:%d (%s)", __func__, *ret, strerror(-(*ret)));
115 return NL_STOP;
116 }
117
118 //callback handlers registered for nl message send
ack_handler_LLStats(struct nl_msg * msg,void * arg)119 static int ack_handler_LLStats(struct nl_msg *msg, void *arg)
120 {
121 int *ret = (int *)arg;
122 struct nl_msg * a;
123
124 ALOGE("%s: called", __func__);
125 a = msg;
126 *ret = 0;
127 return NL_STOP;
128 }
129
130 //callback handlers registered for nl message send
finish_handler_LLStats(struct nl_msg * msg,void * arg)131 static int finish_handler_LLStats(struct nl_msg *msg, void *arg)
132 {
133 int *ret = (int *)arg;
134 struct nl_msg * a;
135
136 ALOGE("%s: called", __func__);
137 a = msg;
138 *ret = 0;
139 return NL_SKIP;
140 }
141
get_wifi_interface_info(wifi_interface_link_layer_info * stats,struct nlattr ** tb_vendor)142 static void get_wifi_interface_info(wifi_interface_link_layer_info *stats, struct nlattr **tb_vendor)
143 {
144 u32 len = 0;
145 u8 *data;
146
147 stats->mode = (wifi_interface_mode)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MODE]);
148 len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR]);
149 len = ((sizeof(stats->mac_addr) <= len) ? sizeof(stats->mac_addr) : len);
150 memcpy(&stats->mac_addr[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_MAC_ADDR]), len);
151 stats->state = (wifi_connection_state)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_STATE]);
152 stats->roaming = (wifi_roam_state)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_ROAMING]);
153 stats->capabilities = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_CAPABILITIES]);
154
155 len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID]);
156 len = ((sizeof(stats->ssid) <= len) ? sizeof(stats->ssid) : len);
157 memcpy(&stats->ssid[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_SSID]), len);
158
159 len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID]);
160 len = ((sizeof(stats->bssid) <= len) ? sizeof(stats->bssid) : len);
161 memcpy(&stats->bssid[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_BSSID]), len);
162 len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR]);
163 len = ((sizeof(stats->ap_country_str) <= len) ? sizeof(stats->ap_country_str) : len);
164 memcpy(&stats->ap_country_str[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_AP_COUNTRY_STR]),
165 len);
166 len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR]);
167 len = ((sizeof(stats->country_str) < len) ? sizeof(stats->country_str) : len);
168 memcpy(&stats->country_str[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_INFO_COUNTRY_STR]),
169 len);
170
171 ALOGI("STATS IFACE: Mode %d", stats->mode);
172 ALOGI("STATS IFACE: MAC %pM", stats->mac_addr);
173 ALOGI("STATS IFACE: State %d ", stats->state);
174 ALOGI("STATS IFACE: Roaming %d ", stats->roaming);
175 ALOGI("STATS IFACE: capabilities %0x ", stats->capabilities);
176 ALOGI("STATS IFACE: SSID %s ", stats->ssid);
177 ALOGI("STATS IFACE: BSSID %pM ", stats->bssid);
178 ALOGI("STATS IFACE: AP country str %c%c%c ", stats->ap_country_str[0],
179 stats->ap_country_str[1], stats->ap_country_str[2]);
180 ALOGI("STATS IFACE:Country String for this Association %c%c%c", stats->country_str[0],
181 stats->country_str[1], stats->country_str[2]);
182 }
183
get_wifi_wmm_ac_stat(wifi_wmm_ac_stat * stats,struct nlattr ** tb_vendor)184 static void get_wifi_wmm_ac_stat(wifi_wmm_ac_stat *stats, struct nlattr **tb_vendor)
185 {
186 stats->ac = (wifi_traffic_ac)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_AC]);
187 stats->tx_mpdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MPDU]);
188 stats->rx_mpdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MPDU]);
189 stats->tx_mcast = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_MCAST]);
190 stats->rx_mcast = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_MCAST]);
191 stats->rx_ampdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RX_AMPDU]);
192 stats->tx_ampdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_TX_AMPDU]);
193 stats->mpdu_lost = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_MPDU_LOST]);
194 stats->retries = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES]);
195 stats->retries_short = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_SHORT]);
196 stats->retries_long = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_RETRIES_LONG]);
197 stats->contention_time_min = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MIN]);
198 stats->contention_time_max = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_MAX]);
199 stats->contention_time_avg = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_TIME_AVG]);
200 stats->contention_num_samples = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_CONTENTION_NUM_SAMPLES]);
201
202 ALOGI("STATS IFACE: ac %u ", stats->ac);
203 ALOGI("STATS IFACE: txMpdu %u ", stats->tx_mpdu) ;
204 ALOGI("STATS IFACE: rxMpdu %u ", stats->rx_mpdu);
205 ALOGI("STATS IFACE: txMcast %u ", stats->tx_mcast);
206 ALOGI("STATS IFACE: rxMcast %u ", stats->rx_mcast);
207 ALOGI("STATS IFACE: rxAmpdu %u ", stats->rx_ampdu);
208 ALOGI("STATS IFACE: txAmpdu %u ", stats->tx_ampdu);
209 ALOGI("STATS IFACE: mpduLost %u ", stats->mpdu_lost);
210 ALOGI("STATS IFACE: retries %u ", stats->retries);
211 ALOGI("STATS IFACE: retriesShort %u ",
212 stats->retries_short);
213 ALOGI("STATS IFACE: retriesLong %u ",
214 stats->retries_long);
215 ALOGI("STATS IFACE: contentionTimeMin %u ",
216 stats->contention_time_min);
217 ALOGI("STATS IFACE: contentionTimeMax %u ",
218 stats->contention_time_max);
219 ALOGI("STATS IFACE: contentionTimeAvg %u ",
220 stats->contention_time_avg);
221 ALOGI("STATS IFACE: contentionNumSamples %u ",
222 stats->contention_num_samples);
223 }
224
get_wifi_rate_stat(wifi_rate_stat * stats,struct nlattr ** tb_vendor)225 static void get_wifi_rate_stat(wifi_rate_stat *stats, struct nlattr **tb_vendor)
226 {
227 stats->rate.preamble = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_PREAMBLE]);
228 stats->rate.nss = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_NSS]);
229 stats->rate.bw = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BW]);
230 stats->rate.rateMcsIdx = nla_get_u8(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MCS_INDEX]);
231 stats->rate.bitrate = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_BIT_RATE]);
232
233 stats->tx_mpdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_TX_MPDU]);
234 stats->rx_mpdu = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RX_MPDU]);
235 stats->mpdu_lost = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_MPDU_LOST]);
236 stats->retries = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES]);
237 stats->retries_short = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_SHORT]);
238 stats->retries_long = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RATE_RETRIES_LONG]);
239
240
241 ALOGI("STATS PEER_ALL : preamble %u", stats->rate.preamble);
242 ALOGI("STATS PEER_ALL : nss %u", stats->rate.nss);
243 ALOGI("STATS PEER_ALL : bw %u", stats->rate.bw);
244 ALOGI("STATS PEER_ALL : rateMcsIdx %u", stats->rate.rateMcsIdx);
245 ALOGI("STATS PEER_ALL : bitrate %u", stats->rate.bitrate);
246
247 ALOGI("STATS PEER_ALL : txMpdu %u", stats->tx_mpdu);
248 ALOGI("STATS PEER_ALL : rxMpdu %u", stats->rx_mpdu);
249 ALOGI("STATS PEER_ALL : mpduLost %u", stats->mpdu_lost);
250 ALOGI("STATS PEER_ALL : retries %u", stats->retries);
251 ALOGI("STATS PEER_ALL : retriesShort %u", stats->retries_short);
252 ALOGI("STATS PEER_ALL : retriesLong %u", stats->retries_long);
253 }
254
get_wifi_peer_info(wifi_peer_info * stats,struct nlattr ** tb_vendor)255 static void get_wifi_peer_info(wifi_peer_info *stats, struct nlattr **tb_vendor)
256 {
257 u32 i = 0, len = 0;
258 int rem;
259 wifi_rate_stat * pRateStats;
260 struct nlattr *rateInfo;
261 stats->type = (wifi_peer_type)nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_TYPE]);
262 len = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]);
263 len = ((sizeof(stats->peer_mac_address) <= len) ? sizeof(stats->peer_mac_address) : len);
264 memcpy((void *)&stats->peer_mac_address[0], nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_MAC_ADDRESS]),
265 len);
266 stats->capabilities = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_CAPABILITIES]);
267
268 stats->num_rate = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
269
270 ALOGI("STATS PEER_ALL : numPeers %u", stats->type);
271 ALOGI("STATS PEER_ALL : peerMacAddress %0x:%0x:%0x:%0x:%0x:%0x ",
272 stats->peer_mac_address[0], stats->peer_mac_address[1],
273 stats->peer_mac_address[2],stats->peer_mac_address[3],
274 stats->peer_mac_address[4],stats->peer_mac_address[5]);
275 ALOGI("STATS PEER_ALL : capabilities %0x", stats->capabilities);
276 ALOGI("STATS PEER_ALL : numRate %u", stats->num_rate);
277 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]);
278 nla_ok(rateInfo, rem);
279 rateInfo = nla_next(rateInfo, &(rem)))
280 {
281 struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
282 pRateStats = (wifi_rate_stat *) ((u8 *)stats->rate_stats + (i++ * sizeof(wifi_rate_stat)));
283
284 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(rateInfo), nla_len(rateInfo), NULL);
285 get_wifi_rate_stat(pRateStats, tb2);
286 }
287 }
288
get_wifi_iface_stats(wifi_iface_stat * stats,struct nlattr ** tb_vendor)289 static void get_wifi_iface_stats(wifi_iface_stat *stats, struct nlattr **tb_vendor)
290 {
291 struct nlattr *wmmInfo;
292 wifi_wmm_ac_stat *pWmmStats;
293 int i=0, rem;
294
295 stats->beacon_rx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_BEACON_RX]);
296 stats->mgmt_rx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_RX]);
297 stats->mgmt_action_rx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_RX]);
298 stats->mgmt_action_tx = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_MGMT_ACTION_TX]);
299 stats->rssi_mgmt = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_MGMT]);
300 stats->rssi_data = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_DATA]);
301 stats->rssi_ack = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_RSSI_ACK]);
302
303 ALOGI("STATS IFACE: beaconRx : %u ", stats->beacon_rx);
304 ALOGI("STATS IFACE: mgmtRx %u ", stats->mgmt_rx);
305 ALOGI("STATS IFACE: mgmtActionRx %u ", stats->mgmt_action_rx);
306 ALOGI("STATS IFACE: mgmtActionTx %u ", stats->mgmt_action_tx);
307 ALOGI("STATS IFACE: rssiMgmt %u ", stats->rssi_mgmt);
308 ALOGI("STATS IFACE: rssiData %u ", stats->rssi_data);
309 ALOGI("STATS IFACE: rssiAck %u ", stats->rssi_ack);
310 for (wmmInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_INFO]);
311 nla_ok(wmmInfo, rem);
312 wmmInfo = nla_next(wmmInfo, &(rem)))
313 {
314 struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
315 pWmmStats = (wifi_wmm_ac_stat *) ((u8 *)stats->ac + (i * sizeof(wifi_wmm_ac_stat)));
316 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(wmmInfo), nla_len(wmmInfo), NULL);
317 get_wifi_wmm_ac_stat(pWmmStats, tb2);
318 }
319 }
320
get_wifi_radio_stats(wifi_radio_stat * stats,struct nlattr ** tb_vendor)321 static void get_wifi_radio_stats(wifi_radio_stat *stats, struct nlattr **tb_vendor)
322 {
323 u32 i = 0;
324 struct nlattr *chInfo;
325 wifi_channel_stat *pChStats;
326 int rem;
327 printf("sunil %d : %s \n",__LINE__,__func__);
328
329 stats->radio = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ID]);
330 printf("sunil %d : %s \n",__LINE__,__func__);
331 stats->on_time = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME]);
332 printf("sunil %d : %s \n",__LINE__,__func__);
333 stats->tx_time = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_TX_TIME]);
334 printf("sunil %d : %s \n",__LINE__,__func__);
335 stats->rx_time = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_RX_TIME]);
336 ALOGI("<<<< rxTime is %u ", stats->rx_time);
337 stats->on_time_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_SCAN]);
338 stats->on_time_nbd = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_NBD]);
339 stats->on_time_gscan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_GSCAN]);
340 stats->on_time_roam_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_ROAM_SCAN]);
341 stats->on_time_pno_scan = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_PNO_SCAN]);
342 stats->on_time_hs20 = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_ON_TIME_HS20]);
343
344 stats->num_channels = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]);
345
346 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]);
347 nla_ok(chInfo, rem);
348 chInfo = nla_next(chInfo, &(rem)))
349 {
350 struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
351 pChStats = (wifi_channel_stat *) ((u8 *)stats->channels + (i++ * (sizeof(wifi_channel_stat))));
352 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(chInfo), nla_len(chInfo), NULL);
353 pChStats->channel.width = (wifi_channel_width)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_WIDTH]);
354 pChStats->channel.center_freq = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ]);
355 pChStats->channel.center_freq0 = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ0]);
356 pChStats->channel.center_freq1 = (wifi_channel)nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_CENTER_FREQ1]);
357 pChStats->on_time = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_ON_TIME]);
358 pChStats->cca_busy_time = nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_CCA_BUSY_TIME]);
359 }
360 }
361
362 // This function will be the main handler for incoming event LLStats_SUBCMD
363 //Call the appropriate callback handler after parsing the vendor data.
handleEvent(WifiEvent & event)364 int LLStatsCommand::handleEvent(WifiEvent &event)
365 {
366 ALOGI("Got a LLStats message from Driver");
367 unsigned i=0;
368 u32 status;
369 WifiVendorCommand::handleEvent(event);
370
371 // Parse the vendordata and get the attribute
372
373 switch(mSubcmd)
374 {
375 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS:
376 {
377 wifi_request_id id;
378 u32 resultsBufSize = 0;
379 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
380 int rem;
381 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
382 (struct nlattr *)mVendorData,
383 mDataLen, NULL);
384 resultsBufSize += (nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]) * sizeof(wifi_channel_stat)
385 + sizeof(wifi_radio_stat));
386 mResultsParams.radio_stat = (wifi_radio_stat *)malloc(resultsBufSize);
387 memset(mResultsParams.radio_stat, 0, resultsBufSize);
388 ALOGI(" rxTime is %u\n ", mResultsParams.radio_stat->rx_time);
389 ALOGI(" NumChan is %d\n ",
390 nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_RADIO_NUM_CHANNELS]));
391
392 if(mResultsParams.radio_stat){
393 wifi_channel_stat *pWifiChannelStats;
394 u32 i =0;
395 printf("sunil %d : %s \n",__LINE__,__func__);
396 get_wifi_radio_stats(mResultsParams.radio_stat, tb_vendor);
397
398 ALOGI(" radio is %u ", mResultsParams.radio_stat->radio);
399 ALOGI(" onTime is %u ", mResultsParams.radio_stat->on_time);
400 ALOGI(" txTime is %u ", mResultsParams.radio_stat->tx_time);
401 ALOGI(" rxTime is %u ", mResultsParams.radio_stat->rx_time);
402 ALOGI(" onTimeScan is %u ", mResultsParams.radio_stat->on_time_scan);
403 ALOGI(" onTimeNbd is %u ", mResultsParams.radio_stat->on_time_nbd);
404 ALOGI(" onTimeGscan is %u ", mResultsParams.radio_stat->on_time_gscan);
405 ALOGI(" onTimeRoamScan is %u", mResultsParams.radio_stat->on_time_roam_scan);
406 ALOGI(" onTimePnoScan is %u ", mResultsParams.radio_stat->on_time_pno_scan);
407 ALOGI(" onTimeHs20 is %u ", mResultsParams.radio_stat->on_time_hs20);
408 ALOGI(" numChannels is %u ", mResultsParams.radio_stat->num_channels);
409 for ( i=0; i < mResultsParams.radio_stat->num_channels; i++)
410 {
411 pWifiChannelStats = (wifi_channel_stat *) ((u8 *)mResultsParams.radio_stat->channels + (i * sizeof(wifi_channel_stat)));
412
413 ALOGI(" width is %u ", pWifiChannelStats->channel.width);
414 ALOGI(" CenterFreq %u ", pWifiChannelStats->channel.center_freq);
415 ALOGI(" CenterFreq0 %u ", pWifiChannelStats->channel.center_freq0);
416 ALOGI(" CenterFreq1 %u ", pWifiChannelStats->channel.center_freq1);
417 ALOGI(" onTime %u ", pWifiChannelStats->on_time);
418 ALOGI(" ccaBusyTime %u ", pWifiChannelStats->cca_busy_time);
419 }
420 ALOGI(" rxTime is %u in %s:%d\n", mResultsParams.radio_stat->rx_time, __func__, __LINE__);
421 }
422 }
423 break;
424
425 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS:
426 {
427 wifi_request_id id;
428 u32 resultsBufSize = 0;
429 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
430 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
431 (struct nlattr *)mVendorData,
432 mDataLen, NULL);
433
434 resultsBufSize = sizeof(wifi_iface_stat); // Do we need no.of peers here??
435 mResultsParams.iface_stat = (wifi_iface_stat *) malloc (sizeof (wifi_iface_stat));
436 get_wifi_interface_info(&mResultsParams.iface_stat->info, tb_vendor);
437 get_wifi_iface_stats(mResultsParams.iface_stat, tb_vendor);
438 }
439 break;
440
441 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS:
442 {
443 wifi_request_id id;
444 u32 resultsBufSize = 0, i=0, num_rates = 0;
445 u32 numPeers;
446 int rem;
447 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX + 1];
448 struct nlattr *peerInfo;
449 wifi_iface_stat *pIfaceStat;
450 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX,
451 (struct nlattr *)mVendorData,
452 mDataLen, NULL);
453
454 ALOGI(" rxTime is %u in %s:%d\n", mResultsParams.radio_stat->rx_time, __func__, __LINE__);
455 ALOGI(" numPeers is %u in %s:%d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS]), __func__, __LINE__);
456 ALOGI(" rxTe is %u in %s:%d\n", mResultsParams.radio_stat->rx_time, __func__, __LINE__);
457 if((numPeers = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_IFACE_NUM_PEERS])) > 0)
458 {
459
460 for (peerInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
461 nla_ok(peerInfo, rem);
462 peerInfo = nla_next(peerInfo, &(rem)))
463 {
464 struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
465 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(peerInfo), nla_len(peerInfo), NULL);
466 num_rates += nla_get_u32(tb2[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO_NUM_RATES]);
467 }
468 resultsBufSize += (numPeers * sizeof(wifi_peer_info)
469 + num_rates * sizeof(wifi_rate_stat) + sizeof (wifi_iface_stat));
470 pIfaceStat = (wifi_iface_stat *) malloc (resultsBufSize);
471
472 if(pIfaceStat){
473 memcpy ( pIfaceStat, mResultsParams.iface_stat , sizeof(wifi_iface_stat));
474 wifi_peer_info *pPeerStats;
475 pIfaceStat->num_peers = numPeers;
476 for (peerInfo = (struct nlattr *) nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]), rem = nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_PEER_INFO]);
477 nla_ok(peerInfo, rem);
478 peerInfo = nla_next(peerInfo, &(rem)))
479 {
480 struct nlattr *tb2[ QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX+ 1];
481 pPeerStats = (wifi_peer_info *) ((u8 *)pIfaceStat->peer_info + (i++ * sizeof(wifi_peer_info)));
482 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX, (struct nlattr *) nla_data(peerInfo), nla_len(peerInfo), NULL);
483 get_wifi_peer_info(pPeerStats, tb2);
484 }
485 }
486 if(mResultsParams.iface_stat)
487 free (mResultsParams.iface_stat);
488 mResultsParams.iface_stat = pIfaceStat;
489 }
490 // Number of Radios are 1 for now : TODO get this info from the driver
491 mHandler.on_link_stats_results(mRequestId,
492 mResultsParams.iface_stat, 1, mResultsParams.radio_stat);
493 if(mResultsParams.radio_stat)
494 {
495 free(mResultsParams.radio_stat);
496 mResultsParams.radio_stat = NULL;
497 }
498 if(mResultsParams.iface_stat)
499 {
500 free(mResultsParams.iface_stat);
501 mResultsParams.iface_stat = NULL;
502 }
503 }
504 break;
505
506 default:
507 //error case should not happen print log
508 ALOGE("%s: Wrong LLStats subcmd received %d", __func__, mSubcmd);
509 }
510
511 return NL_SKIP;
512 }
513
setCallbackHandler(LLStatsCallbackHandler nHandler,u32 event)514 int LLStatsCommand::setCallbackHandler(LLStatsCallbackHandler nHandler, u32 event)
515 {
516 int res = 0;
517 mHandler = nHandler;
518 res = registerVendorHandler(mVendor_id, event);
519 if (res != 0) {
520 //error case should not happen print log
521 ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
522 __func__, mVendor_id, mSubcmd);
523 }
524 return res;
525 }
526
unregisterHandler(u32 subCmd)527 void LLStatsCommand::unregisterHandler(u32 subCmd)
528 {
529 unregisterVendorHandler(mVendor_id, subCmd);
530 }
531
getClearRspParams(u32 * stats_clear_rsp_mask,u8 * stop_rsp)532 void LLStatsCommand::getClearRspParams(u32 *stats_clear_rsp_mask, u8 *stop_rsp)
533 {
534 *stats_clear_rsp_mask = mClearRspParams.stats_clear_rsp_mask;
535 *stop_rsp = mClearRspParams.stop_rsp;
536 }
537
requestResponse()538 int LLStatsCommand::requestResponse()
539 {
540 return WifiCommand::requestResponse(mMsg);
541 }
542
handleResponse(WifiEvent & reply)543 int LLStatsCommand::handleResponse(WifiEvent &reply)
544 {
545 ALOGI("Got a LLStats message from Driver");
546 unsigned i=0;
547 u32 status;
548 WifiVendorCommand::handleResponse(reply);
549
550 // Parse the vendordata and get the attribute
551
552 switch(mSubcmd)
553 {
554 case QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR:
555 {
556 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX + 1];
557 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_MAX,
558 (struct nlattr *)mVendorData,
559 mDataLen, NULL);
560 ALOGI("Resp mask : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]));
561 ALOGI("STOP resp : %d\n", nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]));
562 mClearRspParams.stats_clear_rsp_mask = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_RSP_MASK]);
563 mClearRspParams.stop_rsp = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_RSP]);
564 break;
565 }
566 default :
567 ALOGE("%s: Wrong LLStats subcmd received %d", __func__, mSubcmd);
568 }
569 return NL_SKIP;
570 }
571
572 //Implementation of the functions exposed in linklayer.h
wifi_set_link_stats(wifi_interface_handle iface,wifi_link_layer_params params)573 wifi_error wifi_set_link_stats(wifi_interface_handle iface,
574 wifi_link_layer_params params)
575 {
576 int ret = 0;
577 LLStatsCommand *LLCommand;
578 struct nlattr *nl_data;
579 interface_info *iinfo = getIfaceInfo(iface);
580 wifi_handle handle = getWifiHandle(iface);
581 LLCommand = LLStatsCommand::instance(handle);
582 if (LLCommand == NULL) {
583 ALOGE("%s: Error LLStatsCommand NULL", __func__);
584 return WIFI_ERROR_UNKNOWN;
585 }
586 LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);
587
588 /* create the message */
589 ret = LLCommand->create();
590 if (ret < 0)
591 goto cleanup;
592
593 ret = LLCommand->set_iface_id(iinfo->name);
594 if (ret < 0)
595 goto cleanup;
596
597 /*add the attributes*/
598 nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
599 if (!nl_data)
600 goto cleanup;
601 /**/
602 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD,
603 params.mpdu_size_threshold);
604 if (ret < 0)
605 goto cleanup;
606 /**/
607 ret = LLCommand->put_u32(
608 QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING,
609 params.aggressive_statistics_gathering);
610 if (ret < 0)
611 goto cleanup;
612 LLCommand->attr_end(nl_data);
613
614 ret = LLCommand->requestResponse();
615 if (ret != 0) {
616 ALOGE("%s: requestResponse Error:%d",__func__, ret);
617 }
618
619 cleanup:
620 return (wifi_error)ret;
621 }
622
623 //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)624 wifi_error wifi_get_link_stats(wifi_request_id id,
625 wifi_interface_handle iface,
626 wifi_stats_result_handler handler)
627 {
628 int ret = 0;
629 LLStatsCommand *LLCommand;
630 struct nlattr *nl_data;
631 interface_info *iinfo = getIfaceInfo(iface);
632 wifi_handle handle = getWifiHandle(iface);
633 pthread_t tid;
634
635 LLCommand = LLStatsCommand::instance(handle);
636 if (LLCommand == NULL) {
637 ALOGE("%s: Error LLStatsCommand NULL", __func__);
638 return WIFI_ERROR_UNKNOWN;
639 }
640 LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET);
641
642 LLCommand->initGetContext(id);
643
644 LLStatsCallbackHandler callbackHandler =
645 {
646 .on_link_stats_results = handler.on_link_stats_results
647 };
648
649 /* create the message */
650 ret = LLCommand->create();
651 if (ret < 0)
652 goto cleanup;
653
654 ret = LLCommand->set_iface_id(iinfo->name);
655 if (ret < 0)
656 goto cleanup;
657 /*add the attributes*/
658 nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
659 if (!nl_data)
660 goto cleanup;
661 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID,
662 id);
663 if (ret < 0)
664 goto cleanup;
665 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK,
666 7);
667 if (ret < 0)
668 goto cleanup;
669
670 /**/
671 LLCommand->attr_end(nl_data);
672
673 ret = LLCommand->requestResponse();
674 if (ret != 0) {
675 ALOGE("%s: requestResponse Error:%d",__func__, ret);
676 }
677 if (ret < 0)
678 goto cleanup;
679
680 ret = LLCommand->setCallbackHandler(callbackHandler, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS);
681 if (ret < 0)
682 goto cleanup;
683 ret = LLCommand->setCallbackHandler(callbackHandler, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS);
684 if (ret < 0)
685 goto cleanup;
686 ret = LLCommand->setCallbackHandler(callbackHandler, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS);
687 if (ret < 0)
688 goto cleanup;
689 cleanup:
690 return (wifi_error)ret;
691 }
692
693
694 //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)695 wifi_error wifi_clear_link_stats(wifi_interface_handle iface,
696 u32 stats_clear_req_mask,
697 u32 *stats_clear_rsp_mask,
698 u8 stop_req, u8 *stop_rsp)
699 {
700 int ret = 0;
701 LLStatsCommand *LLCommand;
702 struct nlattr *nl_data;
703 interface_info *iinfo = getIfaceInfo(iface);
704 wifi_handle handle = getWifiHandle(iface);
705
706 LLCommand = LLStatsCommand::instance(handle);
707 if (LLCommand == NULL) {
708 ALOGE("%s: Error LLStatsCommand NULL", __func__);
709 return WIFI_ERROR_UNKNOWN;
710 }
711 LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR);
712
713 /* create the message */
714 ret = LLCommand->create();
715 if (ret < 0)
716 goto cleanup;
717
718 ret = LLCommand->set_iface_id(iinfo->name);
719 if (ret < 0)
720 goto cleanup;
721 /*add the attributes*/
722 nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
723 if (!nl_data)
724 goto cleanup;
725 /**/
726 ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK,
727 stats_clear_req_mask);
728 if (ret < 0)
729 goto cleanup;
730 /**/
731 ret = LLCommand->put_u8(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ,
732 stop_req);
733 if (ret < 0)
734 goto cleanup;
735 LLCommand->attr_end(nl_data);
736
737 ret = LLCommand->requestResponse();
738 if (ret != 0) {
739 ALOGE("%s: requestResponse Error:%d",__func__, ret);
740 }
741
742 LLCommand->getClearRspParams(stats_clear_rsp_mask, stop_rsp);
743
744 cleanup:
745 LLCommand->unregisterHandler(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS);
746 LLCommand->unregisterHandler(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS);
747 LLCommand->unregisterHandler(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS);
748 delete LLCommand;
749 return (wifi_error)ret;
750 }
751
752