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