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