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