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