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