• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Portions copyright (C) 2023 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 <hardware_legacy/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     LOGGER_SET_TPUT_DEBUG_DUMP_CMD,
77     LOGGER_GET_BUF_RING_MAP
78 } DEBUG_SUB_COMMAND;
79 
80 #define MAX_NV_FILE 4
81 #define MAX_SKU_NAME_LEN 5
82 #define OTA_PATH "/data/vendor/firmware/wifi/"
83 #define OTA_CLM_FILE "bcmdhd_clm.blob"
84 #define OTA_TXCAP_BLOB_FILE "bcmdhd_txcap.blob"
85 #define OTA_NVRAM_FILE "bcmdhd.cal"
86 #define HW_DEV_PROP "ro.revision"
87 #define HW_SKU_PROP "ro.boot.hardware.sku"
88 
89 typedef enum {
90     NVRAM,
91     CLM_BLOB,
92     TXCAP_BLOB
93 } OTA_TYPE;
94 
95 char ota_nvram_ext[10];
96 typedef struct ota_info_buf {
97     u32 ota_clm_len;
98     const void *ota_clm_buf[1];
99     u32 ota_nvram_len;
100     const void *ota_nvram_buf[1];
101     u32 ota_txcap_len;
102     const void *ota_txcap_buf[1];
103 } ota_info_buf_t;
104 u32 applied_ota_version = 0;
105 
106 typedef enum {
107     LOGGER_ATTRIBUTE_INVALID			= 0,
108     LOGGER_ATTRIBUTE_DRIVER_VER			= 1,
109     LOGGER_ATTRIBUTE_FW_VER			= 2,
110     LOGGER_ATTRIBUTE_RING_ID			= 3,
111     LOGGER_ATTRIBUTE_RING_NAME			= 4,
112     LOGGER_ATTRIBUTE_RING_FLAGS			= 5,
113     LOGGER_ATTRIBUTE_LOG_LEVEL			= 6,
114     LOGGER_ATTRIBUTE_LOG_TIME_INTVAL		= 7,
115     LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE		= 8,
116     LOGGER_ATTRIBUTE_FW_DUMP_LEN		= 9,
117     LOGGER_ATTRIBUTE_FW_DUMP_DATA		= 10,
118     LOGGER_ATTRIBUTE_FW_ERR_CODE		= 11,
119     LOGGER_ATTRIBUTE_RING_DATA			= 12,
120     LOGGER_ATTRIBUTE_RING_STATUS		= 13,
121     LOGGER_ATTRIBUTE_RING_NUM			= 14,
122     LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN		= 15,
123     LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA		= 16,
124     LOGGER_ATTRIBUTE_PKT_FATE_NUM		= 17,
125     LOGGER_ATTRIBUTE_PKT_FATE_DATA		= 18,
126     LOGGER_ATTRIBUTE_HANG_REASON		= 19,
127     LOGGER_ATTRIBUTE_BUF_RING_NUM		= 20,
128     LOGGER_ATTRIBUTE_BUF_RING_MAP		= 21,
129     /* Add new attributes just above this */
130     LOGGER_ATTRIBUTE_MAX
131 } LOGGER_ATTRIBUTE;
132 
133 typedef enum {
134     DEBUG_OFF = 0,
135     DEBUG_NORMAL,
136     DEBUG_VERBOSE,
137     DEBUG_VERY,
138     DEBUG_VERY_VERY,
139 } LOGGER_LEVEL;
140 
141 typedef enum {
142     GET_FW_VER,
143     GET_DRV_VER,
144     GET_RING_DATA,
145     GET_RING_STATUS,
146     GET_FEATURE,
147     START_RING_LOG,
148     GET_BUF_RING_MAP,
149 } GetCmdType;
150 
151 typedef enum {
152     PACKET_MONITOR_START,
153     TX_PACKET_FATE,
154     RX_PACKET_FATE,
155 } PktFateReqType;
156 
157 enum wake_stat_attributes {
158     WAKE_STAT_ATTRIBUTE_INVALID,
159     WAKE_STAT_ATTRIBUTE_TOTAL,
160     WAKE_STAT_ATTRIBUTE_WAKE,
161     WAKE_STAT_ATTRIBUTE_COUNT,
162     WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
163     WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
164     WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
165     WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT,
166     WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED,
167     WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE,
168     WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT,
169     WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT,
170     WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT,
171     WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT,
172     WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT,
173     WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA,
174     WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA,
175     WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
176     WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
177     WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
178     WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT,
179     WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO,
180     WAKE_STAT_ATTRIBUTE_MAX
181 };
182 
183 typedef enum {
184     SET_HAL_START_ATTRIBUTE_DEINIT = 0x0001,
185     SET_HAL_START_ATTRIBUTE_PRE_INIT = 0x0002,
186     SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
187 } SET_HAL_START_ATTRIBUTE;
188 
189 typedef enum {
190     OTA_DOWNLOAD_CLM_LENGTH_ATTR    = 0x0001,
191     OTA_DOWNLOAD_CLM_ATTR           = 0x0002,
192     OTA_DOWNLOAD_NVRAM_LENGTH_ATTR  = 0x0003,
193     OTA_DOWNLOAD_NVRAM_ATTR         = 0x0004,
194     OTA_SET_FORCE_REG_ON            = 0x0005,
195     OTA_CUR_NVRAM_EXT_ATTR          = 0x0006,
196     OTA_DOWNLOAD_TXCAP_BLOB_LENGTH_ATTR    = 0x0007,
197     OTA_DOWNLOAD_TXCAP_BLOB_ATTR           = 0x0008,
198 } OTA_DOWNLOAD_ATTRIBUTE;
199 
200 #define HAL_START_REQUEST_ID 2
201 #define HAL_RESTART_ID 3
202 #define FILE_NAME_LEN 256
203 #define RING_NAME_LEN 32
204 #if defined(RING_DUMP)
205 /* Loglevel */
206 #define DUMP_DEBUG(x)
207 #define DUMP_INFO(x) ALOGI x
208 #define FILE_DUMP_REQUEST_ID 2
209 #define C2S(x)  case x: return #x;
210 static const char *EWP_EventAttrToString(int len_attr);
211 static const char *EWP_CmdAttrToString(int data_attr);
212 
213 typedef struct buf_data {
214     u32 ver; /* version of struct */
215     u32 len; /* Total len */
216     /* size of each buffer in case of split buffers (0 - single buffer). */
217     u32 buf_threshold;
218     const void *data_buf[1]; /* array of user space buffer pointers.*/
219 } buf_data_t;
220 
221 /* Attributes associated with GOOGLE_FILE_DUMP_EVENT */
222 typedef enum {
223     DUMP_LEN_ATTR_INVALID                       = 0,
224     DUMP_LEN_ATTR_MEMDUMP                       = 1,
225     DUMP_LEN_ATTR_SSSR_C0_BEFORE                = 2,
226     DUMP_LEN_ATTR_SSSR_C0_AFTER                 = 3,
227     DUMP_LEN_ATTR_SSSR_C1_BEFORE                = 4,
228     DUMP_LEN_ATTR_SSSR_C1_AFTER                 = 5,
229     DUMP_LEN_ATTR_SSSR_C2_BEFORE                = 6,
230     DUMP_LEN_ATTR_SSSR_C2_AFTER                 = 7,
231     DUMP_LEN_ATTR_SSSR_DIG_BEFORE               = 8,
232     DUMP_LEN_ATTR_SSSR_DIG_AFTER                = 9,
233     DUMP_LEN_ATTR_TIMESTAMP                     = 10,
234     DUMP_LEN_ATTR_GENERAL_LOG                   = 11,
235     DUMP_LEN_ATTR_ECNTRS                        = 12,
236     DUMP_LEN_ATTR_SPECIAL_LOG                   = 13,
237     DUMP_LEN_ATTR_DHD_DUMP                      = 14,
238     DUMP_LEN_ATTR_EXT_TRAP                      = 15,
239     DUMP_LEN_ATTR_HEALTH_CHK                    = 16,
240     DUMP_LEN_ATTR_PRESERVE_LOG                  = 17,
241     DUMP_LEN_ATTR_COOKIE                        = 18,
242     DUMP_LEN_ATTR_FLOWRING_DUMP                 = 19,
243     DUMP_LEN_ATTR_PKTLOG                        = 20,
244     DUMP_LEN_ATTR_PKTLOG_DEBUG                  = 21,
245     DUMP_FILENAME_ATTR_DEBUG_DUMP               = 22,
246     DUMP_FILENAME_ATTR_MEM_DUMP                 = 23,
247     DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP  = 24,
248     DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP   = 25,
249     DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP  = 26,
250     DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP   = 27,
251     DUMP_FILENAME_ATTR_SSSR_CORE_2_BEFORE_DUMP  = 28,
252     DUMP_FILENAME_ATTR_SSSR_CORE_2_AFTER_DUMP   = 29,
253     DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP     = 30,
254     DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP      = 31,
255     DUMP_FILENAME_ATTR_PKTLOG_DUMP              = 32,
256     DUMP_FILENAME_ATTR_PKTLOG_DEBUG_DUMP        = 33,
257     DUMP_LEN_ATTR_STATUS_LOG                    = 34,
258     DUMP_LEN_ATTR_AXI_ERROR                     = 35,
259     DUMP_FILENAME_ATTR_AXI_ERROR_DUMP           = 36,
260     DUMP_LEN_ATTR_RTT_LOG                       = 37,
261     DUMP_LEN_ATTR_SDTC_ETB_DUMP                 = 38,
262     DUMP_FILENAME_ATTR_SDTC_ETB_DUMP            = 39,
263     DUMP_LEN_ATTR_PKTID_MAP_LOG                 = 40,
264     DUMP_LEN_ATTR_PKTID_UNMAP_LOG               = 41,
265     DUMP_LEN_ATTR_EWP_HW_INIT_LOG               = 42,
266     DUMP_LEN_ATTR_EWP_HW_MOD_DUMP               = 43,
267     DUMP_LEN_ATTR_EWP_HW_REG_DUMP               = 44,
268     /*  Please add new attributes from here to sync up old DHD */
269     DUMP_EVENT_ATTR_MAX                         = 45,
270 } EWP_DUMP_EVENT_ATTRIBUTE;
271 
272 /* Attributes associated with DEBUG_GET_DUMP_BUF */
273 typedef enum {
274     DUMP_BUF_ATTR_INVALID               = 0,
275     DUMP_BUF_ATTR_MEMDUMP               = 1,
276     DUMP_BUF_ATTR_SSSR_C0_BEFORE        = 2,
277     DUMP_BUF_ATTR_SSSR_C0_AFTER         = 3,
278     DUMP_BUF_ATTR_SSSR_C1_BEFORE        = 4,
279     DUMP_BUF_ATTR_SSSR_C1_AFTER         = 5,
280     DUMP_BUF_ATTR_SSSR_C2_BEFORE        = 6,
281     DUMP_BUF_ATTR_SSSR_C2_AFTER         = 7,
282     DUMP_BUF_ATTR_SSSR_DIG_BEFORE       = 8,
283     DUMP_BUF_ATTR_SSSR_DIG_AFTER        = 9,
284     DUMP_BUF_ATTR_TIMESTAMP             = 10,
285     DUMP_BUF_ATTR_GENERAL_LOG           = 11,
286     DUMP_BUF_ATTR_ECNTRS                = 12,
287     DUMP_BUF_ATTR_SPECIAL_LOG           = 13,
288     DUMP_BUF_ATTR_DHD_DUMP              = 14,
289     DUMP_BUF_ATTR_EXT_TRAP              = 15,
290     DUMP_BUF_ATTR_HEALTH_CHK            = 16,
291     DUMP_BUF_ATTR_PRESERVE_LOG          = 17,
292     DUMP_BUF_ATTR_COOKIE                = 18,
293     DUMP_BUF_ATTR_FLOWRING_DUMP         = 19,
294     DUMP_BUF_ATTR_PKTLOG                = 20,
295     DUMP_BUF_ATTR_PKTLOG_DEBUG          = 21,
296     DUMP_BUF_ATTR_STATUS_LOG            = 22,
297     DUMP_BUF_ATTR_AXI_ERROR             = 23,
298     DUMP_BUF_ATTR_RTT_LOG               = 24,
299     DUMP_BUF_ATTR_SDTC_ETB_DUMP         = 25,
300     DUMP_BUF_ATTR_PKTID_MAP_LOG         = 26,
301     DUMP_BUF_ATTR_PKTID_UNMAP_LOG       = 27,
302     DUMP_BUF_ATTR_EWP_HW_INIT_LOG       = 28,
303     DUMP_BUF_ATTR_EWP_HW_MOD_DUMP       = 29,
304     DUMP_BUF_ATTR_EWP_HW_REG_DUMP       = 30,
305     /*  Please add new attributes from here to sync up old DHD */
306     DUMP_BUF_ATTR_MAX		        = 31,
307 } EWP_DUMP_CMD_ATTRIBUTE;
308 
309 typedef enum {
310     DUMP_TYPE_MEM_DUMP                  = 0,
311     DUMP_TYPE_DEBUG_DUMP                = 1,
312     DUMP_TYPE_SSSR_CORE0_BEF_DUMP       = 2,
313     DUMP_TYPE_SSSR_CORE0_AFT_DUMP       = 3,
314     DUMP_TYPE_SSSR_CORE1_BEF_DUMP       = 4,
315     DUMP_TYPE_SSSR_CORE1_AFT_DUMP       = 5,
316     DUMP_TYPE_SSSR_CORE2_BEF_DUMP       = 6,
317     DUMP_TYPE_SSSR_CORE2_AFT_DUMP       = 7,
318     DUMP_TYPE_SSSR_DIG_BEF_DUMP         = 8,
319     DUMP_TYPE_SSSR_DIG_AFT_DUMP         = 9,
320     DUMP_TYPE_PKTLOG_DUMP               = 10,
321     DUMP_TYPE_PKTLOG_DEBUG_DUMP         = 11,
322     DUMP_TYPE_AXI_ERROR_DUMP            = 12,
323     DUMP_TYPE_D2H_MINI_DUMP             = 13,
324     DUMP_TYPE_SDTC_ETB_DUMP             = 14,
325     /*  Please add new attributes from here to sync up old DHD */
326     DUMP_TYPE_MAX                       = 15,
327 } EWP_DUMP_TYPE;
328 
329 /* Struct for table which has len_attr, data_attr and dump file type attr */
330 typedef struct logger_attr_entry {
331     u8 attr_type; /* Type of attribute */
332     u8 buf_attr; /* Buffer associated with the attribute */
333     u8 dump_type; /* Each attribute will be linked to a dump type */
334 } logger_attr_entry_t;
335 
336 logger_attr_entry_t attr_lookup_tbl[] = {
337     /* Mem Dump Block */
338     {DUMP_FILENAME_ATTR_MEM_DUMP, 0, DUMP_TYPE_MEM_DUMP},
339     {DUMP_LEN_ATTR_MEMDUMP, DUMP_BUF_ATTR_MEMDUMP, DUMP_TYPE_MEM_DUMP},
340     /* SSSR Dump Block */
341     {DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_CORE0_BEF_DUMP},
342     {DUMP_LEN_ATTR_SSSR_C0_BEFORE, DUMP_BUF_ATTR_SSSR_C0_BEFORE, DUMP_TYPE_SSSR_CORE0_BEF_DUMP},
343 
344     {DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP, 0, DUMP_TYPE_SSSR_CORE0_AFT_DUMP},
345     {DUMP_LEN_ATTR_SSSR_C0_AFTER, DUMP_BUF_ATTR_SSSR_C0_AFTER, DUMP_TYPE_SSSR_CORE0_AFT_DUMP},
346 
347     {DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_CORE1_BEF_DUMP},
348     {DUMP_LEN_ATTR_SSSR_C1_BEFORE, DUMP_BUF_ATTR_SSSR_C1_BEFORE, DUMP_TYPE_SSSR_CORE1_BEF_DUMP},
349 
350     {DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP, 0, DUMP_TYPE_SSSR_CORE1_AFT_DUMP},
351     {DUMP_LEN_ATTR_SSSR_C1_AFTER, DUMP_BUF_ATTR_SSSR_C1_AFTER, DUMP_TYPE_SSSR_CORE1_AFT_DUMP},
352 
353     {DUMP_FILENAME_ATTR_SSSR_CORE_2_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_CORE2_BEF_DUMP},
354     {DUMP_LEN_ATTR_SSSR_C2_BEFORE, DUMP_BUF_ATTR_SSSR_C2_BEFORE, DUMP_TYPE_SSSR_CORE2_BEF_DUMP},
355 
356     {DUMP_FILENAME_ATTR_SSSR_CORE_2_AFTER_DUMP, 0, DUMP_TYPE_SSSR_CORE2_AFT_DUMP},
357     {DUMP_LEN_ATTR_SSSR_C2_AFTER, DUMP_BUF_ATTR_SSSR_C2_AFTER, DUMP_TYPE_SSSR_CORE2_AFT_DUMP},
358 
359     {DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP, 0, DUMP_TYPE_SSSR_DIG_BEF_DUMP},
360     {DUMP_LEN_ATTR_SSSR_DIG_BEFORE, DUMP_BUF_ATTR_SSSR_DIG_BEFORE, DUMP_TYPE_SSSR_DIG_BEF_DUMP},
361 
362     {DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP, 0, DUMP_TYPE_SSSR_DIG_AFT_DUMP},
363     {DUMP_LEN_ATTR_SSSR_DIG_AFTER, DUMP_BUF_ATTR_SSSR_DIG_AFTER, DUMP_TYPE_SSSR_DIG_AFT_DUMP},
364 
365     /* Debug Dump Block */
366     {DUMP_FILENAME_ATTR_DEBUG_DUMP, 0, DUMP_TYPE_DEBUG_DUMP},
367     {DUMP_LEN_ATTR_TIMESTAMP, DUMP_BUF_ATTR_TIMESTAMP, DUMP_TYPE_DEBUG_DUMP},
368     {DUMP_LEN_ATTR_GENERAL_LOG, DUMP_BUF_ATTR_GENERAL_LOG, DUMP_TYPE_DEBUG_DUMP},
369     {DUMP_LEN_ATTR_ECNTRS, DUMP_BUF_ATTR_ECNTRS, DUMP_TYPE_DEBUG_DUMP},
370     {DUMP_LEN_ATTR_SPECIAL_LOG, DUMP_BUF_ATTR_SPECIAL_LOG, DUMP_TYPE_DEBUG_DUMP},
371     {DUMP_LEN_ATTR_DHD_DUMP, DUMP_BUF_ATTR_DHD_DUMP, DUMP_TYPE_DEBUG_DUMP},
372     {DUMP_LEN_ATTR_EXT_TRAP, DUMP_BUF_ATTR_EXT_TRAP, DUMP_TYPE_DEBUG_DUMP},
373     {DUMP_LEN_ATTR_HEALTH_CHK, DUMP_BUF_ATTR_HEALTH_CHK, DUMP_TYPE_DEBUG_DUMP},
374     {DUMP_LEN_ATTR_PRESERVE_LOG, DUMP_BUF_ATTR_PRESERVE_LOG, DUMP_TYPE_DEBUG_DUMP},
375     {DUMP_LEN_ATTR_COOKIE, DUMP_BUF_ATTR_COOKIE, DUMP_TYPE_DEBUG_DUMP},
376     {DUMP_LEN_ATTR_FLOWRING_DUMP, DUMP_BUF_ATTR_FLOWRING_DUMP, DUMP_TYPE_DEBUG_DUMP},
377     {DUMP_LEN_ATTR_STATUS_LOG, DUMP_BUF_ATTR_STATUS_LOG, DUMP_TYPE_DEBUG_DUMP},
378     {DUMP_LEN_ATTR_RTT_LOG, DUMP_BUF_ATTR_RTT_LOG, DUMP_TYPE_DEBUG_DUMP},
379     {DUMP_LEN_ATTR_PKTID_MAP_LOG, DUMP_BUF_ATTR_PKTID_MAP_LOG, DUMP_TYPE_DEBUG_DUMP},
380     {DUMP_LEN_ATTR_PKTID_UNMAP_LOG, DUMP_BUF_ATTR_PKTID_UNMAP_LOG, DUMP_TYPE_DEBUG_DUMP},
381     {DUMP_LEN_ATTR_EWP_HW_INIT_LOG, DUMP_BUF_ATTR_EWP_HW_INIT_LOG, DUMP_TYPE_DEBUG_DUMP},
382     {DUMP_LEN_ATTR_EWP_HW_MOD_DUMP, DUMP_BUF_ATTR_EWP_HW_MOD_DUMP, DUMP_TYPE_DEBUG_DUMP},
383     {DUMP_LEN_ATTR_EWP_HW_REG_DUMP, DUMP_BUF_ATTR_EWP_HW_REG_DUMP, DUMP_TYPE_DEBUG_DUMP},
384 
385     /* PKT log dump block */
386     {DUMP_FILENAME_ATTR_PKTLOG_DUMP, 0, DUMP_TYPE_PKTLOG_DUMP},
387     {DUMP_LEN_ATTR_PKTLOG, DUMP_BUF_ATTR_PKTLOG, DUMP_TYPE_PKTLOG_DUMP},
388     {DUMP_FILENAME_ATTR_PKTLOG_DEBUG_DUMP, 0, DUMP_TYPE_PKTLOG_DEBUG_DUMP},
389     {DUMP_LEN_ATTR_PKTLOG_DEBUG, DUMP_BUF_ATTR_PKTLOG_DEBUG, DUMP_TYPE_PKTLOG_DEBUG_DUMP},
390     /* AXI error log dump block */
391     {DUMP_FILENAME_ATTR_AXI_ERROR_DUMP, 0, DUMP_TYPE_AXI_ERROR_DUMP},
392     {DUMP_LEN_ATTR_AXI_ERROR, DUMP_BUF_ATTR_AXI_ERROR, DUMP_TYPE_AXI_ERROR_DUMP},
393     /* SDTC etb log dump block */
394     {DUMP_FILENAME_ATTR_SDTC_ETB_DUMP, 0, DUMP_TYPE_SDTC_ETB_DUMP},
395     {DUMP_LEN_ATTR_SDTC_ETB_DUMP, DUMP_BUF_ATTR_SDTC_ETB_DUMP, DUMP_TYPE_SDTC_ETB_DUMP},
396     {DUMP_EVENT_ATTR_MAX, 0, 0},
397 };
398 
EWP_EventAttrToString(int len_attr)399 static const char *EWP_EventAttrToString(int len_attr)
400 {
401     switch (len_attr) {
402         C2S(DUMP_LEN_ATTR_MEMDUMP)
403         C2S(DUMP_LEN_ATTR_SSSR_C0_BEFORE)
404         C2S(DUMP_LEN_ATTR_SSSR_C0_AFTER)
405         C2S(DUMP_LEN_ATTR_SSSR_C1_BEFORE)
406         C2S(DUMP_LEN_ATTR_SSSR_C1_AFTER)
407         C2S(DUMP_LEN_ATTR_SSSR_C2_BEFORE)
408         C2S(DUMP_LEN_ATTR_SSSR_C2_AFTER)
409         C2S(DUMP_LEN_ATTR_SSSR_DIG_BEFORE)
410         C2S(DUMP_LEN_ATTR_SSSR_DIG_AFTER)
411         C2S(DUMP_LEN_ATTR_TIMESTAMP)
412         C2S(DUMP_LEN_ATTR_GENERAL_LOG)
413         C2S(DUMP_LEN_ATTR_ECNTRS)
414         C2S(DUMP_LEN_ATTR_SPECIAL_LOG)
415         C2S(DUMP_LEN_ATTR_DHD_DUMP)
416         C2S(DUMP_LEN_ATTR_EXT_TRAP)
417         C2S(DUMP_LEN_ATTR_HEALTH_CHK)
418         C2S(DUMP_LEN_ATTR_PRESERVE_LOG)
419         C2S(DUMP_LEN_ATTR_COOKIE)
420         C2S(DUMP_LEN_ATTR_FLOWRING_DUMP)
421         C2S(DUMP_LEN_ATTR_PKTLOG)
422         C2S(DUMP_LEN_ATTR_PKTLOG_DEBUG)
423         C2S(DUMP_LEN_ATTR_STATUS_LOG)
424         C2S(DUMP_FILENAME_ATTR_DEBUG_DUMP)
425         C2S(DUMP_FILENAME_ATTR_MEM_DUMP)
426         C2S(DUMP_FILENAME_ATTR_SSSR_CORE_0_BEFORE_DUMP)
427         C2S(DUMP_FILENAME_ATTR_SSSR_CORE_0_AFTER_DUMP)
428         C2S(DUMP_FILENAME_ATTR_SSSR_CORE_1_BEFORE_DUMP)
429         C2S(DUMP_FILENAME_ATTR_SSSR_CORE_1_AFTER_DUMP)
430         C2S(DUMP_FILENAME_ATTR_SSSR_CORE_2_BEFORE_DUMP)
431         C2S(DUMP_FILENAME_ATTR_SSSR_CORE_2_AFTER_DUMP)
432         C2S(DUMP_FILENAME_ATTR_SSSR_DIG_BEFORE_DUMP)
433         C2S(DUMP_FILENAME_ATTR_SSSR_DIG_AFTER_DUMP)
434         C2S(DUMP_FILENAME_ATTR_PKTLOG_DUMP)
435         C2S(DUMP_FILENAME_ATTR_PKTLOG_DEBUG_DUMP)
436         C2S(DUMP_LEN_ATTR_AXI_ERROR)
437         C2S(DUMP_FILENAME_ATTR_AXI_ERROR_DUMP)
438         C2S(DUMP_LEN_ATTR_RTT_LOG)
439         C2S(DUMP_FILENAME_ATTR_SDTC_ETB_DUMP)
440         C2S(DUMP_LEN_ATTR_SDTC_ETB_DUMP)
441         C2S(DUMP_LEN_ATTR_PKTID_MAP_LOG)
442         C2S(DUMP_LEN_ATTR_PKTID_UNMAP_LOG)
443         C2S(DUMP_LEN_ATTR_EWP_HW_INIT_LOG)
444         C2S(DUMP_LEN_ATTR_EWP_HW_MOD_DUMP)
445         C2S(DUMP_LEN_ATTR_EWP_HW_REG_DUMP)
446         default:
447             return "DUMP_LEN_ATTR_INVALID";
448     }
449 }
450 
EWP_CmdAttrToString(int attr)451 static const char *EWP_CmdAttrToString(int attr)
452 {
453     switch (attr) {
454         C2S(DUMP_BUF_ATTR_MEMDUMP)
455         C2S(DUMP_BUF_ATTR_SSSR_C0_BEFORE)
456         C2S(DUMP_BUF_ATTR_SSSR_C0_AFTER)
457         C2S(DUMP_BUF_ATTR_SSSR_C1_BEFORE)
458         C2S(DUMP_BUF_ATTR_SSSR_C1_AFTER)
459         C2S(DUMP_BUF_ATTR_SSSR_C2_BEFORE)
460         C2S(DUMP_BUF_ATTR_SSSR_C2_AFTER)
461         C2S(DUMP_BUF_ATTR_SSSR_DIG_BEFORE)
462         C2S(DUMP_BUF_ATTR_SSSR_DIG_AFTER)
463         C2S(DUMP_BUF_ATTR_TIMESTAMP)
464         C2S(DUMP_BUF_ATTR_GENERAL_LOG)
465         C2S(DUMP_BUF_ATTR_ECNTRS)
466         C2S(DUMP_BUF_ATTR_SPECIAL_LOG)
467         C2S(DUMP_BUF_ATTR_DHD_DUMP)
468         C2S(DUMP_BUF_ATTR_EXT_TRAP)
469         C2S(DUMP_BUF_ATTR_HEALTH_CHK)
470         C2S(DUMP_BUF_ATTR_PRESERVE_LOG)
471         C2S(DUMP_BUF_ATTR_COOKIE)
472         C2S(DUMP_BUF_ATTR_FLOWRING_DUMP)
473         C2S(DUMP_BUF_ATTR_PKTLOG)
474         C2S(DUMP_BUF_ATTR_PKTLOG_DEBUG)
475         C2S(DUMP_BUF_ATTR_STATUS_LOG)
476         C2S(DUMP_BUF_ATTR_AXI_ERROR)
477         C2S(DUMP_BUF_ATTR_RTT_LOG)
478         C2S(DUMP_BUF_ATTR_SDTC_ETB_DUMP)
479         C2S(DUMP_BUF_ATTR_PKTID_MAP_LOG)
480         C2S(DUMP_BUF_ATTR_PKTID_UNMAP_LOG)
481         C2S(DUMP_BUF_ATTR_EWP_HW_INIT_LOG)
482         C2S(DUMP_BUF_ATTR_EWP_HW_MOD_DUMP)
483         C2S(DUMP_BUF_ATTR_EWP_HW_REG_DUMP)
484         default:
485             return "DUMP_BUF_ATTR_INVALID";
486     }
487 }
488 
489 /* Return index for matching buffer attribute */
logger_attr_buffer_lookup(u8 attr)490 static int logger_attr_buffer_lookup(u8 attr) {
491     for (u8 i = 0; i < ARRAYSIZE(attr_lookup_tbl); i++) {
492         if (attr == attr_lookup_tbl[i].buf_attr) {
493             return i;
494         }
495     }
496     ALOGE("Lookup for buf attr = %s failed\n",
497     EWP_CmdAttrToString(attr));
498     return -1;
499 }
500 
501 /* Return index matching the length attribute */
logger_attr_lookup(u8 attr)502 static int logger_attr_lookup(u8 attr) {
503     for (u8 i = 0; i < ARRAYSIZE(attr_lookup_tbl); i++) {
504         if (attr == attr_lookup_tbl[i].attr_type) {
505             return i;
506         }
507     }
508     ALOGE("Lookup for len attr = %s failed\n",
509         EWP_EventAttrToString(attr));
510     return -1;
511 }
512 #endif /* RING_DUMP */
513 
514 #define DBGRING_NAME_MAX 32  //Copy from legacy hal
515 typedef struct wifi_buf_ring_map_entry {
516     uint32_t type;
517     uint32_t ring_id;
518     char ring_name[DBGRING_NAME_MAX];
519 } wifi_buf_ring_map_entry_t;
520 
521 typedef struct {
522     char hw_id[PROPERTY_VALUE_MAX];
523     char sku[MAX_SKU_NAME_LEN];
524 } sku_info_t;
525 
526 sku_info_t sku_table[] = {
527     // BCM4389
528     { {"G9S9B"}, {"MMW"} },
529     { {"G8V0U"}, {"MMW"} },
530     { {"GFQM1"}, {"MMW"} },
531     { {"GB62Z"}, {"MMW"} },
532     { {"GE2AE"}, {"MMW"} },
533     { {"GQML3"}, {"MMW"} },
534     { {"GB7N6"}, {"ROW"} },
535     { {"GLU0G"}, {"ROW"} },
536     { {"GNA8F"}, {"ROW"} },
537     { {"GX7AS"}, {"ROW"} },
538     { {"GP4BC"}, {"ROW"} },
539     { {"GVU6C"}, {"ROW"} },
540     { {"GR1YH"}, {"JPN"} },
541     { {"GF5KQ"}, {"JPN"} },
542     { {"GPQ72"}, {"JPN"} },
543     { {"GB17L"}, {"JPN"} },
544     { {"GFE4J"}, {"JPN"} },
545     { {"G03Z5"}, {"JPN"} },
546     // BCM4398
547     { {"GKWS6"}, {"MMW"} },
548     { {"G1MNW"}, {"MMW"} },
549     { {"GPJ41"}, {"ROW"} },
550     { {"GC3VE"}, {"ROW"} },
551     { {"GE9DP"}, {"JPN"} },
552     { {"GZPF0"}, {"JPN"} },
553     { {"G1AZG"}, {"EU"} },
554     { {"G9BQD"}, {"NA"} },
555     // BCM4383
556     { {"G8HHN"}, {"MMW"} },
557     { {"G6GPR"}, {"ROW"} },
558     { {"G576D"}, {"JPN"} },
559     { {"GKV4X"}, {"NA"} }
560 };
561 ///////////////////////////////////////////////////////////////////////////////
562 class DebugCommand : public WifiCommand
563 {
564     char *mBuff;
565     int *mBuffSize;
566     u32 *mNumRings;
567     wifi_ring_buffer_status *mStatus;
568     u32 *mNumMaps;
569     wifi_buf_ring_map_entry_t *mMaps;
570     unsigned int *mSupport;
571     u32 mVerboseLevel;
572     u32 mFlags;
573     u32 mMaxIntervalSec;
574     u32 mMinDataSize;
575     char *mRingName;
576     GetCmdType mType;
577 
578 public:
579 
580     // constructor for get version
DebugCommand(wifi_interface_handle iface,char * buffer,int * buffer_size,GetCmdType cmdType)581     DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,
582             GetCmdType cmdType)
583         : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
584         (cmdType)
585     {
586         mNumRings =  NULL;
587         mStatus = NULL;
588         mSupport = NULL;
589         mVerboseLevel = 0;
590         mFlags = 0;
591         mMaxIntervalSec = 0;
592         mMinDataSize = 0;
593         mRingName = NULL;
594         memset(mBuff, 0, *mBuffSize);
595     }
596 
597     // constructor for ring data
DebugCommand(wifi_interface_handle iface,char * ring_name,GetCmdType cmdType)598     DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
599         : WifiCommand("DebugCommand", iface, 0), mRingName(ring_name), mType(cmdType)
600     {
601         mBuff = NULL;
602         mBuffSize = NULL;
603         mNumRings =  NULL;
604         mStatus = NULL;
605         mSupport = NULL;
606         mVerboseLevel = 0;
607         mFlags = 0;
608         mMaxIntervalSec = 0;
609         mMinDataSize = 0;
610     }
611 
612     // constructor for ring status
DebugCommand(wifi_interface_handle iface,u32 * num_rings,wifi_ring_buffer_status * status,GetCmdType cmdType)613     DebugCommand(wifi_interface_handle iface, u32 *num_rings,
614             wifi_ring_buffer_status *status, GetCmdType cmdType)
615         : WifiCommand("DebugCommand", iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
616     {
617         mBuff = NULL;
618         mBuffSize = NULL;
619         mSupport = NULL;
620         mVerboseLevel = 0;
621         mFlags = 0;
622         mMaxIntervalSec = 0;
623         mMinDataSize = 0;
624         mRingName = NULL;
625         memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
626     }
627 
628     // constructor for feature set
DebugCommand(wifi_interface_handle iface,unsigned int * support,GetCmdType cmdType)629     DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
630         : WifiCommand("DebugCommand", iface, 0), mSupport(support), mType(cmdType)
631     {
632         mBuff = NULL;
633         mBuffSize = NULL;
634         mNumRings =  NULL;
635         mStatus = NULL;
636         mVerboseLevel = 0;
637         mFlags = 0;
638         mMaxIntervalSec = 0;
639         mMinDataSize = 0;
640         mRingName = NULL;
641     }
642 
643     // constructor for buf ring map
DebugCommand(wifi_interface_handle iface,u32 * num_maps,wifi_buf_ring_map_entry_t * map,GetCmdType cmdType)644     DebugCommand(wifi_interface_handle iface, u32 *num_maps,
645             wifi_buf_ring_map_entry_t *map, GetCmdType cmdType)
646         : WifiCommand("DebugCommand", iface, 0), mNumMaps(num_maps), mMaps(map), mType(cmdType)
647     {
648         memset(mMaps, 0, sizeof(wifi_buf_ring_map_entry_t) * (*mNumMaps));
649     }
650 
651     // 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)652     DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
653             u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)
654         : WifiCommand("DebugCommand", iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
655         mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
656         mRingName(ring_name), mType(cmdType)
657     {
658         mBuff = NULL;
659         mBuffSize = NULL;
660         mNumRings =  NULL;
661         mStatus = NULL;
662         mSupport = NULL;
663     }
664 
createRingRequest(WifiRequest & request)665     int createRingRequest(WifiRequest& request) {
666         int result = request.create(GOOGLE_OUI, LOGGER_START_LOGGING);
667         if (result != WIFI_SUCCESS) {
668             ALOGE("Failed to create start ring logger request; result = %d", result);
669             return result;
670         }
671 
672         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
673 
674         result = request.put_u32(LOGGER_ATTRIBUTE_LOG_LEVEL, mVerboseLevel);
675         if (result != WIFI_SUCCESS) {
676             ALOGE("Failed to put log level; result = %d", result);
677             return result;
678         }
679         result = request.put_u32(LOGGER_ATTRIBUTE_RING_FLAGS, mFlags);
680         if (result != WIFI_SUCCESS) {
681             ALOGE("Failed to put ring flags; result = %d", result);
682             return result;
683         }
684         result = request.put_u32(LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, mMaxIntervalSec);
685         if (result != WIFI_SUCCESS) {
686             ALOGE("Failed to put log time interval; result = %d", result);
687             return result;
688         }
689         result = request.put_u32(LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, mMinDataSize);
690         if (result != WIFI_SUCCESS) {
691             ALOGE("Failed to put min data size; result = %d", result);
692             return result;
693         }
694         result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
695         if (result != WIFI_SUCCESS) {
696             ALOGE("Failed to put ringbuffer name; result = %d", result);
697             return result;
698         }
699         request.attr_end(data);
700 
701         return WIFI_SUCCESS;
702     }
703 
createRequest(WifiRequest & request)704     int createRequest(WifiRequest &request) {
705         int result;
706 
707         switch (mType) {
708             case GET_FW_VER:
709             {
710                 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
711                 if (result != WIFI_SUCCESS) {
712                     ALOGE("Failed to create get fw version request; result = %d", result);
713                     return result;
714                 }
715 
716                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
717 
718                 // Driver expecting only attribute type, passing mbuff as data with
719                 // length 0 to avoid undefined state
720                 result = request.put(LOGGER_ATTRIBUTE_FW_VER, mBuff, 0);
721                 if (result != WIFI_SUCCESS) {
722                     ALOGE("Failed to put get fw version request; result = %d", result);
723                     return result;
724                 }
725                 request.attr_end(data);
726                 break;
727             }
728 
729             case GET_DRV_VER:
730             {
731                 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
732                 if (result != WIFI_SUCCESS) {
733                     ALOGE("Failed to create get drv version request; result = %d", result);
734                     return result;
735                 }
736 
737                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
738 
739                 // Driver expecting only attribute type, passing mbuff as data with
740                 // length 0 to avoid undefined state
741                 result = request.put(LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);
742 
743                 if (result != WIFI_SUCCESS) {
744                     ALOGE("Failed to put get drv version request; result = %d", result);
745                     return result;
746                 }
747                 request.attr_end(data);
748                 break;
749             }
750 
751             case GET_RING_DATA:
752             {
753                 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_DATA);
754                 if (result != WIFI_SUCCESS) {
755                     ALOGE("Failed to create get ring data request; result = %d", result);
756                     return result;
757                 }
758 
759                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
760                 result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
761                 if (result != WIFI_SUCCESS) {
762                     ALOGE("Failed to put ring data request; result = %d", result);
763                     return result;
764                 }
765                 request.attr_end(data);
766                 break;
767             }
768 
769             case GET_RING_STATUS:
770             {
771                 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_STATUS);
772                 if (result != WIFI_SUCCESS) {
773                     ALOGE("Failed to create get ring status request; result = %d", result);
774                     return result;
775                 }
776                 break;
777             }
778 
779             case GET_FEATURE:
780             {
781                 result = request.create(GOOGLE_OUI, LOGGER_GET_FEATURE);
782                 if (result != WIFI_SUCCESS) {
783                     ALOGE("Failed to create get feature request; result = %d", result);
784                     return result;
785                 }
786                 break;
787             }
788 
789             case GET_BUF_RING_MAP:
790             {
791                 result = request.create(GOOGLE_OUI, LOGGER_GET_BUF_RING_MAP);
792                 if (result != WIFI_SUCCESS) {
793                     ALOGE("Failed to create get ring status request; result = %d", result);
794                     return result;
795                 }
796                 break;
797             }
798 
799             case START_RING_LOG:
800                 result = createRingRequest(request);
801                 break;
802 
803             default:
804                 ALOGE("Unknown Debug command");
805                 result = WIFI_ERROR_UNKNOWN;
806         }
807         return result;
808     }
809 
start()810     int start() {
811         ALOGD("Start debug command");
812         WifiRequest request(familyId(), ifaceId());
813         int result = createRequest(request);
814         if (result != WIFI_SUCCESS) {
815             ALOGE("Failed to create debug request; result = %d", result);
816             return result;
817         }
818 
819         result = requestResponse(request);
820         if (result != WIFI_SUCCESS) {
821             ALOGE("Failed to register debug response; result = %d", result);
822         }
823         return result;
824     }
825 
handleResponse(WifiEvent & reply)826     virtual int handleResponse(WifiEvent& reply) {
827         ALOGD("In DebugCommand::handleResponse, mType:%d\n", mType);
828 
829         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
830             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
831             return NL_SKIP;
832         }
833 
834         switch (mType) {
835             case GET_DRV_VER:
836             case GET_FW_VER:
837             {
838                 void *data = reply.get_vendor_data();
839                 int len = reply.get_vendor_data_len();
840 
841                 ALOGD("len = %d, expected len = %d", len, *mBuffSize);
842                 memcpy(mBuff, data, min(len, *mBuffSize));
843                 if (*mBuffSize < len)
844                     return NL_SKIP;
845                 *mBuffSize = len;
846                 break;
847             }
848 
849             case START_RING_LOG:
850             case GET_RING_DATA:
851                 break;
852 
853             case GET_RING_STATUS:
854             {
855                 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
856                 int len = reply.get_vendor_data_len();
857                 wifi_ring_buffer_status *status(mStatus);
858 
859                 if (vendor_data == NULL || len == 0) {
860                     ALOGE("No Debug data found");
861                     return NL_SKIP;
862                 }
863 
864                 nl_iterator it(vendor_data);
865                 if (it.get_type() == LOGGER_ATTRIBUTE_RING_NUM) {
866                     unsigned int num_rings = it.get_u32();
867                     if (*mNumRings < num_rings) {
868                         ALOGE("Not enough status buffers provided, available: %d required: %d",
869                                 *mNumRings, num_rings);
870                     } else {
871                         *mNumRings = num_rings;
872                     }
873                 } else {
874                     ALOGE("Unknown attribute: %d expecting %d",
875                             it.get_type(), LOGGER_ATTRIBUTE_RING_NUM);
876                     return NL_SKIP;
877                 }
878 
879                 it.next();
880                 for (unsigned int i = 0; it.has_next() && i < *mNumRings; it.next()) {
881                     if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
882                         if (it.get_len() > sizeof(wifi_ring_buffer_status)) {
883                             ALOGE("ring status unexpected len = %d, dest len = %lu",
884                                 it.get_len(), sizeof(wifi_ring_buffer_status));
885                             return NL_SKIP;
886                         } else {
887                             memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status));
888                             i++;
889                             status++;
890                         }
891                     } else {
892                         ALOGW("Ignoring invalid attribute type = %d, size = %d",
893                                 it.get_type(), it.get_len());
894                     }
895                 }
896                 break;
897             }
898 
899             case GET_FEATURE:
900             {
901                 void *data = reply.get_vendor_data();
902                 int len = reply.get_vendor_data_len();
903 
904                 ALOGD("len = %d, expected len = %lu", len, sizeof(unsigned int));
905                 memcpy(mSupport, data, sizeof(unsigned int));
906                 break;
907             }
908 
909             case GET_BUF_RING_MAP:
910             {
911                 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
912                 int len = reply.get_vendor_data_len();
913                 wifi_buf_ring_map_entry_t *map(mMaps);
914 
915                 if (vendor_data == NULL || len == 0) {
916                     ALOGE("No Debug data found");
917                     return NL_SKIP;
918                 }
919 
920                 nl_iterator it(vendor_data);
921                 if (it.get_type() == LOGGER_ATTRIBUTE_BUF_RING_NUM) {
922                     unsigned int num_maps = it.get_u32();
923                     if (*mNumMaps < num_maps) {
924                         ALOGE("Not enough status buffers provided, available: %d required: %d",
925                             *mNumMaps, num_maps);
926                     } else {
927                         *mNumMaps = num_maps;
928                     }
929                 } else {
930                     ALOGE("Unknown attribute: %d expecting %d",
931                         it.get_type(), LOGGER_ATTRIBUTE_BUF_RING_NUM);
932                     return NL_SKIP;
933                 }
934 
935                 it.next();
936                 for (unsigned int i = 0; it.has_next() && i < *mNumMaps; it.next()) {
937                     if (it.get_type() == LOGGER_ATTRIBUTE_BUF_RING_MAP) {
938                         if (it.get_len() > sizeof(wifi_buf_ring_map_entry_t)) {
939                             ALOGE("GET_BUF_RING_MAP: unexpected len = %d, dest len = %lu",
940                                 it.get_len(), sizeof(wifi_buf_ring_map_entry_t));
941                             return NL_SKIP;
942                         } else {
943                             memcpy(map, it.get_data(), sizeof(wifi_buf_ring_map_entry_t));
944                         }
945                         i++;
946                         map++;
947                     } else {
948                         ALOGW("Ignoring invalid attribute type = %d, size = %d",
949                             it.get_type(), it.get_len());
950                     }
951                 }
952                 break;
953             }
954 
955             default:
956                 ALOGW("Unknown Debug command");
957         }
958         return NL_OK;
959     }
960 
handleEvent(WifiEvent & event)961     virtual int handleEvent(WifiEvent& event) {
962         /* NO events! */
963         return NL_SKIP;
964     }
965 };
966 
967 /* API to collect a firmware version string */
wifi_get_firmware_version(wifi_interface_handle iface,char * buffer,int buffer_size)968 wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
969         int buffer_size)
970 {
971     if (buffer && (buffer_size > 0)) {
972         DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);
973         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
974         wifi_error result = (wifi_error)cmd->start();
975         cmd->releaseRef();
976         return result;
977     } else {
978         ALOGE("FW version buffer NULL");
979         return  WIFI_ERROR_INVALID_ARGS;
980     }
981 }
982 
983 /* API to collect a driver version string */
wifi_get_driver_version(wifi_interface_handle iface,char * buffer,int buffer_size)984 wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
985 {
986     if (buffer && (buffer_size > 0)) {
987         DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);
988         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
989         wifi_error result = (wifi_error)cmd->start();
990         cmd->releaseRef();
991         return result;
992     } else {
993         ALOGE("Driver version buffer NULL");
994         return  WIFI_ERROR_INVALID_ARGS;
995     }
996 }
997 
998 /* API to collect driver records */
wifi_get_ring_data(wifi_interface_handle iface,char * ring_name)999 wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)
1000 {
1001     DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);
1002     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1003     wifi_error result = (wifi_error)cmd->start();
1004     cmd->releaseRef();
1005     return result;
1006 }
1007 
1008 /* 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)1009 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
1010         u32 *num_rings, wifi_ring_buffer_status *status)
1011 {
1012     if (status && num_rings) {
1013         DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);
1014         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1015         wifi_error result = (wifi_error)cmd->start();
1016         cmd->releaseRef();
1017         return result;
1018     } else {
1019         ALOGE("Ring status buffer NULL");
1020         return  WIFI_ERROR_INVALID_ARGS;
1021     }
1022 }
1023 
1024 /* API to get supportable feature */
wifi_get_logger_supported_feature_set(wifi_interface_handle iface,unsigned int * support)1025 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
1026         unsigned int *support)
1027 {
1028     if (support) {
1029         DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);
1030         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1031         wifi_error result = (wifi_error)cmd->start();
1032         cmd->releaseRef();
1033         return result;
1034     } else {
1035         ALOGE("Get support buffer NULL");
1036         return  WIFI_ERROR_INVALID_ARGS;
1037     }
1038 }
1039 
wifi_start_logging(wifi_interface_handle iface,u32 verbose_level,u32 flags,u32 max_interval_sec,u32 min_data_size,char * ring_name)1040 wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
1041         u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
1042 {
1043     if (ring_name) {
1044         ALOGE("Ring name: level:%d sec:%d ring_name:%s",
1045                 verbose_level, max_interval_sec, ring_name);
1046         DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
1047                     min_data_size, ring_name, START_RING_LOG);
1048         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1049         wifi_error result = (wifi_error)cmd->start();
1050         cmd->releaseRef();
1051         return result;
1052     } else {
1053         ALOGE("Ring name NULL");
1054         return  WIFI_ERROR_INVALID_ARGS;
1055     }
1056 }
1057 
1058 typedef struct {
1059     u32 magic;
1060     int num_entries;
1061 } __attribute__((packed)) wifi_ring_buffer_entry_pack;
1062 
1063 #define WIFI_RING_BUFFER_PACK_MAGIC 0xDBAADBAA
1064 
1065 ///////////////////////////////////////////////////////////////////////////////
1066 class SetLogHandler : public WifiCommand
1067 {
1068     wifi_ring_buffer_data_handler mHandler;
1069 
1070 public:
SetLogHandler(wifi_interface_handle iface,int id,wifi_ring_buffer_data_handler handler)1071     SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
1072         : WifiCommand("SetLogHandler", iface, id), mHandler(handler)
1073     { }
1074 
start()1075     int start() {
1076         ALOGV("Register loghandler");
1077         int result;
1078         uint32_t event_sock_pid = getpid() + (WIFI_HAL_EVENT_SOCK_PORT << 22);
1079 
1080         WifiRequest request(familyId(), ifaceId());
1081 
1082         /* set hal event socket port to driver */
1083         result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_PID);
1084         if (result != WIFI_SUCCESS) {
1085             ALOGV("Failed to set Hal preInit; result = %d", result);
1086             return result;
1087         }
1088         registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
1089 
1090         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1091         result = request.put_u32(SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID, event_sock_pid);
1092         if (result != WIFI_SUCCESS) {
1093             unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
1094             ALOGV("Hal preInit Failed to put pic = %d", result);
1095             return result;
1096         }
1097 
1098         if (result != WIFI_SUCCESS) {
1099             unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
1100             ALOGV("Hal preInit Failed to put pid= %d", result);
1101             return result;
1102         }
1103 
1104         request.attr_end(data);
1105 
1106         result = requestResponse(request);
1107         if (result != WIFI_SUCCESS) {
1108             unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
1109             ALOGE("Failed to register set Hal preInit; result = %d", result);
1110             return result;
1111         }
1112         return result;
1113     }
1114 
cancel()1115     virtual int cancel() {
1116         /* Send a command to driver to stop generating logging events */
1117         ALOGV("Clear loghandler");
1118 
1119         /* unregister event handler */
1120         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
1121         wifi_unregister_cmd(wifiHandle(), id());
1122 
1123         WifiRequest request(familyId(), ifaceId());
1124         int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
1125         if (result != WIFI_SUCCESS) {
1126             ALOGE("failed to create reset request; result = %d", result);
1127             return result;
1128         }
1129 
1130         result = requestResponse(request);
1131         if (result != WIFI_SUCCESS) {
1132             ALOGE("failed to request reset; result = %d", result);
1133             return result;
1134         }
1135 
1136         ALOGD("Success to clear loghandler");
1137         return WIFI_SUCCESS;
1138     }
1139 
handleEvent(WifiEvent & event)1140     virtual int handleEvent(WifiEvent& event) {
1141         char *buffer = NULL;
1142         int buffer_size = 0;
1143 
1144         // ALOGD("In SetLogHandler::handleEvent");
1145         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1146         int len = event.get_vendor_data_len();
1147         int event_id = event.get_vendor_subcmd();
1148         // ALOGI("Got Logger event: %d", event_id);
1149 
1150         if (vendor_data == NULL || len == 0) {
1151             ALOGE("No Debug data found");
1152             return NL_SKIP;
1153         }
1154 
1155         if (event_id == GOOGLE_DEBUG_RING_EVENT) {
1156             wifi_ring_buffer_status status;
1157             memset(&status, 0, sizeof(status));
1158 
1159             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1160                 if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
1161                     if (it.get_len() > sizeof(wifi_ring_buffer_status)) {
1162                         ALOGE("SetLogHandler: ring status unexpected len = %d, dest len = %lu",
1163                            it.get_len(), sizeof(wifi_ring_buffer_status));
1164                         return NL_SKIP;
1165                     } else {
1166                         memcpy(&status, it.get_data(), sizeof(wifi_ring_buffer_status));
1167                     }
1168                 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
1169                     buffer_size = it.get_len();
1170                     buffer = (char *)it.get_data();
1171                     ALOGV("SetLogHandler: ring data size = %d", buffer_size);
1172                 } else {
1173                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
1174                             it.get_type(), it.get_len());
1175                 }
1176             }
1177 
1178             // ALOGI("Retrieved Debug data");
1179             if (mHandler.on_ring_buffer_data) {
1180                 /* Skip msg header. Retrieved log */
1181                 char *pBuff;
1182                 int num_entries;
1183                 int cur_off = 0;
1184                 wifi_ring_buffer_entry_pack *pack_hdr =
1185                     (wifi_ring_buffer_entry_pack *)buffer;
1186                 wifi_ring_buffer_entry *entry_hdr =
1187                     (wifi_ring_buffer_entry *)(buffer + sizeof(*pack_hdr));
1188                 cur_off += sizeof(*pack_hdr);
1189 
1190                 if (pack_hdr->magic != WIFI_RING_BUFFER_PACK_MAGIC) {
1191                     ALOGE("SetLogHandler: magic code is not matched "
1192                         "magic:%u ring_name:%s\n", pack_hdr->magic, status.name);
1193                     return NL_SKIP;
1194                 }
1195 
1196                 num_entries = pack_hdr->num_entries;
1197 
1198                 while (num_entries > 0) {
1199                     /* Check for accesses that exceed the total buffer size */
1200                     if (cur_off + sizeof(*entry_hdr) + entry_hdr->entry_size > buffer_size) {
1201                         ALOGE("SetLogHandler: detected invalid access "
1202                             "num_entries:%d cur_num:%d buffer_size:%d cur_off:%d "
1203                             "hdrsize:%lu entry_size:%d ring_name:%s\n",
1204                             pack_hdr->num_entries, num_entries, buffer_size, cur_off,
1205                             sizeof(*entry_hdr), entry_hdr->entry_size, status.name);
1206                         return NL_SKIP;
1207                     }
1208 
1209                     /* Copy buffer without hdr to the ringbuffer in LegacyHAL */
1210                     pBuff = (char *)entry_hdr + sizeof(*entry_hdr);
1211                     (*mHandler.on_ring_buffer_data)((char *)status.name, pBuff,
1212                         entry_hdr->entry_size, &status);
1213 
1214                     cur_off += sizeof(*entry_hdr) + entry_hdr->entry_size;
1215 
1216                     /* jump to next entry_hdr */
1217                     entry_hdr = (wifi_ring_buffer_entry *)((char *)entry_hdr + sizeof(*entry_hdr) + entry_hdr->entry_size);
1218 
1219                     num_entries--;
1220                 }
1221 
1222             }
1223         } else {
1224             ALOGE("Unknown Event");
1225             return NL_SKIP;
1226         }
1227         return NL_OK;
1228     }
1229 };
1230 
wifi_set_log_handler(wifi_request_id id,wifi_interface_handle iface,wifi_ring_buffer_data_handler handler)1231 wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
1232         wifi_ring_buffer_data_handler handler)
1233 {
1234     wifi_handle handle = getWifiHandle(iface);
1235     ALOGE("Loghandler start, handle = %p", handle);
1236 
1237     SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
1238     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1239     wifi_error result = wifi_register_cmd(handle, id, cmd);
1240     if (result != WIFI_SUCCESS) {
1241         cmd->releaseRef();
1242         return result;
1243     }
1244     result = (wifi_error)cmd->start();
1245     if (result != WIFI_SUCCESS) {
1246         wifi_unregister_cmd(handle, id);
1247         cmd->releaseRef();
1248         return result;
1249     }
1250 
1251 #ifdef RING_DUMP
1252     wifi_start_ring_dump(iface, handler);
1253 #endif /* RING_DUMP */
1254     return result;
1255 }
1256 
wifi_reset_log_handler(wifi_request_id id,wifi_interface_handle iface)1257 wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
1258 {
1259     wifi_handle handle = getWifiHandle(iface);
1260     ALOGE("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
1261 
1262 #ifdef RING_DUMP
1263     wifi_stop_ring_dump(iface);
1264 #endif /* RING_DUMP */
1265 
1266     if (id == -1) {
1267         wifi_ring_buffer_data_handler handler;
1268         memset(&handler, 0, sizeof(handler));
1269 
1270         SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
1271         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1272         cmd->cancel();
1273         cmd->releaseRef();
1274 
1275         return WIFI_SUCCESS;
1276     }
1277 
1278     return wifi_get_cancel_cmd(id, iface);
1279 }
1280 
1281 ///////////////////////////////////////////////////////////////////////////////
1282 class SetAlertHandler : public WifiCommand
1283 {
1284     wifi_alert_handler mHandler;
1285     int mBuffSize;
1286     char *mBuff;
1287     int mErrCode;
1288 
1289 public:
SetAlertHandler(wifi_interface_handle iface,int id,wifi_alert_handler handler)1290     SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)
1291         : WifiCommand("SetAlertHandler", iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),
1292             mErrCode(0)
1293     { }
1294 
start()1295     int start() {
1296         ALOGV("Start Alerting");
1297         registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
1298         return WIFI_SUCCESS;
1299     }
1300 
cancel()1301     virtual int cancel() {
1302         ALOGV("Clear alerthandler");
1303 
1304         /* unregister alert handler */
1305         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
1306         wifi_unregister_cmd(wifiHandle(), id());
1307         ALOGD("Success to clear alerthandler");
1308         return WIFI_SUCCESS;
1309     }
1310 
handleResponse(WifiEvent & reply)1311     virtual int handleResponse(WifiEvent& reply) {
1312         ALOGD("In SetAlertHandler::handleResponse");
1313 
1314         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1315             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1316             return NL_SKIP;
1317         }
1318 
1319         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1320         int len = reply.get_vendor_data_len();
1321 
1322         ALOGD("len = %d", len);
1323         if (vendor_data == NULL || len == 0) {
1324             ALOGE("no vendor data in memory dump response; ignoring it");
1325             return NL_SKIP;
1326         }
1327 
1328         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1329             if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
1330                 ALOGI("Initiating alert callback");
1331                 if (mHandler.on_alert) {
1332                     (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
1333                 }
1334                 if (mBuff) {
1335                     free(mBuff);
1336                     mBuff = NULL;
1337                 }
1338             }
1339         }
1340         return NL_OK;
1341     }
1342 
handleEvent(WifiEvent & event)1343     virtual int handleEvent(WifiEvent& event) {
1344         char *buffer = NULL;
1345         int buffer_size = 0;
1346         bool is_err_alert = false;
1347 
1348         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1349         int len = event.get_vendor_data_len();
1350         int event_id = event.get_vendor_subcmd();
1351         ALOGI("Got event: %d", event_id);
1352 
1353         if (vendor_data == NULL || len == 0) {
1354             ALOGE("No Debug data found");
1355             return NL_SKIP;
1356         }
1357 
1358         if (event_id == GOOGLE_DEBUG_MEM_DUMP_EVENT) {
1359             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1360                 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
1361                     mBuffSize = it.get_u32();
1362                 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
1363                     buffer_size = it.get_len();
1364                     buffer = (char *)it.get_data();
1365                 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_ERR_CODE) {
1366                     /* Error code is for error alert event only */
1367                     mErrCode = it.get_u32();
1368                     is_err_alert = true;
1369                 } else {
1370                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
1371                             it.get_type(), it.get_len());
1372                 }
1373             }
1374 
1375             if (is_err_alert) {
1376                 mBuffSize = sizeof(mErrCode);
1377                 if (mBuff) free(mBuff);
1378                 mBuff = (char *)malloc(mBuffSize);
1379                 if (!mBuff) {
1380                   ALOGE("Buffer allocation failed");
1381                   return NL_SKIP;
1382                 }
1383                 memcpy(mBuff, (char *)&mErrCode, mBuffSize);
1384                 ALOGI("Initiating alert callback");
1385                 if (mHandler.on_alert) {
1386                   (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
1387                 }
1388                 if (mBuff) {
1389                   free(mBuff);
1390                   mBuff = NULL;
1391                 }
1392                 mBuffSize = 0;
1393                 return NL_OK;
1394             }
1395 
1396             if (mBuffSize) {
1397                 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
1398                 if (mBuff) free(mBuff);
1399                 mBuff = (char *)malloc(mBuffSize + buffer_size);
1400                 if (!mBuff) {
1401                     ALOGE("Buffer allocation failed");
1402                     return NL_SKIP;
1403                 }
1404                 memcpy(mBuff, buffer, buffer_size);
1405 
1406                 WifiRequest request(familyId(), ifaceId());
1407                 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
1408                 if (result != WIFI_SUCCESS) {
1409                     ALOGE("Failed to create get memory dump request; result = %d", result);
1410                     free(mBuff);
1411                     return NL_SKIP;
1412                 }
1413                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1414                 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
1415                 if (result != WIFI_SUCCESS) {
1416                     ALOGE("Failed to put get memory dump request; result = %d", result);
1417                     return result;
1418                 }
1419 
1420                 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA,
1421                          (uint64_t)(mBuff+buffer_size));
1422                 if (result != WIFI_SUCCESS) {
1423                     ALOGE("Failed to put get memory dump request; result = %d", result);
1424                     return result;
1425                 }
1426 
1427                 request.attr_end(data);
1428                 mBuffSize += buffer_size;
1429 
1430                 result = requestResponse(request);
1431 
1432                 if (result != WIFI_SUCCESS) {
1433                     ALOGE("Failed to register get momory dump response; result = %d", result);
1434                 }
1435             } else {
1436                 ALOGE("dump event missing dump length attribute");
1437                 return NL_SKIP;
1438             }
1439         }
1440         return NL_OK;
1441     }
1442 };
1443 
1444 class SetRestartHandler : public WifiCommand
1445 {
1446     wifi_subsystem_restart_handler mHandler;
1447     char *mBuff;
1448 public:
SetRestartHandler(wifi_handle handle,wifi_request_id id,wifi_subsystem_restart_handler handler)1449     SetRestartHandler(wifi_handle handle, wifi_request_id id, wifi_subsystem_restart_handler handler)
1450         : WifiCommand("SetRestartHandler", handle, id), mHandler(handler), mBuff(NULL)
1451     { }
start()1452     int start() {
1453         ALOGI("Start Restart Handler handler");
1454         registerVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
1455         return WIFI_SUCCESS;
1456     }
cancel()1457     virtual int cancel() {
1458         ALOGI("Clear Restart Handler");
1459 
1460         /* unregister alert handler */
1461         unregisterVendorHandler(BRCM_OUI, BRCM_VENDOR_EVENT_HANGED);
1462         wifi_unregister_cmd(wifiHandle(), id());
1463         ALOGI("Success to clear restarthandler");
1464         return WIFI_SUCCESS;
1465     }
1466 
handleResponse(WifiEvent & reply)1467     virtual int handleResponse(WifiEvent& reply) {
1468         /* Nothing to do on response! */
1469         return NL_OK;
1470     }
1471 
handleEvent(WifiEvent & event)1472     virtual int handleEvent(WifiEvent& event) {
1473         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1474         int len = event.get_vendor_data_len();
1475         int event_id = event.get_vendor_subcmd();
1476         ALOGI("Got event: %d", event_id);
1477 
1478         if (vendor_data == NULL || len == 0) {
1479             ALOGE("No Debug data found");
1480             return NL_SKIP;
1481         }
1482         if (event_id == BRCM_VENDOR_EVENT_HANGED) {
1483             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1484                 if (it.get_type() == LOGGER_ATTRIBUTE_HANG_REASON) {
1485                     mBuff = (char *)it.get_data();
1486                 } else {
1487                     ALOGI("Ignoring invalid attribute type = %d, size = %d",
1488                             it.get_type(), it.get_len());
1489                 }
1490             }
1491 
1492             if (*mHandler.on_subsystem_restart) {
1493                 (*mHandler.on_subsystem_restart)(mBuff);
1494                 ALOGI("Hang event received. Trigger SSR handler:%p",
1495                     mHandler.on_subsystem_restart);
1496             } else {
1497                 ALOGI("No Restart handler registered");
1498             }
1499         }
1500         return NL_OK;
1501     }
1502 };
1503 
1504 ///////////////////////////////////////////////////////////////////////////////
1505 class SubSystemRestart : public WifiCommand
1506 {
1507     public:
SubSystemRestart(wifi_interface_handle iface)1508     SubSystemRestart(wifi_interface_handle iface)
1509         : WifiCommand("SubSystemRestart", iface, 0)
1510     { }
1511 
createRequest(WifiRequest & request)1512     int createRequest(WifiRequest& request) {
1513         int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_TRIGGER_SSR);
1514         if (result < 0) {
1515             return result;
1516         }
1517 
1518         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1519 
1520         request.attr_end(data);
1521         return WIFI_SUCCESS;
1522     }
1523 
create()1524     int create() {
1525         WifiRequest request(familyId(), ifaceId());
1526 
1527         int result = createRequest(request);
1528         if (result < 0) {
1529             ALOGE("Failed to create ssr request result = %d\n", result);
1530             return result;
1531         }
1532 
1533         result = requestResponse(request);
1534         if (result != WIFI_SUCCESS) {
1535             ALOGE("Failed to register ssr response; result = %d\n", result);
1536         }
1537         return result;
1538     }
1539 
1540     protected:
handleResponse(WifiEvent & reply)1541     int handleResponse(WifiEvent& reply) {
1542         /* Nothing to do on response! */
1543         return NL_OK;
1544     }
1545 
handleEvent(WifiEvent & event)1546     int handleEvent(WifiEvent& event) {
1547         /* NO events to handle here! */
1548         return NL_SKIP;
1549     }
1550 
1551 };
1552 ///////////////////////////////////////////////////////////////////////////////
1553 class HalInit : public WifiCommand
1554 {
1555     int mErrCode;
1556 
1557     public:
HalInit(wifi_interface_handle iface,int id)1558     HalInit(wifi_interface_handle iface, int id)
1559         : WifiCommand("HalInit", iface, id), mErrCode(0)
1560     { }
1561 
start()1562     int start() {
1563         ALOGE("Start Set Hal");
1564         WifiRequest request(familyId(), ifaceId());
1565 
1566         int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
1567         if (result != WIFI_SUCCESS) {
1568             ALOGE("Failed to set hal start; result = %d", result);
1569             return result;
1570         }
1571 
1572         result = requestResponse(request);
1573         if (result != WIFI_SUCCESS) {
1574             ALOGE("Failed to register set hal start response; result = %d", result);
1575         }
1576         return result;
1577     }
1578 
1579 
cancel()1580     virtual int cancel() {
1581         ALOGE("Cancel: Stop Hal");
1582         WifiRequest request(familyId(), ifaceId());
1583 
1584         int result = request.create(GOOGLE_OUI, LOGGER_HAL_STOP);
1585         if (result != WIFI_SUCCESS) {
1586             ALOGE("Failed to stop hal ; result = %d", result);
1587             return result;
1588         }
1589 
1590         result = requestResponse(request);
1591         if (result != WIFI_SUCCESS) {
1592             ALOGE("Failed to register set hal start response; result = %d", result);
1593         }
1594         wifi_unregister_cmd(wifiHandle(), id());
1595 	ALOGV("Stop HAL Successfully Completed, mErrCode = %d\n", mErrCode);
1596         return result;
1597     }
1598 
preInit()1599     int preInit() {
1600         ALOGE("Hal preInit");
1601         WifiRequest request(familyId(), ifaceId());
1602 
1603         int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
1604         if (result != WIFI_SUCCESS) {
1605             ALOGE("Failed to set Hal preInit; result = %d", result);
1606             return result;
1607         }
1608 
1609         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1610         result = request.put_string(SET_HAL_START_ATTRIBUTE_PRE_INIT, (char *)HAL_VERSION);
1611         if (result != WIFI_SUCCESS) {
1612             ALOGE("Hal preInit Failed to put data= %d", result);
1613             return result;
1614         }
1615         request.attr_end(data);
1616 
1617         result = requestResponse(request);
1618         if (result != WIFI_SUCCESS) {
1619             ALOGE("Failed to register set Hal preInit; result = %d", result);
1620         }
1621         return result;
1622     }
1623 
handleResponse(WifiEvent & reply)1624     virtual int handleResponse(WifiEvent& reply) {
1625         ALOGE("In SetHalStarted::handleResponse");
1626 
1627         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1628             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1629             return NL_SKIP;
1630         }
1631         return NL_OK;
1632     }
1633 
handleEvent(WifiEvent & event)1634     virtual int handleEvent(WifiEvent& event) {
1635         /* NO events! */
1636         return NL_SKIP;
1637     }
1638 };
1639 
1640 #ifdef RING_DUMP
1641 ///////////////////////////////////////////////////////////////////////////////
1642 class RingDump : public WifiCommand
1643 {
1644     int mLargestBuffSize;
1645     char *mBuff;
1646     int mErrCode;
1647     int mNumMaps;
1648     wifi_buf_ring_map_entry_t *mMap;
1649     int attr_type_len[DUMP_EVENT_ATTR_MAX];
1650     char *ring_name[DUMP_BUF_ATTR_MAX];
1651     wifi_ring_buffer_data_handler mHandle;
1652 
1653 public:
RingDump(wifi_interface_handle iface,int id,int num_maps,wifi_buf_ring_map_entry_t * map,wifi_ring_buffer_data_handler ring_handle)1654     RingDump(wifi_interface_handle iface, int id, int num_maps, wifi_buf_ring_map_entry_t *map,
1655         wifi_ring_buffer_data_handler ring_handle)
1656         : WifiCommand("RingDump", iface, id), mLargestBuffSize(0), mBuff(NULL),
1657         mErrCode(0), mNumMaps(num_maps), mMap(map), mHandle(ring_handle)
1658     {
1659         memset(attr_type_len, 0, sizeof(attr_type_len));
1660         for (int i = 0; i < DUMP_BUF_ATTR_MAX; i++) {
1661             ring_name[i] = NULL;
1662         }
1663     }
RingDump(wifi_interface_handle iface,int id)1664     RingDump(wifi_interface_handle iface, int id)
1665         : WifiCommand("RingDump", iface, id), mLargestBuffSize(0), mBuff(NULL),
1666         mErrCode(0)
1667     {
1668         memset(&mHandle, 0, sizeof(wifi_ring_buffer_data_handler));
1669     }
1670 
start()1671     int start() {
1672         DUMP_INFO(("Start Ring Dump Map_cnt:%d\n", mNumMaps));
1673         registerVendorHandler(GOOGLE_OUI, GOOGLE_FILE_DUMP_EVENT);
1674 
1675         //Set ringname to buf hashmap
1676         for (int i = 0; i < mNumMaps; i++) {
1677             int type = mMap[i].type;
1678             ring_name[type] = (char *)malloc(DBGRING_NAME_MAX);
1679             memset(ring_name[type], 0, DBGRING_NAME_MAX);
1680             memcpy(ring_name[type], mMap[i].ring_name, strlen(mMap[i].ring_name));
1681             DUMP_DEBUG(("Set ringname Buf:%s Ringname:%s len:%lu",
1682                 EWP_CmdAttrToString(type), ring_name[type], strlen(mMap[i].ring_name)));
1683         }
1684         return WIFI_SUCCESS;
1685     }
1686 
freeup()1687     virtual int freeup() {
1688         DUMP_DEBUG(("freeup:Enter\n"));
1689         if (mBuff) {
1690             free(mBuff);
1691             mBuff = NULL;
1692             DUMP_INFO(("freed allocated memory\n"));
1693         }
1694         return WIFI_SUCCESS;
1695     }
1696 
cancel()1697     virtual int cancel() {
1698         /* unregister file dump handler */
1699         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_FILE_DUMP_EVENT);
1700         wifi_unregister_cmd(wifiHandle(), id());
1701 
1702         /* Free up the ring names allocated */
1703         for (u8 i = 0; i < DUMP_BUF_ATTR_MAX; i++) {
1704             if (ring_name[i]) {
1705                 free(ring_name[i]);
1706                 ring_name[i] = NULL;
1707             }
1708         }
1709         memset(&mHandle, 0, sizeof(wifi_ring_buffer_data_handler));
1710 
1711         DUMP_INFO(("Stop Ring Dump Successfully Completed, mErrCode = %d\n", mErrCode));
1712         return WIFI_SUCCESS;
1713     }
1714 
handleResponse(WifiEvent & reply)1715     virtual int handleResponse(WifiEvent& reply) {
1716         DUMP_DEBUG(("RingDump::handleResponse\n"));
1717         int buf_attr = DUMP_BUF_ATTR_INVALID;
1718         int len_attr = DUMP_LEN_ATTR_INVALID;
1719         int index = -1;
1720 
1721         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1722             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1723             return NL_SKIP;
1724         }
1725 
1726         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1727         int len = reply.get_vendor_data_len();
1728 
1729         if (vendor_data == NULL || len == 0) {
1730             ALOGE("no vendor data in memory dump response; ignoring it");
1731             return NL_SKIP;
1732         }
1733 
1734         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1735             buf_attr = it.get_type();
1736             switch (buf_attr) {
1737                 case DUMP_BUF_ATTR_MEMDUMP:
1738                 case DUMP_BUF_ATTR_TIMESTAMP:
1739                 case DUMP_BUF_ATTR_ECNTRS:
1740                 case DUMP_BUF_ATTR_DHD_DUMP:
1741                 case DUMP_BUF_ATTR_EXT_TRAP:
1742                 case DUMP_BUF_ATTR_HEALTH_CHK:
1743                 case DUMP_BUF_ATTR_COOKIE:
1744                 case DUMP_BUF_ATTR_FLOWRING_DUMP:
1745                 case DUMP_BUF_ATTR_STATUS_LOG:
1746                 case DUMP_BUF_ATTR_RTT_LOG:
1747                 case DUMP_BUF_ATTR_PKTID_MAP_LOG:
1748                 case DUMP_BUF_ATTR_PKTID_UNMAP_LOG: {
1749                     if (it.get_u32()) {
1750                         ALOGE("Copying data to userspace failed, status = %d\n", it.get_u32());
1751                         return WIFI_ERROR_UNKNOWN;
1752                     }
1753                     index = logger_attr_buffer_lookup(buf_attr);
1754                     if (index == -1) {
1755                         ALOGE("Invalid index. buf attr = %s\n", EWP_CmdAttrToString(buf_attr));
1756                         return WIFI_ERROR_UNKNOWN;
1757                     }
1758                     len_attr = attr_lookup_tbl[index].attr_type;
1759                     if (len_attr == DUMP_EVENT_ATTR_MAX) {
1760                         ALOGE("Invalid len attr = %s\n", EWP_EventAttrToString(len_attr));
1761                         return WIFI_ERROR_UNKNOWN;
1762                     }
1763                     if (!mBuff || attr_type_len[len_attr] <= 0) {
1764                         return WIFI_ERROR_UNKNOWN;
1765                     }
1766 
1767                     if (!ring_name[buf_attr]) {
1768                         ALOGE("Not allocated buf attr = %s\n", EWP_CmdAttrToString(buf_attr));
1769                         return WIFI_ERROR_UNKNOWN;
1770                     }
1771                     DUMP_INFO(("RingDump:: buf_attr:%s size = %d ring_name:%s\n",
1772                         EWP_CmdAttrToString(buf_attr), attr_type_len[len_attr],
1773                         ring_name[buf_attr]));
1774                     if (mHandle.on_ring_buffer_data) {
1775                         /* on_ring_buffer_data callback requires status memory
1776                          * so should pass status memory */
1777                         wifi_ring_buffer_status status;
1778                         memset(&status, 0, sizeof(status));
1779                         /* Skip msg header. Retrieved log */
1780                         (*mHandle.on_ring_buffer_data)(ring_name[buf_attr], mBuff,
1781                             attr_type_len[len_attr], &status);
1782                     }
1783                     if (mBuff) {
1784                         memset(mBuff, 0, mLargestBuffSize);
1785                     }
1786                     break;
1787                 }
1788                 default: {
1789                     DUMP_DEBUG(("Ignoring invalid attribute buf_attr = %d, size = %d",
1790                         buf_attr, it.get_len()));
1791                     break;
1792                 }
1793             }
1794         }
1795         return NL_OK;
1796     }
1797 
request_logger_dump(WifiRequest & request,buf_data_t * buf,int len_attr)1798     virtual int request_logger_dump(WifiRequest& request,
1799             buf_data_t *buf, int len_attr) {
1800 
1801         int result = 0;
1802         int buf_attr = DUMP_BUF_ATTR_INVALID;
1803         int index = -1;
1804         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1805 
1806         index = logger_attr_lookup(len_attr);
1807         if (index == -1) {
1808             ALOGE("Invalid index\n");
1809             return WIFI_ERROR_UNKNOWN;
1810         }
1811         buf_attr = attr_lookup_tbl[index].buf_attr;
1812 
1813         if (buf_attr != DUMP_BUF_ATTR_INVALID) {
1814             result = request.put(buf_attr, buf, sizeof(buf_data_t));
1815             if (result != WIFI_SUCCESS) {
1816                 ALOGE("Failed to put get memory dump request; result = %d", result);
1817                 return result;
1818             }
1819         } else {
1820             ALOGE("Invalid buf attr = %s, index = %d\n",
1821                 EWP_CmdAttrToString(buf_attr), index);
1822             return WIFI_ERROR_UNKNOWN;
1823         }
1824         DUMP_INFO(("Trigger get dump for buf attr = %s\n",
1825                 EWP_CmdAttrToString(buf_attr)));
1826 
1827         request.attr_end(data);
1828         return result;
1829     }
1830 
handleEvent(WifiEvent & event)1831     virtual int handleEvent(WifiEvent& event) {
1832         mLargestBuffSize = 0;
1833         mBuff = NULL;
1834         memset(attr_type_len, 0, sizeof(attr_type_len));
1835         u8 i = 0;
1836         int result = 0;
1837         int mActualBuffSize = 0;
1838         int index = -1;
1839 
1840         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1841         int len = event.get_vendor_data_len();
1842         int event_id = event.get_vendor_subcmd();
1843         int req_attr_cnt = 0;
1844         int req_attr[DUMP_EVENT_ATTR_MAX];
1845         int buf_attr = DUMP_BUF_ATTR_INVALID;
1846 
1847         if (vendor_data == NULL || len == 0) {
1848             ALOGE("No Debug data found");
1849             return NL_SKIP;
1850         }
1851         DUMP_INFO(("Ring Dump handler. Got event: %d", event_id));
1852 
1853         buf_data_t buf;
1854 
1855         memset(&buf, 0, sizeof(buf_data_t));
1856         buf.ver = 0;
1857         buf.buf_threshold = 0;
1858 
1859         if (event_id == GOOGLE_FILE_DUMP_EVENT) {
1860             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1861                 int attr = it.get_type();
1862                 switch (attr) {
1863                     case DUMP_LEN_ATTR_MEMDUMP:
1864                     case DUMP_LEN_ATTR_TIMESTAMP:
1865                     case DUMP_LEN_ATTR_ECNTRS:
1866                     case DUMP_LEN_ATTR_DHD_DUMP:
1867                     case DUMP_LEN_ATTR_EXT_TRAP:
1868                     case DUMP_LEN_ATTR_HEALTH_CHK:
1869                     case DUMP_LEN_ATTR_COOKIE:
1870                     case DUMP_LEN_ATTR_FLOWRING_DUMP:
1871                     case DUMP_LEN_ATTR_STATUS_LOG:
1872                     case DUMP_LEN_ATTR_RTT_LOG:
1873                     case DUMP_LEN_ATTR_PKTID_MAP_LOG:
1874                     case DUMP_LEN_ATTR_PKTID_UNMAP_LOG: {
1875                         mActualBuffSize = it.get_u32();
1876                         DUMP_DEBUG(("len attr %s, len %d\n",
1877                             EWP_EventAttrToString(attr), mActualBuffSize));
1878                         if (mActualBuffSize > mLargestBuffSize)
1879                             mLargestBuffSize = mActualBuffSize;
1880                             attr_type_len[attr] = mActualBuffSize;
1881 
1882                             /* Store the order in which attributes are received
1883                              * so that file dump can be done in the same order
1884                              */
1885                             req_attr[req_attr_cnt++] = attr;
1886                             break;
1887                     }
1888                     default: {
1889                         ALOGE("Ignoring invalid attribute type = %d, size = %d",
1890                             attr, it.get_len());
1891                             break;
1892                         }
1893                 }
1894             }
1895             /* Allocation for the largest buffer size to use it recursively for other buf attr. */
1896             if (mLargestBuffSize) {
1897                 DUMP_INFO(("Max dump size: %d", mLargestBuffSize));
1898                 mBuff = (char *)malloc(mLargestBuffSize);
1899                 if (!mBuff) {
1900                     ALOGE("Buffer allocation failed");
1901                     return NL_SKIP;
1902                 }
1903                 memset(mBuff, 0, mLargestBuffSize);
1904             }
1905 
1906             WifiRequest request(familyId(), ifaceId());
1907             result = request.create(GOOGLE_OUI, LOGGER_DEBUG_GET_DUMP);
1908             if (result != WIFI_SUCCESS) {
1909                 ALOGE("Failed to create get memory dump request; result = %d", result);
1910                 freeup();
1911                 goto exit;
1912             }
1913 
1914             /* Requesting logger dump for each received attr */
1915             for (i = 0; i < req_attr_cnt; i++) {
1916                 int attr = req_attr[i];
1917 
1918                 if (attr_type_len[attr] == 0) {
1919                     continue;
1920                 }
1921 
1922                 index = logger_attr_lookup(attr);
1923                 buf_attr = attr_lookup_tbl[index].buf_attr;
1924                 if (!ring_name[buf_attr]) {
1925                     ALOGE("Failed to find ringname index:%d buf_attr:%d", index, buf_attr);
1926                     continue;
1927                 }
1928 
1929                 buf.len = attr_type_len[attr];
1930                 buf.data_buf[0] = mBuff;
1931                 DUMP_DEBUG(("buf len = %d, buf ptr= %p for attr = %s\n",
1932                     buf.len, buf.data_buf[0], EWP_EventAttrToString(attr)));
1933                 result = request_logger_dump(request, &buf, attr);
1934                 if (result != WIFI_SUCCESS) {
1935                     /* Proceeding further for other attributes */
1936                     ALOGE("Failed to request the logger dump for attr = %s; result = %d",
1937                         EWP_EventAttrToString(attr), result);
1938                     continue;
1939                 }
1940                 result = requestResponse(request);
1941                 if (result != WIFI_SUCCESS) {
1942                     ALOGE("Failed to register get memory dump response for attr = %s; result = %d",
1943                         EWP_EventAttrToString(attr), result);
1944                         /* Proceeding further for other attributes */
1945                         continue;
1946                 }
1947             }
1948 
1949             WifiRequest request2(familyId(), ifaceId());
1950             result = request2.create(GOOGLE_OUI, LOGGER_FILE_DUMP_DONE_IND);
1951             if (result != WIFI_SUCCESS) {
1952                 ALOGE("Failed to trigger dev close; result = %d", result);
1953                 freeup();
1954                 goto exit;
1955             }
1956             requestResponse(request2);
1957             freeup();
1958         } else {
1959             ALOGE("dump event missing dump length attribute");
1960             return NL_SKIP;
1961         }
1962     exit:
1963         if (result != WIFI_SUCCESS) {
1964             return NL_SKIP;
1965         }
1966         return NL_OK;
1967     }
1968 };
1969 ///////////////////////////////////////////////////////////////////////////////
1970 #endif /* RING_DUMP */
1971 
wifi_start_hal(wifi_interface_handle iface)1972 wifi_error wifi_start_hal(wifi_interface_handle iface)
1973 {
1974     wifi_handle handle = getWifiHandle(iface);
1975     ALOGV("HAL INIT start, handle = %p", handle);
1976 
1977     HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
1978     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1979     wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
1980     if (result != WIFI_SUCCESS) {
1981         cmd->releaseRef();
1982         return result;
1983     }
1984     result = (wifi_error)cmd->start();
1985     if (result != WIFI_SUCCESS) {
1986         wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
1987         cmd->releaseRef();
1988         return result;
1989     }
1990     return result;
1991 }
1992 
wifi_hal_preInit(wifi_interface_handle iface)1993 wifi_error wifi_hal_preInit(wifi_interface_handle iface)
1994 {
1995     wifi_handle handle = getWifiHandle(iface);
1996     ALOGV("wifi_hal_preInit, handle = %p", handle);
1997 
1998     HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
1999     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2000     wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
2001     if (result != WIFI_SUCCESS) {
2002         cmd->releaseRef();
2003         return result;
2004     }
2005     result = (wifi_error)cmd->preInit();
2006     if (result != WIFI_SUCCESS) {
2007         wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
2008         cmd->releaseRef();
2009         return result;
2010     }
2011     return result;
2012 }
2013 
2014 #ifdef RING_DUMP
wifi_start_ring_dump(wifi_interface_handle iface,wifi_ring_buffer_data_handler ring_handle)2015 wifi_error wifi_start_ring_dump(wifi_interface_handle iface,
2016     wifi_ring_buffer_data_handler ring_handle)
2017 {
2018     wifi_handle handle = getWifiHandle(iface);
2019     DUMP_INFO(("start ring dump, handle = %p", handle));
2020     wifi_buf_ring_map_entry_t map[DUMP_BUF_ATTR_MAX];
2021     unsigned int num_maps = DUMP_BUF_ATTR_MAX;
2022     wifi_error result;
2023 
2024     /* Get mapping table from driver */
2025     DebugCommand *debug_cmd = new DebugCommand(iface, &num_maps, map, GET_BUF_RING_MAP);
2026     NULL_CHECK_RETURN(debug_cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2027     result = (wifi_error)debug_cmd->start();
2028     debug_cmd->releaseRef();
2029 
2030     /* Set ringname to corresponding buf attr */
2031     RingDump *cmd = new RingDump(iface, FILE_DUMP_REQUEST_ID, num_maps, map, ring_handle);
2032     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2033     result = wifi_register_cmd(handle, FILE_DUMP_REQUEST_ID, cmd);
2034     if (result != WIFI_SUCCESS) {
2035         cmd->releaseRef();
2036         return result;
2037     }
2038 
2039     result = (wifi_error)cmd->start();
2040     if (result != WIFI_SUCCESS) {
2041         wifi_unregister_cmd(handle, FILE_DUMP_REQUEST_ID);
2042         cmd->releaseRef();
2043         return result;
2044     }
2045     return result;
2046 }
2047 
wifi_stop_ring_dump(wifi_interface_handle iface)2048 wifi_error wifi_stop_ring_dump(wifi_interface_handle iface)
2049 {
2050     RingDump *cmd = new RingDump(iface, FILE_DUMP_REQUEST_ID);
2051     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2052     DUMP_INFO(("stop ring dump"));
2053     cmd->cancel();
2054     cmd->releaseRef();
2055     return WIFI_SUCCESS;
2056 }
2057 #endif /* RING_DUMP */
2058 
wifi_stop_hal(wifi_interface_handle iface)2059 wifi_error wifi_stop_hal(wifi_interface_handle iface)
2060 {
2061     HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
2062     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2063     cmd->cancel();
2064     cmd->releaseRef();
2065     return WIFI_SUCCESS;
2066 }
2067 
2068 
wifi_set_subsystem_restart_handler(wifi_handle handle,wifi_subsystem_restart_handler handler)2069 wifi_error wifi_set_subsystem_restart_handler(wifi_handle handle,
2070                                               wifi_subsystem_restart_handler handler)
2071 {
2072     hal_info *info = NULL;
2073 
2074     info = (hal_info *)handle;
2075     if (info == NULL) {
2076         ALOGE("Could not find hal info\n");
2077         return WIFI_ERROR_UNKNOWN;
2078     }
2079 
2080     SetRestartHandler *cmd = new SetRestartHandler(handle, HAL_RESTART_ID, handler);
2081     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2082     wifi_error result = wifi_register_cmd(handle, HAL_RESTART_ID, cmd);
2083     if (result != WIFI_SUCCESS) {
2084         cmd->releaseRef();
2085         return result;
2086     }
2087 
2088     result = (wifi_error)cmd->start();
2089     if (result != WIFI_SUCCESS) {
2090         wifi_unregister_cmd(handle, HAL_RESTART_ID);
2091         cmd->releaseRef();
2092         return result;
2093     }
2094 
2095     /* Cache the handler to use it for trigger subsystem restart */
2096     ALOGI("Register SSR handler:%p", handler);
2097     info->restart_handler = handler;
2098     return result;
2099 }
2100 
wifi_trigger_subsystem_restart(wifi_handle handle)2101 wifi_error wifi_trigger_subsystem_restart(wifi_handle handle)
2102 {
2103     wifi_error result = WIFI_SUCCESS;
2104     hal_info *info = NULL;
2105     char error_str[20];
2106     SubSystemRestart *cmd = NULL;
2107     wifi_interface_handle *ifaceHandles = NULL;
2108     wifi_interface_handle wlan0Handle;
2109     int numIfaceHandles = 0;
2110 
2111     info = (hal_info *)handle;
2112     if (handle == NULL || info == NULL) {
2113         ALOGE("Could not find hal info\n");
2114         result = WIFI_ERROR_UNKNOWN;
2115         goto exit;
2116     }
2117 
2118     ALOGI("Trigger subsystem restart\n");
2119 
2120     wlan0Handle = wifi_get_wlan_interface((wifi_handle)handle, ifaceHandles, numIfaceHandles);
2121 
2122     cmd = new SubSystemRestart(wlan0Handle);
2123     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2124 
2125     result = (wifi_error)cmd->create();
2126     if (result != WIFI_SUCCESS) {
2127         cmd->releaseRef();
2128         strncpy(error_str, "WIFI_ERROR_UNKNOWN", sizeof(error_str));
2129         ALOGE("Failed to create SSR");
2130         goto exit;
2131     }
2132 
2133     strncpy(error_str, "WIFI_SUCCESS", sizeof(error_str));
2134 
2135 exit:
2136     if (info->restart_handler.on_subsystem_restart) {
2137         ALOGI("Trigger ssr handler registered handler:%p",
2138             info->restart_handler.on_subsystem_restart);
2139         (info->restart_handler.on_subsystem_restart)(error_str);
2140     } else {
2141         ALOGI("No trigger ssr handler registered");
2142     }
2143 
2144     return result;
2145 }
2146 
wifi_set_alert_handler(wifi_request_id id,wifi_interface_handle iface,wifi_alert_handler handler)2147 wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
2148         wifi_alert_handler handler)
2149 {
2150     wifi_handle handle = getWifiHandle(iface);
2151     ALOGV("Alerthandler start, handle = %p", handle);
2152 
2153     SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
2154     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2155     wifi_error result = wifi_register_cmd(handle, id, cmd);
2156     if (result != WIFI_SUCCESS) {
2157         cmd->releaseRef();
2158         return result;
2159     }
2160     result = (wifi_error)cmd->start();
2161     if (result != WIFI_SUCCESS) {
2162         wifi_unregister_cmd(handle, id);
2163         cmd->releaseRef();
2164         return result;
2165     }
2166     return result;
2167 }
2168 
wifi_reset_alert_handler(wifi_request_id id,wifi_interface_handle iface)2169 wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)
2170 {
2171     wifi_handle handle = getWifiHandle(iface);
2172     ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);
2173 
2174     if (id == -1) {
2175         wifi_alert_handler handler;
2176         memset(&handler, 0, sizeof(handler));
2177 
2178         SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
2179         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2180         cmd->cancel();
2181         cmd->releaseRef();
2182         return WIFI_SUCCESS;
2183     }
2184 
2185     return wifi_get_cancel_cmd(id, iface);
2186 }
2187 
2188 ///////////////////////////////////////////////////////////////////////////////
2189 class MemoryDumpCommand: public WifiCommand
2190 {
2191     wifi_firmware_memory_dump_handler mHandler;
2192     int mBuffSize;
2193     char *mBuff;
2194 
2195 public:
MemoryDumpCommand(wifi_interface_handle iface,wifi_firmware_memory_dump_handler handler)2196     MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler)
2197         : WifiCommand("MemoryDumpCommand", iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL)
2198     { }
2199 
start()2200     int start() {
2201         ALOGD("Start memory dump command");
2202         WifiRequest request(familyId(), ifaceId());
2203 
2204         int result = request.create(GOOGLE_OUI, LOGGER_TRIGGER_MEM_DUMP);
2205         if (result != WIFI_SUCCESS) {
2206             ALOGE("Failed to create trigger fw memory dump request; result = %d", result);
2207             return result;
2208         }
2209 
2210         result = requestResponse(request);
2211         if (result != WIFI_SUCCESS) {
2212             ALOGE("Failed to register trigger memory dump response; result = %d", result);
2213         }
2214         return result;
2215     }
2216 
handleResponse(WifiEvent & reply)2217     virtual int handleResponse(WifiEvent& reply) {
2218         ALOGD("In MemoryDumpCommand::handleResponse");
2219 
2220         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
2221             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
2222             return NL_SKIP;
2223         }
2224 
2225         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
2226         int len = reply.get_vendor_data_len();
2227 
2228         ALOGD("len = %d", len);
2229         if (vendor_data == NULL || len == 0) {
2230             ALOGE("no vendor data in memory dump response; ignoring it");
2231             return NL_SKIP;
2232         }
2233 
2234         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
2235             if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
2236                 mBuffSize = it.get_u32();
2237 
2238                 if (mBuff)
2239                     free(mBuff);
2240                 mBuff = (char *)malloc(mBuffSize);
2241                 if (!mBuff) {
2242                     ALOGE("Buffer allocation failed");
2243                     return NL_SKIP;
2244                 }
2245                 WifiRequest request(familyId(), ifaceId());
2246                 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
2247                 if (result != WIFI_SUCCESS) {
2248                     ALOGE("Failed to create get memory dump request; result = %d", result);
2249                     free(mBuff);
2250                     return NL_SKIP;
2251                 }
2252 
2253                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
2254                 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
2255                 if (result != WIFI_SUCCESS) {
2256                     ALOGE("Failed to put get memory dump request; result = %d", result);
2257                     return result;
2258                 }
2259 
2260                 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);
2261                 if (result != WIFI_SUCCESS) {
2262                     ALOGE("Failed to put get memory dump request; result = %d", result);
2263                     return result;
2264                 }
2265                 request.attr_end(data);
2266 
2267                 result = requestResponse(request);
2268                 if (result != WIFI_SUCCESS) {
2269                     ALOGE("Failed to register get momory dump response; result = %d", result);
2270                 }
2271             } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
2272                 ALOGI("Initiating memory dump callback");
2273                 if (mHandler.on_firmware_memory_dump) {
2274                     (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);
2275                 }
2276                 if (mBuff) {
2277                     free(mBuff);
2278                     mBuff = NULL;
2279                 }
2280             } else {
2281                 ALOGW("Ignoring invalid attribute type = %d, size = %d",
2282                         it.get_type(), it.get_len());
2283             }
2284         }
2285         return NL_OK;
2286     }
2287 
handleEvent(WifiEvent & event)2288     virtual int handleEvent(WifiEvent& event) {
2289         /* NO events! */
2290         return NL_SKIP;
2291     }
2292 };
2293 
2294 /* 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)2295 wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
2296         wifi_firmware_memory_dump_handler handler)
2297 {
2298     MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler);
2299     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2300     wifi_error result = (wifi_error)cmd->start();
2301     cmd->releaseRef();
2302     return result;
2303 }
2304 
2305 class PacketFateCommand: public WifiCommand
2306 {
2307     void *mReportBufs;
2308     size_t mNoReqFates;
2309     size_t *mNoProvidedFates;
2310     PktFateReqType mReqType;
2311 
2312 public:
PacketFateCommand(wifi_interface_handle handle)2313     PacketFateCommand(wifi_interface_handle handle)
2314         : WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START)
2315     {
2316         mReportBufs = NULL;
2317         mNoReqFates = 0;
2318         mNoProvidedFates = NULL;
2319     }
2320 
PacketFateCommand(wifi_interface_handle handle,wifi_tx_report * tx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)2321     PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
2322             size_t n_requested_fates, size_t *n_provided_fates)
2323         : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(tx_report_bufs),
2324                   mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
2325                   mReqType(TX_PACKET_FATE)
2326     { }
2327 
PacketFateCommand(wifi_interface_handle handle,wifi_rx_report * rx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)2328     PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,
2329             size_t n_requested_fates, size_t *n_provided_fates)
2330         : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(rx_report_bufs),
2331                   mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
2332                   mReqType(RX_PACKET_FATE)
2333     { }
2334 
createRequest(WifiRequest & request)2335     int createRequest(WifiRequest& request) {
2336         if (mReqType == TX_PACKET_FATE) {
2337             ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);
2338             return createTxPktFateRequest(request);
2339         } else if (mReqType == RX_PACKET_FATE) {
2340             ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);
2341             return createRxPktFateRequest(request);
2342         } else if (mReqType == PACKET_MONITOR_START) {
2343             ALOGD("%s Monitor packet fate request\n", __FUNCTION__);
2344             return createMonitorPktFateRequest(request);
2345         } else {
2346             ALOGE("%s Unknown packet fate request\n", __FUNCTION__);
2347             return WIFI_ERROR_NOT_SUPPORTED;
2348         }
2349         return WIFI_SUCCESS;
2350     }
2351 
createMonitorPktFateRequest(WifiRequest & request)2352     int createMonitorPktFateRequest(WifiRequest& request) {
2353         int result = request.create(GOOGLE_OUI, LOGGER_START_PKT_FATE_MONITORING);
2354         if (result < 0) {
2355             ALOGE("Failed to create monitorPktFate result:%d\n", result);
2356             return result;
2357         }
2358 
2359         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
2360         request.attr_end(data);
2361         return result;
2362     }
2363 
createTxPktFateRequest(WifiRequest & request)2364     int createTxPktFateRequest(WifiRequest& request) {
2365         int result = request.create(GOOGLE_OUI, LOGGER_GET_TX_PKT_FATES);
2366         if (result < 0) {
2367             ALOGE("Failed to create TxPktFate result:%d\n", result);
2368             return result;
2369         }
2370 
2371         memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));
2372         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
2373         result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
2374         if (result < 0) {
2375             ALOGE("Failed to set TxPktFate num result:%d mNoReqFates:%d\n", result, mNoReqFates);
2376             return result;
2377         }
2378         result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
2379         if (result < 0) {
2380             ALOGE("Failed to set TxPktFate buf result:%d\n", result);
2381             return result;
2382         }
2383         request.attr_end(data);
2384         return result;
2385     }
2386 
createRxPktFateRequest(WifiRequest & request)2387     int createRxPktFateRequest(WifiRequest& request) {
2388         int result = request.create(GOOGLE_OUI, LOGGER_GET_RX_PKT_FATES);
2389         if (result < 0) {
2390             ALOGE("Failed to create RxPktFate result:%d\n", result);
2391             return result;
2392         }
2393 
2394         memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));
2395         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
2396         result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
2397         if (result < 0) {
2398             ALOGE("Failed to set RxPktFate num result:%d mNoReqFates:%d\n", result, mNoReqFates);
2399             return result;
2400         }
2401         result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
2402         if (result < 0) {
2403             ALOGE("Failed to set RxPktFate buf result:%d\n", result);
2404             return result;
2405         }
2406         request.attr_end(data);
2407         return result;
2408     }
2409 
start()2410     int start() {
2411         ALOGD("Start get packet fate command\n");
2412         WifiRequest request(familyId(), ifaceId());
2413 
2414         int result = createRequest(request);
2415         if (result < 0) {
2416             ALOGE("Failed to create get pkt fate request; result = %d\n", result);
2417             return result;
2418         }
2419 
2420         result = requestResponse(request);
2421         if (result != WIFI_SUCCESS) {
2422             ALOGE("Failed to register get pkt fate response; result = %d\n", result);
2423         }
2424         return result;
2425     }
2426 
handleResponse(WifiEvent & reply)2427     int handleResponse(WifiEvent& reply) {
2428         ALOGD("In GetPktFateCommand::handleResponse\n");
2429 
2430         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
2431             ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
2432             return NL_SKIP;
2433         }
2434 
2435         int id = reply.get_vendor_id();
2436         int subcmd = reply.get_vendor_subcmd();
2437         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
2438         int len = reply.get_vendor_data_len();
2439 
2440         ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
2441 
2442         if (mReqType == TX_PACKET_FATE) {
2443             ALOGI("Response recieved for get TX pkt fate command\n");
2444         } else if (mReqType == RX_PACKET_FATE) {
2445             ALOGI("Response recieved for get RX pkt fate command\n");
2446         } else if (mReqType == PACKET_MONITOR_START) {
2447             ALOGI("Response recieved for monitor pkt fate command\n");
2448             return NL_OK;
2449         } else {
2450             ALOGE("Response recieved for unknown pkt fate command\n");
2451             return NL_SKIP;
2452         }
2453 
2454         if (vendor_data == NULL || len == 0) {
2455             ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
2456             return NL_SKIP;
2457         }
2458 
2459         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
2460             if (it.get_type() == LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
2461                 *mNoProvidedFates = it.get_u32();
2462                 ALOGI("No: of pkt fates provided is %zu\n", *mNoProvidedFates);
2463             } else {
2464                 ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
2465                         it.get_type(), it.get_len());
2466             }
2467         }
2468 
2469         return NL_OK;
2470     }
2471 
handleEvent(WifiEvent & event)2472     int handleEvent(WifiEvent& event) {
2473         /* NO events to handle here! */
2474         return NL_SKIP;
2475     }
2476 };
2477 
2478 class GetWakeReasonCountCommand : public WifiCommand {
2479     WLAN_DRIVER_WAKE_REASON_CNT *mWakeReasonCnt;
2480     void *mCmdEventWakeCount;
2481     public:
GetWakeReasonCountCommand(wifi_interface_handle handle,WLAN_DRIVER_WAKE_REASON_CNT * wlanDriverWakeReasonCount)2482     GetWakeReasonCountCommand(wifi_interface_handle handle,
2483         WLAN_DRIVER_WAKE_REASON_CNT *wlanDriverWakeReasonCount) :
2484         WifiCommand("GetWakeReasonCountCommand", handle, 0),
2485         mWakeReasonCnt(wlanDriverWakeReasonCount)
2486     {
2487         mCmdEventWakeCount = mWakeReasonCnt->cmd_event_wake_cnt;
2488     }
2489 
createRequest(WifiRequest & request)2490     int createRequest(WifiRequest& request) {
2491         int result = request.create(GOOGLE_OUI, LOGGER_GET_WAKE_REASON_STATS);
2492         if (result < 0) {
2493             return result;
2494         }
2495 
2496         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
2497 
2498         request.attr_end(data);
2499         return WIFI_SUCCESS;
2500     }
2501 
start()2502     int start() {
2503         ALOGD("Start get wake stats command\n");
2504         WifiRequest request(familyId(), ifaceId());
2505 
2506         int result = createRequest(request);
2507         if (result < 0) {
2508             ALOGE("Failed to create request result = %d\n", result);
2509             return result;
2510         }
2511 
2512         result = requestResponse(request);
2513         if (result != WIFI_SUCCESS) {
2514             ALOGE("Failed to register wake stats  response; result = %d\n", result);
2515         }
2516         return result;
2517     }
2518 
2519     protected:
handleResponse(WifiEvent & reply)2520     int handleResponse(WifiEvent& reply) {
2521         ALOGE("In GetWakeReasonCountCommand::handleResponse");
2522 
2523         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
2524             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
2525             return NL_SKIP;
2526         }
2527 
2528         int id = reply.get_vendor_id();
2529         int subcmd = reply.get_vendor_subcmd();
2530 
2531         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
2532         int len = reply.get_vendor_data_len();
2533 
2534         ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
2535         if (vendor_data == NULL || len == 0) {
2536             ALOGE("no vendor data in GetGetWakeReasonCountCommand response; ignoring it");
2537             return NL_SKIP;
2538         }
2539 
2540         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
2541             switch (it.get_type()) {
2542                 case WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW:
2543                     mWakeReasonCnt->total_driver_fw_local_wake =
2544                         it.get_u32();
2545                     break;
2546                 case WAKE_STAT_ATTRIBUTE_TOTAL:
2547                     mWakeReasonCnt->total_cmd_event_wake =
2548                         it.get_u32();
2549                     break;
2550                 case WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED:
2551                     mWakeReasonCnt->cmd_event_wake_cnt_used =
2552                         it.get_u32();
2553                     break;
2554                 case WAKE_STAT_ATTRIBUTE_WAKE:
2555                     memcpy(mCmdEventWakeCount, it.get_data(),
2556                             (mWakeReasonCnt->cmd_event_wake_cnt_used * sizeof(int)));
2557                     break;
2558                 case WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE:
2559                     mWakeReasonCnt->total_rx_data_wake =
2560                         it.get_u32();
2561                     break;
2562                 case WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT:
2563                     mWakeReasonCnt->rx_wake_details.rx_unicast_cnt =
2564                         it.get_u32();
2565                     break;
2566                 case WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT:
2567                     mWakeReasonCnt->rx_wake_details.rx_multicast_cnt =
2568                         it.get_u32();
2569                     break;
2570                 case WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT:
2571                     mWakeReasonCnt->rx_wake_details.rx_broadcast_cnt =
2572                         it.get_u32();
2573                     break;
2574                 case WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT:
2575                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp_pkt =
2576                         it.get_u32();
2577                     break;
2578                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT:
2579                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_pkt =
2580                         it.get_u32();
2581                     break;
2582                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA:
2583                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ra =
2584                         it.get_u32();
2585                     break;
2586                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA:
2587                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_na =
2588                         it.get_u32();
2589                     break;
2590                 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS:
2591                     mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ns =
2592                         it.get_u32();
2593                     break;
2594                 case WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT:
2595                     mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt =
2596                         it.get_u32();
2597                     break;
2598                 case WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT:
2599                     mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
2600                         it.get_u32();
2601                     break;
2602                 case WAKE_STAT_ATTRIBUTE_OTHER_RX_MULTICAST_ADD_CNT:
2603                     mWakeReasonCnt->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
2604                         it.get_u32();
2605                     break;
2606                 default:
2607                     break;
2608             }
2609 
2610         }
2611         return NL_OK;
2612     }
2613 };
2614 
wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)2615 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
2616 {
2617     PacketFateCommand *cmd = new PacketFateCommand(handle);
2618     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2619     wifi_error result = (wifi_error)cmd->start();
2620     cmd->releaseRef();
2621     return result;
2622 }
2623 
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)2624 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
2625         wifi_tx_report *tx_report_bufs, size_t n_requested_fates,
2626         size_t *n_provided_fates)
2627 {
2628     PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,
2629                 n_requested_fates, n_provided_fates);
2630     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2631     wifi_error result = (wifi_error)cmd->start();
2632     cmd->releaseRef();
2633     return result;
2634 }
2635 
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)2636 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
2637         wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
2638         size_t *n_provided_fates)
2639 {
2640     PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
2641                 n_requested_fates, n_provided_fates);
2642     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2643     wifi_error result = (wifi_error)cmd->start();
2644     cmd->releaseRef();
2645     return result;
2646 }
2647 
wifi_get_wake_reason_stats(wifi_interface_handle handle,WLAN_DRIVER_WAKE_REASON_CNT * wifi_wake_reason_cnt)2648 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
2649         WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
2650 {
2651     GetWakeReasonCountCommand *cmd =
2652         new GetWakeReasonCountCommand(handle, wifi_wake_reason_cnt);
2653     wifi_error result = (wifi_error)cmd->start();
2654     cmd->releaseRef();
2655     return result;
2656 }
2657 
2658 ///////////////////////////////////////////////////////////////////////////////
2659 class OtaUpdateCommand : public WifiCommand
2660 {
2661 
2662     public:
OtaUpdateCommand(wifi_interface_handle iface)2663     OtaUpdateCommand(wifi_interface_handle iface)
2664         : WifiCommand("OtaUpdateCommand", iface, 0)
2665     { }
2666 
start()2667     int start() {
2668         ALOGE("Start OtaUpdateCommand");
2669         WifiRequest request(familyId(), ifaceId());
2670 
2671         int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_GET_OTA_CURRUNT_INFO);
2672         if (result != WIFI_SUCCESS) {
2673             ALOGE("Failed to set hal start; result = %d", result);
2674             return result;
2675         }
2676 
2677         result = requestResponse(request);
2678         if (result != WIFI_SUCCESS) {
2679             ALOGE("Failed to register set hal start response; result = %d", result);
2680         }
2681         return result;
2682     }
2683 
otaDownload(ota_info_buf_t * buf,uint32_t ota_version)2684     int otaDownload(ota_info_buf_t* buf, uint32_t ota_version) {
2685         u32 force_reg_on = false;
2686         WifiRequest request(familyId(), ifaceId());
2687         int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_OTA_UPDATE);
2688 
2689         ALOGE("Download the OTA configuration");
2690         if (result != WIFI_SUCCESS) {
2691             ALOGE("Failed to set Hal preInit; result = %d", result);
2692             return result;
2693         }
2694 
2695         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
2696 
2697         result = request.put_u32(OTA_DOWNLOAD_CLM_LENGTH_ATTR, buf->ota_clm_len);
2698         if (result != WIFI_SUCCESS) {
2699             ALOGE("otaDownload Failed to put data= %d", result);
2700             return result;
2701         }
2702 
2703         result = request.put(OTA_DOWNLOAD_CLM_ATTR, buf->ota_clm_buf, sizeof(*buf->ota_clm_buf));
2704         if (result != WIFI_SUCCESS) {
2705             ALOGE("otaDownload Failed to put data= %d", result);
2706             return result;
2707         }
2708 
2709         result = request.put_u32(OTA_DOWNLOAD_NVRAM_LENGTH_ATTR, buf->ota_nvram_len);
2710         if (result != WIFI_SUCCESS) {
2711             ALOGE("otaDownload Failed to put data= %d", result);
2712             return result;
2713         }
2714 
2715         result = request.put(OTA_DOWNLOAD_NVRAM_ATTR,
2716                 buf->ota_nvram_buf, sizeof(*buf->ota_nvram_buf));
2717         if (result != WIFI_SUCCESS) {
2718             ALOGE("otaDownload Failed to put data= %d", result);
2719             return result;
2720         }
2721 
2722         if (applied_ota_version != ota_version) {
2723             force_reg_on = true;
2724             applied_ota_version = ota_version;
2725         }
2726         result = request.put_u32(OTA_SET_FORCE_REG_ON, force_reg_on);
2727         if (result != WIFI_SUCCESS) {
2728             ALOGE("otaDownload Failed to put data= %d", result);
2729             return result;
2730         }
2731 
2732         result = request.put_u32(OTA_DOWNLOAD_TXCAP_BLOB_LENGTH_ATTR, buf->ota_txcap_len);
2733         if (result != WIFI_SUCCESS) {
2734             ALOGE("otaDownload Failed to put data= %d", result);
2735             return result;
2736         }
2737 
2738         result = request.put(OTA_DOWNLOAD_TXCAP_BLOB_ATTR,
2739             buf->ota_txcap_buf, sizeof(*buf->ota_txcap_buf));
2740         if (result != WIFI_SUCCESS) {
2741             ALOGE("otaDownload Failed to put data= %d", result);
2742             return result;
2743         }
2744 
2745         request.attr_end(data);
2746 
2747         result = requestResponse(request);
2748         if (result != WIFI_SUCCESS) {
2749             ALOGE("Failed to register set otaDownload; result = %d\n", result);
2750         }
2751 
2752         return result;
2753     }
2754 
handleResponse(WifiEvent & reply)2755     virtual int handleResponse(WifiEvent& reply) {
2756         ALOGD("In OtaUpdateCommand::handleResponse");
2757 
2758         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
2759             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
2760             return NL_SKIP;
2761         }
2762 
2763         int id = reply.get_vendor_id();
2764         int subcmd = reply.get_vendor_subcmd();
2765         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
2766         int len = reply.get_vendor_data_len();
2767 
2768         ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
2769 
2770         if (vendor_data == NULL || len == 0) {
2771             ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
2772             return NL_SKIP;
2773         }
2774 
2775         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
2776             switch (it.get_type()) {
2777                 case OTA_CUR_NVRAM_EXT_ATTR:
2778                     strncpy(ota_nvram_ext, (char*)it.get_string(), it.get_len());
2779                     ALOGI("Current Nvram ext [%s]\n", ota_nvram_ext);
2780                     break;
2781                 default:
2782                     ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
2783                             it.get_type(), it.get_len());
2784                     break;
2785             }
2786         }
2787         return NL_OK;
2788     }
2789 
handleEvent(WifiEvent & event)2790     virtual int handleEvent(WifiEvent& event) {
2791         /* NO events! */
2792         return NL_SKIP;
2793     }
2794 };
2795 
read_ota_file(char * file,char ** buffer,uint32_t * size)2796 wifi_error read_ota_file(char* file, char** buffer, uint32_t* size)
2797 {
2798     FILE* fp = NULL;
2799     int file_size;
2800     char* buf;
2801     fp = fopen(file, "r");
2802 
2803     if (fp == NULL) {
2804         ALOGI("File [%s] doesn't exist.", file);
2805         return WIFI_ERROR_NOT_AVAILABLE;
2806     }
2807 
2808     fseek(fp, 0, SEEK_END);
2809     file_size = ftell(fp);
2810 
2811     buf = (char *)malloc(file_size + 1);
2812     if (buf == NULL) {
2813         fclose(fp);
2814         return WIFI_ERROR_UNKNOWN;
2815     }
2816     memset(buf, 0, file_size + 1);
2817     fseek(fp, 0, SEEK_SET);
2818     fread(buf, file_size, 1, fp);
2819 
2820     *buffer = (char*) buf;
2821     *size = file_size;
2822     fclose(fp);
2823     return WIFI_SUCCESS;
2824 }
2825 
check_multiple_nvram_clm(uint32_t type,char * hw_revision,char * hw_sku,char ** buffer,uint32_t * buffer_len)2826 wifi_error check_multiple_nvram_clm(uint32_t type, char* hw_revision, char* hw_sku,
2827         char** buffer, uint32_t* buffer_len)
2828 {
2829     char file_name[MAX_NV_FILE][FILE_NAME_LEN];
2830     char nvram_clmblob_default_file[FILE_NAME_LEN] = {0,};
2831     wifi_error result = WIFI_SUCCESS;
2832 
2833     if (type == CLM_BLOB) {
2834         sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_CLM_FILE);
2835     }
2836     else if (type == NVRAM) {
2837         sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_NVRAM_FILE);
2838     }
2839     else if (type == TXCAP_BLOB) {
2840         sprintf(nvram_clmblob_default_file, "%s%s", OTA_PATH, OTA_TXCAP_BLOB_FILE);
2841     }
2842 
2843     for (unsigned int i = 0; i < MAX_NV_FILE; i++) {
2844         memset(file_name[i], 0, FILE_NAME_LEN);
2845     }
2846 
2847     sprintf(file_name[0], "%s_%s_%s", nvram_clmblob_default_file, hw_revision, hw_sku);
2848     sprintf(file_name[1], "%s_%s", nvram_clmblob_default_file, hw_revision);
2849     sprintf(file_name[2], "%s_%s", nvram_clmblob_default_file, hw_sku);
2850     sprintf(file_name[3], "%s", nvram_clmblob_default_file);
2851 
2852     for (unsigned int i = 0; i < MAX_NV_FILE; i++) {
2853         result = read_ota_file(file_name[i], buffer, buffer_len);
2854         if (result == WIFI_SUCCESS) {
2855             ALOGI("[OTA] %s PATH %s", type == NVRAM ? "NVRAM" : "CLM", file_name[i]);
2856             break;
2857         }
2858     }
2859     return result;
2860 }
2861 
wifi_hal_ota_update(wifi_interface_handle iface,uint32_t ota_version)2862 wifi_error wifi_hal_ota_update(wifi_interface_handle iface, uint32_t ota_version)
2863 {
2864     wifi_handle handle = getWifiHandle(iface);
2865     wifi_error result = WIFI_SUCCESS;
2866     ota_info_buf_t buf;
2867     char *buffer_nvram = NULL;
2868     char *buffer_clm = NULL;
2869     char *buffer_txcap_blob = NULL;
2870     char prop_revision_buf[PROPERTY_VALUE_MAX] = {0,};
2871     char prop_sku_buf[PROPERTY_VALUE_MAX] = {0,};
2872     char sku_name[MAX_SKU_NAME_LEN] = {0,};
2873 
2874     OtaUpdateCommand *cmd = new OtaUpdateCommand(iface);
2875     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
2876 
2877     ALOGD("wifi_hal_ota_update, handle = %p, ota_version %d\n", handle, ota_version);
2878 
2879     result = (wifi_error)cmd->start();
2880     if (result != WIFI_SUCCESS) {
2881         cmd->releaseRef();
2882         return result;
2883     }
2884 
2885     property_get(HW_DEV_PROP, prop_revision_buf, NULL);
2886     property_get(HW_SKU_PROP, prop_sku_buf, NULL);
2887 
2888     strncpy(sku_name, "NA", MAX_SKU_NAME_LEN);
2889     for (int i = 0; i < ARRAYSIZE(sku_table); i ++) {
2890         if (strcmp(prop_sku_buf, sku_table[i].hw_id) == 0) {
2891             strncpy(sku_name, sku_table[i].sku, MAX_SKU_NAME_LEN);
2892             break;
2893         }
2894     }
2895     ALOGD("prop_sku_buf is %s, sku_name is %s", prop_sku_buf, sku_name);
2896 
2897     check_multiple_nvram_clm(CLM_BLOB, prop_revision_buf, sku_name, &buffer_clm, &buf.ota_clm_len);
2898     if (buffer_clm == NULL) {
2899         ALOGE("buffer_clm is null");
2900         goto exit;
2901     }
2902     buf.ota_clm_buf[0] = buffer_clm;
2903 
2904     check_multiple_nvram_clm(TXCAP_BLOB, prop_revision_buf, sku_name,
2905         &buffer_txcap_blob, &buf.ota_txcap_len);
2906     if (buffer_txcap_blob == NULL) {
2907         ALOGE("buffer_txcap_blob is null");
2908         goto exit;
2909     }
2910     buf.ota_txcap_buf[0] = buffer_txcap_blob;
2911 
2912     check_multiple_nvram_clm(NVRAM, prop_revision_buf, sku_name,
2913             &buffer_nvram, &buf.ota_nvram_len);
2914     if (buffer_nvram == NULL) {
2915         ALOGE("buffer_nvram is null");
2916         goto exit;
2917     }
2918     buf.ota_nvram_buf[0] = buffer_nvram;
2919     cmd->otaDownload(&buf, ota_version);
2920 
2921 exit:
2922     if (buffer_clm != NULL) {
2923         free(buffer_clm);
2924     }
2925     if (buffer_nvram != NULL) {
2926         free(buffer_nvram);
2927     }
2928     if (buffer_txcap_blob != NULL) {
2929         free(buffer_txcap_blob);
2930     }
2931 
2932     cmd->releaseRef();
2933 
2934     return result;
2935 }
2936