• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2  *
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions
5  * are met:
6  *  * Redistributions of source code must retain the above copyright
7  *    notice, this list of conditions and the following disclaimer.
8  *  * Redistributions in binary form must reproduce the above
9  *    copyright notice, this list of conditions and the following
10  *    disclaimer in the documentation and/or other materials provided
11  *    with the distribution.
12  *  * Neither the name of The Linux Foundation nor the names of its
13  *    contributors may be used to endorse or promote products derived
14  *    from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "sync.h"
30 
31 #include "wifi_hal.h"
32 #include "common.h"
33 #include "cpp_bindings.h"
34 #include <errno.h>
35 #include <utils/Log.h>
36 #include "wifiloggercmd.h"
37 #include "rb_wrapper.h"
38 #include <stdlib.h>
39 
40 #define LOGGER_MEMDUMP_FILENAME "/proc/debug/fwdump"
41 #define LOGGER_MEMDUMP_CHUNKSIZE (4 * 1024)
42 
43 char power_events_ring_name[] = "power_events_rb";
44 char connectivity_events_ring_name[] = "connectivity_events_rb";
45 char pkt_stats_ring_name[] = "pkt_stats_rb";
46 char driver_prints_ring_name[] = "driver_prints_rb";
47 char firmware_prints_ring_name[] = "firmware_prints_rb";
48 
get_ring_id(hal_info * info,char * ring_name)49 static int get_ring_id(hal_info *info, char *ring_name)
50 {
51     int rb_id;
52 
53     for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
54         if (is_rb_name_match(&info->rb_infos[rb_id], ring_name)) {
55            return rb_id;
56         }
57     }
58     return -1;
59 }
60 
61 //Implementation of the functions exposed in wifi_logger.h
62 
63 /* 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)64 wifi_error wifi_start_logging(wifi_interface_handle iface,
65                               u32 verbose_level, u32 flags,
66                               u32 max_interval_sec, u32 min_data_size,
67                               char *buffer_name)
68 {
69     int requestId, ret = 0;
70     WifiLoggerCommand *wifiLoggerCommand = NULL;
71     struct nlattr *nlData;
72     interface_info *ifaceInfo = getIfaceInfo(iface);
73     wifi_handle wifiHandle = getWifiHandle(iface);
74     hal_info *info = getHalInfo(wifiHandle);
75     int ring_id = 0;
76 
77     /*
78      * No request id from caller, so generate one and pass it on to the driver.
79      * Generate one randomly.
80      */
81     requestId = get_requestid();
82 
83     if (buffer_name == NULL) {
84         ALOGE("%s: Invalid Ring Name. \n", __FUNCTION__);
85         return WIFI_ERROR_UNKNOWN;
86     }
87 
88     ring_id = get_ring_id(info, buffer_name);
89     if (ring_id < 0) {
90         ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__);
91         return WIFI_ERROR_UNKNOWN;
92     }
93 
94     if ((ring_id == POWER_EVENTS_RB_ID) ||
95         (ring_id == PKT_STATS_RB_ID)) {
96         wifiLoggerCommand = new WifiLoggerCommand(
97                                 wifiHandle,
98                                 requestId,
99                                 OUI_QCA,
100                                 QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_START);
101 
102         if (wifiLoggerCommand == NULL) {
103            ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
104            return WIFI_ERROR_UNKNOWN;
105         }
106         /* Create the NL message. */
107         ret = wifiLoggerCommand->create();
108 
109         if (ret < 0)
110             goto cleanup;
111 
112         /* Set the interface Id of the message. */
113         ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
114 
115         if (ret < 0)
116             goto cleanup;
117 
118         /* Add the vendor specific attributes for the NL command. */
119         nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
120 
121         if (!nlData)
122             goto cleanup;
123 
124         if (wifiLoggerCommand->put_u32(
125                     QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID, ring_id))
126         {
127             goto cleanup;
128         }
129         if (wifiLoggerCommand->put_u32(
130                     QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_VERBOSE_LEVEL,
131                     verbose_level))
132         {
133             goto cleanup;
134         }
135         if (wifiLoggerCommand->put_u32(
136                     QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_FLAGS,
137                     flags))
138         {
139             goto cleanup;
140         }
141 
142         wifiLoggerCommand->attr_end(nlData);
143 
144         /* Send the msg and wait for a response. */
145         ret = wifiLoggerCommand->requestResponse();
146         if (ret) {
147             ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
148         }
149 
150     }
151     ALOGV("%s: Logging Started for %s.", __FUNCTION__, buffer_name);
152     rb_start_logging(&info->rb_infos[ring_id], verbose_level,
153                     flags, max_interval_sec, min_data_size);
154 cleanup:
155     if (wifiLoggerCommand)
156         delete wifiLoggerCommand;
157     return (wifi_error)ret;
158 
159 }
160 
161 /*  Function to get each ring related info */
wifi_get_ring_buffers_status(wifi_interface_handle iface,u32 * num_buffers,wifi_ring_buffer_status * status)162 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
163                                         u32 *num_buffers,
164                                         wifi_ring_buffer_status *status)
165 {
166     int ret = 0;
167     interface_info *ifaceInfo = getIfaceInfo(iface);
168     wifi_handle wifiHandle = getWifiHandle(iface);
169     hal_info *info = getHalInfo(wifiHandle);
170     wifi_ring_buffer_status *rbs;
171     struct rb_info *rb_info;
172     int rb_id;
173 
174     if ((*num_buffers) < NUM_RING_BUFS) {
175         ALOGE("%s: Input num_buffers:%d cannot be accommodated, "
176               "Total ring buffer num:%d", __FUNCTION__, num_buffers,
177               NUM_RING_BUFS);
178         *num_buffers = 0;
179         return WIFI_ERROR_OUT_OF_MEMORY;
180     }
181     for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
182         rb_info = &info->rb_infos[rb_id];
183         rbs = status + rb_id;
184 
185         get_rb_status(rb_info, rbs);
186     }
187     *num_buffers = NUM_RING_BUFS;
188     return (wifi_error)ret;
189 }
190 
push_out_all_ring_buffers(hal_info * info)191 void push_out_all_ring_buffers(hal_info *info)
192 {
193     int rb_id;
194 
195     for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
196         push_out_rb_data(&info->rb_infos[rb_id]);
197     }
198 }
199 
send_alert(hal_info * info,int reason_code)200 void send_alert(hal_info *info, int reason_code)
201 {
202     wifi_alert_handler handler;
203 
204     pthread_mutex_lock(&info->ah_lock);
205     handler.on_alert = info->on_alert;
206     pthread_mutex_unlock(&info->ah_lock);
207 
208     if (handler.on_alert) {
209         handler.on_alert(0, NULL, 0, reason_code);
210     }
211 }
212 
setFeatureSet(u32 * support)213 void WifiLoggerCommand::setFeatureSet(u32 *support) {
214     mSupportedSet = support;
215 }
216 
217 /*  Function to get the supported feature set for logging.*/
wifi_get_logger_supported_feature_set(wifi_interface_handle iface,u32 * support)218 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
219                                                  u32 *support)
220 {
221 
222     int requestId, ret = 0;
223     WifiLoggerCommand *wifiLoggerCommand;
224     struct nlattr *nlData;
225     interface_info *ifaceInfo = getIfaceInfo(iface);
226     wifi_handle wifiHandle = getWifiHandle(iface);
227     hal_info *info = getHalInfo(wifiHandle);
228 
229     /* No request id from caller, so generate one and pass it on to the driver.
230      * Generate one randomly.
231      */
232     requestId = get_requestid();
233 
234     wifiLoggerCommand = new WifiLoggerCommand(
235                             wifiHandle,
236                             requestId,
237                             OUI_QCA,
238                             QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET);
239 
240     if (wifiLoggerCommand == NULL) {
241         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
242         return WIFI_ERROR_UNKNOWN;
243     }
244     /* Create the NL message. */
245     ret = wifiLoggerCommand->create();
246 
247     if (ret < 0)
248         goto cleanup;
249 
250     /* Set the interface Id of the message. */
251     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
252 
253     if (ret < 0)
254         goto cleanup;
255 
256     /* Add the vendor specific attributes for the NL command. */
257     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
258 
259     if (!nlData)
260         goto cleanup;
261 
262     if (wifiLoggerCommand->put_u32(
263                 QCA_WLAN_VENDOR_ATTR_FEATURE_SET, requestId))
264     {
265         goto cleanup;
266     }
267     wifiLoggerCommand->attr_end(nlData);
268 
269     wifiLoggerCommand->setFeatureSet(support);
270 
271     /* Send the msg and wait for a response. */
272     ret = wifiLoggerCommand->requestResponse();
273     if (ret) {
274         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
275     }
276 
277 cleanup:
278     delete wifiLoggerCommand;
279     return (wifi_error)ret;
280 }
281 
282 /*  Function to get the data in each ring for the given ring ID.*/
wifi_get_ring_data(wifi_interface_handle iface,char * ring_name)283 wifi_error wifi_get_ring_data(wifi_interface_handle iface,
284                               char *ring_name)
285 {
286 
287     int requestId, ret = 0;
288     WifiLoggerCommand *wifiLoggerCommand;
289     struct nlattr *nlData;
290     interface_info *ifaceInfo = getIfaceInfo(iface);
291     wifi_handle wifiHandle = getWifiHandle(iface);
292     hal_info *info = getHalInfo(wifiHandle);
293     int ring_id = 0;
294 
295     ring_id = get_ring_id(info, ring_name);
296     if (ring_id < 0) {
297         ALOGE("%s: Invalid Ring Buffer Name ", __FUNCTION__);
298         return WIFI_ERROR_UNKNOWN;
299     }
300 
301     requestId = get_requestid();
302 
303     wifiLoggerCommand = new WifiLoggerCommand(
304                                 wifiHandle,
305                                 requestId,
306                                 OUI_QCA,
307                                 QCA_NL80211_VENDOR_SUBCMD_GET_RING_DATA);
308     if (wifiLoggerCommand == NULL) {
309         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
310         return WIFI_ERROR_UNKNOWN;
311     }
312     /* Create the NL message. */
313     ret = wifiLoggerCommand->create();
314 
315     if (ret < 0)
316         goto cleanup;
317 
318     /* Set the interface Id of the message. */
319     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
320 
321     if (ret < 0)
322         goto cleanup;
323 
324     /* Add the vendor specific attributes for the NL command. */
325     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
326 
327     if (!nlData)
328         goto cleanup;
329 
330     if (wifiLoggerCommand->put_u32(
331                 QCA_WLAN_VENDOR_ATTR_WIFI_LOGGER_RING_ID, ring_id))
332     {
333         goto cleanup;
334     }
335     wifiLoggerCommand->attr_end(nlData);
336 
337     /* Send the msg and wait for a response. */
338     ret = wifiLoggerCommand->requestResponse();
339     if (ret) {
340         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
341     }
342 
343 cleanup:
344     delete wifiLoggerCommand;
345     return (wifi_error)ret;
346 }
347 
setVersionInfo(char * buffer,int buffer_size)348 void WifiLoggerCommand::setVersionInfo(char *buffer, int buffer_size) {
349     mVersion = buffer;
350     mVersionLen = buffer_size;
351 }
352 
353 /*  Function to send enable request to the wifi driver.*/
wifi_get_firmware_version(wifi_interface_handle iface,char * buffer,int buffer_size)354 wifi_error wifi_get_firmware_version(wifi_interface_handle iface,
355                                      char *buffer, int buffer_size)
356 {
357     int requestId, ret = 0;
358     WifiLoggerCommand *wifiLoggerCommand;
359     struct nlattr *nlData;
360     interface_info *ifaceInfo = getIfaceInfo(iface);
361     wifi_handle wifiHandle = getWifiHandle(iface);
362     hal_info *info = getHalInfo(wifiHandle);
363 
364     /* No request id from caller, so generate one and pass it on to the driver.
365      * Generate one randomly.
366      */
367     requestId = get_requestid();
368 
369     wifiLoggerCommand = new WifiLoggerCommand(
370                                 wifiHandle,
371                                 requestId,
372                                 OUI_QCA,
373                                 QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO);
374     if (wifiLoggerCommand == NULL) {
375         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
376         return WIFI_ERROR_UNKNOWN;
377     }
378     /* Create the NL message. */
379     ret = wifiLoggerCommand->create();
380 
381     if (ret < 0)
382         goto cleanup;
383 
384     /* Set the interface Id of the message. */
385     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
386 
387     if (ret < 0)
388         goto cleanup;
389 
390     /* Add the vendor specific attributes for the NL command. */
391     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
392 
393     if (!nlData)
394         goto cleanup;
395 
396     if (wifiLoggerCommand->put_u32(
397                 QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION, requestId))
398     {
399         goto cleanup;
400     }
401     wifiLoggerCommand->attr_end(nlData);
402 
403     wifiLoggerCommand->setVersionInfo(buffer, buffer_size);
404 
405     /* Send the msg and wait for a response. */
406     ret = wifiLoggerCommand->requestResponse();
407     if (ret) {
408         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
409     }
410 cleanup:
411     delete wifiLoggerCommand;
412     return (wifi_error)ret;
413 
414 }
415 
416 /*  Function to get wlan driver version.*/
wifi_get_driver_version(wifi_interface_handle iface,char * buffer,int buffer_size)417 wifi_error wifi_get_driver_version(wifi_interface_handle iface,
418                                    char *buffer, int buffer_size)
419 {
420 
421     int requestId, ret = 0;
422     WifiLoggerCommand *wifiLoggerCommand;
423     struct nlattr *nlData;
424     interface_info *ifaceInfo = getIfaceInfo(iface);
425     wifi_handle wifiHandle = getWifiHandle(iface);
426     hal_info *info = getHalInfo(wifiHandle);
427 
428     /* No request id from caller, so generate one and pass it on to the driver.
429      * Generate one randomly.
430      */
431     requestId = get_requestid();
432 
433     wifiLoggerCommand = new WifiLoggerCommand(
434                             wifiHandle,
435                             requestId,
436                             OUI_QCA,
437                             QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO);
438     if (wifiLoggerCommand == NULL) {
439         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
440         return WIFI_ERROR_UNKNOWN;
441     }
442     /* Create the NL message. */
443     ret = wifiLoggerCommand->create();
444 
445     if (ret < 0)
446         goto cleanup;
447 
448     /* Set the interface Id of the message. */
449     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
450 
451     if (ret < 0)
452         goto cleanup;
453 
454     /* Add the vendor specific attributes for the NL command. */
455     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
456 
457     if (!nlData)
458         goto cleanup;
459 
460     if (wifiLoggerCommand->put_u32(
461             QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION, requestId))
462     {
463         goto cleanup;
464     }
465     wifiLoggerCommand->attr_end(nlData);
466 
467     wifiLoggerCommand->setVersionInfo(buffer, buffer_size);
468 
469     /* Send the msg and wait for a response. */
470     ret = wifiLoggerCommand->requestResponse();
471     if (ret) {
472         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
473     }
474 cleanup:
475     delete wifiLoggerCommand;
476     return (wifi_error)ret;
477 }
478 
479 
480 /* Function to get the Firmware memory dump. */
wifi_get_firmware_memory_dump(wifi_interface_handle iface,wifi_firmware_memory_dump_handler handler)481 wifi_error wifi_get_firmware_memory_dump(wifi_interface_handle iface,
482                                 wifi_firmware_memory_dump_handler handler)
483 {
484     int requestId, ret = 0;
485     WifiLoggerCommand *wifiLoggerCommand;
486     struct nlattr *nlData;
487     interface_info *ifaceInfo = getIfaceInfo(iface);
488     wifi_handle wifiHandle = getWifiHandle(iface);
489     hal_info *info = getHalInfo(wifiHandle);
490 
491     /* No request id from caller, so generate one and pass it on to the driver.
492      * Generate one randomly.
493      */
494     requestId = get_requestid();
495 
496     wifiLoggerCommand = new WifiLoggerCommand(
497                             wifiHandle,
498                             requestId,
499                             OUI_QCA,
500                             QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP);
501     if (wifiLoggerCommand == NULL) {
502         ALOGE("%s: Error WifiLoggerCommand NULL", __FUNCTION__);
503         return WIFI_ERROR_UNKNOWN;
504     }
505     /* Create the NL message. */
506     ret = wifiLoggerCommand->create();
507 
508     if (ret < 0)
509         goto cleanup;
510 
511     /* Set the interface Id of the message. */
512     ret = wifiLoggerCommand->set_iface_id(ifaceInfo->name);
513 
514     if (ret < 0)
515         goto cleanup;
516 
517     /* Add the vendor specific attributes for the NL command. */
518     nlData = wifiLoggerCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
519 
520     if (!nlData)
521         goto cleanup;
522 
523     wifiLoggerCommand->attr_end(nlData);
524 
525     /* copy the callback into callback handler */
526     WifiLoggerCallbackHandler callbackHandler;
527     memset(&callbackHandler, 0, sizeof(callbackHandler));
528     callbackHandler.on_firmware_memory_dump = \
529         handler.on_firmware_memory_dump;
530 
531     ret = wifiLoggerCommand->setCallbackHandler(callbackHandler);
532     if (ret < 0)
533         goto cleanup;
534 
535     /* Send the msg and wait for the memory dump response */
536     ret = wifiLoggerCommand->requestResponse();
537     if (ret) {
538         ALOGE("%s: Error %d happened. ", __FUNCTION__, ret);
539     }
540 
541 cleanup:
542     delete wifiLoggerCommand;
543     return (wifi_error)ret;
544 }
545 
wifi_set_log_handler(wifi_request_id id,wifi_interface_handle iface,wifi_ring_buffer_data_handler handler)546 wifi_error wifi_set_log_handler(wifi_request_id id,
547                                 wifi_interface_handle iface,
548                                 wifi_ring_buffer_data_handler handler)
549 {
550     wifi_handle wifiHandle = getWifiHandle(iface);
551     hal_info *info = getHalInfo(wifiHandle);
552 
553     pthread_mutex_lock(&info->lh_lock);
554     info->on_ring_buffer_data = handler.on_ring_buffer_data;
555     pthread_mutex_unlock(&info->lh_lock);
556     if (handler.on_ring_buffer_data == NULL) {
557         ALOGE("Set log handler is NULL");
558         return WIFI_ERROR_UNKNOWN;
559     }
560     return WIFI_SUCCESS;
561 }
562 
wifi_reset_log_handler(wifi_request_id id,wifi_interface_handle iface)563 wifi_error wifi_reset_log_handler(wifi_request_id id,
564                                   wifi_interface_handle iface)
565 {
566     wifi_handle wifiHandle = getWifiHandle(iface);
567     hal_info *info = getHalInfo(wifiHandle);
568 
569     pthread_mutex_lock(&info->lh_lock);
570     info->on_ring_buffer_data = NULL;
571     pthread_mutex_unlock(&info->lh_lock);
572     return WIFI_SUCCESS;
573 }
574 
wifi_set_alert_handler(wifi_request_id id,wifi_interface_handle iface,wifi_alert_handler handler)575 wifi_error wifi_set_alert_handler(wifi_request_id id,
576                                   wifi_interface_handle iface,
577                                   wifi_alert_handler handler)
578 {
579     wifi_handle wifiHandle = getWifiHandle(iface);
580     hal_info *info = getHalInfo(wifiHandle);
581 
582     if (handler.on_alert == NULL) {
583         ALOGE("Set alert handler is NULL");
584         return WIFI_ERROR_UNKNOWN;
585     }
586     pthread_mutex_lock(&info->ah_lock);
587     info->on_alert = handler.on_alert;
588     pthread_mutex_unlock(&info->ah_lock);
589     return WIFI_SUCCESS;
590 }
591 
wifi_reset_alert_handler(wifi_request_id id,wifi_interface_handle iface)592 wifi_error wifi_reset_alert_handler(wifi_request_id id,
593                                     wifi_interface_handle iface)
594 {
595     wifi_handle wifiHandle = getWifiHandle(iface);
596     hal_info *info = getHalInfo(wifiHandle);
597 
598     pthread_mutex_lock(&info->ah_lock);
599     info->on_alert = NULL;
600     pthread_mutex_unlock(&info->ah_lock);
601     return WIFI_SUCCESS;
602 }
603 
WifiLoggerCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)604 WifiLoggerCommand::WifiLoggerCommand(wifi_handle handle, int id, u32 vendor_id, u32 subcmd)
605         : WifiVendorCommand(handle, id, vendor_id, subcmd)
606 {
607     ALOGV("WifiLoggerCommand %p constructed", this);
608     mVersion = NULL;
609     mVersionLen = 0;
610     mRequestId = id;
611     memset(&mHandler, 0,sizeof(mHandler));
612     mWaitforRsp = false;
613     mMoreData = false;
614     mSupportedSet = NULL;
615 }
616 
~WifiLoggerCommand()617 WifiLoggerCommand::~WifiLoggerCommand()
618 {
619     ALOGV("WifiLoggerCommand %p destructor", this);
620     unregisterVendorHandler(mVendor_id, mSubcmd);
621 }
622 
623 /* This function implements creation of Vendor command */
create()624 int WifiLoggerCommand::create() {
625     int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
626     if (ret < 0) {
627         return ret;
628     }
629 
630     /* Insert the oui in the msg */
631     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
632     if (ret < 0)
633         goto out;
634     /* Insert the subcmd in the msg */
635     ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
636     if (ret < 0)
637         goto out;
638 
639      ALOGV("%s: mVendor_id = %d, Subcmd = %d.",
640         __FUNCTION__, mVendor_id, mSubcmd);
641 
642 out:
643     return ret;
644 }
645 
rb_timerhandler(hal_info * info)646 void rb_timerhandler(hal_info *info)
647 {
648    struct timeval now;
649    int rb_id;
650 
651    gettimeofday(&now,NULL);
652    for (rb_id = 0; rb_id < NUM_RING_BUFS; rb_id++) {
653        rb_check_for_timeout(&info->rb_infos[rb_id], &now);
654    }
655 }
656 
wifi_logger_ring_buffers_init(hal_info * info)657 wifi_error wifi_logger_ring_buffers_init(hal_info *info)
658 {
659     wifi_error ret;
660 
661     ret = rb_init(info, &info->rb_infos[POWER_EVENTS_RB_ID],
662                   POWER_EVENTS_RB_ID,
663                   POWER_EVENTS_RB_BUF_SIZE,
664                   POWER_EVENTS_NUM_BUFS,
665                   power_events_ring_name);
666     if (ret != WIFI_SUCCESS) {
667         ALOGE("Failed to initialize power events ring buffer");
668         goto cleanup;
669     }
670 
671     ret = rb_init(info, &info->rb_infos[CONNECTIVITY_EVENTS_RB_ID],
672                   CONNECTIVITY_EVENTS_RB_ID,
673                   CONNECTIVITY_EVENTS_RB_BUF_SIZE,
674                   CONNECTIVITY_EVENTS_NUM_BUFS,
675                   connectivity_events_ring_name);
676     if (ret != WIFI_SUCCESS) {
677         ALOGE("Failed to initialize connectivity events ring buffer");
678         goto cleanup;
679     }
680 
681     ret = rb_init(info, &info->rb_infos[PKT_STATS_RB_ID],
682                   PKT_STATS_RB_ID,
683                   PKT_STATS_RB_BUF_SIZE,
684                   PKT_STATS_NUM_BUFS,
685                   pkt_stats_ring_name);
686     if (ret != WIFI_SUCCESS) {
687         ALOGE("Failed to initialize per packet stats ring buffer");
688         goto cleanup;
689     }
690 
691     ret = rb_init(info, &info->rb_infos[DRIVER_PRINTS_RB_ID],
692                   DRIVER_PRINTS_RB_ID,
693                   DRIVER_PRINTS_RB_BUF_SIZE,
694                   DRIVER_PRINTS_NUM_BUFS,
695                   driver_prints_ring_name);
696     if (ret != WIFI_SUCCESS) {
697         ALOGE("Failed to initialize driver prints ring buffer");
698         goto cleanup;
699     }
700 
701     ret = rb_init(info, &info->rb_infos[FIRMWARE_PRINTS_RB_ID],
702                   FIRMWARE_PRINTS_RB_ID,
703                   FIRMWARE_PRINTS_RB_BUF_SIZE,
704                   FIRMWARE_PRINTS_NUM_BUFS,
705                   firmware_prints_ring_name);
706     if (ret != WIFI_SUCCESS) {
707         ALOGE("Failed to initialize firmware prints ring buffer");
708         goto cleanup;
709     }
710 
711     pthread_mutex_init(&info->lh_lock, NULL);
712     pthread_mutex_init(&info->ah_lock, NULL);
713 
714     return ret;
715 
716 cleanup:
717     wifi_logger_ring_buffers_deinit(info);
718     return ret;
719 }
720 
wifi_logger_ring_buffers_deinit(hal_info * info)721 void wifi_logger_ring_buffers_deinit(hal_info *info)
722 {
723     int i;
724 
725     for (i = 0; i < NUM_RING_BUFS; i++) {
726         rb_deinit(&info->rb_infos[i]);
727     }
728     pthread_mutex_destroy(&info->lh_lock);
729     pthread_mutex_destroy(&info->ah_lock);
730 }
731 
732 
733 /* Callback handlers registered for nl message send */
error_handler_wifi_logger(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)734 static int error_handler_wifi_logger(struct sockaddr_nl *nla,
735                                      struct nlmsgerr *err,
736                                      void *arg)
737 {
738     struct sockaddr_nl *tmp;
739     int *ret = (int *)arg;
740     tmp = nla;
741     *ret = err->error;
742     ALOGE("%s: Error code:%d (%s)", __FUNCTION__, *ret, strerror(-(*ret)));
743     return NL_STOP;
744 }
745 
746 /* Callback handlers registered for nl message send */
ack_handler_wifi_logger(struct nl_msg * msg,void * arg)747 static int ack_handler_wifi_logger(struct nl_msg *msg, void *arg)
748 {
749     int *ret = (int *)arg;
750     struct nl_msg * a;
751 
752     a = msg;
753     *ret = 0;
754     return NL_STOP;
755 }
756 
757 /* Callback handlers registered for nl message send */
finish_handler_wifi_logger(struct nl_msg * msg,void * arg)758 static int finish_handler_wifi_logger(struct nl_msg *msg, void *arg)
759 {
760   int *ret = (int *)arg;
761   struct nl_msg * a;
762 
763   a = msg;
764   *ret = 0;
765   return NL_SKIP;
766 }
767 
requestEvent()768 int WifiLoggerCommand::requestEvent()
769 {
770     int res = -1;
771     struct nl_cb *cb;
772 
773     cb = nl_cb_alloc(NL_CB_DEFAULT);
774     if (!cb) {
775         ALOGE("%s: Callback allocation failed",__FUNCTION__);
776         res = -1;
777         goto out;
778     }
779 
780     /* Send message */
781     res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
782     if (res < 0)
783         goto out;
784     res = 1;
785 
786     nl_cb_err(cb, NL_CB_CUSTOM, error_handler_wifi_logger, &res);
787     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler_wifi_logger, &res);
788     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler_wifi_logger, &res);
789 
790     /* Err is populated as part of finish_handler. */
791     while (res > 0){
792          nl_recvmsgs(mInfo->cmd_sock, cb);
793     }
794 
795     ALOGV("%s: Msg sent, res=%d, mWaitForRsp=%d", __FUNCTION__, res, mWaitforRsp);
796     /* Only wait for the asynchronous event if HDD returns success, res=0 */
797     if (!res && (mWaitforRsp == true)) {
798         struct timespec abstime;
799         abstime.tv_sec = 4;
800         abstime.tv_nsec = 0;
801         res = mCondition.wait(abstime);
802         if (res == ETIMEDOUT)
803         {
804             ALOGE("%s: Time out happened.", __FUNCTION__);
805         }
806         ALOGV("%s: Command invoked return value:%d, mWaitForRsp=%d",
807             __FUNCTION__, res, mWaitforRsp);
808     }
809 out:
810     /* Cleanup the mMsg */
811     mMsg.destroy();
812     return res;
813 }
814 
requestResponse()815 int WifiLoggerCommand::requestResponse()
816 {
817     return WifiCommand::requestResponse(mMsg);
818 }
819 
handleResponse(WifiEvent & reply)820 int WifiLoggerCommand::handleResponse(WifiEvent &reply) {
821     u32 status;
822     int ret = WIFI_SUCCESS;
823     int i = 0;
824     int len = 0, version;
825     char version_type[20];
826     char* memBuffer = NULL;
827     FILE* memDumpFilePtr = NULL;
828     WifiVendorCommand::handleResponse(reply);
829 
830     memset(version_type, 0, 20);
831     switch(mSubcmd)
832     {
833         case QCA_NL80211_VENDOR_SUBCMD_GET_WIFI_INFO:
834         {
835             struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX + 1];
836 
837             nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_WIFI_INFO_GET_MAX,
838                             (struct nlattr *)mVendorData, mDataLen, NULL);
839 
840             if (tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]) {
841                 len = nla_len(tb_vendor[
842                         QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION]);
843                 memcpy(version_type, "Driver", strlen("Driver"));
844                 version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_DRIVER_VERSION;
845             } else if (
846                 tb_vendor[QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]) {
847                 len = nla_len(
848                         tb_vendor[
849                         QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION]);
850                 memcpy(version_type, "Firmware", strlen("Firmware"));
851                 version = QCA_WLAN_VENDOR_ATTR_WIFI_INFO_FIRMWARE_VERSION;
852             }
853             if (len && mVersion && mVersionLen) {
854                 memset(mVersion, 0, mVersionLen);
855                 /* if len is greater than the incoming length then
856                    accommodate 1 lesser than mVersionLen to have the
857                    string terminated with '\0' */
858                 len = (len > mVersionLen)? (mVersionLen - 1) : len;
859                 memcpy(mVersion, nla_data(tb_vendor[version]), len);
860                 ALOGD("%s: WLAN version len : %d", __FUNCTION__, len);
861                 ALOGD("%s: WLAN %s version : %s ", __FUNCTION__,
862                       version_type, mVersion);
863             }
864         }
865         break;
866         case QCA_NL80211_VENDOR_SUBCMD_GET_LOGGER_FEATURE_SET:
867         {
868             struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
869 
870             nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
871                             (struct nlattr *)mVendorData, mDataLen, NULL);
872 
873             if (tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]) {
874                 *mSupportedSet =
875                 nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
876                 ALOGD("%s: Supported Feature Set : val 0x%x",
877                       __FUNCTION__, *mSupportedSet);
878             }
879         }
880         break;
881 
882         case QCA_NL80211_VENDOR_SUBCMD_WIFI_LOGGER_MEMORY_DUMP:
883         {
884             int id = 0;
885             u32 memDumpSize = 0;
886             int numRecordsRead = 0;
887             u32 remaining = 0;
888             char* buffer = NULL;
889             struct nlattr *tbVendor[
890                 QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX + 1];
891 
892             nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MAX,
893                     (struct nlattr *)mVendorData,
894                     mDataLen, NULL);
895 
896             if (!tbVendor[
897                 QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE]) {
898                 ALOGE("%s: LOGGER_RESULTS_MEMDUMP_SIZE not"
899                       "found", __FUNCTION__);
900                 break;
901             }
902 
903             memDumpSize = nla_get_u32(
904                 tbVendor[QCA_WLAN_VENDOR_ATTR_LOGGER_RESULTS_MEMDUMP_SIZE]
905                 );
906 
907             /* Allocate the memory indicated in memDumpSize */
908             memBuffer = (char*) malloc(sizeof(char) * memDumpSize);
909             if (memBuffer == NULL) {
910                 ALOGE("%s: No Memory for allocating Buffer ",
911                       "size of %d", __func__, memDumpSize);
912                 break;
913             }
914             memset(memBuffer, 0, sizeof(char) * memDumpSize);
915 
916             ALOGI("%s: Memory Dump size: %u", __func__,
917                   memDumpSize);
918 
919             /* Open the proc or debugfs filesystem */
920             memDumpFilePtr = fopen(LOGGER_MEMDUMP_FILENAME, "r");
921             if (memDumpFilePtr == NULL) {
922                 ALOGE("Failed to open %s file", LOGGER_MEMDUMP_FILENAME);
923                 break;
924             }
925 
926             /* Read the memDumpSize value at once */
927             numRecordsRead = fread(memBuffer, 1, memDumpSize,
928                                    memDumpFilePtr);
929             if (numRecordsRead <= 0 ||
930                 numRecordsRead != (int) memDumpSize) {
931                 ALOGE("%s: Read %d failed for reading at once.",
932                       __func__, numRecordsRead);
933                 /* Lets try to read in chunks */
934                 rewind(memDumpFilePtr);
935                 remaining = memDumpSize;
936                 buffer = memBuffer;
937                 while (remaining) {
938                     u32 readSize = 0;
939                     if (remaining >= LOGGER_MEMDUMP_CHUNKSIZE) {
940                         readSize = LOGGER_MEMDUMP_CHUNKSIZE;
941                     }
942                     else {
943                         readSize = remaining;
944                     }
945                     numRecordsRead = fread(buffer, 1,
946                                            readSize, memDumpFilePtr);
947                     if (numRecordsRead) {
948                         remaining -= readSize;
949                         buffer += readSize;
950                         ALOGV("%s: Read successful for size:%u "
951                               "remaining:%u", __func__, readSize,
952                               remaining);
953                     }
954                     else {
955                         ALOGE("%s: Chunk read failed for size:%u",
956                               __func__, readSize);
957                         break;
958                     }
959                 }
960             }
961 
962             /* After successful read, call the callback handler*/
963             if (mHandler.on_firmware_memory_dump) {
964                 mHandler.on_firmware_memory_dump(memBuffer,
965                                                  memDumpSize);
966 
967             }
968         }
969         break;
970 
971         default :
972             ALOGE("%s: Wrong Wifi Logger subcmd response received %d",
973                 __FUNCTION__, mSubcmd);
974     }
975 
976     /* free the allocated memory */
977     if (memBuffer) {
978         free(memBuffer);
979     }
980     if (memDumpFilePtr) {
981         fclose(memDumpFilePtr);
982     }
983     return NL_SKIP;
984 }
985 
986 /* This function will be the main handler for incoming (from driver)
987  * WIFI_LOGGER_SUBCMD.
988  * Calls the appropriate callback handler after parsing the vendor data.
989  */
handleEvent(WifiEvent & event)990 int WifiLoggerCommand::handleEvent(WifiEvent &event)
991 {
992     WifiVendorCommand::handleEvent(event);
993 
994     switch(mSubcmd)
995     {
996        default:
997            /* Error case should not happen print log */
998            ALOGE("%s: Wrong subcmd received %d", __func__, mSubcmd);
999            break;
1000     }
1001 
1002 cleanup:
1003     return NL_SKIP;
1004 }
1005 
setCallbackHandler(WifiLoggerCallbackHandler nHandler)1006 int WifiLoggerCommand::setCallbackHandler(WifiLoggerCallbackHandler nHandler)
1007 {
1008     int res = 0;
1009     mHandler = nHandler;
1010     res = registerVendorHandler(mVendor_id, mSubcmd);
1011     if (res != 0) {
1012         ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
1013               __FUNCTION__, mVendor_id, mSubcmd);
1014     }
1015     return res;
1016 }
1017 
unregisterHandler(u32 subCmd)1018 void WifiLoggerCommand::unregisterHandler(u32 subCmd)
1019 {
1020     unregisterVendorHandler(mVendor_id, subCmd);
1021 }
1022 
timed_wait(u16 wait_time)1023 int WifiLoggerCommand::timed_wait(u16 wait_time)
1024 {
1025     struct timespec absTime;
1026     int res;
1027     absTime.tv_sec = wait_time;
1028     absTime.tv_nsec = 0;
1029     return mCondition.wait(absTime);
1030 }
1031 
waitForRsp(bool wait)1032 void WifiLoggerCommand::waitForRsp(bool wait)
1033 {
1034     mWaitforRsp = wait;
1035 }
1036 
1037