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