[9610][7885] wlbt :Revert setScanningMacOui support as feature and only pass VTS.
[GitHub/MotorolaMobilityLLC/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 return result;
982 }
983
984 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
985 wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
986 size_t *n_provided_fates)
987 {
988 PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
989 n_requested_fates, n_provided_fates);
990 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
991 wifi_error result = (wifi_error)cmd->start();
992 cmd->releaseRef();
993 return result;
994 }
995
996 class MemoryDumpCommand: public WifiCommand
997 {
998 wifi_firmware_memory_dump_handler mHandler;
999 wifi_driver_memory_dump_callbacks mcallback;
1000 int mBuffSize;
1001 char *mBuff;
1002 GetCmdType mType;
1003
1004 public:
1005 MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler, GetCmdType cmdtype )
1006 : WifiCommand(iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL), mType(cmdtype)
1007 {
1008 memset(&mHandler,0,sizeof(wifi_firmware_memory_dump_handler));
1009 }
1010
1011 MemoryDumpCommand(wifi_interface_handle iface, wifi_driver_memory_dump_callbacks callback, GetCmdType cmdtype)
1012 : WifiCommand(iface, 0), mcallback(callback), mBuffSize(0), mBuff(NULL), mType(cmdtype)
1013 {
1014 memset(&mcallback,0,sizeof(wifi_driver_memory_dump_callbacks));
1015 }
1016
1017 int createRequest(WifiRequest &request) {
1018 int result;
1019
1020 switch (mType) {
1021 case GET_FW_DUMP:
1022 {
1023 result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_TRIGGER_FW_MEM_DUMP);
1024 if (result != WIFI_SUCCESS) {
1025 ALOGE("Failed to create trigger fw memory dump request; result = %d", result);
1026 return result;
1027 }
1028 break;
1029 }
1030 case GET_DRIVER_DUMP :
1031 {
1032 result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_TRIGGER_DRIVER_MEM_DUMP);
1033 if (result != WIFI_SUCCESS) {
1034 ALOGE("Failed to create trigger driver memory dump request; result = %d", result);
1035 return result;
1036 }
1037 break;
1038 }
1039 default:
1040 ALOGE("Unknown Debug command");
1041 result = WIFI_ERROR_UNKNOWN;
1042 }
1043 return result;
1044 }
1045 int start() {
1046 ALOGD("Start memory dump command");
1047 WifiRequest request(familyId(), ifaceId());
1048
1049 int result = createRequest(request);
1050 if (result != WIFI_SUCCESS) {
1051 ALOGE("Failed to create trigger memory dump request; result = %d", result);
1052 return result;
1053 }
1054
1055 result = requestResponse(request);
1056 if (result != WIFI_SUCCESS) {
1057 ALOGE("Failed to register trigger memory dump response; result = %d", result);
1058 }
1059 return result;
1060 }
1061
1062 virtual int handleResponse(WifiEvent& reply) {
1063 ALOGD("In MemoryDumpCommand::handleResponse");
1064
1065 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1066 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1067 return NL_SKIP;
1068 }
1069
1070 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1071 int len = reply.get_vendor_data_len();
1072
1073 ALOGD("len = %d", len);
1074 if (vendor_data == NULL || len == 0) {
1075 ALOGE("no vendor data in memory dump response; ignoring it");
1076 return NL_SKIP;
1077 }
1078 switch(mType) {
1079 case GET_FW_DUMP:
1080 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1081 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
1082 mBuffSize = it.get_u32();
1083 if (mBuff)
1084 free(mBuff);
1085 mBuff = (char *)malloc(mBuffSize);
1086 if (!mBuff) {
1087 ALOGE("Buffer allocation failed");
1088 return NL_SKIP;
1089 }
1090 WifiRequest request(familyId(), ifaceId());
1091 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_FW_MEM_DUMP);
1092 if (result != WIFI_SUCCESS) {
1093 ALOGE("Failed to create get fw memory dump request; result = %d", result);
1094 free(mBuff);
1095 return NL_SKIP;
1096 }
1097 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1098 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
1099 if (result != WIFI_SUCCESS) {
1100 ALOGE("Failed to put get fw memory dump request; result = %d", result);
1101 return result;
1102 }
1103 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);
1104 if (result != WIFI_SUCCESS) {
1105 ALOGE("Failed to put get fw memory dump request; result = %d", result);
1106 return result;
1107 }
1108 request.attr_end(data);
1109 result = requestResponse(request);
1110 if (result != WIFI_SUCCESS) {
1111 ALOGE("Failed to register get fw momory dump response; result = %d", result);
1112 }
1113 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
1114 ALOGI("Initiating memory dump callback");
1115 if (mHandler.on_firmware_memory_dump) {
1116 (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);
1117 }
1118 if (mBuff) {
1119 free(mBuff);
1120 mBuff = NULL;
1121 }
1122 } else {
1123 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1124 it.get_type(), it.get_len());
1125 }
1126 }
1127 case GET_DRIVER_DUMP :
1128 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1129 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN) {
1130 mBuffSize = it.get_u32();
1131 if (mBuff)
1132 free(mBuff);
1133 mBuff = (char *)malloc(mBuffSize);
1134 if (!mBuff) {
1135 ALOGE("Buffer allocation failed");
1136 return NL_SKIP;
1137 }
1138 WifiRequest request(familyId(), ifaceId());
1139 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_DRIVER_MEM_DUMP);
1140 if (result != WIFI_SUCCESS) {
1141 ALOGE("Failed to create get driver memory dump request; result = %d", result);
1142 free(mBuff);
1143 return NL_SKIP;
1144 }
1145 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1146 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN, mBuffSize);
1147 if (result != WIFI_SUCCESS) {
1148 ALOGE("Failed to put get driver memory dump request; result = %d", result);
1149 return result;
1150 }
1151 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA, (uint64_t)mBuff);
1152 if (result != WIFI_SUCCESS) {
1153 ALOGE("Failed to put get driver memory dump request; result = %d", result);
1154 return result;
1155 }
1156 request.attr_end(data);
1157 result = requestResponse(request);
1158 if (result != WIFI_SUCCESS) {
1159 ALOGE("Failed to register get driver momory dump response; result = %d", result);
1160 }
1161 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA) {
1162 ALOGI("Initiating memory dump callback");
1163 if (mcallback.on_driver_memory_dump) {
1164 (*mcallback.on_driver_memory_dump)(mBuff, mBuffSize);
1165 }
1166 if (mBuff) {
1167 free(mBuff);
1168 mBuff = NULL;
1169 }
1170 } else {
1171 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1172 it.get_type(), it.get_len());
1173 }
1174 }
1175 }
1176 return NL_OK;
1177 }
1178
1179 virtual int handleEvent(WifiEvent& event) {
1180 /* NO events! */
1181 return NL_SKIP;
1182 }
1183 };
1184
1185 /* API to collect a firmware memory dump for a given iface */
1186 wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
1187 wifi_firmware_memory_dump_handler handler)
1188 {
1189 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler, GET_FW_DUMP);
1190 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1191 wifi_error result = (wifi_error)cmd->start();
1192 cmd->releaseRef();
1193 return result;
1194 }
1195
1196 wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface,
1197 wifi_driver_memory_dump_callbacks callbacks)
1198 {
1199 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, callbacks, GET_DRIVER_DUMP);
1200 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1201 wifi_error result = (wifi_error)cmd->start();
1202 cmd->releaseRef();
1203 return result;
1204 }
1205 class WifiLoggerCommand: public WifiCommand
1206 {
1207 WLAN_DRIVER_WAKE_REASON_CNT *mGetWakeStats;
1208
1209 public:
1210 WifiLoggerCommand(wifi_interface_handle handle, WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1211 : WifiCommand(handle, 0), mGetWakeStats(wifi_wake_reason_cnt)
1212 { }
1213
1214 int createRequest(WifiRequest& request) {
1215 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_WAKE_REASON_STATS);
1216 if (result < 0) {
1217 return result;
1218 }
1219
1220 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1221
1222 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ, mGetWakeStats->cmd_event_wake_cnt_sz);
1223 if (result != WIFI_SUCCESS) {
1224 ALOGE("Failed to put wake_cnt_sz; result = %d", result);
1225 return result;
1226 }
1227 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ, mGetWakeStats->driver_fw_local_wake_cnt_sz);
1228 if (result != WIFI_SUCCESS) {
1229 ALOGE("Failed to put driver_fw_local_wake_cnt; result = %d", result);
1230 return result;
1231 }
1232 request.attr_end(data);
1233 return result;
1234 }
1235
1236 int start() {
1237 ALOGD("Start get wake reason stats command\n");
1238 WifiRequest request(familyId(), ifaceId());
1239 int result = createRequest(request);
1240 if (result < 0) {
1241 ALOGE("Failed to create get wake reason stats request; result = %d\n", result);
1242 return result;
1243 }
1244 result = requestResponse(request);
1245 if (result != WIFI_SUCCESS) {
1246 ALOGE("Failed to register get wake reason stats response; result = %d\n", result);
1247 }
1248 return result;
1249 }
1250
1251 int handleResponse(WifiEvent& reply) {
1252 int len = 0;
1253 ALOGD("In WifiLoggerCommand::handleResponse\n");
1254
1255 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1256 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
1257 return NL_SKIP;
1258 }
1259 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1260 len = reply.get_vendor_data_len();
1261 if (vendor_data == NULL || len == 0) {
1262 ALOGE("No Debug data found");
1263 return NL_SKIP;
1264 }
1265 nl_iterator it(vendor_data);
1266
1267 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_CMD_EVENT_WAKE) {
1268 ALOGE("TOTAL_CMD_EVENT_WAKE not found %d", it.get_type());
1269 return NL_SKIP;
1270 }
1271
1272 mGetWakeStats->total_cmd_event_wake = it.get_u32();
1273 it.next();
1274
1275 if(mGetWakeStats->total_cmd_event_wake && mGetWakeStats->cmd_event_wake_cnt) {
1276 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR) {
1277 ALOGE("CMD_EVENT_WAKE_CNT_PTR not found %d", it.get_type());
1278 return NL_SKIP;
1279 }
1280
1281 len = it.get_len();
1282 mGetWakeStats->cmd_event_wake_cnt_used = (len < mGetWakeStats->cmd_event_wake_cnt_sz) ? len : mGetWakeStats->cmd_event_wake_cnt_sz;
1283 memcpy(mGetWakeStats->cmd_event_wake_cnt, it.get_data(), mGetWakeStats->cmd_event_wake_cnt_used * sizeof(int));
1284 } else {
1285 mGetWakeStats->cmd_event_wake_cnt_used = 0;
1286 }
1287
1288 it.next();
1289
1290 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE) {
1291 ALOGE("TOTAL_DRIVER_FW_LOCAL_WAKE not found %d", it.get_type());
1292 return NL_SKIP;
1293 }
1294
1295 mGetWakeStats->total_driver_fw_local_wake = it.get_u32();
1296 it.next();
1297
1298 if(mGetWakeStats->total_driver_fw_local_wake && mGetWakeStats->driver_fw_local_wake_cnt) {
1299 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR) {
1300 ALOGE("DRIVER_FW_LOCAL_WAKE_CNT_PTR not found %d", it.get_type());
1301 return NL_SKIP;
1302 }
1303
1304 len = it.get_len();
1305 mGetWakeStats->driver_fw_local_wake_cnt_used= (len < mGetWakeStats->driver_fw_local_wake_cnt_sz) ? len : mGetWakeStats->driver_fw_local_wake_cnt_sz;
1306 memcpy(mGetWakeStats->driver_fw_local_wake_cnt, it.get_data(), mGetWakeStats->driver_fw_local_wake_cnt_used * sizeof(int));
1307 } else {
1308 mGetWakeStats->driver_fw_local_wake_cnt_used= 0;
1309 }
1310
1311 it.next();
1312
1313 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_RX_DATA_WAKE) {
1314 ALOGE("TOTAL_RX_DATA_WAKE not found %d", it.get_type());
1315 return NL_SKIP;
1316 }
1317
1318 mGetWakeStats->total_rx_data_wake = it.get_u32();
1319 it.next();
1320
1321 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_UNICAST_CNT) {
1322 ALOGE("RX_UNICAST_CNT not found %d", it.get_type());
1323 return NL_SKIP;
1324 }
1325
1326 mGetWakeStats->rx_wake_details.rx_unicast_cnt = it.get_u32();
1327 it.next();
1328
1329 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_MULTICAST_CNT) {
1330 ALOGE("RX_MULTICAST_CNT not found %d", it.get_type());
1331 return NL_SKIP;
1332 }
1333
1334 mGetWakeStats->rx_wake_details.rx_multicast_cnt = it.get_u32();
1335 it.next();
1336
1337 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_BROADCAST_CNT) {
1338 ALOGE("RX_BROADCAST_CNT not found %d", it.get_type());
1339 return NL_SKIP;
1340 }
1341
1342 mGetWakeStats->rx_wake_details.rx_broadcast_cnt = it.get_u32();
1343 it.next();
1344
1345 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP_PKT) {
1346 ALOGE("ICMP_PKT not found %d", it.get_type());
1347 return NL_SKIP;
1348 }
1349
1350 mGetWakeStats->rx_wake_pkt_classification_info .icmp_pkt = it.get_u32();
1351 it.next();
1352
1353 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_PKT) {
1354 ALOGE("ICMP6_PKT not found %d", it.get_type());
1355 return NL_SKIP;
1356 }
1357
1358 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_pkt = it.get_u32();
1359 it.next();
1360
1361 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RA) {
1362 ALOGE("ICMP6_RA not found %d", it.get_type());
1363 return NL_SKIP;
1364 }
1365
1366 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ra = it.get_u32();
1367 it.next();
1368
1369 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NA) {
1370 ALOGE("ICMP6_NA not found %d", it.get_type());
1371 return NL_SKIP;
1372 }
1373
1374 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_na = it.get_u32();
1375 it.next();
1376
1377 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NS) {
1378 ALOGE("ICMP6_NS not found %d", it.get_type());
1379 return NL_SKIP;
1380 }
1381
1382 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ns = it.get_u32();
1383 it.next();
1384
1385 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP4_RX_MULTICAST_CNT) {
1386 ALOGE("ICMP4_RX_MULTICAST_CNT not found %d", it.get_type());
1387 return NL_SKIP;
1388 }
1389
1390 mGetWakeStats->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt = it.get_u32();
1391 it.next();
1392
1393 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RX_MULTICAST_CNT) {
1394 ALOGE("ICMP6_RX_MULTICAST_CNT not found %d", it.get_type());
1395 return NL_SKIP;
1396 }
1397
1398 mGetWakeStats->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt = it.get_u32();
1399 it.next();
1400
1401 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_OTHER_RX_MULTICAST_CNT) {
1402 ALOGE("OTHER_RX_MULTICAST_CNT not found %d", it.get_type());
1403 return NL_SKIP;
1404 }
1405
1406 mGetWakeStats->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt = it.get_u32();
1407
1408 return NL_OK;
1409 }
1410
1411 int handleEvent(WifiEvent& event) {
1412 /* NO events to handle here! */
1413 return NL_SKIP;
1414 }
1415 };
1416
1417 /* Function to get wake lock stats */
1418 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
1419 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1420 {
1421 if(wifi_wake_reason_cnt) {
1422 WifiLoggerCommand *cmd = new WifiLoggerCommand(iface,wifi_wake_reason_cnt);
1423 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1424 wifi_error result = (wifi_error)cmd->start();
1425 cmd->releaseRef();
1426 return result;
1427 } else {
1428 ALOGE("Reason cnt NULL");
1429 return WIFI_ERROR_INVALID_ARGS;
1430 }
1431 }
1432