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
37 #include "nl80211_copy.h"
38 #include "sync.h"
39
40 #define LOG_TAG "WifiHAL"
41
42 #include <log/log.h>
43
44 #include "wifi_hal.h"
45 #include "common.h"
46 #include "cpp_bindings.h"
47
48 typedef enum {
49 LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
50 LOGGER_TRIGGER_MEM_DUMP,
51 LOGGER_GET_MEM_DUMP,
52 LOGGER_GET_VER,
53 LOGGER_GET_RING_STATUS,
54 LOGGER_GET_RING_DATA,
55 LOGGER_GET_FEATURE,
56 LOGGER_RESET_LOGGING,
57 LOGGER_TRIGGER_DRIVER_MEM_DUMP,
58 LOGGER_GET_DRIVER_MEM_DUMP,
59 LOGGER_START_PKT_FATE_MONITORING,
60 LOGGER_GET_TX_PKT_FATES,
61 LOGGER_GET_RX_PKT_FATES,
62 } DEBUG_SUB_COMMAND;
63
64 typedef enum {
65 LOGGER_ATTRIBUTE_DRIVER_VER,
66 LOGGER_ATTRIBUTE_FW_VER,
67 LOGGER_ATTRIBUTE_RING_ID,
68 LOGGER_ATTRIBUTE_RING_NAME,
69 LOGGER_ATTRIBUTE_RING_FLAGS,
70 LOGGER_ATTRIBUTE_LOG_LEVEL,
71 LOGGER_ATTRIBUTE_LOG_TIME_INTVAL,
72 LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
73 LOGGER_ATTRIBUTE_FW_DUMP_LEN,
74 LOGGER_ATTRIBUTE_FW_DUMP_DATA,
75 // LOGGER_ATTRIBUTE_FW_ERR_CODE,
76 LOGGER_ATTRIBUTE_RING_DATA,
77 LOGGER_ATTRIBUTE_RING_STATUS,
78 LOGGER_ATTRIBUTE_RING_NUM,
79 LOGGER_ATTRIBUTE_DRIVER_DUMP_LEN,
80 LOGGER_ATTRIBUTE_DRIVER_DUMP_DATA,
81 LOGGER_ATTRIBUTE_PKT_FATE_NUM,
82 LOGGER_ATTRIBUTE_PKT_FATE_DATA,
83 } LOGGER_ATTRIBUTE;
84
85 typedef enum {
86 DEBUG_OFF = 0,
87 DEBUG_NORMAL,
88 DEBUG_VERBOSE,
89 DEBUG_VERY,
90 DEBUG_VERY_VERY,
91 } LOGGER_LEVEL;
92
93 typedef enum {
94 GET_FW_VER,
95 GET_DRV_VER,
96 GET_RING_DATA,
97 GET_RING_STATUS,
98 GET_FEATURE,
99 START_RING_LOG,
100 } GetCmdType;
101
102 typedef enum {
103 PACKET_MONITOR_START,
104 TX_PACKET_FATE,
105 RX_PACKET_FATE,
106 } PktFateReqType;
107
108
109 ///////////////////////////////////////////////////////////////////////////////
110 class DebugCommand : public WifiCommand
111 {
112 char *mBuff;
113 int *mBuffSize;
114 u32 *mNumRings;
115 wifi_ring_buffer_status *mStatus;
116 unsigned int *mSupport;
117 u32 mVerboseLevel;
118 u32 mFlags;
119 u32 mMaxIntervalSec;
120 u32 mMinDataSize;
121 char *mRingName;
122 GetCmdType mType;
123
124 public:
125
126 // constructor for get version
DebugCommand(wifi_interface_handle iface,char * buffer,int * buffer_size,GetCmdType cmdType)127 DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,
128 GetCmdType cmdType)
129 : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
130 (cmdType)
131 {
132 memset(mBuff, 0, *mBuffSize);
133 }
134
135 // constructor for ring data
DebugCommand(wifi_interface_handle iface,char * ring_name,GetCmdType cmdType)136 DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
137 : WifiCommand("DebugCommand", iface, 0), mRingName(ring_name), mType(cmdType)
138 { }
139
140 // constructor for ring status
DebugCommand(wifi_interface_handle iface,u32 * num_rings,wifi_ring_buffer_status * status,GetCmdType cmdType)141 DebugCommand(wifi_interface_handle iface, u32 *num_rings,
142 wifi_ring_buffer_status *status, GetCmdType cmdType)
143 : WifiCommand("DebugCommand", iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
144 {
145 memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
146 }
147
148 // constructor for feature set
DebugCommand(wifi_interface_handle iface,unsigned int * support,GetCmdType cmdType)149 DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
150 : WifiCommand("DebugCommand", iface, 0), mSupport(support), mType(cmdType)
151 { }
152
153 // 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)154 DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
155 u32 max_interval_sec, u32 min_data_size, char *ring_name, GetCmdType cmdType)
156 : WifiCommand("DebugCommand", iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
157 mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
158 mRingName(ring_name), mType(cmdType)
159 { }
160
createRingRequest(WifiRequest & request)161 int createRingRequest(WifiRequest& request) {
162 int result = request.create(GOOGLE_OUI, LOGGER_START_LOGGING);
163 if (result != WIFI_SUCCESS) {
164 ALOGE("Failed to create start ring logger request; result = %d", result);
165 return result;
166 }
167
168 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
169
170 result = request.put_u32(LOGGER_ATTRIBUTE_LOG_LEVEL, mVerboseLevel);
171 if (result != WIFI_SUCCESS) {
172 ALOGE("Failed to put log level; result = %d", result);
173 return result;
174 }
175 result = request.put_u32(LOGGER_ATTRIBUTE_RING_FLAGS, mFlags);
176 if (result != WIFI_SUCCESS) {
177 ALOGE("Failed to put ring flags; result = %d", result);
178 return result;
179 }
180 result = request.put_u32(LOGGER_ATTRIBUTE_LOG_TIME_INTVAL, mMaxIntervalSec);
181 if (result != WIFI_SUCCESS) {
182 ALOGE("Failed to put log time interval; result = %d", result);
183 return result;
184 }
185 result = request.put_u32(LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE, mMinDataSize);
186 if (result != WIFI_SUCCESS) {
187 ALOGE("Failed to put min data size; result = %d", result);
188 return result;
189 }
190 result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
191 if (result != WIFI_SUCCESS) {
192 ALOGE("Failed to put ringbuffer name; result = %d", result);
193 return result;
194 }
195 request.attr_end(data);
196
197 return WIFI_SUCCESS;
198 }
199
createRequest(WifiRequest & request)200 int createRequest(WifiRequest &request) {
201 int result;
202
203 switch (mType) {
204 case GET_FW_VER:
205 {
206 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
207 if (result != WIFI_SUCCESS) {
208 ALOGE("Failed to create get fw version request; result = %d", result);
209 return result;
210 }
211
212 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
213
214 // Driver expecting only attribute type, passing mbuff as data with
215 // length 0 to avoid undefined state
216 result = request.put(LOGGER_ATTRIBUTE_FW_VER, mBuff, 0);
217 if (result != WIFI_SUCCESS) {
218 ALOGE("Failed to put get fw version request; result = %d", result);
219 return result;
220 }
221 request.attr_end(data);
222 break;
223 }
224
225 case GET_DRV_VER:
226 {
227 result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
228 if (result != WIFI_SUCCESS) {
229 ALOGE("Failed to create get drv version request; result = %d", result);
230 return result;
231 }
232
233 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
234
235 // Driver expecting only attribute type, passing mbuff as data with
236 // length 0 to avoid undefined state
237 result = request.put(LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);
238
239 if (result != WIFI_SUCCESS) {
240 ALOGE("Failed to put get drv version request; result = %d", result);
241 return result;
242 }
243 request.attr_end(data);
244 break;
245 }
246
247 case GET_RING_DATA:
248 {
249 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_DATA);
250 if (result != WIFI_SUCCESS) {
251 ALOGE("Failed to create get ring data request; result = %d", result);
252 return result;
253 }
254
255 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
256 result = request.put_string(LOGGER_ATTRIBUTE_RING_NAME, mRingName);
257 if (result != WIFI_SUCCESS) {
258 ALOGE("Failed to put ring data request; result = %d", result);
259 return result;
260 }
261 request.attr_end(data);
262 break;
263 }
264
265 case GET_RING_STATUS:
266 {
267 result = request.create(GOOGLE_OUI, LOGGER_GET_RING_STATUS);
268 if (result != WIFI_SUCCESS) {
269 ALOGE("Failed to create get ring status request; result = %d", result);
270 return result;
271 }
272 break;
273 }
274
275 case GET_FEATURE:
276 {
277 result = request.create(GOOGLE_OUI, LOGGER_GET_FEATURE);
278 if (result != WIFI_SUCCESS) {
279 ALOGE("Failed to create get feature request; result = %d", result);
280 return result;
281 }
282 break;
283 }
284
285 case START_RING_LOG:
286 result = createRingRequest(request);
287 break;
288
289 default:
290 ALOGE("Unknown Debug command");
291 result = WIFI_ERROR_UNKNOWN;
292 }
293 return result;
294 }
295
start()296 int start() {
297 // ALOGD("Start debug command");
298 WifiRequest request(familyId(), ifaceId());
299 int result = createRequest(request);
300 if (result != WIFI_SUCCESS) {
301 ALOGE("Failed to create debug request; result = %d", result);
302 return result;
303 }
304
305 result = requestResponse(request);
306 if (result != WIFI_SUCCESS) {
307 ALOGE("Failed to register debug response; result = %d", result);
308 }
309 return result;
310 }
311
handleResponse(WifiEvent & reply)312 virtual int handleResponse(WifiEvent& reply) {
313 ALOGD("In DebugCommand::handleResponse");
314
315 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
316 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
317 return NL_SKIP;
318 }
319
320 switch (mType) {
321 case GET_DRV_VER:
322 case GET_FW_VER:
323 {
324 void *data = reply.get_vendor_data();
325 int len = reply.get_vendor_data_len();
326
327 ALOGD("len = %d, expected len = %d", len, *mBuffSize);
328 memcpy(mBuff, data, min(len, *mBuffSize));
329 if (*mBuffSize < len)
330 return NL_SKIP;
331 *mBuffSize = len;
332 break;
333 }
334
335 case START_RING_LOG:
336 case GET_RING_DATA:
337 break;
338
339 case GET_RING_STATUS:
340 {
341 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
342 int len = reply.get_vendor_data_len();
343 wifi_ring_buffer_status *status(mStatus);
344
345 if (vendor_data == NULL || len == 0) {
346 ALOGE("No Debug data found");
347 return NL_SKIP;
348 }
349
350 nl_iterator it(vendor_data);
351 if (it.get_type() == LOGGER_ATTRIBUTE_RING_NUM) {
352 unsigned int num_rings = it.get_u32();
353 if (*mNumRings < num_rings) {
354 ALOGE("Not enough status buffers provided, available: %d required: %d",
355 *mNumRings, num_rings);
356 } else {
357 *mNumRings = num_rings;
358 }
359 } else {
360 ALOGE("Unknown attribute: %d expecting %d",
361 it.get_type(), LOGGER_ATTRIBUTE_RING_NUM);
362 return NL_SKIP;
363 }
364
365 it.next();
366 for (unsigned int i = 0; it.has_next() && i < *mNumRings; it.next()) {
367 if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
368 memcpy(status, it.get_data(), sizeof(wifi_ring_buffer_status));
369 i++;
370 status++;
371 } else {
372 ALOGW("Ignoring invalid attribute type = %d, size = %d",
373 it.get_type(), it.get_len());
374 }
375 }
376 break;
377 }
378
379 case GET_FEATURE:
380 {
381 void *data = reply.get_vendor_data();
382 int len = reply.get_vendor_data_len();
383
384 ALOGD("len = %d, expected len = %d", len, sizeof(unsigned int));
385 memcpy(mSupport, data, sizeof(unsigned int));
386 break;
387 }
388
389 default:
390 ALOGW("Unknown Debug command");
391 }
392 return NL_OK;
393 }
394
handleEvent(WifiEvent & event)395 virtual int handleEvent(WifiEvent& event) {
396 /* NO events! */
397 return NL_SKIP;
398 }
399 };
400
401 /* API to collect a firmware version string */
wifi_get_firmware_version(wifi_interface_handle iface,char * buffer,int buffer_size)402 wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
403 int buffer_size)
404 {
405 if (buffer && (buffer_size > 0)) {
406 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_FW_VER);
407 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
408 wifi_error result = (wifi_error)cmd->start();
409 cmd->releaseRef();
410 return result;
411 } else {
412 ALOGE("FW version buffer NULL");
413 return WIFI_ERROR_INVALID_ARGS;
414 }
415 }
416
417 /* API to collect a driver version string */
wifi_get_driver_version(wifi_interface_handle iface,char * buffer,int buffer_size)418 wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
419 {
420 if (buffer && (buffer_size > 0)) {
421 DebugCommand *cmd = new DebugCommand(iface, buffer, &buffer_size, GET_DRV_VER);
422 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
423 wifi_error result = (wifi_error)cmd->start();
424 cmd->releaseRef();
425 return result;
426 } else {
427 ALOGE("Driver version buffer NULL");
428 return WIFI_ERROR_INVALID_ARGS;
429 }
430 }
431
432 /* API to collect driver records */
wifi_get_ring_data(wifi_interface_handle iface,char * ring_name)433 wifi_error wifi_get_ring_data(wifi_interface_handle iface, char *ring_name)
434 {
435 DebugCommand *cmd = new DebugCommand(iface, ring_name, GET_RING_DATA);
436 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
437 wifi_error result = (wifi_error)cmd->start();
438 cmd->releaseRef();
439 return result;
440 }
441
442 /* 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)443 wifi_error wifi_get_ring_buffers_status(wifi_interface_handle iface,
444 u32 *num_rings, wifi_ring_buffer_status *status)
445 {
446 if (status && num_rings) {
447 DebugCommand *cmd = new DebugCommand(iface, num_rings, status, GET_RING_STATUS);
448 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
449 wifi_error result = (wifi_error)cmd->start();
450 cmd->releaseRef();
451 return result;
452 } else {
453 ALOGE("Ring status buffer NULL");
454 return WIFI_ERROR_INVALID_ARGS;
455 }
456 }
457
458 /* API to get supportable feature */
wifi_get_logger_supported_feature_set(wifi_interface_handle iface,unsigned int * support)459 wifi_error wifi_get_logger_supported_feature_set(wifi_interface_handle iface,
460 unsigned int *support)
461 {
462 if (support) {
463 DebugCommand *cmd = new DebugCommand(iface, support, GET_FEATURE);
464 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
465 wifi_error result = (wifi_error)cmd->start();
466 cmd->releaseRef();
467 return result;
468 } else {
469 ALOGE("Get support buffer NULL");
470 return WIFI_ERROR_INVALID_ARGS;
471 }
472 }
473
wifi_start_logging(wifi_interface_handle iface,u32 verbose_level,u32 flags,u32 max_interval_sec,u32 min_data_size,char * ring_name)474 wifi_error wifi_start_logging(wifi_interface_handle iface, u32 verbose_level,
475 u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
476 {
477 if (ring_name) {
478 DebugCommand *cmd = new DebugCommand(iface, verbose_level, flags, max_interval_sec,
479 min_data_size, ring_name, START_RING_LOG);
480 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
481 wifi_error result = (wifi_error)cmd->start();
482 cmd->releaseRef();
483 return result;
484 } else {
485 ALOGE("Ring name NULL");
486 return WIFI_ERROR_INVALID_ARGS;
487 }
488 }
489
490
491 ///////////////////////////////////////////////////////////////////////////////
492 class SetLogHandler : public WifiCommand
493 {
494 wifi_ring_buffer_data_handler mHandler;
495
496 public:
SetLogHandler(wifi_interface_handle iface,int id,wifi_ring_buffer_data_handler handler)497 SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
498 : WifiCommand("SetLogHandler", iface, id), mHandler(handler)
499 { }
500
start()501 int start() {
502 ALOGV("Register loghandler");
503 registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
504 return WIFI_SUCCESS;
505 }
506
cancel()507 virtual int cancel() {
508 /* Send a command to driver to stop generating logging events */
509 ALOGV("Clear loghandler");
510
511 /* unregister event handler */
512 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
513
514 WifiRequest request(familyId(), ifaceId());
515 int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
516 if (result != WIFI_SUCCESS) {
517 ALOGE("failed to create reset request; result = %d", result);
518 return result;
519 }
520
521 result = requestResponse(request);
522 if (result != WIFI_SUCCESS) {
523 ALOGE("failed to request reset; result = %d", result);
524 return result;
525 }
526
527 ALOGD("Success to clear loghandler");
528 return WIFI_SUCCESS;
529 }
530
handleEvent(WifiEvent & event)531 virtual int handleEvent(WifiEvent& event) {
532 char *buffer = NULL;
533 int buffer_size = 0;
534
535 // ALOGD("In SetLogHandler::handleEvent");
536 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
537 int len = event.get_vendor_data_len();
538 int event_id = event.get_vendor_subcmd();
539 // ALOGI("Got Logger event: %d", event_id);
540
541 if (vendor_data == NULL || len == 0) {
542 ALOGE("No Debug data found");
543 return NL_SKIP;
544 }
545
546 if(event_id == GOOGLE_DEBUG_RING_EVENT) {
547 wifi_ring_buffer_status status;
548 memset(&status, 0, sizeof(status));
549
550 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
551 if (it.get_type() == LOGGER_ATTRIBUTE_RING_STATUS) {
552 memcpy(&status, it.get_data(), sizeof(status));
553 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
554 buffer_size = it.get_len();
555 buffer = (char *)it.get_data();
556 } else {
557 ALOGW("Ignoring invalid attribute type = %d, size = %d",
558 it.get_type(), it.get_len());
559 }
560 }
561
562 // ALOGI("Retrieved Debug data");
563 if (mHandler.on_ring_buffer_data) {
564 (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,
565 &status);
566 }
567 } else {
568 ALOGE("Unknown Event");
569 return NL_SKIP;
570 }
571 return NL_OK;
572 }
573 };
574
wifi_set_log_handler(wifi_request_id id,wifi_interface_handle iface,wifi_ring_buffer_data_handler handler)575 wifi_error wifi_set_log_handler(wifi_request_id id, wifi_interface_handle iface,
576 wifi_ring_buffer_data_handler handler)
577 {
578 wifi_handle handle = getWifiHandle(iface);
579 ALOGV("Loghandler start, handle = %p", handle);
580
581 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
582 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
583 wifi_error result = wifi_register_cmd(handle, id, cmd);
584 if (result != WIFI_SUCCESS) {
585 cmd->releaseRef();
586 return result;
587 }
588 result = (wifi_error)cmd->start();
589 if (result != WIFI_SUCCESS) {
590 wifi_unregister_cmd(handle, id);
591 cmd->releaseRef();
592 return result;
593 }
594 return result;
595 }
596
wifi_reset_log_handler(wifi_request_id id,wifi_interface_handle iface)597 wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
598 {
599 wifi_handle handle = getWifiHandle(iface);
600 ALOGV("Loghandler reset, wifi_request_id = %d, handle = %p", id, handle);
601
602 if (id == -1) {
603 wifi_ring_buffer_data_handler handler;
604 memset(&handler, 0, sizeof(handler));
605
606 SetLogHandler *cmd = new SetLogHandler(iface, id, handler);
607 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
608 cmd->cancel();
609 cmd->releaseRef();
610 return WIFI_SUCCESS;
611 }
612
613 return wifi_cancel_cmd(id, iface);
614 }
615
616 ///////////////////////////////////////////////////////////////////////////////
617 class SetAlertHandler : public WifiCommand
618 {
619 wifi_alert_handler mHandler;
620 int mBuffSize;
621 char *mBuff;
622 int mErrCode;
623
624 public:
SetAlertHandler(wifi_interface_handle iface,int id,wifi_alert_handler handler)625 SetAlertHandler(wifi_interface_handle iface, int id, wifi_alert_handler handler)
626 : WifiCommand("SetAlertHandler", iface, id), mHandler(handler), mBuffSize(0), mBuff(NULL),
627 mErrCode(0)
628 { }
629
start()630 int start() {
631 ALOGV("Start Alerting");
632 registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
633 return WIFI_SUCCESS;
634 }
635
cancel()636 virtual int cancel() {
637 ALOGV("Clear alerthandler");
638
639 /* unregister alert handler */
640 unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT);
641 wifi_unregister_cmd(wifiHandle(), id());
642 ALOGD("Success to clear alerthandler");
643 return WIFI_SUCCESS;
644 }
645
handleResponse(WifiEvent & reply)646 virtual int handleResponse(WifiEvent& reply) {
647 ALOGD("In SetAlertHandler::handleResponse");
648
649 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
650 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
651 return NL_SKIP;
652 }
653
654 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
655 int len = reply.get_vendor_data_len();
656
657 ALOGD("len = %d", len);
658 if (vendor_data == NULL || len == 0) {
659 ALOGE("no vendor data in memory dump response; ignoring it");
660 return NL_SKIP;
661 }
662
663 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
664 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
665 ALOGI("Initiating alert callback");
666 if (mHandler.on_alert) {
667 (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
668 }
669 if (mBuff) {
670 free(mBuff);
671 mBuff = NULL;
672 }
673 }
674 }
675 return NL_OK;
676 }
677
handleEvent(WifiEvent & event)678 virtual int handleEvent(WifiEvent& event) {
679 wifi_ring_buffer_id ring_id;
680 char *buffer = NULL;
681 int buffer_size = 0;
682
683
684 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
685 int len = event.get_vendor_data_len();
686 int event_id = event.get_vendor_subcmd();
687 ALOGI("Got event: %d", event_id);
688
689 if (vendor_data == NULL || len == 0) {
690 ALOGE("No Debug data found");
691 return NL_SKIP;
692 }
693
694 if (event_id == GOOGLE_DEBUG_MEM_DUMP_EVENT) {
695 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
696 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
697 mBuffSize = it.get_u32();
698 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
699 buffer_size = it.get_len();
700 buffer = (char *)it.get_data();
701 /*
702 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_ERR_CODE) {
703 mErrCode = it.get_u32();
704 */
705 } else {
706 ALOGW("Ignoring invalid attribute type = %d, size = %d",
707 it.get_type(), it.get_len());
708 }
709 }
710 if (mBuffSize) {
711 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
712 if (mBuff) free(mBuff);
713 mBuff = (char *)malloc(mBuffSize + buffer_size);
714 if (!mBuff) {
715 ALOGE("Buffer allocation failed");
716 return NL_SKIP;
717 }
718 memcpy(mBuff, buffer, buffer_size);
719
720 WifiRequest request(familyId(), ifaceId());
721 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
722 if (result != WIFI_SUCCESS) {
723 ALOGE("Failed to create get memory dump request; result = %d", result);
724 free(mBuff);
725 return NL_SKIP;
726 }
727 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
728 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
729 if (result != WIFI_SUCCESS) {
730 ALOGE("Failed to put get memory dump request; result = %d", result);
731 return result;
732 }
733
734 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA,
735 (uint64_t)(mBuff+buffer_size));
736 if (result != WIFI_SUCCESS) {
737 ALOGE("Failed to put get memory dump request; result = %d", result);
738 return result;
739 }
740
741 request.attr_end(data);
742 mBuffSize += buffer_size;
743
744 result = requestResponse(request);
745
746 if (result != WIFI_SUCCESS) {
747 ALOGE("Failed to register get momory dump response; result = %d", result);
748 }
749 } else {
750 ALOGE("dump event missing dump length attribute");
751 return NL_SKIP;
752 }
753 }
754 return NL_OK;
755 }
756 };
757
wifi_set_alert_handler(wifi_request_id id,wifi_interface_handle iface,wifi_alert_handler handler)758 wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
759 wifi_alert_handler handler)
760 {
761 wifi_handle handle = getWifiHandle(iface);
762 ALOGV("Alerthandler start, handle = %p", handle);
763
764 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
765 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
766 wifi_error result = wifi_register_cmd(handle, id, cmd);
767 if (result != WIFI_SUCCESS) {
768 cmd->releaseRef();
769 return result;
770 }
771 result = (wifi_error)cmd->start();
772 if (result != WIFI_SUCCESS) {
773 wifi_unregister_cmd(handle, id);
774 cmd->releaseRef();
775 return result;
776 }
777 return result;
778 }
779
wifi_reset_alert_handler(wifi_request_id id,wifi_interface_handle iface)780 wifi_error wifi_reset_alert_handler(wifi_request_id id, wifi_interface_handle iface)
781 {
782 wifi_handle handle = getWifiHandle(iface);
783 ALOGV("Alerthandler reset, wifi_request_id = %d, handle = %p", id, handle);
784
785 if (id == -1) {
786 wifi_alert_handler handler;
787 memset(&handler, 0, sizeof(handler));
788
789 SetAlertHandler *cmd = new SetAlertHandler(iface, id, handler);
790 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
791 cmd->cancel();
792 cmd->releaseRef();
793 return WIFI_SUCCESS;
794 }
795
796 return wifi_cancel_cmd(id, iface);
797 }
798
799 ///////////////////////////////////////////////////////////////////////////////
800 class MemoryDumpCommand: public WifiCommand
801 {
802 wifi_firmware_memory_dump_handler mHandler;
803 int mBuffSize;
804 char *mBuff;
805
806 public:
MemoryDumpCommand(wifi_interface_handle iface,wifi_firmware_memory_dump_handler handler)807 MemoryDumpCommand(wifi_interface_handle iface, wifi_firmware_memory_dump_handler handler)
808 : WifiCommand("MemoryDumpCommand", iface, 0), mHandler(handler), mBuffSize(0), mBuff(NULL)
809 { }
810
start()811 int start() {
812 ALOGD("Start memory dump command");
813 WifiRequest request(familyId(), ifaceId());
814
815 int result = request.create(GOOGLE_OUI, LOGGER_TRIGGER_MEM_DUMP);
816 if (result != WIFI_SUCCESS) {
817 ALOGE("Failed to create trigger fw memory dump request; result = %d", result);
818 return result;
819 }
820
821 result = requestResponse(request);
822 if (result != WIFI_SUCCESS) {
823 ALOGE("Failed to register trigger memory dump response; result = %d", result);
824 }
825 return result;
826 }
827
handleResponse(WifiEvent & reply)828 virtual int handleResponse(WifiEvent& reply) {
829 ALOGD("In MemoryDumpCommand::handleResponse");
830
831 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
832 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
833 return NL_SKIP;
834 }
835
836 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
837 int len = reply.get_vendor_data_len();
838
839 ALOGD("len = %d", len);
840 if (vendor_data == NULL || len == 0) {
841 ALOGE("no vendor data in memory dump response; ignoring it");
842 return NL_SKIP;
843 }
844
845 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
846 if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_LEN) {
847 mBuffSize = it.get_u32();
848
849 if (mBuff)
850 free(mBuff);
851 mBuff = (char *)malloc(mBuffSize);
852 if (!mBuff) {
853 ALOGE("Buffer allocation failed");
854 return NL_SKIP;
855 }
856 WifiRequest request(familyId(), ifaceId());
857 int result = request.create(GOOGLE_OUI, LOGGER_GET_MEM_DUMP);
858 if (result != WIFI_SUCCESS) {
859 ALOGE("Failed to create get memory dump request; result = %d", result);
860 free(mBuff);
861 return NL_SKIP;
862 }
863
864 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
865 result = request.put_u32(LOGGER_ATTRIBUTE_FW_DUMP_LEN, mBuffSize);
866 if (result != WIFI_SUCCESS) {
867 ALOGE("Failed to put get memory dump request; result = %d", result);
868 return result;
869 }
870
871 result = request.put_u64(LOGGER_ATTRIBUTE_FW_DUMP_DATA, (uint64_t)mBuff);
872 if (result != WIFI_SUCCESS) {
873 ALOGE("Failed to put get memory dump request; result = %d", result);
874 return result;
875 }
876 request.attr_end(data);
877
878 result = requestResponse(request);
879 if (result != WIFI_SUCCESS) {
880 ALOGE("Failed to register get momory dump response; result = %d", result);
881 }
882 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_DUMP_DATA) {
883 ALOGI("Initiating memory dump callback");
884 if (mHandler.on_firmware_memory_dump) {
885 (*mHandler.on_firmware_memory_dump)(mBuff, mBuffSize);
886 }
887 if (mBuff) {
888 free(mBuff);
889 mBuff = NULL;
890 }
891 } else {
892 ALOGW("Ignoring invalid attribute type = %d, size = %d",
893 it.get_type(), it.get_len());
894 }
895 }
896 return NL_OK;
897 }
898
handleEvent(WifiEvent & event)899 virtual int handleEvent(WifiEvent& event) {
900 /* NO events! */
901 return NL_SKIP;
902 }
903 };
904
905 /* 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)906 wifi_error wifi_get_firmware_memory_dump( wifi_interface_handle iface,
907 wifi_firmware_memory_dump_handler handler)
908 {
909 MemoryDumpCommand *cmd = new MemoryDumpCommand(iface, handler);
910 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
911 wifi_error result = (wifi_error)cmd->start();
912 cmd->releaseRef();
913 return result;
914 }
915
916 class PacketFateCommand: public WifiCommand
917 {
918 void *mReportBufs;
919 size_t mNoReqFates;
920 size_t *mNoProvidedFates;
921 PktFateReqType mReqType;
922
923 public:
PacketFateCommand(wifi_interface_handle handle)924 PacketFateCommand(wifi_interface_handle handle)
925 : WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START)
926 { }
927
PacketFateCommand(wifi_interface_handle handle,wifi_tx_report * tx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)928 PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
929 size_t n_requested_fates, size_t *n_provided_fates)
930 : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(tx_report_bufs),
931 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
932 mReqType(TX_PACKET_FATE)
933 { }
934
PacketFateCommand(wifi_interface_handle handle,wifi_rx_report * rx_report_bufs,size_t n_requested_fates,size_t * n_provided_fates)935 PacketFateCommand(wifi_interface_handle handle, wifi_rx_report *rx_report_bufs,
936 size_t n_requested_fates, size_t *n_provided_fates)
937 : WifiCommand("PacketFateCommand", handle, 0), mReportBufs(rx_report_bufs),
938 mNoReqFates(n_requested_fates), mNoProvidedFates(n_provided_fates),
939 mReqType(RX_PACKET_FATE)
940 { }
941
createRequest(WifiRequest & request)942 int createRequest(WifiRequest& request) {
943 if (mReqType == TX_PACKET_FATE) {
944 ALOGD("%s Get Tx packet fate request\n", __FUNCTION__);
945 return createTxPktFateRequest(request);
946 } else if (mReqType == RX_PACKET_FATE) {
947 ALOGD("%s Get Rx packet fate request\n", __FUNCTION__);
948 return createRxPktFateRequest(request);
949 } else if (mReqType == PACKET_MONITOR_START) {
950 ALOGD("%s Monitor packet fate request\n", __FUNCTION__);
951 return createMonitorPktFateRequest(request);
952 } else {
953 ALOGE("%s Unknown packet fate request\n", __FUNCTION__);
954 return WIFI_ERROR_NOT_SUPPORTED;
955 }
956 return WIFI_SUCCESS;
957 }
958
createMonitorPktFateRequest(WifiRequest & request)959 int createMonitorPktFateRequest(WifiRequest& request) {
960 int result = request.create(GOOGLE_OUI, LOGGER_START_PKT_FATE_MONITORING);
961 if (result < 0) {
962 return result;
963 }
964
965 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
966 request.attr_end(data);
967 return result;
968 }
969
createTxPktFateRequest(WifiRequest & request)970 int createTxPktFateRequest(WifiRequest& request) {
971 int result = request.create(GOOGLE_OUI, LOGGER_GET_TX_PKT_FATES);
972 if (result < 0) {
973 return result;
974 }
975
976 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_tx_report)));
977 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
978 result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
979 if (result < 0) {
980 return result;
981 }
982 result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
983 if (result < 0) {
984 return result;
985 }
986 request.attr_end(data);
987 return result;
988 }
989
createRxPktFateRequest(WifiRequest & request)990 int createRxPktFateRequest(WifiRequest& request) {
991 int result = request.create(GOOGLE_OUI, LOGGER_GET_RX_PKT_FATES);
992 if (result < 0) {
993 return result;
994 }
995
996 memset(mReportBufs, 0, (mNoReqFates * sizeof(wifi_rx_report)));
997 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
998 result = request.put_u32(LOGGER_ATTRIBUTE_PKT_FATE_NUM, mNoReqFates);
999 if (result < 0) {
1000 return result;
1001 }
1002 result = request.put_u64(LOGGER_ATTRIBUTE_PKT_FATE_DATA, (uint64_t)mReportBufs);
1003 if (result < 0) {
1004 return result;
1005 }
1006 request.attr_end(data);
1007 return result;
1008 }
1009
start()1010 int start() {
1011 ALOGD("Start get packet fate command\n");
1012 WifiRequest request(familyId(), ifaceId());
1013
1014 int result = createRequest(request);
1015 if (result < 0) {
1016 ALOGE("Failed to create get pkt fate request; result = %d\n", result);
1017 return result;
1018 }
1019
1020 result = requestResponse(request);
1021 if (result != WIFI_SUCCESS) {
1022 ALOGE("Failed to register get pkt fate response; result = %d\n", result);
1023 }
1024 return result;
1025 }
1026
handleResponse(WifiEvent & reply)1027 int handleResponse(WifiEvent& reply) {
1028 ALOGD("In GetPktFateCommand::handleResponse\n");
1029
1030 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1031 ALOGI("Ignoring reply with cmd = %d", reply.get_cmd());
1032 return NL_SKIP;
1033 }
1034
1035 int id = reply.get_vendor_id();
1036 int subcmd = reply.get_vendor_subcmd();
1037 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1038 int len = reply.get_vendor_data_len();
1039
1040 ALOGI("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1041
1042 if (mReqType == TX_PACKET_FATE) {
1043 ALOGI("Response recieved for get TX pkt fate command\n");
1044 } else if (mReqType == RX_PACKET_FATE) {
1045 ALOGI("Response recieved for get RX pkt fate command\n");
1046 } else if (mReqType == PACKET_MONITOR_START) {
1047 ALOGI("Response recieved for monitor pkt fate command\n");
1048 return NL_OK;
1049 } else {
1050 ALOGE("Response recieved for unknown pkt fate command\n");
1051 return NL_SKIP;
1052 }
1053
1054 if (vendor_data == NULL || len == 0) {
1055 ALOGE("no vendor data in GetPktFateCommand response; ignoring it\n");
1056 return NL_SKIP;
1057 }
1058
1059 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1060 if (it.get_type() == LOGGER_ATTRIBUTE_PKT_FATE_NUM) {
1061 *mNoProvidedFates = it.get_u32();
1062 ALOGI("No: of pkt fates provided is %d\n", *mNoProvidedFates);
1063 } else {
1064 ALOGE("Ignoring invalid attribute type = %d, size = %d\n",
1065 it.get_type(), it.get_len());
1066 }
1067 }
1068
1069 return NL_OK;
1070 }
1071
handleEvent(WifiEvent & event)1072 int handleEvent(WifiEvent& event) {
1073 /* NO events to handle here! */
1074 return NL_SKIP;
1075 }
1076 };
1077
wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)1078 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
1079 {
1080 PacketFateCommand *cmd = new PacketFateCommand(handle);
1081 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1082 wifi_error result = (wifi_error)cmd->start();
1083 cmd->releaseRef();
1084 return result;
1085 }
1086
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)1087 wifi_error wifi_get_tx_pkt_fates(wifi_interface_handle handle,
1088 wifi_tx_report *tx_report_bufs, size_t n_requested_fates,
1089 size_t *n_provided_fates)
1090 {
1091 PacketFateCommand *cmd = new PacketFateCommand(handle, tx_report_bufs,
1092 n_requested_fates, n_provided_fates);
1093 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1094 wifi_error result = (wifi_error)cmd->start();
1095 cmd->releaseRef();
1096 return result;
1097 }
1098
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)1099 wifi_error wifi_get_rx_pkt_fates(wifi_interface_handle handle,
1100 wifi_rx_report *rx_report_bufs, size_t n_requested_fates,
1101 size_t *n_provided_fates)
1102 {
1103 PacketFateCommand *cmd = new PacketFateCommand(handle, rx_report_bufs,
1104 n_requested_fates, n_provided_fates);
1105 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1106 wifi_error result = (wifi_error)cmd->start();
1107 cmd->releaseRef();
1108 return result;
1109 }
1110