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