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