• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <unistd.h>
37 
38 
39 #include "nl80211_copy.h"
40 #include "sync.h"
41 
42 #define LOG_TAG  "WifiHAL"
43 
44 #include <log/log.h>
45 
46 #include "wifi_hal.h"
47 #include "common.h"
48 #include "cpp_bindings.h"
49 #include "brcm_version.h"
50 #define WIFI_HAL_EVENT_SOCK_PORT     645
51 
52 #define ARRAYSIZE(a)	(u8)(sizeof(a) / sizeof(a[0]))
53 typedef enum {
54     LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
55     LOGGER_TRIGGER_MEM_DUMP,
56     LOGGER_GET_MEM_DUMP,
57     LOGGER_GET_VER,
58     LOGGER_GET_RING_STATUS,
59     LOGGER_GET_RING_DATA,
60     LOGGER_GET_FEATURE,
61     LOGGER_RESET_LOGGING,
62     LOGGER_TRIGGER_DRIVER_MEM_DUMP,
63     LOGGER_GET_DRIVER_MEM_DUMP,
64     LOGGER_START_PKT_FATE_MONITORING,
65     LOGGER_GET_TX_PKT_FATES,
66     LOGGER_GET_RX_PKT_FATES,
67     LOGGER_GET_WAKE_REASON_STATS,
68     LOGGER_DEBUG_GET_DUMP,
69     LOGGER_FILE_DUMP_DONE_IND,
70     LOGGER_SET_HAL_START,
71     LOGGER_HAL_STOP,
72     LOGGER_SET_HAL_PID
73 } DEBUG_SUB_COMMAND;
74 
75 typedef enum {
76     LOGGER_ATTRIBUTE_DRIVER_VER,
77     LOGGER_ATTRIBUTE_FW_VER,
78     LOGGER_ATTRIBUTE_RING_ID,
79     LOGGER_ATTRIBUTE_RING_NAME,
80     LOGGER_ATTRIBUTE_RING_FLAGS,
81     LOGGER_ATTRIBUTE_LOG_LEVEL,
82     LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
83     LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
84     LOGGER_ATTRIBUTE_FW_DUMP_LEN,
85     LOGGER_ATTRIBUTE_FW_DUMP_DATA,
86     LOGGER_ATTRIBUTE_FW_ERR_CODE,
87     LOGGER_ATTRIBUTE_RING_DATA,
88     LOGGER_ATTRIBUTE_RING_STATUS,
89     LOGGER_ATTRIBUTE_RING_NUM,
90     LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
91     LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
92     LOGGER_ATTRIBUTE_PKT_FATE_NUM,
93     LOGGER_ATTRIBUTE_PKT_FATE_DATA,
94 } LOGGER_ATTRIBUTE;
95 
96 typedef enum {
97     DEBUG_OFF = 0,
98     DEBUG_NORMAL,
99     DEBUG_VERBOSE,
100     DEBUG_VERY,
101     DEBUG_VERY_VERY,
102 } LOGGER_LEVEL;
103 
104 typedef enum {
105     GET_FW_VER,
106     GET_DRV_VER,
107     GET_RING_DATA,
108     GET_RING_STATUS,
109     GET_FEATURE,
110     START_RING_LOG,
111 } GetCmdType;
112 
113 typedef enum {
114     PACKET_MONITOR_START,
115     TX_PACKET_FATE,
116     RX_PACKET_FATE,
117 } PktFateReqType;
118 
119 enum wake_stat_attributes {
120     WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT,
121     WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE,
122     WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT,
123     WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
124     WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
125     WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
126     WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT,
127     WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED,
128     WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE,
129     WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT,
130     WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT,
131     WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT,
132     WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT,
133     WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT,
134     WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA,
135     WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA,
136     WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
137     WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
138     WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
139     WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT,
140     WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO
141 };
142 
143 typedef enum {
144     SET_HAL_START_ATTRIBUTE_DEINIT = 0x0001,
145     SET_HAL_START_ATTRIBUTE_PRE_INIT = 0x0002,
146     SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
147 } SET_HAL_START_ATTRIBUTE;
148 
149 #define HAL_START_REQUEST_ID 2
150 
151 ///////////////////////////////////////////////////////////////////////////////
152 class DebugCommand : public WifiCommand
153 {
154     char *mBuff;
155     int *mBuffSize;
156     u32 *mNumRings;
157     wifi_ring_buffer_status *mStatus;
158     unsigned int *mSupport;
159     u32 mVerboseLevel;
160     u32 mFlags;
161     u32 mMaxIntervalSec;
162     u32 mMinDataSize;
163     char *mRingName;
164     GetCmdType mType;
165 
166 public:
167 
168     // constructor for get version
DebugCommand(wifi_interface_handle iface,char * buffer,int * buffer_size,GetCmdType cmdType)169     DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,
170             GetCmdType cmdType)
171         : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
172         (cmdType)
173     {
174         mNumRings =  NULL;
175         mStatus = NULL;
176         mSupport = NULL;
177         mVerboseLevel = 0;
178         mFlags = 0;
179         mMaxIntervalSec = 0;
180         mMinDataSize = 0;
181         mRingName = NULL;
182         memset(mBuff, 0, *mBuffSize);
183     }
184 
185     // constructor for ring data
DebugCommand(wifi_interface_handle iface,char * ring_name,GetCmdType cmdType)186     DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
187         : WifiCommand("DebugCommand", iface, 0), mRingName(ring_name), mType(cmdType)
188     {
189         mBuff = NULL;
190         mBuffSize = NULL;
191         mNumRings =  NULL;
192         mStatus = NULL;
193         mSupport = NULL;
194         mVerboseLevel = 0;
195         mFlags = 0;
196         mMaxIntervalSec = 0;
197         mMinDataSize = 0;
198     }
199 
200     // constructor for ring status
DebugCommand(wifi_interface_handle iface,u32 * num_rings,wifi_ring_buffer_status * status,GetCmdType cmdType)201     DebugCommand(wifi_interface_handle iface, u32 *num_rings,
202             wifi_ring_buffer_status *status, GetCmdType cmdType)
203         : WifiCommand("DebugCommand", iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
204     {
205         mBuff = NULL;
206         mBuffSize = NULL;
207         mSupport = NULL;
208         mVerboseLevel = 0;
209         mFlags = 0;
210         mMaxIntervalSec = 0;
211         mMinDataSize = 0;
212         mRingName = NULL;
213         memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
214     }
215 
216     // constructor for feature set
DebugCommand(wifi_interface_handle iface,unsigned int * support,GetCmdType cmdType)217     DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
218         : WifiCommand("DebugCommand", iface, 0), mSupport(support), mType(cmdType)
219     {
220         mBuff = NULL;
221         mBuffSize = NULL;
222         mNumRings =  NULL;
223         mStatus = NULL;
224         mVerboseLevel = 0;
225         mFlags = 0;
226         mMaxIntervalSec = 0;
227         mMinDataSize = 0;
228         mRingName = NULL;
229     }
230 
231     // 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)232     DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
233             u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)
234         : WifiCommand("DebugCommand", iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
235         mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
236         mRingName(ring_name), mType(cmdType)
237     {
238         mBuff = NULL;
239         mBuffSize = NULL;
240         mNumRings =  NULL;
241         mStatus = NULL;
242         mSupport = NULL;
243     }
244 
createRingRequest(WifiRequest & request)245     int createRingRequest(WifiRequest& request) {
246         int result = request.create(GOOGLE_OUI, LOGGER_START_LOGGING);
247         if (result != WIFI_SUCCESS) {
248             ALOGE("Failed to create start ring logger request; result = %d", result);
249             return result;
250         }
251 
252         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
253 
254         result = request.put_u32(LOGGER_ATTRIBUTE_LOG_LEVEL, mVerboseLevel);
255         if (result != WIFI_SUCCESS) {
256             ALOGE("Failed to put log level; result = %d", result);
257             return result;
258         }
259         result = request.put_u32(LOGGER_ATTRIBUTE_RING_FLAGS, mFlags);
260         if (result != WIFI_SUCCESS) {
261             ALOGE("Failed to put ring flags; result = %d", result);
262             return result;
263         }
264         result = request.put_u32(LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, mMaxIntervalSec);
265         if (result != WIFI_SUCCESS) {
266             ALOGE("Failed to put log time interval; result = %d", result);
267             return result;
268         }
269         result = request.put_u32(LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, mMinDataSize);
270         if (result != WIFI_SUCCESS) {
271             ALOGE("Failed to put min data size; result = %d", result);
272             return result;
273         }
274         result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
275         if (result != WIFI_SUCCESS) {
276             ALOGE("Failed to put ringbuffer name; result = %d", result);
277             return result;
278         }
279         request.attr_end(data);
280 
281         return WIFI_SUCCESS;
282     }
283 
createRequest(WifiRequest & request)284     int createRequest(WifiRequest &request) {
285         int result;
286 
287         switch (mType) {
288             case GET_FW_VER:
289             {
290                 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
291                 if (result != WIFI_SUCCESS) {
292                     ALOGE("Failed to create get fw version request; result = %d", result);
293                     return result;
294                 }
295 
296                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
297 
298                 // Driver expecting only attribute type, passing mbuff as data with
299                 // length 0 to avoid undefined state
300                 result = request.put(LOGGER_ATTRIBUTE_FW_VER, mBuff, 0);
301                 if (result != WIFI_SUCCESS) {
302                     ALOGE("Failed to put get fw version request; result = %d", result);
303                     return result;
304                 }
305                 request.attr_end(data);
306                 break;
307             }
308 
309             case GET_DRV_VER:
310             {
311                 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
312                 if (result != WIFI_SUCCESS) {
313                     ALOGE("Failed to create get drv version request; result = %d", result);
314                     return result;
315                 }
316 
317                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
318 
319                 // Driver expecting only attribute type, passing mbuff as data with
320                 // length 0 to avoid undefined state
321                 result = request.put(LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);
322 
323                 if (result != WIFI_SUCCESS) {
324                     ALOGE("Failed to put get drv version request; result = %d", result);
325                     return result;
326                 }
327                 request.attr_end(data);
328                 break;
329             }
330 
331             case GET_RING_DATA:
332             {
333                 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_DATA);
334                 if (result != WIFI_SUCCESS) {
335                     ALOGE("Failed to create get ring data request; result = %d", result);
336                     return result;
337                 }
338 
339                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
340                 result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
341                 if (result != WIFI_SUCCESS) {
342                     ALOGE("Failed to put ring data request; result = %d", result);
343                     return result;
344                 }
345                 request.attr_end(data);
346                 break;
347             }
348 
349             case GET_RING_STATUS:
350             {
351                 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_STATUS);
352                 if (result != WIFI_SUCCESS) {
353                     ALOGE("Failed to create get ring status request; result = %d", result);
354                     return result;
355                 }
356                 break;
357             }
358 
359             case GET_FEATURE:
360             {
361                 result = request.create(GOOGLE_OUI, LOGGER_GET_FEATURE);
362                 if (result != WIFI_SUCCESS) {
363                     ALOGE("Failed to create get feature request; result = %d", result);
364                     return result;
365                 }
366                 break;
367             }
368 
369             case START_RING_LOG:
370                 result = createRingRequest(request);
371                 break;
372 
373             default:
374                 ALOGE("Unknown Debug command");
375                 result = WIFI_ERROR_UNKNOWN;
376         }
377         return result;
378     }
379 
start()380     int start() {
381         // ALOGD("Start debug command");
382         WifiRequest request(familyId(), ifaceId());
383         int result = createRequest(request);
384         if (result != WIFI_SUCCESS) {
385             ALOGE("Failed to create debug request; result = %d", result);
386             return result;
387         }
388 
389         result = requestResponse(request);
390         if (result != WIFI_SUCCESS) {
391             ALOGE("Failed to register debug response; result = %d", result);
392         }
393         return result;
394     }
395 
handleResponse(WifiEvent & reply)396     virtual int handleResponse(WifiEvent& reply) {
397         ALOGD("In DebugCommand::handleResponse");
398 
399         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
400             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
401             return NL_SKIP;
402         }
403 
404         switch (mType) {
405             case GET_DRV_VER:
406             case GET_FW_VER:
407             {
408                 void *data = reply.get_vendor_data();
409                 int len = reply.get_vendor_data_len();
410 
411                 ALOGD("len = %d, expected len = %d", len, *mBuffSize);
412                 memcpy(mBuff, data, min(len, *mBuffSize));
413                 if (*mBuffSize < len)
414                     return NL_SKIP;
415                 *mBuffSize = len;
416                 break;
417             }
418 
419             case START_RING_LOG:
420             case GET_RING_DATA:
421                 break;
422 
423             case GET_RING_STATUS:
424             {
425                 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
426                 int len = reply.get_vendor_data_len();
427                 wifi_ring_buffer_status *status(mStatus);
428 
429                 if (vendor_data == NULL || len == 0) {
430                     ALOGE("No Debug data found");
431                     return NL_SKIP;
432                 }
433 
434                 nl_iterator it(vendor_data);
435                 if (it.get_type() == LOGGER_ATTRIBUTE_RING_NUM) {
436                     unsigned int num_rings = it.get_u32();
437                     if (*mNumRings < num_rings) {
438                         ALOGE("Not enough status buffers provided, available: %d required: %d",
439                                 *mNumRings, num_rings);
440                     } else {
441                         *mNumRings = num_rings;
442                     }
443                 } else {
444                     ALOGE("Unknown attribute: %d expecting %d",
445                             it.get_type(), LOGGER_ATTRIBUTE_RING_NUM);
446                     return NL_SKIP;
447                 }
448 
449                 it.next();
450                 for (unsigned int i = 0; it.has_next() && i < *mNumRings; it.next()) {
451                     if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
452                         memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status));
453                         i++;
454                         status++;
455                     } else {
456                         ALOGW("Ignoring invalid attribute type = %d, size = %d",
457                                 it.get_type(), it.get_len());
458                     }
459                 }
460                 break;
461             }
462 
463             case GET_FEATURE:
464             {
465                 void *data = reply.get_vendor_data();
466                 int len = reply.get_vendor_data_len();
467 
468                 ALOGD("len = %d, expected len = %d", len, sizeof(unsigned int));
469                 memcpy(mSupport, data, sizeof(unsigned int));
470                 break;
471             }
472 
473             default:
474                 ALOGW("Unknown Debug command");
475         }
476         return NL_OK;
477     }
478 
handleEvent(WifiEvent & event)479     virtual int handleEvent(WifiEvent& event) {
480         /* NO events! */
481         return NL_SKIP;
482     }
483 };
484 
485 /* API to collect a firmware version string */
wifi_get_firmware_version(wifi_interface_handle iface,char * buffer,int buffer_size)486 wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
487         int buffer_size)
488 {
489     if (buffer && (buffer_size > 0)) {
490         DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);
491         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
492         wifi_error result = (wifi_error)cmd->start();
493         cmd->releaseRef();
494         return result;
495     } else {
496         ALOGE("FW version buffer NULL");
497         return  WIFI_ERROR_INVALID_ARGS;
498     }
499 }
500 
501 /* API to collect a driver version string */
wifi_get_driver_version(wifi_interface_handle iface,char * buffer,int buffer_size)502 wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
503 {
504     if (buffer && (buffer_size > 0)) {
505         DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);
506         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
507         wifi_error result = (wifi_error)cmd->start();
508         cmd->releaseRef();
509         return result;
510     } else {
511         ALOGE("Driver version buffer NULL");
512         return  WIFI_ERROR_INVALID_ARGS;
513     }
514 }
515 
516 /* API to collect driver records */
wifi_get_ring_data(wifi_interface_handle iface,char * ring_name)517 wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)
518 {
519     DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);
520     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
521     wifi_error result = (wifi_error)cmd->start();
522     cmd->releaseRef();
523     return result;
524 }
525 
526 /* 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)527 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
528         u32 *num_rings, wifi_ring_buffer_status *status)
529 {
530     if (status && num_rings) {
531         DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);
532         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
533         wifi_error result = (wifi_error)cmd->start();
534         cmd->releaseRef();
535         return result;
536     } else {
537         ALOGE("Ring status buffer NULL");
538         return  WIFI_ERROR_INVALID_ARGS;
539     }
540 }
541 
542 /* API to get supportable feature */
wifi_get_logger_supported_feature_set(wifi_interface_handle iface,unsigned int * support)543 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
544         unsigned int *support)
545 {
546     if (support) {
547         DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);
548         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
549         wifi_error result = (wifi_error)cmd->start();
550         cmd->releaseRef();
551         return result;
552     } else {
553         ALOGE("Get support buffer NULL");
554         return  WIFI_ERROR_INVALID_ARGS;
555     }
556 }
557 
wifi_start_logging(wifi_interface_handle iface,u32 verbose_level,u32 flags,u32 max_interval_sec,u32 min_data_size,char * ring_name)558 wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
559         u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
560 {
561     if (ring_name) {
562         DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
563                     min_data_size, ring_name, START_RING_LOG);
564         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
565         wifi_error result = (wifi_error)cmd->start();
566         cmd->releaseRef();
567         return result;
568     } else {
569         ALOGE("Ring name NULL");
570         return  WIFI_ERROR_INVALID_ARGS;
571     }
572 }
573 
574 
575 ///////////////////////////////////////////////////////////////////////////////
576 class SetLogHandler : public WifiCommand
577 {
578     wifi_ring_buffer_data_handler mHandler;
579 
580 public:
SetLogHandler(wifi_interface_handle iface,int id,wifi_ring_buffer_data_handler handler)581     SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
582         : WifiCommand("SetLogHandler", iface, id), mHandler(handler)
583     { }
584 
start()585     int start() {
586         ALOGV("Register loghandler");
587         int result;
588         uint32_t event_sock_pid = getpid() + (WIFI_HAL_EVENT_SOCK_PORT << 22);
589         registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
590 
591         WifiRequest request(familyId(), ifaceId());
592 
593         /* set hal event socket port to driver */
594         result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_PID);
595         if (result != WIFI_SUCCESS) {
596             ALOGV("Failed to set Hal preInit; result = %d", result);
597             return result;
598         }
599         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
600         result = request.put_u32(SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID, event_sock_pid);
601         if (result != WIFI_SUCCESS) {
602             ALOGV("Hal preInit Failed to put pic = %d", result);
603             return result;
604         }
605 
606         if (result != WIFI_SUCCESS) {
607             ALOGV("Hal preInit Failed to put pid= %d", result);
608             return result;
609         }
610 
611         request.attr_end(data);
612 
613         result = requestResponse(request);
614         if (result != WIFI_SUCCESS) {
615             ALOGE("Failed to register set Hal preInit; result = %d", result);
616             return result;
617         }
618         return result;
619     }
620 
cancel()621     virtual int cancel() {
622         /* Send a command to driver to stop generating logging events */
623         ALOGV("Clear loghandler");
624 
625         /* unregister event handler */
626         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
627 
628         WifiRequest request(familyId(), ifaceId());
629         int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
630         if (result != WIFI_SUCCESS) {
631             ALOGE("failed to create reset request; result = %d", result);
632             return result;
633         }
634 
635         result = requestResponse(request);
636         if (result != WIFI_SUCCESS) {
637             ALOGE("failed to request reset; result = %d", result);
638             return result;
639         }
640 
641         ALOGD("Success to clear loghandler");
642         return WIFI_SUCCESS;
643     }
644 
handleEvent(WifiEvent & event)645     virtual int handleEvent(WifiEvent& event) {
646         char *buffer = NULL;
647         int buffer_size = 0;
648 
649         // ALOGD("In SetLogHandler::handleEvent");
650         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
651         int len = event.get_vendor_data_len();
652         int event_id = event.get_vendor_subcmd();
653         // ALOGI("Got Logger event: %d", event_id);
654 
655         if (vendor_data == NULL || len == 0) {
656             ALOGE("No Debug data found");
657             return NL_SKIP;
658         }
659 
660         if(event_id == GOOGLE_DEBUG_RING_EVENT) {
661             wifi_ring_buffer_status status;
662             memset(&status, 0, sizeof(status));
663 
664             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
665                 if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
666                     memcpy(&status, it.get_data(), sizeof(status));
667                 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
668                     buffer_size = it.get_len();
669                     buffer = (char *)it.get_data();
670                 } else {
671                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
672                             it.get_type(), it.get_len());
673                 }
674             }
675 
676             // ALOGI("Retrieved Debug data");
677             if (mHandler.on_ring_buffer_data) {
678                 /* Skip msg header. Retrieved log */
679                 char *pBuff;
680                 wifi_ring_buffer_entry *buffer_entry =
681                             (wifi_ring_buffer_entry *) buffer;
682                 pBuff = (char *) (buffer_entry + 1);
683                 (*mHandler.on_ring_buffer_data)((char *)status.name, pBuff,
684                     buffer_entry->entry_size, &status);
685             }
686         } else {
687             ALOGE("Unknown Event");
688             return NL_SKIP;
689         }
690         return NL_OK;
691     }
692 };
693 
wifi_set_log_handler(wifi_request_id id,wifi_interface_handle iface,wifi_ring_buffer_data_handler handler)694 wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
695         wifi_ring_buffer_data_handler handler)
696 {
697     wifi_handle handle = getWifiHandle(iface);
698     ALOGV("Loghandler start, handle = %p", handle);
699 
700     SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
701     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
702     wifi_error result = wifi_register_cmd(handle, id, cmd);
703     if (result != WIFI_SUCCESS) {
704         cmd->releaseRef();
705         return result;
706     }
707     result = (wifi_error)cmd->start();
708     if (result != WIFI_SUCCESS) {
709         wifi_unregister_cmd(handle, id);
710         cmd->releaseRef();
711         return result;
712     }
713     return result;
714 }
715 
wifi_reset_log_handler(wifi_request_id id,wifi_interface_handle iface)716 wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
717 {
718     wifi_handle handle = getWifiHandle(iface);
719     ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
720 
721     if (id == -1) {
722         wifi_ring_buffer_data_handler handler;
723         memset(&handler, 0, sizeof(handler));
724 
725         SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
726         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
727         cmd->cancel();
728         cmd->releaseRef();
729         return WIFI_SUCCESS;
730     }
731 
732     return wifi_cancel_cmd(id, iface);
733 }
734 
735 ///////////////////////////////////////////////////////////////////////////////
736 class SetAlertHandler : public WifiCommand
737 {
738     wifi_alert_handler mHandler;
739     int mBuffSize;
740     char *mBuff;
741     int mErrCode;
742 
743 public:
SetAlertHandler(wifi_interface_handle iface,int id,wifi_alert_handler handler)744     SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)
745         : WifiCommand("SetAlertHandler", iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),
746             mErrCode(0)
747     { }
748 
start()749     int start() {
750         ALOGV("Start Alerting");
751         registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
752         return WIFI_SUCCESS;
753     }
754 
cancel()755     virtual int cancel() {
756         ALOGV("Clear alerthandler");
757 
758         /* unregister alert handler */
759         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
760         wifi_unregister_cmd(wifiHandle(), id());
761         ALOGD("Success to clear alerthandler");
762         return WIFI_SUCCESS;
763     }
764 
handleResponse(WifiEvent & reply)765     virtual int handleResponse(WifiEvent& reply) {
766         ALOGD("In SetAlertHandler::handleResponse");
767 
768         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
769             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
770             return NL_SKIP;
771         }
772 
773         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
774         int len = reply.get_vendor_data_len();
775 
776         ALOGD("len = %d", len);
777         if (vendor_data == NULL || len == 0) {
778             ALOGE("no vendor data in memory dump response; ignoring it");
779             return NL_SKIP;
780         }
781 
782         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
783             if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
784                 ALOGI("Initiating alert callback");
785                 if (mHandler.on_alert) {
786                     (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
787                 }
788                 if (mBuff) {
789                     free(mBuff);
790                     mBuff = NULL;
791                 }
792             }
793         }
794         return NL_OK;
795     }
796 
handleEvent(WifiEvent & event)797     virtual int handleEvent(WifiEvent& event) {
798         wifi_ring_buffer_id ring_id;
799         char *buffer = NULL;
800         int buffer_size = 0;
801         bool is_err_alert = false;
802 
803         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
804         int len = event.get_vendor_data_len();
805         int event_id = event.get_vendor_subcmd();
806         ALOGI("Got event: %d", event_id);
807 
808         if (vendor_data == NULL || len == 0) {
809             ALOGE("No Debug data found");
810             return NL_SKIP;
811         }
812 
813         if (event_id == GOOGLE_DEBUG_MEM_DUMP_EVENT) {
814             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
815                 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
816                     mBuffSize = it.get_u32();
817                 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
818                     buffer_size = it.get_len();
819                     buffer = (char *)it.get_data();
820                 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_ERR_CODE) {
821                     /* Error code is for error alert event only */
822                     mErrCode = it.get_u32();
823                     is_err_alert = true;
824                 } else {
825                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
826                             it.get_type(), it.get_len());
827                 }
828             }
829 
830             if(is_err_alert) {
831                 mBuffSize = sizeof(mErrCode);
832                 if (mBuff) free(mBuff);
833                 mBuff = (char *)malloc(mBuffSize);
834                 if (!mBuff) {
835                   ALOGE("Buffer allocation failed");
836                   return NL_SKIP;
837                 }
838                 memcpy(mBuff, (char *)&mErrCode, mBuffSize);
839                 ALOGI("Initiating alert callback");
840                 if (mHandler.on_alert) {
841                   (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
842                 }
843                 if (mBuff) {
844                   free(mBuff);
845                   mBuff = NULL;
846                 }
847                 mBuffSize = 0;
848                 return NL_OK;
849             }
850 
851             if (mBuffSize) {
852                 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
853                 if (mBuff) free(mBuff);
854                 mBuff = (char *)malloc(mBuffSize + buffer_size);
855                 if (!mBuff) {
856                     ALOGE("Buffer allocation failed");
857                     return NL_SKIP;
858                 }
859                 memcpy(mBuff, buffer, buffer_size);
860 
861                 WifiRequest request(familyId(), ifaceId());
862                 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
863                 if (result != WIFI_SUCCESS) {
864                     ALOGE("Failed to create get memory dump request; result = %d", result);
865                     free(mBuff);
866                     return NL_SKIP;
867                 }
868                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
869                 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
870                 if (result != WIFI_SUCCESS) {
871                     ALOGE("Failed to put get memory dump request; result = %d", result);
872                     return result;
873                 }
874 
875                 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA,
876                          (uint64_t)(mBuff+buffer_size));
877                 if (result != WIFI_SUCCESS) {
878                     ALOGE("Failed to put get memory dump request; result = %d", result);
879                     return result;
880                 }
881 
882                 request.attr_end(data);
883                 mBuffSize += buffer_size;
884 
885                 result = requestResponse(request);
886 
887                 if (result != WIFI_SUCCESS) {
888                     ALOGE("Failed to register get momory dump response; result = %d", result);
889                 }
890             } else {
891                 ALOGE("dump event missing dump length attribute");
892                 return NL_SKIP;
893             }
894         }
895         return NL_OK;
896     }
897 };
898 
899 ///////////////////////////////////////////////////////////////////////////////
900 class HalInit : public WifiCommand
901 {
902     int mErrCode;
903 
904     public:
HalInit(wifi_interface_handle iface,int id)905     HalInit(wifi_interface_handle iface, int id)
906         : WifiCommand("HalInit", iface, id), mErrCode(0)
907     { }
908 
start()909     int start() {
910         ALOGE("Start Set Hal");
911         WifiRequest request(familyId(), ifaceId());
912 
913         int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
914         if (result != WIFI_SUCCESS) {
915             ALOGE("Failed to set hal start; result = %d", result);
916             return result;
917         }
918 
919         result = requestResponse(request);
920         if (result != WIFI_SUCCESS) {
921             ALOGE("Failed to register set hal start response; result = %d", result);
922         }
923         return result;
924     }
925 
926 
cancel()927     virtual int cancel() {
928         ALOGE("Cancel: Stop Hal");
929         WifiRequest request(familyId(), ifaceId());
930 
931         int result = request.create(GOOGLE_OUI, LOGGER_HAL_STOP);
932         if (result != WIFI_SUCCESS) {
933             ALOGE("Failed to stop hal ; result = %d", result);
934             return result;
935         }
936 
937         result = requestResponse(request);
938         if (result != WIFI_SUCCESS) {
939             ALOGE("Failed to register set hal start response; result = %d", result);
940         }
941         wifi_unregister_cmd(wifiHandle(), id());
942         return result;
943     }
944 
preInit()945     int preInit() {
946         ALOGE("Hal preInit");
947         WifiRequest request(familyId(), ifaceId());
948 
949         int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
950         if (result != WIFI_SUCCESS) {
951             ALOGE("Failed to set Hal preInit; result = %d", result);
952             return result;
953         }
954 
955         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
956         result = request.put_string(SET_HAL_START_ATTRIBUTE_PRE_INIT, (char *)HAL_VERSION);
957         if (result != WIFI_SUCCESS) {
958             ALOGE("Hal preInit Failed to put data= %d", result);
959             return result;
960         }
961         request.attr_end(data);
962 
963         result = requestResponse(request);
964         if (result != WIFI_SUCCESS) {
965             ALOGE("Failed to register set Hal preInit; result = %d", result);
966         }
967         return result;
968     }
969 
handleResponse(WifiEvent & reply)970     virtual int handleResponse(WifiEvent& reply) {
971         ALOGE("In SetHalStarted::handleResponse");
972 
973         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
974             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
975             return NL_SKIP;
976         }
977         return NL_OK;
978     }
979 
handleEvent(WifiEvent & event)980     virtual int handleEvent(WifiEvent& event) {
981         /* NO events! */
982         return NL_SKIP;
983     }
984 };
985 
986 
wifi_start_hal(wifi_interface_handle iface)987 wifi_error wifi_start_hal(wifi_interface_handle iface)
988 {
989     wifi_handle handle = getWifiHandle(iface);
990     ALOGV("HAL INIT start, handle = %p", handle);
991 
992     HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
993     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
994     wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
995     if (result != WIFI_SUCCESS) {
996         cmd->releaseRef();
997         return result;
998     }
999     result = (wifi_error)cmd->start();
1000     if (result != WIFI_SUCCESS) {
1001         wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
1002         cmd->releaseRef();
1003         return result;
1004     }
1005     return result;
1006 }
1007 
wifi_hal_preInit(wifi_interface_handle iface)1008 wifi_error wifi_hal_preInit(wifi_interface_handle iface)
1009 {
1010     wifi_handle handle = getWifiHandle(iface);
1011     ALOGV("wifi_hal_preInit, handle = %p", handle);
1012 
1013     HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
1014     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1015     wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
1016     if (result != WIFI_SUCCESS) {
1017         cmd->releaseRef();
1018         return result;
1019     }
1020     result = (wifi_error)cmd->preInit();
1021     if (result != WIFI_SUCCESS) {
1022         wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
1023         cmd->releaseRef();
1024         return result;
1025     }
1026     return result;
1027 }
1028 
wifi_stop_hal(wifi_interface_handle iface)1029 wifi_error wifi_stop_hal(wifi_interface_handle iface)
1030 {
1031     wifi_handle handle = getWifiHandle(iface);
1032 
1033     HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
1034     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1035     cmd->cancel();
1036     cmd->releaseRef();
1037     return WIFI_SUCCESS;
1038 }
1039 
wifi_set_alert_handler(wifi_request_id id,wifi_interface_handle iface,wifi_alert_handler handler)1040 wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
1041         wifi_alert_handler handler)
1042 {
1043     wifi_handle handle = getWifiHandle(iface);
1044     ALOGV("Alerthandler start, handle = %p", handle);
1045 
1046     SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
1047     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1048     wifi_error result = wifi_register_cmd(handle, id, cmd);
1049     if (result != WIFI_SUCCESS) {
1050         cmd->releaseRef();
1051         return result;
1052     }
1053     result = (wifi_error)cmd->start();
1054     if (result != WIFI_SUCCESS) {
1055         wifi_unregister_cmd(handle, id);
1056         cmd->releaseRef();
1057         return result;
1058     }
1059     return result;
1060 }
1061 
wifi_reset_alert_handler(wifi_request_id id,wifi_interface_handle iface)1062 wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)
1063 {
1064     wifi_handle handle = getWifiHandle(iface);
1065     ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);
1066 
1067     if (id == -1) {
1068         wifi_alert_handler handler;
1069         memset(&handler, 0, sizeof(handler));
1070 
1071         SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
1072         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1073         cmd->cancel();
1074         cmd->releaseRef();
1075         return WIFI_SUCCESS;
1076     }
1077 
1078     return wifi_cancel_cmd(id, iface);
1079 }
1080 
1081 ///////////////////////////////////////////////////////////////////////////////
1082 class MemoryDumpCommand: public WifiCommand
1083 {
1084     wifi_firmware_memory_dump_handler mHandler;
1085     int mBuffSize;
1086     char *mBuff;
1087 
1088 public:
MemoryDumpCommand(wifi_interface_handle iface,wifi_firmware_memory_dump_handler handler)1089     MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler)
1090         : WifiCommand("MemoryDumpCommand", iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL)
1091     { }
1092 
start()1093     int start() {
1094         ALOGD("Start memory dump command");
1095         WifiRequest request(familyId(), ifaceId());
1096 
1097         int result = request.create(GOOGLE_OUI, LOGGER_TRIGGER_MEM_DUMP);
1098         if (result != WIFI_SUCCESS) {
1099             ALOGE("Failed to create trigger fw memory dump request; result = %d", result);
1100             return result;
1101         }
1102 
1103         result = requestResponse(request);
1104         if (result != WIFI_SUCCESS) {
1105             ALOGE("Failed to register trigger memory dump response; result = %d", result);
1106         }
1107         return result;
1108     }
1109 
handleResponse(WifiEvent & reply)1110     virtual int handleResponse(WifiEvent& reply) {
1111         ALOGD("In MemoryDumpCommand::handleResponse");
1112 
1113         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1114             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1115             return NL_SKIP;
1116         }
1117 
1118         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1119         int len = reply.get_vendor_data_len();
1120 
1121         ALOGD("len = %d", len);
1122         if (vendor_data == NULL || len == 0) {
1123             ALOGE("no vendor data in memory dump response; ignoring it");
1124             return NL_SKIP;
1125         }
1126 
1127         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1128             if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
1129                 mBuffSize = it.get_u32();
1130 
1131                 if (mBuff)
1132                     free(mBuff);
1133                 mBuff = (char *)malloc(mBuffSize);
1134                 if (!mBuff) {
1135                     ALOGE("Buffer allocation failed");
1136                     return NL_SKIP;
1137                 }
1138                 WifiRequest request(familyId(), ifaceId());
1139                 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
1140                 if (result != WIFI_SUCCESS) {
1141                     ALOGE("Failed to create get memory dump request; result = %d", result);
1142                     free(mBuff);
1143                     return NL_SKIP;
1144                 }
1145 
1146                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1147                 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
1148                 if (result != WIFI_SUCCESS) {
1149                     ALOGE("Failed to put get memory dump request; result = %d", result);
1150                     return result;
1151                 }
1152 
1153                 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);
1154                 if (result != WIFI_SUCCESS) {
1155                     ALOGE("Failed to put get memory dump request; result = %d", result);
1156                     return result;
1157                 }
1158                 request.attr_end(data);
1159 
1160                 result = requestResponse(request);
1161                 if (result != WIFI_SUCCESS) {
1162                     ALOGE("Failed to register get momory dump response; result = %d", result);
1163                 }
1164             } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
1165                 ALOGI("Initiating memory dump callback");
1166                 if (mHandler.on_firmware_memory_dump) {
1167                     (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);
1168                 }
1169                 if (mBuff) {
1170                     free(mBuff);
1171                     mBuff = NULL;
1172                 }
1173             } else {
1174                 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1175                         it.get_type(), it.get_len());
1176             }
1177         }
1178         return NL_OK;
1179     }
1180 
handleEvent(WifiEvent & event)1181     virtual int handleEvent(WifiEvent& event) {
1182         /* NO events! */
1183         return NL_SKIP;
1184     }
1185 };
1186 
1187 /* 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)1188 wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
1189         wifi_firmware_memory_dump_handler handler)
1190 {
1191     MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler);
1192     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1193     wifi_error result = (wifi_error)cmd->start();
1194     cmd->releaseRef();
1195     return result;
1196 }
1197 
1198 class PacketFateCommand: public WifiCommand
1199 {
1200     void *mReportBufs;
1201     size_t mNoReqFates;
1202     size_t *mNoProvidedFates;
1203     PktFateReqType mReqType;
1204 
1205 public:
PacketFateCommand(wifi_interface_handle handle)1206     PacketFateCommand(wifi_interface_handle handle)
1207         : WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START)
1208     {
1209         mReportBufs = NULL;
1210         mNoReqFates = 0;
1211         mNoProvidedFates = NULL;
1212     }
1213 
PacketFateCommand(wifi_interface_handle handle,wifi_tx_report * tx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)1214     PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
1215             size_t n_requested_fates, size_t *n_provided_fates)
1216         : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(tx_report_bufs),
1217                   mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
1218                   mReqType(TX_PACKET_FATE)
1219     { }
1220 
PacketFateCommand(wifi_interface_handle handle,wifi_rx_report * rx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)1221     PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,
1222             size_t n_requested_fates, size_t *n_provided_fates)
1223         : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(rx_report_bufs),
1224                   mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
1225                   mReqType(RX_PACKET_FATE)
1226     { }
1227 
createRequest(WifiRequest & request)1228     int createRequest(WifiRequest& request) {
1229         if (mReqType == TX_PACKET_FATE) {
1230             ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);
1231             return createTxPktFateRequest(request);
1232         } else if (mReqType == RX_PACKET_FATE) {
1233             ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);
1234             return createRxPktFateRequest(request);
1235         } else if (mReqType == PACKET_MONITOR_START) {
1236             ALOGD("%s Monitor packet fate request\n", __FUNCTION__);
1237             return createMonitorPktFateRequest(request);
1238         } else {
1239             ALOGE("%s Unknown packet fate request\n", __FUNCTION__);
1240             return WIFI_ERROR_NOT_SUPPORTED;
1241         }
1242         return WIFI_SUCCESS;
1243     }
1244 
createMonitorPktFateRequest(WifiRequest & request)1245     int createMonitorPktFateRequest(WifiRequest& request) {
1246         int result = request.create(GOOGLE_OUI, LOGGER_START_PKT_FATE_MONITORING);
1247         if (result < 0) {
1248             return result;
1249         }
1250 
1251         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1252         request.attr_end(data);
1253         return result;
1254     }
1255 
createTxPktFateRequest(WifiRequest & request)1256     int createTxPktFateRequest(WifiRequest& request) {
1257         int result = request.create(GOOGLE_OUI, LOGGER_GET_TX_PKT_FATES);
1258         if (result < 0) {
1259             return result;
1260         }
1261 
1262         memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));
1263         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1264         result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
1265         if (result < 0) {
1266             return result;
1267         }
1268         result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
1269         if (result < 0) {
1270             return result;
1271         }
1272         request.attr_end(data);
1273         return result;
1274     }
1275 
createRxPktFateRequest(WifiRequest & request)1276     int createRxPktFateRequest(WifiRequest& request) {
1277         int result = request.create(GOOGLE_OUI, LOGGER_GET_RX_PKT_FATES);
1278         if (result < 0) {
1279             return result;
1280         }
1281 
1282         memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));
1283         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1284         result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
1285         if (result < 0) {
1286             return result;
1287         }
1288         result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
1289         if (result < 0) {
1290             return result;
1291         }
1292         request.attr_end(data);
1293         return result;
1294     }
1295 
start()1296     int start() {
1297         ALOGD("Start get packet fate command\n");
1298         WifiRequest request(familyId(), ifaceId());
1299 
1300         int result = createRequest(request);
1301         if (result < 0) {
1302             ALOGE("Failed to create get pkt fate request; result = %d\n", result);
1303             return result;
1304         }
1305 
1306         result = requestResponse(request);
1307         if (result != WIFI_SUCCESS) {
1308             ALOGE("Failed to register get pkt fate response; result = %d\n", result);
1309         }
1310         return result;
1311     }
1312 
handleResponse(WifiEvent & reply)1313     int handleResponse(WifiEvent& reply) {
1314         ALOGD("In GetPktFateCommand::handleResponse\n");
1315 
1316         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1317             ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
1318             return NL_SKIP;
1319         }
1320 
1321         int id = reply.get_vendor_id();
1322         int subcmd = reply.get_vendor_subcmd();
1323         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1324         int len = reply.get_vendor_data_len();
1325 
1326         ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1327 
1328         if (mReqType == TX_PACKET_FATE) {
1329             ALOGI("Response recieved for get TX pkt fate command\n");
1330         } else if (mReqType == RX_PACKET_FATE) {
1331             ALOGI("Response recieved for get RX pkt fate command\n");
1332         } else if (mReqType == PACKET_MONITOR_START) {
1333             ALOGI("Response recieved for monitor pkt fate command\n");
1334             return NL_OK;
1335         } else {
1336             ALOGE("Response recieved for unknown pkt fate command\n");
1337             return NL_SKIP;
1338         }
1339 
1340         if (vendor_data == NULL || len == 0) {
1341             ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
1342             return NL_SKIP;
1343         }
1344 
1345         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1346             if (it.get_type() == LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
1347                 *mNoProvidedFates = it.get_u32();
1348                 ALOGI("No: of pkt fates provided is %d\n", *mNoProvidedFates);
1349             } else {
1350                 ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
1351                         it.get_type(), it.get_len());
1352             }
1353         }
1354 
1355         return NL_OK;
1356     }
1357 
handleEvent(WifiEvent & event)1358     int handleEvent(WifiEvent& event) {
1359         /* NO events to handle here! */
1360         return NL_SKIP;
1361     }
1362 };
1363 
1364 class GetWakeReasonCountCommand : public WifiCommand {
1365     WLAN_DRIVER_WAKE_REASON_CNT *mWakeReasonCnt;
1366     void *mCmdEventWakeCount;
1367     public:
GetWakeReasonCountCommand(wifi_interface_handle handle,WLAN_DRIVER_WAKE_REASON_CNT * wlanDriverWakeReasonCount)1368     GetWakeReasonCountCommand(wifi_interface_handle handle,
1369         WLAN_DRIVER_WAKE_REASON_CNT *wlanDriverWakeReasonCount) :
1370         WifiCommand("GetWakeReasonCountCommand", handle, 0),
1371         mWakeReasonCnt(wlanDriverWakeReasonCount)
1372     {
1373         mCmdEventWakeCount = mWakeReasonCnt->cmd_event_wake_cnt;
1374     }
1375 
createRequest(WifiRequest & request)1376     int createRequest(WifiRequest& request) {
1377         int result = request.create(GOOGLE_OUI, LOGGER_GET_WAKE_REASON_STATS);
1378         if (result < 0) {
1379             return result;
1380         }
1381 
1382         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1383 
1384         request.attr_end(data);
1385         return WIFI_SUCCESS;
1386     }
1387 
start()1388     int start() {
1389         ALOGD("Start get wake stats command\n");
1390         WifiRequest request(familyId(), ifaceId());
1391 
1392         int result = createRequest(request);
1393         if (result < 0) {
1394             ALOGE("Failed to create request result = %d\n", result);
1395             return result;
1396         }
1397 
1398         result = requestResponse(request);
1399         if (result != WIFI_SUCCESS) {
1400             ALOGE("Failed to register wake stats  response; result = %d\n", result);
1401         }
1402         return result;
1403     }
1404 
1405     protected:
handleResponse(WifiEvent & reply)1406     int handleResponse(WifiEvent& reply) {
1407         ALOGE("In GetWakeReasonCountCommand::handleResponse");
1408 
1409         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1410             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1411             return NL_SKIP;
1412         }
1413 
1414         int id = reply.get_vendor_id();
1415         int subcmd = reply.get_vendor_subcmd();
1416 
1417         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1418         int len = reply.get_vendor_data_len();
1419 
1420         ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1421         if (vendor_data == NULL || len == 0) {
1422             ALOGE("no vendor data in GetGetWakeReasonCountCommand response; ignoring it");
1423             return NL_SKIP;
1424         }
1425 
1426         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1427             switch (it.get_type()) {
1428                 case WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW:
1429                     mWakeReasonCnt->total_driver_fw_local_wake =
1430                         it.get_u32();
1431                     break;
1432                 case WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT:
1433                     mWakeReasonCnt->total_cmd_event_wake =
1434                         it.get_u32();
1435                     break;
1436                 case WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED:
1437                     mWakeReasonCnt->cmd_event_wake_cnt_used =
1438                         it.get_u32();
1439                     break;
1440                 case WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE:
1441                     memcpy(mCmdEventWakeCount, it.get_data(),
1442                             (mWakeReasonCnt->cmd_event_wake_cnt_used * sizeof(int)));
1443                     break;
1444                 case WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE:
1445                     mWakeReasonCnt->total_rx_data_wake =
1446                         it.get_u32();
1447                     break;
1448                 case WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT:
1449                     mWakeReasonCnt->rx_wake_details.rx_unicast_cnt =
1450                         it.get_u32();
1451                     break;
1452                 case WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT:
1453                     mWakeReasonCnt->rx_wake_details.rx_multicast_cnt =
1454                         it.get_u32();
1455                     break;
1456                 case WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT:
1457                     mWakeReasonCnt->rx_wake_details.rx_broadcast_cnt =
1458                         it.get_u32();
1459                     break;
1460                 case WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT:
1461                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp_pkt =
1462                         it.get_u32();
1463                     break;
1464                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT:
1465                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_pkt =
1466                         it.get_u32();
1467                     break;
1468                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA:
1469                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ra =
1470                         it.get_u32();
1471                     break;
1472                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA:
1473                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_na =
1474                         it.get_u32();
1475                     break;
1476                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS:
1477                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ns =
1478                         it.get_u32();
1479                     break;
1480                 case WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT:
1481                     mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt =
1482                         it.get_u32();
1483                     break;
1484                 case WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT:
1485                     mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
1486                         it.get_u32();
1487                     break;
1488                 case WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT:
1489                     mWakeReasonCnt->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
1490                         it.get_u32();
1491                     break;
1492                 default:
1493                     break;
1494             }
1495 
1496         }
1497         return NL_OK;
1498     }
1499 };
1500 
wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)1501 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
1502 {
1503     PacketFateCommand *cmd = new PacketFateCommand(handle);
1504     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1505     wifi_error result = (wifi_error)cmd->start();
1506     cmd->releaseRef();
1507     return result;
1508 }
1509 
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)1510 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
1511         wifi_tx_report *tx_report_bufs, size_t n_requested_fates,
1512         size_t *n_provided_fates)
1513 {
1514     PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,
1515                 n_requested_fates, n_provided_fates);
1516     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1517     wifi_error result = (wifi_error)cmd->start();
1518     cmd->releaseRef();
1519     return result;
1520 }
1521 
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)1522 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
1523         wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
1524         size_t *n_provided_fates)
1525 {
1526     PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
1527                 n_requested_fates, n_provided_fates);
1528     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1529     wifi_error result = (wifi_error)cmd->start();
1530     cmd->releaseRef();
1531     return result;
1532 }
1533 
wifi_get_wake_reason_stats(wifi_interface_handle handle,WLAN_DRIVER_WAKE_REASON_CNT * wifi_wake_reason_cnt)1534 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
1535         WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1536 {
1537     GetWakeReasonCountCommand *cmd =
1538         new GetWakeReasonCountCommand(handle, wifi_wake_reason_cnt);
1539     wifi_error result = (wifi_error)cmd->start();
1540     cmd->releaseRef();
1541     return result;
1542 }
1543