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