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 
45 char power_events_ring_name[] = "power_events_rb";
46 char connectivity_events_ring_name[] = "connectivity_events_rb";
47 char pkt_stats_ring_name[] = "pkt_stats_rb";
48 char driver_prints_ring_name[] = "driver_prints_rb";
49 char firmware_prints_ring_name[] = "firmware_prints_rb";
50 
get_ring_id(hal_info * info,char * ring_name)51 static 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 */
wifi_start_logging(wifi_interface_handle iface,u32 verbose_level,u32 flags,u32 max_interval_sec,u32 min_data_size,char * buffer_name)66 wifi_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);
153 cleanup:
154     if (wifiLoggerCommand)
155         delete wifiLoggerCommand;
156     return (wifi_error)ret;
157 
158 }
159 
160 /*  Function to get each ring related info */
wifi_get_ring_buffers_status(wifi_interface_handle iface,u32 * num_buffers,wifi_ring_buffer_status * status)161 wifi_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 (wifi_error)ret;
187 }
188 
push_out_all_ring_buffers(hal_info * info)189 void 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 
send_alert(hal_info * info,int reason_code)198 void 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 
setFeatureSet(u32 * support)211 void WifiLoggerCommand::setFeatureSet(u32 *support) {
212     mSupportedSet = support;
213 }
214 
215 /*  Function to get the supported feature set for logging.*/
wifi_get_logger_supported_feature_set(wifi_interface_handle iface,u32 * support)216 wifi_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 
274 cleanup:
275     delete wifiLoggerCommand;
276     return (wifi_error)ret;
277 }
278 
279 /*  Function to get the data in each ring for the given ring ID.*/
wifi_get_ring_data(wifi_interface_handle iface,char * ring_name)280 wifi_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 
340 cleanup:
341     delete wifiLoggerCommand;
342     return (wifi_error)ret;
343 }
344 
setVersionInfo(char * buffer,int buffer_size)345 void 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.*/
wifi_get_firmware_version(wifi_interface_handle iface,char * buffer,int buffer_size)351 wifi_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     }
406 cleanup:
407     delete wifiLoggerCommand;
408     return (wifi_error)ret;
409 
410 }
411 
412 /*  Function to get wlan driver version.*/
wifi_get_driver_version(wifi_interface_handle iface,char * buffer,int buffer_size)413 wifi_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     }
469 cleanup:
470     delete wifiLoggerCommand;
471     return (wifi_error)ret;
472 }
473 
474 
475 /* Function to get the Firmware memory dump. */
wifi_get_firmware_memory_dump(wifi_interface_handle iface,wifi_firmware_memory_dump_handler handler)476 wifi_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 
535 cleanup:
536     delete wifiLoggerCommand;
537     return (wifi_error)ret;
538 }
539 
wifi_set_log_handler(wifi_request_id id,wifi_interface_handle iface,wifi_ring_buffer_data_handler handler)540 wifi_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 
wifi_reset_log_handler(wifi_request_id id,wifi_interface_handle iface)557 wifi_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 
wifi_set_alert_handler(wifi_request_id id,wifi_interface_handle iface,wifi_alert_handler handler)569 wifi_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 
wifi_reset_alert_handler(wifi_request_id id,wifi_interface_handle iface)586 wifi_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 */
wifi_start_pkt_fate_monitoring(wifi_interface_handle iface)604 wifi_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 */
wifi_get_tx_pkt_fates(wifi_interface_handle iface,wifi_tx_report * tx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)644 wifi_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 */
wifi_get_rx_pkt_fates(wifi_interface_handle iface,wifi_rx_report * rx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)714 wifi_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 
WifiLoggerCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)771 WifiLoggerCommand::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 
~WifiLoggerCommand()783 WifiLoggerCommand::~WifiLoggerCommand()
784 {
785     unregisterVendorHandler(mVendor_id, mSubcmd);
786 }
787 
788 /* This function implements creation of Vendor command */
create()789 int 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 
807 out:
808     return ret;
809 }
810 
rb_timerhandler(hal_info * info)811 void 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 
wifi_logger_ring_buffers_init(hal_info * info)822 wifi_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 
881 cleanup:
882     wifi_logger_ring_buffers_deinit(info);
883     return ret;
884 }
885 
wifi_logger_ring_buffers_deinit(hal_info * info)886 void 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 */
error_handler_wifi_logger(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)899 static 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 */
ack_handler_wifi_logger(struct nl_msg * msg,void * arg)912 static 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 */
finish_handler_wifi_logger(struct nl_msg * msg,void * arg)923 static 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 
requestEvent()933 int 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     }
974 out:
975     /* Cleanup the mMsg */
976     mMsg.destroy();
977     return res;
978 }
979 
requestResponse()980 int WifiLoggerCommand::requestResponse()
981 {
982     return WifiCommand::requestResponse(mMsg);
983 }
984 
handleResponse(WifiEvent & reply)985 int 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  */
handleEvent(WifiEvent & event)1311 int 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 
setCallbackHandler(WifiLoggerCallbackHandler nHandler)1326 int 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 
unregisterHandler(u32 subCmd)1338 void WifiLoggerCommand::unregisterHandler(u32 subCmd)
1339 {
1340     unregisterVendorHandler(mVendor_id, subCmd);
1341 }
1342 
timed_wait(u16 wait_time)1343 int 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 
waitForRsp(bool wait)1351 void WifiLoggerCommand::waitForRsp(bool wait)
1352 {
1353     mWaitforRsp = wait;
1354 }
1355 
1356 /* Function to get Driver memory dump */
wifi_get_driver_memory_dump(wifi_interface_handle iface,wifi_driver_memory_dump_callbacks callback)1357 wifi_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 */
wifi_get_wake_reason_stats(wifi_interface_handle iface,WLAN_DRIVER_WAKE_REASON_CNT * wifi_wake_reason_cnt)1434 wifi_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 
1502 cleanup:
1503     delete wifiLoggerCommand;
1504     return (wifi_error)ret;
1505 }
1506 
getWakeStatsRspParams(WLAN_DRIVER_WAKE_REASON_CNT * wifi_wake_reason_cnt)1507 void WifiLoggerCommand::getWakeStatsRspParams(
1508                             WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1509 {
1510     mGetWakeStats = wifi_wake_reason_cnt;
1511 }
1512