Home | History | Annotate | Download | only in wifi_hal
      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