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