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-types.h>
17
18 #include "nl80211_copy.h"
19 #include "sync.h"
20
21 #define LOG_TAG "WifiHAL"
22
23 #include <utils/Log.h>
24
25 #include "wifi_hal.h"
26 #include "common.h"
27 #include "cpp_bindings.h"
28
29 using namespace android;
30
31 typedef enum {
32 LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
33 LOGGER_TRIGGER_MEM_DUMP,
34 LOGGER_GET_MEM_DUMP,
35 LOGGER_GET_VER,
36 LOGGER_GET_RING_STATUS,
37 LOGGER_GET_RING_DATA,
38 LOGGER_GET_FEATURE,
39 LOGGER_RESET_LOGGING,
40 LOGGER_TRIGGER_DRIVER_MEM_DUMP,
41 LOGGER_GET_DRIVER_MEM_DUMP,
42 LOGGER_START_PKT_FATE_MONITORING,
43 LOGGER_GET_TX_PKT_FATES,
44 LOGGER_GET_RX_PKT_FATES,
45 } DEBUG_SUB_COMMAND;
46
47 typedef enum {
48 LOGGER_ATTRIBUTE_DRIVER_VER,
49 LOGGER_ATTRIBUTE_FW_VER,
50 LOGGER_ATTRIBUTE_RING_ID,
51 LOGGER_ATTRIBUTE_RING_NAME,
52 LOGGER_ATTRIBUTE_RING_FLAGS,
53 LOGGER_ATTRIBUTE_LOG_LEVEL,
54 LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
55 LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
56 LOGGER_ATTRIBUTE_FW_DUMP_LEN,
57 LOGGER_ATTRIBUTE_FW_DUMP_DATA,
58 // LOGGER_ATTRIBUTE_FW_ERR_CODE,
59 LOGGER_ATTRIBUTE_RING_DATA,
60 LOGGER_ATTRIBUTE_RING_STATUS,
61 LOGGER_ATTRIBUTE_RING_NUM,
62 LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
63 LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
64 LOGGER_ATTRIBUTE_PKT_FATE_NUM,
65 LOGGER_ATTRIBUTE_PKT_FATE_DATA,
66 } LOGGER_ATTRIBUTE;
67
68 typedef enum {
69 DEBUG_OFF = 0,
70 DEBUG_NORMAL,
71 DEBUG_VERBOSE,
72 DEBUG_VERY,
73 DEBUG_VERY_VERY,
74 } LOGGER_LEVEL;
75
76 typedef enum {
77 GET_FW_VER,
78 GET_DRV_VER,
79 GET_RING_DATA,
80 GET_RING_STATUS,
81 GET_FEATURE,
82 START_RING_LOG,
83 } GetCmdType;
84
85 typedef enum {
86 PACKET_MONITOR_START,
87 TX_PACKET_FATE,
88 RX_PACKET_FATE,
89 } PktFateReqType;
90
91
92 ///////////////////////////////////////////////////////////////////////////////
93 class DebugCommand : public WifiCommand
94 {
95 char *mBuff;
96 int *mBuffSize;
97 u32 *mNumRings;
98 wifi_ring_buffer_status *mStatus;
99 unsigned int *mSupport;
100 u32 mVerboseLevel;
101 u32 mFlags;
102 u32 mMaxIntervalSec;
103 u32 mMinDataSize;
104 char *mRingName;
105 GetCmdType mType;
106
107 public:
108
109 // constructor for get version
DebugCommand(wifi_interface_handle iface,char * buffer,int * buffer_size,GetCmdType cmdType)110 DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,
111 GetCmdType cmdType)
112 : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
113 (cmdType)
114 {
115 memset(mBuff, 0, *mBuffSize);
116 }
117
118 // constructor for ring data
DebugCommand(wifi_interface_handle iface,char * ring_name,GetCmdType cmdType)119 DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
120 : WifiCommand("DebugCommand", iface, 0), mRingName(ring_name), mType(cmdType)
121 { }
122
123 // constructor for ring status
DebugCommand(wifi_interface_handle iface,u32 * num_rings,wifi_ring_buffer_status * status,GetCmdType cmdType)124 DebugCommand(wifi_interface_handle iface, u32 *num_rings,
125 wifi_ring_buffer_status *status, GetCmdType cmdType)
126 : WifiCommand("DebugCommand", iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
127 {
128 memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
129 }
130
131 // constructor for feature set
DebugCommand(wifi_interface_handle iface,unsigned int * support,GetCmdType cmdType)132 DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
133 : WifiCommand("DebugCommand", iface, 0), mSupport(support), mType(cmdType)
134 { }
135
136 // constructor for ring params
DebugCommand(wifi_interface_handle iface,u32 verbose_level,u32 flags,u32 max_interval_sec,u32 min_data_size,char * ring_name,GetCmdType cmdType)137 DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
138 u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)
139 : WifiCommand("DebugCommand", iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
140 mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
141 mRingName(ring_name), mType(cmdType)
142 { }
143
createRingRequest(WifiRequest & request)144 int createRingRequest(WifiRequest& request) {
145 int result = request.create(GOOGLE_OUI, LOGGER_START_LOGGING);
146 if (result != WIFI_SUCCESS) {
147 ALOGE("Failed to create start ring logger request; result = %d", result);
148 return result;
149 }
150
151 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
152
153 result = request.put_u32(LOGGER_ATTRIBUTE_LOG_LEVEL, mVerboseLevel);
154 if (result != WIFI_SUCCESS) {
155 ALOGE("Failed to put log level; result = %d", result);
156 return result;
157 }
158 result = request.put_u32(LOGGER_ATTRIBUTE_RING_FLAGS, mFlags);
159 if (result != WIFI_SUCCESS) {
160 ALOGE("Failed to put ring flags; result = %d", result);
161 return result;
162 }
163 result = request.put_u32(LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, mMaxIntervalSec);
164 if (result != WIFI_SUCCESS) {
165 ALOGE("Failed to put log time interval; result = %d", result);
166 return result;
167 }
168 result = request.put_u32(LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, mMinDataSize);
169 if (result != WIFI_SUCCESS) {
170 ALOGE("Failed to put min data size; result = %d", result);
171 return result;
172 }
173 result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
174 if (result != WIFI_SUCCESS) {
175 ALOGE("Failed to put ringbuffer name; result = %d", result);
176 return result;
177 }
178 request.attr_end(data);
179
180 return WIFI_SUCCESS;
181 }
182
createRequest(WifiRequest & request)183 int createRequest(WifiRequest &request) {
184 int result;
185
186 switch (mType) {
187 case GET_FW_VER:
188 {
189 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
190 if (result != WIFI_SUCCESS) {
191 ALOGE("Failed to create get fw version request; result = %d", result);
192 return result;
193 }
194
195 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
196
197 // Driver expecting only attribute type, passing mbuff as data with
198 // length 0 to avoid undefined state
199 result = request.put(LOGGER_ATTRIBUTE_FW_VER, mBuff, 0);
200 if (result != WIFI_SUCCESS) {
201 ALOGE("Failed to put get fw version request; result = %d", result);
202 return result;
203 }
204 request.attr_end(data);
205 break;
206 }
207
208 case GET_DRV_VER:
209 {
210 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
211 if (result != WIFI_SUCCESS) {
212 ALOGE("Failed to create get drv version request; result = %d", result);
213 return result;
214 }
215
216 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
217
218 // Driver expecting only attribute type, passing mbuff as data with
219 // length 0 to avoid undefined state
220 result = request.put(LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);
221
222 if (result != WIFI_SUCCESS) {
223 ALOGE("Failed to put get drv version request; result = %d", result);
224 return result;
225 }
226 request.attr_end(data);
227 break;
228 }
229
230 case GET_RING_DATA:
231 {
232 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_DATA);
233 if (result != WIFI_SUCCESS) {
234 ALOGE("Failed to create get ring data request; result = %d", result);
235 return result;
236 }
237
238 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
239 result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
240 if (result != WIFI_SUCCESS) {
241 ALOGE("Failed to put ring data request; result = %d", result);
242 return result;
243 }
244 request.attr_end(data);
245 break;
246 }
247
248 case GET_RING_STATUS:
249 {
250 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_STATUS);
251 if (result != WIFI_SUCCESS) {
252 ALOGE("Failed to create get ring status request; result = %d", result);
253 return result;
254 }
255 break;
256 }
257
258 case GET_FEATURE:
259 {
260 result = request.create(GOOGLE_OUI, LOGGER_GET_FEATURE);
261 if (result != WIFI_SUCCESS) {
262 ALOGE("Failed to create get feature request; result = %d", result);
263 return result;
264 }
265 break;
266 }
267
268 case START_RING_LOG:
269 result = createRingRequest(request);
270 break;
271
272 default:
273 ALOGE("Unknown Debug command");
274 result = WIFI_ERROR_UNKNOWN;
275 }
276 return result;
277 }
278
start()279 int start() {
280 // ALOGD("Start debug command");
281 WifiRequest request(familyId(), ifaceId());
282 int result = createRequest(request);
283 if (result != WIFI_SUCCESS) {
284 ALOGE("Failed to create debug request; result = %d", result);
285 return result;
286 }
287
288 result = requestResponse(request);
289 if (result != WIFI_SUCCESS) {
290 ALOGE("Failed to register debug response; result = %d", result);
291 }
292 return result;
293 }
294
handleResponse(WifiEvent & reply)295 virtual int handleResponse(WifiEvent& reply) {
296 ALOGD("In DebugCommand::handleResponse");
297
298 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
299 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
300 return NL_SKIP;
301 }
302
303 switch (mType) {
304 case GET_DRV_VER:
305 case GET_FW_VER:
306 {
307 void *data = reply.get_vendor_data();
308 int len = reply.get_vendor_data_len();
309
310 ALOGD("len = %d, expected len = %d", len, *mBuffSize);
311 memcpy(mBuff, data, min(len, *mBuffSize));
312 if (*mBuffSize < len)
313 return NL_SKIP;
314 *mBuffSize = len;
315 break;
316 }
317
318 case START_RING_LOG:
319 case GET_RING_DATA:
320 break;
321
322 case GET_RING_STATUS:
323 {
324 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
325 int len = reply.get_vendor_data_len();
326 wifi_ring_buffer_status *status(mStatus);
327
328 if (vendor_data == NULL || len == 0) {
329 ALOGE("No Debug data found");
330 return NL_SKIP;
331 }
332
333 nl_iterator it(vendor_data);
334 if (it.get_type() == LOGGER_ATTRIBUTE_RING_NUM) {
335 unsigned int num_rings = it.get_u32();
336 if (*mNumRings < num_rings) {
337 ALOGE("Not enough status buffers provided, available: %d required: %d",
338 *mNumRings, num_rings);
339 } else {
340 *mNumRings = num_rings;
341 }
342 } else {
343 ALOGE("Unknown attribute: %d expecting %d",
344 it.get_type(), LOGGER_ATTRIBUTE_RING_NUM);
345 return NL_SKIP;
346 }
347
348 it.next();
349 for (unsigned int i = 0; it.has_next() && i < *mNumRings; it.next()) {
350 if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
351 memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status));
352 i++;
353 status++;
354 } else {
355 ALOGW("Ignoring invalid attribute type = %d, size = %d",
356 it.get_type(), it.get_len());
357 }
358 }
359 break;
360 }
361
362 case GET_FEATURE:
363 {
364 void *data = reply.get_vendor_data();
365 int len = reply.get_vendor_data_len();
366
367 ALOGD("len = %d, expected len = %d", len, sizeof(unsigned int));
368 memcpy(mSupport, data, sizeof(unsigned int));
369 break;
370 }
371
372 default:
373 ALOGW("Unknown Debug command");
374 }
375 return NL_OK;
376 }
377
handleEvent(WifiEvent & event)378 virtual int handleEvent(WifiEvent& event) {
379 /* NO events! */
380 return NL_SKIP;
381 }
382 };
383
384 /* API to collect a firmware version string */
wifi_get_firmware_version(wifi_interface_handle iface,char * buffer,int buffer_size)385 wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
386 int buffer_size)
387 {
388 if (buffer && (buffer_size > 0)) {
389 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);
390 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
391 wifi_error result = (wifi_error)cmd->start();
392 cmd->releaseRef();
393 return result;
394 } else {
395 ALOGE("FW version buffer NULL");
396 return WIFI_ERROR_INVALID_ARGS;
397 }
398 }
399
400 /* API to collect a driver version string */
wifi_get_driver_version(wifi_interface_handle iface,char * buffer,int buffer_size)401 wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
402 {
403 if (buffer && (buffer_size > 0)) {
404 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);
405 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
406 wifi_error result = (wifi_error)cmd->start();
407 cmd->releaseRef();
408 return result;
409 } else {
410 ALOGE("Driver version buffer NULL");
411 return WIFI_ERROR_INVALID_ARGS;
412 }
413 }
414
415 /* API to collect driver records */
wifi_get_ring_data(wifi_interface_handle iface,char * ring_name)416 wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)
417 {
418 DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);
419 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
420 wifi_error result = (wifi_error)cmd->start();
421 cmd->releaseRef();
422 return result;
423 }
424
425 /* API to get the status of all ring buffers supported by driver */
wifi_get_ring_buffers_status(wifi_interface_handle iface,u32 * num_rings,wifi_ring_buffer_status * status)426 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
427 u32 *num_rings, wifi_ring_buffer_status *status)
428 {
429 if (status && num_rings) {
430 DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);
431 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
432 wifi_error result = (wifi_error)cmd->start();
433 cmd->releaseRef();
434 return result;
435 } else {
436 ALOGE("Ring status buffer NULL");
437 return WIFI_ERROR_INVALID_ARGS;
438 }
439 }
440
441 /* API to get supportable feature */
wifi_get_logger_supported_feature_set(wifi_interface_handle iface,unsigned int * support)442 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
443 unsigned int *support)
444 {
445 if (support) {
446 DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);
447 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
448 wifi_error result = (wifi_error)cmd->start();
449 cmd->releaseRef();
450 return result;
451 } else {
452 ALOGE("Get support buffer NULL");
453 return WIFI_ERROR_INVALID_ARGS;
454 }
455 }
456
wifi_start_logging(wifi_interface_handle iface,u32 verbose_level,u32 flags,u32 max_interval_sec,u32 min_data_size,char * ring_name)457 wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
458 u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
459 {
460 if (ring_name) {
461 DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
462 min_data_size, ring_name, START_RING_LOG);
463 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
464 wifi_error result = (wifi_error)cmd->start();
465 cmd->releaseRef();
466 return result;
467 } else {
468 ALOGE("Ring name NULL");
469 return WIFI_ERROR_INVALID_ARGS;
470 }
471 }
472
473
474 ///////////////////////////////////////////////////////////////////////////////
475 class SetLogHandler : public WifiCommand
476 {
477 wifi_ring_buffer_data_handler mHandler;
478
479 public:
SetLogHandler(wifi_interface_handle iface,int id,wifi_ring_buffer_data_handler handler)480 SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
481 : WifiCommand("SetLogHandler", iface, id), mHandler(handler)
482 { }
483
start()484 int start() {
485 ALOGV("Register loghandler");
486 registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
487 return WIFI_SUCCESS;
488 }
489
cancel()490 virtual int cancel() {
491 /* Send a command to driver to stop generating logging events */
492 ALOGV("Clear loghandler");
493
494 /* unregister event handler */
495 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
496
497 WifiRequest request(familyId(), ifaceId());
498 int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
499 if (result != WIFI_SUCCESS) {
500 ALOGE("failed to create reset request; result = %d", result);
501 return result;
502 }
503
504 result = requestResponse(request);
505 if (result != WIFI_SUCCESS) {
506 ALOGE("failed to request reset; result = %d", result);
507 return result;
508 }
509
510 ALOGD("Success to clear loghandler");
511 return WIFI_SUCCESS;
512 }
513
handleEvent(WifiEvent & event)514 virtual int handleEvent(WifiEvent& event) {
515 char *buffer = NULL;
516 int buffer_size = 0;
517
518 // ALOGD("In SetLogHandler::handleEvent");
519 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
520 int len = event.get_vendor_data_len();
521 int event_id = event.get_vendor_subcmd();
522 // ALOGI("Got Logger event: %d", event_id);
523
524 if (vendor_data == NULL || len == 0) {
525 ALOGE("No Debug data found");
526 return NL_SKIP;
527 }
528
529 if(event_id == GOOGLE_DEBUG_RING_EVENT) {
530 wifi_ring_buffer_status status;
531 memset(&status, 0, sizeof(status));
532
533 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
534 if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
535 memcpy(&status, it.get_data(), sizeof(status));
536 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
537 buffer_size = it.get_len();
538 buffer = (char *)it.get_data();
539 } else {
540 ALOGW("Ignoring invalid attribute type = %d, size = %d",
541 it.get_type(), it.get_len());
542 }
543 }
544
545 // ALOGI("Retrieved Debug data");
546 if (mHandler.on_ring_buffer_data) {
547 (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,
548 &status);
549 }
550 } else {
551 ALOGE("Unknown Event");
552 return NL_SKIP;
553 }
554 return NL_OK;
555 }
556 };
557
wifi_set_log_handler(wifi_request_id id,wifi_interface_handle iface,wifi_ring_buffer_data_handler handler)558 wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
559 wifi_ring_buffer_data_handler handler)
560 {
561 wifi_handle handle = getWifiHandle(iface);
562 ALOGV("Loghandler start, handle = %p", handle);
563
564 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
565 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
566 wifi_error result = wifi_register_cmd(handle, id, cmd);
567 if (result != WIFI_SUCCESS) {
568 cmd->releaseRef();
569 return result;
570 }
571 result = (wifi_error)cmd->start();
572 if (result != WIFI_SUCCESS) {
573 wifi_unregister_cmd(handle, id);
574 cmd->releaseRef();
575 return result;
576 }
577 return result;
578 }
579
wifi_reset_log_handler(wifi_request_id id,wifi_interface_handle iface)580 wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
581 {
582 wifi_handle handle = getWifiHandle(iface);
583 ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
584
585 if (id == -1) {
586 wifi_ring_buffer_data_handler handler;
587 memset(&handler, 0, sizeof(handler));
588
589 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
590 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
591 cmd->cancel();
592 cmd->releaseRef();
593 return WIFI_SUCCESS;
594 }
595
596 return wifi_cancel_cmd(id, iface);
597 }
598
599 ///////////////////////////////////////////////////////////////////////////////
600 class SetAlertHandler : public WifiCommand
601 {
602 wifi_alert_handler mHandler;
603 int mBuffSize;
604 char *mBuff;
605 int mErrCode;
606
607 public:
SetAlertHandler(wifi_interface_handle iface,int id,wifi_alert_handler handler)608 SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)
609 : WifiCommand("SetAlertHandler", iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),
610 mErrCode(0)
611 { }
612
start()613 int start() {
614 ALOGV("Start Alerting");
615 registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
616 return WIFI_SUCCESS;
617 }
618
cancel()619 virtual int cancel() {
620 ALOGV("Clear alerthandler");
621
622 /* unregister alert handler */
623 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
624 wifi_unregister_cmd(wifiHandle(), id());
625 ALOGD("Success to clear alerthandler");
626 return WIFI_SUCCESS;
627 }
628
handleResponse(WifiEvent & reply)629 virtual int handleResponse(WifiEvent& reply) {
630 ALOGD("In SetAlertHandler::handleResponse");
631
632 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
633 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
634 return NL_SKIP;
635 }
636
637 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
638 int len = reply.get_vendor_data_len();
639
640 ALOGD("len = %d", len);
641 if (vendor_data == NULL || len == 0) {
642 ALOGE("no vendor data in memory dump response; ignoring it");
643 return NL_SKIP;
644 }
645
646 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
647 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
648 ALOGI("Initiating alert callback");
649 if (mHandler.on_alert) {
650 (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
651 }
652 if (mBuff) {
653 free(mBuff);
654 mBuff = NULL;
655 }
656 }
657 }
658 return NL_OK;
659 }
660
handleEvent(WifiEvent & event)661 virtual int handleEvent(WifiEvent& event) {
662 wifi_ring_buffer_id ring_id;
663 char *buffer = NULL;
664 int buffer_size = 0;
665
666
667 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
668 int len = event.get_vendor_data_len();
669 int event_id = event.get_vendor_subcmd();
670 ALOGI("Got event: %d", event_id);
671
672 if (vendor_data == NULL || len == 0) {
673 ALOGE("No Debug data found");
674 return NL_SKIP;
675 }
676
677 if (event_id == GOOGLE_DEBUG_MEM_DUMP_EVENT) {
678 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
679 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
680 mBuffSize = it.get_u32();
681 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
682 buffer_size = it.get_len();
683 buffer = (char *)it.get_data();
684 /*
685 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_ERR_CODE) {
686 mErrCode = it.get_u32();
687 */
688 } else {
689 ALOGW("Ignoring invalid attribute type = %d, size = %d",
690 it.get_type(), it.get_len());
691 }
692 }
693 if (mBuffSize) {
694 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
695 if (mBuff) free(mBuff);
696 mBuff = (char *)malloc(mBuffSize + buffer_size);
697 if (!mBuff) {
698 ALOGE("Buffer allocation failed");
699 return NL_SKIP;
700 }
701 memcpy(mBuff, buffer, buffer_size);
702
703 WifiRequest request(familyId(), ifaceId());
704 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
705 if (result != WIFI_SUCCESS) {
706 ALOGE("Failed to create get memory dump request; result = %d", result);
707 free(mBuff);
708 return NL_SKIP;
709 }
710 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
711 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
712 if (result != WIFI_SUCCESS) {
713 ALOGE("Failed to put get memory dump request; result = %d", result);
714 return result;
715 }
716
717 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA,
718 (uint64_t)(mBuff+buffer_size));
719 if (result != WIFI_SUCCESS) {
720 ALOGE("Failed to put get memory dump request; result = %d", result);
721 return result;
722 }
723
724 request.attr_end(data);
725 mBuffSize += buffer_size;
726
727 result = requestResponse(request);
728
729 if (result != WIFI_SUCCESS) {
730 ALOGE("Failed to register get momory dump response; result = %d", result);
731 }
732 } else {
733 ALOGE("dump event missing dump length attribute");
734 return NL_SKIP;
735 }
736 }
737 return NL_OK;
738 }
739 };
740
wifi_set_alert_handler(wifi_request_id id,wifi_interface_handle iface,wifi_alert_handler handler)741 wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
742 wifi_alert_handler handler)
743 {
744 wifi_handle handle = getWifiHandle(iface);
745 ALOGV("Alerthandler start, handle = %p", handle);
746
747 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
748 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
749 wifi_error result = wifi_register_cmd(handle, id, cmd);
750 if (result != WIFI_SUCCESS) {
751 cmd->releaseRef();
752 return result;
753 }
754 result = (wifi_error)cmd->start();
755 if (result != WIFI_SUCCESS) {
756 wifi_unregister_cmd(handle, id);
757 cmd->releaseRef();
758 return result;
759 }
760 return result;
761 }
762
wifi_reset_alert_handler(wifi_request_id id,wifi_interface_handle iface)763 wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)
764 {
765 wifi_handle handle = getWifiHandle(iface);
766 ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);
767
768 if (id == -1) {
769 wifi_alert_handler handler;
770 memset(&handler, 0, sizeof(handler));
771
772 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
773 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
774 cmd->cancel();
775 cmd->releaseRef();
776 return WIFI_SUCCESS;
777 }
778
779 return wifi_cancel_cmd(id, iface);
780 }
781
782 ///////////////////////////////////////////////////////////////////////////////
783 class MemoryDumpCommand: public WifiCommand
784 {
785 wifi_firmware_memory_dump_handler mHandler;
786 int mBuffSize;
787 char *mBuff;
788
789 public:
MemoryDumpCommand(wifi_interface_handle iface,wifi_firmware_memory_dump_handler handler)790 MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler)
791 : WifiCommand("MemoryDumpCommand", iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL)
792 { }
793
start()794 int start() {
795 ALOGD("Start memory dump command");
796 WifiRequest request(familyId(), ifaceId());
797
798 int result = request.create(GOOGLE_OUI, LOGGER_TRIGGER_MEM_DUMP);
799 if (result != WIFI_SUCCESS) {
800 ALOGE("Failed to create trigger fw memory dump request; result = %d", result);
801 return result;
802 }
803
804 result = requestResponse(request);
805 if (result != WIFI_SUCCESS) {
806 ALOGE("Failed to register trigger memory dump response; result = %d", result);
807 }
808 return result;
809 }
810
handleResponse(WifiEvent & reply)811 virtual int handleResponse(WifiEvent& reply) {
812 ALOGD("In MemoryDumpCommand::handleResponse");
813
814 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
815 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
816 return NL_SKIP;
817 }
818
819 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
820 int len = reply.get_vendor_data_len();
821
822 ALOGD("len = %d", len);
823 if (vendor_data == NULL || len == 0) {
824 ALOGE("no vendor data in memory dump response; ignoring it");
825 return NL_SKIP;
826 }
827
828 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
829 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
830 mBuffSize = it.get_u32();
831
832 if (mBuff)
833 free(mBuff);
834 mBuff = (char *)malloc(mBuffSize);
835 if (!mBuff) {
836 ALOGE("Buffer allocation failed");
837 return NL_SKIP;
838 }
839 WifiRequest request(familyId(), ifaceId());
840 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
841 if (result != WIFI_SUCCESS) {
842 ALOGE("Failed to create get memory dump request; result = %d", result);
843 free(mBuff);
844 return NL_SKIP;
845 }
846
847 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
848 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
849 if (result != WIFI_SUCCESS) {
850 ALOGE("Failed to put get memory dump request; result = %d", result);
851 return result;
852 }
853
854 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);
855 if (result != WIFI_SUCCESS) {
856 ALOGE("Failed to put get memory dump request; result = %d", result);
857 return result;
858 }
859 request.attr_end(data);
860
861 result = requestResponse(request);
862 if (result != WIFI_SUCCESS) {
863 ALOGE("Failed to register get momory dump response; result = %d", result);
864 }
865 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
866 ALOGI("Initiating memory dump callback");
867 if (mHandler.on_firmware_memory_dump) {
868 (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);
869 }
870 if (mBuff) {
871 free(mBuff);
872 mBuff = NULL;
873 }
874 } else {
875 ALOGW("Ignoring invalid attribute type = %d, size = %d",
876 it.get_type(), it.get_len());
877 }
878 }
879 return NL_OK;
880 }
881
handleEvent(WifiEvent & event)882 virtual int handleEvent(WifiEvent& event) {
883 /* NO events! */
884 return NL_SKIP;
885 }
886 };
887
888 /* API to collect a firmware memory dump for a given iface */
wifi_get_firmware_memory_dump(wifi_interface_handle iface,wifi_firmware_memory_dump_handler handler)889 wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
890 wifi_firmware_memory_dump_handler handler)
891 {
892 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler);
893 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
894 wifi_error result = (wifi_error)cmd->start();
895 cmd->releaseRef();
896 return result;
897 }
898
899 class PacketFateCommand: public WifiCommand
900 {
901 void *mReportBufs;
902 size_t mNoReqFates;
903 size_t *mNoProvidedFates;
904 PktFateReqType mReqType;
905
906 public:
PacketFateCommand(wifi_interface_handle handle)907 PacketFateCommand(wifi_interface_handle handle)
908 : WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START)
909 { }
910
PacketFateCommand(wifi_interface_handle handle,wifi_tx_report * tx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)911 PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
912 size_t n_requested_fates, size_t *n_provided_fates)
913 : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(tx_report_bufs),
914 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
915 mReqType(TX_PACKET_FATE)
916 { }
917
PacketFateCommand(wifi_interface_handle handle,wifi_rx_report * rx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)918 PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,
919 size_t n_requested_fates, size_t *n_provided_fates)
920 : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(rx_report_bufs),
921 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
922 mReqType(RX_PACKET_FATE)
923 { }
924
createRequest(WifiRequest & request)925 int createRequest(WifiRequest& request) {
926 if (mReqType == TX_PACKET_FATE) {
927 ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);
928 return createTxPktFateRequest(request);
929 } else if (mReqType == RX_PACKET_FATE) {
930 ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);
931 return createRxPktFateRequest(request);
932 } else if (mReqType == PACKET_MONITOR_START) {
933 ALOGD("%s Monitor packet fate request\n", __FUNCTION__);
934 return createMonitorPktFateRequest(request);
935 } else {
936 ALOGE("%s Unknown packet fate request\n", __FUNCTION__);
937 return WIFI_ERROR_NOT_SUPPORTED;
938 }
939 return WIFI_SUCCESS;
940 }
941
createMonitorPktFateRequest(WifiRequest & request)942 int createMonitorPktFateRequest(WifiRequest& request) {
943 int result = request.create(GOOGLE_OUI, LOGGER_START_PKT_FATE_MONITORING);
944 if (result < 0) {
945 return result;
946 }
947
948 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
949 request.attr_end(data);
950 return result;
951 }
952
createTxPktFateRequest(WifiRequest & request)953 int createTxPktFateRequest(WifiRequest& request) {
954 int result = request.create(GOOGLE_OUI, LOGGER_GET_TX_PKT_FATES);
955 if (result < 0) {
956 return result;
957 }
958
959 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));
960 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
961 result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
962 if (result < 0) {
963 return result;
964 }
965 result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
966 if (result < 0) {
967 return result;
968 }
969 request.attr_end(data);
970 return result;
971 }
972
createRxPktFateRequest(WifiRequest & request)973 int createRxPktFateRequest(WifiRequest& request) {
974 int result = request.create(GOOGLE_OUI, LOGGER_GET_RX_PKT_FATES);
975 if (result < 0) {
976 return result;
977 }
978
979 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));
980 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
981 result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
982 if (result < 0) {
983 return result;
984 }
985 result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
986 if (result < 0) {
987 return result;
988 }
989 request.attr_end(data);
990 return result;
991 }
992
start()993 int start() {
994 ALOGD("Start get packet fate command\n");
995 WifiRequest request(familyId(), ifaceId());
996
997 int result = createRequest(request);
998 if (result < 0) {
999 ALOGE("Failed to create get pkt fate request; result = %d\n", result);
1000 return result;
1001 }
1002
1003 result = requestResponse(request);
1004 if (result != WIFI_SUCCESS) {
1005 ALOGE("Failed to register get pkt fate response; result = %d\n", result);
1006 }
1007 return result;
1008 }
1009
handleResponse(WifiEvent & reply)1010 int handleResponse(WifiEvent& reply) {
1011 ALOGD("In GetPktFateCommand::handleResponse\n");
1012
1013 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1014 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
1015 return NL_SKIP;
1016 }
1017
1018 int id = reply.get_vendor_id();
1019 int subcmd = reply.get_vendor_subcmd();
1020 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1021 int len = reply.get_vendor_data_len();
1022
1023 ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1024
1025 if (mReqType == TX_PACKET_FATE) {
1026 ALOGI("Response recieved for get TX pkt fate command\n");
1027 } else if (mReqType == RX_PACKET_FATE) {
1028 ALOGI("Response recieved for get RX pkt fate command\n");
1029 } else if (mReqType == PACKET_MONITOR_START) {
1030 ALOGI("Response recieved for monitor pkt fate command\n");
1031 return NL_OK;
1032 } else {
1033 ALOGE("Response recieved for unknown pkt fate command\n");
1034 return NL_SKIP;
1035 }
1036
1037 if (vendor_data == NULL || len == 0) {
1038 ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
1039 return NL_SKIP;
1040 }
1041
1042 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1043 if (it.get_type() == LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
1044 *mNoProvidedFates = it.get_u32();
1045 ALOGI("No: of pkt fates provided is %d\n", *mNoProvidedFates);
1046 } else {
1047 ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
1048 it.get_type(), it.get_len());
1049 }
1050 }
1051
1052 return NL_OK;
1053 }
1054
handleEvent(WifiEvent & event)1055 int handleEvent(WifiEvent& event) {
1056 /* NO events to handle here! */
1057 return NL_SKIP;
1058 }
1059 };
1060
wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)1061 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
1062 {
1063 PacketFateCommand *cmd = new PacketFateCommand(handle);
1064 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1065 wifi_error result = (wifi_error)cmd->start();
1066 cmd->releaseRef();
1067 return result;
1068 }
1069
wifi_get_tx_pkt_fates(wifi_interface_handle handle,wifi_tx_report * tx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)1070 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
1071 wifi_tx_report *tx_report_bufs, size_t n_requested_fates,
1072 size_t *n_provided_fates)
1073 {
1074 PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,
1075 n_requested_fates, n_provided_fates);
1076 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1077 wifi_error result = (wifi_error)cmd->start();
1078 cmd->releaseRef();
1079 return result;
1080 }
1081
wifi_get_rx_pkt_fates(wifi_interface_handle handle,wifi_rx_report * rx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)1082 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
1083 wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
1084 size_t *n_provided_fates)
1085 {
1086 PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
1087 n_requested_fates, n_provided_fates);
1088 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1089 wifi_error result = (wifi_error)cmd->start();
1090 cmd->releaseRef();
1091 return result;
1092 }
1093