[APR-2053]wlbt: NAN R2 integration fxes
[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
384 ALOGD("len = %d, expected len = %lu", reply.get_vendor_data_len(), (unsigned long)sizeof(unsigned int));
385 memcpy(mSupport, data, sizeof(unsigned int));
386 break;
387 }
388
389 default:
390 ALOGW("Unknown Debug command");
391 }
392 return NL_OK;
393 }
394
395 virtual int handleEvent(WifiEvent& event) {
396 /* NO events! */
397 return NL_SKIP;
398 }
399 };
400
401 /* API to get supportable feature */
402 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
403 unsigned int *support)
404 {
405 if (support) {
406 DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);
407 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
408 wifi_error result = (wifi_error)cmd->start();
409 cmd->releaseRef();
410 return result;
411 } else {
412 ALOGE("Get support buffer NULL");
413 return WIFI_ERROR_INVALID_ARGS;
414 }
415 }
416
417 /* API to get the status of all ring buffers supported by driver */
418 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
419 u32 *num_rings, wifi_ring_buffer_status *status)
420 {
421 if (status && num_rings) {
422 DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);
423 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
424 wifi_error result = (wifi_error)cmd->start();
425 cmd->releaseRef();
426 return result;
427 } else {
428 ALOGE("Ring status buffer NULL");
429 return WIFI_ERROR_INVALID_ARGS;
430 }
431 }
432
433 /* API to collect driver records */
434 wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)
435 {
436 DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);
437 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
438 wifi_error result = (wifi_error)cmd->start();
439 cmd->releaseRef();
440 return result;
441 }
442
443 wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
444 u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
445 {
446 if (ring_name) {
447 DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
448 min_data_size, ring_name, START_RING_LOG);
449 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
450 wifi_error result = (wifi_error)cmd->start();
451 cmd->releaseRef();
452 return result;
453 } else {
454 ALOGE("Ring name NULL");
455 return WIFI_ERROR_INVALID_ARGS;
456 }
457 }
458
459 /* API to collect a firmware version string */
460 wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
461 int buffer_size)
462 {
463 if (buffer && (buffer_size > 0)) {
464 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);
465 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
466 wifi_error result = (wifi_error)cmd->start();
467 cmd->releaseRef();
468 return result;
469 } else {
470 ALOGE("FW version buffer NULL");
471 return WIFI_ERROR_INVALID_ARGS;
472 }
473 }
474
475 /* API to collect a driver version string */
476 wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
477 {
478 if (buffer && (buffer_size > 0)) {
479 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);
480 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
481 wifi_error result = (wifi_error)cmd->start();
482 cmd->releaseRef();
483 return result;
484 } else {
485 ALOGE("Driver version buffer NULL");
486 return WIFI_ERROR_INVALID_ARGS;
487 }
488 }
489
490
491 ///////////////////////////////////////////////////////////////////////////////
492 class SetLogHandler : public WifiCommand
493 {
494 wifi_ring_buffer_data_handler mHandler;
495
496 public:
497 SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
498 : WifiCommand(iface, id), mHandler(handler)
499 { }
500
501 int start() {
502 ALOGV("Register loghandler");
503 registerVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_RING_EVENT);
504 return WIFI_SUCCESS;
505 }
506
507 virtual int cancel() {
508 /* Send a command to driver to stop generating logging events */
509 ALOGV("Clear loghandler");
510
511 /* unregister event handler */
512 unregisterVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_RING_EVENT);
513
514 WifiRequest request(familyId(), ifaceId());
515 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_RESET_LOGGING);
516 if (result != WIFI_SUCCESS) {
517 ALOGE("failed to create reset request; result = %d", result);
518 return result;
519 }
520
521 result = requestResponse(request);
522 if (result != WIFI_SUCCESS) {
523 ALOGE("failed to request reset; result = %d", result);
524 return result;
525 }
526
527 ALOGD("Success to clear loghandler");
528 return WIFI_SUCCESS;
529 }
530
531 virtual int handleEvent(WifiEvent& event) {
532 char *buffer = NULL;
533 int buffer_size = 0;
534
535 // ALOGD("In SetLogHandler::handleEvent");
536 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
537 int len = event.get_vendor_data_len();
538 int event_id = event.get_vendor_subcmd();
539 // ALOGI("Got Logger event: %d", event_id);
540
541 if (vendor_data == NULL || len == 0) {
542 ALOGE("No Debug data found");
543 return NL_SKIP;
544 }
545
546 if(event_id == ENHANCE_LOGGER_RING_EVENT) {
547 wifi_ring_buffer_status status;
548 memset(&status, 0, sizeof(status));
549
550 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
551 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_STATUS) {
552 memcpy(&status, it.get_data(), sizeof(status));
553 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_DATA) {
554 buffer_size = it.get_len();
555 buffer = (char *)it.get_data();
556 } else {
557 ALOGW("Ignoring invalid attribute type = %d, size = %d",
558 it.get_type(), it.get_len());
559 }
560 }
561
562 // ALOGI("Retrieved Debug data");
563 if (mHandler.on_ring_buffer_data) {
564 (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,
565 &status);
566 }
567 } else {
568 ALOGE("Unknown Event");
569 return NL_SKIP;
570 }
571 return NL_OK;
572 }
573 };
574
575 wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
576 wifi_ring_buffer_data_handler handler)
577 {
578 wifi_handle handle = getWifiHandle(iface);
579 ALOGV("Loghandler start, handle = %p", handle);
580
581 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
582 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
583 wifi_error result = wifi_register_cmd(handle, id, cmd);
584 if (result != WIFI_SUCCESS) {
585 cmd->releaseRef();
586 return result;
587 }
588 result = (wifi_error)cmd->start();
589 if (result != WIFI_SUCCESS) {
590 wifi_unregister_cmd(handle, id);
591 cmd->releaseRef();
592 return result;
593 }
594 return result;
595 }
596
597 wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
598 {
599 wifi_handle handle = getWifiHandle(iface);
600 ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
601
602 if (id == -1) {
603 wifi_ring_buffer_data_handler handler;
604 memset(&handler, 0, sizeof(handler));
605
606 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
607 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
608 cmd->cancel();
609 cmd->releaseRef();
610 return WIFI_SUCCESS;
611 }
612
613 return wifi_cancel_cmd(id, iface);
614 }
615
616 ///////////////////////////////////////////////////////////////////////////////
617 class SetAlertHandler : public WifiCommand
618 {
619 wifi_alert_handler mHandler;
620 int mBuffSize;
621 char *mBuff;
622 int mErrCode;
623
624 public:
625 SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)
626 : WifiCommand(iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),
627 mErrCode(0)
628 { }
629
630 int start() {
631 ALOGV("Start Alerting");
632 registerVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);
633 return WIFI_SUCCESS;
634 }
635
636 virtual int cancel() {
637 ALOGV("Clear alerthandler");
638
639 /* unregister alert handler */
640 unregisterVendorHandler(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);
641 wifi_unregister_cmd(wifiHandle(), id());
642 ALOGD("Success to clear alerthandler");
643 return WIFI_SUCCESS;
644 }
645
646 virtual int handleResponse(WifiEvent& reply) {
647 ALOGD("In SetAlertHandler::handleResponse");
648
649 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
650 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
651 return NL_SKIP;
652 }
653
654 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
655 int len = reply.get_vendor_data_len();
656
657 ALOGD("len = %d", len);
658 if (vendor_data == NULL || len == 0) {
659 ALOGE("no vendor data in memory dump response; ignoring it");
660 return NL_SKIP;
661 }
662
663 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
664 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
665 ALOGI("Initiating alert callback");
666 if (mHandler.on_alert) {
667 (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
668 }
669 if (mBuff) {
670 free(mBuff);
671 mBuff = NULL;
672 }
673 }
674 }
675 return NL_OK;
676 }
677
678 virtual int handleEvent(WifiEvent& event) {
679 char *buffer = NULL;
680 int buffer_size = 0;
681
682
683 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
684 int len = event.get_vendor_data_len();
685 int event_id = event.get_vendor_subcmd();
686 ALOGI("Got event: %d", event_id);
687
688 if (vendor_data == NULL || len == 0) {
689 ALOGE("No Debug data found");
690 return NL_SKIP;
691 }
692
693 if (event_id == ENHANCE_LOGGER_MEM_DUMP_EVENT) {
694 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
695 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
696 mBuffSize = it.get_u32();
697 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_RING_DATA) {
698 buffer_size = it.get_len();
699 buffer = (char *)it.get_data();
700 /*
701 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_FW_ERR_CODE) {
702 mErrCode = it.get_u32();
703 */
704 } else {
705 ALOGW("Ignoring invalid attribute type = %d, size = %d",
706 it.get_type(), it.get_len());
707 }
708 }
709 if (mBuffSize) {
710 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
711 if (mBuff) free(mBuff);
712 mBuff = (char *)malloc(mBuffSize + buffer_size);
713 if (!mBuff) {
714 ALOGE("Buffer allocation failed");
715 return NL_SKIP;
716 }
717 memcpy(mBuff, buffer, buffer_size);
718
719 WifiRequest request(familyId(), ifaceId());
720 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_MEM_DUMP_EVENT);
721 if (result != WIFI_SUCCESS) {
722 ALOGE("Failed to create get memory dump request; result = %d", result);
723 free(mBuff);
724 return NL_SKIP;
725 }
726 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
727 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
728 if (result != WIFI_SUCCESS) {
729 ALOGE("Failed to put get memory dump request; result = %d", result);
730 return result;
731 }
732
733 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_FW_DUMP_DATA,
734 (uint64_t)(mBuff+buffer_size));
735 if (result != WIFI_SUCCESS) {
736 ALOGE("Failed to put get memory dump request; result = %d", result);
737 return result;
738 }
739
740 request.attr_end(data);
741 mBuffSize += buffer_size;
742
743 result = requestResponse(request);
744
745 if (result != WIFI_SUCCESS) {
746 ALOGE("Failed to register get momory dump response; result = %d", result);
747 }
748 } else {
749 ALOGE("dump event missing dump length attribute");
750 return NL_SKIP;
751 }
752 }
753 return NL_OK;
754 }
755 };
756
757 wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
758 wifi_alert_handler handler)
759 {
760 wifi_handle handle = getWifiHandle(iface);
761 ALOGV("Alerthandler start, handle = %p", handle);
762
763 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
764 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
765 wifi_error result = wifi_register_cmd(handle, id, cmd);
766 if (result != WIFI_SUCCESS) {
767 cmd->releaseRef();
768 return result;
769 }
770 result = (wifi_error)cmd->start();
771 if (result != WIFI_SUCCESS) {
772 wifi_unregister_cmd(handle, id);
773 cmd->releaseRef();
774 return result;
775 }
776 return result;
777 }
778
779 wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)
780 {
781 wifi_handle handle = getWifiHandle(iface);
782 ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);
783
784 if (id == -1) {
785 wifi_alert_handler handler;
786 memset(&handler, 0, sizeof(handler));
787
788 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
789 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
790 cmd->cancel();
791 cmd->releaseRef();
792 return WIFI_SUCCESS;
793 }
794
795 return wifi_cancel_cmd(id, iface);
796 }
797
798
799 class PacketFateCommand: public WifiCommand
800 {
801 void *mReportBufs = NULL;
802 size_t mNoReqFates = 0;
803 size_t *mNoProvidedFates = NULL;
804 PktFateReqType mReqType;
805
806 public:
807 PacketFateCommand(wifi_interface_handle handle)
808 : WifiCommand(handle, 0), mReqType(PACKET_MONITOR_START)
809 { }
810
811 PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
812 size_t n_requested_fates, size_t *n_provided_fates)
813 : WifiCommand(handle, 0), mReportBufs(tx_report_bufs),
814 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
815 mReqType(TX_PACKET_FATE)
816 { }
817
818 PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,
819 size_t n_requested_fates, size_t *n_provided_fates)
820 : WifiCommand(handle, 0), mReportBufs(rx_report_bufs),
821 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
822 mReqType(RX_PACKET_FATE)
823 { }
824
825 int createRequest(WifiRequest& request) {
826 if (mReqType == TX_PACKET_FATE) {
827 ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);
828 return createTxPktFateRequest(request);
829 } else if (mReqType == RX_PACKET_FATE) {
830 ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);
831 return createRxPktFateRequest(request);
832 } else if (mReqType == PACKET_MONITOR_START) {
833 ALOGD("%s Monitor packet fate request\n", __FUNCTION__);
834 return createMonitorPktFateRequest(request);
835 } else {
836 ALOGE("%s Unknown packet fate request\n", __FUNCTION__);
837 return WIFI_ERROR_NOT_SUPPORTED;
838 }
839 return WIFI_SUCCESS;
840 }
841
842 int createMonitorPktFateRequest(WifiRequest& request) {
843 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_START_PKT_FATE_MONITORING);
844 if (result < 0) {
845 return result;
846 }
847
848 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
849 request.attr_end(data);
850 return result;
851 }
852
853 int createTxPktFateRequest(WifiRequest& request) {
854 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_TX_PKT_FATES);
855 if (result < 0) {
856 return result;
857 }
858
859 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));
860 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
861 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
862 if (result < 0) {
863 return result;
864 }
865 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
866 if (result < 0) {
867 return result;
868 }
869 request.attr_end(data);
870 return result;
871 }
872
873 int createRxPktFateRequest(WifiRequest& request) {
874 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_RX_PKT_FATES);
875 if (result < 0) {
876 return result;
877 }
878
879 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));
880 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
881 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
882 if (result < 0) {
883 return result;
884 }
885 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
886 if (result < 0) {
887 return result;
888 }
889 request.attr_end(data);
890 return result;
891 }
892
893 int start() {
894 ALOGD("Start get packet fate command\n");
895 WifiRequest request(familyId(), ifaceId());
896
897 int result = createRequest(request);
898 if (result < 0) {
899 ALOGE("Failed to create get pkt fate request; result = %d\n", result);
900 return result;
901 }
902
903 result = requestResponse(request);
904 if (result != WIFI_SUCCESS) {
905 ALOGE("Failed to register get pkt fate response; result = %d\n", result);
906 }
907 return result;
908 }
909
910 int handleResponse(WifiEvent& reply) {
911 ALOGD("In GetPktFateCommand::handleResponse\n");
912
913 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
914 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
915 return NL_SKIP;
916 }
917
918 int id = reply.get_vendor_id();
919 int subcmd = reply.get_vendor_subcmd();
920 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
921 int len = reply.get_vendor_data_len();
922
923 ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
924
925 if (mReqType == TX_PACKET_FATE) {
926 ALOGI("Response recieved for get TX pkt fate command\n");
927 } else if (mReqType == RX_PACKET_FATE) {
928 ALOGI("Response recieved for get RX pkt fate command\n");
929 } else if (mReqType == PACKET_MONITOR_START) {
930 ALOGI("Response recieved for monitor pkt fate command\n");
931 return NL_OK;
932 } else {
933 ALOGE("Response recieved for unknown pkt fate command\n");
934 return NL_SKIP;
935 }
936
937 if (vendor_data == NULL || len == 0) {
938 ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
939 return NL_SKIP;
940 }
941
942 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
943 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
944 *mNoProvidedFates = it.get_u32();
945 ALOGI("No: of pkt fates provided is %zu\n", *mNoProvidedFates);
946 } else {
947 ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
948 it.get_type(), it.get_len());
949 }
950 }
951
952 return NL_OK;
953 }
954
955 int handleEvent(WifiEvent& event) {
956 /* NO events to handle here! */
957 return NL_SKIP;
958 }
959 };
960
961 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
962 {
963 PacketFateCommand *cmd = new PacketFateCommand(handle);
964 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
965 wifi_error result = (wifi_error)cmd->start();
966 cmd->releaseRef();
967 return result;
968 }
969
970 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
971 wifi_tx_report *tx_report_bufs, size_t n_requested_fates,
972 size_t *n_provided_fates)
973 {
974 PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,
975 n_requested_fates, n_provided_fates);
976 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
977 wifi_error result = (wifi_error)cmd->start();
978 cmd->releaseRef();
979 memset(tx_report_bufs, 0, (n_requested_fates * sizeof(wifi_tx_report)));
980 return result;
981 }
982
983 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
984 wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
985 size_t *n_provided_fates)
986 {
987 PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
988 n_requested_fates, n_provided_fates);
989 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
990 wifi_error result = (wifi_error)cmd->start();
991 cmd->releaseRef();
992 memset(rx_report_bufs, 0, (n_requested_fates * sizeof(wifi_rx_report)));
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(&mcallback, 0, sizeof(wifi_driver_memory_dump_callbacks));
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(&mHandler, 0, sizeof(wifi_firmware_memory_dump_handler));
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 break;
1128 case GET_DRIVER_DUMP :
1129 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1130 if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN) {
1131 mBuffSize = it.get_u32();
1132 if (mBuff)
1133 free(mBuff);
1134 mBuff = (char *)malloc(mBuffSize);
1135 if (!mBuff) {
1136 ALOGE("Buffer allocation failed");
1137 return NL_SKIP;
1138 }
1139 WifiRequest request(familyId(), ifaceId());
1140 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_DRIVER_MEM_DUMP);
1141 if (result != WIFI_SUCCESS) {
1142 ALOGE("Failed to create get driver memory dump request; result = %d", result);
1143 free(mBuff);
1144 return NL_SKIP;
1145 }
1146 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1147 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN, mBuffSize);
1148 if (result != WIFI_SUCCESS) {
1149 ALOGE("Failed to put get driver memory dump request; result = %d", result);
1150 return result;
1151 }
1152 result = request.put_u64(ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA, (uint64_t)mBuff);
1153 if (result != WIFI_SUCCESS) {
1154 ALOGE("Failed to put get driver memory dump request; result = %d", result);
1155 return result;
1156 }
1157 request.attr_end(data);
1158 result = requestResponse(request);
1159 if (result != WIFI_SUCCESS) {
1160 ALOGE("Failed to register get driver momory dump response; result = %d", result);
1161 }
1162 } else if (it.get_type() == ENHANCE_LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA) {
1163 ALOGI("Initiating memory dump callback");
1164 if (mcallback.on_driver_memory_dump) {
1165 (*mcallback.on_driver_memory_dump)(mBuff, mBuffSize);
1166 }
1167 if (mBuff) {
1168 free(mBuff);
1169 mBuff = NULL;
1170 }
1171 } else {
1172 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1173 it.get_type(), it.get_len());
1174 }
1175 }
1176 break;
1177 case GET_FW_VER:
1178 case GET_DRV_VER:
1179 case GET_RING_DATA:
1180 case GET_RING_STATUS:
1181 case GET_FEATURE:
1182 case START_RING_LOG:
1183 default:
1184 {
1185 ALOGW("Ignoring GetCmdType %d \n", mType);
1186 }
1187 }
1188 return NL_OK;
1189 }
1190
1191 virtual int handleEvent(WifiEvent& event) {
1192 /* NO events! */
1193 return NL_SKIP;
1194 }
1195 };
1196
1197 /* API to collect a firmware memory dump for a given iface */
1198 wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
1199 wifi_firmware_memory_dump_handler handler)
1200 {
1201 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler, GET_FW_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
1208 wifi_error wifi_get_driver_memory_dump(wifi_interface_handle iface,
1209 wifi_driver_memory_dump_callbacks callbacks)
1210 {
1211 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, callbacks, GET_DRIVER_DUMP);
1212 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1213 wifi_error result = (wifi_error)cmd->start();
1214 cmd->releaseRef();
1215 return result;
1216 }
1217 class WifiLoggerCommand: public WifiCommand
1218 {
1219 WLAN_DRIVER_WAKE_REASON_CNT *mGetWakeStats;
1220
1221 public:
1222 WifiLoggerCommand(wifi_interface_handle handle, WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1223 : WifiCommand(handle, 0), mGetWakeStats(wifi_wake_reason_cnt)
1224 { }
1225
1226 int createRequest(WifiRequest& request) {
1227 int result = request.create(GOOGLE_OUI, ENHANCE_LOGGER_GET_WAKE_REASON_STATS);
1228 if (result < 0) {
1229 return result;
1230 }
1231
1232 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1233
1234 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_SZ, mGetWakeStats->cmd_event_wake_cnt_sz);
1235 if (result != WIFI_SUCCESS) {
1236 ALOGE("Failed to put wake_cnt_sz; result = %d", result);
1237 return result;
1238 }
1239 result = request.put_u32(ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_SZ, mGetWakeStats->driver_fw_local_wake_cnt_sz);
1240 if (result != WIFI_SUCCESS) {
1241 ALOGE("Failed to put driver_fw_local_wake_cnt; result = %d", result);
1242 return result;
1243 }
1244 request.attr_end(data);
1245 return result;
1246 }
1247
1248 int start() {
1249 ALOGD("Start get wake reason stats command\n");
1250 WifiRequest request(familyId(), ifaceId());
1251 int result = createRequest(request);
1252 if (result < 0) {
1253 ALOGE("Failed to create get wake reason stats request; result = %d\n", result);
1254 return result;
1255 }
1256 result = requestResponse(request);
1257 if (result != WIFI_SUCCESS) {
1258 ALOGE("Failed to register get wake reason stats response; result = %d\n", result);
1259 }
1260 return result;
1261 }
1262
1263 int handleResponse(WifiEvent& reply) {
1264 int len = 0;
1265 ALOGD("In WifiLoggerCommand::handleResponse\n");
1266
1267 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1268 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
1269 return NL_SKIP;
1270 }
1271 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1272 len = reply.get_vendor_data_len();
1273 if (vendor_data == NULL || len == 0) {
1274 ALOGE("No Debug data found");
1275 return NL_SKIP;
1276 }
1277 nl_iterator it(vendor_data);
1278
1279 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_CMD_EVENT_WAKE) {
1280 ALOGE("TOTAL_CMD_EVENT_WAKE not found %d", it.get_type());
1281 return NL_SKIP;
1282 }
1283
1284 mGetWakeStats->total_cmd_event_wake = it.get_u32();
1285 it.next();
1286
1287 if(mGetWakeStats->total_cmd_event_wake && mGetWakeStats->cmd_event_wake_cnt) {
1288 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_CMD_EVENT_WAKE_CNT_PTR) {
1289 ALOGE("CMD_EVENT_WAKE_CNT_PTR not found %d", it.get_type());
1290 return NL_SKIP;
1291 }
1292
1293 len = it.get_len();
1294 mGetWakeStats->cmd_event_wake_cnt_used = (len < mGetWakeStats->cmd_event_wake_cnt_sz) ? len : mGetWakeStats->cmd_event_wake_cnt_sz;
1295 memcpy(mGetWakeStats->cmd_event_wake_cnt, it.get_data(), mGetWakeStats->cmd_event_wake_cnt_used * sizeof(int));
1296 } else {
1297 mGetWakeStats->cmd_event_wake_cnt_used = 0;
1298 }
1299
1300 it.next();
1301
1302 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_DRIVER_FW_LOCAL_WAKE) {
1303 ALOGE("TOTAL_DRIVER_FW_LOCAL_WAKE not found %d", it.get_type());
1304 return NL_SKIP;
1305 }
1306
1307 mGetWakeStats->total_driver_fw_local_wake = it.get_u32();
1308 it.next();
1309
1310 if(mGetWakeStats->total_driver_fw_local_wake && mGetWakeStats->driver_fw_local_wake_cnt) {
1311 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_DRIVER_FW_LOCAL_WAKE_CNT_PTR) {
1312 ALOGE("DRIVER_FW_LOCAL_WAKE_CNT_PTR not found %d", it.get_type());
1313 return NL_SKIP;
1314 }
1315
1316 len = it.get_len();
1317 mGetWakeStats->driver_fw_local_wake_cnt_used= (len < mGetWakeStats->driver_fw_local_wake_cnt_sz) ? len : mGetWakeStats->driver_fw_local_wake_cnt_sz;
1318 memcpy(mGetWakeStats->driver_fw_local_wake_cnt, it.get_data(), mGetWakeStats->driver_fw_local_wake_cnt_used * sizeof(int));
1319 } else {
1320 mGetWakeStats->driver_fw_local_wake_cnt_used= 0;
1321 }
1322
1323 it.next();
1324
1325 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_TOTAL_RX_DATA_WAKE) {
1326 ALOGE("TOTAL_RX_DATA_WAKE not found %d", it.get_type());
1327 return NL_SKIP;
1328 }
1329
1330 mGetWakeStats->total_rx_data_wake = it.get_u32();
1331 it.next();
1332
1333 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_UNICAST_CNT) {
1334 ALOGE("RX_UNICAST_CNT not found %d", it.get_type());
1335 return NL_SKIP;
1336 }
1337
1338 mGetWakeStats->rx_wake_details.rx_unicast_cnt = it.get_u32();
1339 it.next();
1340
1341 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_MULTICAST_CNT) {
1342 ALOGE("RX_MULTICAST_CNT not found %d", it.get_type());
1343 return NL_SKIP;
1344 }
1345
1346 mGetWakeStats->rx_wake_details.rx_multicast_cnt = it.get_u32();
1347 it.next();
1348
1349 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_RX_BROADCAST_CNT) {
1350 ALOGE("RX_BROADCAST_CNT not found %d", it.get_type());
1351 return NL_SKIP;
1352 }
1353
1354 mGetWakeStats->rx_wake_details.rx_broadcast_cnt = it.get_u32();
1355 it.next();
1356
1357 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP_PKT) {
1358 ALOGE("ICMP_PKT not found %d", it.get_type());
1359 return NL_SKIP;
1360 }
1361
1362 mGetWakeStats->rx_wake_pkt_classification_info .icmp_pkt = it.get_u32();
1363 it.next();
1364
1365 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_PKT) {
1366 ALOGE("ICMP6_PKT not found %d", it.get_type());
1367 return NL_SKIP;
1368 }
1369
1370 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_pkt = it.get_u32();
1371 it.next();
1372
1373 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RA) {
1374 ALOGE("ICMP6_RA not found %d", it.get_type());
1375 return NL_SKIP;
1376 }
1377
1378 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ra = it.get_u32();
1379 it.next();
1380
1381 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NA) {
1382 ALOGE("ICMP6_NA not found %d", it.get_type());
1383 return NL_SKIP;
1384 }
1385
1386 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_na = it.get_u32();
1387 it.next();
1388
1389 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_NS) {
1390 ALOGE("ICMP6_NS not found %d", it.get_type());
1391 return NL_SKIP;
1392 }
1393
1394 mGetWakeStats->rx_wake_pkt_classification_info .icmp6_ns = it.get_u32();
1395 it.next();
1396
1397 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP4_RX_MULTICAST_CNT) {
1398 ALOGE("ICMP4_RX_MULTICAST_CNT not found %d", it.get_type());
1399 return NL_SKIP;
1400 }
1401
1402 mGetWakeStats->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt = it.get_u32();
1403 it.next();
1404
1405 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_ICMP6_RX_MULTICAST_CNT) {
1406 ALOGE("ICMP6_RX_MULTICAST_CNT not found %d", it.get_type());
1407 return NL_SKIP;
1408 }
1409
1410 mGetWakeStats->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt = it.get_u32();
1411 it.next();
1412
1413 if (it.get_type() != ENHANCE_LOGGER_ATTRIBUTE_WAKE_STATS_OTHER_RX_MULTICAST_CNT) {
1414 ALOGE("OTHER_RX_MULTICAST_CNT not found %d", it.get_type());
1415 return NL_SKIP;
1416 }
1417
1418 mGetWakeStats->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt = it.get_u32();
1419
1420 return NL_OK;
1421 }
1422
1423 int handleEvent(WifiEvent& event) {
1424 /* NO events to handle here! */
1425 return NL_SKIP;
1426 }
1427 };
1428
1429 /* Function to get wake lock stats */
1430 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
1431 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1432 {
1433 if(wifi_wake_reason_cnt) {
1434 WifiLoggerCommand *cmd = new WifiLoggerCommand(iface,wifi_wake_reason_cnt);
1435 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1436 wifi_error result = (wifi_error)cmd->start();
1437 cmd->releaseRef();
1438 return result;
1439 } else {
1440 ALOGE("Reason cnt NULL");
1441 return WIFI_ERROR_INVALID_ARGS;
1442 }
1443 }
1444