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