llstats.cpp revision a779e36f603bbb1b3cd82afeeb4d519d69f6c9fc
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
29LLStatsCommand* LLStatsCommand::mLLStatsCommandInstance  = NULL;
30
31// This function implements creation of Vendor command
32// For LLStats just call base Vendor command create
33int 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__);
50out:
51    return ret;
52}
53
54LLStatsCommand::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
63LLStatsCommand::~LLStatsCommand()
64{
65    ALOGW("LLStatsCommand %p distructor", this);
66    mLLStatsCommandInstance = NULL;
67    unregisterVendorHandler(mVendor_id, mSubcmd);
68}
69
70LLStatsCommand* 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
95void LLStatsCommand::initGetContext(u32 reqId)
96{
97    mRequestId = reqId;
98    memset(&mResultsParams, 0,sizeof(LLStatsResultsParams));
99    memset(&mHandler, 0,sizeof(mHandler));
100}
101
102void LLStatsCommand::setSubCmd(u32 subcmd)
103{
104    mSubcmd = subcmd;
105}
106//callback handlers registered for nl message send
107static 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
119static 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
131static 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
142static 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
184static 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
225static 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
255static 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
289static 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
321static 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.
364int 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
514int 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
527void LLStatsCommand::unregisterHandler(u32 subCmd)
528{
529    unregisterVendorHandler(mVendor_id, subCmd);
530}
531
532void 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
538int LLStatsCommand::requestResponse()
539{
540    return WifiCommand::requestResponse(mMsg);
541}
542
543int 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
573wifi_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
619cleanup:
620    return (wifi_error)ret;
621}
622
623//Implementation of the functions exposed in LLStats.h
624wifi_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;
689cleanup:
690    return (wifi_error)ret;
691}
692
693
694//Implementation of the functions exposed in LLStats.h
695wifi_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
744cleanup:
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