1/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 *  * Redistributions of source code must retain the above copyright
7 *    notice, this list of conditions and the following disclaimer.
8 *  * Redistributions in binary form must reproduce the above
9 *    copyright notice, this list of conditions and the following
10 *    disclaimer in the documentation and/or other materials provided
11 *    with the distribution.
12 *  * Neither the name of The Linux Foundation nor the names of its
13 *    contributors may be used to endorse or promote products derived
14 *    from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "sync.h"
30
31#include "wifi_hal.h"
32#include "common.h"
33#include "cpp_bindings.h"
34#include <errno.h>
35#include <utils/Log.h>
36#include "wifiloggercmd.h"
37#include "rb_wrapper.h"
38#include <stdlib.h>
39
40#define LOGGER_MEMDUMP_FILENAME "/proc/debug/fwdump"
41#define DRIVER_MEMDUMP_FILENAME "/proc/debugdriver/driverdump"
42#define LOGGER_MEMDUMP_CHUNKSIZE (4 * 1024)
43#define DRIVER_MEMDUMP_MAX_FILESIZE (16 * 1024)
44
45char power_events_ring_name[] = "power_events_rb";
46char connectivity_events_ring_name[] = "connectivity_events_rb";
47char pkt_stats_ring_name[] = "pkt_stats_rb";
48char driver_prints_ring_name[] = "driver_prints_rb";
49char firmware_prints_ring_name[] = "firmware_prints_rb";
50
51static int get_ring_id(hal_info *info, char *ring_name)
52{
53    int rb_id;
54
55    for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
56        if (is_rb_name_match(&info->rb_infos[rb_id], ring_name)) {
57           return rb_id;
58        }
59    }
60    return -1;
61}
62
63//Implementation of the functions exposed in wifi_logger.h
64
65/* Function to intiate logging */
66wifi_error wifi_start_logging(wifi_interface_handle iface,
67                              u32 verbose_level, u32 flags,
68                              u32 max_interval_sec, u32 min_data_size,
69                              char *buffer_name)
70{
71    int requestId, ret = 0;
72    WifiLoggerCommand *wifiLoggerCommand = NULL;
73    struct nlattr *nlData;
74    interface_info *ifaceInfo = getIfaceInfo(iface);
75    wifi_handle wifiHandle = getWifiHandle(iface);
76    hal_info *info = getHalInfo(wifiHandle);
77    int ring_id = 0;
78
79    /*
80     * No request id from caller, so generate one and pass it on to the driver.
81     * Generate one randomly.
82     */
83    requestId = get_requestid();
84
85    if (buffer_name == NULL) {
86        ALOGE("%s: Invalid Ring Name. \n", __FUNCTION__);
87        return WIFI_ERROR_UNKNOWN;
88    }
89
90    ring_id = get_ring_id(info, buffer_name);
91    if (ring_id < 0) {
92        ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__);
93        return WIFI_ERROR_UNKNOWN;
94    }
95
96    wifiLoggerCommand = new WifiLoggerCommand(
97                            wifiHandle,
98                            requestId,
99                            OUI_QCA,
100                            QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START);
101
102    if (wifiLoggerCommand == NULL) {
103       ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
104       return WIFI_ERROR_UNKNOWN;
105    }
106    /* Create the NL message. */
107    ret = wifiLoggerCommand->create();
108
109    if (ret < 0)
110        goto cleanup;
111
112    /* Set the interface Id of the message. */
113    ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
114
115    if (ret < 0)
116        goto cleanup;
117
118    /* Add the vendor specific attributes for the NL command. */
119    nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
120
121    if (!nlData)
122        goto cleanup;
123
124    if (wifiLoggerCommand->put_u32(
125                QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID, ring_id))
126    {
127        goto cleanup;
128    }
129    if (wifiLoggerCommand->put_u32(
130                QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL,
131                verbose_level))
132    {
133        goto cleanup;
134    }
135    if (wifiLoggerCommand->put_u32(
136                QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS,
137                flags))
138    {
139        goto cleanup;
140    }
141
142    wifiLoggerCommand->attr_end(nlData);
143
144    /* Send the msg and wait for a response. */
145    ret = wifiLoggerCommand->requestResponse();
146    if (ret) {
147        ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
148    }
149
150    ALOGV("%s: Logging Started for %s.", __FUNCTION__, buffer_name);
151    rb_start_logging(&info->rb_infos[ring_id], verbose_level,
152                    flags, max_interval_sec, min_data_size);
153cleanup:
154    if (wifiLoggerCommand)
155        delete wifiLoggerCommand;
156    return (wifi_error)ret;
157
158}
159
160/*  Function to get each ring related info */
161wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
162                                        u32 *num_buffers,
163                                        wifi_ring_buffer_status *status)
164{
165    int ret = 0;
166    interface_info *ifaceInfo = getIfaceInfo(iface);
167    wifi_handle wifiHandle = getWifiHandle(iface);
168    hal_info *info = getHalInfo(wifiHandle);
169    wifi_ring_buffer_status *rbs;
170    struct rb_info *rb_info;
171    int rb_id;
172
173    if ((*num_buffers) < NUM_RING_BUFS) {
174        ALOGE("%s: Input num_buffers:%u cannot be accommodated, "
175              "Total ring buffer num:%d", __FUNCTION__, *num_buffers,
176              NUM_RING_BUFS);
177        *num_buffers = 0;
178        return WIFI_ERROR_OUT_OF_MEMORY;
179    }
180    for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
181        rb_info = &info->rb_infos[rb_id];
182        rbs = status + rb_id;
183
184        get_rb_status(rb_info, rbs);
185    }
186    *num_buffers = NUM_RING_BUFS;
187    return (wifi_error)ret;
188}
189
190void push_out_all_ring_buffers(hal_info *info)
191{
192    int rb_id;
193
194    for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
195        push_out_rb_data(&info->rb_infos[rb_id]);
196    }
197}
198
199void send_alert(hal_info *info, int reason_code)
200{
201    wifi_alert_handler handler;
202
203    pthread_mutex_lock(&info->ah_lock);
204    handler.on_alert = info->on_alert;
205    pthread_mutex_unlock(&info->ah_lock);
206
207    if (handler.on_alert) {
208        handler.on_alert(0, NULL, 0, reason_code);
209    }
210}
211
212void WifiLoggerCommand::setFeatureSet(u32 *support) {
213    mSupportedSet = support;
214}
215
216/*  Function to get the supported feature set for logging.*/
217wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
218                                                 u32 *support)
219{
220
221    int requestId, ret = 0;
222    WifiLoggerCommand *wifiLoggerCommand;
223    struct nlattr *nlData;
224    interface_info *ifaceInfo = getIfaceInfo(iface);
225    wifi_handle wifiHandle = getWifiHandle(iface);
226    hal_info *info = getHalInfo(wifiHandle);
227
228    /* No request id from caller, so generate one and pass it on to the driver.
229     * Generate one randomly.
230     */
231    requestId = get_requestid();
232
233    wifiLoggerCommand = new WifiLoggerCommand(
234                            wifiHandle,
235                            requestId,
236                            OUI_QCA,
237                            QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET);
238
239    if (wifiLoggerCommand == NULL) {
240        ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
241        return WIFI_ERROR_UNKNOWN;
242    }
243    /* Create the NL message. */
244    ret = wifiLoggerCommand->create();
245
246    if (ret < 0)
247        goto cleanup;
248
249    /* Set the interface Id of the message. */
250    ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
251
252    if (ret < 0)
253        goto cleanup;
254
255    /* Add the vendor specific attributes for the NL command. */
256    nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
257
258    if (!nlData)
259        goto cleanup;
260
261    if (wifiLoggerCommand->put_u32(
262                QCA_WLAN_VENDOR_ATTR_FEATURE_SET, requestId))
263    {
264        goto cleanup;
265    }
266    wifiLoggerCommand->attr_end(nlData);
267
268    wifiLoggerCommand->setFeatureSet(support);
269
270    /* Send the msg and wait for a response. */
271    ret = wifiLoggerCommand->requestResponse();
272    if (ret) {
273        ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
274    }
275
276cleanup:
277    delete wifiLoggerCommand;
278    return (wifi_error)ret;
279}
280
281/*  Function to get the data in each ring for the given ring ID.*/
282wifi_error wifi_get_ring_data(wifi_interface_handle iface,
283                              char *ring_name)
284{
285
286    int requestId, ret = 0;
287    WifiLoggerCommand *wifiLoggerCommand;
288    struct nlattr *nlData;
289    interface_info *ifaceInfo = getIfaceInfo(iface);
290    wifi_handle wifiHandle = getWifiHandle(iface);
291    hal_info *info = getHalInfo(wifiHandle);
292    int ring_id = 0;
293
294    ring_id = get_ring_id(info, ring_name);
295    if (ring_id < 0) {
296        ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__);
297        return WIFI_ERROR_UNKNOWN;
298    }
299
300    requestId = get_requestid();
301
302    wifiLoggerCommand = new WifiLoggerCommand(
303                                wifiHandle,
304                                requestId,
305                                OUI_QCA,
306                                QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA);
307    if (wifiLoggerCommand == NULL) {
308        ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
309        return WIFI_ERROR_UNKNOWN;
310    }
311    /* Create the NL message. */
312    ret = wifiLoggerCommand->create();
313
314    if (ret < 0)
315        goto cleanup;
316
317    /* Set the interface Id of the message. */
318    ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
319
320    if (ret < 0)
321        goto cleanup;
322
323    /* Add the vendor specific attributes for the NL command. */
324    nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
325
326    if (!nlData)
327        goto cleanup;
328
329    if (wifiLoggerCommand->put_u32(
330                QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID, ring_id))
331    {
332        goto cleanup;
333    }
334    wifiLoggerCommand->attr_end(nlData);
335
336    /* Send the msg and wait for a response. */
337    ret = wifiLoggerCommand->requestResponse();
338    if (ret) {
339        ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
340    }
341
342cleanup:
343    delete wifiLoggerCommand;
344    return (wifi_error)ret;
345}
346
347void WifiLoggerCommand::setVersionInfo(char *buffer, int buffer_size) {
348    mVersion = buffer;
349    mVersionLen = buffer_size;
350}
351
352/*  Function to send enable request to the wifi driver.*/
353wifi_error wifi_get_firmware_version(wifi_interface_handle iface,
354                                     char *buffer, int buffer_size)
355{
356    int requestId, ret = 0;
357    WifiLoggerCommand *wifiLoggerCommand;
358    struct nlattr *nlData;
359    interface_info *ifaceInfo = getIfaceInfo(iface);
360    wifi_handle wifiHandle = getWifiHandle(iface);
361    hal_info *info = getHalInfo(wifiHandle);
362
363    /* No request id from caller, so generate one and pass it on to the driver.
364     * Generate one randomly.
365     */
366    requestId = get_requestid();
367
368    wifiLoggerCommand = new WifiLoggerCommand(
369                                wifiHandle,
370                                requestId,
371                                OUI_QCA,
372                                QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO);
373    if (wifiLoggerCommand == NULL) {
374        ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
375        return WIFI_ERROR_UNKNOWN;
376    }
377    /* Create the NL message. */
378    ret = wifiLoggerCommand->create();
379
380    if (ret < 0)
381        goto cleanup;
382
383    /* Set the interface Id of the message. */
384    ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
385
386    if (ret < 0)
387        goto cleanup;
388
389    /* Add the vendor specific attributes for the NL command. */
390    nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
391
392    if (!nlData)
393        goto cleanup;
394
395    if (wifiLoggerCommand->put_u32(
396                QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION, requestId))
397    {
398        goto cleanup;
399    }
400    wifiLoggerCommand->attr_end(nlData);
401
402    wifiLoggerCommand->setVersionInfo(buffer, buffer_size);
403
404    /* Send the msg and wait for a response. */
405    ret = wifiLoggerCommand->requestResponse();
406    if (ret) {
407        ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
408    }
409cleanup:
410    delete wifiLoggerCommand;
411    return (wifi_error)ret;
412
413}
414
415/*  Function to get wlan driver version.*/
416wifi_error wifi_get_driver_version(wifi_interface_handle iface,
417                                   char *buffer, int buffer_size)
418{
419
420    int requestId, ret = 0;
421    WifiLoggerCommand *wifiLoggerCommand;
422    struct nlattr *nlData;
423    interface_info *ifaceInfo = getIfaceInfo(iface);
424    wifi_handle wifiHandle = getWifiHandle(iface);
425    hal_info *info = getHalInfo(wifiHandle);
426
427    /* No request id from caller, so generate one and pass it on to the driver.
428     * Generate one randomly.
429     */
430    requestId = get_requestid();
431
432    wifiLoggerCommand = new WifiLoggerCommand(
433                            wifiHandle,
434                            requestId,
435                            OUI_QCA,
436                            QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO);
437    if (wifiLoggerCommand == NULL) {
438        ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
439        return WIFI_ERROR_UNKNOWN;
440    }
441    /* Create the NL message. */
442    ret = wifiLoggerCommand->create();
443
444    if (ret < 0)
445        goto cleanup;
446
447    /* Set the interface Id of the message. */
448    ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
449
450    if (ret < 0)
451        goto cleanup;
452
453    /* Add the vendor specific attributes for the NL command. */
454    nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
455
456    if (!nlData)
457        goto cleanup;
458
459    if (wifiLoggerCommand->put_u32(
460            QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION, requestId))
461    {
462        goto cleanup;
463    }
464    wifiLoggerCommand->attr_end(nlData);
465
466    wifiLoggerCommand->setVersionInfo(buffer, buffer_size);
467
468    /* Send the msg and wait for a response. */
469    ret = wifiLoggerCommand->requestResponse();
470    if (ret) {
471        ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
472    }
473cleanup:
474    delete wifiLoggerCommand;
475    return (wifi_error)ret;
476}
477
478
479/* Function to get the Firmware memory dump. */
480wifi_error wifi_get_firmware_memory_dump(wifi_interface_handle iface,
481                                wifi_firmware_memory_dump_handler handler)
482{
483    int requestId, ret = 0;
484    WifiLoggerCommand *wifiLoggerCommand;
485    struct nlattr *nlData;
486    interface_info *ifaceInfo = getIfaceInfo(iface);
487    wifi_handle wifiHandle = getWifiHandle(iface);
488    hal_info *info = getHalInfo(wifiHandle);
489
490    /* No request id from caller, so generate one and pass it on to the driver.
491     * Generate one randomly.
492     */
493    requestId = get_requestid();
494
495    wifiLoggerCommand = new WifiLoggerCommand(
496                            wifiHandle,
497                            requestId,
498                            OUI_QCA,
499                            QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP);
500    if (wifiLoggerCommand == NULL) {
501        ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
502        return WIFI_ERROR_UNKNOWN;
503    }
504    /* Create the NL message. */
505    ret = wifiLoggerCommand->create();
506
507    if (ret < 0)
508        goto cleanup;
509
510    /* Set the interface Id of the message. */
511    ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
512
513    if (ret < 0)
514        goto cleanup;
515
516    /* Add the vendor specific attributes for the NL command. */
517    nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
518
519    if (!nlData)
520        goto cleanup;
521
522    wifiLoggerCommand->attr_end(nlData);
523
524    /* copy the callback into callback handler */
525    WifiLoggerCallbackHandler callbackHandler;
526    memset(&callbackHandler, 0, sizeof(callbackHandler));
527    callbackHandler.on_firmware_memory_dump = \
528        handler.on_firmware_memory_dump;
529
530    ret = wifiLoggerCommand->setCallbackHandler(callbackHandler);
531    if (ret < 0)
532        goto cleanup;
533
534    /* Send the msg and wait for the memory dump response */
535    ret = wifiLoggerCommand->requestResponse();
536    if (ret) {
537        ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
538    }
539
540cleanup:
541    delete wifiLoggerCommand;
542    return (wifi_error)ret;
543}
544
545wifi_error wifi_set_log_handler(wifi_request_id id,
546                                wifi_interface_handle iface,
547                                wifi_ring_buffer_data_handler handler)
548{
549    wifi_handle wifiHandle = getWifiHandle(iface);
550    hal_info *info = getHalInfo(wifiHandle);
551
552    pthread_mutex_lock(&info->lh_lock);
553    info->on_ring_buffer_data = handler.on_ring_buffer_data;
554    pthread_mutex_unlock(&info->lh_lock);
555    if (handler.on_ring_buffer_data == NULL) {
556        ALOGE("Set log handler is NULL");
557        return WIFI_ERROR_UNKNOWN;
558    }
559    return WIFI_SUCCESS;
560}
561
562wifi_error wifi_reset_log_handler(wifi_request_id id,
563                                  wifi_interface_handle iface)
564{
565    wifi_handle wifiHandle = getWifiHandle(iface);
566    hal_info *info = getHalInfo(wifiHandle);
567
568    pthread_mutex_lock(&info->lh_lock);
569    info->on_ring_buffer_data = NULL;
570    pthread_mutex_unlock(&info->lh_lock);
571    return WIFI_SUCCESS;
572}
573
574wifi_error wifi_set_alert_handler(wifi_request_id id,
575                                  wifi_interface_handle iface,
576                                  wifi_alert_handler handler)
577{
578    wifi_handle wifiHandle = getWifiHandle(iface);
579    hal_info *info = getHalInfo(wifiHandle);
580
581    if (handler.on_alert == NULL) {
582        ALOGE("Set alert handler is NULL");
583        return WIFI_ERROR_UNKNOWN;
584    }
585    pthread_mutex_lock(&info->ah_lock);
586    info->on_alert = handler.on_alert;
587    pthread_mutex_unlock(&info->ah_lock);
588    return WIFI_SUCCESS;
589}
590
591wifi_error wifi_reset_alert_handler(wifi_request_id id,
592                                    wifi_interface_handle iface)
593{
594    wifi_handle wifiHandle = getWifiHandle(iface);
595    hal_info *info = getHalInfo(wifiHandle);
596
597    pthread_mutex_lock(&info->ah_lock);
598    info->on_alert = NULL;
599    pthread_mutex_unlock(&info->ah_lock);
600    return WIFI_SUCCESS;
601}
602
603
604/**
605    API to start packet fate monitoring.
606    - Once stared, monitoring should remain active until HAL is unloaded.
607    - When HAL is unloaded, all packet fate buffers should be cleared.
608*/
609wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle iface)
610{
611    wifi_handle wifiHandle = getWifiHandle(iface);
612    hal_info *info = getHalInfo(wifiHandle);
613
614    if (info->fate_monitoring_enabled == true) {
615        ALOGV("Packet monitoring is already enabled");
616        return WIFI_SUCCESS;
617    }
618
619    info->pkt_fate_stats = (packet_fate_monitor_info *) malloc (
620                                              sizeof(packet_fate_monitor_info));
621    if (info->pkt_fate_stats == NULL) {
622        ALOGE("Failed to allocate memory for : %zu bytes",
623              sizeof(packet_fate_monitor_info));
624        return WIFI_ERROR_OUT_OF_MEMORY;
625    }
626    memset(info->pkt_fate_stats, 0, sizeof(packet_fate_monitor_info));
627
628    pthread_mutex_lock(&info->pkt_fate_stats_lock);
629    info->fate_monitoring_enabled = true;
630    pthread_mutex_unlock(&info->pkt_fate_stats_lock);
631
632    return WIFI_SUCCESS;
633}
634
635
636/**
637    API to retrieve fates of outbound packets.
638    - HAL implementation should fill |tx_report_bufs| with fates of
639      _first_ min(n_requested_fates, actual packets) frames
640      transmitted for the most recent association. The fate reports
641      should follow the same order as their respective packets.
642    - Packets reported by firmware, but not recognized by driver
643      should be included.  However, the ordering of the corresponding
644      reports is at the discretion of HAL implementation.
645    - Framework may call this API multiple times for the same association.
646    - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|.
647    - Framework will allocate and free the referenced storage.
648*/
649wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle iface,
650                                 wifi_tx_report *tx_report_bufs,
651                                 size_t n_requested_fates,
652                                 size_t *n_provided_fates)
653{
654    wifi_handle wifiHandle = getWifiHandle(iface);
655    hal_info *info = getHalInfo(wifiHandle);
656    wifi_tx_report_i *tx_fate_stats;
657    size_t i;
658
659    if (info->fate_monitoring_enabled != true) {
660        ALOGE("Packet monitoring is not yet triggered");
661        return WIFI_ERROR_UNINITIALIZED;
662    }
663    pthread_mutex_lock(&info->pkt_fate_stats_lock);
664
665    tx_fate_stats = &info->pkt_fate_stats->tx_fate_stats[0];
666
667    *n_provided_fates = min(n_requested_fates,
668                            info->pkt_fate_stats->n_tx_stats_collected);
669
670    for (i=0; i < *n_provided_fates; i++) {
671        memcpy(tx_report_bufs[i].md5_prefix,
672                    tx_fate_stats[i].md5_prefix, MD5_PREFIX_LEN);
673        tx_report_bufs[i].fate = tx_fate_stats[i].fate;
674        tx_report_bufs[i].frame_inf.payload_type =
675            tx_fate_stats[i].frame_inf.payload_type;
676        tx_report_bufs[i].frame_inf.driver_timestamp_usec =
677            tx_fate_stats[i].frame_inf.driver_timestamp_usec;
678        tx_report_bufs[i].frame_inf.firmware_timestamp_usec =
679            tx_fate_stats[i].frame_inf.firmware_timestamp_usec;
680        tx_report_bufs[i].frame_inf.frame_len =
681            tx_fate_stats[i].frame_inf.frame_len;
682
683        if (tx_report_bufs[i].frame_inf.payload_type == FRAME_TYPE_ETHERNET_II)
684            memcpy(tx_report_bufs[i].frame_inf.frame_content.ethernet_ii_bytes,
685                   tx_fate_stats[i].frame_inf.frame_content,
686                   min(tx_fate_stats[i].frame_inf.frame_len,
687                       MAX_FRAME_LEN_ETHERNET));
688        else if (tx_report_bufs[i].frame_inf.payload_type ==
689                                                         FRAME_TYPE_80211_MGMT)
690            memcpy(
691                tx_report_bufs[i].frame_inf.frame_content.ieee_80211_mgmt_bytes,
692                tx_fate_stats[i].frame_inf.frame_content,
693                min(tx_fate_stats[i].frame_inf.frame_len,
694                    MAX_FRAME_LEN_80211_MGMT));
695        else
696            /* Currently framework is interested only two types(
697             * FRAME_TYPE_ETHERNET_II and FRAME_TYPE_80211_MGMT) of packets, so
698             * ignore the all other types of packets received from driver */
699            ALOGI("Unknown format packet");
700    }
701    pthread_mutex_unlock(&info->pkt_fate_stats_lock);
702
703    return WIFI_SUCCESS;
704}
705
706/**
707    API to retrieve fates of inbound packets.
708    - HAL implementation should fill |rx_report_bufs| with fates of
709      _first_ min(n_requested_fates, actual packets) frames
710      received for the most recent association. The fate reports
711      should follow the same order as their respective packets.
712    - Packets reported by firmware, but not recognized by driver
713      should be included.  However, the ordering of the corresponding
714      reports is at the discretion of HAL implementation.
715    - Framework may call this API multiple times for the same association.
716    - Framework will ensure |n_requested_fates <= MAX_FATE_LOG_LEN|.
717    - Framework will allocate and free the referenced storage.
718*/
719wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle iface,
720                                 wifi_rx_report *rx_report_bufs,
721                                 size_t n_requested_fates,
722                                 size_t *n_provided_fates)
723{
724    wifi_handle wifiHandle = getWifiHandle(iface);
725    hal_info *info = getHalInfo(wifiHandle);
726    wifi_rx_report_i *rx_fate_stats;
727    size_t i;
728
729    if (info->fate_monitoring_enabled != true) {
730        ALOGE("Packet monitoring is not yet triggered");
731        return WIFI_ERROR_UNINITIALIZED;
732    }
733    pthread_mutex_lock(&info->pkt_fate_stats_lock);
734
735    rx_fate_stats = &info->pkt_fate_stats->rx_fate_stats[0];
736
737    *n_provided_fates = min(n_requested_fates,
738                            info->pkt_fate_stats->n_rx_stats_collected);
739
740    for (i=0; i < *n_provided_fates; i++) {
741        memcpy(rx_report_bufs[i].md5_prefix,
742                    rx_fate_stats[i].md5_prefix, MD5_PREFIX_LEN);
743        rx_report_bufs[i].fate = rx_fate_stats[i].fate;
744        rx_report_bufs[i].frame_inf.payload_type =
745            rx_fate_stats[i].frame_inf.payload_type;
746        rx_report_bufs[i].frame_inf.driver_timestamp_usec =
747            rx_fate_stats[i].frame_inf.driver_timestamp_usec;
748        rx_report_bufs[i].frame_inf.firmware_timestamp_usec =
749            rx_fate_stats[i].frame_inf.firmware_timestamp_usec;
750        rx_report_bufs[i].frame_inf.frame_len =
751            rx_fate_stats[i].frame_inf.frame_len;
752
753        if (rx_report_bufs[i].frame_inf.payload_type == FRAME_TYPE_ETHERNET_II)
754            memcpy(rx_report_bufs[i].frame_inf.frame_content.ethernet_ii_bytes,
755                   rx_fate_stats[i].frame_inf.frame_content,
756                   min(rx_fate_stats[i].frame_inf.frame_len,
757                   MAX_FRAME_LEN_ETHERNET));
758        else if (rx_report_bufs[i].frame_inf.payload_type ==
759                                                         FRAME_TYPE_80211_MGMT)
760            memcpy(
761                rx_report_bufs[i].frame_inf.frame_content.ieee_80211_mgmt_bytes,
762                rx_fate_stats[i].frame_inf.frame_content,
763                min(rx_fate_stats[i].frame_inf.frame_len,
764                    MAX_FRAME_LEN_80211_MGMT));
765        else
766            /* Currently framework is interested only two types(
767             * FRAME_TYPE_ETHERNET_II and FRAME_TYPE_80211_MGMT) of packets, so
768             * ignore the all other types of packets received from driver */
769            ALOGI("Unknown format packet");
770    }
771    pthread_mutex_unlock(&info->pkt_fate_stats_lock);
772
773    return WIFI_SUCCESS;
774}
775
776WifiLoggerCommand::WifiLoggerCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
777        : WifiVendorCommand(handle, id, vendor_id, subcmd)
778{
779    mVersion = NULL;
780    mVersionLen = 0;
781    mRequestId = id;
782    memset(&mHandler, 0,sizeof(mHandler));
783    mWaitforRsp = false;
784    mMoreData = false;
785    mSupportedSet = NULL;
786}
787
788WifiLoggerCommand::~WifiLoggerCommand()
789{
790    unregisterVendorHandler(mVendor_id, mSubcmd);
791}
792
793/* This function implements creation of Vendor command */
794int WifiLoggerCommand::create() {
795    int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
796    if (ret < 0) {
797        return ret;
798    }
799
800    /* Insert the oui in the msg */
801    ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
802    if (ret < 0)
803        goto out;
804    /* Insert the subcmd in the msg */
805    ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
806    if (ret < 0)
807        goto out;
808
809     ALOGV("%s: mVendor_id = %d, Subcmd = %d.",
810        __FUNCTION__, mVendor_id, mSubcmd);
811
812out:
813    return ret;
814}
815
816void rb_timerhandler(hal_info *info)
817{
818   struct timeval now;
819   int rb_id;
820
821   gettimeofday(&now,NULL);
822   for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
823       rb_check_for_timeout(&info->rb_infos[rb_id], &now);
824   }
825}
826
827wifi_error wifi_logger_ring_buffers_init(hal_info *info)
828{
829    wifi_error ret;
830
831    ret = rb_init(info, &info->rb_infos[POWER_EVENTS_RB_ID],
832                  POWER_EVENTS_RB_ID,
833                  POWER_EVENTS_RB_BUF_SIZE,
834                  POWER_EVENTS_NUM_BUFS,
835                  power_events_ring_name);
836    if (ret != WIFI_SUCCESS) {
837        ALOGE("Failed to initialize power events ring buffer");
838        goto cleanup;
839    }
840
841    ret = rb_init(info, &info->rb_infos[CONNECTIVITY_EVENTS_RB_ID],
842                  CONNECTIVITY_EVENTS_RB_ID,
843                  CONNECTIVITY_EVENTS_RB_BUF_SIZE,
844                  CONNECTIVITY_EVENTS_NUM_BUFS,
845                  connectivity_events_ring_name);
846    if (ret != WIFI_SUCCESS) {
847        ALOGE("Failed to initialize connectivity events ring buffer");
848        goto cleanup;
849    }
850
851    ret = rb_init(info, &info->rb_infos[PKT_STATS_RB_ID],
852                  PKT_STATS_RB_ID,
853                  PKT_STATS_RB_BUF_SIZE,
854                  PKT_STATS_NUM_BUFS,
855                  pkt_stats_ring_name);
856    if (ret != WIFI_SUCCESS) {
857        ALOGE("Failed to initialize per packet stats ring buffer");
858        goto cleanup;
859    }
860
861    ret = rb_init(info, &info->rb_infos[DRIVER_PRINTS_RB_ID],
862                  DRIVER_PRINTS_RB_ID,
863                  DRIVER_PRINTS_RB_BUF_SIZE,
864                  DRIVER_PRINTS_NUM_BUFS,
865                  driver_prints_ring_name);
866    if (ret != WIFI_SUCCESS) {
867        ALOGE("Failed to initialize driver prints ring buffer");
868        goto cleanup;
869    }
870
871    ret = rb_init(info, &info->rb_infos[FIRMWARE_PRINTS_RB_ID],
872                  FIRMWARE_PRINTS_RB_ID,
873                  FIRMWARE_PRINTS_RB_BUF_SIZE,
874                  FIRMWARE_PRINTS_NUM_BUFS,
875                  firmware_prints_ring_name);
876    if (ret != WIFI_SUCCESS) {
877        ALOGE("Failed to initialize firmware prints ring buffer");
878        goto cleanup;
879    }
880
881    pthread_mutex_init(&info->lh_lock, NULL);
882    pthread_mutex_init(&info->ah_lock, NULL);
883
884    return ret;
885
886cleanup:
887    wifi_logger_ring_buffers_deinit(info);
888    return ret;
889}
890
891void wifi_logger_ring_buffers_deinit(hal_info *info)
892{
893    int i;
894
895    for (i = 0; i < NUM_RING_BUFS; i++) {
896        rb_deinit(&info->rb_infos[i]);
897    }
898    pthread_mutex_destroy(&info->lh_lock);
899    pthread_mutex_destroy(&info->ah_lock);
900}
901
902
903/* Callback handlers registered for nl message send */
904static int error_handler_wifi_logger(struct sockaddr_nl *nla,
905                                     struct nlmsgerr *err,
906                                     void *arg)
907{
908    struct sockaddr_nl *tmp;
909    int *ret = (int *)arg;
910    tmp = nla;
911    *ret = err->error;
912    ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret)));
913    return NL_STOP;
914}
915
916/* Callback handlers registered for nl message send */
917static int ack_handler_wifi_logger(struct nl_msg *msg, void *arg)
918{
919    int *ret = (int *)arg;
920    struct nl_msg * a;
921
922    a = msg;
923    *ret = 0;
924    return NL_STOP;
925}
926
927/* Callback handlers registered for nl message send */
928static int finish_handler_wifi_logger(struct nl_msg *msg, void *arg)
929{
930  int *ret = (int *)arg;
931  struct nl_msg * a;
932
933  a = msg;
934  *ret = 0;
935  return NL_SKIP;
936}
937
938int WifiLoggerCommand::requestEvent()
939{
940    int res = -1;
941    struct nl_cb *cb;
942
943    cb = nl_cb_alloc(NL_CB_DEFAULT);
944    if (!cb) {
945        ALOGE("%s: Callback allocation failed",__FUNCTION__);
946        res = -1;
947        goto out;
948    }
949
950    /* Send message */
951    res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
952    if (res < 0)
953        goto out;
954    res = 1;
955
956    nl_cb_err(cb, NL_CB_CUSTOM, error_handler_wifi_logger, &res);
957    nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_wifi_logger, &res);
958    nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_wifi_logger, &res);
959
960    /* Err is populated as part of finish_handler. */
961    while (res > 0){
962         nl_recvmsgs(mInfo->cmd_sock, cb);
963    }
964
965    ALOGV("%s: Msg sent, res=%d, mWaitForRsp=%d", __FUNCTION__, res, mWaitforRsp);
966    /* Only wait for the asynchronous event if HDD returns success, res=0 */
967    if (!res && (mWaitforRsp == true)) {
968        struct timespec abstime;
969        abstime.tv_sec = 4;
970        abstime.tv_nsec = 0;
971        res = mCondition.wait(abstime);
972        if (res == ETIMEDOUT)
973        {
974            ALOGE("%s: Time out happened.", __FUNCTION__);
975        }
976        ALOGV("%s: Command invoked return value:%d, mWaitForRsp=%d",
977            __FUNCTION__, res, mWaitforRsp);
978    }
979out:
980    /* Cleanup the mMsg */
981    mMsg.destroy();
982    return res;
983}
984
985int WifiLoggerCommand::requestResponse()
986{
987    return WifiCommand::requestResponse(mMsg);
988}
989
990int WifiLoggerCommand::handleResponse(WifiEvent &reply) {
991    u32 status;
992    int ret = WIFI_SUCCESS;
993    int i = 0;
994    int len = 0, version;
995    char version_type[20];
996    char* memBuffer = NULL;
997    FILE* memDumpFilePtr = NULL;
998    WifiVendorCommand::handleResponse(reply);
999
1000    memset(version_type, 0, 20);
1001    switch(mSubcmd)
1002    {
1003        case QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO:
1004        {
1005            struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
1006
1007            nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
1008                            (struct nlattr *)mVendorData, mDataLen, NULL);
1009
1010            if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
1011                len = nla_len(tb_vendor[
1012                        QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]);
1013                memcpy(version_type, "Driver", strlen("Driver"));
1014                version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION;
1015            } else if (
1016                tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
1017                len = nla_len(
1018                        tb_vendor[
1019                        QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]);
1020                memcpy(version_type, "Firmware", strlen("Firmware"));
1021                version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION;
1022            }
1023            if (len && mVersion && mVersionLen) {
1024                memset(mVersion, 0, mVersionLen);
1025                /* if len is greater than the incoming length then
1026                   accommodate 1 lesser than mVersionLen to have the
1027                   string terminated with '\0' */
1028                len = (len > mVersionLen)? (mVersionLen - 1) : len;
1029                memcpy(mVersion, nla_data(tb_vendor[version]), len);
1030                ALOGV("%s: WLAN %s version : %s ", __FUNCTION__,
1031                      version_type, mVersion);
1032            }
1033        }
1034        break;
1035        case QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET:
1036        {
1037            struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
1038
1039            nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
1040                            (struct nlattr *)mVendorData, mDataLen, NULL);
1041
1042            if (tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]) {
1043                *mSupportedSet =
1044                nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
1045#ifdef QC_HAL_DEBUG
1046                ALOGV("%s: Supported Feature Set : val 0x%x",
1047                      __FUNCTION__, *mSupportedSet);
1048#endif
1049            }
1050        }
1051        break;
1052
1053        case QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP:
1054        {
1055            int id = 0;
1056            u32 memDumpSize = 0;
1057            int numRecordsRead = 0;
1058            u32 remaining = 0;
1059            char* buffer = NULL;
1060            struct nlattr *tbVendor[
1061                QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX + 1];
1062
1063            nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX,
1064                    (struct nlattr *)mVendorData,
1065                    mDataLen, NULL);
1066
1067            if (!tbVendor[
1068                QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE]) {
1069                ALOGE("%s: LOGGER_RESULTS_MEMDUMP_SIZE not"
1070                      "found", __FUNCTION__);
1071                break;
1072            }
1073
1074            memDumpSize = nla_get_u32(
1075                tbVendor[QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE]
1076                );
1077
1078            /* Allocate the memory indicated in memDumpSize */
1079            memBuffer = (char*) malloc(sizeof(char) * memDumpSize);
1080            if (memBuffer == NULL) {
1081                ALOGE("%s: No Memory for allocating Buffer ",
1082                      "size of %d", __func__, memDumpSize);
1083                break;
1084            }
1085            memset(memBuffer, 0, sizeof(char) * memDumpSize);
1086
1087            ALOGI("%s: Memory Dump size: %u", __func__,
1088                  memDumpSize);
1089
1090            /* Open the proc or debugfs filesystem */
1091            memDumpFilePtr = fopen(LOGGER_MEMDUMP_FILENAME, "r");
1092            if (memDumpFilePtr == NULL) {
1093                ALOGE("Failed to open %s file", LOGGER_MEMDUMP_FILENAME);
1094                break;
1095            }
1096
1097            /* Read the memDumpSize value at once */
1098            numRecordsRead = fread(memBuffer, 1, memDumpSize,
1099                                   memDumpFilePtr);
1100            if (numRecordsRead <= 0 ||
1101                numRecordsRead != (int) memDumpSize) {
1102                ALOGE("%s: Read %d failed for reading at once.",
1103                      __func__, numRecordsRead);
1104                /* Lets try to read in chunks */
1105                rewind(memDumpFilePtr);
1106                remaining = memDumpSize;
1107                buffer = memBuffer;
1108                while (remaining) {
1109                    u32 readSize = 0;
1110                    if (remaining >= LOGGER_MEMDUMP_CHUNKSIZE) {
1111                        readSize = LOGGER_MEMDUMP_CHUNKSIZE;
1112                    }
1113                    else {
1114                        readSize = remaining;
1115                    }
1116                    numRecordsRead = fread(buffer, 1,
1117                                           readSize, memDumpFilePtr);
1118                    if (numRecordsRead) {
1119                        remaining -= readSize;
1120                        buffer += readSize;
1121                        ALOGV("%s: Read successful for size:%u "
1122                              "remaining:%u", __func__, readSize,
1123                              remaining);
1124                    }
1125                    else {
1126                        ALOGE("%s: Chunk read failed for size:%u",
1127                              __func__, readSize);
1128                        break;
1129                    }
1130                }
1131            }
1132
1133            /* After successful read, call the callback handler*/
1134            if (mHandler.on_firmware_memory_dump) {
1135                mHandler.on_firmware_memory_dump(memBuffer,
1136                                                 memDumpSize);
1137
1138            }
1139        }
1140        break;
1141        case QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS:
1142        {
1143            struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_MAX +1];
1144
1145            /* parse and extract wake reason stats */
1146            nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_WAKE_STATS_MAX,
1147                      (struct nlattr *)mVendorData,
1148                      mDataLen, NULL);
1149
1150            if (!tbVendor[
1151                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE]) {
1152                ALOGE("%s: TOTAL_CMD_EVENT_WAKE not found", __FUNCTION__);
1153                break;
1154            }
1155            mGetWakeStats->total_cmd_event_wake = nla_get_u32(
1156                tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE]);
1157
1158            if (mGetWakeStats->total_cmd_event_wake &&
1159                    mGetWakeStats->cmd_event_wake_cnt) {
1160                if (!tbVendor[
1161                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR]) {
1162                    ALOGE("%s: CMD_EVENT_WAKE_CNT_PTR not found", __FUNCTION__);
1163                    break;
1164                }
1165                len = nla_len(tbVendor[
1166                        QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR]);
1167                mGetWakeStats->cmd_event_wake_cnt_used =
1168                        (len < mGetWakeStats->cmd_event_wake_cnt_sz) ? len :
1169                                    mGetWakeStats->cmd_event_wake_cnt_sz;
1170                memcpy(mGetWakeStats->cmd_event_wake_cnt,
1171                    nla_data(tbVendor[
1172                        QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR]),
1173                    (mGetWakeStats->cmd_event_wake_cnt_used * sizeof(int)));
1174            } else
1175                mGetWakeStats->cmd_event_wake_cnt_used = 0;
1176
1177            if (!tbVendor[
1178                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE])
1179            {
1180                ALOGE("%s: TOTAL_DRIVER_FW_LOCAL_WAKE not found", __FUNCTION__);
1181                break;
1182            }
1183            mGetWakeStats->total_driver_fw_local_wake = nla_get_u32(tbVendor[
1184                QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE]);
1185
1186            if (mGetWakeStats->total_driver_fw_local_wake &&
1187                    mGetWakeStats->driver_fw_local_wake_cnt) {
1188                if (!tbVendor[
1189                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR])
1190                {
1191                    ALOGE("%s: DRIVER_FW_LOCAL_WAKE_CNT_PTR not found",
1192                        __FUNCTION__);
1193                    break;
1194                }
1195                len = nla_len(tbVendor[
1196                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR]);
1197                mGetWakeStats->driver_fw_local_wake_cnt_used =
1198                    (len < mGetWakeStats->driver_fw_local_wake_cnt_sz) ? len :
1199                                    mGetWakeStats->driver_fw_local_wake_cnt_sz;
1200
1201                memcpy(mGetWakeStats->driver_fw_local_wake_cnt,
1202                    nla_data(tbVendor[
1203                        QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR]),
1204                    (mGetWakeStats->driver_fw_local_wake_cnt_used * sizeof(int)));
1205            } else
1206                mGetWakeStats->driver_fw_local_wake_cnt_used = 0;
1207
1208            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE]) {
1209                ALOGE("%s: TOTAL_RX_DATA_WAKE not found", __FUNCTION__);
1210                break;
1211            }
1212            mGetWakeStats->total_rx_data_wake = nla_get_u32(tbVendor[
1213                        QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE]);
1214
1215            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT]) {
1216                ALOGE("%s: RX_UNICAST_CNT not found", __FUNCTION__);
1217                break;
1218            }
1219            mGetWakeStats->rx_wake_details.rx_unicast_cnt = nla_get_u32(
1220                    tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT]);
1221
1222            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT]) {
1223                ALOGE("%s: RX_MULTICAST_CNT not found", __FUNCTION__);
1224                break;
1225            }
1226            mGetWakeStats->rx_wake_details.rx_multicast_cnt = nla_get_u32(
1227                    tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT]);
1228
1229            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT]) {
1230                ALOGE("%s: RX_BROADCAST_CNT not found", __FUNCTION__);
1231                break;
1232            }
1233            mGetWakeStats->rx_wake_details.rx_broadcast_cnt = nla_get_u32(
1234                    tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT]);
1235
1236            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT]) {
1237                ALOGE("%s: ICMP_PKT not found", __FUNCTION__);
1238                break;
1239            }
1240            mGetWakeStats->rx_wake_pkt_classification_info.icmp_pkt =
1241                nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT]);
1242
1243            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT]) {
1244                ALOGE("%s: ICMP6_PKT not found", __FUNCTION__);
1245                break;
1246            }
1247            mGetWakeStats->rx_wake_pkt_classification_info.icmp6_pkt =
1248                nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT]);
1249
1250            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA]) {
1251                ALOGE("%s: ICMP6_RA not found", __FUNCTION__);
1252                break;
1253            }
1254            mGetWakeStats->rx_wake_pkt_classification_info.icmp6_ra =
1255                nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA]);
1256
1257            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA]) {
1258                ALOGE("%s: ICMP6_NA not found", __FUNCTION__);
1259                break;
1260            }
1261            mGetWakeStats->rx_wake_pkt_classification_info.icmp6_na =
1262                nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA]);
1263
1264            if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS]) {
1265                ALOGE("%s: ICMP6_NS not found", __FUNCTION__);
1266                break;
1267            }
1268            mGetWakeStats->rx_wake_pkt_classification_info.icmp6_ns =
1269                nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS]);
1270
1271            if (!tbVendor[
1272                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT]) {
1273                ALOGE("%s: ICMP4_RX_MULTICAST_CNT not found", __FUNCTION__);
1274                break;
1275            }
1276            mGetWakeStats->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt =
1277                nla_get_u32(tbVendor[
1278                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT]);
1279
1280            if (!tbVendor[
1281                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT]) {
1282                ALOGE("%s: ICMP6_RX_MULTICAST_CNT not found", __FUNCTION__);
1283                break;
1284            }
1285            mGetWakeStats->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
1286                nla_get_u32(tbVendor[
1287                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT]);
1288
1289            if (!tbVendor[
1290                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT]) {
1291                ALOGE("%s: OTHER_RX_MULTICAST_CNT not found", __FUNCTION__);
1292                break;
1293            }
1294            mGetWakeStats->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
1295                nla_get_u32(tbVendor[
1296                    QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT]);
1297
1298        }
1299        break;
1300
1301        default :
1302            ALOGE("%s: Wrong Wifi Logger subcmd response received %d",
1303                __FUNCTION__, mSubcmd);
1304    }
1305
1306    /* free the allocated memory */
1307    if (memBuffer) {
1308        free(memBuffer);
1309    }
1310    if (memDumpFilePtr) {
1311        fclose(memDumpFilePtr);
1312    }
1313    return NL_SKIP;
1314}
1315
1316/* This function will be the main handler for incoming (from driver)
1317 * WIFI_LOGGER_SUBCMD.
1318 * Calls the appropriate callback handler after parsing the vendor data.
1319 */
1320int WifiLoggerCommand::handleEvent(WifiEvent &event)
1321{
1322    WifiVendorCommand::handleEvent(event);
1323
1324    switch(mSubcmd)
1325    {
1326       default:
1327           /* Error case should not happen print log */
1328           ALOGE("%s: Wrong subcmd received %d", __func__, mSubcmd);
1329           break;
1330    }
1331
1332cleanup:
1333    return NL_SKIP;
1334}
1335
1336int WifiLoggerCommand::setCallbackHandler(WifiLoggerCallbackHandler nHandler)
1337{
1338    int res = 0;
1339    mHandler = nHandler;
1340    res = registerVendorHandler(mVendor_id, mSubcmd);
1341    if (res != 0) {
1342        ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
1343              __FUNCTION__, mVendor_id, mSubcmd);
1344    }
1345    return res;
1346}
1347
1348void WifiLoggerCommand::unregisterHandler(u32 subCmd)
1349{
1350    unregisterVendorHandler(mVendor_id, subCmd);
1351}
1352
1353int WifiLoggerCommand::timed_wait(u16 wait_time)
1354{
1355    struct timespec absTime;
1356    int res;
1357    absTime.tv_sec = wait_time;
1358    absTime.tv_nsec = 0;
1359    return mCondition.wait(absTime);
1360}
1361
1362void WifiLoggerCommand::waitForRsp(bool wait)
1363{
1364    mWaitforRsp = wait;
1365}
1366
1367/* Function to get Driver memory dump */
1368wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface,
1369                                    wifi_driver_memory_dump_callbacks callback)
1370{
1371    FILE *fp;
1372    size_t fileSize, remaining, readSize;
1373    size_t numRecordsRead;
1374    char *memBuffer = NULL, *buffer = NULL;
1375
1376    /* Open File */
1377    fp = fopen(DRIVER_MEMDUMP_FILENAME, "r");
1378    if (fp == NULL) {
1379        ALOGE("Failed to open %s file", DRIVER_MEMDUMP_FILENAME);
1380        return WIFI_ERROR_UNKNOWN;
1381    }
1382
1383    memBuffer = (char *) malloc(DRIVER_MEMDUMP_MAX_FILESIZE);
1384    if (memBuffer == NULL) {
1385        ALOGE("%s: malloc failed for size %d", __FUNCTION__,
1386                    DRIVER_MEMDUMP_MAX_FILESIZE);
1387        fclose(fp);
1388        return WIFI_ERROR_OUT_OF_MEMORY;
1389    }
1390
1391    /* Read the DRIVER_MEMDUMP_MAX_FILESIZE value at once */
1392    numRecordsRead = fread(memBuffer, 1, DRIVER_MEMDUMP_MAX_FILESIZE, fp);
1393    if (feof(fp))
1394        fileSize = numRecordsRead;
1395    else if (numRecordsRead == DRIVER_MEMDUMP_MAX_FILESIZE) {
1396        ALOGE("%s: Reading only first %zu bytes from file", __FUNCTION__,
1397                numRecordsRead);
1398        fileSize = numRecordsRead;
1399    } else {
1400        ALOGE("%s: Read failed for reading at once, ret: %zu. Trying to read in"
1401                "chunks", __FUNCTION__, numRecordsRead);
1402        /* Lets try to read in chunks */
1403        rewind(fp);
1404        remaining = DRIVER_MEMDUMP_MAX_FILESIZE;
1405        buffer = memBuffer;
1406        fileSize = 0;
1407        while (remaining) {
1408            readSize = 0;
1409            if (remaining >= LOGGER_MEMDUMP_CHUNKSIZE)
1410                readSize = LOGGER_MEMDUMP_CHUNKSIZE;
1411            else
1412                readSize = remaining;
1413
1414            numRecordsRead = fread(buffer, 1, readSize, fp);
1415            fileSize += numRecordsRead;
1416            if (feof(fp))
1417                break;
1418            else if (numRecordsRead == readSize) {
1419                remaining -= readSize;
1420                buffer += readSize;
1421                ALOGV("%s: Read successful for size:%zu remaining:%zu",
1422                         __FUNCTION__, readSize, remaining);
1423            } else {
1424                ALOGE("%s: Chunk read failed for size:%zu", __FUNCTION__,
1425                        readSize);
1426                free(memBuffer);
1427                memBuffer = NULL;
1428                fclose(fp);
1429                return WIFI_ERROR_UNKNOWN;
1430            }
1431        }
1432    }
1433    ALOGV("%s filename: %s fileSize: %zu", __FUNCTION__, DRIVER_MEMDUMP_FILENAME,
1434            fileSize);
1435    /* After successful read, call the callback function*/
1436    callback.on_driver_memory_dump(memBuffer, fileSize);
1437
1438    /* free the allocated memory */
1439    free(memBuffer);
1440    fclose(fp);
1441    return WIFI_SUCCESS;
1442}
1443
1444/* Function to get wake lock stats */
1445wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
1446                             WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1447{
1448    int requestId, ret = WIFI_SUCCESS;
1449    WifiLoggerCommand *wifiLoggerCommand;
1450    struct nlattr *nlData;
1451    interface_info *ifaceInfo = getIfaceInfo(iface);
1452    wifi_handle wifiHandle = getWifiHandle(iface);
1453
1454    /* No request id from caller, so generate one and pass it on to the driver.
1455     * Generate it randomly.
1456     */
1457    requestId = get_requestid();
1458
1459    if (!wifi_wake_reason_cnt) {
1460        ALOGE("%s: Invalid buffer provided. Exit.",
1461            __FUNCTION__);
1462        return WIFI_ERROR_INVALID_ARGS;
1463    }
1464
1465    wifiLoggerCommand = new WifiLoggerCommand(
1466                                wifiHandle,
1467                                requestId,
1468                                OUI_QCA,
1469                                QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS);
1470    if (wifiLoggerCommand == NULL) {
1471        ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
1472        return WIFI_ERROR_UNKNOWN;
1473    }
1474
1475    /* Create the NL message. */
1476    ret = wifiLoggerCommand->create();
1477    if (ret < 0)
1478        goto cleanup;
1479
1480    /* Set the interface Id of the message. */
1481    ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
1482    if (ret < 0)
1483        goto cleanup;
1484
1485    wifiLoggerCommand->getWakeStatsRspParams(wifi_wake_reason_cnt);
1486
1487    /* Add the vendor specific attributes for the NL command. */
1488    nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1489    if (!nlData)
1490        goto cleanup;
1491
1492    if (wifiLoggerCommand->put_u32(
1493                QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ,
1494                wifi_wake_reason_cnt->cmd_event_wake_cnt_sz))
1495    {
1496        goto cleanup;
1497    }
1498
1499    if (wifiLoggerCommand->put_u32(
1500                QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ,
1501                wifi_wake_reason_cnt->driver_fw_local_wake_cnt_sz))
1502    {
1503        goto cleanup;
1504    }
1505    wifiLoggerCommand->attr_end(nlData);
1506
1507    /* Send the msg and wait for a response. */
1508    ret = wifiLoggerCommand->requestResponse();
1509    if (ret) {
1510        ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
1511    }
1512
1513cleanup:
1514    delete wifiLoggerCommand;
1515    return (wifi_error)ret;
1516}
1517
1518void WifiLoggerCommand::getWakeStatsRspParams(
1519                            WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1520{
1521    mGetWakeStats = wifi_wake_reason_cnt;
1522}
1523