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. 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();
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_u32(
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();
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_u32(
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             if (!tbVendor[
1168                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE]) {
1169                 mGetWakeStats->total_cmd_event_wake = 0;
1170             } else {
1171                 mGetWakeStats->total_cmd_event_wake = nla_get_u32(
1172                     tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_CMD_EVENT_WAKE]);
1173             }
1174 
1175             if (mGetWakeStats->total_cmd_event_wake &&
1176                     mGetWakeStats->cmd_event_wake_cnt) {
1177                 if (!tbVendor[
1178                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR]) {
1179                     mGetWakeStats->cmd_event_wake_cnt_used = 0;
1180                 } else {
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                 }
1191             } else
1192                 mGetWakeStats->cmd_event_wake_cnt_used = 0;
1193 
1194             if (!tbVendor[
1195                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE]) {
1196                 mGetWakeStats->total_driver_fw_local_wake = 0;
1197             } else {
1198                 mGetWakeStats->total_driver_fw_local_wake = nla_get_u32(tbVendor[
1199                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE]);
1200             }
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                     mGetWakeStats->driver_fw_local_wake_cnt_used = 0;
1207                 } else {
1208                     len = nla_len(tbVendor[
1209                         QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR]);
1210                     mGetWakeStats->driver_fw_local_wake_cnt_used =
1211                         (len < mGetWakeStats->driver_fw_local_wake_cnt_sz) ? len :
1212                                         mGetWakeStats->driver_fw_local_wake_cnt_sz;
1213 
1214                     memcpy(mGetWakeStats->driver_fw_local_wake_cnt,
1215                         nla_data(tbVendor[
1216                             QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR]),
1217                         (mGetWakeStats->driver_fw_local_wake_cnt_used * sizeof(int)));
1218                 }
1219             } else
1220                 mGetWakeStats->driver_fw_local_wake_cnt_used = 0;
1221 
1222             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE]) {
1223                 ALOGE("%s: TOTAL_RX_DATA_WAKE not found", __FUNCTION__);
1224                 break;
1225             }
1226             mGetWakeStats->total_rx_data_wake = nla_get_u32(tbVendor[
1227                         QCA_WLAN_VENDOR_ATTR_WAKE_STATS_TOTAL_RX_DATA_WAKE]);
1228 
1229             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT]) {
1230                 ALOGE("%s: RX_UNICAST_CNT not found", __FUNCTION__);
1231                 break;
1232             }
1233             mGetWakeStats->rx_wake_details.rx_unicast_cnt = nla_get_u32(
1234                     tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_UNICAST_CNT]);
1235 
1236             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT]) {
1237                 ALOGE("%s: RX_MULTICAST_CNT not found", __FUNCTION__);
1238                 break;
1239             }
1240             mGetWakeStats->rx_wake_details.rx_multicast_cnt = nla_get_u32(
1241                     tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_MULTICAST_CNT]);
1242 
1243             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT]) {
1244                 ALOGE("%s: RX_BROADCAST_CNT not found", __FUNCTION__);
1245                 break;
1246             }
1247             mGetWakeStats->rx_wake_details.rx_broadcast_cnt = nla_get_u32(
1248                     tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_RX_BROADCAST_CNT]);
1249 
1250             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT]) {
1251                 ALOGE("%s: ICMP_PKT not found", __FUNCTION__);
1252                 break;
1253             }
1254             mGetWakeStats->rx_wake_pkt_classification_info.icmp_pkt =
1255                 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP_PKT]);
1256 
1257             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT]) {
1258                 ALOGE("%s: ICMP6_PKT not found", __FUNCTION__);
1259                 break;
1260             }
1261             mGetWakeStats->rx_wake_pkt_classification_info.icmp6_pkt =
1262                 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_PKT]);
1263 
1264             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA]) {
1265                 ALOGE("%s: ICMP6_RA not found", __FUNCTION__);
1266                 break;
1267             }
1268             mGetWakeStats->rx_wake_pkt_classification_info.icmp6_ra =
1269                 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RA]);
1270 
1271             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA]) {
1272                 ALOGE("%s: ICMP6_NA not found", __FUNCTION__);
1273                 break;
1274             }
1275             mGetWakeStats->rx_wake_pkt_classification_info.icmp6_na =
1276                 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NA]);
1277 
1278             if (!tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS]) {
1279                 ALOGE("%s: ICMP6_NS not found", __FUNCTION__);
1280                 break;
1281             }
1282             mGetWakeStats->rx_wake_pkt_classification_info.icmp6_ns =
1283                 nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_NS]);
1284 
1285             if (!tbVendor[
1286                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT]) {
1287                 ALOGE("%s: ICMP4_RX_MULTICAST_CNT not found", __FUNCTION__);
1288                 break;
1289             }
1290             mGetWakeStats->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt =
1291                 nla_get_u32(tbVendor[
1292                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP4_RX_MULTICAST_CNT]);
1293 
1294             if (!tbVendor[
1295                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT]) {
1296                 ALOGE("%s: ICMP6_RX_MULTICAST_CNT not found", __FUNCTION__);
1297                 break;
1298             }
1299             mGetWakeStats->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
1300                 nla_get_u32(tbVendor[
1301                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_ICMP6_RX_MULTICAST_CNT]);
1302 
1303             if (!tbVendor[
1304                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT]) {
1305                 ALOGE("%s: OTHER_RX_MULTICAST_CNT not found", __FUNCTION__);
1306                 break;
1307             }
1308             mGetWakeStats->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
1309                 nla_get_u32(tbVendor[
1310                     QCA_WLAN_VENDOR_ATTR_WAKE_STATS_OTHER_RX_MULTICAST_CNT]);
1311 
1312         }
1313         break;
1314 
1315         default :
1316             ALOGE("%s: Wrong Wifi Logger subcmd response received %d",
1317                 __FUNCTION__, mSubcmd);
1318     }
1319 
1320     /* free the allocated memory */
1321     if (memBuffer) {
1322         free(memBuffer);
1323     }
1324     if (memDumpFilePtr) {
1325         fclose(memDumpFilePtr);
1326     }
1327     return NL_SKIP;
1328 }
1329 
1330 /* This function will be the main handler for incoming (from driver)
1331  * WIFI_LOGGER_SUBCMD.
1332  * Calls the appropriate callback handler after parsing the vendor data.
1333  */
handleEvent(WifiEvent & event)1334 int WifiLoggerCommand::handleEvent(WifiEvent &event)
1335 {
1336     WifiVendorCommand::handleEvent(event);
1337 
1338     switch(mSubcmd)
1339     {
1340        default:
1341            /* Error case should not happen print log */
1342            ALOGE("%s: Wrong subcmd received %d", __func__, mSubcmd);
1343            break;
1344     }
1345 
1346     return NL_SKIP;
1347 }
1348 
setCallbackHandler(WifiLoggerCallbackHandler nHandler)1349 wifi_error WifiLoggerCommand::setCallbackHandler(WifiLoggerCallbackHandler nHandler)
1350 {
1351     wifi_error res;
1352     mHandler = nHandler;
1353     res = registerVendorHandler(mVendor_id, mSubcmd);
1354     if (res != WIFI_SUCCESS) {
1355         ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
1356               __FUNCTION__, mVendor_id, mSubcmd);
1357     }
1358     return res;
1359 }
1360 
unregisterHandler(u32 subCmd)1361 void WifiLoggerCommand::unregisterHandler(u32 subCmd)
1362 {
1363     unregisterVendorHandler(mVendor_id, subCmd);
1364 }
1365 
timed_wait(u16 wait_time)1366 wifi_error WifiLoggerCommand::timed_wait(u16 wait_time)
1367 {
1368     struct timespec absTime;
1369     absTime.tv_sec = wait_time;
1370     absTime.tv_nsec = 0;
1371     return mCondition.wait(absTime);
1372 }
1373 
waitForRsp(bool wait)1374 void WifiLoggerCommand::waitForRsp(bool wait)
1375 {
1376     mWaitforRsp = wait;
1377 }
1378 
1379 /* Function to get Driver memory dump */
wifi_get_driver_memory_dump(wifi_interface_handle iface,wifi_driver_memory_dump_callbacks callback)1380 wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface,
1381                                     wifi_driver_memory_dump_callbacks callback)
1382 {
1383     FILE *fp;
1384     size_t fileSize, remaining, readSize;
1385     size_t numRecordsRead;
1386     char *memBuffer = NULL, *buffer = NULL;
1387     wifi_handle wifiHandle = getWifiHandle(iface);
1388     hal_info *info = getHalInfo(wifiHandle);
1389 
1390     /* Check Supported logger capability */
1391     if (!(info->supported_logger_feature_set &
1392           WIFI_LOGGER_DRIVER_DUMP_SUPPORTED)) {
1393         ALOGE("%s: Driver memory dump logging feature not supported %x",
1394               __FUNCTION__, info->supported_logger_feature_set);
1395         return WIFI_ERROR_NOT_SUPPORTED;
1396     }
1397     /* Open File */
1398     fp = fopen(DRIVER_MEMDUMP_FILENAME, "r");
1399     if (fp == NULL) {
1400         ALOGE("Failed to open %s file", DRIVER_MEMDUMP_FILENAME);
1401         return WIFI_ERROR_UNKNOWN;
1402     }
1403 
1404     memBuffer = (char *) malloc(DRIVER_MEMDUMP_MAX_FILESIZE);
1405     if (memBuffer == NULL) {
1406         ALOGE("%s: malloc failed for size %d", __FUNCTION__,
1407                     DRIVER_MEMDUMP_MAX_FILESIZE);
1408         fclose(fp);
1409         return WIFI_ERROR_OUT_OF_MEMORY;
1410     }
1411 
1412     /* Read the DRIVER_MEMDUMP_MAX_FILESIZE value at once */
1413     numRecordsRead = fread(memBuffer, 1, DRIVER_MEMDUMP_MAX_FILESIZE, fp);
1414     if (feof(fp))
1415         fileSize = numRecordsRead;
1416     else if (numRecordsRead == DRIVER_MEMDUMP_MAX_FILESIZE) {
1417         ALOGE("%s: Reading only first %zu bytes from file", __FUNCTION__,
1418                 numRecordsRead);
1419         fileSize = numRecordsRead;
1420     } else {
1421         ALOGE("%s: Read failed for reading at once, ret: %zu. Trying to read in"
1422                 "chunks", __FUNCTION__, numRecordsRead);
1423         /* Lets try to read in chunks */
1424         rewind(fp);
1425         remaining = DRIVER_MEMDUMP_MAX_FILESIZE;
1426         buffer = memBuffer;
1427         fileSize = 0;
1428         while (remaining) {
1429             readSize = 0;
1430             if (remaining >= LOGGER_MEMDUMP_CHUNKSIZE)
1431                 readSize = LOGGER_MEMDUMP_CHUNKSIZE;
1432             else
1433                 readSize = remaining;
1434 
1435             numRecordsRead = fread(buffer, 1, readSize, fp);
1436             fileSize += numRecordsRead;
1437             if (feof(fp))
1438                 break;
1439             else if (numRecordsRead == readSize) {
1440                 remaining -= readSize;
1441                 buffer += readSize;
1442                 ALOGV("%s: Read successful for size:%zu remaining:%zu",
1443                          __FUNCTION__, readSize, remaining);
1444             } else {
1445                 ALOGE("%s: Chunk read failed for size:%zu", __FUNCTION__,
1446                         readSize);
1447                 free(memBuffer);
1448                 memBuffer = NULL;
1449                 fclose(fp);
1450                 return WIFI_ERROR_UNKNOWN;
1451             }
1452         }
1453     }
1454     ALOGV("%s filename: %s fileSize: %zu", __FUNCTION__, DRIVER_MEMDUMP_FILENAME,
1455             fileSize);
1456     /* After successful read, call the callback function*/
1457     callback.on_driver_memory_dump(memBuffer, fileSize);
1458 
1459     /* free the allocated memory */
1460     free(memBuffer);
1461     fclose(fp);
1462     return WIFI_SUCCESS;
1463 }
1464 
1465 /* Function to get wake lock stats */
wifi_get_wake_reason_stats(wifi_interface_handle iface,WLAN_DRIVER_WAKE_REASON_CNT * wifi_wake_reason_cnt)1466 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
1467                              WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1468 {
1469     int requestId;
1470     wifi_error ret;
1471     WifiLoggerCommand *wifiLoggerCommand;
1472     struct nlattr *nlData;
1473     interface_info *ifaceInfo = getIfaceInfo(iface);
1474     wifi_handle wifiHandle = getWifiHandle(iface);
1475     hal_info *info = getHalInfo(wifiHandle);
1476 
1477     /* Check Supported logger capability */
1478     if (!(info->supported_logger_feature_set &
1479           WIFI_LOGGER_WAKE_LOCK_SUPPORTED)) {
1480         ALOGE("%s: Wake lock logging feature not supported %x",
1481               __FUNCTION__, info->supported_logger_feature_set);
1482         return WIFI_ERROR_NOT_SUPPORTED;
1483     }
1484 
1485     /* No request id from caller, so generate one and pass it on to the driver.
1486      * Generate it randomly.
1487      */
1488     requestId = get_requestid();
1489 
1490     if (!wifi_wake_reason_cnt) {
1491         ALOGE("%s: Invalid buffer provided. Exit.",
1492             __FUNCTION__);
1493         return WIFI_ERROR_INVALID_ARGS;
1494     }
1495 
1496     wifiLoggerCommand = new WifiLoggerCommand(
1497                                 wifiHandle,
1498                                 requestId,
1499                                 OUI_QCA,
1500                                 QCA_NL80211_VENDOR_SUBCMD_GET_WAKE_REASON_STATS);
1501     if (wifiLoggerCommand == NULL) {
1502         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
1503         return WIFI_ERROR_UNKNOWN;
1504     }
1505 
1506     /* Create the NL message. */
1507     ret = wifiLoggerCommand->create();
1508     if (ret != WIFI_SUCCESS)
1509         goto cleanup;
1510 
1511     /* Set the interface Id of the message. */
1512     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
1513     if (ret != WIFI_SUCCESS)
1514         goto cleanup;
1515 
1516     wifiLoggerCommand->getWakeStatsRspParams(wifi_wake_reason_cnt);
1517 
1518     /* Add the vendor specific attributes for the NL command. */
1519     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
1520     if (!nlData)
1521         goto cleanup;
1522 
1523     ret = wifiLoggerCommand->put_u32(
1524                 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ,
1525                 wifi_wake_reason_cnt->cmd_event_wake_cnt_sz);
1526     if (ret != WIFI_SUCCESS)
1527         goto cleanup;
1528 
1529     ret = wifiLoggerCommand->put_u32(
1530                 QCA_WLAN_VENDOR_ATTR_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ,
1531                 wifi_wake_reason_cnt->driver_fw_local_wake_cnt_sz);
1532     if (ret != WIFI_SUCCESS)
1533         goto cleanup;
1534 
1535     wifiLoggerCommand->attr_end(nlData);
1536 
1537     /* Send the msg and wait for a response. */
1538     ret = wifiLoggerCommand->requestResponse();
1539     if (ret != WIFI_SUCCESS)
1540         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
1541 
1542 cleanup:
1543     delete wifiLoggerCommand;
1544     return ret;
1545 }
1546 
getWakeStatsRspParams(WLAN_DRIVER_WAKE_REASON_CNT * wifi_wake_reason_cnt)1547 void WifiLoggerCommand::getWakeStatsRspParams(
1548                             WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1549 {
1550     mGetWakeStats = wifi_wake_reason_cnt;
1551 }
1552