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