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