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