03ed87fd370e3c6c6228a5f7d5388baa0c44089f
[GitHub/LineageOS/android_hardware_samsung_slsi_scsc_wifibt_wifi_hal.git] / wifi_logger.cpp
1 #include <stdint.h>
2 #include <fcntl.h>
3 #include <sys/socket.h>
4 #include <netlink/genl/genl.h>
5 #include <netlink/genl/family.h>
6 #include <netlink/genl/ctrl.h>
7 #include <linux/rtnetlink.h>
8 #include <netpacket/packet.h>
9 #include <linux/filter.h>
10 #include <linux/errqueue.h>
11
12 #include <linux/pkt_sched.h>
13 #include <netlink/object-api.h>
14 #include <netlink/netlink.h>
15 #include <netlink/socket.h>
16 #include <netlink-private/object-api.h>
17 #include <netlink-private/types.h>
18
19 #include "nl80211_copy.h"
20 #include "sync.h"
21
22 #define LOG_TAG "WifiHAL"
23
24 #include <utils/Log.h>
25
26 #include "wifi_hal.h"
27 #include "common.h"
28 #include "cpp_bindings.h"
29
30 /* using namespace android; */
31
32 typedef enum {
33 ENHANCE_LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
34 ENHANCE_LOGGER_TRIGGER_FW_MEM_DUMP,
35 ENHANCE_LOGGER_GET_FW_MEM_DUMP,
36 ENHANCE_LOGGER_GET_VER,
37 ENHANCE_LOGGER_GET_RING_STATUS,
38 ENHANCE_LOGGER_GET_RING_DATA,
39 ENHANCE_LOGGER_GET_FEATURE,
40 ENHANCE_LOGGER_RESET_LOGGING,
41 ENHANCE_LOGGER_TRIGGER_DRIVER_MEM_DUMP,
42 ENHANCE_LOGGER_GET_DRIVER_MEM_DUMP,
43 ENHANCE_LOGGER_START_PKT_FATE_MONITORING,
44 ENHANCE_LOGGER_GET_TX_PKT_FATES,
45 ENHANCE_LOGGER_GET_RX_PKT_FATES,
46 ENHANCE_LOGGER_GET_WAKE_REASON_STATS,
47 } DEBUG_SUB_COMMAND;
48
49 typedef enum {
50 ENHANCE_LOGGER_ATTRIBUTE_DRIVER_VER,
51 ENHANCE_LOGGER_ATTRIBUTE_FW_VER,
52 ENHANCE_LOGGER_ATTRIBUTE_RING_ID,
53 ENHANCE_LOGGER_ATTRIBUTE_RING_NAME,
54 ENHANCE_LOGGER_ATTRIBUTE_RING_FLAGS,
55 ENHANCE_LOGGER_ATTRIBUTE_LOG_LEVEL,
56 ENHANCE_LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
57 ENHANCE_LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
58 ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN,
59 ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA,
60 // LOGGER_ATTRIBUTE_FW_ERR_CODE,
61 ENHANCE_LOGGER_ATTRIBUTE_RING_DATA,
62 ENHANCE_LOGGER_ATTRIBUTE_RING_STATUS,
63 ENHANCE_LOGGER_ATTRIBUTE_RING_NUM,
64 ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
65 ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
66 ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM,
67 ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA,
68 //Attributes for data used by wake stats subcmd.
69 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_INVALID = 0,
70 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_CMD_EVENT_WAKE,
71 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR,
72 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ,
73 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE,
74 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR,
75 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ,
76 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_RX_DATA_WAKE,
77 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_UNICAST_CNT,
78 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_MULTICAST_CNT,
79 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_BROADCAST_CNT,
80 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP_PKT,
81 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_PKT,
82 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RA,
83 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NA,
84 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NS,
85 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP4_RX_MULTICAST_CNT,
86 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RX_MULTICAST_CNT,
87 ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_OTHER_RX_MULTICAST_CNT,
88 } ENHANCE_LOGGER_ATTRIBUTE;
89
90 typedef enum {
91 DEBUG_OFF = 0,
92 DEBUG_NORMAL,
93 DEBUG_VERBOSE,
94 DEBUG_VERY,
95 DEBUG_VERY_VERY,
96 } ENHANCE_LOGGER_LEVEL;
97
98 typedef enum {
99 GET_FW_VER,
100 GET_DRV_VER,
101 GET_RING_DATA,
102 GET_RING_STATUS,
103 GET_FEATURE,
104 START_RING_LOG,
105 GET_FW_DUMP,
106 GET_DRIVER_DUMP,
107 } GetCmdType;
108
109 typedef enum {
110 PACKET_MONITOR_START,
111 TX_PACKET_FATE,
112 RX_PACKET_FATE,
113 } PktFateReqType;
114
115 class DebugCommand : public WifiCommand
116 {
117 char *mBuff = NULL;
118 int *mBuffSize = NULL;
119 u32 *mNumRings = NULL;
120 wifi_ring_buffer_status *mStatus = NULL;
121 unsigned int *mSupport = NULL;
122 u32 mVerboseLevel = 0;
123 u32 mFlags = 0;
124 u32 mMaxIntervalSec = 0;
125 u32 mMinDataSize = 0;
126 char *mRingName = NULL;
127 GetCmdType mType;
128
129 public:
130
131 // constructor for get version
132 DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,
133 GetCmdType cmdType)
134 : WifiCommand(iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
135 (cmdType)
136 {
137 memset(mBuff, 0, *mBuffSize);
138 }
139
140 // constructor for ring data
141 DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
142 : WifiCommand(iface, 0), mRingName(ring_name), mType(cmdType)
143 { }
144
145 // constructor for ring status
146 DebugCommand(wifi_interface_handle iface, u32 *num_rings,
147 wifi_ring_buffer_status *status, GetCmdType cmdType)
148 : WifiCommand(iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
149 {
150 memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
151 }
152
153 // constructor for feature set
154 DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
155 : WifiCommand(iface, 0), mSupport(support), mType(cmdType)
156 { }
157
158 // constructor for ring params
159 DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
160 u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)
161 : WifiCommand(iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
162 mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
163 mRingName(ring_name), mType(cmdType)
164 { }
165
166 int createRingRequest(WifiRequest& request) {
167 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_START_LOGGING);
168 if (result != WIFI_SUCCESS) {
169 ALOGE("Failed to create start ring logger request; result = %d", result);
170 return result;
171 }
172
173 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
174
175 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_LOG_LEVEL, mVerboseLevel);
176 if (result != WIFI_SUCCESS) {
177 ALOGE("Failed to put log level; result = %d", result);
178 return result;
179 }
180 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_RING_FLAGS, mFlags);
181 if (result != WIFI_SUCCESS) {
182 ALOGE("Failed to put ring flags; result = %d", result);
183 return result;
184 }
185 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, mMaxIntervalSec);
186 if (result != WIFI_SUCCESS) {
187 ALOGE("Failed to put log time interval; result = %d", result);
188 return result;
189 }
190 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, mMinDataSize);
191 if (result != WIFI_SUCCESS) {
192 ALOGE("Failed to put min data size; result = %d", result);
193 return result;
194 }
195 result = request.put_string(ENHANCE_LOGGER_ATTRIBUTE_RING_NAME, mRingName);
196 if (result != WIFI_SUCCESS) {
197 ALOGE("Failed to put ringbuffer name; result = %d", result);
198 return result;
199 }
200 request.attr_end(data);
201
202 return WIFI_SUCCESS;
203 }
204
205 int createRequest(WifiRequest &request) {
206 int result;
207
208 switch (mType) {
209 case GET_FW_VER:
210 {
211 result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_VER);
212 if (result != WIFI_SUCCESS) {
213 ALOGE("Failed to create get fw version request; result = %d", result);
214 return result;
215 }
216
217 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
218
219 // Driver expecting only attribute type, passing mbuff as data with
220 // length 0 to avoid undefined state
221 result = request.put(ENHANCE_LOGGER_ATTRIBUTE_FW_VER, mBuff, 0);
222 if (result != WIFI_SUCCESS) {
223 ALOGE("Failed to put get fw version request; result = %d", result);
224 return result;
225 }
226 request.attr_end(data);
227 break;
228 }
229
230 case GET_DRV_VER:
231 {
232 result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_VER);
233 if (result != WIFI_SUCCESS) {
234 ALOGE("Failed to create get drv version request; result = %d", result);
235 return result;
236 }
237
238 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
239
240 // Driver expecting only attribute type, passing mbuff as data with
241 // length 0 to avoid undefined state
242 result = request.put(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);
243
244 if (result != WIFI_SUCCESS) {
245 ALOGE("Failed to put get drv version request; result = %d", result);
246 return result;
247 }
248 request.attr_end(data);
249 break;
250 }
251
252 case GET_RING_DATA:
253 {
254 result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_RING_DATA);
255 if (result != WIFI_SUCCESS) {
256 ALOGE("Failed to create get ring data request; result = %d", result);
257 return result;
258 }
259
260 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
261 result = request.put_string(ENHANCE_LOGGER_ATTRIBUTE_RING_NAME, mRingName);
262 if (result != WIFI_SUCCESS) {
263 ALOGE("Failed to put ring data request; result = %d", result);
264 return result;
265 }
266 request.attr_end(data);
267 break;
268 }
269
270 case GET_RING_STATUS:
271 {
272 result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_RING_STATUS);
273 if (result != WIFI_SUCCESS) {
274 ALOGE("Failed to create get ring status request; result = %d", result);
275 return result;
276 }
277 break;
278 }
279
280 case GET_FEATURE:
281 {
282 result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_FEATURE);
283 if (result != WIFI_SUCCESS) {
284 ALOGE("Failed to create get feature request; result = %d", result);
285 return result;
286 }
287 break;
288 }
289
290 case START_RING_LOG:
291 result = createRingRequest(request);
292 break;
293
294 default:
295 ALOGE("Unknown Debug command");
296 result = WIFI_ERROR_UNKNOWN;
297 }
298 return result;
299 }
300
301 int start() {
302 // ALOGD("Start debug command");
303 WifiRequest request(familyId(), ifaceId());
304 int result = createRequest(request);
305 if (result != WIFI_SUCCESS) {
306 ALOGE("Failed to create debug request; result = %d", result);
307 return result;
308 }
309
310 result = requestResponse(request);
311 if (result != WIFI_SUCCESS) {
312 ALOGE("Failed to register debug response; result = %d", result);
313 }
314 return result;
315 }
316
317 virtual int handleResponse(WifiEvent& reply) {
318 ALOGD("In DebugCommand::handleResponse");
319
320 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
321 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
322 return NL_SKIP;
323 }
324
325 switch (mType) {
326 case GET_DRV_VER:
327 case GET_FW_VER:
328 {
329 void *data = reply.get_vendor_data();
330 int len = reply.get_vendor_data_len();
331
332 ALOGD("len = %d, expected len = %d", len, *mBuffSize);
333 memcpy(mBuff, data, min(len, *mBuffSize));
334 if (*mBuffSize < len)
335 return NL_SKIP;
336 *mBuffSize = len;
337 break;
338 }
339
340 case START_RING_LOG:
341 case GET_RING_DATA:
342 break;
343
344 case GET_RING_STATUS:
345 {
346 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
347 int len = reply.get_vendor_data_len();
348 wifi_ring_buffer_status *status(mStatus);
349
350 if (vendor_data == NULL || len == 0) {
351 ALOGE("No Debug data found");
352 return NL_SKIP;
353 }
354
355 nl_iterator it(vendor_data);
356 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_NUM) {
357 unsigned int num_rings = it.get_u32();
358 if (*mNumRings < num_rings) {
359 ALOGE("Not enough status buffers provided, available: %d required: %d",
360 *mNumRings, num_rings);
361 } else {
362 *mNumRings = num_rings;
363 }
364 } else {
365 ALOGE("Unknown attribute: %d expecting %d",
366 it.get_type(), ENHANCE_LOGGER_ATTRIBUTE_RING_NUM);
367 return NL_SKIP;
368 }
369
370 it.next();
371 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_STATUS) {
372 memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status) * (*mNumRings));
373 } else {
374 ALOGW("Ignoring invalid attribute type = %d, size = %d",
375 it.get_type(), it.get_len());
376 }
377 break;
378 }
379
380 case GET_FEATURE:
381 {
382 void *data = reply.get_vendor_data();
383 int len = reply.get_vendor_data_len();
384
385 ALOGD("len = %d, expected len = %d", len, sizeof(unsigned int));
386 memcpy(mSupport, data, sizeof(unsigned int));
387 break;
388 }
389
390 default:
391 ALOGW("Unknown Debug command");
392 }
393 return NL_OK;
394 }
395
396 virtual int handleEvent(WifiEvent& event) {
397 /* NO events! */
398 return NL_SKIP;
399 }
400 };
401
402 /* API to get supportable feature */
403 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
404 unsigned int *support)
405 {
406 if (support) {
407 DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);
408 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
409 wifi_error result = (wifi_error)cmd->start();
410 cmd->releaseRef();
411 return result;
412 } else {
413 ALOGE("Get support buffer NULL");
414 return WIFI_ERROR_INVALID_ARGS;
415 }
416 }
417
418 /* API to get the status of all ring buffers supported by driver */
419 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
420 u32 *num_rings, wifi_ring_buffer_status *status)
421 {
422 if (status && num_rings) {
423 DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);
424 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
425 wifi_error result = (wifi_error)cmd->start();
426 cmd->releaseRef();
427 return result;
428 } else {
429 ALOGE("Ring status buffer NULL");
430 return WIFI_ERROR_INVALID_ARGS;
431 }
432 }
433
434 /* API to collect driver records */
435 wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)
436 {
437 DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);
438 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
439 wifi_error result = (wifi_error)cmd->start();
440 cmd->releaseRef();
441 return result;
442 }
443
444 wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
445 u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
446 {
447 if (ring_name) {
448 DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
449 min_data_size, ring_name, START_RING_LOG);
450 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
451 wifi_error result = (wifi_error)cmd->start();
452 cmd->releaseRef();
453 return result;
454 } else {
455 ALOGE("Ring name NULL");
456 return WIFI_ERROR_INVALID_ARGS;
457 }
458 }
459
460 /* API to collect a firmware version string */
461 wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
462 int buffer_size)
463 {
464 if (buffer && (buffer_size > 0)) {
465 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);
466 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
467 wifi_error result = (wifi_error)cmd->start();
468 cmd->releaseRef();
469 return result;
470 } else {
471 ALOGE("FW version buffer NULL");
472 return WIFI_ERROR_INVALID_ARGS;
473 }
474 }
475
476 /* API to collect a driver version string */
477 wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
478 {
479 if (buffer && (buffer_size > 0)) {
480 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);
481 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
482 wifi_error result = (wifi_error)cmd->start();
483 cmd->releaseRef();
484 return result;
485 } else {
486 ALOGE("Driver version buffer NULL");
487 return WIFI_ERROR_INVALID_ARGS;
488 }
489 }
490
491
492 ///////////////////////////////////////////////////////////////////////////////
493 class SetLogHandler : public WifiCommand
494 {
495 wifi_ring_buffer_data_handler mHandler;
496
497 public:
498 SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
499 : WifiCommand(iface, id), mHandler(handler)
500 { }
501
502 int start() {
503 ALOGV("Register loghandler");
504 registerVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_RING_EVENT);
505 return WIFI_SUCCESS;
506 }
507
508 virtual int cancel() {
509 /* Send a command to driver to stop generating logging events */
510 ALOGV("Clear loghandler");
511
512 /* unregister event handler */
513 unregisterVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_RING_EVENT);
514
515 WifiRequest request(familyId(), ifaceId());
516 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_RESET_LOGGING);
517 if (result != WIFI_SUCCESS) {
518 ALOGE("failed to create reset request; result = %d", result);
519 return result;
520 }
521
522 result = requestResponse(request);
523 if (result != WIFI_SUCCESS) {
524 ALOGE("failed to request reset; result = %d", result);
525 return result;
526 }
527
528 ALOGD("Success to clear loghandler");
529 return WIFI_SUCCESS;
530 }
531
532 virtual int handleEvent(WifiEvent& event) {
533 char *buffer = NULL;
534 int buffer_size = 0;
535
536 // ALOGD("In SetLogHandler::handleEvent");
537 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
538 int len = event.get_vendor_data_len();
539 int event_id = event.get_vendor_subcmd();
540 // ALOGI("Got Logger event: %d", event_id);
541
542 if (vendor_data == NULL || len == 0) {
543 ALOGE("No Debug data found");
544 return NL_SKIP;
545 }
546
547 if(event_id == ENHANCE_LOGGER_RING_EVENT) {
548 wifi_ring_buffer_status status;
549 memset(&status, 0, sizeof(status));
550
551 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
552 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_STATUS) {
553 memcpy(&status, it.get_data(), sizeof(status));
554 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_DATA) {
555 buffer_size = it.get_len();
556 buffer = (char *)it.get_data();
557 } else {
558 ALOGW("Ignoring invalid attribute type = %d, size = %d",
559 it.get_type(), it.get_len());
560 }
561 }
562
563 // ALOGI("Retrieved Debug data");
564 if (mHandler.on_ring_buffer_data) {
565 (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,
566 &status);
567 }
568 } else {
569 ALOGE("Unknown Event");
570 return NL_SKIP;
571 }
572 return NL_OK;
573 }
574 };
575
576 wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
577 wifi_ring_buffer_data_handler handler)
578 {
579 wifi_handle handle = getWifiHandle(iface);
580 ALOGV("Loghandler start, handle = %p", handle);
581
582 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
583 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
584 wifi_error result = wifi_register_cmd(handle, id, cmd);
585 if (result != WIFI_SUCCESS) {
586 cmd->releaseRef();
587 return result;
588 }
589 result = (wifi_error)cmd->start();
590 if (result != WIFI_SUCCESS) {
591 wifi_unregister_cmd(handle, id);
592 cmd->releaseRef();
593 return result;
594 }
595 return result;
596 }
597
598 wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
599 {
600 wifi_handle handle = getWifiHandle(iface);
601 ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
602
603 if (id == -1) {
604 wifi_ring_buffer_data_handler handler;
605 memset(&handler, 0, sizeof(handler));
606
607 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
608 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
609 cmd->cancel();
610 cmd->releaseRef();
611 return WIFI_SUCCESS;
612 }
613
614 return wifi_cancel_cmd(id, iface);
615 }
616
617 ///////////////////////////////////////////////////////////////////////////////
618 class SetAlertHandler : public WifiCommand
619 {
620 wifi_alert_handler mHandler;
621 int mBuffSize;
622 char *mBuff;
623 int mErrCode;
624
625 public:
626 SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)
627 : WifiCommand(iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),
628 mErrCode(0)
629 { }
630
631 int start() {
632 ALOGV("Start Alerting");
633 registerVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);
634 return WIFI_SUCCESS;
635 }
636
637 virtual int cancel() {
638 ALOGV("Clear alerthandler");
639
640 /* unregister alert handler */
641 unregisterVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);
642 wifi_unregister_cmd(wifiHandle(), id());
643 ALOGD("Success to clear alerthandler");
644 return WIFI_SUCCESS;
645 }
646
647 virtual int handleResponse(WifiEvent& reply) {
648 ALOGD("In SetAlertHandler::handleResponse");
649
650 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
651 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
652 return NL_SKIP;
653 }
654
655 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
656 int len = reply.get_vendor_data_len();
657
658 ALOGD("len = %d", len);
659 if (vendor_data == NULL || len == 0) {
660 ALOGE("no vendor data in memory dump response; ignoring it");
661 return NL_SKIP;
662 }
663
664 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
665 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
666 ALOGI("Initiating alert callback");
667 if (mHandler.on_alert) {
668 (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
669 }
670 if (mBuff) {
671 free(mBuff);
672 mBuff = NULL;
673 }
674 }
675 }
676 return NL_OK;
677 }
678
679 virtual int handleEvent(WifiEvent& event) {
680 wifi_ring_buffer_id ring_id;
681 char *buffer = NULL;
682 int buffer_size = 0;
683
684
685 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
686 int len = event.get_vendor_data_len();
687 int event_id = event.get_vendor_subcmd();
688 ALOGI("Got event: %d", event_id);
689
690 if (vendor_data == NULL || len == 0) {
691 ALOGE("No Debug data found");
692 return NL_SKIP;
693 }
694
695 if (event_id == ENHANCE_LOGGER_MEM_DUMP_EVENT) {
696 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
697 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
698 mBuffSize = it.get_u32();
699 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_DATA) {
700 buffer_size = it.get_len();
701 buffer = (char *)it.get_data();
702 /*
703 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_ERR_CODE) {
704 mErrCode = it.get_u32();
705 */
706 } else {
707 ALOGW("Ignoring invalid attribute type = %d, size = %d",
708 it.get_type(), it.get_len());
709 }
710 }
711 if (mBuffSize) {
712 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
713 if (mBuff) free(mBuff);
714 mBuff = (char *)malloc(mBuffSize + buffer_size);
715 if (!mBuff) {
716 ALOGE("Buffer allocation failed");
717 return NL_SKIP;
718 }
719 memcpy(mBuff, buffer, buffer_size);
720
721 WifiRequest request(familyId(), ifaceId());
722 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);
723 if (result != WIFI_SUCCESS) {
724 ALOGE("Failed to create get memory dump request; result = %d", result);
725 free(mBuff);
726 return NL_SKIP;
727 }
728 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
729 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
730 if (result != WIFI_SUCCESS) {
731 ALOGE("Failed to put get memory dump request; result = %d", result);
732 return result;
733 }
734
735 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA,
736 (uint64_t)(mBuff+buffer_size));
737 if (result != WIFI_SUCCESS) {
738 ALOGE("Failed to put get memory dump request; result = %d", result);
739 return result;
740 }
741
742 request.attr_end(data);
743 mBuffSize += buffer_size;
744
745 result = requestResponse(request);
746
747 if (result != WIFI_SUCCESS) {
748 ALOGE("Failed to register get momory dump response; result = %d", result);
749 }
750 } else {
751 ALOGE("dump event missing dump length attribute");
752 return NL_SKIP;
753 }
754 }
755 return NL_OK;
756 }
757 };
758
759 wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
760 wifi_alert_handler handler)
761 {
762 wifi_handle handle = getWifiHandle(iface);
763 ALOGV("Alerthandler start, handle = %p", handle);
764
765 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
766 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
767 wifi_error result = wifi_register_cmd(handle, id, cmd);
768 if (result != WIFI_SUCCESS) {
769 cmd->releaseRef();
770 return result;
771 }
772 result = (wifi_error)cmd->start();
773 if (result != WIFI_SUCCESS) {
774 wifi_unregister_cmd(handle, id);
775 cmd->releaseRef();
776 return result;
777 }
778 return result;
779 }
780
781 wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)
782 {
783 wifi_handle handle = getWifiHandle(iface);
784 ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);
785
786 if (id == -1) {
787 wifi_alert_handler handler;
788 memset(&handler, 0, sizeof(handler));
789
790 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
791 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
792 cmd->cancel();
793 cmd->releaseRef();
794 return WIFI_SUCCESS;
795 }
796
797 return wifi_cancel_cmd(id, iface);
798 }
799
800
801 class PacketFateCommand: public WifiCommand
802 {
803 void *mReportBufs = NULL;
804 size_t mNoReqFates = 0;
805 size_t *mNoProvidedFates = NULL;
806 PktFateReqType mReqType;
807
808 public:
809 PacketFateCommand(wifi_interface_handle handle)
810 : WifiCommand(handle, 0), mReqType(PACKET_MONITOR_START)
811 { }
812
813 PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
814 size_t n_requested_fates, size_t *n_provided_fates)
815 : WifiCommand(handle, 0), mReportBufs(tx_report_bufs),
816 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
817 mReqType(TX_PACKET_FATE)
818 { }
819
820 PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,
821 size_t n_requested_fates, size_t *n_provided_fates)
822 : WifiCommand(handle, 0), mReportBufs(rx_report_bufs),
823 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
824 mReqType(RX_PACKET_FATE)
825 { }
826
827 int createRequest(WifiRequest& request) {
828 if (mReqType == TX_PACKET_FATE) {
829 ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);
830 return createTxPktFateRequest(request);
831 } else if (mReqType == RX_PACKET_FATE) {
832 ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);
833 return createRxPktFateRequest(request);
834 } else if (mReqType == PACKET_MONITOR_START) {
835 ALOGD("%s Monitor packet fate request\n", __FUNCTION__);
836 return createMonitorPktFateRequest(request);
837 } else {
838 ALOGE("%s Unknown packet fate request\n", __FUNCTION__);
839 return WIFI_ERROR_NOT_SUPPORTED;
840 }
841 return WIFI_SUCCESS;
842 }
843
844 int createMonitorPktFateRequest(WifiRequest& request) {
845 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_START_PKT_FATE_MONITORING);
846 if (result < 0) {
847 return result;
848 }
849
850 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
851 request.attr_end(data);
852 return result;
853 }
854
855 int createTxPktFateRequest(WifiRequest& request) {
856 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_TX_PKT_FATES);
857 if (result < 0) {
858 return result;
859 }
860
861 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));
862 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
863 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
864 if (result < 0) {
865 return result;
866 }
867 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
868 if (result < 0) {
869 return result;
870 }
871 request.attr_end(data);
872 return result;
873 }
874
875 int createRxPktFateRequest(WifiRequest& request) {
876 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_RX_PKT_FATES);
877 if (result < 0) {
878 return result;
879 }
880
881 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));
882 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
883 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
884 if (result < 0) {
885 return result;
886 }
887 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
888 if (result < 0) {
889 return result;
890 }
891 request.attr_end(data);
892 return result;
893 }
894
895 int start() {
896 ALOGD("Start get packet fate command\n");
897 WifiRequest request(familyId(), ifaceId());
898
899 int result = createRequest(request);
900 if (result < 0) {
901 ALOGE("Failed to create get pkt fate request; result = %d\n", result);
902 return result;
903 }
904
905 result = requestResponse(request);
906 if (result != WIFI_SUCCESS) {
907 ALOGE("Failed to register get pkt fate response; result = %d\n", result);
908 }
909 return result;
910 }
911
912 int handleResponse(WifiEvent& reply) {
913 ALOGD("In GetPktFateCommand::handleResponse\n");
914
915 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
916 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
917 return NL_SKIP;
918 }
919
920 int id = reply.get_vendor_id();
921 int subcmd = reply.get_vendor_subcmd();
922 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
923 int len = reply.get_vendor_data_len();
924
925 ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
926
927 if (mReqType == TX_PACKET_FATE) {
928 ALOGI("Response recieved for get TX pkt fate command\n");
929 } else if (mReqType == RX_PACKET_FATE) {
930 ALOGI("Response recieved for get RX pkt fate command\n");
931 } else if (mReqType == PACKET_MONITOR_START) {
932 ALOGI("Response recieved for monitor pkt fate command\n");
933 return NL_OK;
934 } else {
935 ALOGE("Response recieved for unknown pkt fate command\n");
936 return NL_SKIP;
937 }
938
939 if (vendor_data == NULL || len == 0) {
940 ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
941 return NL_SKIP;
942 }
943
944 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
945 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
946 *mNoProvidedFates = it.get_u32();
947 ALOGI("No: of pkt fates provided is %d\n", *mNoProvidedFates);
948 } else {
949 ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
950 it.get_type(), it.get_len());
951 }
952 }
953
954 return NL_OK;
955 }
956
957 int handleEvent(WifiEvent& event) {
958 /* NO events to handle here! */
959 return NL_SKIP;
960 }
961 };
962
963 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
964 {
965 PacketFateCommand *cmd = new PacketFateCommand(handle);
966 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
967 wifi_error result = (wifi_error)cmd->start();
968 cmd->releaseRef();
969 return result;
970 }
971
972 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
973 wifi_tx_report *tx_report_bufs, size_t n_requested_fates,
974 size_t *n_provided_fates)
975 {
976 PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,
977 n_requested_fates, n_provided_fates);
978 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
979 wifi_error result = (wifi_error)cmd->start();
980 cmd->releaseRef();
981 memset(tx_report_bufs, 0, (n_requested_fates * sizeof(wifi_tx_report)));
982 return result;
983 }
984
985 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
986 wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
987 size_t *n_provided_fates)
988 {
989 PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
990 n_requested_fates, n_provided_fates);
991 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
992 wifi_error result = (wifi_error)cmd->start();
993 cmd->releaseRef();
994 memset(rx_report_bufs, 0, (n_requested_fates * sizeof(wifi_rx_report)));
995 return result;
996 }
997
998 class MemoryDumpCommand: public WifiCommand
999 {
1000 wifi_firmware_memory_dump_handler mHandler;
1001 wifi_driver_memory_dump_callbacks mcallback;
1002 int mBuffSize;
1003 char *mBuff;
1004 GetCmdType mType;
1005
1006 public:
1007 MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler, GetCmdType cmdtype )
1008 : WifiCommand(iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL), mType(cmdtype)
1009 {
1010 memset(&mcallback, 0, sizeof(wifi_driver_memory_dump_callbacks));
1011 }
1012
1013 MemoryDumpCommand(wifi_interface_handle iface, wifi_driver_memory_dump_callbacks callback, GetCmdType cmdtype)
1014 : WifiCommand(iface, 0), mcallback(callback), mBuffSize(0), mBuff(NULL), mType(cmdtype)
1015 {
1016 memset(&mHandler, 0, sizeof(wifi_firmware_memory_dump_handler));
1017 }
1018
1019 int createRequest(WifiRequest &request) {
1020 int result;
1021
1022 switch (mType) {
1023 case GET_FW_DUMP:
1024 {
1025 result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_TRIGGER_FW_MEM_DUMP);
1026 if (result != WIFI_SUCCESS) {
1027 ALOGE("Failed to create trigger fw memory dump request; result = %d", result);
1028 return result;
1029 }
1030 break;
1031 }
1032 case GET_DRIVER_DUMP :
1033 {
1034 result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_TRIGGER_DRIVER_MEM_DUMP);
1035 if (result != WIFI_SUCCESS) {
1036 ALOGE("Failed to create trigger driver memory dump request; result = %d", result);
1037 return result;
1038 }
1039 break;
1040 }
1041 default:
1042 ALOGE("Unknown Debug command");
1043 result = WIFI_ERROR_UNKNOWN;
1044 }
1045 return result;
1046 }
1047 int start() {
1048 ALOGD("Start memory dump command");
1049 WifiRequest request(familyId(), ifaceId());
1050
1051 int result = createRequest(request);
1052 if (result != WIFI_SUCCESS) {
1053 ALOGE("Failed to create trigger memory dump request; result = %d", result);
1054 return result;
1055 }
1056
1057 result = requestResponse(request);
1058 if (result != WIFI_SUCCESS) {
1059 ALOGE("Failed to register trigger memory dump response; result = %d", result);
1060 }
1061 return result;
1062 }
1063
1064 virtual int handleResponse(WifiEvent& reply) {
1065 ALOGD("In MemoryDumpCommand::handleResponse");
1066
1067 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1068 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1069 return NL_SKIP;
1070 }
1071
1072 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1073 int len = reply.get_vendor_data_len();
1074
1075 ALOGD("len = %d", len);
1076 if (vendor_data == NULL || len == 0) {
1077 ALOGE("no vendor data in memory dump response; ignoring it");
1078 return NL_SKIP;
1079 }
1080 switch(mType) {
1081 case GET_FW_DUMP:
1082 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1083 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
1084 mBuffSize = it.get_u32();
1085 if (mBuff)
1086 free(mBuff);
1087 mBuff = (char *)malloc(mBuffSize);
1088 if (!mBuff) {
1089 ALOGE("Buffer allocation failed");
1090 return NL_SKIP;
1091 }
1092 WifiRequest request(familyId(), ifaceId());
1093 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_FW_MEM_DUMP);
1094 if (result != WIFI_SUCCESS) {
1095 ALOGE("Failed to create get fw memory dump request; result = %d", result);
1096 free(mBuff);
1097 return NL_SKIP;
1098 }
1099 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1100 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
1101 if (result != WIFI_SUCCESS) {
1102 ALOGE("Failed to put get fw memory dump request; result = %d", result);
1103 return result;
1104 }
1105 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);
1106 if (result != WIFI_SUCCESS) {
1107 ALOGE("Failed to put get fw memory dump request; result = %d", result);
1108 return result;
1109 }
1110 request.attr_end(data);
1111 result = requestResponse(request);
1112 if (result != WIFI_SUCCESS) {
1113 ALOGE("Failed to register get fw momory dump response; result = %d", result);
1114 }
1115 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
1116 ALOGI("Initiating memory dump callback");
1117 if (mHandler.on_firmware_memory_dump) {
1118 (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);
1119 }
1120 if (mBuff) {
1121 free(mBuff);
1122 mBuff = NULL;
1123 }
1124 } else {
1125 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1126 it.get_type(), it.get_len());
1127 }
1128 }
1129 case GET_DRIVER_DUMP :
1130 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1131 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN) {
1132 mBuffSize = it.get_u32();
1133 if (mBuff)
1134 free(mBuff);
1135 mBuff = (char *)malloc(mBuffSize);
1136 if (!mBuff) {
1137 ALOGE("Buffer allocation failed");
1138 return NL_SKIP;
1139 }
1140 WifiRequest request(familyId(), ifaceId());
1141 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_DRIVER_MEM_DUMP);
1142 if (result != WIFI_SUCCESS) {
1143 ALOGE("Failed to create get driver memory dump request; result = %d", result);
1144 free(mBuff);
1145 return NL_SKIP;
1146 }
1147 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1148 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN, mBuffSize);
1149 if (result != WIFI_SUCCESS) {
1150 ALOGE("Failed to put get driver memory dump request; result = %d", result);
1151 return result;
1152 }
1153 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA, (uint64_t)mBuff);
1154 if (result != WIFI_SUCCESS) {
1155 ALOGE("Failed to put get driver memory dump request; result = %d", result);
1156 return result;
1157 }
1158 request.attr_end(data);
1159 result = requestResponse(request);
1160 if (result != WIFI_SUCCESS) {
1161 ALOGE("Failed to register get driver momory dump response; result = %d", result);
1162 }
1163 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA) {
1164 ALOGI("Initiating memory dump callback");
1165 if (mcallback.on_driver_memory_dump) {
1166 (*mcallback.on_driver_memory_dump)(mBuff, mBuffSize);
1167 }
1168 if (mBuff) {
1169 free(mBuff);
1170 mBuff = NULL;
1171 }
1172 } else {
1173 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1174 it.get_type(), it.get_len());
1175 }
1176 }
1177 }
1178 return NL_OK;
1179 }
1180
1181 virtual int handleEvent(WifiEvent& event) {
1182 /* NO events! */
1183 return NL_SKIP;
1184 }
1185 };
1186
1187 /* API to collect a firmware memory dump for a given iface */
1188 wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
1189 wifi_firmware_memory_dump_handler handler)
1190 {
1191 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler, GET_FW_DUMP);
1192 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1193 wifi_error result = (wifi_error)cmd->start();
1194 cmd->releaseRef();
1195 return result;
1196 }
1197
1198 wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface,
1199 wifi_driver_memory_dump_callbacks callbacks)
1200 {
1201 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, callbacks, GET_DRIVER_DUMP);
1202 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1203 wifi_error result = (wifi_error)cmd->start();
1204 cmd->releaseRef();
1205 return result;
1206 }
1207 class WifiLoggerCommand: public WifiCommand
1208 {
1209 WLAN_DRIVER_WAKE_REASON_CNT *mGetWakeStats;
1210
1211 public:
1212 WifiLoggerCommand(wifi_interface_handle handle, WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1213 : WifiCommand(handle, 0), mGetWakeStats(wifi_wake_reason_cnt)
1214 { }
1215
1216 int createRequest(WifiRequest& request) {
1217 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_WAKE_REASON_STATS);
1218 if (result < 0) {
1219 return result;
1220 }
1221
1222 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1223
1224 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ, mGetWakeStats->cmd_event_wake_cnt_sz);
1225 if (result != WIFI_SUCCESS) {
1226 ALOGE("Failed to put wake_cnt_sz; result = %d", result);
1227 return result;
1228 }
1229 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ, mGetWakeStats->driver_fw_local_wake_cnt_sz);
1230 if (result != WIFI_SUCCESS) {
1231 ALOGE("Failed to put driver_fw_local_wake_cnt; result = %d", result);
1232 return result;
1233 }
1234 request.attr_end(data);
1235 return result;
1236 }
1237
1238 int start() {
1239 ALOGD("Start get wake reason stats command\n");
1240 WifiRequest request(familyId(), ifaceId());
1241 int result = createRequest(request);
1242 if (result < 0) {
1243 ALOGE("Failed to create get wake reason stats request; result = %d\n", result);
1244 return result;
1245 }
1246 result = requestResponse(request);
1247 if (result != WIFI_SUCCESS) {
1248 ALOGE("Failed to register get wake reason stats response; result = %d\n", result);
1249 }
1250 return result;
1251 }
1252
1253 int handleResponse(WifiEvent& reply) {
1254 int len = 0;
1255 ALOGD("In WifiLoggerCommand::handleResponse\n");
1256
1257 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1258 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
1259 return NL_SKIP;
1260 }
1261 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1262 len = reply.get_vendor_data_len();
1263 if (vendor_data == NULL || len == 0) {
1264 ALOGE("No Debug data found");
1265 return NL_SKIP;
1266 }
1267 nl_iterator it(vendor_data);
1268
1269 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_CMD_EVENT_WAKE) {
1270 ALOGE("TOTAL_CMD_EVENT_WAKE not found %d", it.get_type());
1271 return NL_SKIP;
1272 }
1273
1274 mGetWakeStats->total_cmd_event_wake = it.get_u32();
1275 it.next();
1276
1277 if(mGetWakeStats->total_cmd_event_wake && mGetWakeStats->cmd_event_wake_cnt) {
1278 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR) {
1279 ALOGE("CMD_EVENT_WAKE_CNT_PTR not found %d", it.get_type());
1280 return NL_SKIP;
1281 }
1282
1283 len = it.get_len();
1284 mGetWakeStats->cmd_event_wake_cnt_used = (len < mGetWakeStats->cmd_event_wake_cnt_sz) ? len : mGetWakeStats->cmd_event_wake_cnt_sz;
1285 memcpy(mGetWakeStats->cmd_event_wake_cnt, it.get_data(), mGetWakeStats->cmd_event_wake_cnt_used * sizeof(int));
1286 } else {
1287 mGetWakeStats->cmd_event_wake_cnt_used = 0;
1288 }
1289
1290 it.next();
1291
1292 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE) {
1293 ALOGE("TOTAL_DRIVER_FW_LOCAL_WAKE not found %d", it.get_type());
1294 return NL_SKIP;
1295 }
1296
1297 mGetWakeStats->total_driver_fw_local_wake = it.get_u32();
1298 it.next();
1299
1300 if(mGetWakeStats->total_driver_fw_local_wake && mGetWakeStats->driver_fw_local_wake_cnt) {
1301 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR) {
1302 ALOGE("DRIVER_FW_LOCAL_WAKE_CNT_PTR not found %d", it.get_type());
1303 return NL_SKIP;
1304 }
1305
1306 len = it.get_len();
1307 mGetWakeStats->driver_fw_local_wake_cnt_used= (len < mGetWakeStats->driver_fw_local_wake_cnt_sz) ? len : mGetWakeStats->driver_fw_local_wake_cnt_sz;
1308 memcpy(mGetWakeStats->driver_fw_local_wake_cnt, it.get_data(), mGetWakeStats->driver_fw_local_wake_cnt_used * sizeof(int));
1309 } else {
1310 mGetWakeStats->driver_fw_local_wake_cnt_used= 0;
1311 }
1312
1313 it.next();
1314
1315 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_RX_DATA_WAKE) {
1316 ALOGE("TOTAL_RX_DATA_WAKE not found %d", it.get_type());
1317 return NL_SKIP;
1318 }
1319
1320 mGetWakeStats->total_rx_data_wake = it.get_u32();
1321 it.next();
1322
1323 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_UNICAST_CNT) {
1324 ALOGE("RX_UNICAST_CNT not found %d", it.get_type());
1325 return NL_SKIP;
1326 }
1327
1328 mGetWakeStats->rx_wake_details.rx_unicast_cnt = it.get_u32();
1329 it.next();
1330
1331 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_MULTICAST_CNT) {
1332 ALOGE("RX_MULTICAST_CNT not found %d", it.get_type());
1333 return NL_SKIP;
1334 }
1335
1336 mGetWakeStats->rx_wake_details.rx_multicast_cnt = it.get_u32();
1337 it.next();
1338
1339 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_BROADCAST_CNT) {
1340 ALOGE("RX_BROADCAST_CNT not found %d", it.get_type());
1341 return NL_SKIP;
1342 }
1343
1344 mGetWakeStats->rx_wake_details.rx_broadcast_cnt = it.get_u32();
1345 it.next();
1346
1347 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP_PKT) {
1348 ALOGE("ICMP_PKT not found %d", it.get_type());
1349 return NL_SKIP;
1350 }
1351
1352 mGetWakeStats->rx_wake_pkt_classification_info .icmp_pkt = it.get_u32();
1353 it.next();
1354
1355 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_PKT) {
1356 ALOGE("ICMP6_PKT not found %d", it.get_type());
1357 return NL_SKIP;
1358 }
1359
1360 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_pkt = it.get_u32();
1361 it.next();
1362
1363 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RA) {
1364 ALOGE("ICMP6_RA not found %d", it.get_type());
1365 return NL_SKIP;
1366 }
1367
1368 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ra = it.get_u32();
1369 it.next();
1370
1371 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NA) {
1372 ALOGE("ICMP6_NA not found %d", it.get_type());
1373 return NL_SKIP;
1374 }
1375
1376 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_na = it.get_u32();
1377 it.next();
1378
1379 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NS) {
1380 ALOGE("ICMP6_NS not found %d", it.get_type());
1381 return NL_SKIP;
1382 }
1383
1384 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ns = it.get_u32();
1385 it.next();
1386
1387 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP4_RX_MULTICAST_CNT) {
1388 ALOGE("ICMP4_RX_MULTICAST_CNT not found %d", it.get_type());
1389 return NL_SKIP;
1390 }
1391
1392 mGetWakeStats->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt = it.get_u32();
1393 it.next();
1394
1395 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RX_MULTICAST_CNT) {
1396 ALOGE("ICMP6_RX_MULTICAST_CNT not found %d", it.get_type());
1397 return NL_SKIP;
1398 }
1399
1400 mGetWakeStats->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt = it.get_u32();
1401 it.next();
1402
1403 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_OTHER_RX_MULTICAST_CNT) {
1404 ALOGE("OTHER_RX_MULTICAST_CNT not found %d", it.get_type());
1405 return NL_SKIP;
1406 }
1407
1408 mGetWakeStats->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt = it.get_u32();
1409
1410 return NL_OK;
1411 }
1412
1413 int handleEvent(WifiEvent& event) {
1414 /* NO events to handle here! */
1415 return NL_SKIP;
1416 }
1417 };
1418
1419 /* Function to get wake lock stats */
1420 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
1421 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1422 {
1423 if(wifi_wake_reason_cnt) {
1424 WifiLoggerCommand *cmd = new WifiLoggerCommand(iface,wifi_wake_reason_cnt);
1425 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1426 wifi_error result = (wifi_error)cmd->start();
1427 cmd->releaseRef();
1428 return result;
1429 } else {
1430 ALOGE("Reason cnt NULL");
1431 return WIFI_ERROR_INVALID_ARGS;
1432 }
1433 }
1434