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
30 #include <linux/pkt_sched.h>
31 #include <netlink/object-api.h>
32 #include <netlink/netlink.h>
33 #include <netlink/socket.h>
34 #include <netlink-private/object-api.h>
35 #include <netlink-private/types.h>
36 #include <unistd.h>
37
38
39 #include "nl80211_copy.h"
40 #include "sync.h"
41
42 #define LOG_TAG "WifiHAL"
43
44 #include <log/log.h>
45
46 #include "wifi_hal.h"
47 #include "common.h"
48 #include "cpp_bindings.h"
49 #include "brcm_version.h"
50 #define WIFI_HAL_EVENT_SOCK_PORT 645
51
52 #define ARRAYSIZE(a) (u8)(sizeof(a) / sizeof(a[0]))
53 typedef enum {
54 LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
55 LOGGER_TRIGGER_MEM_DUMP,
56 LOGGER_GET_MEM_DUMP,
57 LOGGER_GET_VER,
58 LOGGER_GET_RING_STATUS,
59 LOGGER_GET_RING_DATA,
60 LOGGER_GET_FEATURE,
61 LOGGER_RESET_LOGGING,
62 LOGGER_TRIGGER_DRIVER_MEM_DUMP,
63 LOGGER_GET_DRIVER_MEM_DUMP,
64 LOGGER_START_PKT_FATE_MONITORING,
65 LOGGER_GET_TX_PKT_FATES,
66 LOGGER_GET_RX_PKT_FATES,
67 LOGGER_GET_WAKE_REASON_STATS,
68 LOGGER_DEBUG_GET_DUMP,
69 LOGGER_FILE_DUMP_DONE_IND,
70 LOGGER_SET_HAL_START,
71 LOGGER_HAL_STOP,
72 LOGGER_SET_HAL_PID
73 } DEBUG_SUB_COMMAND;
74
75 typedef enum {
76 LOGGER_ATTRIBUTE_DRIVER_VER,
77 LOGGER_ATTRIBUTE_FW_VER,
78 LOGGER_ATTRIBUTE_RING_ID,
79 LOGGER_ATTRIBUTE_RING_NAME,
80 LOGGER_ATTRIBUTE_RING_FLAGS,
81 LOGGER_ATTRIBUTE_LOG_LEVEL,
82 LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
83 LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
84 LOGGER_ATTRIBUTE_FW_DUMP_LEN,
85 LOGGER_ATTRIBUTE_FW_DUMP_DATA,
86 LOGGER_ATTRIBUTE_FW_ERR_CODE,
87 LOGGER_ATTRIBUTE_RING_DATA,
88 LOGGER_ATTRIBUTE_RING_STATUS,
89 LOGGER_ATTRIBUTE_RING_NUM,
90 LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
91 LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
92 LOGGER_ATTRIBUTE_PKT_FATE_NUM,
93 LOGGER_ATTRIBUTE_PKT_FATE_DATA,
94 } LOGGER_ATTRIBUTE;
95
96 typedef enum {
97 DEBUG_OFF = 0,
98 DEBUG_NORMAL,
99 DEBUG_VERBOSE,
100 DEBUG_VERY,
101 DEBUG_VERY_VERY,
102 } LOGGER_LEVEL;
103
104 typedef enum {
105 GET_FW_VER,
106 GET_DRV_VER,
107 GET_RING_DATA,
108 GET_RING_STATUS,
109 GET_FEATURE,
110 START_RING_LOG,
111 } GetCmdType;
112
113 typedef enum {
114 PACKET_MONITOR_START,
115 TX_PACKET_FATE,
116 RX_PACKET_FATE,
117 } PktFateReqType;
118
119 enum wake_stat_attributes {
120 WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT,
121 WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE,
122 WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT,
123 WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
124 WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
125 WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
126 WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT,
127 WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED,
128 WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE,
129 WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT,
130 WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT,
131 WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT,
132 WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT,
133 WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT,
134 WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA,
135 WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA,
136 WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
137 WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
138 WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
139 WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT,
140 WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO
141 };
142
143 typedef enum {
144 SET_HAL_START_ATTRIBUTE_DEINIT = 0x0001,
145 SET_HAL_START_ATTRIBUTE_PRE_INIT = 0x0002,
146 SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
147 } SET_HAL_START_ATTRIBUTE;
148
149 #define HAL_START_REQUEST_ID 2
150
151 ///////////////////////////////////////////////////////////////////////////////
152 class DebugCommand : public WifiCommand
153 {
154 char *mBuff;
155 int *mBuffSize;
156 u32 *mNumRings;
157 wifi_ring_buffer_status *mStatus;
158 unsigned int *mSupport;
159 u32 mVerboseLevel;
160 u32 mFlags;
161 u32 mMaxIntervalSec;
162 u32 mMinDataSize;
163 char *mRingName;
164 GetCmdType mType;
165
166 public:
167
168 // constructor for get version
DebugCommand(wifi_interface_handle iface,char * buffer,int * buffer_size,GetCmdType cmdType)169 DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,
170 GetCmdType cmdType)
171 : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
172 (cmdType)
173 {
174 mNumRings = NULL;
175 mStatus = NULL;
176 mSupport = NULL;
177 mVerboseLevel = 0;
178 mFlags = 0;
179 mMaxIntervalSec = 0;
180 mMinDataSize = 0;
181 mRingName = NULL;
182 memset(mBuff, 0, *mBuffSize);
183 }
184
185 // constructor for ring data
DebugCommand(wifi_interface_handle iface,char * ring_name,GetCmdType cmdType)186 DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
187 : WifiCommand("DebugCommand", iface, 0), mRingName(ring_name), mType(cmdType)
188 {
189 mBuff = NULL;
190 mBuffSize = NULL;
191 mNumRings = NULL;
192 mStatus = NULL;
193 mSupport = NULL;
194 mVerboseLevel = 0;
195 mFlags = 0;
196 mMaxIntervalSec = 0;
197 mMinDataSize = 0;
198 }
199
200 // constructor for ring status
DebugCommand(wifi_interface_handle iface,u32 * num_rings,wifi_ring_buffer_status * status,GetCmdType cmdType)201 DebugCommand(wifi_interface_handle iface, u32 *num_rings,
202 wifi_ring_buffer_status *status, GetCmdType cmdType)
203 : WifiCommand("DebugCommand", iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
204 {
205 mBuff = NULL;
206 mBuffSize = NULL;
207 mSupport = NULL;
208 mVerboseLevel = 0;
209 mFlags = 0;
210 mMaxIntervalSec = 0;
211 mMinDataSize = 0;
212 mRingName = NULL;
213 memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
214 }
215
216 // constructor for feature set
DebugCommand(wifi_interface_handle iface,unsigned int * support,GetCmdType cmdType)217 DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
218 : WifiCommand("DebugCommand", iface, 0), mSupport(support), mType(cmdType)
219 {
220 mBuff = NULL;
221 mBuffSize = NULL;
222 mNumRings = NULL;
223 mStatus = NULL;
224 mVerboseLevel = 0;
225 mFlags = 0;
226 mMaxIntervalSec = 0;
227 mMinDataSize = 0;
228 mRingName = NULL;
229 }
230
231 // 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)232 DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
233 u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)
234 : WifiCommand("DebugCommand", iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
235 mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
236 mRingName(ring_name), mType(cmdType)
237 {
238 mBuff = NULL;
239 mBuffSize = NULL;
240 mNumRings = NULL;
241 mStatus = NULL;
242 mSupport = NULL;
243 }
244
createRingRequest(WifiRequest & request)245 int createRingRequest(WifiRequest& request) {
246 int result = request.create(GOOGLE_OUI, LOGGER_START_LOGGING);
247 if (result != WIFI_SUCCESS) {
248 ALOGE("Failed to create start ring logger request; result = %d", result);
249 return result;
250 }
251
252 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
253
254 result = request.put_u32(LOGGER_ATTRIBUTE_LOG_LEVEL, mVerboseLevel);
255 if (result != WIFI_SUCCESS) {
256 ALOGE("Failed to put log level; result = %d", result);
257 return result;
258 }
259 result = request.put_u32(LOGGER_ATTRIBUTE_RING_FLAGS, mFlags);
260 if (result != WIFI_SUCCESS) {
261 ALOGE("Failed to put ring flags; result = %d", result);
262 return result;
263 }
264 result = request.put_u32(LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, mMaxIntervalSec);
265 if (result != WIFI_SUCCESS) {
266 ALOGE("Failed to put log time interval; result = %d", result);
267 return result;
268 }
269 result = request.put_u32(LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, mMinDataSize);
270 if (result != WIFI_SUCCESS) {
271 ALOGE("Failed to put min data size; result = %d", result);
272 return result;
273 }
274 result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
275 if (result != WIFI_SUCCESS) {
276 ALOGE("Failed to put ringbuffer name; result = %d", result);
277 return result;
278 }
279 request.attr_end(data);
280
281 return WIFI_SUCCESS;
282 }
283
createRequest(WifiRequest & request)284 int createRequest(WifiRequest &request) {
285 int result;
286
287 switch (mType) {
288 case GET_FW_VER:
289 {
290 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
291 if (result != WIFI_SUCCESS) {
292 ALOGE("Failed to create get fw version request; result = %d", result);
293 return result;
294 }
295
296 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
297
298 // Driver expecting only attribute type, passing mbuff as data with
299 // length 0 to avoid undefined state
300 result = request.put(LOGGER_ATTRIBUTE_FW_VER, mBuff, 0);
301 if (result != WIFI_SUCCESS) {
302 ALOGE("Failed to put get fw version request; result = %d", result);
303 return result;
304 }
305 request.attr_end(data);
306 break;
307 }
308
309 case GET_DRV_VER:
310 {
311 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
312 if (result != WIFI_SUCCESS) {
313 ALOGE("Failed to create get drv version request; result = %d", result);
314 return result;
315 }
316
317 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
318
319 // Driver expecting only attribute type, passing mbuff as data with
320 // length 0 to avoid undefined state
321 result = request.put(LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);
322
323 if (result != WIFI_SUCCESS) {
324 ALOGE("Failed to put get drv version request; result = %d", result);
325 return result;
326 }
327 request.attr_end(data);
328 break;
329 }
330
331 case GET_RING_DATA:
332 {
333 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_DATA);
334 if (result != WIFI_SUCCESS) {
335 ALOGE("Failed to create get ring data request; result = %d", result);
336 return result;
337 }
338
339 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
340 result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
341 if (result != WIFI_SUCCESS) {
342 ALOGE("Failed to put ring data request; result = %d", result);
343 return result;
344 }
345 request.attr_end(data);
346 break;
347 }
348
349 case GET_RING_STATUS:
350 {
351 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_STATUS);
352 if (result != WIFI_SUCCESS) {
353 ALOGE("Failed to create get ring status request; result = %d", result);
354 return result;
355 }
356 break;
357 }
358
359 case GET_FEATURE:
360 {
361 result = request.create(GOOGLE_OUI, LOGGER_GET_FEATURE);
362 if (result != WIFI_SUCCESS) {
363 ALOGE("Failed to create get feature request; result = %d", result);
364 return result;
365 }
366 break;
367 }
368
369 case START_RING_LOG:
370 result = createRingRequest(request);
371 break;
372
373 default:
374 ALOGE("Unknown Debug command");
375 result = WIFI_ERROR_UNKNOWN;
376 }
377 return result;
378 }
379
start()380 int start() {
381 // ALOGD("Start debug command");
382 WifiRequest request(familyId(), ifaceId());
383 int result = createRequest(request);
384 if (result != WIFI_SUCCESS) {
385 ALOGE("Failed to create debug request; result = %d", result);
386 return result;
387 }
388
389 result = requestResponse(request);
390 if (result != WIFI_SUCCESS) {
391 ALOGE("Failed to register debug response; result = %d", result);
392 }
393 return result;
394 }
395
handleResponse(WifiEvent & reply)396 virtual int handleResponse(WifiEvent& reply) {
397 ALOGD("In DebugCommand::handleResponse");
398
399 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
400 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
401 return NL_SKIP;
402 }
403
404 switch (mType) {
405 case GET_DRV_VER:
406 case GET_FW_VER:
407 {
408 void *data = reply.get_vendor_data();
409 int len = reply.get_vendor_data_len();
410
411 ALOGD("len = %d, expected len = %d", len, *mBuffSize);
412 memcpy(mBuff, data, min(len, *mBuffSize));
413 if (*mBuffSize < len)
414 return NL_SKIP;
415 *mBuffSize = len;
416 break;
417 }
418
419 case START_RING_LOG:
420 case GET_RING_DATA:
421 break;
422
423 case GET_RING_STATUS:
424 {
425 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
426 int len = reply.get_vendor_data_len();
427 wifi_ring_buffer_status *status(mStatus);
428
429 if (vendor_data == NULL || len == 0) {
430 ALOGE("No Debug data found");
431 return NL_SKIP;
432 }
433
434 nl_iterator it(vendor_data);
435 if (it.get_type() == LOGGER_ATTRIBUTE_RING_NUM) {
436 unsigned int num_rings = it.get_u32();
437 if (*mNumRings < num_rings) {
438 ALOGE("Not enough status buffers provided, available: %d required: %d",
439 *mNumRings, num_rings);
440 } else {
441 *mNumRings = num_rings;
442 }
443 } else {
444 ALOGE("Unknown attribute: %d expecting %d",
445 it.get_type(), LOGGER_ATTRIBUTE_RING_NUM);
446 return NL_SKIP;
447 }
448
449 it.next();
450 for (unsigned int i = 0; it.has_next() && i < *mNumRings; it.next()) {
451 if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
452 memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status));
453 i++;
454 status++;
455 } else {
456 ALOGW("Ignoring invalid attribute type = %d, size = %d",
457 it.get_type(), it.get_len());
458 }
459 }
460 break;
461 }
462
463 case GET_FEATURE:
464 {
465 void *data = reply.get_vendor_data();
466 int len = reply.get_vendor_data_len();
467
468 ALOGD("len = %d, expected len = %d", len, sizeof(unsigned int));
469 memcpy(mSupport, data, sizeof(unsigned int));
470 break;
471 }
472
473 default:
474 ALOGW("Unknown Debug command");
475 }
476 return NL_OK;
477 }
478
handleEvent(WifiEvent & event)479 virtual int handleEvent(WifiEvent& event) {
480 /* NO events! */
481 return NL_SKIP;
482 }
483 };
484
485 /* API to collect a firmware version string */
wifi_get_firmware_version(wifi_interface_handle iface,char * buffer,int buffer_size)486 wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
487 int buffer_size)
488 {
489 if (buffer && (buffer_size > 0)) {
490 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);
491 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
492 wifi_error result = (wifi_error)cmd->start();
493 cmd->releaseRef();
494 return result;
495 } else {
496 ALOGE("FW version buffer NULL");
497 return WIFI_ERROR_INVALID_ARGS;
498 }
499 }
500
501 /* API to collect a driver version string */
wifi_get_driver_version(wifi_interface_handle iface,char * buffer,int buffer_size)502 wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
503 {
504 if (buffer && (buffer_size > 0)) {
505 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);
506 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
507 wifi_error result = (wifi_error)cmd->start();
508 cmd->releaseRef();
509 return result;
510 } else {
511 ALOGE("Driver version buffer NULL");
512 return WIFI_ERROR_INVALID_ARGS;
513 }
514 }
515
516 /* API to collect driver records */
wifi_get_ring_data(wifi_interface_handle iface,char * ring_name)517 wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)
518 {
519 DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);
520 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
521 wifi_error result = (wifi_error)cmd->start();
522 cmd->releaseRef();
523 return result;
524 }
525
526 /* 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)527 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
528 u32 *num_rings, wifi_ring_buffer_status *status)
529 {
530 if (status && num_rings) {
531 DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);
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("Ring status buffer NULL");
538 return WIFI_ERROR_INVALID_ARGS;
539 }
540 }
541
542 /* API to get supportable feature */
wifi_get_logger_supported_feature_set(wifi_interface_handle iface,unsigned int * support)543 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
544 unsigned int *support)
545 {
546 if (support) {
547 DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);
548 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
549 wifi_error result = (wifi_error)cmd->start();
550 cmd->releaseRef();
551 return result;
552 } else {
553 ALOGE("Get support buffer NULL");
554 return WIFI_ERROR_INVALID_ARGS;
555 }
556 }
557
wifi_start_logging(wifi_interface_handle iface,u32 verbose_level,u32 flags,u32 max_interval_sec,u32 min_data_size,char * ring_name)558 wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
559 u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
560 {
561 if (ring_name) {
562 DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
563 min_data_size, ring_name, START_RING_LOG);
564 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
565 wifi_error result = (wifi_error)cmd->start();
566 cmd->releaseRef();
567 return result;
568 } else {
569 ALOGE("Ring name NULL");
570 return WIFI_ERROR_INVALID_ARGS;
571 }
572 }
573
574
575 ///////////////////////////////////////////////////////////////////////////////
576 class SetLogHandler : public WifiCommand
577 {
578 wifi_ring_buffer_data_handler mHandler;
579
580 public:
SetLogHandler(wifi_interface_handle iface,int id,wifi_ring_buffer_data_handler handler)581 SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
582 : WifiCommand("SetLogHandler", iface, id), mHandler(handler)
583 { }
584
start()585 int start() {
586 ALOGV("Register loghandler");
587 int result;
588 uint32_t event_sock_pid = getpid() + (WIFI_HAL_EVENT_SOCK_PORT << 22);
589 registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
590
591 WifiRequest request(familyId(), ifaceId());
592
593 /* set hal event socket port to driver */
594 result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_PID);
595 if (result != WIFI_SUCCESS) {
596 ALOGV("Failed to set Hal preInit; result = %d", result);
597 return result;
598 }
599 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
600 result = request.put_u32(SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID, event_sock_pid);
601 if (result != WIFI_SUCCESS) {
602 ALOGV("Hal preInit Failed to put pic = %d", result);
603 return result;
604 }
605
606 if (result != WIFI_SUCCESS) {
607 ALOGV("Hal preInit Failed to put pid= %d", result);
608 return result;
609 }
610
611 request.attr_end(data);
612
613 result = requestResponse(request);
614 if (result != WIFI_SUCCESS) {
615 ALOGE("Failed to register set Hal preInit; result = %d", result);
616 return result;
617 }
618 return result;
619 }
620
cancel()621 virtual int cancel() {
622 /* Send a command to driver to stop generating logging events */
623 ALOGV("Clear loghandler");
624
625 /* unregister event handler */
626 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
627
628 WifiRequest request(familyId(), ifaceId());
629 int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
630 if (result != WIFI_SUCCESS) {
631 ALOGE("failed to create reset request; result = %d", result);
632 return result;
633 }
634
635 result = requestResponse(request);
636 if (result != WIFI_SUCCESS) {
637 ALOGE("failed to request reset; result = %d", result);
638 return result;
639 }
640
641 ALOGD("Success to clear loghandler");
642 return WIFI_SUCCESS;
643 }
644
handleEvent(WifiEvent & event)645 virtual int handleEvent(WifiEvent& event) {
646 char *buffer = NULL;
647 int buffer_size = 0;
648
649 // ALOGD("In SetLogHandler::handleEvent");
650 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
651 int len = event.get_vendor_data_len();
652 int event_id = event.get_vendor_subcmd();
653 // ALOGI("Got Logger event: %d", event_id);
654
655 if (vendor_data == NULL || len == 0) {
656 ALOGE("No Debug data found");
657 return NL_SKIP;
658 }
659
660 if(event_id == GOOGLE_DEBUG_RING_EVENT) {
661 wifi_ring_buffer_status status;
662 memset(&status, 0, sizeof(status));
663
664 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
665 if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
666 memcpy(&status, it.get_data(), sizeof(status));
667 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
668 buffer_size = it.get_len();
669 buffer = (char *)it.get_data();
670 } else {
671 ALOGW("Ignoring invalid attribute type = %d, size = %d",
672 it.get_type(), it.get_len());
673 }
674 }
675
676 // ALOGI("Retrieved Debug data");
677 if (mHandler.on_ring_buffer_data) {
678 /* Skip msg header. Retrieved log */
679 char *pBuff;
680 wifi_ring_buffer_entry *buffer_entry =
681 (wifi_ring_buffer_entry *) buffer;
682 pBuff = (char *) (buffer_entry + 1);
683 (*mHandler.on_ring_buffer_data)((char *)status.name, pBuff,
684 buffer_entry->entry_size, &status);
685 }
686 } else {
687 ALOGE("Unknown Event");
688 return NL_SKIP;
689 }
690 return NL_OK;
691 }
692 };
693
wifi_set_log_handler(wifi_request_id id,wifi_interface_handle iface,wifi_ring_buffer_data_handler handler)694 wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
695 wifi_ring_buffer_data_handler handler)
696 {
697 wifi_handle handle = getWifiHandle(iface);
698 ALOGV("Loghandler start, handle = %p", handle);
699
700 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
701 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
702 wifi_error result = wifi_register_cmd(handle, id, cmd);
703 if (result != WIFI_SUCCESS) {
704 cmd->releaseRef();
705 return result;
706 }
707 result = (wifi_error)cmd->start();
708 if (result != WIFI_SUCCESS) {
709 wifi_unregister_cmd(handle, id);
710 cmd->releaseRef();
711 return result;
712 }
713 return result;
714 }
715
wifi_reset_log_handler(wifi_request_id id,wifi_interface_handle iface)716 wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
717 {
718 wifi_handle handle = getWifiHandle(iface);
719 ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
720
721 if (id == -1) {
722 wifi_ring_buffer_data_handler handler;
723 memset(&handler, 0, sizeof(handler));
724
725 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
726 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
727 cmd->cancel();
728 cmd->releaseRef();
729 return WIFI_SUCCESS;
730 }
731
732 return wifi_cancel_cmd(id, iface);
733 }
734
735 ///////////////////////////////////////////////////////////////////////////////
736 class SetAlertHandler : public WifiCommand
737 {
738 wifi_alert_handler mHandler;
739 int mBuffSize;
740 char *mBuff;
741 int mErrCode;
742
743 public:
SetAlertHandler(wifi_interface_handle iface,int id,wifi_alert_handler handler)744 SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)
745 : WifiCommand("SetAlertHandler", iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),
746 mErrCode(0)
747 { }
748
start()749 int start() {
750 ALOGV("Start Alerting");
751 registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
752 return WIFI_SUCCESS;
753 }
754
cancel()755 virtual int cancel() {
756 ALOGV("Clear alerthandler");
757
758 /* unregister alert handler */
759 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
760 wifi_unregister_cmd(wifiHandle(), id());
761 ALOGD("Success to clear alerthandler");
762 return WIFI_SUCCESS;
763 }
764
handleResponse(WifiEvent & reply)765 virtual int handleResponse(WifiEvent& reply) {
766 ALOGD("In SetAlertHandler::handleResponse");
767
768 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
769 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
770 return NL_SKIP;
771 }
772
773 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
774 int len = reply.get_vendor_data_len();
775
776 ALOGD("len = %d", len);
777 if (vendor_data == NULL || len == 0) {
778 ALOGE("no vendor data in memory dump response; ignoring it");
779 return NL_SKIP;
780 }
781
782 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
783 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
784 ALOGI("Initiating alert callback");
785 if (mHandler.on_alert) {
786 (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
787 }
788 if (mBuff) {
789 free(mBuff);
790 mBuff = NULL;
791 }
792 }
793 }
794 return NL_OK;
795 }
796
handleEvent(WifiEvent & event)797 virtual int handleEvent(WifiEvent& event) {
798 wifi_ring_buffer_id ring_id;
799 char *buffer = NULL;
800 int buffer_size = 0;
801 bool is_err_alert = false;
802
803 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
804 int len = event.get_vendor_data_len();
805 int event_id = event.get_vendor_subcmd();
806 ALOGI("Got event: %d", event_id);
807
808 if (vendor_data == NULL || len == 0) {
809 ALOGE("No Debug data found");
810 return NL_SKIP;
811 }
812
813 if (event_id == GOOGLE_DEBUG_MEM_DUMP_EVENT) {
814 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
815 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
816 mBuffSize = it.get_u32();
817 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
818 buffer_size = it.get_len();
819 buffer = (char *)it.get_data();
820 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_ERR_CODE) {
821 /* Error code is for error alert event only */
822 mErrCode = it.get_u32();
823 is_err_alert = true;
824 } else {
825 ALOGW("Ignoring invalid attribute type = %d, size = %d",
826 it.get_type(), it.get_len());
827 }
828 }
829
830 if(is_err_alert) {
831 mBuffSize = sizeof(mErrCode);
832 if (mBuff) free(mBuff);
833 mBuff = (char *)malloc(mBuffSize);
834 if (!mBuff) {
835 ALOGE("Buffer allocation failed");
836 return NL_SKIP;
837 }
838 memcpy(mBuff, (char *)&mErrCode, mBuffSize);
839 ALOGI("Initiating alert callback");
840 if (mHandler.on_alert) {
841 (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
842 }
843 if (mBuff) {
844 free(mBuff);
845 mBuff = NULL;
846 }
847 mBuffSize = 0;
848 return NL_OK;
849 }
850
851 if (mBuffSize) {
852 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
853 if (mBuff) free(mBuff);
854 mBuff = (char *)malloc(mBuffSize + buffer_size);
855 if (!mBuff) {
856 ALOGE("Buffer allocation failed");
857 return NL_SKIP;
858 }
859 memcpy(mBuff, buffer, buffer_size);
860
861 WifiRequest request(familyId(), ifaceId());
862 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
863 if (result != WIFI_SUCCESS) {
864 ALOGE("Failed to create get memory dump request; result = %d", result);
865 free(mBuff);
866 return NL_SKIP;
867 }
868 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
869 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
870 if (result != WIFI_SUCCESS) {
871 ALOGE("Failed to put get memory dump request; result = %d", result);
872 return result;
873 }
874
875 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA,
876 (uint64_t)(mBuff+buffer_size));
877 if (result != WIFI_SUCCESS) {
878 ALOGE("Failed to put get memory dump request; result = %d", result);
879 return result;
880 }
881
882 request.attr_end(data);
883 mBuffSize += buffer_size;
884
885 result = requestResponse(request);
886
887 if (result != WIFI_SUCCESS) {
888 ALOGE("Failed to register get momory dump response; result = %d", result);
889 }
890 } else {
891 ALOGE("dump event missing dump length attribute");
892 return NL_SKIP;
893 }
894 }
895 return NL_OK;
896 }
897 };
898
899 ///////////////////////////////////////////////////////////////////////////////
900 class HalInit : public WifiCommand
901 {
902 int mErrCode;
903
904 public:
HalInit(wifi_interface_handle iface,int id)905 HalInit(wifi_interface_handle iface, int id)
906 : WifiCommand("HalInit", iface, id), mErrCode(0)
907 { }
908
start()909 int start() {
910 ALOGE("Start Set Hal");
911 WifiRequest request(familyId(), ifaceId());
912
913 int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
914 if (result != WIFI_SUCCESS) {
915 ALOGE("Failed to set hal start; result = %d", result);
916 return result;
917 }
918
919 result = requestResponse(request);
920 if (result != WIFI_SUCCESS) {
921 ALOGE("Failed to register set hal start response; result = %d", result);
922 }
923 return result;
924 }
925
926
cancel()927 virtual int cancel() {
928 ALOGE("Cancel: Stop Hal");
929 WifiRequest request(familyId(), ifaceId());
930
931 int result = request.create(GOOGLE_OUI, LOGGER_HAL_STOP);
932 if (result != WIFI_SUCCESS) {
933 ALOGE("Failed to stop hal ; result = %d", result);
934 return result;
935 }
936
937 result = requestResponse(request);
938 if (result != WIFI_SUCCESS) {
939 ALOGE("Failed to register set hal start response; result = %d", result);
940 }
941 wifi_unregister_cmd(wifiHandle(), id());
942 return result;
943 }
944
preInit()945 int preInit() {
946 ALOGE("Hal preInit");
947 WifiRequest request(familyId(), ifaceId());
948
949 int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
950 if (result != WIFI_SUCCESS) {
951 ALOGE("Failed to set Hal preInit; result = %d", result);
952 return result;
953 }
954
955 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
956 result = request.put_string(SET_HAL_START_ATTRIBUTE_PRE_INIT, (char *)HAL_VERSION);
957 if (result != WIFI_SUCCESS) {
958 ALOGE("Hal preInit Failed to put data= %d", result);
959 return result;
960 }
961 request.attr_end(data);
962
963 result = requestResponse(request);
964 if (result != WIFI_SUCCESS) {
965 ALOGE("Failed to register set Hal preInit; result = %d", result);
966 }
967 return result;
968 }
969
handleResponse(WifiEvent & reply)970 virtual int handleResponse(WifiEvent& reply) {
971 ALOGE("In SetHalStarted::handleResponse");
972
973 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
974 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
975 return NL_SKIP;
976 }
977 return NL_OK;
978 }
979
handleEvent(WifiEvent & event)980 virtual int handleEvent(WifiEvent& event) {
981 /* NO events! */
982 return NL_SKIP;
983 }
984 };
985
986
wifi_start_hal(wifi_interface_handle iface)987 wifi_error wifi_start_hal(wifi_interface_handle iface)
988 {
989 wifi_handle handle = getWifiHandle(iface);
990 ALOGV("HAL INIT start, handle = %p", handle);
991
992 HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
993 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
994 wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
995 if (result != WIFI_SUCCESS) {
996 cmd->releaseRef();
997 return result;
998 }
999 result = (wifi_error)cmd->start();
1000 if (result != WIFI_SUCCESS) {
1001 wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
1002 cmd->releaseRef();
1003 return result;
1004 }
1005 return result;
1006 }
1007
wifi_hal_preInit(wifi_interface_handle iface)1008 wifi_error wifi_hal_preInit(wifi_interface_handle iface)
1009 {
1010 wifi_handle handle = getWifiHandle(iface);
1011 ALOGV("wifi_hal_preInit, handle = %p", handle);
1012
1013 HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
1014 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1015 wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
1016 if (result != WIFI_SUCCESS) {
1017 cmd->releaseRef();
1018 return result;
1019 }
1020 result = (wifi_error)cmd->preInit();
1021 if (result != WIFI_SUCCESS) {
1022 wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
1023 cmd->releaseRef();
1024 return result;
1025 }
1026 return result;
1027 }
1028
wifi_stop_hal(wifi_interface_handle iface)1029 wifi_error wifi_stop_hal(wifi_interface_handle iface)
1030 {
1031 wifi_handle handle = getWifiHandle(iface);
1032
1033 HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
1034 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1035 cmd->cancel();
1036 cmd->releaseRef();
1037 return WIFI_SUCCESS;
1038 }
1039
wifi_set_alert_handler(wifi_request_id id,wifi_interface_handle iface,wifi_alert_handler handler)1040 wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
1041 wifi_alert_handler handler)
1042 {
1043 wifi_handle handle = getWifiHandle(iface);
1044 ALOGV("Alerthandler start, handle = %p", handle);
1045
1046 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
1047 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1048 wifi_error result = wifi_register_cmd(handle, id, cmd);
1049 if (result != WIFI_SUCCESS) {
1050 cmd->releaseRef();
1051 return result;
1052 }
1053 result = (wifi_error)cmd->start();
1054 if (result != WIFI_SUCCESS) {
1055 wifi_unregister_cmd(handle, id);
1056 cmd->releaseRef();
1057 return result;
1058 }
1059 return result;
1060 }
1061
wifi_reset_alert_handler(wifi_request_id id,wifi_interface_handle iface)1062 wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)
1063 {
1064 wifi_handle handle = getWifiHandle(iface);
1065 ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);
1066
1067 if (id == -1) {
1068 wifi_alert_handler handler;
1069 memset(&handler, 0, sizeof(handler));
1070
1071 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
1072 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1073 cmd->cancel();
1074 cmd->releaseRef();
1075 return WIFI_SUCCESS;
1076 }
1077
1078 return wifi_cancel_cmd(id, iface);
1079 }
1080
1081 ///////////////////////////////////////////////////////////////////////////////
1082 class MemoryDumpCommand: public WifiCommand
1083 {
1084 wifi_firmware_memory_dump_handler mHandler;
1085 int mBuffSize;
1086 char *mBuff;
1087
1088 public:
MemoryDumpCommand(wifi_interface_handle iface,wifi_firmware_memory_dump_handler handler)1089 MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler)
1090 : WifiCommand("MemoryDumpCommand", iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL)
1091 { }
1092
start()1093 int start() {
1094 ALOGD("Start memory dump command");
1095 WifiRequest request(familyId(), ifaceId());
1096
1097 int result = request.create(GOOGLE_OUI, LOGGER_TRIGGER_MEM_DUMP);
1098 if (result != WIFI_SUCCESS) {
1099 ALOGE("Failed to create trigger fw memory dump request; result = %d", result);
1100 return result;
1101 }
1102
1103 result = requestResponse(request);
1104 if (result != WIFI_SUCCESS) {
1105 ALOGE("Failed to register trigger memory dump response; result = %d", result);
1106 }
1107 return result;
1108 }
1109
handleResponse(WifiEvent & reply)1110 virtual int handleResponse(WifiEvent& reply) {
1111 ALOGD("In MemoryDumpCommand::handleResponse");
1112
1113 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1114 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1115 return NL_SKIP;
1116 }
1117
1118 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1119 int len = reply.get_vendor_data_len();
1120
1121 ALOGD("len = %d", len);
1122 if (vendor_data == NULL || len == 0) {
1123 ALOGE("no vendor data in memory dump response; ignoring it");
1124 return NL_SKIP;
1125 }
1126
1127 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1128 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
1129 mBuffSize = it.get_u32();
1130
1131 if (mBuff)
1132 free(mBuff);
1133 mBuff = (char *)malloc(mBuffSize);
1134 if (!mBuff) {
1135 ALOGE("Buffer allocation failed");
1136 return NL_SKIP;
1137 }
1138 WifiRequest request(familyId(), ifaceId());
1139 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
1140 if (result != WIFI_SUCCESS) {
1141 ALOGE("Failed to create get memory dump request; result = %d", result);
1142 free(mBuff);
1143 return NL_SKIP;
1144 }
1145
1146 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1147 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
1148 if (result != WIFI_SUCCESS) {
1149 ALOGE("Failed to put get memory dump request; result = %d", result);
1150 return result;
1151 }
1152
1153 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);
1154 if (result != WIFI_SUCCESS) {
1155 ALOGE("Failed to put get memory dump request; result = %d", result);
1156 return result;
1157 }
1158 request.attr_end(data);
1159
1160 result = requestResponse(request);
1161 if (result != WIFI_SUCCESS) {
1162 ALOGE("Failed to register get momory dump response; result = %d", result);
1163 }
1164 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
1165 ALOGI("Initiating memory dump callback");
1166 if (mHandler.on_firmware_memory_dump) {
1167 (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);
1168 }
1169 if (mBuff) {
1170 free(mBuff);
1171 mBuff = NULL;
1172 }
1173 } else {
1174 ALOGW("Ignoring invalid attribute type = %d, size = %d",
1175 it.get_type(), it.get_len());
1176 }
1177 }
1178 return NL_OK;
1179 }
1180
handleEvent(WifiEvent & event)1181 virtual int handleEvent(WifiEvent& event) {
1182 /* NO events! */
1183 return NL_SKIP;
1184 }
1185 };
1186
1187 /* 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)1188 wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
1189 wifi_firmware_memory_dump_handler handler)
1190 {
1191 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler);
1192 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1193 wifi_error result = (wifi_error)cmd->start();
1194 cmd->releaseRef();
1195 return result;
1196 }
1197
1198 class PacketFateCommand: public WifiCommand
1199 {
1200 void *mReportBufs;
1201 size_t mNoReqFates;
1202 size_t *mNoProvidedFates;
1203 PktFateReqType mReqType;
1204
1205 public:
PacketFateCommand(wifi_interface_handle handle)1206 PacketFateCommand(wifi_interface_handle handle)
1207 : WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START)
1208 {
1209 mReportBufs = NULL;
1210 mNoReqFates = 0;
1211 mNoProvidedFates = NULL;
1212 }
1213
PacketFateCommand(wifi_interface_handle handle,wifi_tx_report * tx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)1214 PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
1215 size_t n_requested_fates, size_t *n_provided_fates)
1216 : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(tx_report_bufs),
1217 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
1218 mReqType(TX_PACKET_FATE)
1219 { }
1220
PacketFateCommand(wifi_interface_handle handle,wifi_rx_report * rx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)1221 PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,
1222 size_t n_requested_fates, size_t *n_provided_fates)
1223 : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(rx_report_bufs),
1224 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
1225 mReqType(RX_PACKET_FATE)
1226 { }
1227
createRequest(WifiRequest & request)1228 int createRequest(WifiRequest& request) {
1229 if (mReqType == TX_PACKET_FATE) {
1230 ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);
1231 return createTxPktFateRequest(request);
1232 } else if (mReqType == RX_PACKET_FATE) {
1233 ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);
1234 return createRxPktFateRequest(request);
1235 } else if (mReqType == PACKET_MONITOR_START) {
1236 ALOGD("%s Monitor packet fate request\n", __FUNCTION__);
1237 return createMonitorPktFateRequest(request);
1238 } else {
1239 ALOGE("%s Unknown packet fate request\n", __FUNCTION__);
1240 return WIFI_ERROR_NOT_SUPPORTED;
1241 }
1242 return WIFI_SUCCESS;
1243 }
1244
createMonitorPktFateRequest(WifiRequest & request)1245 int createMonitorPktFateRequest(WifiRequest& request) {
1246 int result = request.create(GOOGLE_OUI, LOGGER_START_PKT_FATE_MONITORING);
1247 if (result < 0) {
1248 return result;
1249 }
1250
1251 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1252 request.attr_end(data);
1253 return result;
1254 }
1255
createTxPktFateRequest(WifiRequest & request)1256 int createTxPktFateRequest(WifiRequest& request) {
1257 int result = request.create(GOOGLE_OUI, LOGGER_GET_TX_PKT_FATES);
1258 if (result < 0) {
1259 return result;
1260 }
1261
1262 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));
1263 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1264 result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
1265 if (result < 0) {
1266 return result;
1267 }
1268 result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
1269 if (result < 0) {
1270 return result;
1271 }
1272 request.attr_end(data);
1273 return result;
1274 }
1275
createRxPktFateRequest(WifiRequest & request)1276 int createRxPktFateRequest(WifiRequest& request) {
1277 int result = request.create(GOOGLE_OUI, LOGGER_GET_RX_PKT_FATES);
1278 if (result < 0) {
1279 return result;
1280 }
1281
1282 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));
1283 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1284 result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
1285 if (result < 0) {
1286 return result;
1287 }
1288 result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
1289 if (result < 0) {
1290 return result;
1291 }
1292 request.attr_end(data);
1293 return result;
1294 }
1295
start()1296 int start() {
1297 ALOGD("Start get packet fate command\n");
1298 WifiRequest request(familyId(), ifaceId());
1299
1300 int result = createRequest(request);
1301 if (result < 0) {
1302 ALOGE("Failed to create get pkt fate request; result = %d\n", result);
1303 return result;
1304 }
1305
1306 result = requestResponse(request);
1307 if (result != WIFI_SUCCESS) {
1308 ALOGE("Failed to register get pkt fate response; result = %d\n", result);
1309 }
1310 return result;
1311 }
1312
handleResponse(WifiEvent & reply)1313 int handleResponse(WifiEvent& reply) {
1314 ALOGD("In GetPktFateCommand::handleResponse\n");
1315
1316 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1317 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
1318 return NL_SKIP;
1319 }
1320
1321 int id = reply.get_vendor_id();
1322 int subcmd = reply.get_vendor_subcmd();
1323 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1324 int len = reply.get_vendor_data_len();
1325
1326 ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1327
1328 if (mReqType == TX_PACKET_FATE) {
1329 ALOGI("Response recieved for get TX pkt fate command\n");
1330 } else if (mReqType == RX_PACKET_FATE) {
1331 ALOGI("Response recieved for get RX pkt fate command\n");
1332 } else if (mReqType == PACKET_MONITOR_START) {
1333 ALOGI("Response recieved for monitor pkt fate command\n");
1334 return NL_OK;
1335 } else {
1336 ALOGE("Response recieved for unknown pkt fate command\n");
1337 return NL_SKIP;
1338 }
1339
1340 if (vendor_data == NULL || len == 0) {
1341 ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
1342 return NL_SKIP;
1343 }
1344
1345 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1346 if (it.get_type() == LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
1347 *mNoProvidedFates = it.get_u32();
1348 ALOGI("No: of pkt fates provided is %d\n", *mNoProvidedFates);
1349 } else {
1350 ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
1351 it.get_type(), it.get_len());
1352 }
1353 }
1354
1355 return NL_OK;
1356 }
1357
handleEvent(WifiEvent & event)1358 int handleEvent(WifiEvent& event) {
1359 /* NO events to handle here! */
1360 return NL_SKIP;
1361 }
1362 };
1363
1364 class GetWakeReasonCountCommand : public WifiCommand {
1365 WLAN_DRIVER_WAKE_REASON_CNT *mWakeReasonCnt;
1366 void *mCmdEventWakeCount;
1367 public:
GetWakeReasonCountCommand(wifi_interface_handle handle,WLAN_DRIVER_WAKE_REASON_CNT * wlanDriverWakeReasonCount)1368 GetWakeReasonCountCommand(wifi_interface_handle handle,
1369 WLAN_DRIVER_WAKE_REASON_CNT *wlanDriverWakeReasonCount) :
1370 WifiCommand("GetWakeReasonCountCommand", handle, 0),
1371 mWakeReasonCnt(wlanDriverWakeReasonCount)
1372 {
1373 mCmdEventWakeCount = mWakeReasonCnt->cmd_event_wake_cnt;
1374 }
1375
createRequest(WifiRequest & request)1376 int createRequest(WifiRequest& request) {
1377 int result = request.create(GOOGLE_OUI, LOGGER_GET_WAKE_REASON_STATS);
1378 if (result < 0) {
1379 return result;
1380 }
1381
1382 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1383
1384 request.attr_end(data);
1385 return WIFI_SUCCESS;
1386 }
1387
start()1388 int start() {
1389 ALOGD("Start get wake stats command\n");
1390 WifiRequest request(familyId(), ifaceId());
1391
1392 int result = createRequest(request);
1393 if (result < 0) {
1394 ALOGE("Failed to create request result = %d\n", result);
1395 return result;
1396 }
1397
1398 result = requestResponse(request);
1399 if (result != WIFI_SUCCESS) {
1400 ALOGE("Failed to register wake stats response; result = %d\n", result);
1401 }
1402 return result;
1403 }
1404
1405 protected:
handleResponse(WifiEvent & reply)1406 int handleResponse(WifiEvent& reply) {
1407 ALOGE("In GetWakeReasonCountCommand::handleResponse");
1408
1409 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1410 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1411 return NL_SKIP;
1412 }
1413
1414 int id = reply.get_vendor_id();
1415 int subcmd = reply.get_vendor_subcmd();
1416
1417 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1418 int len = reply.get_vendor_data_len();
1419
1420 ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1421 if (vendor_data == NULL || len == 0) {
1422 ALOGE("no vendor data in GetGetWakeReasonCountCommand response; ignoring it");
1423 return NL_SKIP;
1424 }
1425
1426 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1427 switch (it.get_type()) {
1428 case WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW:
1429 mWakeReasonCnt->total_driver_fw_local_wake =
1430 it.get_u32();
1431 break;
1432 case WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT:
1433 mWakeReasonCnt->total_cmd_event_wake =
1434 it.get_u32();
1435 break;
1436 case WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED:
1437 mWakeReasonCnt->cmd_event_wake_cnt_used =
1438 it.get_u32();
1439 break;
1440 case WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE:
1441 memcpy(mCmdEventWakeCount, it.get_data(),
1442 (mWakeReasonCnt->cmd_event_wake_cnt_used * sizeof(int)));
1443 break;
1444 case WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE:
1445 mWakeReasonCnt->total_rx_data_wake =
1446 it.get_u32();
1447 break;
1448 case WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT:
1449 mWakeReasonCnt->rx_wake_details.rx_unicast_cnt =
1450 it.get_u32();
1451 break;
1452 case WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT:
1453 mWakeReasonCnt->rx_wake_details.rx_multicast_cnt =
1454 it.get_u32();
1455 break;
1456 case WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT:
1457 mWakeReasonCnt->rx_wake_details.rx_broadcast_cnt =
1458 it.get_u32();
1459 break;
1460 case WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT:
1461 mWakeReasonCnt->rx_wake_pkt_classification_info.icmp_pkt =
1462 it.get_u32();
1463 break;
1464 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT:
1465 mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_pkt =
1466 it.get_u32();
1467 break;
1468 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA:
1469 mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ra =
1470 it.get_u32();
1471 break;
1472 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA:
1473 mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_na =
1474 it.get_u32();
1475 break;
1476 case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS:
1477 mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ns =
1478 it.get_u32();
1479 break;
1480 case WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT:
1481 mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt =
1482 it.get_u32();
1483 break;
1484 case WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT:
1485 mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
1486 it.get_u32();
1487 break;
1488 case WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT:
1489 mWakeReasonCnt->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
1490 it.get_u32();
1491 break;
1492 default:
1493 break;
1494 }
1495
1496 }
1497 return NL_OK;
1498 }
1499 };
1500
wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)1501 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
1502 {
1503 PacketFateCommand *cmd = new PacketFateCommand(handle);
1504 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1505 wifi_error result = (wifi_error)cmd->start();
1506 cmd->releaseRef();
1507 return result;
1508 }
1509
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)1510 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
1511 wifi_tx_report *tx_report_bufs, size_t n_requested_fates,
1512 size_t *n_provided_fates)
1513 {
1514 PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,
1515 n_requested_fates, n_provided_fates);
1516 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1517 wifi_error result = (wifi_error)cmd->start();
1518 cmd->releaseRef();
1519 return result;
1520 }
1521
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)1522 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
1523 wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
1524 size_t *n_provided_fates)
1525 {
1526 PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
1527 n_requested_fates, n_provided_fates);
1528 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1529 wifi_error result = (wifi_error)cmd->start();
1530 cmd->releaseRef();
1531 return result;
1532 }
1533
wifi_get_wake_reason_stats(wifi_interface_handle handle,WLAN_DRIVER_WAKE_REASON_CNT * wifi_wake_reason_cnt)1534 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
1535 WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
1536 {
1537 GetWakeReasonCountCommand *cmd =
1538 new GetWakeReasonCountCommand(handle, wifi_wake_reason_cnt);
1539 wifi_error result = (wifi_error)cmd->start();
1540 cmd->releaseRef();
1541 return result;
1542 }
1543