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