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 #include <errno.h>
30 
31 #include <linux/pkt_sched.h>
32 #include <netlink/object-api.h>
33 #include <netlink/netlink.h>
34 #include <netlink/socket.h>
35 #include <netlink-private/object-api.h>
36 #include <netlink-private/types.h>
37 #include <unistd.h>
38 #include <cutils/properties.h>
39 
40 
41 #include "nl80211_copy.h"
42 #include "sync.h"
43 
44 #define LOG_TAG  "WifiHAL"
45 
46 #include <log/log.h>
47 
48 #include "wifi_hal.h"
49 #include "common.h"
50 #include "cpp_bindings.h"
51 #include <sys/stat.h>
52 #include "brcm_version.h"
53 #define WIFI_HAL_EVENT_SOCK_PORT     645
54 
55 #define ARRAYSIZE(a)	(u8)(sizeof(a) / sizeof(a[0]))
56 typedef enum {
57     LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
58     LOGGER_TRIGGER_MEM_DUMP,
59     LOGGER_GET_MEM_DUMP,
60     LOGGER_GET_VER,
61     LOGGER_GET_RING_STATUS,
62     LOGGER_GET_RING_DATA,
63     LOGGER_GET_FEATURE,
64     LOGGER_RESET_LOGGING,
65     LOGGER_TRIGGER_DRIVER_MEM_DUMP,
66     LOGGER_GET_DRIVER_MEM_DUMP,
67     LOGGER_START_PKT_FATE_MONITORING,
68     LOGGER_GET_TX_PKT_FATES,
69     LOGGER_GET_RX_PKT_FATES,
70     LOGGER_GET_WAKE_REASON_STATS,
71     LOGGER_DEBUG_GET_DUMP,
72     LOGGER_FILE_DUMP_DONE_IND,
73     LOGGER_SET_HAL_START,
74     LOGGER_HAL_STOP,
75     LOGGER_SET_HAL_PID
76 } DEBUG_SUB_COMMAND;
77 
78 #define MAX_NV_FILE 4
79 #define MAX_SKU_NAME_LEN 5
80 #define OTA_PATH "/data/vendor/firmware/wifi/"
81 #define OTA_CLM_FILE "bcmdhd_clm.blob"
82 #define OTA_NVRAM_FILE "bcmdhd.cal"
83 #define HW_DEV_PROP "ro.revision"
84 #define HW_SKU_PROP "ro.boot.hardware.sku"
85 
86 typedef enum {
87     NVRAM,
88     CLM_BLOB
89 } OTA_TYPE;
90 
91 char ota_nvram_ext[10];
92 typedef struct ota_info_buf {
93     u32 ota_clm_len;
94     const void *ota_clm_buf[1];
95     u32 ota_nvram_len;
96     const void *ota_nvram_buf[1];
97 } ota_info_buf_t;
98 u32 applied_ota_version = 0;
99 
100 typedef enum {
101     LOGGER_ATTRIBUTE_INVALID			= 0,
102     LOGGER_ATTRIBUTE_DRIVER_VER			= 1,
103     LOGGER_ATTRIBUTE_FW_VER			= 2,
104     LOGGER_ATTRIBUTE_RING_ID			= 3,
105     LOGGER_ATTRIBUTE_RING_NAME			= 4,
106     LOGGER_ATTRIBUTE_RING_FLAGS			= 5,
107     LOGGER_ATTRIBUTE_LOG_LEVEL			= 6,
108     LOGGER_ATTRIBUTE_LOG_TIME_INTVAL		= 7,
109     LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE		= 8,
110     LOGGER_ATTRIBUTE_FW_DUMP_LEN		= 9,
111     LOGGER_ATTRIBUTE_FW_DUMP_DATA		= 10,
112     LOGGER_ATTRIBUTE_FW_ERR_CODE		= 11,
113     LOGGER_ATTRIBUTE_RING_DATA			= 12,
114     LOGGER_ATTRIBUTE_RING_STATUS		= 13,
115     LOGGER_ATTRIBUTE_RING_NUM			= 14,
116     LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN		= 15,
117     LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA		= 16,
118     LOGGER_ATTRIBUTE_PKT_FATE_NUM		= 17,
119     LOGGER_ATTRIBUTE_PKT_FATE_DATA		= 18,
120     LOGGER_ATTRIBUTE_HANG_REASON		= 19,
121     /* Add new attributes just above this */
122     LOGGER_ATTRIBUTE_MAX
123 } LOGGER_ATTRIBUTE;
124 
125 typedef enum {
126     DEBUG_OFF = 0,
127     DEBUG_NORMAL,
128     DEBUG_VERBOSE,
129     DEBUG_VERY,
130     DEBUG_VERY_VERY,
131 } LOGGER_LEVEL;
132 
133 typedef enum {
134     GET_FW_VER,
135     GET_DRV_VER,
136     GET_RING_DATA,
137     GET_RING_STATUS,
138     GET_FEATURE,
139     START_RING_LOG,
140 } GetCmdType;
141 
142 typedef enum {
143     PACKET_MONITOR_START,
144     TX_PACKET_FATE,
145     RX_PACKET_FATE,
146 } PktFateReqType;
147 
148 enum wake_stat_attributes {
149     WAKE_STAT_ATTRIBUTE_INVALID,
150     WAKE_STAT_ATTRIBUTE_TOTAL,
151     WAKE_STAT_ATTRIBUTE_WAKE,
152     WAKE_STAT_ATTRIBUTE_COUNT,
153     WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
154     WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
155     WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
156     WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT,
157     WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED,
158     WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE,
159     WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT,
160     WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT,
161     WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT,
162     WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT,
163     WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT,
164     WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA,
165     WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA,
166     WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
167     WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
168     WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
169     WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT,
170     WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO,
171     WAKE_STAT_ATTRIBUTE_MAX
172 };
173 
174 typedef enum {
175     SET_HAL_START_ATTRIBUTE_DEINIT = 0x0001,
176     SET_HAL_START_ATTRIBUTE_PRE_INIT = 0x0002,
177     SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
178 } SET_HAL_START_ATTRIBUTE;
179 
180 typedef enum {
181     OTA_DOWNLOAD_CLM_LENGTH_ATTR    = 0x0001,
182     OTA_DOWNLOAD_CLM_ATTR           = 0x0002,
183     OTA_DOWNLOAD_NVRAM_LENGTH_ATTR  = 0x0003,
184     OTA_DOWNLOAD_NVRAM_ATTR         = 0x0004,
185     OTA_SET_FORCE_REG_ON            = 0x0005,
186     OTA_CUR_NVRAM_EXT_ATTR          = 0x0006,
187 } OTA_DOWNLOAD_ATTRIBUTE;
188 
189 #define HAL_START_REQUEST_ID 2
190 #define HAL_RESTART_ID 3
191 #define FILE_NAME_LEN 256
192 ///////////////////////////////////////////////////////////////////////////////
193 class DebugCommand : public WifiCommand
194 {
195     char *mBuff;
196     int *mBuffSize;
197     u32 *mNumRings;
198     wifi_ring_buffer_status *mStatus;
199     unsigned int *mSupport;
200     u32 mVerboseLevel;
201     u32 mFlags;
202     u32 mMaxIntervalSec;
203     u32 mMinDataSize;
204     char *mRingName;
205     GetCmdType mType;
206 
207 public:
208 
209     // constructor for get version
210     DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,
211             GetCmdType cmdType)
212         : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
213         (cmdType)
214     {
215         mNumRings =  NULL;
216         mStatus = NULL;
217         mSupport = NULL;
218         mVerboseLevel = 0;
219         mFlags = 0;
220         mMaxIntervalSec = 0;
221         mMinDataSize = 0;
222         mRingName = NULL;
223         memset(mBuff, 0, *mBuffSize);
224     }
225 
226     // constructor for ring data
227     DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
228         : WifiCommand("DebugCommand", iface, 0), mRingName(ring_name), mType(cmdType)
229     {
230         mBuff = NULL;
231         mBuffSize = NULL;
232         mNumRings =  NULL;
233         mStatus = NULL;
234         mSupport = NULL;
235         mVerboseLevel = 0;
236         mFlags = 0;
237         mMaxIntervalSec = 0;
238         mMinDataSize = 0;
239     }
240 
241     // constructor for ring status
242     DebugCommand(wifi_interface_handle iface, u32 *num_rings,
243             wifi_ring_buffer_status *status, GetCmdType cmdType)
244         : WifiCommand("DebugCommand", iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
245     {
246         mBuff = NULL;
247         mBuffSize = NULL;
248         mSupport = NULL;
249         mVerboseLevel = 0;
250         mFlags = 0;
251         mMaxIntervalSec = 0;
252         mMinDataSize = 0;
253         mRingName = NULL;
254         memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
255     }
256 
257     // constructor for feature set
258     DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
259         : WifiCommand("DebugCommand", iface, 0), mSupport(support), mType(cmdType)
260     {
261         mBuff = NULL;
262         mBuffSize = NULL;
263         mNumRings =  NULL;
264         mStatus = NULL;
265         mVerboseLevel = 0;
266         mFlags = 0;
267         mMaxIntervalSec = 0;
268         mMinDataSize = 0;
269         mRingName = NULL;
270     }
271 
272     // constructor for ring params
273     DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
274             u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)
275         : WifiCommand("DebugCommand", iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
276         mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
277         mRingName(ring_name), mType(cmdType)
278     {
279         mBuff = NULL;
280         mBuffSize = NULL;
281         mNumRings =  NULL;
282         mStatus = NULL;
283         mSupport = NULL;
284     }
285 
286     int createRingRequest(WifiRequest& request) {
287         int result = request.create(GOOGLE_OUI, LOGGER_START_LOGGING);
288         if (result != WIFI_SUCCESS) {
289             ALOGE("Failed to create start ring logger request; result = %d", result);
290             return result;
291         }
292 
293         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
294 
295         result = request.put_u32(LOGGER_ATTRIBUTE_LOG_LEVEL, mVerboseLevel);
296         if (result != WIFI_SUCCESS) {
297             ALOGE("Failed to put log level; result = %d", result);
298             return result;
299         }
300         result = request.put_u32(LOGGER_ATTRIBUTE_RING_FLAGS, mFlags);
301         if (result != WIFI_SUCCESS) {
302             ALOGE("Failed to put ring flags; result = %d", result);
303             return result;
304         }
305         result = request.put_u32(LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, mMaxIntervalSec);
306         if (result != WIFI_SUCCESS) {
307             ALOGE("Failed to put log time interval; result = %d", result);
308             return result;
309         }
310         result = request.put_u32(LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, mMinDataSize);
311         if (result != WIFI_SUCCESS) {
312             ALOGE("Failed to put min data size; result = %d", result);
313             return result;
314         }
315         result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
316         if (result != WIFI_SUCCESS) {
317             ALOGE("Failed to put ringbuffer name; result = %d", result);
318             return result;
319         }
320         request.attr_end(data);
321 
322         return WIFI_SUCCESS;
323     }
324 
325     int createRequest(WifiRequest &request) {
326         int result;
327 
328         switch (mType) {
329             case GET_FW_VER:
330             {
331                 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
332                 if (result != WIFI_SUCCESS) {
333                     ALOGE("Failed to create get fw version request; result = %d", result);
334                     return result;
335                 }
336 
337                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
338 
339                 // Driver expecting only attribute type, passing mbuff as data with
340                 // length 0 to avoid undefined state
341                 result = request.put(LOGGER_ATTRIBUTE_FW_VER, mBuff, 0);
342                 if (result != WIFI_SUCCESS) {
343                     ALOGE("Failed to put get fw version request; result = %d", result);
344                     return result;
345                 }
346                 request.attr_end(data);
347                 break;
348             }
349 
350             case GET_DRV_VER:
351             {
352                 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
353                 if (result != WIFI_SUCCESS) {
354                     ALOGE("Failed to create get drv version request; result = %d", result);
355                     return result;
356                 }
357 
358                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
359 
360                 // Driver expecting only attribute type, passing mbuff as data with
361                 // length 0 to avoid undefined state
362                 result = request.put(LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);
363 
364                 if (result != WIFI_SUCCESS) {
365                     ALOGE("Failed to put get drv version request; result = %d", result);
366                     return result;
367                 }
368                 request.attr_end(data);
369                 break;
370             }
371 
372             case GET_RING_DATA:
373             {
374                 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_DATA);
375                 if (result != WIFI_SUCCESS) {
376                     ALOGE("Failed to create get ring data request; result = %d", result);
377                     return result;
378                 }
379 
380                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
381                 result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
382                 if (result != WIFI_SUCCESS) {
383                     ALOGE("Failed to put ring data request; result = %d", result);
384                     return result;
385                 }
386                 request.attr_end(data);
387                 break;
388             }
389 
390             case GET_RING_STATUS:
391             {
392                 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_STATUS);
393                 if (result != WIFI_SUCCESS) {
394                     ALOGE("Failed to create get ring status request; result = %d", result);
395                     return result;
396                 }
397                 break;
398             }
399 
400             case GET_FEATURE:
401             {
402                 result = request.create(GOOGLE_OUI, LOGGER_GET_FEATURE);
403                 if (result != WIFI_SUCCESS) {
404                     ALOGE("Failed to create get feature request; result = %d", result);
405                     return result;
406                 }
407                 break;
408             }
409 
410             case START_RING_LOG:
411                 result = createRingRequest(request);
412                 break;
413 
414             default:
415                 ALOGE("Unknown Debug command");
416                 result = WIFI_ERROR_UNKNOWN;
417         }
418         return result;
419     }
420 
421     int start() {
422         // ALOGD("Start debug command");
423         WifiRequest request(familyId(), ifaceId());
424         int result = createRequest(request);
425         if (result != WIFI_SUCCESS) {
426             ALOGE("Failed to create debug request; result = %d", result);
427             return result;
428         }
429 
430         result = requestResponse(request);
431         if (result != WIFI_SUCCESS) {
432             ALOGE("Failed to register debug response; result = %d", result);
433         }
434         return result;
435     }
436 
437     virtual int handleResponse(WifiEvent& reply) {
438         ALOGD("In DebugCommand::handleResponse");
439 
440         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
441             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
442             return NL_SKIP;
443         }
444 
445         switch (mType) {
446             case GET_DRV_VER:
447             case GET_FW_VER:
448             {
449                 void *data = reply.get_vendor_data();
450                 int len = reply.get_vendor_data_len();
451 
452                 ALOGD("len = %d, expected len = %d", len, *mBuffSize);
453                 memcpy(mBuff, data, min(len, *mBuffSize));
454                 if (*mBuffSize < len)
455                     return NL_SKIP;
456                 *mBuffSize = len;
457                 break;
458             }
459 
460             case START_RING_LOG:
461             case GET_RING_DATA:
462                 break;
463 
464             case GET_RING_STATUS:
465             {
466                 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
467                 int len = reply.get_vendor_data_len();
468                 wifi_ring_buffer_status *status(mStatus);
469 
470                 if (vendor_data == NULL || len == 0) {
471                     ALOGE("No Debug data found");
472                     return NL_SKIP;
473                 }
474 
475                 nl_iterator it(vendor_data);
476                 if (it.get_type() == LOGGER_ATTRIBUTE_RING_NUM) {
477                     unsigned int num_rings = it.get_u32();
478                     if (*mNumRings < num_rings) {
479                         ALOGE("Not enough status buffers provided, available: %d required: %d",
480                                 *mNumRings, num_rings);
481                     } else {
482                         *mNumRings = num_rings;
483                     }
484                 } else {
485                     ALOGE("Unknown attribute: %d expecting %d",
486                             it.get_type(), LOGGER_ATTRIBUTE_RING_NUM);
487                     return NL_SKIP;
488                 }
489 
490                 it.next();
491                 for (unsigned int i = 0; it.has_next() && i < *mNumRings; it.next()) {
492                     if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
493                         memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status));
494                         i++;
495                         status++;
496                     } else {
497                         ALOGW("Ignoring invalid attribute type = %d, size = %d",
498                                 it.get_type(), it.get_len());
499                     }
500                 }
501                 break;
502             }
503 
504             case GET_FEATURE:
505             {
506                 void *data = reply.get_vendor_data();
507                 int len = reply.get_vendor_data_len();
508 
509                 ALOGD("len = %d, expected len = %lu", len, sizeof(unsigned int));
510                 memcpy(mSupport, data, sizeof(unsigned int));
511                 break;
512             }
513 
514             default:
515                 ALOGW("Unknown Debug command");
516         }
517         return NL_OK;
518     }
519 
520     virtual int handleEvent(WifiEvent& event) {
521         /* NO events! */
522         return NL_SKIP;
523     }
524 };
525 
526 /* API to collect a firmware version string */
527 wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
528         int buffer_size)
529 {
530     if (buffer && (buffer_size > 0)) {
531         DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);
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("FW version buffer NULL");
538         return  WIFI_ERROR_INVALID_ARGS;
539     }
540 }
541 
542 /* API to collect a driver version string */
543 wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
544 {
545     if (buffer && (buffer_size > 0)) {
546         DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);
547         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
548         wifi_error result = (wifi_error)cmd->start();
549         cmd->releaseRef();
550         return result;
551     } else {
552         ALOGE("Driver version buffer NULL");
553         return  WIFI_ERROR_INVALID_ARGS;
554     }
555 }
556 
557 /* API to collect driver records */
558 wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)
559 {
560     DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);
561     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
562     wifi_error result = (wifi_error)cmd->start();
563     cmd->releaseRef();
564     return result;
565 }
566 
567 /* API to get the status of all ring buffers supported by driver */
568 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
569         u32 *num_rings, wifi_ring_buffer_status *status)
570 {
571     if (status && num_rings) {
572         DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);
573         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
574         wifi_error result = (wifi_error)cmd->start();
575         cmd->releaseRef();
576         return result;
577     } else {
578         ALOGE("Ring status buffer NULL");
579         return  WIFI_ERROR_INVALID_ARGS;
580     }
581 }
582 
583 /* API to get supportable feature */
584 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
585         unsigned int *support)
586 {
587     if (support) {
588         DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);
589         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
590         wifi_error result = (wifi_error)cmd->start();
591         cmd->releaseRef();
592         return result;
593     } else {
594         ALOGE("Get support buffer NULL");
595         return  WIFI_ERROR_INVALID_ARGS;
596     }
597 }
598 
599 wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
600         u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
601 {
602     if (ring_name) {
603         DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
604                     min_data_size, ring_name, START_RING_LOG);
605         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
606         wifi_error result = (wifi_error)cmd->start();
607         cmd->releaseRef();
608         return result;
609     } else {
610         ALOGE("Ring name NULL");
611         return  WIFI_ERROR_INVALID_ARGS;
612     }
613 }
614 
615 
616 ///////////////////////////////////////////////////////////////////////////////
617 class SetLogHandler : public WifiCommand
618 {
619     wifi_ring_buffer_data_handler mHandler;
620 
621 public:
622     SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
623         : WifiCommand("SetLogHandler", iface, id), mHandler(handler)
624     { }
625 
626     int start() {
627         ALOGV("Register loghandler");
628         int result;
629         uint32_t event_sock_pid = getpid() + (WIFI_HAL_EVENT_SOCK_PORT << 22);
630         registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
631 
632         WifiRequest request(familyId(), ifaceId());
633 
634         /* set hal event socket port to driver */
635         result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_PID);
636         if (result != WIFI_SUCCESS) {
637             ALOGV("Failed to set Hal preInit; result = %d", result);
638             return result;
639         }
640         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
641         result = request.put_u32(SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID, event_sock_pid);
642         if (result != WIFI_SUCCESS) {
643             ALOGV("Hal preInit Failed to put pic = %d", result);
644             return result;
645         }
646 
647         if (result != WIFI_SUCCESS) {
648             ALOGV("Hal preInit Failed to put pid= %d", result);
649             return result;
650         }
651 
652         request.attr_end(data);
653 
654         result = requestResponse(request);
655         if (result != WIFI_SUCCESS) {
656             ALOGE("Failed to register set Hal preInit; result = %d", result);
657             return result;
658         }
659         return result;
660     }
661 
662     virtual int cancel() {
663         /* Send a command to driver to stop generating logging events */
664         ALOGV("Clear loghandler");
665 
666         /* unregister event handler */
667         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
668         wifi_unregister_cmd(wifiHandle(), id());
669 
670         WifiRequest request(familyId(), ifaceId());
671         int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
672         if (result != WIFI_SUCCESS) {
673             ALOGE("failed to create reset request; result = %d", result);
674             return result;
675         }
676 
677         result = requestResponse(request);
678         if (result != WIFI_SUCCESS) {
679             ALOGE("failed to request reset; result = %d", result);
680             return result;
681         }
682 
683         ALOGD("Success to clear loghandler");
684         return WIFI_SUCCESS;
685     }
686 
687     virtual int handleEvent(WifiEvent& event) {
688         char *buffer = NULL;
689         int buffer_size = 0;
690 
691         // ALOGD("In SetLogHandler::handleEvent");
692         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
693         int len = event.get_vendor_data_len();
694         int event_id = event.get_vendor_subcmd();
695         // ALOGI("Got Logger event: %d", event_id);
696 
697         if (vendor_data == NULL || len == 0) {
698             ALOGE("No Debug data found");
699             return NL_SKIP;
700         }
701 
702         if(event_id == GOOGLE_DEBUG_RING_EVENT) {
703             wifi_ring_buffer_status status;
704             memset(&status, 0, sizeof(status));
705 
706             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
707                 if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
708                     memcpy(&status, it.get_data(), sizeof(status));
709                 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
710                     buffer_size = it.get_len();
711                     buffer = (char *)it.get_data();
712                 } else {
713                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
714                             it.get_type(), it.get_len());
715                 }
716             }
717 
718             // ALOGI("Retrieved Debug data");
719             if (mHandler.on_ring_buffer_data) {
720                 /* Skip msg header. Retrieved log */
721                 char *pBuff;
722                 wifi_ring_buffer_entry *buffer_entry =
723                             (wifi_ring_buffer_entry *) buffer;
724                 pBuff = (char *) (buffer_entry + 1);
725                 (*mHandler.on_ring_buffer_data)((char *)status.name, pBuff,
726                     buffer_entry->entry_size, &status);
727             }
728         } else {
729             ALOGE("Unknown Event");
730             return NL_SKIP;
731         }
732         return NL_OK;
733     }
734 };
735 
736 wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
737         wifi_ring_buffer_data_handler handler)
738 {
739     wifi_handle handle = getWifiHandle(iface);
740     ALOGV("Loghandler start, handle = %p", handle);
741 
742     SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
743     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
744     wifi_error result = wifi_register_cmd(handle, id, cmd);
745     if (result != WIFI_SUCCESS) {
746         cmd->releaseRef();
747         return result;
748     }
749     result = (wifi_error)cmd->start();
750     if (result != WIFI_SUCCESS) {
751         wifi_unregister_cmd(handle, id);
752         cmd->releaseRef();
753         return result;
754     }
755     return result;
756 }
757 
758 wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
759 {
760     wifi_handle handle = getWifiHandle(iface);
761     ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
762 
763     if (id == -1) {
764         wifi_ring_buffer_data_handler handler;
765         memset(&handler, 0, sizeof(handler));
766 
767         SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
768         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
769         cmd->cancel();
770         cmd->releaseRef();
771         return WIFI_SUCCESS;
772     }
773 
774     return wifi_get_cancel_cmd(id, iface);
775 }
776 
777 ///////////////////////////////////////////////////////////////////////////////
778 class SetAlertHandler : public WifiCommand
779 {
780     wifi_alert_handler mHandler;
781     int mBuffSize;
782     char *mBuff;
783     int mErrCode;
784 
785 public:
786     SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)
787         : WifiCommand("SetAlertHandler", iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),
788             mErrCode(0)
789     { }
790 
791     int start() {
792         ALOGV("Start Alerting");
793         registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
794         return WIFI_SUCCESS;
795     }
796 
797     virtual int cancel() {
798         ALOGV("Clear alerthandler");
799 
800         /* unregister alert handler */
801         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
802         wifi_unregister_cmd(wifiHandle(), id());
803         ALOGD("Success to clear alerthandler");
804         return WIFI_SUCCESS;
805     }
806 
807     virtual int handleResponse(WifiEvent& reply) {
808         ALOGD("In SetAlertHandler::handleResponse");
809 
810         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
811             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
812             return NL_SKIP;
813         }
814 
815         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
816         int len = reply.get_vendor_data_len();
817 
818         ALOGD("len = %d", len);
819         if (vendor_data == NULL || len == 0) {
820             ALOGE("no vendor data in memory dump response; ignoring it");
821             return NL_SKIP;
822         }
823 
824         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
825             if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
826                 ALOGI("Initiating alert callback");
827                 if (mHandler.on_alert) {
828                     (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
829                 }
830                 if (mBuff) {
831                     free(mBuff);
832                     mBuff = NULL;
833                 }
834             }
835         }
836         return NL_OK;
837     }
838 
839     virtual int handleEvent(WifiEvent& event) {
840         char *buffer = NULL;
841         int buffer_size = 0;
842         bool is_err_alert = false;
843 
844         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
845         int len = event.get_vendor_data_len();
846         int event_id = event.get_vendor_subcmd();
847         ALOGI("Got event: %d", event_id);
848 
849         if (vendor_data == NULL || len == 0) {
850             ALOGE("No Debug data found");
851             return NL_SKIP;
852         }
853 
854         if (event_id == GOOGLE_DEBUG_MEM_DUMP_EVENT) {
855             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
856                 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
857                     mBuffSize = it.get_u32();
858                 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
859                     buffer_size = it.get_len();
860                     buffer = (char *)it.get_data();
861                 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_ERR_CODE) {
862                     /* Error code is for error alert event only */
863                     mErrCode = it.get_u32();
864                     is_err_alert = true;
865                 } else {
866                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
867                             it.get_type(), it.get_len());
868                 }
869             }
870 
871             if (is_err_alert) {
872                 mBuffSize = sizeof(mErrCode);
873                 if (mBuff) free(mBuff);
874                 mBuff = (char *)malloc(mBuffSize);
875                 if (!mBuff) {
876                   ALOGE("Buffer allocation failed");
877                   return NL_SKIP;
878                 }
879                 memcpy(mBuff, (char *)&mErrCode, mBuffSize);
880                 ALOGI("Initiating alert callback");
881                 if (mHandler.on_alert) {
882                   (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
883                 }
884                 if (mBuff) {
885                   free(mBuff);
886                   mBuff = NULL;
887                 }
888                 mBuffSize = 0;
889                 return NL_OK;
890             }
891 
892             if (mBuffSize) {
893                 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
894                 if (mBuff) free(mBuff);
895                 mBuff = (char *)malloc(mBuffSize + buffer_size);
896                 if (!mBuff) {
897                     ALOGE("Buffer allocation failed");
898                     return NL_SKIP;
899                 }
900                 memcpy(mBuff, buffer, buffer_size);
901 
902                 WifiRequest request(familyId(), ifaceId());
903                 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
904                 if (result != WIFI_SUCCESS) {
905                     ALOGE("Failed to create get memory dump request; result = %d", result);
906                     free(mBuff);
907                     return NL_SKIP;
908                 }
909                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
910                 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
911                 if (result != WIFI_SUCCESS) {
912                     ALOGE("Failed to put get memory dump request; result = %d", result);
913                     return result;
914                 }
915 
916                 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA,
917                          (uint64_t)(mBuff+buffer_size));
918                 if (result != WIFI_SUCCESS) {
919                     ALOGE("Failed to put get memory dump request; result = %d", result);
920                     return result;
921                 }
922 
923                 request.attr_end(data);
924                 mBuffSize += buffer_size;
925 
926                 result = requestResponse(request);
927 
928                 if (result != WIFI_SUCCESS) {
929                     ALOGE("Failed to register get momory dump response; result = %d", result);
930                 }
931             } else {
932                 ALOGE("dump event missing dump length attribute");
933                 return NL_SKIP;
934             }
935         }
936         return NL_OK;
937     }
938 };
939 
940 class SetRestartHandler : public WifiCommand
941 {
942     wifi_subsystem_restart_handler mHandler;
943     char *mBuff;
944 public:
945     SetRestartHandler(wifi_handle handle, wifi_request_id id, wifi_subsystem_restart_handler handler)
946         : WifiCommand("SetRestartHandler", handle, id), mHandler(handler), mBuff(NULL)
947     { }
948     int start() {
949         ALOGI("Start Restart Handler handler:%p", mHandler);
950         registerVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
951         return WIFI_SUCCESS;
952     }
953     virtual int cancel() {
954         ALOGI("Clear Restart Handler");
955 
956         /* unregister alert handler */
957         unregisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
958         wifi_unregister_cmd(wifiHandle(), id());
959         ALOGI("Success to clear restarthandler");
960         return WIFI_SUCCESS;
961     }
962 
963     virtual int handleResponse(WifiEvent& reply) {
964         /* Nothing to do on response! */
965         return NL_OK;
966     }
967 
968     virtual int handleEvent(WifiEvent& event) {
969         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
970         int len = event.get_vendor_data_len();
971         int event_id = event.get_vendor_subcmd();
972         ALOGI("Got event: %d", event_id);
973 
974         if (vendor_data == NULL || len == 0) {
975             ALOGE("No Debug data found");
976             return NL_SKIP;
977         }
978         if (event_id == BRCM_VENDOR_EVENT_HANGED) {
979             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
980                 if (it.get_type() == LOGGER_ATTRIBUTE_HANG_REASON) {
981                     mBuff = (char *)it.get_data();
982                 } else {
983                     ALOGI("Ignoring invalid attribute type = %d, size = %d",
984                             it.get_type(), it.get_len());
985                 }
986             }
987 
988             if (*mHandler.on_subsystem_restart) {
989                 (*mHandler.on_subsystem_restart)(mBuff);
990                 ALOGI("Hang event received. Trigger SSR handler:%p",
991                     mHandler.on_subsystem_restart);
992             } else {
993                 ALOGI("No Restart handler registered");
994             }
995         }
996         return NL_OK;
997     }
998 };
999 
1000 ///////////////////////////////////////////////////////////////////////////////
1001 class SubSystemRestart : public WifiCommand
1002 {
1003     public:
1004     SubSystemRestart(wifi_interface_handle iface)
1005         : WifiCommand("SubSystemRestart", iface, 0)
1006     { }
1007 
1008     int createRequest(WifiRequest& request) {
1009         int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_TRIGGER_SSR);
1010         if (result < 0) {
1011             return result;
1012         }
1013 
1014         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1015 
1016         request.attr_end(data);
1017         return WIFI_SUCCESS;
1018     }
1019 
1020     int create() {
1021         WifiRequest request(familyId(), ifaceId());
1022 
1023         int result = createRequest(request);
1024         if (result < 0) {
1025             ALOGE("Failed to create ssr request result = %d\n", result);
1026             return result;
1027         }
1028 
1029         result = requestResponse(request);
1030         if (result != WIFI_SUCCESS) {
1031             ALOGE("Failed to register ssr response; result = %d\n", result);
1032         }
1033         return result;
1034     }
1035 
1036     protected:
1037     int handleResponse(WifiEvent& reply) {
1038         /* Nothing to do on response! */
1039         return NL_OK;
1040     }
1041 
1042     int handleEvent(WifiEvent& event) {
1043         /* NO events to handle here! */
1044         return NL_SKIP;
1045     }
1046 
1047 };
1048 ///////////////////////////////////////////////////////////////////////////////
1049 class HalInit : public WifiCommand
1050 {
1051     int mErrCode;
1052 
1053     public:
1054     HalInit(wifi_interface_handle iface, int id)
1055         : WifiCommand("HalInit", iface, id), mErrCode(0)
1056     { }
1057 
1058     int start() {
1059         ALOGE("Start Set Hal");
1060         WifiRequest request(familyId(), ifaceId());
1061 
1062         int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
1063         if (result != WIFI_SUCCESS) {
1064             ALOGE("Failed to set hal start; result = %d", result);
1065             return result;
1066         }
1067 
1068         result = requestResponse(request);
1069         if (result != WIFI_SUCCESS) {
1070             ALOGE("Failed to register set hal start response; result = %d", result);
1071         }
1072         return result;
1073     }
1074 
1075 
1076     virtual int cancel() {
1077         ALOGE("Cancel: Stop Hal");
1078         WifiRequest request(familyId(), ifaceId());
1079 
1080         int result = request.create(GOOGLE_OUI, LOGGER_HAL_STOP);
1081         if (result != WIFI_SUCCESS) {
1082             ALOGE("Failed to stop hal ; result = %d", result);
1083             return result;
1084         }
1085 
1086         result = requestResponse(request);
1087         if (result != WIFI_SUCCESS) {
1088             ALOGE("Failed to register set hal start response; result = %d", result);
1089         }
1090         wifi_unregister_cmd(wifiHandle(), id());
1091 	ALOGV("Stop HAL Successfully Completed, mErrCode = %d\n", mErrCode);
1092         return result;
1093     }
1094 
1095     int preInit() {
1096         ALOGE("Hal preInit");
1097         WifiRequest request(familyId(), ifaceId());
1098 
1099         int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
1100         if (result != WIFI_SUCCESS) {
1101             ALOGE("Failed to set Hal preInit; result = %d", result);
1102             return result;
1103         }
1104 
1105         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1106         result = request.put_string(SET_HAL_START_ATTRIBUTE_PRE_INIT, (char *)HAL_VERSION);
1107         if (result != WIFI_SUCCESS) {
1108             ALOGE("Hal preInit Failed to put data= %d", result);
1109             return result;
1110         }
1111         request.attr_end(data);
1112 
1113         result = requestResponse(request);
1114         if (result != WIFI_SUCCESS) {
1115             ALOGE("Failed to register set Hal preInit; result = %d", result);
1116         }
1117         return result;
1118     }
1119 
1120     virtual int handleResponse(WifiEvent& reply) {
1121         ALOGE("In SetHalStarted::handleResponse");
1122 
1123         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1124             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1125             return NL_SKIP;
1126         }
1127         return NL_OK;
1128     }
1129 
1130     virtual int handleEvent(WifiEvent& event) {
1131         /* NO events! */
1132         return NL_SKIP;
1133     }
1134 };
1135 
1136 
1137 wifi_error wifi_start_hal(wifi_interface_handle iface)
1138 {
1139     wifi_handle handle = getWifiHandle(iface);
1140     ALOGV("HAL INIT start, handle = %p", handle);
1141 
1142     HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
1143     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1144     wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
1145     if (result != WIFI_SUCCESS) {
1146         cmd->releaseRef();
1147         return result;
1148     }
1149     result = (wifi_error)cmd->start();
1150     if (result != WIFI_SUCCESS) {
1151         wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
1152         cmd->releaseRef();
1153         return result;
1154     }
1155     return result;
1156 }
1157 
1158 wifi_error wifi_hal_preInit(wifi_interface_handle iface)
1159 {
1160     wifi_handle handle = getWifiHandle(iface);
1161     ALOGV("wifi_hal_preInit, handle = %p", handle);
1162 
1163     HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
1164     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1165     wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
1166     if (result != WIFI_SUCCESS) {
1167         cmd->releaseRef();
1168         return result;
1169     }
1170     result = (wifi_error)cmd->preInit();
1171     if (result != WIFI_SUCCESS) {
1172         wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
1173         cmd->releaseRef();
1174         return result;
1175     }
1176     return result;
1177 }
1178 
1179 wifi_error wifi_stop_hal(wifi_interface_handle iface)
1180 {
1181     HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
1182     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1183     cmd->cancel();
1184     cmd->releaseRef();
1185     return WIFI_SUCCESS;
1186 }
1187 
1188 
1189 wifi_error wifi_set_subsystem_restart_handler(wifi_handle handle,
1190                                               wifi_subsystem_restart_handler handler)
1191 {
1192     hal_info *info = NULL;
1193 
1194     info = (hal_info *)handle;
1195     if (info == NULL) {
1196         ALOGE("Could not find hal info\n");
1197         return WIFI_ERROR_UNKNOWN;
1198     }
1199 
1200     SetRestartHandler *cmd = new SetRestartHandler(handle, HAL_RESTART_ID, handler);
1201     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1202     wifi_error result = wifi_register_cmd(handle, HAL_RESTART_ID, cmd);
1203     if (result != WIFI_SUCCESS) {
1204         cmd->releaseRef();
1205         return result;
1206     }
1207 
1208     result = (wifi_error)cmd->start();
1209     if (result != WIFI_SUCCESS) {
1210         wifi_unregister_cmd(handle, HAL_RESTART_ID);
1211         cmd->releaseRef();
1212         return result;
1213     }
1214 
1215     /* Cache the handler to use it for trigger subsystem restart */
1216     ALOGI("Register SSR handler:%p", handler);
1217     info->restart_handler = handler;
1218     return result;
1219 }
1220 
1221 wifi_error wifi_trigger_subsystem_restart(wifi_handle handle)
1222 {
1223     wifi_error result = WIFI_SUCCESS;
1224     hal_info *info = NULL;
1225     char error_str[20];
1226     SubSystemRestart *cmd = NULL;
1227     wifi_interface_handle *ifaceHandles = NULL;
1228     wifi_interface_handle wlan0Handle;
1229     int numIfaceHandles = 0;
1230 
1231     info = (hal_info *)handle;
1232     if (handle == NULL || info == NULL) {
1233         ALOGE("Could not find hal info\n");
1234         result = WIFI_ERROR_UNKNOWN;
1235         goto exit;
1236     }
1237 
1238     ALOGI("Trigger subsystem restart\n");
1239 
1240     wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
1241 
1242     cmd = new SubSystemRestart(wlan0Handle);
1243     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1244 
1245     result = (wifi_error)cmd->create();
1246     if (result != WIFI_SUCCESS) {
1247         cmd->releaseRef();
1248         strncpy(error_str, "WIFI_ERROR_UNKNOWN", sizeof(error_str));
1249         ALOGE("Failed to create SSR");
1250         goto exit;
1251     }
1252 
1253     strncpy(error_str, "WIFI_SUCCESS", sizeof(error_str));
1254 
1255 exit:
1256     if (info->restart_handler.on_subsystem_restart) {
1257         ALOGI("Trigger ssr handler registered handler:%p",
1258             info->restart_handler.on_subsystem_restart);
1259         (info->restart_handler.on_subsystem_restart)(error_str);
1260     } else {
1261         ALOGI("No trigger ssr handler registered");
1262     }
1263 
1264     return result;
1265 }
1266 
1267 wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
1268         wifi_alert_handler handler)
1269 {
1270     wifi_handle handle = getWifiHandle(iface);
1271     ALOGV("Alerthandler start, handle = %p", handle);
1272 
1273     SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
1274     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1275     wifi_error result = wifi_register_cmd(handle, id, cmd);
1276     if (result != WIFI_SUCCESS) {
1277         cmd->releaseRef();
1278         return result;
1279     }
1280     result = (wifi_error)cmd->start();
1281     if (result != WIFI_SUCCESS) {
1282         wifi_unregister_cmd(handle, id);
1283         cmd->releaseRef();
1284         return result;
1285     }
1286     return result;
1287 }
1288 
1289 wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)
1290 {
1291     wifi_handle handle = getWifiHandle(iface);
1292     ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);
1293 
1294     if (id == -1) {
1295         wifi_alert_handler handler;
1296         memset(&handler, 0, sizeof(handler));
1297 
1298         SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
1299         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1300         cmd->cancel();
1301         cmd->releaseRef();
1302         return WIFI_SUCCESS;
1303     }
1304 
1305     return wifi_get_cancel_cmd(id, iface);
1306 }
1307 
1308 ///////////////////////////////////////////////////////////////////////////////
1309 class MemoryDumpCommand: public WifiCommand
1310 {
1311     wifi_firmware_memory_dump_handler mHandler;
1312     int mBuffSize;
1313     char *mBuff;
1314 
1315 public:
1316     MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler)
1317         : WifiCommand("MemoryDumpCommand", iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL)
1318     { }
1319 
1320     int start() {
1321         ALOGD("Start memory dump command");
1322         WifiRequest request(familyId(), ifaceId());
1323 
1324         int result = request.create(GOOGLE_OUI, LOGGER_TRIGGER_MEM_DUMP);
1325         if (result != WIFI_SUCCESS) {
1326             ALOGE("Failed to create trigger fw memory dump request; result = %d", result);
1327             return result;
1328         }
1329 
1330         result = requestResponse(request);
1331         if (result != WIFI_SUCCESS) {
1332             ALOGE("Failed to register trigger memory dump response; result = %d", result);
1333         }
1334         return result;
1335     }
1336 
1337     virtual int handleResponse(WifiEvent& reply) {
1338         ALOGD("In MemoryDumpCommand::handleResponse");
1339 
1340         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1341             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1342             return NL_SKIP;
1343         }
1344 
1345         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1346         int len = reply.get_vendor_data_len();
1347 
1348         ALOGD("len = %d", len);
1349         if (vendor_data == NULL || len == 0) {
1350             ALOGE("no vendor data in memory dump response; ignoring it");
1351             return NL_SKIP;
1352         }
1353 
1354         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1355             if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
1356                 mBuffSize = it.get_u32();
1357 
1358                 if (mBuff)
1359                     free(mBuff);
1360                 mBuff = (char *)malloc(mBuffSize);
1361                 if (!mBuff) {
1362                     ALOGE("Buffer allocation failed");
1363                     return NL_SKIP;
1364                 }
1365                 WifiRequest request(familyId(), ifaceId());
1366                 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
1367                 if (result != WIFI_SUCCESS) {
1368                     ALOGE("Failed to create get memory dump request; result = %d", result);
1369                     free(mBuff);
1370                     return NL_SKIP;
1371                 }
1372 
1373                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1374                 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
1375                 if (result != WIFI_SUCCESS) {
1376                     ALOGE("Failed to put get memory dump request; result = %d", result);
1377                     return result;
1378                 }
1379 
1380                 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);
1381                 if (result != WIFI_SUCCESS) {
1382                     ALOGE("Failed to put get memory dump request; result = %d", result);
1383                     return result;
1384                 }
1385                 request.attr_end(data);
1386 
1387                 result = requestResponse(request);
1388                 if (result != WIFI_SUCCESS) {
1389                     ALOGE("Failed to register get momory dump response; result = %d", result);
1390                 }
1391             } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
1392                 ALOGI("Initiating memory dump callback");
1393                 if (mHandler.on_firmware_memory_dump) {
1394                     (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);
1395                 }
1396                 if (mBuff) {
1397                     free(mBuff);
1398                     mBuff = NULL;
1399                 }
1400             } else {
1401                 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1402                         it.get_type(), it.get_len());
1403             }
1404         }
1405         return NL_OK;
1406     }
1407 
1408     virtual int handleEvent(WifiEvent& event) {
1409         /* NO events! */
1410         return NL_SKIP;
1411     }
1412 };
1413 
1414 /* API to collect a firmware memory dump for a given iface */
1415 wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
1416         wifi_firmware_memory_dump_handler handler)
1417 {
1418     MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler);
1419     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1420     wifi_error result = (wifi_error)cmd->start();
1421     cmd->releaseRef();
1422     return result;
1423 }
1424 
1425 class PacketFateCommand: public WifiCommand
1426 {
1427     void *mReportBufs;
1428     size_t mNoReqFates;
1429     size_t *mNoProvidedFates;
1430     PktFateReqType mReqType;
1431 
1432 public:
1433     PacketFateCommand(wifi_interface_handle handle)
1434         : WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START)
1435     {
1436         mReportBufs = NULL;
1437         mNoReqFates = 0;
1438         mNoProvidedFates = NULL;
1439     }
1440 
1441     PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
1442             size_t n_requested_fates, size_t *n_provided_fates)
1443         : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(tx_report_bufs),
1444                   mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
1445                   mReqType(TX_PACKET_FATE)
1446     { }
1447 
1448     PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,
1449             size_t n_requested_fates, size_t *n_provided_fates)
1450         : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(rx_report_bufs),
1451                   mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
1452                   mReqType(RX_PACKET_FATE)
1453     { }
1454 
1455     int createRequest(WifiRequest& request) {
1456         if (mReqType == TX_PACKET_FATE) {
1457             ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);
1458             return createTxPktFateRequest(request);
1459         } else if (mReqType == RX_PACKET_FATE) {
1460             ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);
1461             return createRxPktFateRequest(request);
1462         } else if (mReqType == PACKET_MONITOR_START) {
1463             ALOGD("%s Monitor packet fate request\n", __FUNCTION__);
1464             return createMonitorPktFateRequest(request);
1465         } else {
1466             ALOGE("%s Unknown packet fate request\n", __FUNCTION__);
1467             return WIFI_ERROR_NOT_SUPPORTED;
1468         }
1469         return WIFI_SUCCESS;
1470     }
1471 
1472     int createMonitorPktFateRequest(WifiRequest& request) {
1473         int result = request.create(GOOGLE_OUI, LOGGER_START_PKT_FATE_MONITORING);
1474         if (result < 0) {
1475             return result;
1476         }
1477 
1478         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1479         request.attr_end(data);
1480         return result;
1481     }
1482 
1483     int createTxPktFateRequest(WifiRequest& request) {
1484         int result = request.create(GOOGLE_OUI, LOGGER_GET_TX_PKT_FATES);
1485         if (result < 0) {
1486             return result;
1487         }
1488 
1489         memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));
1490         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1491         result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
1492         if (result < 0) {
1493             return result;
1494         }
1495         result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
1496         if (result < 0) {
1497             return result;
1498         }
1499         request.attr_end(data);
1500         return result;
1501     }
1502 
1503     int createRxPktFateRequest(WifiRequest& request) {
1504         int result = request.create(GOOGLE_OUI, LOGGER_GET_RX_PKT_FATES);
1505         if (result < 0) {
1506             return result;
1507         }
1508 
1509         memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));
1510         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1511         result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
1512         if (result < 0) {
1513             return result;
1514         }
1515         result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
1516         if (result < 0) {
1517             return result;
1518         }
1519         request.attr_end(data);
1520         return result;
1521     }
1522 
1523     int start() {
1524         ALOGD("Start get packet fate command\n");
1525         WifiRequest request(familyId(), ifaceId());
1526 
1527         int result = createRequest(request);
1528         if (result < 0) {
1529             ALOGE("Failed to create get pkt fate request; result = %d\n", result);
1530             return result;
1531         }
1532 
1533         result = requestResponse(request);
1534         if (result != WIFI_SUCCESS) {
1535             ALOGE("Failed to register get pkt fate response; result = %d\n", result);
1536         }
1537         return result;
1538     }
1539 
1540     int handleResponse(WifiEvent& reply) {
1541         ALOGD("In GetPktFateCommand::handleResponse\n");
1542 
1543         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1544             ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
1545             return NL_SKIP;
1546         }
1547 
1548         int id = reply.get_vendor_id();
1549         int subcmd = reply.get_vendor_subcmd();
1550         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1551         int len = reply.get_vendor_data_len();
1552 
1553         ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1554 
1555         if (mReqType == TX_PACKET_FATE) {
1556             ALOGI("Response recieved for get TX pkt fate command\n");
1557         } else if (mReqType == RX_PACKET_FATE) {
1558             ALOGI("Response recieved for get RX pkt fate command\n");
1559         } else if (mReqType == PACKET_MONITOR_START) {
1560             ALOGI("Response recieved for monitor pkt fate command\n");
1561             return NL_OK;
1562         } else {
1563             ALOGE("Response recieved for unknown pkt fate command\n");
1564             return NL_SKIP;
1565         }
1566 
1567         if (vendor_data == NULL || len == 0) {
1568             ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
1569             return NL_SKIP;
1570         }
1571 
1572         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1573             if (it.get_type() == LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
1574                 *mNoProvidedFates = it.get_u32();
1575                 ALOGI("No: of pkt fates provided is %zu\n", *mNoProvidedFates);
1576             } else {
1577                 ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
1578                         it.get_type(), it.get_len());
1579             }
1580         }
1581 
1582         return NL_OK;
1583     }
1584 
1585     int handleEvent(WifiEvent& event) {
1586         /* NO events to handle here! */
1587         return NL_SKIP;
1588     }
1589 };
1590 
1591 class GetWakeReasonCountCommand : public WifiCommand {
1592     WLAN_DRIVER_WAKE_REASON_CNT *mWakeReasonCnt;
1593     void *mCmdEventWakeCount;
1594     public:
1595     GetWakeReasonCountCommand(wifi_interface_handle handle,
1596         WLAN_DRIVER_WAKE_REASON_CNT *wlanDriverWakeReasonCount) :
1597         WifiCommand("GetWakeReasonCountCommand", handle, 0),
1598         mWakeReasonCnt(wlanDriverWakeReasonCount)
1599     {
1600         mCmdEventWakeCount = mWakeReasonCnt->cmd_event_wake_cnt;
1601     }
1602 
1603     int createRequest(WifiRequest& request) {
1604         int result = request.create(GOOGLE_OUI, LOGGER_GET_WAKE_REASON_STATS);
1605         if (result < 0) {
1606             return result;
1607         }
1608 
1609         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1610 
1611         request.attr_end(data);
1612         return WIFI_SUCCESS;
1613     }
1614 
1615     int start() {
1616         ALOGD("Start get wake stats command\n");
1617         WifiRequest request(familyId(), ifaceId());
1618 
1619         int result = createRequest(request);
1620         if (result < 0) {
1621             ALOGE("Failed to create request result = %d\n", result);
1622             return result;
1623         }
1624 
1625         result = requestResponse(request);
1626         if (result != WIFI_SUCCESS) {
1627             ALOGE("Failed to register wake stats  response; result = %d\n", result);
1628         }
1629         return result;
1630     }
1631 
1632     protected:
1633     int handleResponse(WifiEvent& reply) {
1634         ALOGE("In GetWakeReasonCountCommand::handleResponse");
1635 
1636         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1637             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1638             return NL_SKIP;
1639         }
1640 
1641         int id = reply.get_vendor_id();
1642         int subcmd = reply.get_vendor_subcmd();
1643 
1644         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1645         int len = reply.get_vendor_data_len();
1646 
1647         ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1648         if (vendor_data == NULL || len == 0) {
1649             ALOGE("no vendor data in GetGetWakeReasonCountCommand response; ignoring it");
1650             return NL_SKIP;
1651         }
1652 
1653         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1654             switch (it.get_type()) {
1655                 case WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW:
1656                     mWakeReasonCnt->total_driver_fw_local_wake =
1657                         it.get_u32();
1658                     break;
1659                 case WAKE_STAT_ATTRIBUTE_TOTAL:
1660                     mWakeReasonCnt->total_cmd_event_wake =
1661                         it.get_u32();
1662                     break;
1663                 case WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED:
1664                     mWakeReasonCnt->cmd_event_wake_cnt_used =
1665                         it.get_u32();
1666                     break;
1667                 case WAKE_STAT_ATTRIBUTE_WAKE:
1668                     memcpy(mCmdEventWakeCount, it.get_data(),
1669                             (mWakeReasonCnt->cmd_event_wake_cnt_used * sizeof(int)));
1670                     break;
1671                 case WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE:
1672                     mWakeReasonCnt->total_rx_data_wake =
1673                         it.get_u32();
1674                     break;
1675                 case WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT:
1676                     mWakeReasonCnt->rx_wake_details.rx_unicast_cnt =
1677                         it.get_u32();
1678                     break;
1679                 case WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT:
1680                     mWakeReasonCnt->rx_wake_details.rx_multicast_cnt =
1681                         it.get_u32();
1682                     break;
1683                 case WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT:
1684                     mWakeReasonCnt->rx_wake_details.rx_broadcast_cnt =
1685                         it.get_u32();
1686                     break;
1687                 case WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT:
1688                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp_pkt =
1689                         it.get_u32();
1690                     break;
1691                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT:
1692                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_pkt =
1693                         it.get_u32();
1694                     break;
1695                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA:
1696                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ra =
1697                         it.get_u32();
1698                     break;
1699                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA:
1700                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_na =
1701                         it.get_u32();
1702                     break;
1703                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS:
1704                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ns =
1705                         it.get_u32();
1706                     break;
1707                 case WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT:
1708                     mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt =
1709                         it.get_u32();
1710                     break;
1711                 case WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT:
1712                     mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
1713                         it.get_u32();
1714                     break;
1715                 case WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT:
1716                     mWakeReasonCnt->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
1717                         it.get_u32();
1718                     break;
1719                 default:
1720                     break;
1721             }
1722 
1723         }
1724         return NL_OK;
1725     }
1726 };
1727 
1728 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
1729 {
1730     PacketFateCommand *cmd = new PacketFateCommand(handle);
1731     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1732     wifi_error result = (wifi_error)cmd->start();
1733     cmd->releaseRef();
1734     return result;
1735 }
1736 
1737 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
1738         wifi_tx_report *tx_report_bufs, size_t n_requested_fates,
1739         size_t *n_provided_fates)
1740 {
1741     PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,
1742                 n_requested_fates, n_provided_fates);
1743     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1744     wifi_error result = (wifi_error)cmd->start();
1745     cmd->releaseRef();
1746     return result;
1747 }
1748 
1749 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
1750         wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
1751         size_t *n_provided_fates)
1752 {
1753     PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
1754                 n_requested_fates, n_provided_fates);
1755     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1756     wifi_error result = (wifi_error)cmd->start();
1757     cmd->releaseRef();
1758     return result;
1759 }
1760 
1761 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
1762         WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1763 {
1764     GetWakeReasonCountCommand *cmd =
1765         new GetWakeReasonCountCommand(handle, wifi_wake_reason_cnt);
1766     wifi_error result = (wifi_error)cmd->start();
1767     cmd->releaseRef();
1768     return result;
1769 }
1770 
1771 ///////////////////////////////////////////////////////////////////////////////
1772 class OtaUpdateCommand : public WifiCommand
1773 {
1774     int mErrCode;
1775 
1776     public:
1777     OtaUpdateCommand(wifi_interface_handle iface)
1778         : WifiCommand("OtaUpdateCommand", iface, 0), mErrCode(0)
1779     { }
1780 
1781     int start() {
1782         ALOGE("Start OtaUpdateCommand");
1783         WifiRequest request(familyId(), ifaceId());
1784 
1785         int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_GET_OTA_CURRUNT_INFO);
1786         if (result != WIFI_SUCCESS) {
1787             ALOGE("Failed to set hal start; result = %d", result);
1788             return result;
1789         }
1790 
1791         result = requestResponse(request);
1792         if (result != WIFI_SUCCESS) {
1793             ALOGE("Failed to register set hal start response; result = %d", result);
1794         }
1795         return result;
1796     }
1797 
1798     int otaDownload(ota_info_buf_t* buf, uint32_t ota_version) {
1799         u32 force_reg_on = false;
1800         WifiRequest request(familyId(), ifaceId());
1801         int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_OTA_UPDATE);
1802 
1803         ALOGE("Download the OTA configuration");
1804         if (result != WIFI_SUCCESS) {
1805             ALOGE("Failed to set Hal preInit; result = %d", result);
1806             return result;
1807         }
1808 
1809         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1810 
1811         result = request.put_u32(OTA_DOWNLOAD_CLM_LENGTH_ATTR, buf->ota_clm_len);
1812         if (result != WIFI_SUCCESS) {
1813             ALOGE("otaDownload Failed to put data= %d", result);
1814             return result;
1815         }
1816 
1817         result = request.put(OTA_DOWNLOAD_CLM_ATTR, buf->ota_clm_buf, sizeof(*buf->ota_clm_buf));
1818         if (result != WIFI_SUCCESS) {
1819             ALOGE("otaDownload Failed to put data= %d", result);
1820             return result;
1821         }
1822 
1823         result = request.put_u32(OTA_DOWNLOAD_NVRAM_LENGTH_ATTR, buf->ota_nvram_len);
1824         if (result != WIFI_SUCCESS) {
1825             ALOGE("otaDownload Failed to put data= %d", result);
1826             return result;
1827         }
1828 
1829         result = request.put(OTA_DOWNLOAD_NVRAM_ATTR,
1830                 buf->ota_nvram_buf, sizeof(*buf->ota_nvram_buf));
1831         if (result != WIFI_SUCCESS) {
1832             ALOGE("otaDownload Failed to put data= %d", result);
1833             return result;
1834         }
1835 
1836         if (applied_ota_version != ota_version) {
1837             force_reg_on = true;
1838             applied_ota_version = ota_version;
1839         }
1840         result = request.put_u32(OTA_SET_FORCE_REG_ON, force_reg_on);
1841         if (result != WIFI_SUCCESS) {
1842             ALOGE("otaDownload Failed to put data= %d", result);
1843             return result;
1844         }
1845 
1846         request.attr_end(data);
1847 
1848         result = requestResponse(request);
1849         if (result != WIFI_SUCCESS) {
1850             ALOGE("Failed to register set otaDownload; result = %d", result);
1851         }
1852 
1853         return result;
1854     }
1855 
1856     virtual int handleResponse(WifiEvent& reply) {
1857         ALOGD("In OtaUpdateCommand::handleResponse");
1858 
1859         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1860             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1861             return NL_SKIP;
1862         }
1863 
1864         int id = reply.get_vendor_id();
1865         int subcmd = reply.get_vendor_subcmd();
1866         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1867         int len = reply.get_vendor_data_len();
1868 
1869         ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1870 
1871         if (vendor_data == NULL || len == 0) {
1872             ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
1873             return NL_SKIP;
1874         }
1875 
1876         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1877             switch (it.get_type()) {
1878                 case OTA_CUR_NVRAM_EXT_ATTR:
1879                     strncpy(ota_nvram_ext, (char*)it.get_string(), it.get_len());
1880                     ALOGI("Current Nvram ext [%s]\n", ota_nvram_ext);
1881                     break;
1882                 default:
1883                     ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
1884                             it.get_type(), it.get_len());
1885                     break;
1886             }
1887         }
1888         return NL_OK;
1889     }
1890 
1891     virtual int handleEvent(WifiEvent& event) {
1892         /* NO events! */
1893         return NL_SKIP;
1894     }
1895 };
1896 
1897 wifi_error read_ota_file(char* file, char** buffer, uint32_t* size)
1898 {
1899     FILE* fp = NULL;
1900     int file_size, count;
1901     char* buf;
1902     fp = fopen(file, "r");
1903 
1904     if (fp == NULL) {
1905         ALOGI("File [%s] doesn't exist.", file);
1906         return WIFI_ERROR_NOT_AVAILABLE;
1907     }
1908 
1909     fseek(fp, 0, SEEK_END);
1910     file_size = ftell(fp);
1911 
1912     buf = (char *)malloc(file_size + 1);
1913     if (buf == NULL) {
1914         fclose(fp);
1915         return WIFI_ERROR_UNKNOWN;
1916     }
1917     memset(buf, 0, file_size + 1);
1918     fseek(fp, 0, SEEK_SET);
1919     count = fread(buf, file_size, 1, fp);
1920 
1921     *buffer = (char*) buf;
1922     *size = file_size;
1923     fclose(fp);
1924     return WIFI_SUCCESS;
1925 }
1926 
1927 wifi_error check_multiple_nvram_clm(uint32_t type, char* hw_revision, char* hw_sku,
1928         char** buffer, uint32_t* buffer_len)
1929 {
1930     char file_name[MAX_NV_FILE][FILE_NAME_LEN];
1931     char nvram_clmblob_default_file[FILE_NAME_LEN] = {0,};
1932     wifi_error result = WIFI_SUCCESS;
1933 
1934     if (type == CLM_BLOB) {
1935         sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_CLM_FILE);
1936     }
1937     else if (type == NVRAM) {
1938         sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_NVRAM_FILE);
1939     }
1940     for (unsigned int i = 0; i < MAX_NV_FILE; i++) {
1941         memset(file_name[i], 0, FILE_NAME_LEN);
1942     }
1943 
1944     sprintf(file_name[0], "%s_%s_%s", nvram_clmblob_default_file, hw_revision, hw_sku);
1945     sprintf(file_name[1], "%s_%s", nvram_clmblob_default_file, hw_revision);
1946     sprintf(file_name[2], "%s_%s", nvram_clmblob_default_file, hw_sku);
1947     sprintf(file_name[3], "%s", nvram_clmblob_default_file);
1948 
1949     for (unsigned int i = 0; i < MAX_NV_FILE; i++) {
1950         result = read_ota_file(file_name[i], buffer, buffer_len);
1951         if (result == WIFI_SUCCESS) {
1952             ALOGI("[OTA] %s PATH %s", type == NVRAM ? "NVRAM" : "CLM", file_name[i]);
1953             break;
1954         }
1955     }
1956     return result;
1957 }
1958 
1959 wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version)
1960 {
1961     wifi_handle handle = getWifiHandle(iface);
1962     wifi_error result = WIFI_SUCCESS;
1963     ota_info_buf_t buf;
1964     char *buffer_nvram = NULL;
1965     char *buffer_clm = NULL;
1966     char prop_revision_buf[PROPERTY_VALUE_MAX] = {0,};
1967     char prop_sku_buf[PROPERTY_VALUE_MAX] = {0,};
1968     char sku_name[MAX_SKU_NAME_LEN] = {0,};
1969 
1970     OtaUpdateCommand *cmd = new OtaUpdateCommand(iface);
1971     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1972 
1973     ALOGD("wifi_hal_ota_update, handle = %p, ota_version %d\n", handle, ota_version);
1974 
1975     result = (wifi_error)cmd->start();
1976     if (result != WIFI_SUCCESS) {
1977         cmd->releaseRef();
1978         return result;
1979     }
1980 
1981     property_get(HW_DEV_PROP, prop_revision_buf, NULL);
1982     property_get(HW_SKU_PROP, prop_sku_buf, NULL);
1983 
1984     if (strcmp(prop_sku_buf, "G9S9B") == 0 ||
1985         strcmp(prop_sku_buf, "G8V0U") == 0 ||
1986         strcmp(prop_sku_buf, "GFQM1") == 0) {
1987         strncpy(sku_name, "MMW", MAX_SKU_NAME_LEN);
1988     } else if (strcmp(prop_sku_buf, "GR1YH") == 0 ||
1989                strcmp(prop_sku_buf, "GF5KQ") == 0 ||
1990                strcmp(prop_sku_buf, "GPQ72") == 0) {
1991         strncpy(sku_name, "JPN", MAX_SKU_NAME_LEN);
1992     } else if (strcmp(prop_sku_buf, "GB7N6") == 0 ||
1993                strcmp(prop_sku_buf, "GLU0G") == 0 ||
1994                strcmp(prop_sku_buf, "GNA8F") == 0) {
1995         strncpy(sku_name, "ROW", MAX_SKU_NAME_LEN);
1996     } else {
1997         strncpy(sku_name, "NA", MAX_SKU_NAME_LEN);
1998     }
1999 
2000     check_multiple_nvram_clm(CLM_BLOB, prop_revision_buf, sku_name, &buffer_clm, &buf.ota_clm_len);
2001     if (buffer_clm == NULL) {
2002         ALOGE("buffer_clm is null");
2003         goto exit;
2004     }
2005     buf.ota_clm_buf[0] = buffer_clm;
2006 
2007     check_multiple_nvram_clm(NVRAM, prop_revision_buf, sku_name,
2008             &buffer_nvram, &buf.ota_nvram_len);
2009     if (buffer_nvram == NULL) {
2010         ALOGE("buffer_nvram is null");
2011         goto exit;
2012     }
2013     buf.ota_nvram_buf[0] = buffer_nvram;
2014     cmd->otaDownload(&buf, ota_version);
2015 
2016 exit:
2017     if (buffer_clm != NULL) {
2018         free(buffer_clm);
2019     }
2020     if (buffer_nvram != NULL) {
2021         free(buffer_nvram);
2022     }
2023 
2024     cmd->releaseRef();
2025 
2026     return result;
2027 }
2028