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 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 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 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 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 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 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 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 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 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 395 virtual int handleEvent(WifiEvent& event) { 396 /* NO events! */ 397 return NL_SKIP; 398 } 399 }; 400 401 /* API to collect a firmware version string */ 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 */ 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 */ 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 */ 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 */ 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 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: 497 SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler) 498 : WifiCommand("SetLogHandler", iface, id), mHandler(handler) 499 { } 500 501 int start() { 502 ALOGV("Register loghandler"); 503 registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT); 504 return WIFI_SUCCESS; 505 } 506 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 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 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 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: 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 630 int start() { 631 ALOGV("Start Alerting"); 632 registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_MEM_DUMP_EVENT); 633 return WIFI_SUCCESS; 634 } 635 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 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 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 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 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: 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 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 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 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 */ 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: 924 PacketFateCommand(wifi_interface_handle handle) 925 : WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START) 926 { } 927 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 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 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 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 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 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 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 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 1072 int handleEvent(WifiEvent& event) { 1073 /* NO events to handle here! */ 1074 return NL_SKIP; 1075 } 1076 }; 1077 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 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 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