update wifi_hal and wpa_supplicant_8_lib
authorJan Altensen <info@stricted.net>
Sun, 24 Feb 2019 12:33:39 +0000 (13:33 +0100)
committerJan Altensen <info@stricted.net>
Sun, 24 Feb 2019 12:33:39 +0000 (13:33 +0100)
Change-Id: I2f0006f415546c1ae42cfa8c76404eea7e49d1df

12 files changed:
wifi_hal/Android.mk
wifi_hal/common.h
wifi_hal/cpp_bindings.cpp
wifi_hal/cpp_bindings.h
wifi_hal/gscan.cpp [deleted file]
wifi_hal/rtt.cpp [deleted file]
wifi_hal/wifi_hal.cpp
wifi_hal/wifi_logger.cpp [new file with mode: 0644]
wifi_hal/wifi_offload.cpp
wpa_supplicant_8_lib/Android.mk
wpa_supplicant_8_lib/mediatek_driver_cmd_nl80211.c
wpa_supplicant_8_lib/mediatek_driver_nl80211.h [new file with mode: 0644]

index 8a39c6091f9113d550d3a0a8d13f49fefcd9c125..48e6646c2f315dcee0f3af319890d8c89502de74 100644 (file)
@@ -24,10 +24,6 @@ LOCAL_CFLAGS += -Wno-unused-parameter -Wno-int-to-pointer-cast
 LOCAL_CFLAGS += -Wno-maybe-uninitialized -Wno-parentheses
 LOCAL_CPPFLAGS += -Wno-conversion-null
 
-ifeq ($(MTK_TC7_FEATURE), yes)
-LOCAL_CFLAGS += -DCONFIG_PNO_SUPPORT
-endif
-
 LOCAL_C_INCLUDES += \
        external/libnl/include \
        $(call include-path-for, libhardware_legacy)/hardware_legacy \
@@ -35,12 +31,12 @@ LOCAL_C_INCLUDES += \
 
 LOCAL_SRC_FILES := \
        wifi_hal.cpp \
-       rtt.cpp \
        common.cpp \
        cpp_bindings.cpp \
-       gscan.cpp \
+       wifi_logger.cpp \
        wifi_offload.cpp
 
+LOCAL_SHARED_LIBRARIES += libutils liblog
 LOCAL_MODULE := libwifi-hal-mt66xx
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_OWNER := mtk
index 34df2a4291264187c9c604b9719f9194d4bfeda0..46d9e43e51b783482a52d0994cb55b8868ce5517 100644 (file)
@@ -80,6 +80,12 @@ typedef enum {
 
     WIFI_SUBCMD_SET_RSSI_MONITOR,                     /* 0x0007 */
     /* Add more sub commands here */
+
+    WIFI_SUBCMD_GET_ROAMING_CAPABILITIES,             /* 0x0008 */
+    /* skip 0x0009 for diver set_roaming_policy */
+    WIFI_SUBCMD_CONFIG_ROAMING = 0x000a,              /* 0x000a */
+    WIFI_SUBCMD_ENABLE_ROAMING,                       /* 0x000b */
+    WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO,             /* 0x000c */
 } WIFI_SUB_COMMAND;
 
 typedef enum {
@@ -123,6 +129,15 @@ typedef enum {
     WIFI_ATTRIBUTE_MAX_RSSI,
     WIFI_ATTRIBUTE_MIN_RSSI,
     WIFI_ATTRIBUTE_RSSI_MONITOR_START,
+
+    WIFI_ATTRIBUTE_ROAMING_CAPABILITIES,
+    WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM,
+    WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID,
+    WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM,
+    WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID,
+    WIFI_ATTRIBUTE_ROAMING_STATE,
+
+    WIFI_ATTRIBUTE_TX_POWER_SCENARIO,
 } WIFI_ATTRIBUTE;
 
 typedef enum {
@@ -188,6 +203,7 @@ typedef struct {
 
 
     // add other details
+    wifi_roaming_capabilities roaming_capa;         // capabilities of roaming
 } hal_info;
 
 #define PNO_SSID_FOUND  0x1
index 62127f0fc41951559cff947363e24b5af7cccd7c..7fbaeba07f3857e5e76dde48ed8eb2469fbd9cab 100644 (file)
@@ -17,6 +17,7 @@
 #include <netlink/handlers.h>
 
 #include <ctype.h>
+#include <errno.h>
 
 #include "wifi_hal.h"
 #include "common.h"
@@ -582,6 +583,28 @@ static int no_seq_check(struct nl_msg *msg, void *arg)
        return NL_OK;
 }
 
+wifi_error WifiCommand::kernelErrorToWifiHalError(int kerr)
+{
+    if (kerr >= 0)
+        return WIFI_SUCCESS;
+
+    switch (kerr) {
+        case -EOPNOTSUPP:
+            return WIFI_ERROR_NOT_SUPPORTED;
+        case -EAGAIN:
+            return WIFI_ERROR_NOT_AVAILABLE;
+        case -EINVAL:
+            return WIFI_ERROR_INVALID_ARGS;
+        case -ETIMEDOUT:
+            return WIFI_ERROR_TIMED_OUT;
+        case -ENOMEM:
+            return WIFI_ERROR_OUT_OF_MEMORY;
+        case -EBUSY:
+            return WIFI_ERROR_BUSY;
+    }
+    return WIFI_ERROR_UNKNOWN;
+}
+
 int WifiCommand::requestResponse() {
     int err = create();
     if (err < 0) {
@@ -622,7 +645,7 @@ int WifiCommand::requestResponse(WifiRequest& request) {
         ALOGD("WifiCommand::requestResponse err=%d", err);
 out:
     nl_cb_put(cb);
-    return err;
+    return kernelErrorToWifiHalError(err);
 }
 
 int WifiCommand::requestEvent(int cmd) {
@@ -641,8 +664,10 @@ int WifiCommand::requestEvent(int cmd) {
     ALOGD("WifiCommand::requestEvent waiting for response %d", cmd);
 
     res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
-    if (res < 0)
+    if (res < 0) {
+        res = kernelErrorToWifiHalError(res);
         goto out;
+    }
 
     ALOGD("WifiCommand::requestEvent waiting for event");
     res = mCondition.wait();
@@ -666,8 +691,10 @@ int WifiCommand::requestVendorEvent(uint32_t id, int subcmd) {
         goto out;
 
     res = nl_send_auto_complete(mInfo->cmd_sock, mMsg.getMessage());
-    if (res < 0)
+    if (res < 0) {
+        res = kernelErrorToWifiHalError(res);
         goto out;
+    }
 
     res = mCondition.wait();
     if (res < 0)
index 7aaa481dc2afadcfbb0bc4e86a991d2564412d22..39a2bd549940615015931764da5247e1f3b7c169 100644 (file)
@@ -251,7 +251,7 @@ public:
     }
 
     virtual void addRef() {
-        int refs = __sync_add_and_fetch(&mRefs, 1);
+        __sync_add_and_fetch(&mRefs, 1);
         // ALOGD("addRef: WifiCommand %p has %d references", this, refs);
     }
 
@@ -280,6 +280,8 @@ public:
     int requestVendorEvent(uint32_t id, int subcmd);
     int requestResponse(WifiRequest& request);
 
+    wifi_error kernelErrorToWifiHalError(int kerr);
+
 protected:
     wifi_handle wifiHandle() {
         return getWifiHandle(mInfo);
diff --git a/wifi_hal/gscan.cpp b/wifi_hal/gscan.cpp
deleted file mode 100644 (file)
index 4f9c6bf..0000000
+++ /dev/null
@@ -1,1881 +0,0 @@
-
-#include <stdint.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <netlink/genl/genl.h>
-#include <netlink/genl/family.h>
-#include <netlink/genl/ctrl.h>
-#include <linux/rtnetlink.h>
-#include <netpacket/packet.h>
-#include <linux/filter.h>
-#include <linux/errqueue.h>
-
-#include <linux/pkt_sched.h>
-#include <netlink/object-api.h>
-#include <netlink/netlink.h>
-#include <netlink/socket.h>
-#include <netlink/handlers.h>
-
-#include "sync.h"
-
-#define LOG_TAG  "WifiHAL"
-
-#include <utils/Log.h>
-
-#include "wifi_hal.h"
-#include "common.h"
-#include "cpp_bindings.h"
-
-typedef enum {
-    GSCAN_ATTRIBUTE_CAPABILITIES = 1,
-
-    GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
-    GSCAN_ATTRIBUTE_BASE_PERIOD,
-    GSCAN_ATTRIBUTE_BUCKETS_BAND,
-    GSCAN_ATTRIBUTE_BUCKET_ID,
-    GSCAN_ATTRIBUTE_BUCKET_PERIOD,
-    GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
-    GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
-    GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
-    GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
-    GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
-
-    GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
-    GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE,            /* indicates no more results */
-    GSCAN_ATTRIBUTE_FLUSH_FEATURE,                    /* Flush all the configs */
-    GSCAN_ENABLE_FULL_SCAN_RESULTS,
-    GSCAN_ATTRIBUTE_REPORT_EVENTS,
-    /* Adaptive scan attributes */
-    GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT,
-    GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
-
-    GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
-    GSCAN_ATTRIBUTE_FLUSH_RESULTS,
-    GSCAN_ATTRIBUTE_SCAN_RESULTS,                     /* flat array of wifi_scan_result */
-    GSCAN_ATTRIBUTE_SCAN_ID,                          /* indicates scan number */
-    GSCAN_ATTRIBUTE_SCAN_FLAGS,                       /* indicates if scan was aborted */
-    GSCAN_ATTRIBUTE_AP_FLAGS,                         /* flags on significant change event */
-    GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK,
-
-    GSCAN_ATTRIBUTE_SSID = 40,
-    GSCAN_ATTRIBUTE_BSSID,
-    GSCAN_ATTRIBUTE_CHANNEL,
-    GSCAN_ATTRIBUTE_RSSI,
-    GSCAN_ATTRIBUTE_TIMESTAMP,
-    GSCAN_ATTRIBUTE_RTT,
-    GSCAN_ATTRIBUTE_RTTSD,
-
-    GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50,
-    GSCAN_ATTRIBUTE_RSSI_LOW,
-    GSCAN_ATTRIBUTE_RSSI_HIGH,
-    GSCAN_ATTRIBUTE_HOTLIST_ELEM,
-    GSCAN_ATTRIBUTE_HOTLIST_FLUSH,
-
-    GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60,
-    GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE,
-    GSCAN_ATTRIBUTE_MIN_BREACHING,
-    GSCAN_ATTRIBUTE_NUM_AP,                     /* TBD */
-    GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS,
-    GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH,
-
-    /* EPNO */
-    GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70,
-    GSCAN_ATTRIBUTE_EPNO_SSID,
-    GSCAN_ATTRIBUTE_EPNO_SSID_LEN,
-    GSCAN_ATTRIBUTE_EPNO_RSSI,
-    GSCAN_ATTRIBUTE_EPNO_FLAGS,
-    GSCAN_ATTRIBUTE_EPNO_AUTH,
-    GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
-    GSCAN_ATTRIBUTE_EPNO_FLUSH,
-
-    GSCAN_ATTRIBUTE_WHITELIST_SSID = 80,
-    GSCAN_ATTRIBUTE_NUM_WL_SSID,
-    GSCAN_ATTRIBUTE_WL_SSID_LEN,
-    GSCAN_ATTRIBUTE_WL_SSID_FLUSH,
-    GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM,
-    GSCAN_ATTRIBUTE_NUM_BSSID,
-    GSCAN_ATTRIBUTE_BSSID_PREF_LIST,
-    GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH,
-    GSCAN_ATTRIBUTE_BSSID_PREF,
-    GSCAN_ATTRIBUTE_RSSI_MODIFIER,
-
-    GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD = 90,
-    GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD,
-    GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR,
-    GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR,
-    GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST,
-    GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS,
-    GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER,
-    GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE,
-
-    /* BSSID blacklist */
-    GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH = 100,
-    GSCAN_ATTRIBUTE_BLACKLIST_BSSID,
-
-    /* ANQPO */
-    GSCAN_ATTRIBUTE_ANQPO_HS_LIST = 110,
-    GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE,
-    GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID,
-    GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM,
-    GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
-    GSCAN_ATTRIBUTE_ANQPO_HS_PLMN,
-
-    /* ePNO cfg */
-    GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR = 130,
-    GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
-    GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
-    GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
-    GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
-    GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
-    GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
-
-    GSCAN_ATTRIBUTE_MAX
-
-} GSCAN_ATTRIBUTE;
-
-// helper methods
-wifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface,
-         wifi_scan_result_handler handler);
-wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface);
-int wifi_handle_full_scan_event(wifi_request_id id, WifiEvent& event,
-         wifi_scan_result_handler handler);
-void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from);
-
-
-void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from)
-{
-    to->ts = from->ts;
-    to->channel = from->channel;
-    to->rssi = from->rssi;
-    to->rtt = from->rtt;
-    to->rtt_sd = from->rtt_sd;
-    to->beacon_period = from->beacon_period;
-    to->capability = from->capability;
-    memcpy(to->ssid, from->ssid, (DOT11_MAX_SSID_LEN+1));
-    memcpy(&to->bssid, &from->bssid, sizeof(mac_addr));
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-class GetCapabilitiesCommand : public WifiCommand
-{
-    wifi_gscan_capabilities *mCapabilities;
-public:
-    GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites)
-        : WifiCommand("GetCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
-    {
-        memset(mCapabilities, 0, sizeof(*mCapabilities));
-    }
-
-    virtual int create() {
-        ALOGD("[WIFI HAL]Creating message to get gscan capablities; handle=%p, iface=%d, ifname=%s",
-                mIfaceInfo->handle, mIfaceInfo->id, mIfaceInfo->name);
-
-        int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES);
-        if (ret < 0) {
-            return ret;
-        }
-
-        return ret;
-    }
-
-protected:
-    virtual int handleResponse(WifiEvent& reply) {
-
-        ALOGV("In GetCapabilities::handleResponse");
-
-        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
-            ALOGE("Ignoring reply with cmd = %d", reply.get_cmd());
-            return NL_SKIP;
-        }
-
-        int id = reply.get_vendor_id();
-        int subcmd = reply.get_vendor_subcmd();
-        int wiphy_id = reply.get_u32(NL80211_ATTR_WIPHY);
-        int if_id = reply.get_u32(NL80211_ATTR_IFINDEX);
-
-        struct nlattr *vendor_data = (struct nlattr *)reply.get_vendor_data();
-        int len = reply.get_vendor_data_len();
-        void *payload = NULL;
-        if (vendor_data->nla_type == GSCAN_ATTRIBUTE_CAPABILITIES) {
-            payload = nla_data(vendor_data);
-            len -= NLA_HDRLEN;
-        }
-
-        ALOGD("wiphy_id=%d, if_id=%d, Id=%0x, subcmd=%d, len=%d, expected len=%d",
-            wiphy_id, if_id, id, subcmd, len, sizeof(*mCapabilities));
-        if (payload)
-            memcpy(mCapabilities, payload, min(len, (int) sizeof(*mCapabilities)));
-
-        ALOGI("max_scan_cache_size=%d, %d, %d, %d, %d, %d, %d, %d, max_bssid_history_entries=%d",
-               mCapabilities->max_scan_cache_size, mCapabilities->max_scan_buckets,
-               mCapabilities->max_ap_cache_per_scan,
-               mCapabilities->max_rssi_sample_size,
-               mCapabilities->max_scan_reporting_threshold,
-               mCapabilities->max_hotlist_bssids,
-               mCapabilities->max_hotlist_ssids,
-               mCapabilities->max_significant_wifi_change_aps,
-               mCapabilities->max_bssid_history_entries);
-
-        /* this case wifi driver don't support GScan */
-        if (!(mCapabilities->max_scan_cache_size || mCapabilities->max_scan_buckets
-            || mCapabilities->max_ap_cache_per_scan))
-            return NL_STOP;
-
-        return NL_OK;
-    }
-};
-
-wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
-        wifi_gscan_capabilities *capabilities)
-{
-    GetCapabilitiesCommand command(handle, capabilities);
-    return (wifi_error) command.requestResponse();
-}
-
-class GetChannelListCommand : public WifiCommand
-{
-private:
-    wifi_channel *mChannels;
-    int mMaxChannels;
-    int *mNumOfChannel;
-    int mBand;
-
-public:
-    GetChannelListCommand(wifi_interface_handle handle, int band, int max_channels,
-        wifi_channel *channels, int *num_channels)
-        : WifiCommand("GetChannelListCommand", handle, 0)
-    {
-        mBand = band;
-        mMaxChannels = max_channels;
-        mChannels = channels;
-        mNumOfChannel = num_channels;
-        memset(mChannels, 0, sizeof(wifi_channel) * mMaxChannels);
-    }
-
-    virtual int create() {
-        ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id);
-
-        int ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_CHANNEL_LIST);
-        if (ret < 0) {
-            return ret;
-        }
-
-        ALOGI("In GetChannelList::mBand=%d", mBand);
-
-        nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
-        ret = mMsg.put_u32(WIFI_ATTRIBUTE_BAND, mBand);
-        if (ret < 0) {
-            return ret;
-        }
-
-        mMsg.attr_end(data);
-        return ret;
-    }
-
-protected:
-    virtual int handleResponse(WifiEvent& reply) {
-
-        ALOGV("In GetChannelList::handleResponse");
-
-        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
-            ALOGE("Ignore reply with cmd 0x%x", reply.get_cmd());
-            return NL_SKIP;
-        }
-
-        int vendor_id = reply.get_vendor_id();
-        int subcmd = reply.get_vendor_subcmd();
-        ALOGV("vendor_id = 0x%x, subcmd = 0x%x", vendor_id, subcmd);
-
-        nlattr *vendor = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
-        int len = reply.get_vendor_data_len();
-        if (vendor == NULL || len == 0) {
-            ALOGE("No vendor data in GetChannelList response, ignore it");
-            return NL_SKIP;
-        }
-
-        int num_channels = 0;
-        for (nl_iterator it(vendor); it.has_next(); it.next()) {
-            if (it.get_type() == WIFI_ATTRIBUTE_NUM_CHANNELS) {
-                num_channels = it.get_u32();
-                ALOGI("Get channel list with %d channels", num_channels);
-                if (num_channels > mMaxChannels)
-                    num_channels = mMaxChannels;
-                *mNumOfChannel = num_channels;
-            } else if (it.get_type() == WIFI_ATTRIBUTE_CHANNEL_LIST && num_channels) {
-                memcpy(mChannels, it.get_data(), sizeof(wifi_channel) * num_channels);
-            } else {
-                ALOGW("Ignore invalid attribute type = %d, size = %d",
-                        it.get_type(), it.get_len());
-            }
-        }
-
-        ALOGD("mChannels[0]=%d mChannels[1]=%d", *mChannels, *(mChannels + 1));
-
-        return NL_OK;
-    }
-};
-
-wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
-        int band, int max_channels, wifi_channel *channels, int *num_channels)
-{
-    GetChannelListCommand command(handle, band, max_channels, channels, num_channels);
-    return (wifi_error) command.requestResponse();
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-/* helper functions */
-
-static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr)
-{
-    memset(results, 0, sizeof(wifi_scan_result) * num);
-
-    int i = 0;
-    for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) {
-
-        int index = it.get_type();
-        ALOGI("retrieved scan result %d", index);
-        nlattr *sc_data = (nlattr *) it.get_data();
-        wifi_scan_result *result = results + i;
-
-        for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) {
-            int type = it2.get_type();
-            if (type == GSCAN_ATTRIBUTE_SSID) {
-                strncpy(result->ssid, (char *) it2.get_data(), it2.get_len());
-                result->ssid[it2.get_len()] = 0;
-            } else if (type == GSCAN_ATTRIBUTE_BSSID) {
-                memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr));
-            } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) {
-                result->ts = it2.get_u64();
-            } else if (type == GSCAN_ATTRIBUTE_CHANNEL) {
-                result->ts = it2.get_u16();
-            } else if (type == GSCAN_ATTRIBUTE_RSSI) {
-                result->rssi = it2.get_u8();
-            } else if (type == GSCAN_ATTRIBUTE_RTT) {
-                result->rtt = it2.get_u64();
-            } else if (type == GSCAN_ATTRIBUTE_RTTSD) {
-                result->rtt_sd = it2.get_u64();
-            }
-        }
-
-    }
-
-    if (i >= num) {
-        ALOGE("Got too many results; skipping some");
-    }
-
-    return i;
-}
-
-int createFeatureRequest(WifiRequest& request, int subcmd, int enable) {
-
-    int result = request.create(GOOGLE_OUI, subcmd);
-    if (result < 0) {
-        return result;
-    }
-
-    nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-    result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable);
-    if (result < 0) {
-        return result;
-    }
-
-    request.attr_end(data);
-    return WIFI_SUCCESS;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-class FullScanResultsCommand : public WifiCommand
-{
-    int *mParams;
-    wifi_scan_result_handler mHandler;
-public:
-    FullScanResultsCommand(wifi_interface_handle iface, int id, int *params,
-                wifi_scan_result_handler handler)
-        : WifiCommand("FullScanResultsCommand", iface, id), mParams(params), mHandler(handler)
-    { }
-
-    int createRequest(WifiRequest& request, int subcmd, int enable) {
-        int result = request.create(GOOGLE_OUI, subcmd);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable);
-        if (result < 0) {
-            return result;
-        }
-
-        request.attr_end(data);
-        return WIFI_SUCCESS;
-
-    }
-
-    int start() {
-        ALOGD("Enabling Full scan results");
-        WifiRequest request(familyId(), ifaceId());
-        int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create request; result = %d", result);
-            return result;
-        }
-
-        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
-
-        result = requestResponse(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to enable full scan results; result = %d", result);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
-            return result;
-        }
-
-        return result;
-    }
-
-    virtual int cancel() {
-        ALOGD("Disabling Full scan results");
-
-        WifiRequest request(familyId(), ifaceId());
-        int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create request; result = %d", result);
-        } else {
-            result = requestResponse(request);
-            if (result != WIFI_SUCCESS) {
-                ALOGE("failed to disable full scan results;result = %d", result);
-            }
-        }
-
-        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
-        return WIFI_SUCCESS;
-    }
-
-    virtual int handleResponse(WifiEvent& reply) {
-         ALOGD("Request complete!");
-        /* Nothing to do on response! */
-        return NL_SKIP;
-    }
-
-    virtual int handleEvent(WifiEvent& event) {
-        ALOGV("Full scan results:  Got an event");
-        return wifi_handle_full_scan_event(id(), event, mHandler);
-    }
-
-};
-/////////////////////////////////////////////////////////////////////////////
-
-class ScanCommand : public WifiCommand
-{
-    wifi_scan_cmd_params *mParams;
-    wifi_scan_result_handler mHandler;
-public:
-    ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params,
-                wifi_scan_result_handler handler)
-        : WifiCommand("ScanCommand", iface, id), mParams(params), mHandler(handler)
-    { }
-
-    int createSetupRequest(WifiRequest& request) {
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_CONFIG);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period);
-        if (result < 0) {
-            return result;
-        }
-
-        result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets);
-        if (result < 0) {
-            return result;
-        }
-
-        for (int i = 0; i < mParams->num_buckets; i++) {
-            nlattr * bucket = request.attr_start(i);    // next bucket
-            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period);
-            if (result < 0) {
-                return result;
-            }
-
-            /* parameter validity check */
-            if (mParams->buckets[i].band < WIFI_BAND_UNSPECIFIED
-                || mParams->buckets[i].band > WIFI_BAND_ABG_WITH_DFS)
-                mParams->buckets[i].band = WIFI_BAND_ABG; /* default 2.4G + 5G */
-            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND,
-                    mParams->buckets[i].band);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT,
-                    mParams->buckets[i].step_count);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
-                    mParams->buckets[i].max_period);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS,
-                    mParams->buckets[i].report_events);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
-                    mParams->buckets[i].num_channels);
-            if (result < 0) {
-                return result;
-            }
-
-            if (mParams->buckets[i].num_channels) {
-                nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS);
-                ALOGV(" channels: ");
-                for (int j = 0; j < mParams->buckets[i].num_channels; j++) {
-                    result = request.put_u32(j, mParams->buckets[i].channels[j].channel);
-                    ALOGV(" %u", mParams->buckets[i].channels[j].channel);
-
-                    if (result < 0) {
-                        return result;
-                    }
-                }
-                request.attr_end(channels);
-            }
-
-            request.attr_end(bucket);
-        }
-
-        request.attr_end(data);
-        return WIFI_SUCCESS;
-    }
-
-    int createScanConfigRequest(WifiRequest& request) {
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan);
-        if (result < 0) {
-            return result;
-        }
-
-        /* parameter validity check */
-        if (mParams->report_threshold_percent < 0 || mParams->report_threshold_percent > 100)
-            mParams->report_threshold_percent = 100;
-        result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
-                mParams->report_threshold_percent);
-        if (result < 0) {
-            return result;
-        }
-
-        int num_scans = mParams->report_threshold_num_scans;
-
-        result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans);
-        if (result < 0) {
-            return result;
-        }
-
-        request.attr_end(data);
-        return WIFI_SUCCESS;
-    }
-
-    int createStartRequest(WifiRequest& request) {
-        return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
-    }
-
-    int createStopRequest(WifiRequest& request) {
-        return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0);
-    }
-
-    int start() {
-        ALOGI("1) GScan Setting configuration: ");
-        WifiRequest request(familyId(), ifaceId());
-        int result = createSetupRequest(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create setup request; result = %d", result);
-            return result;
-        }
-
-        result = requestResponse(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to configure setup; result = %d", result);
-            return result;
-        }
-
-        request.destroy();
-
-        result = createScanConfigRequest(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create scan config request; result = %d", result);
-            return result;
-        }
-
-        result = requestResponse(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to configure scan; result = %d", result);
-            return result;
-        }
-
-        ALOGI("2) Enable GScan: ");
-
-        result = createStartRequest(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create start request; result = %d", result);
-            return result;
-        }
-
-        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
-        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
-        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
-
-        result = requestResponse(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to start scan; result = %d", result);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
-            return result;
-        }
-        return result;
-    }
-
-    virtual int cancel() {
-        ALOGI("Stopping GScan");
-
-        WifiRequest request(familyId(), ifaceId());
-        int result = createStopRequest(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create stop request; result = %d", result);
-        } else {
-            result = requestResponse(request);
-            if (result != WIFI_SUCCESS) {
-                ALOGE("failed to stop scan; result = %d", result);
-            }
-        }
-
-        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
-        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
-        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
-        return WIFI_SUCCESS;
-    }
-
-    virtual int handleResponse(WifiEvent& reply) {
-        /* Nothing to do on response! */
-        return NL_SKIP;
-    }
-
-    virtual int handleEvent(WifiEvent& event) {
-        ALOGV("[WIFI HAL]Got a GScan results event");
-
-        // event.log();
-
-        struct nlattr *vendor_data = (struct nlattr *)event.get_vendor_data();
-        int len = event.get_vendor_data_len();
-        int event_id = event.get_vendor_subcmd();
-
-        if (vendor_data)
-            ALOGV("vendor_data->nla_type=%d nla_len=%d, len=%d, event_id=%d",
-                vendor_data->nla_type, vendor_data->nla_len, len, event_id);
-
-        if ((event_id == GSCAN_EVENT_COMPLETE_SCAN) ||
-            (event_id == GSCAN_EVENT_SCAN_RESULTS_AVAILABLE)) {
-            if (vendor_data == NULL || vendor_data->nla_len != 8) {
-                ALOGE("Bad event data!");
-                return NL_SKIP;
-            }
-            wifi_scan_event evt_type;
-            evt_type = (wifi_scan_event) nla_get_u32(vendor_data);
-            ALOGI("Received event_id=%d, event type=%d", event_id, evt_type);
-            if (*mHandler.on_scan_event)
-                (*mHandler.on_scan_event)(id(), evt_type);
-        } else if (event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) {
-            wifi_handle_full_scan_event(id(), event, mHandler);
-        }
-        return NL_SKIP;
-    }
-};
-
-wifi_error wifi_start_gscan(
-        wifi_request_id id,
-        wifi_interface_handle iface,
-        wifi_scan_cmd_params params,
-        wifi_scan_result_handler handler)
-{
-    wifi_handle handle = getWifiHandle(iface);
-
-    ALOGD("[WIFI HAL]Starting GScan, halHandle = %p", handle);
-
-    ScanCommand *cmd = new ScanCommand(iface, id, &params, handler);
-    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-    wifi_error result = wifi_register_cmd(handle, id, cmd);
-    if (result != WIFI_SUCCESS) {
-        cmd->releaseRef();
-        return result;
-    }
-    result = (wifi_error)cmd->start();
-    if (result != WIFI_SUCCESS) {
-        wifi_unregister_cmd(handle, id);
-        cmd->releaseRef();
-        return result;
-    }
-    return result;
-}
-
-wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
-{
-    ALOGD("[WIFI HAL]Stopping GScan");
-    wifi_handle handle = getWifiHandle(iface);
-
-    if (id == -1) {
-        wifi_scan_result_handler handler;
-        wifi_scan_cmd_params dummy_params;
-        memset(&handler, 0, sizeof(handler));
-
-        ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
-        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-        cmd->cancel();
-        cmd->releaseRef();
-        return WIFI_SUCCESS;
-    }
-
-    return wifi_cancel_cmd(id, iface);
-}
-
-
-wifi_error wifi_enable_full_scan_results(
-        wifi_request_id id,
-        wifi_interface_handle iface,
-        wifi_scan_result_handler handler)
-{
-    wifi_handle handle = getWifiHandle(iface);
-    int params_dummy;
-    ALOGD("[WIFI HAL]Enabling full scan results, halHandle = %p", handle);
-
-    FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, &params_dummy, handler);
-    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-    wifi_error result = wifi_register_cmd(handle, id, cmd);
-    if (result != WIFI_SUCCESS) {
-        cmd->releaseRef();
-        return result;
-    }
-    result = (wifi_error)cmd->start();
-    if (result != WIFI_SUCCESS) {
-        wifi_unregister_cmd(handle, id);
-        cmd->releaseRef();
-        return result;
-    }
-    return result;
-}
-
-int wifi_handle_full_scan_event(
-        wifi_request_id id,
-        WifiEvent& event,
-        wifi_scan_result_handler handler)
-{
-    //nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
-    struct nlattr *vendor_data = (struct nlattr *)event.get_vendor_data();
-    unsigned int len = event.get_vendor_data_len();
-    int event_id = event.get_vendor_subcmd();
-
-    if (vendor_data == NULL || len < sizeof(wifi_gscan_full_result_t)) {
-        ALOGE("Full scan results: No scan results found");
-        return NL_SKIP;
-    }
-
-    wifi_gscan_full_result_t *drv_res = NULL;
-    if (event_id == GSCAN_EVENT_FULL_SCAN_RESULTS)
-        drv_res = (wifi_gscan_full_result_t *)nla_data(vendor_data);
-    if (!drv_res) {
-        ALOGE("cannot get vendor_data of GSCAN_EVENT_FULL_SCAN_RESULTS\n");
-        return NL_SKIP;
-    }
-    /* To protect against corrupted data, put a ceiling */
-    int ie_len = min(MAX_PROBE_RESP_IE_LEN, drv_res->ie_length);
-    wifi_scan_result *full_scan_result;
-    wifi_gscan_result_t *fixed = &drv_res->fixed;
-
-    if ((ie_len + offsetof(wifi_gscan_full_result_t, ie_data)) > len) {
-        ALOGE("BAD event data, len %d ie_len %d fixed length %lu!\n", len,
-            ie_len, offsetof(wifi_gscan_full_result_t, ie_data));
-        return NL_SKIP;
-    }
-    full_scan_result = (wifi_scan_result *) malloc((ie_len + offsetof(wifi_scan_result, ie_data)));
-    if (!full_scan_result) {
-        ALOGE("Full scan results: Can't malloc!\n");
-        return NL_SKIP;
-    }
-    convert_to_hal_result(full_scan_result, fixed);
-    full_scan_result->ie_length = ie_len;
-    memcpy(full_scan_result->ie_data, drv_res->ie_data, ie_len);
-    if(handler.on_full_scan_result)
-        handler.on_full_scan_result(id, full_scan_result, drv_res->scan_ch_bucket);
-
-    ALOGI("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %llu %llu %llu 0x%x %x %d\n",
-        fixed->ssid, fixed->bssid[0], fixed->bssid[1], fixed->bssid[2], fixed->bssid[3],
-        fixed->bssid[4], fixed->bssid[5], fixed->rssi, fixed->channel, fixed->ts,
-        fixed->rtt, fixed->rtt_sd, fixed->capability, drv_res->scan_ch_bucket, drv_res->ie_length);
-    free(full_scan_result);
-    return NL_SKIP;
-}
-
-wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface)
-{
-    ALOGD("[WIFI HAL]Disabling full scan results");
-    wifi_handle handle = getWifiHandle(iface);
-
-    if(id == -1) {
-        wifi_scan_result_handler handler;
-        wifi_handle handle = getWifiHandle(iface);
-        int params_dummy;
-
-        memset(&handler, 0, sizeof(handler));
-        FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, &params_dummy, handler);
-        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-        cmd->cancel();
-        cmd->releaseRef();
-        return WIFI_SUCCESS;
-    }
-
-    return wifi_cancel_cmd(id, iface);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-class GetScanResultsCommand : public WifiCommand {
-    wifi_cached_scan_results *mScans;
-    int mMax;
-    int *mNum;
-    int mRetrieved;
-    byte mFlush;
-    int mCompleted;
-public:
-    GetScanResultsCommand(wifi_interface_handle iface, byte flush,
-            wifi_cached_scan_results *results, int max, int *num)
-        : WifiCommand("GetScanResultsCommand", iface, -1), mScans(results), mMax(max), mNum(num),
-                mRetrieved(0), mFlush(flush), mCompleted(0)
-    { }
-
-    int createRequest(WifiRequest& request, int num, byte flush) {
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num);
-        if (result < 0) {
-            return result;
-        }
-
-        result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush);
-        if (result < 0) {
-            return result;
-        }
-
-        request.attr_end(data);
-        return WIFI_SUCCESS;
-    }
-
-    int execute() {
-        WifiRequest request(familyId(), ifaceId());
-        ALOGD("retrieving mMax=%d scan results", mMax);
-
-        for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
-            int num_to_retrieve = mMax - mRetrieved;
-            ALOGI("retrieving %d:%d cached gscan results in one shot", mRetrieved, num_to_retrieve);
-            int result = createRequest(request, num_to_retrieve, mFlush);
-            if (result < 0) {
-                ALOGE("failed to create request");
-                return result;
-            }
-
-            int prev_retrieved = mRetrieved;
-
-            result = requestResponse(request);
-
-            if (result != WIFI_SUCCESS) {
-                ALOGE("failed to retrieve scan results; result = %d", result);
-                return result;
-            }
-
-            ALOGD("mRetrieved=%d, prev_retrieved=%d, mCompleted=%d", mRetrieved, prev_retrieved, mCompleted);
-
-            if (mRetrieved == prev_retrieved || mCompleted) {
-                /* no more items left to retrieve */
-                break;
-            }
-
-            request.destroy();
-        }
-
-        ALOGI("GetScanResults total read %d results", mRetrieved);
-        *mNum = mRetrieved;
-        return WIFI_SUCCESS;
-    }
-
-    virtual int handleResponse(WifiEvent& reply) {
-        ALOGV("In GetScanResultsCommand::handleResponse");
-
-        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
-            ALOGE("Ignoring reply with cmd = %d", reply.get_cmd());
-            return NL_SKIP;
-        }
-
-        int id = reply.get_vendor_id();
-        int subcmd = reply.get_vendor_subcmd();
-
-        /*
-        if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) {
-            ALOGE("Invalid response to GetScanResultsCommand; ignoring it");
-            return NL_SKIP;
-        }
-        */
-
-        //nlattr *vendor = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
-        struct nlattr *vendor_data = (struct nlattr *)reply.get_vendor_data();
-        int len = reply.get_vendor_data_len();
-        if (vendor_data == NULL || len == 0) {
-            ALOGE("no vendor data in GetScanResults response; ignoring it");
-            return NL_SKIP;
-        }
-        ALOGD("Id = %0x, subcmd = %d, vendor=%p, get_vendor_data()=%p vendor->nla_type=%d len=%d",
-                id, subcmd, vendor_data, reply.get_vendor_data(), vendor_data->nla_type, len);
-
-        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
-            if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) {
-                mCompleted = it.get_u8();
-                ALOGI("retrieved mCompleted flag : %d", mCompleted);
-            } else if (it.get_type() >= GSCAN_ATTRIBUTE_NUM_OF_RESULTS
-                && it.get_type() <= GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK) {
-                int scan_id = 0, flags = 0, num = 0, scan_ch_bucket_mask = 0;
-                for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
-                    if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) {
-                        scan_id = it2.get_u32();
-                        ALOGD("retrieved scan_id : %d", scan_id);
-                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) {
-                        flags = it2.get_u8();
-                        ALOGD("retrieved scan_flags : 0x%0x", flags);
-                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) {
-                        num = it2.get_u32();
-                        ALOGD("retrieved num_results: %d", num);
-                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK) {
-                        scan_ch_bucket_mask = it2.get_u32();
-                        ALOGD("retrieved scan_ch_bucket_mask: 0x%0x", scan_ch_bucket_mask);
-                    } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS && num) {
-                        if (mRetrieved >= mMax) {
-                            ALOGW("Stored %d scans, ignoring excess results", mRetrieved);
-                            break;
-                        }
-                        num = min(num, (int)(it2.get_len()/sizeof(wifi_scan_result)));
-                        num = min(num, (int)MAX_AP_CACHE_PER_SCAN);
-                        ALOGI("Copying %d scan results, mRetrieved=%d, scan_id=%d, flag=0x%x, bktMask=0x%04x",
-                            num, mRetrieved, scan_id, flags, scan_ch_bucket_mask);
-                        wifi_gscan_result_t *results = (wifi_gscan_result_t *)it2.get_data();
-                        wifi_scan_result *mScanResults = mScans[mRetrieved].results;
-
-                        for (int i = 0; i < num; i++) {
-                            wifi_gscan_result_t *result = &results[i];
-                            convert_to_hal_result(&mScanResults[i], result);
-                            mScanResults[i].ie_length = result->ie_length;
-                            //mScanResults[i].ie_data = result->ie_data;
-                            ALOGD("%02d  %-32s  " MACSTR "  %ddB channel=%d, capa=0x%04x, ie_len=%d", i,
-                                result->ssid, MAC2STR(result->bssid),
-                                result->rssi, result->channel, mScanResults[i].capability, mScanResults[i].ie_length);
-                        }
-                        mScans[mRetrieved].scan_id = scan_id;
-                        mScans[mRetrieved].flags = flags;
-                        mScans[mRetrieved].num_results = num;
-                        mScans[mRetrieved].buckets_scanned = scan_ch_bucket_mask;
-                        ALOGV("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
-                        mRetrieved++;
-                    } else {
-                        ALOGW("Ignoring invalid attribute type = %d, size = %d",
-                                it.get_type(), it.get_len());
-                    }
-                }
-            } else {
-                ALOGW("Ignoring invalid attribute type = %d, size = %d",
-                        it.get_type(), it.get_len());
-            }
-        }
-        ALOGD("GetScanResults read %dth results", mRetrieved);
-        return NL_OK;
-    }
-};
-
-wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
-        int max, wifi_cached_scan_results *results, int *num) {
-
-    ALOGI("[WIFI HAL]Getting cached gscan results, flush=%d, max=%d, num=%d", flush, max, *num);
-
-    GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
-    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-    wifi_error err = (wifi_error) cmd->execute();
-    cmd->releaseRef();
-    return err;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-
-class BssidHotlistCommand : public WifiCommand
-{
-private:
-    wifi_bssid_hotlist_params mParams;
-    wifi_hotlist_ap_found_handler mHandler;
-    static const int MAX_RESULTS = 64;
-    wifi_scan_result mResults[MAX_RESULTS];
-public:
-    BssidHotlistCommand(wifi_interface_handle handle, int id,
-            wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
-        : WifiCommand("BssidHotlistCommand", handle, id), mParams(params), mHandler(handler)
-    { }
-
-    int createSetupRequest(WifiRequest& request) {
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
-        if (result < 0) {
-            return result;
-        }
-
-        result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_NUM_AP, mParams.num_bssid);
-        if (result < 0) {
-            return result;
-        }
-
-        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
-        for (int i = 0; i < mParams.num_bssid; i++) {
-            nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM);
-            if (attr2 == NULL) {
-                return WIFI_ERROR_OUT_OF_MEMORY;
-            }
-            result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
-            if (result < 0) {
-                return result;
-            }
-            request.attr_end(attr2);
-        }
-
-        request.attr_end(attr);
-        request.attr_end(data);
-        return result;
-    }
-
-    int createTeardownRequest(WifiRequest& request) {
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
-        if (result < 0) {
-            return result;
-        }
-
-        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
-        request.attr_end(attr);
-        request.attr_end(data);
-        return result;
-    }
-
-    int start() {
-        ALOGD("[WIFI HAL]Executing hotlist setup request, num = %d", mParams.num_bssid);
-        WifiRequest request(familyId(), ifaceId());
-        int result = createSetupRequest(request);
-        if (result < 0) {
-            return result;
-        }
-
-        result = requestResponse(request);
-        if (result < 0) {
-            ALOGI("Failed to execute hotlist setup request, result = %d", result);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
-            return result;
-        }
-
-        ALOGI("Successfully set %d APs in the hotlist", mParams.num_bssid);
-        result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
-        if (result < 0) {
-            return result;
-        }
-
-        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
-        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
-
-        result = requestResponse(request);
-        if (result < 0) {
-            ALOGE("failed to start scan; result = %d", result);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
-            return result;
-        }
-
-        ALOGI("successfully restarted the scan");
-        return result;
-    }
-
-    virtual int cancel() {
-        /* unregister event handler */
-        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
-        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
-        /* create set hotlist message with empty hotlist */
-        WifiRequest request(familyId(), ifaceId());
-        int result = createTeardownRequest(request);
-        if (result < 0) {
-            return result;
-        }
-
-        result = requestResponse(request);
-        if (result < 0) {
-            return result;
-        }
-
-        ALOGI("Successfully reset APs in current hotlist");
-        return result;
-    }
-
-    virtual int handleResponse(WifiEvent& reply) {
-        /* Nothing to do on response! */
-        return NL_SKIP;
-    }
-
-    virtual int handleEvent(WifiEvent& event) {
-        ALOGD("[WIFI HAL]Hotlist AP event");
-        int event_id = event.get_vendor_subcmd();
-        // event.log();
-
-        struct nlattr *vendor_data = (struct nlattr *)event.get_vendor_data();
-        int len = event.get_vendor_data_len();
-
-        if (vendor_data == NULL || len == 0) {
-            ALOGI("No scan results found");
-            return NL_SKIP;
-        }
-
-        memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS);
-
-        int num = len / sizeof(wifi_scan_result);
-        num = min(MAX_RESULTS, num);
-        ALOGD("hotlist APs num=%d, vendor len=%d, nla_len=%d nla_type=%d",
-                num, len, vendor_data->nla_len, vendor_data->nla_type);
-        if(vendor_data->nla_type == GSCAN_EVENT_HOTLIST_RESULTS_LOST
-           || vendor_data->nla_type == GSCAN_EVENT_HOTLIST_RESULTS_FOUND)
-            memcpy(mResults, nla_data(vendor_data), num * sizeof(wifi_scan_result));
-
-        if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) {
-            ALOGI("FOUND %d hotlist APs", num);
-            if (*mHandler.on_hotlist_ap_found)
-                (*mHandler.on_hotlist_ap_found)(id(), num, mResults);
-        } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) {
-            ALOGI("LOST %d hotlist APs", num);
-            if (*mHandler.on_hotlist_ap_lost)
-                (*mHandler.on_hotlist_ap_lost)(id(), num, mResults);
-        }
-        return NL_SKIP;
-    }
-};
-
-class ePNOCommand : public WifiCommand
-{
-private:
-    wifi_epno_params epno_params;
-    wifi_epno_handler mHandler;
-    wifi_scan_result mResults[MAX_EPNO_NETWORKS];
-public:
-    ePNOCommand(wifi_interface_handle handle, int id,
-            const wifi_epno_params *params, wifi_epno_handler handler)
-        : WifiCommand("ePNOCommand", handle, id), mHandler(handler)
-    {
-        if (params != NULL) {
-            memcpy(&epno_params, params, sizeof(wifi_epno_params));
-        } else {
-            memset(&epno_params, 0, sizeof(wifi_epno_params));
-        }
-    }
-
-    int createSetupRequest(WifiRequest& request) {
-        if (epno_params.num_networks > MAX_EPNO_NETWORKS) {
-            ALOGE("wrong epno num_networks:%d", epno_params.num_networks);
-            return WIFI_ERROR_INVALID_ARGS;
-        }
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
-        if (result < 0) {
-            return result;
-        }
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
-        if (result < 0) {
-            return result;
-        }
-
-        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR,
-                            (u8)epno_params.min5GHz_rssi);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
-                            (u8)epno_params.min24GHz_rssi);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
-                            epno_params.initial_score_max);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
-                            epno_params.current_connection_bonus);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
-                            epno_params.same_network_bonus);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
-                            epno_params.secure_bonus);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
-                            epno_params.band5GHz_bonus);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
-                        epno_params.num_networks);
-        if (result < 0) {
-            return result;
-        }
-        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST);
-        wifi_epno_network *ssid_list = epno_params.networks;
-        for (int i = 0; i < epno_params.num_networks; i++) {
-            nlattr *attr2 = request.attr_start(i);
-            if (attr2 == NULL) {
-                return WIFI_ERROR_OUT_OF_MEMORY;
-            }
-            result = request.put(GSCAN_ATTRIBUTE_EPNO_SSID, ssid_list[i].ssid, DOT11_MAX_SSID_LEN);
-            ALOGI("PNO network: SSID %s flags %x auth %x", ssid_list[i].ssid,
-                ssid_list[i].flags,
-                ssid_list[i].auth_bit_field);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_SSID_LEN, strlen(ssid_list[i].ssid));
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_FLAGS, ssid_list[i].flags);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_AUTH, ssid_list[i].auth_bit_field);
-            if (result < 0) {
-                return result;
-            }
-            request.attr_end(attr2);
-        }
-        request.attr_end(attr);
-        request.attr_end(data);
-        return result;
-    }
-
-    int createTeardownRequest(WifiRequest& request) {
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
-        if (result < 0) {
-            return result;
-        }
-        request.attr_end(data);
-        return result;
-    }
-
-    int start() {
-        ALOGI("Executing ePNO setup request, num = %d", epno_params.num_networks);
-        WifiRequest request(familyId(), ifaceId());
-        int result = createSetupRequest(request);
-        if (result < 0) {
-            return result;
-        }
-
-        result = requestResponse(request);
-        if (result < 0) {
-            ALOGI("Failed to execute ePNO setup request, result = %d", result);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
-            return result;
-        }
-
-        ALOGI("Successfully set %d SSIDs for ePNO", epno_params.num_networks);
-        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
-        ALOGI("successfully restarted the scan");
-        return result;
-    }
-
-    virtual int cancel() {
-        /* unregister event handler */
-        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
-        /* create set hotlist message with empty hotlist */
-        WifiRequest request(familyId(), ifaceId());
-        int result = createTeardownRequest(request);
-        if (result < 0) {
-            return result;
-        }
-
-        result = requestResponse(request);
-        if (result < 0) {
-            return result;
-        }
-
-        ALOGI("Successfully reset APs in current hotlist");
-        return result;
-    }
-
-    virtual int handleResponse(WifiEvent& reply) {
-        /* Nothing to do on response! */
-        return NL_SKIP;
-    }
-
-    virtual int handleEvent(WifiEvent& event) {
-        ALOGI("ePNO event");
-        int event_id = event.get_vendor_subcmd();
-        // event.log();
-
-        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
-        int len = event.get_vendor_data_len();
-
-        if (vendor_data == NULL || len == 0) {
-            ALOGI("No scan results found");
-            return NL_SKIP;
-        }
-
-        memset(mResults, 0, sizeof(wifi_scan_result) * MAX_EPNO_NETWORKS);
-
-        unsigned int num = len / sizeof(wifi_pno_result_t);
-        unsigned int i;
-        num = min(MAX_EPNO_NETWORKS, num);
-        wifi_pno_result_t *res = (wifi_pno_result_t *) event.get_vendor_data();
-        for (i = 0; i < num; i++) {
-            if (res[i].flags == PNO_SSID_FOUND) {
-                memcpy(mResults[i].ssid, res[i].ssid, res[i].ssid_len);
-                memcpy(mResults[i].bssid, res[i].bssid, sizeof(mac_addr));
-
-                mResults[i].ssid[res[i].ssid_len] = '\0';
-                mResults[i].channel = res[i].channel;
-                mResults[i].rssi = res[i].rssi;
-            }
-        }
-        if (*mHandler.on_network_found)
-            (*mHandler.on_network_found)(id(), num, mResults);
-        return NL_SKIP;
-    }
-};
-
-wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
-        wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
-{
-    wifi_handle handle = getWifiHandle(iface);
-
-    BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
-    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-    wifi_error result = wifi_register_cmd(handle, id, cmd);
-    if (result != WIFI_SUCCESS) {
-        cmd->releaseRef();
-        return result;
-    }
-    result = (wifi_error)cmd->start();
-    if (result != WIFI_SUCCESS) {
-        wifi_unregister_cmd(handle, id);
-        cmd->releaseRef();
-        return result;
-    }
-    return result;
-}
-
-wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
-{
-    return wifi_cancel_cmd(id, iface);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-class SignificantWifiChangeCommand : public WifiCommand
-{
-    typedef struct {
-        mac_addr bssid;                     // BSSID
-        wifi_channel channel;               // channel frequency in MHz
-        int num_rssi;                       // number of rssi samples
-        wifi_rssi rssi[8];                   // RSSI history in db
-    } wifi_significant_change_result_internal;
-
-private:
-    wifi_significant_change_params mParams;
-    wifi_significant_change_handler mHandler;
-    static const int MAX_RESULTS = 64;
-    wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS];
-    wifi_significant_change_result *mResults[MAX_RESULTS];
-public:
-    SignificantWifiChangeCommand(wifi_interface_handle handle, int id,
-            wifi_significant_change_params params, wifi_significant_change_handler handler)
-        : WifiCommand("SignificantWifiChangeCommand", handle, id), mParams(params),
-            mHandler(handler)
-    { }
-
-    int createSetupRequest(WifiRequest& request) {
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching);
-        if (result < 0) {
-            return result;
-        }
-        result = request.put_u16(GSCAN_ATTRIBUTE_NUM_AP, mParams.num_bssid);
-        if (result < 0) {
-            return result;
-        }
-
-        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS);
-
-        for (int i = 0; i < mParams.num_bssid; i++) {
-            nlattr *attr2 = request.attr_start(i);
-            if (attr2 == NULL) {
-                return WIFI_ERROR_OUT_OF_MEMORY;
-            }
-            result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
-            if (result < 0) {
-                return result;
-            }
-            request.attr_end(attr2);
-        }
-
-        request.attr_end(attr);
-        request.attr_end(data);
-
-        return result;
-    }
-
-    int createTeardownRequest(WifiRequest& request) {
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
-        if (result < 0) {
-            return result;
-        }
-
-        request.attr_end(data);
-        return result;
-    }
-
-    int start() {
-        ALOGD("[WIFI HAL]Set significant wifi change config");
-        WifiRequest request(familyId(), ifaceId());
-
-        int result = createSetupRequest(request);
-        if (result < 0) {
-            return result;
-        }
-
-        result = requestResponse(request);
-        if (result < 0) {
-            ALOGE("failed to set significant wifi change config %d", result);
-            return result;
-        }
-
-        ALOGI("successfully set significant wifi change config");
-
-        result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
-        if (result < 0) {
-            return result;
-        }
-
-        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
-
-        result = requestResponse(request);
-        if (result < 0) {
-            ALOGE("failed to start scan; result = %d", result);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
-            return result;
-        }
-
-        ALOGI("successfully restarted the scan");
-        return result;
-    }
-
-    virtual int cancel() {
-        /* unregister event handler */
-        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
-
-        /* create set significant change monitor message with empty hotlist */
-        WifiRequest request(familyId(), ifaceId());
-
-        int result = createTeardownRequest(request);
-        if (result < 0) {
-            return result;
-        }
-
-        result = requestResponse(request);
-        if (result < 0) {
-            return result;
-        }
-
-        ALOGI("successfully reset significant wifi change config");
-        return result;
-    }
-
-    virtual int handleResponse(WifiEvent& reply) {
-        /* Nothing to do on response! */
-        return NL_SKIP;
-    }
-
-    virtual int handleEvent(WifiEvent& event) {
-        ALOGD("[WIFI HAL]Got a significant wifi change event");
-
-        struct nlattr *vendor_data = (struct nlattr *)event.get_vendor_data();
-        int len = event.get_vendor_data_len();
-
-        if (vendor_data == NULL || len == 0) {
-            ALOGI("No scan results found");
-            return NL_SKIP;
-        }
-
-        typedef struct {
-            uint16_t flags;
-            uint16_t channel;
-            mac_addr bssid;
-            s8 rssi_history[8];
-        } ChangeInfo;
-
-        int num = min(len / sizeof(ChangeInfo), MAX_RESULTS);
-        ChangeInfo *ci;
-        if (vendor_data->nla_type == GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS)
-            ci = (ChangeInfo *)nla_data(vendor_data);
-        else
-            return NL_SKIP;
-
-        for (int i = 0; i < num; i++) {
-            memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr));
-            mResultsBuffer[i].channel = ci[i].channel;
-            mResultsBuffer[i].num_rssi = 8;
-            for (int j = 0; j < mResultsBuffer[i].num_rssi; j++)
-                mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j];
-            mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
-        }
-
-        ALOGI("Retrieved %d scan results, vendor len=%d nla_type=%d", num, len, vendor_data->nla_type);
-
-        if (num != 0) {
-            (*mHandler.on_significant_change)(id(), num, mResults);
-        } else {
-            ALOGW("No significant change reported");
-        }
-
-        return NL_SKIP;
-    }
-};
-
-wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface,
-        wifi_significant_change_params params, wifi_significant_change_handler handler)
-{
-    wifi_handle handle = getWifiHandle(iface);
-
-    SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
-            iface, id, params, handler);
-    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-    wifi_error result = wifi_register_cmd(handle, id, cmd);
-    if (result != WIFI_SUCCESS) {
-        cmd->releaseRef();
-        return result;
-    }
-    result = (wifi_error)cmd->start();
-    if (result != WIFI_SUCCESS) {
-        wifi_unregister_cmd(handle, id);
-        cmd->releaseRef();
-        return result;
-    }
-    return result;
-}
-
-wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
-{
-    return wifi_cancel_cmd(id, iface);
-}
-
-wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
-{
-    if (id == -1) {
-        wifi_epno_handler handler;
-        wifi_handle handle = getWifiHandle(iface);
-
-        memset(&handler, 0, sizeof(handler));
-        ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler);
-        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-        cmd->cancel();
-        cmd->releaseRef();
-        return WIFI_SUCCESS;
-    }
-    return wifi_cancel_cmd(id, iface);
-}
-
-wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface,
-        const wifi_epno_params *params, wifi_epno_handler handler)
-{
-    wifi_handle handle = getWifiHandle(iface);
-
-    ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler);
-    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-    wifi_error result = wifi_register_cmd(handle, id, cmd);
-    if (result != WIFI_SUCCESS) {
-        cmd->releaseRef();
-        return result;
-    }
-    result = (wifi_error)cmd->start();
-    if (result != WIFI_SUCCESS) {
-        wifi_unregister_cmd(handle, id);
-        cmd->releaseRef();
-        return result;
-    }
-    return result;
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-
-class AnqpoConfigureCommand : public WifiCommand
-{
-    int num_hs;
-    wifi_passpoint_network *mNetworks;
-    wifi_passpoint_event_handler mHandler;
-    wifi_scan_result *mResult;
-public:
-    AnqpoConfigureCommand(wifi_request_id id, wifi_interface_handle iface,
-        int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler)
-        : WifiCommand("AnqpoConfigureCommand", iface, id), num_hs(num), mNetworks(hs_list),
-            mHandler(handler)
-    {
-        mResult = NULL;
-    }
-
-    int createRequest(WifiRequest& request, int val) {
-
-        int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_ANQPO_CONFIG);
-        result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, num_hs);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-
-        struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST);
-        for (int i = 0; i < num_hs; i++) {
-            nlattr *attr2 = request.attr_start(i);
-            if (attr2 == NULL) {
-                return WIFI_ERROR_OUT_OF_MEMORY;
-            }
-            result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, mNetworks[i].id);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, mNetworks[i].realm, 256);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
-                         mNetworks[i].roamingConsortiumIds, 128);
-            if (result < 0) {
-                return result;
-            }
-            result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, mNetworks[i].plmn, 3);
-            if (result < 0) {
-                return result;
-            }
-
-            request.attr_end(attr2);
-        }
-
-        request.attr_end(attr);
-        request.attr_end(data);
-
-        return WIFI_SUCCESS;
-    }
-
-    int start() {
-
-        WifiRequest request(familyId(), ifaceId());
-        int result = createRequest(request, num_hs);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create request; result = %d", result);
-            return result;
-        }
-
-        registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
-
-        result = requestResponse(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to set ANQPO networks; result = %d", result);
-            unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
-            return result;
-        }
-
-        return result;
-    }
-
-    virtual int cancel() {
-
-        WifiRequest request(familyId(), ifaceId());
-        int result = createRequest(request, 0);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create request; result = %d", result);
-        } else {
-            result = requestResponse(request);
-            if (result != WIFI_SUCCESS) {
-                ALOGE("failed to reset ANQPO networks;result = %d", result);
-            }
-        }
-
-        unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
-        return WIFI_SUCCESS;
-    }
-
-    virtual int handleResponse(WifiEvent& reply) {
-         ALOGD("Request complete!");
-        /* Nothing to do on response! */
-        return NL_SKIP;
-    }
-
-    virtual int handleEvent(WifiEvent& event) {
-        typedef struct {
-            u16 channel;        /* channel of GAS protocol */
-            u8  dialog_token;   /* GAS dialog token */
-            u8  fragment_id;    /* fragment id */
-            u16 status_code;    /* status code on GAS completion */
-            u16 data_len;       /* length of data to follow */
-            u8  data[1];        /* variable length specified by data_len */
-        } wifi_anqp_gas_resp;
-
-        ALOGI("ANQPO hotspot matched event!");
-
-        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
-        unsigned int len = event.get_vendor_data_len();
-
-        if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
-            ALOGI("No scan results found");
-            return NL_SKIP;
-        }
-        mResult = (wifi_scan_result *)malloc(sizeof(wifi_scan_result));
-        if (!mResult) {
-            return NL_SKIP;
-        }
-        wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data();
-        wifi_gscan_result_t *fixed = &drv_res->fixed;
-        convert_to_hal_result(mResult, fixed);
-
-        byte *anqp = (byte *)drv_res + offsetof(wifi_gscan_full_result_t, ie_data) + drv_res->ie_length;
-        wifi_anqp_gas_resp *gas = (wifi_anqp_gas_resp *)anqp;
-        int anqp_len = offsetof(wifi_anqp_gas_resp, data) + gas->data_len;
-        int networkId = *(int *)((byte *)anqp + anqp_len);
-
-        ALOGI("%-32s\t", mResult->ssid);
-
-        ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1],
-                mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]);
-
-        ALOGI("%d\t", mResult->rssi);
-        ALOGI("%d\t", mResult->channel);
-        ALOGI("%lld\t", mResult->ts);
-        ALOGI("%lld\t", mResult->rtt);
-        ALOGI("%lld\n", mResult->rtt_sd);
-
-        if(*mHandler.on_passpoint_network_found)
-            (*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp);
-        free(mResult);
-        return NL_SKIP;
-    }
-};
-
-wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num,
-        wifi_passpoint_network *networks, wifi_passpoint_event_handler handler)
-{
-    wifi_handle handle = getWifiHandle(iface);
-
-    AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler);
-    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-    wifi_error result = wifi_register_cmd(handle, id, cmd);
-    if (result != WIFI_SUCCESS) {
-        cmd->releaseRef();
-        return result;
-    }
-    result = (wifi_error)cmd->start();
-    if (result != WIFI_SUCCESS) {
-        wifi_unregister_cmd(handle, id);
-        cmd->releaseRef();
-        return result;
-    }
-    return result;
-}
-
-wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
-{
-    return wifi_cancel_cmd(id, iface);
-}
-
diff --git a/wifi_hal/rtt.cpp b/wifi_hal/rtt.cpp
deleted file mode 100644 (file)
index a3ecb7e..0000000
+++ /dev/null
@@ -1,697 +0,0 @@
-#include <stdint.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <netlink/genl/genl.h>
-#include <netlink/genl/family.h>
-#include <netlink/genl/ctrl.h>
-#include <linux/rtnetlink.h>
-#include <netpacket/packet.h>
-#include <linux/filter.h>
-#include <linux/errqueue.h>
-
-#include <linux/pkt_sched.h>
-#include <netlink/object-api.h>
-#include <netlink/netlink.h>
-#include <netlink/socket.h>
-
-#include "nl80211_copy.h"
-
-#include "sync.h"
-
-#define LOG_TAG  "WifiHAL"
-
-#include <utils/Log.h>
-#include <utils/String8.h>
-
-#include "wifi_hal.h"
-#include "common.h"
-#include "cpp_bindings.h"
-
-using namespace android;
-#define RTT_RESULT_SIZE (sizeof(wifi_rtt_result));
-
-typedef enum {
-    RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
-    RTT_SUBCMD_CANCEL_CONFIG,
-    RTT_SUBCMD_GETCAPABILITY,
-    RTT_SUBCMD_GETAVAILCHANNEL,
-    RTT_SUBCMD_SET_RESPONDER,
-    RTT_SUBCMD_CANCEL_RESPONDER,
-} RTT_SUB_COMMAND;
-
-typedef enum {
-    RTT_ATTRIBUTE_CAPABILITIES = 1,
-
-    RTT_ATTRIBUTE_TARGET_CNT = 10,
-    RTT_ATTRIBUTE_TARGET_INFO,
-    RTT_ATTRIBUTE_TARGET_MAC,
-    RTT_ATTRIBUTE_TARGET_TYPE,
-    RTT_ATTRIBUTE_TARGET_PEER,
-    RTT_ATTRIBUTE_TARGET_CHAN,
-    RTT_ATTRIBUTE_TARGET_PERIOD,
-    RTT_ATTRIBUTE_TARGET_NUM_BURST,
-    RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
-    RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
-    RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
-    RTT_ATTRIBUTE_TARGET_LCI,
-    RTT_ATTRIBUTE_TARGET_LCR,
-    RTT_ATTRIBUTE_TARGET_BURST_DURATION,
-    RTT_ATTRIBUTE_TARGET_PREAMBLE,
-    RTT_ATTRIBUTE_TARGET_BW,
-    RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
-    RTT_ATTRIBUTE_RESULTS_PER_TARGET,
-    RTT_ATTRIBUTE_RESULT_CNT,
-    RTT_ATTRIBUTE_RESULT
-} RTT_ATTRIBUTE;
-
-typedef struct strmap_entry {
-    int       id;
-    String8   text;
-} strmap_entry_t;
-
-struct dot11_rm_ie {
-    u8 id;
-    u8 len;
-    u8 token;
-    u8 mode;
-    u8 type;
-} __attribute__ ((packed));
-
-typedef struct dot11_rm_ie dot11_rm_ie_t;
-#define DOT11_HDR_LEN                           2
-#define DOT11_RM_IE_LEN                         5
-#define DOT11_MNG_MEASURE_REQUEST_ID           38 /* 11H MeasurementRequest */
-#define DOT11_MEASURE_TYPE_LCI                  8 /* d11 measurement LCI type */
-#define DOT11_MEASURE_TYPE_CIVICLOC            11 /* d11 measurement location civic */
-
-static const strmap_entry_t err_info[] = {
-    {RTT_STATUS_SUCCESS, String8("Success")},
-    {RTT_STATUS_FAILURE, String8("Failure")},
-    {RTT_STATUS_FAIL_NO_RSP, String8("No reponse")},
-    {RTT_STATUS_FAIL_INVALID_TS, String8("Invalid Timestamp")},
-    {RTT_STATUS_FAIL_PROTOCOL, String8("Protocol error")},
-    {RTT_STATUS_FAIL_REJECTED, String8("Rejected")},
-    {RTT_STATUS_FAIL_NOT_SCHEDULED_YET, String8("not scheduled")},
-    {RTT_STATUS_FAIL_SCHEDULE,  String8("schedule failed")},
-    {RTT_STATUS_FAIL_TM_TIMEOUT, String8("timeout")},
-    {RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, String8("AP is on difference channel")},
-    {RTT_STATUS_FAIL_NO_CAPABILITY, String8("no capability")},
-    {RTT_STATUS_FAIL_BUSY_TRY_LATER, String8("busy and try later")},
-    {RTT_STATUS_ABORTED, String8("aborted")}
-};
-
-static const char* get_err_info(int status)
-{
-    int i;
-    const strmap_entry_t *p_entry;
-    int num_entries = sizeof(err_info)/ sizeof(err_info[0]);
-    /* scan thru the table till end */
-    p_entry = err_info;
-    for (i = 0; i < (int) num_entries; i++)
-    {
-        if (p_entry->id == status)
-            return p_entry->text;
-        p_entry++; /* next entry */
-    }
-    return "unknown error"; /* not found */
-}
-
-class GetRttCapabilitiesCommand : public WifiCommand
-{
-    wifi_rtt_capabilities *mCapabilities;
-public:
-    GetRttCapabilitiesCommand(wifi_interface_handle iface, wifi_rtt_capabilities *capabitlites)
-        : WifiCommand("GetRttCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
-    {
-        memset(mCapabilities, 0, sizeof(*mCapabilities));
-    }
-
-    virtual int create() {
-        ALOGD("[WIFI HAL]Creating message to get Rtt capablities; iface = %d", mIfaceInfo->id);
-
-        int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETCAPABILITY);
-        if (ret < 0) {
-            return ret;
-        }
-
-        return ret;
-    }
-
-protected:
-    virtual int handleResponse(WifiEvent& reply) {
-
-        ALOGD("In GetRttCapabilitiesCommand::handleResponse");
-
-        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
-            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
-            return NL_SKIP;
-        }
-
-        int id = reply.get_vendor_id();
-        int subcmd = reply.get_vendor_subcmd();
-        int wiphy_id = reply.get_u32(NL80211_ATTR_WIPHY);
-        int if_id = reply.get_u32(NL80211_ATTR_IFINDEX);
-
-        struct nlattr *vendor_data = (struct nlattr *)reply.get_vendor_data();
-        int len = reply.get_vendor_data_len();
-        void *payload = NULL;
-        if(vendor_data->nla_type == RTT_ATTRIBUTE_CAPABILITIES) {
-            payload = nla_data(vendor_data);
-            len -= NLA_HDRLEN;
-        }
-
-        ALOGD("wiphy_id=%d, if_id=%d, Id=%0x, subcmd=%d, len=%d, expected len=%d", wiphy_id, if_id, id, subcmd, len,
-                    sizeof(*mCapabilities));
-        if (payload)
-            memcpy(mCapabilities, payload, min(len, (int) sizeof(*mCapabilities)));
-
-        ALOGI("RTT capability: %d, %d, %d, %d, %d, %d",
-                    mCapabilities->rtt_one_sided_supported, mCapabilities->rtt_ftm_supported,
-                    mCapabilities->lci_support, mCapabilities->lcr_support,
-                    mCapabilities->preamble_support, mCapabilities->bw_support);
-
-        return NL_OK;
-    }
-};
-
-
-class GetRttResponderInfoCommand : public WifiCommand
-{
-    wifi_rtt_responder* mResponderInfo;
-public:
-    GetRttResponderInfoCommand(wifi_interface_handle iface, wifi_rtt_responder *responderInfo)
-        : WifiCommand("GetRttResponderInfoCommand", iface, 0), mResponderInfo(responderInfo)
-    {
-        memset(mResponderInfo, 0 , sizeof(*mResponderInfo));
-
-    }
-
-    virtual int create() {
-        ALOGD("Creating message to get responder info ; iface = %d", mIfaceInfo->id);
-
-        int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETAVAILCHANNEL);
-        if (ret < 0) {
-            return ret;
-        }
-
-        return ret;
-    }
-
-protected:
-    virtual int handleResponse(WifiEvent& reply) {
-
-        ALOGD("In GetRttResponderInfoCommand::handleResponse");
-
-        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
-            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
-            return NL_SKIP;
-        }
-
-        int id = reply.get_vendor_id();
-        int subcmd = reply.get_vendor_subcmd();
-
-        void *data = reply.get_vendor_data();
-        int len = reply.get_vendor_data_len();
-
-        ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
-                sizeof(*mResponderInfo));
-
-        memcpy(mResponderInfo, data, min(len, (int) sizeof(*mResponderInfo)));
-
-        return NL_OK;
-    }
-};
-
-
-class EnableResponderCommand : public WifiCommand
-{
-    wifi_channel_info  mChannelInfo;
-    unsigned m_max_duration_sec;
-    wifi_rtt_responder* mResponderInfo;
-public:
-    EnableResponderCommand(wifi_interface_handle iface, int id, wifi_channel_info channel_hint,
-            unsigned max_duration_seconds, wifi_rtt_responder *responderInfo)
-            : WifiCommand("EnableResponderCommand", iface, 0), mChannelInfo(channel_hint),
-            m_max_duration_sec(max_duration_seconds), mResponderInfo(responderInfo)
-    {
-        memset(mResponderInfo, 0, sizeof(*mResponderInfo));
-    }
-
-    virtual int create() {
-        ALOGD("Creating message to set responder ; iface = %d", mIfaceInfo->id);
-
-        int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_SET_RESPONDER);
-        if (ret < 0) {
-            return ret;
-        }
-
-        return ret;
-    }
-
-protected:
-    virtual int handleResponse(WifiEvent& reply) {
-
-        ALOGD("In EnableResponderCommand::handleResponse");
-
-        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
-            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
-            return NL_SKIP;
-        }
-
-        int id = reply.get_vendor_id();
-        int subcmd = reply.get_vendor_subcmd();
-
-        void *data = reply.get_vendor_data();
-        int len = reply.get_vendor_data_len();
-
-        ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
-                sizeof(*mResponderInfo));
-
-        memcpy(mResponderInfo, data, min(len, (int) sizeof(*mResponderInfo)));
-
-        return NL_OK;
-    }
-};
-
-
-class CancelResponderCommand : public WifiCommand
-{
-
-public:
-    CancelResponderCommand(wifi_interface_handle iface, int id)
-        : WifiCommand("CancelResponderCommand", iface, 0)/*, mChannelInfo(channel)*/
-    {
-
-    }
-
-    virtual int create() {
-        ALOGD("Creating message to cancel responder ; iface = %d", mIfaceInfo->id);
-
-        int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_RESPONDER);
-        if (ret < 0) {
-            return ret;
-        }
-
-        return ret;
-    }
-
-protected:
-    virtual int handleResponse(WifiEvent& reply) {
-        /* Nothing to do on response! */
-        return NL_SKIP;
-    }
-
-};
-
-
-class RttCommand : public WifiCommand
-{
-    unsigned numRttParams;
-    int mCompleted;
-    int currentIdx;
-    int totalCnt;
-    static const int MAX_RESULTS = 1024;
-    wifi_rtt_result *rttResults[MAX_RESULTS];
-    wifi_rtt_config *rttParams;
-    wifi_rtt_event_handler rttHandler;
-public:
-    RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config,
-            wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
-        : WifiCommand("RttCommand", iface, id), numRttParams(num_rtt_config), rttParams(rtt_config),
-        rttHandler(handler)
-    {
-        memset(rttResults, 0, sizeof(rttResults));
-        currentIdx = 0;
-        mCompleted = 0;
-        totalCnt = 0;
-    }
-
-    RttCommand(wifi_interface_handle iface, int id)
-        : WifiCommand("RttCommand", iface, id)
-    {
-        currentIdx = 0;
-        mCompleted = 0;
-        totalCnt = 0;
-        numRttParams = 0;
-    }
-
-    int createSetupRequest(WifiRequest& request) {
-        int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams);
-        if (result < 0) {
-            return result;
-        }
-        nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO);
-        for (unsigned i = 0; i < numRttParams; i++) {
-            nlattr *attr2 = request.attr_start(i);
-            if (attr2 == NULL) {
-                return WIFI_ERROR_OUT_OF_MEMORY;
-            }
-
-            result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].addr);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].type);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].peer);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].channel,
-                    sizeof(wifi_channel_info));
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_BURST, rttParams[i].num_burst);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
-                    rttParams[i].num_frames_per_burst);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
-                    rttParams[i].num_retries_per_rtt_frame);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
-                    rttParams[i].num_retries_per_ftmr);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u32(RTT_ATTRIBUTE_TARGET_PERIOD,
-                    rttParams[i].burst_period);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u32(RTT_ATTRIBUTE_TARGET_BURST_DURATION,
-                    rttParams[i].burst_duration);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCI,
-                    rttParams[i].LCI_request);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCR,
-                    rttParams[i].LCR_request);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u8(RTT_ATTRIBUTE_TARGET_BW,
-                    rttParams[i].bw);
-            if (result < 0) {
-                return result;
-            }
-
-            result = request.put_u8(RTT_ATTRIBUTE_TARGET_PREAMBLE,
-                    rttParams[i].preamble);
-            if (result < 0) {
-                return result;
-            }
-            request.attr_end(attr2);
-        }
-
-        request.attr_end(rtt_config);
-        request.attr_end(data);
-        return WIFI_SUCCESS;
-    }
-
-    int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) {
-        int result = request.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_CONFIG);
-        if (result < 0) {
-            return result;
-        }
-
-        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
-        request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
-        for(unsigned i = 0; i < num_devices; i++) {
-            result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
-            if (result < 0) {
-                return result;
-            }
-        }
-        request.attr_end(data);
-        return result;
-    }
-    int start() {
-        ALOGD("Setting RTT configuration");
-        WifiRequest request(familyId(), ifaceId());
-        int result = createSetupRequest(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create setup request; result = %d", result);
-            return result;
-        }
-
-        result = requestResponse(request);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to configure RTT setup; result = %d", result);
-            return result;
-        }
-
-        registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
-        ALOGI("Successfully started RTT operation");
-        return result;
-    }
-
-    virtual int cancel() {
-        ALOGD("Stopping RTT");
-
-        WifiRequest request(familyId(), ifaceId());
-        int result = createTeardownRequest(request, 0, NULL);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create stop request; result = %d", result);
-        } else {
-            result = requestResponse(request);
-            if (result != WIFI_SUCCESS) {
-                ALOGE("failed to stop scan; result = %d", result);
-            }
-        }
-
-        unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
-        return WIFI_SUCCESS;
-    }
-
-    int cancel_specific(unsigned num_devices, mac_addr addr[]) {
-        ALOGE("Stopping RTT");
-
-        WifiRequest request(familyId(), ifaceId());
-        int result = createTeardownRequest(request, num_devices, addr);
-        if (result != WIFI_SUCCESS) {
-            ALOGE("failed to create stop request; result = %d", result);
-        } else {
-            result = requestResponse(request);
-            if (result != WIFI_SUCCESS) {
-                ALOGE("failed to stop RTT; result = %d", result);
-            }
-        }
-
-        unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
-        return WIFI_SUCCESS;
-    }
-
-    virtual int handleResponse(WifiEvent& reply) {
-        /* Nothing to do on response! */
-        return NL_SKIP;
-    }
-
-    virtual int handleEvent(WifiEvent& event) {
-        ALOGI("Got an RTT event");
-        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
-        int len = event.get_vendor_data_len();
-        if (vendor_data == NULL || len == 0) {
-            ALOGI("No rtt results found");
-        }
-        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
-            if (it.get_type() == RTT_ATTRIBUTE_RESULTS_COMPLETE) {
-                mCompleted = it.get_u32();
-                ALOGI("retrieved completed flag : %d\n", mCompleted);
-            } else if (it.get_type() == RTT_ATTRIBUTE_RESULTS_PER_TARGET) {
-                int result_cnt = 0;
-                mac_addr bssid;
-                for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
-                    if (it2.get_type() == RTT_ATTRIBUTE_TARGET_MAC) {
-                        memcpy(bssid, it2.get_data(), sizeof(mac_addr));
-                        ALOGI("retrived target mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
-                                bssid[0],
-                                bssid[1],
-                                bssid[2],
-                                bssid[3],
-                                bssid[4],
-                                bssid[5]);
-                    } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_CNT) {
-                        result_cnt = it2.get_u32();
-                        ALOGI("retrieved result_cnt : %d\n", result_cnt);
-                    } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT) {
-                        int result_len = it2.get_len();
-                        rttResults[currentIdx] =  (wifi_rtt_result *)malloc(it2.get_len());
-                        wifi_rtt_result *rtt_result = rttResults[currentIdx];
-                        if (rtt_result == NULL) {
-                            mCompleted = 1;
-                            ALOGE("failed to allocate the wifi_rtt_result\n");
-                            break;
-                        }
-                        memcpy(rtt_result, it2.get_data(), it2.get_len());
-                        result_len -= sizeof(wifi_rtt_result);
-                        if (result_len > 0) {
-                            result_len -= sizeof(wifi_rtt_result);
-                            dot11_rm_ie_t *ele_1;
-                            dot11_rm_ie_t *ele_2;
-                            /* The result has LCI or LCR element */
-                            ele_1 = (dot11_rm_ie_t *)(rtt_result + 1);
-                            if (ele_1->id == DOT11_MNG_MEASURE_REQUEST_ID) {
-                                if (ele_1->type == DOT11_MEASURE_TYPE_LCI) {
-                                    rtt_result->LCI = (wifi_information_element *)ele_1;
-                                    result_len -= (ele_1->len + DOT11_HDR_LEN);
-                                    /* get a next rm ie */
-                                    if (result_len > 0) {
-                                        ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
-                                        if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
-                                                (ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) {
-                                            rtt_result->LCR = (wifi_information_element *)ele_2;
-                                        }
-                                    }
-                                } else if (ele_1->type == DOT11_MEASURE_TYPE_CIVICLOC){
-                                    rtt_result->LCR = (wifi_information_element *)ele_1;
-                                    result_len -= (ele_1->len + DOT11_HDR_LEN);
-                                    /* get a next rm ie */
-                                    if (result_len > 0) {
-                                        ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
-                                        if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
-                                                (ele_2->type == DOT11_MEASURE_TYPE_LCI)) {
-                                            rtt_result->LCI = (wifi_information_element *)ele_2;
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                        totalCnt++;
-                        ALOGI("retrived rtt_result : \n\tburst_num :%d, measurement_number : %d, success_number : %d\n"
-                                "\tnumber_per_burst_peer : %d, status : %s, retry_after_duration : %d s\n"
-                                "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %llu ns, rtt_sd : %llu\n"
-                                "\tdistance : %d, burst_duration : %d ms, negotiated_burst_num : %d\n",
-                                rtt_result->burst_num, rtt_result->measurement_number,
-                                rtt_result->success_number, rtt_result->number_per_burst_peer,
-                                get_err_info(rtt_result->status), rtt_result->retry_after_duration,
-                                rtt_result->rssi, rtt_result->rx_rate.bitrate * 100,
-                                rtt_result->rtt/10, rtt_result->rtt_sd, rtt_result->distance_mm / 10,
-                                rtt_result->burst_duration, rtt_result->negotiated_burst_num);
-                        currentIdx++;
-                    }
-                }
-            }
-
-        }
-        if (mCompleted) {
-            unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
-            (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
-            for (int i = 0; i < currentIdx; i++) {
-                free(rttResults[i]);
-                rttResults[i] = NULL;
-            }
-            totalCnt = currentIdx = 0;
-            WifiCommand *cmd = wifi_unregister_cmd(wifiHandle(), id());
-            if (cmd)
-                cmd->releaseRef();
-        }
-        return NL_SKIP;
-    }
-};
-
-
-/* API to request RTT measurement */
-wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
-        unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
-{
-    wifi_handle handle = getWifiHandle(iface);
-    RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
-    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-    wifi_error result = wifi_register_cmd(handle, id, cmd);
-    if (result != WIFI_SUCCESS) {
-        cmd->releaseRef();
-        return result;
-    }
-    result = (wifi_error)cmd->start();
-    if (result != WIFI_SUCCESS) {
-        wifi_unregister_cmd(handle, id);
-        cmd->releaseRef();
-        return result;
-    }
-    return result;
-}
-
-/* API to cancel RTT measurements */
-wifi_error wifi_rtt_range_cancel(wifi_request_id id,  wifi_interface_handle iface,
-        unsigned num_devices, mac_addr addr[])
-{
-    wifi_handle handle = getWifiHandle(iface);
-    RttCommand *cmd = new RttCommand(iface, id);
-    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
-    cmd->cancel_specific(num_devices, addr);
-    cmd->releaseRef();
-    return WIFI_SUCCESS;
-}
-
-/* API to get RTT capability */
-wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
-        wifi_rtt_capabilities *capabilities)
-{
-    GetRttCapabilitiesCommand command(iface, capabilities);
-    return (wifi_error) command.requestResponse();
-}
-
-/* API to get the responder information */
-wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface,
-        wifi_rtt_responder* responderInfo)
-{
-    GetRttResponderInfoCommand command(iface, responderInfo);
-    return (wifi_error) command.requestResponse();
-
-}
-
-/**
- * Enable RTT responder mode.
- * channel_hint - hint of the channel information where RTT responder should be enabled on.
- * max_duration_seconds - timeout of responder mode.
- * wifi_rtt_responder - information for RTT responder e.g. channel used and preamble supported.
- */
-wifi_error wifi_enable_responder(wifi_request_id id, wifi_interface_handle iface,
-                                wifi_channel_info channel_hint, unsigned max_duration_seconds,
-                                wifi_rtt_responder* responderInfo)
-{
-    EnableResponderCommand command(iface, id, channel_hint, max_duration_seconds, responderInfo);
-    return (wifi_error) command.requestResponse();
-}
-
-/**
- * Disable RTT responder mode.
- */
-wifi_error wifi_disable_responder(wifi_request_id id, wifi_interface_handle iface)
-{
-    CancelResponderCommand command(iface, id);
-    return (wifi_error) command.requestResponse();
-}
-
index e93dbb269c08fc68c9cdf2ce7ca491c1de5b46b6..86ed42349979217bad8030f27901c85bbd799113 100644 (file)
@@ -1,4 +1,6 @@
 #include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
 #include <fcntl.h>
 #include <sys/socket.h>
 #include <netlink/genl/genl.h>
 #include "cpp_bindings.h"
 #include "cutils/properties.h"
 
+template<typename>
+struct DummyFunction;
+
+template<typename R, typename... Args>
+struct DummyFunction<R (*)(Args...)> {
+    static constexpr R invoke(Args...) { return WIFI_SUCCESS; }
+};
+
+template<typename... Args>
+struct DummyFunction<void (*)(Args...)> {
+    static constexpr void invoke(Args...) { }
+};
+
+template<typename T>
+void populateDummyFor(T& val) {
+    val = &DummyFunction<T>::invoke;
+}
+
 /*
  BUGBUG: normally, libnl allocates ports for all connections it makes; but
  being a static library, it doesn't really know how many other netlink connections
@@ -44,7 +64,6 @@
 #define WIFI_HAL_CMD_SOCK_PORT       644
 #define WIFI_HAL_EVENT_SOCK_PORT     645
 
-static void internal_event_handler(wifi_handle handle, int events);
 static int internal_no_seq_check(nl_msg *msg, void *arg);
 static int internal_valid_message_handler(nl_msg *msg, void *arg);
 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
@@ -54,34 +73,18 @@ static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_
                         iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
 
-static wifi_error wifi_reset_log_handler_dummy(wifi_request_id id, wifi_interface_handle iface);
 static wifi_error wifi_get_wake_reason_stats_dummy(wifi_interface_handle iface,
     WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
 static wifi_error wifi_get_packet_filter_capabilities_dummy(
     wifi_interface_handle handle, u32 *version, u32 *max_len);
-static wifi_error wifi_configure_nd_offload_dummy(wifi_interface_handle iface, u8 enable);
-static wifi_error wifi_get_firmware_version_dummy(
-    wifi_interface_handle iface, char *buffer, int buffer_size);
-static wifi_error wifi_get_driver_version_dummy(
-    wifi_interface_handle iface, char *buffer, int buffer_size);
-static wifi_error wifi_get_ring_data_dummy(wifi_interface_handle iface, char *ring_name);
 static wifi_error wifi_get_ring_buffers_status_dummy(wifi_interface_handle iface,
     u32 *num_rings, wifi_ring_buffer_status *status);
 static wifi_error wifi_get_logger_supported_feature_set_dummy(wifi_interface_handle iface,
     unsigned int *support);
-static wifi_error wifi_start_logging_dummy(wifi_interface_handle iface, u32 verbose_level,
-    u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name);
-static wifi_error wifi_start_pkt_fate_monitoring_dummy(wifi_interface_handle iface);
 static wifi_error wifi_get_tx_pkt_fates_dummy(wifi_interface_handle handle,
     wifi_tx_report *tx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates);
 static wifi_error wifi_get_rx_pkt_fates_dummy(wifi_interface_handle handle,
     wifi_rx_report *rx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates);
-static wifi_error wifi_get_driver_memory_dump_dummy(wifi_interface_handle iface,
-    wifi_driver_memory_dump_callbacks callbacks);
-static wifi_error wifi_set_log_handler_dummy(wifi_request_id id, wifi_interface_handle iface,
-    wifi_ring_buffer_data_handler handler);
-static wifi_error wifi_set_scanning_mac_oui_dummy(wifi_interface_handle handle, oui scan_oui);
-
 
 /* Initialize/Cleanup */
 
@@ -122,56 +125,40 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
     fn->wifi_cleanup = wifi_cleanup;
     fn->wifi_event_loop = wifi_event_loop;
     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
-    fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
-    fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui_dummy;
     fn->wifi_get_ifaces = wifi_get_ifaces;
     fn->wifi_get_iface_name = wifi_get_iface_name;
-    fn->wifi_start_gscan = wifi_start_gscan;
-    fn->wifi_stop_gscan = wifi_stop_gscan;
-    fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
-    fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
-    fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
-    fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
-    fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
-    /*fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
-    fn->wifi_get_link_stats = wifi_get_link_stats;
-    fn->wifi_set_link_stats = wifi_set_link_stats;
-    fn->wifi_clear_link_stats = wifi_clear_link_stats;*/
-    fn->wifi_get_valid_channels = wifi_get_valid_channels;
-    fn->wifi_rtt_range_request = wifi_rtt_range_request;
-    fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
-    fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
-    /*fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
-    fn->wifi_enable_responder = wifi_enable_responder;
-    fn->wifi_disable_responder = wifi_disable_responder;
-    fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;*/
-    fn->wifi_start_logging = wifi_start_logging_dummy;
-    fn->wifi_set_epno_list = wifi_set_epno_list;
-    fn->wifi_reset_epno_list = wifi_reset_epno_list;
     fn->wifi_set_country_code = wifi_set_country_code;
-    /*fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;*/
-    fn->wifi_set_log_handler = wifi_set_log_handler_dummy;
-    fn->wifi_reset_log_handler = wifi_reset_log_handler_dummy;
-    /*fn->wifi_set_alert_handler = wifi_set_alert_handler;
-    fn->wifi_reset_alert_handler = wifi_reset_alert_handler;*/
-    fn->wifi_get_firmware_version = wifi_get_firmware_version_dummy;
-    fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status_dummy;
-    fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set_dummy;
-    fn->wifi_get_ring_data = wifi_get_ring_data_dummy;
-    fn->wifi_get_driver_version = wifi_get_driver_version_dummy;
+    fn->wifi_get_firmware_version = wifi_get_firmware_version;
+    fn->wifi_get_driver_version = wifi_get_driver_version;
     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
-    fn->wifi_configure_nd_offload = wifi_configure_nd_offload_dummy;
     fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
-    fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring_dummy;
+    fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
+    fn->wifi_configure_roaming = wifi_configure_roaming;
+    fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
+    fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
+    fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
+    fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;
+    fn->wifi_get_valid_channels = wifi_get_valid_channels;
+
+    fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status_dummy;
+    fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set_dummy;
     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates_dummy;
     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates_dummy;
     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities_dummy;
-
-    fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump_dummy;
     fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats_dummy;
-    fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities_dummy;
+
+    populateDummyFor(fn->wifi_wait_for_driver_ready);
+    populateDummyFor(fn->wifi_set_nodfs_flag);
+    populateDummyFor(fn->wifi_set_log_handler);
+    populateDummyFor(fn->wifi_reset_log_handler);
+    populateDummyFor(fn->wifi_configure_nd_offload);
+    populateDummyFor(fn->wifi_start_pkt_fate_monitoring);
+    populateDummyFor(fn->wifi_get_driver_memory_dump);
+    populateDummyFor(fn->wifi_get_ring_data);
+    populateDummyFor(fn->wifi_start_logging);
+    populateDummyFor(fn->wifi_get_gscan_capabilities);
 
     return WIFI_SUCCESS;
 }
@@ -331,6 +318,13 @@ static void internal_cleaned_up_handler(wifi_handle handle)
         info->event_sock = NULL;
     }
 
+    if (info->interfaces) {
+        int i = 0;
+        for (; i < info->num_interfaces; i++)
+            free(info->interfaces[i]);
+        free(info->interfaces);
+    }
+
     (*cleaned_up_handler)(handle);
     pthread_mutex_destroy(&info->cb_lock);
     free(info);
@@ -503,8 +497,6 @@ static int internal_valid_message_handler(nl_msg *msg, void *arg)
         ALOGV("event received %s", event.get_cmdString());
     }
 
-    bool dispatched = false;
-
     pthread_mutex_lock(&info->cb_lock);
 
     for (int i = 0; i < info->num_event_cb; i++) {
@@ -578,7 +570,6 @@ public:
         // ALOGD("handling reponse in %s", __func__);
 
         struct nlattr **tb = reply.attributes();
-        struct genlmsghdr *gnlh = reply.header();
         struct nlattr *mcgrp = NULL;
         int i;
 
@@ -771,6 +762,114 @@ public:
     }
 };
 
+class ConfigRoamingCommand : public WifiCommand
+{
+private:
+    wifi_roaming_config *mConfig;
+
+public:
+    ConfigRoamingCommand(wifi_interface_handle handle, wifi_roaming_config *config)
+        : WifiCommand("ConfigRoamingCommand", handle, 0)
+    {
+        mConfig = config;
+    }
+
+    int createRequest(WifiRequest& request, int subcmd, wifi_roaming_config *config) {
+        int result = request.create(GOOGLE_OUI, subcmd);
+        if (result < 0) {
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+        result = request.put_u32(WIFI_ATTRIBUTE_ROAMING_BLACKLIST_NUM, config->num_blacklist_bssid);
+        if (result < 0) {
+            return result;
+        }
+
+        mac_addr *bssid_list = config->blacklist_bssid;
+        for (u32 i = 0; i < config->num_blacklist_bssid; i++) {
+            result = request.put_addr(WIFI_ATTRIBUTE_ROAMING_BLACKLIST_BSSID, bssid_list[i]);
+            ALOGI("Blacklist BSSID[%d] " MACSTR, i, MAC2STR(bssid_list[i]));
+            if (result < 0) {
+                return result;
+            }
+        }
+
+        result = request.put_u32(WIFI_ATTRIBUTE_ROAMING_WHITELIST_NUM, config->num_whitelist_ssid);
+        if (result < 0) {
+            return result;
+        }
+
+        char ssid[MAX_SSID_LENGTH + 1];
+        ssid_t *ssid_list = config->whitelist_ssid;
+        for (u32 i = 0; i < config->num_whitelist_ssid; i++) {
+            memcpy(ssid, ssid_list[i].ssid_str, ssid_list[i].length);
+            ssid[ssid_list[i].length] = '\0';
+            result = request.put(
+                WIFI_ATTRIBUTE_ROAMING_WHITELIST_SSID, ssid, ssid_list[i].length + 1);
+            ALOGI("Whitelist ssid[%d] : %s", i, ssid);
+            if (result < 0) {
+                return result;
+            }
+        }
+
+        request.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+
+    int start() {
+        ALOGD("[WIFI HAL] Configure roaming");
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request, WIFI_SUBCMD_CONFIG_ROAMING, mConfig);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to create request, result=%d", result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("[WIFI HAL]Failed to configure roaming, result=%d", result);
+        }
+
+        return result;
+    }
+
+protected:
+    virtual int handleResponse(WifiEvent& reply) {
+         ALOGD("ConfigRoamingCommand complete!");
+        /* Nothing to do on response! */
+        return NL_SKIP;
+    }
+};
+
+class EnableRoamingCommand : public WifiCommand {
+private:
+    fw_roaming_state_t mState;
+public:
+    EnableRoamingCommand(wifi_interface_handle handle, fw_roaming_state_t state)
+        : WifiCommand("EnableRoamingCommand", handle, 0) {
+            mState = state;
+        }
+    virtual int create() {
+        int ret;
+
+        ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_ENABLE_ROAMING);
+        if (ret < 0) {
+             ALOGE("Can't create message to send to driver - %d", ret);
+             return ret;
+        }
+
+        nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+        ret = mMsg.put_u32(WIFI_ATTRIBUTE_ROAMING_STATE, mState);
+        if (ret < 0) {
+            return ret;
+        }
+
+        mMsg.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+};
+
 class GetFeatureSetCommand : public WifiCommand
 {
 private:
@@ -797,8 +896,8 @@ public:
 
         if(feature_type == WIFI_ATTRIBUTE_FEATURE_SET) {
             ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET);
-        } else if (feature_type == WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
-            ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX);
+        } else if (feature_type == WIFI_ATTRIBUTE_ROAMING_CAPABILITIES) {
+            ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_ROAMING_CAPABILITIES);
         } else {
             ALOGE("Unknown feature type %d", feature_type);
             return -1;
@@ -814,7 +913,7 @@ public:
 protected:
     virtual int handleResponse(WifiEvent& reply) {
 
-        ALOGD("In GetFeatureSetCommand::handleResponse");
+        ALOGD("In GetFeatureSetCommand::handleResponse for %d", feature_type);
 
         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
             ALOGD("Ignore reply with cmd 0x%x", reply.get_cmd());
@@ -839,30 +938,24 @@ protected:
                 return NL_SKIP;
             }
             memcpy(fset, data, min(len, (int) sizeof(*fset)));
-        }
-        else if (feature_type == WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
-            int num_features_set = 0;
-            int i = 0;
-
+            ALOGI("feature_set=0x%x", *fset);
+        } else if (feature_type == WIFI_ATTRIBUTE_ROAMING_CAPABILITIES){
             if(!feature_matrix || !fm_size) {
                 ALOGE("feature_set pointer is not set");
                 return NL_SKIP;
             }
 
+            *fm_size = set_size_max; // black and white
+            int i = 0;
+            u32 max[2] = {MAX_BLACKLIST_BSSID, MAX_WHITELIST_SSID};
             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
-                if (it.get_type() == WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
-                    num_features_set = it.get_u32();
-                    ALOGI("Get feature list with %d concurrent sets", num_features_set);
-                    if(set_size_max && (num_features_set > set_size_max))
-                        num_features_set = set_size_max;
-                    *fm_size = num_features_set;
-                } else if ((it.get_type() == WIFI_ATTRIBUTE_FEATURE_SET) &&
-                             i < num_features_set) {
-                    feature_matrix[i] = it.get_u32();
+                if (it.get_type() == WIFI_ATTRIBUTE_ROAMING_CAPABILITIES && i < set_size_max) {
+                    feature_matrix[i] = it.get_u32() > max[i] ? max[i] : it.get_u32();
+                    ALOGI("feature_matrix %d: %d", i, feature_matrix[i]);
                     i++;
                 } else {
-                    ALOGW("Ignore invalid attribute type = %d, size = %d",
-                            it.get_type(), it.get_len());
+                    ALOGW("Ignore invalid attribute type = %d, idx = %d",
+                            it.get_type(), i);
                 }
             }
         }
@@ -872,6 +965,147 @@ protected:
 
 };
 
+class SelectTxPowerCommand : public WifiCommand {
+private:
+    int mScenario;
+public:
+    SelectTxPowerCommand(wifi_interface_handle handle, int scenario)
+        : WifiCommand("SelectTxPowerCommand", handle, 0) {
+            mScenario = scenario;
+        }
+    virtual int create() {
+        int ret;
+
+        ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SELECT_TX_POWER_SCENARIO);
+        if (ret < 0) {
+             ALOGE("Can't create message to send to driver - %d", ret);
+             return ret;
+        }
+
+        nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+        ret = mMsg.put_u32(WIFI_ATTRIBUTE_TX_POWER_SCENARIO, mScenario);
+        if (ret < 0) {
+            return ret;
+        }
+
+        mMsg.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+};
+
+class SetScanMacOuiCommand : public WifiCommand {
+private:
+    const byte *mScanMacOui;
+public:
+    SetScanMacOuiCommand(wifi_interface_handle handle, const oui scan_oui)
+        : WifiCommand("SetScanMacOuiCommand", handle, 0), mScanMacOui(scan_oui) {
+    }
+    virtual int create() {
+        ALOGI("Set scan mac oui");
+        int ret;
+
+        ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI);
+        if (ret < 0) {
+             ALOGE("Can't create message to send to driver - %d", ret);
+             return ret;
+        }
+
+        nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+        ret = mMsg.put(WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, (void *)mScanMacOui, sizeof(oui));
+        if (ret < 0) {
+            return ret;
+        }
+
+        mMsg.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+};
+
+class GetChannelListCommand : public WifiCommand
+{
+private:
+    wifi_channel *mChannels;
+    int mMaxChannels;
+    int *mNumOfChannel;
+    int mBand;
+
+public:
+    GetChannelListCommand(wifi_interface_handle handle, int band, int max_channels,
+        wifi_channel *channels, int *num_channels)
+        : WifiCommand("GetChannelListCommand", handle, 0)
+    {
+        mBand = band;
+        mMaxChannels = max_channels;
+        mChannels = channels;
+        mNumOfChannel = num_channels;
+        memset(mChannels, 0, sizeof(wifi_channel) * mMaxChannels);
+    }
+
+    virtual int create() {
+        ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id);
+
+        int ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_CHANNEL_LIST);
+        if (ret < 0) {
+            return ret;
+        }
+
+        ALOGI("In GetChannelList::mBand=%d", mBand);
+
+        nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
+        ret = mMsg.put_u32(WIFI_ATTRIBUTE_BAND, mBand);
+        if (ret < 0) {
+            return ret;
+        }
+
+        mMsg.attr_end(data);
+        return ret;
+    }
+
+protected:
+    virtual int handleResponse(WifiEvent& reply) {
+
+        ALOGV("In GetChannelList::handleResponse");
+
+        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+            ALOGE("Ignore reply with cmd 0x%x", reply.get_cmd());
+            return NL_SKIP;
+        }
+
+        int vendor_id = reply.get_vendor_id();
+        int subcmd = reply.get_vendor_subcmd();
+        ALOGV("vendor_id = 0x%x, subcmd = 0x%x", vendor_id, subcmd);
+
+        nlattr *vendor = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+        int len = reply.get_vendor_data_len();
+        if (vendor == NULL || len == 0) {
+            ALOGE("No vendor data in GetChannelList response, ignore it");
+            return NL_SKIP;
+        }
+
+        int num_channels = 0;
+        for (nl_iterator it(vendor); it.has_next(); it.next()) {
+            if (it.get_type() == WIFI_ATTRIBUTE_NUM_CHANNELS) {
+                num_channels = it.get_u32();
+                ALOGI("Get channel list with %d channels", num_channels);
+                if (num_channels > mMaxChannels)
+                    num_channels = mMaxChannels;
+                *mNumOfChannel = num_channels;
+            } else if (it.get_type() == WIFI_ATTRIBUTE_CHANNEL_LIST && num_channels) {
+                memcpy(mChannels, it.get_data(), sizeof(wifi_channel) * num_channels);
+            } else {
+                ALOGW("Ignore invalid attribute type = %d, size = %d",
+                        it.get_type(), it.get_len());
+            }
+        }
+
+        ALOGD("mChannels[0]=%d mChannels[1]=%d", *mChannels, *(mChannels + 1));
+
+        return NL_OK;
+    }
+};
+
+/////////////////////////////////////////////////////////////////////////
+
 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
 {
     GetMulticastIdCommand cmd(handle, name, group);
@@ -882,11 +1116,9 @@ static int wifi_get_multicast_id(wifi_handle handle, const char *name, const cha
         return cmd.getId();
 }
 
-/////////////////////////////////////////////////////////////////////////
-
 static bool is_wifi_interface(const char *name)
 {
-    if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
+    if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0 && strncmp(name, "ap", 2) != 0) {
         /* Not a wifi interface; ignore it */
         return false;
     } else {
@@ -936,6 +1168,7 @@ wifi_error wifi_init_interfaces(wifi_handle handle)
         closedir(d);
         return WIFI_ERROR_OUT_OF_MEMORY;
     }
+    memset(info->interfaces, 0, sizeof(interface_info *) * n);
 
     int i = 0;
     while ((de = readdir(d))) {
@@ -978,41 +1211,10 @@ wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t
 
 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *pset)
 {
-#if 0
-    GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_FEATURE_SET, set, NULL, NULL, 1);
+    GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_FEATURE_SET, pset, NULL, NULL, 1);
     return (wifi_error)command.requestResponse();
-#else
-    feature_set set = 0;
-    char prop_buf[PROPERTY_VALUE_MAX];
-
-    property_get("ro.wlan.mtk.wifi.5g", prop_buf, NULL);
-    if (!strcmp(prop_buf, "1"))
-        set |= WIFI_FEATURE_INFRA_5G;
-
-    set |= WIFI_FEATURE_P2P;
-    set |= WIFI_FEATURE_SOFT_AP;
-    set |= WIFI_FEATURE_TDLS;
-
-#ifdef CONFIG_PNO_SUPPORT
-    set |= WIFI_FEATURE_PNO;
-#endif
-
-
-    memcpy(pset, &set, sizeof(feature_set));
-
-    ALOGI("[WIFI HAL]wifi_get_supported_feature_set: handle=%p, feature_set=0x%x", handle, *pset);
-    return WIFI_SUCCESS;
-#endif
 }
 
-wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
-       feature_set set[], int *set_size)
-{
-    GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_NUM_FEATURE_SET, NULL, set, set_size, set_size_max);
-    return (wifi_error)command.requestResponse();
-}
-
-
 wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
 {
     SetCountryCodeCommand command(handle, country_code);
@@ -1047,7 +1249,6 @@ static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_h
     if (id == -1) {
         wifi_rssi_event_handler handler;
         s8 max_rssi = 0, min_rssi = 0;
-        wifi_handle handle = getWifiHandle(iface);
         memset(&handler, 0, sizeof(handler));
         SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, handler);
         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
@@ -1058,19 +1259,108 @@ static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_h
     return wifi_cancel_cmd(id, iface);
 }
 
-/////////////////////////////////////////////////////////////////////////////
+wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle,
+                                            wifi_roaming_capabilities *caps) {
+    ALOGI("Get roaming capabilities");
+
+    wifi_handle wifiHandle = getWifiHandle(handle);
+    hal_info *info = getHalInfo(wifiHandle);
+
+    if (!caps) {
+        ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__);
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    if (!info) {
+        ALOGE("%s: hal_info is NULL", __FUNCTION__);
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    // first time to get roaming cap
+    if (info->roaming_capa.max_blacklist_size == 0 && info->roaming_capa.max_whitelist_size == 0) {
+        int size = 0;
+        GetFeatureSetCommand command(handle, WIFI_ATTRIBUTE_ROAMING_CAPABILITIES, NULL,
+            (feature_set*) caps, &size, 2);
+        wifi_error ret = (wifi_error)command.requestResponse();
+        if (ret == WIFI_SUCCESS) {
+            info->roaming_capa.max_blacklist_size = caps->max_blacklist_size;
+            info->roaming_capa.max_whitelist_size = caps->max_whitelist_size;
+        }
+        return ret;
+    } else {
+        memcpy(caps, &info->roaming_capa, sizeof(wifi_roaming_capabilities));
+    }
 
-static wifi_error wifi_set_scanning_mac_oui_dummy(wifi_interface_handle handle, oui scan_oui)
-{
     return WIFI_SUCCESS;
 }
 
-static wifi_error wifi_set_log_handler_dummy(wifi_request_id id, wifi_interface_handle iface,
-    wifi_ring_buffer_data_handler handler)
+wifi_error wifi_configure_roaming(wifi_interface_handle handle,
+                                     wifi_roaming_config *roaming_config) {
+    ALOGI("Configure roaming");
+    wifi_handle wifiHandle = getWifiHandle(handle);
+    hal_info *info = getHalInfo(wifiHandle);
+    if (!roaming_config) {
+        ALOGE("%s: Invalid Buffer provided. Exit", __FUNCTION__);
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    /* Set bssid blacklist */
+    if (roaming_config->num_blacklist_bssid > info->roaming_capa.max_blacklist_size) {
+        ALOGE("%s: Number of blacklist bssids(%d) provided is more than maximum blacklist bssids(%d)"
+              " supported", __FUNCTION__, roaming_config->num_blacklist_bssid,
+              info->roaming_capa.max_blacklist_size);
+        return WIFI_ERROR_NOT_SUPPORTED;
+    }
+
+    /* Set ssid whitelist */
+    if (roaming_config->num_whitelist_ssid > info->roaming_capa.max_whitelist_size) {
+        ALOGE("%s: Number of whitelist ssid(%d) provided is more than maximum whitelist ssids(%d) "
+              "supported", __FUNCTION__, roaming_config->num_whitelist_ssid,
+              info->roaming_capa.max_whitelist_size);
+        return WIFI_ERROR_NOT_SUPPORTED;
+    }
+
+    ConfigRoamingCommand command(handle, roaming_config);
+    return (wifi_error)command.start();
+}
+
+wifi_error wifi_enable_firmware_roaming(wifi_interface_handle handle,
+                              fw_roaming_state_t state) {
+    ALOGI("Enable roaming %d", state);
+    EnableRoamingCommand command(handle, state);
+    return (wifi_error) command.requestResponse();
+}
+
+wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle,
+        wifi_power_scenario scenario)
 {
-    return WIFI_SUCCESS;
+    ALOGI("Select tx power scenario %d", scenario);
+    SelectTxPowerCommand command(handle, scenario);
+    return (wifi_error) command.requestResponse();
 }
 
+wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle)
+{
+    ALOGI("Reset tx power scenario");
+    SelectTxPowerCommand command(handle, -1);
+    return (wifi_error) command.requestResponse();
+}
+
+wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
+{
+    SetScanMacOuiCommand command(handle, scan_oui);
+    return (wifi_error) command.requestResponse();
+}
+
+wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
+        int band, int max_channels, wifi_channel *channels, int *num_channels)
+{
+    GetChannelListCommand command(handle, band, max_channels, channels, num_channels);
+    return (wifi_error) command.requestResponse();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
 static wifi_error wifi_get_wake_reason_stats_dummy(wifi_interface_handle iface,
     WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
 {
@@ -1092,16 +1382,6 @@ static wifi_error wifi_get_packet_filter_capabilities_dummy(wifi_interface_handl
     return  WIFI_ERROR_INVALID_ARGS;
 }
 
-static wifi_error wifi_configure_nd_offload_dummy(wifi_interface_handle iface, u8 enable)
-{
-    return WIFI_SUCCESS;
-}
-
-static wifi_error wifi_start_pkt_fate_monitoring_dummy(wifi_interface_handle iface)
-{
-    return WIFI_SUCCESS;
-}
-
 static wifi_error wifi_get_tx_pkt_fates_dummy(wifi_interface_handle handle,
     wifi_tx_report *tx_report_bufs, size_t n_requested_fates, size_t *n_provided_fates)
 {
@@ -1122,44 +1402,6 @@ static wifi_error wifi_get_rx_pkt_fates_dummy(wifi_interface_handle handle,
     return WIFI_ERROR_INVALID_ARGS;
 }
 
-static wifi_error wifi_get_driver_memory_dump_dummy(wifi_interface_handle iface,
-    wifi_driver_memory_dump_callbacks callbacks)
-{
-    return WIFI_SUCCESS;
-}
-
-static wifi_error wifi_reset_log_handler_dummy(wifi_request_id id, wifi_interface_handle iface)
-{
-    return WIFI_SUCCESS;
-}
-
-static wifi_error wifi_get_firmware_version_dummy(wifi_interface_handle iface, char *buffer,
-        int buffer_size)
-{
-    if (buffer && buffer_size > 0) {
-        strncpy(buffer, "0", buffer_size);
-        return WIFI_SUCCESS;
-    }
-    return  WIFI_ERROR_INVALID_ARGS;
-}
-
-static wifi_error wifi_get_driver_version_dummy(wifi_interface_handle iface,
-    char *buffer, int buffer_size)
-{
-    if (buffer && buffer_size > 0) {
-        strncpy(buffer, "0", buffer_size);
-        return WIFI_SUCCESS;
-    }
-    return  WIFI_ERROR_INVALID_ARGS;
-}
-
-static wifi_error wifi_get_ring_data_dummy(wifi_interface_handle iface, char *ring_name)
-{
-    if (ring_name) {
-        return WIFI_SUCCESS;
-    }
-    return  WIFI_ERROR_INVALID_ARGS;
-}
 
 static wifi_error wifi_get_ring_buffers_status_dummy(wifi_interface_handle iface,
         u32 *num_rings, wifi_ring_buffer_status *status)
@@ -1167,7 +1409,7 @@ static wifi_error wifi_get_ring_buffers_status_dummy(wifi_interface_handle iface
     if (num_rings && status) {
         *num_rings = 1;
         memset(status, 0, sizeof(*status));
-        strncpy((char*)status->name, "dummy", sizeof(*status->name));
+        strncpy((char*)status->name, "dummy", sizeof(status->name));
         return WIFI_SUCCESS;
     }
     return WIFI_ERROR_INVALID_ARGS;
@@ -1182,13 +1424,3 @@ static wifi_error wifi_get_logger_supported_feature_set_dummy(wifi_interface_han
     }
     return WIFI_ERROR_INVALID_ARGS;
 }
-
-static wifi_error wifi_start_logging_dummy(wifi_interface_handle iface, u32 verbose_level,
-        u32 flags, u32 max_interval_sec, u32 min_data_size, char *ring_name)
-{
-    if (ring_name) {
-        return WIFI_SUCCESS;
-    }
-    return  WIFI_ERROR_INVALID_ARGS;
-}
-
diff --git a/wifi_hal/wifi_logger.cpp b/wifi_hal/wifi_logger.cpp
new file mode 100644 (file)
index 0000000..aadd585
--- /dev/null
@@ -0,0 +1,170 @@
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/rtnetlink.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>
+#include <linux/errqueue.h>
+
+#include <linux/pkt_sched.h>
+#include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink-private/object-api.h>
+#include <netlink-private/types.h>
+
+#include "nl80211_copy.h"
+#include "sync.h"
+
+#define LOG_TAG  "WifiHAL"
+
+#include <log/log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+
+enum DEBUG_SUB_COMMAND {
+    LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
+    LOGGER_GET_VER,
+};
+
+enum LOGGER_ATTRIBUTE {
+    LOGGER_ATTRIBUTE_DRIVER_VER,
+    LOGGER_ATTRIBUTE_FW_VER,
+};
+
+enum GetCmdType {
+    GET_FW_VER,
+    GET_DRV_VER,
+};
+
+///////////////////////////////////////////////////////////////////////////////
+class DebugCommand : public WifiCommand
+{
+    char *mBuff;
+    int *mBuffSize;
+    GetCmdType mType;
+
+public:
+
+    // constructor for get version
+    DebugCommand(wifi_interface_handle iface, char *buffer, int *buffer_size,
+            GetCmdType cmdType)
+        : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
+        (cmdType)
+    {
+        memset(mBuff, 0, *mBuffSize);
+    }
+
+    int createRequest(WifiRequest &request) {
+        int result;
+
+        nlattr *data = NULL;
+        switch (mType) {
+            case GET_FW_VER:
+            case GET_DRV_VER:
+                result = request.create(GOOGLE_OUI, LOGGER_GET_VER);
+                if (result != WIFI_SUCCESS) {
+                    ALOGE("Failed to create get drv version request; result = %d", result);
+                    return result;
+                }
+
+                data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+                // Driver expecting only attribute type, passing mbuff as data with
+                // length 0 to avoid undefined state
+                result = request.put(mType == GET_FW_VER ?
+                    LOGGER_ATTRIBUTE_FW_VER : LOGGER_ATTRIBUTE_DRIVER_VER, mBuff, 0);
+                if (result != WIFI_SUCCESS) {
+                    ALOGE("Failed to put get drv version request; result = %d", result);
+                    return result;
+                }
+                request.attr_end(data);
+                break;
+            default:
+                ALOGE("Unknown Debug command");
+                result = WIFI_ERROR_UNKNOWN;
+        }
+        return result;
+    }
+
+    int start() {
+        // ALOGD("Start debug command");
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to create debug request; result = %d", result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to register debug response; result = %d", result);
+        }
+        return result;
+    }
+
+    virtual int handleResponse(WifiEvent& reply) {
+        ALOGD("In DebugCommand::handleResponse");
+
+        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+            return NL_SKIP;
+        }
+
+        void *data = NULL;
+        int len = 0;
+        switch (mType) {
+            case GET_DRV_VER:
+            case GET_FW_VER:
+                data = reply.get_vendor_data();
+                len = reply.get_vendor_data_len();
+
+                ALOGD("len = %d, expected len = %d", len, *mBuffSize);
+                memcpy(mBuff, data, min(len, *mBuffSize));
+                if (*mBuffSize < len)
+                    return NL_SKIP;
+                *mBuffSize = len;
+                break;
+            default:
+                ALOGW("Unknown Debug command");
+        }
+        return NL_OK;
+    }
+
+    virtual int handleEvent(WifiEvent& event) {
+        /* NO events! */
+        return NL_SKIP;
+    }
+};
+
+wifi_error get_version(wifi_interface_handle iface, char *buffer, int *buffer_size, GetCmdType type)
+{
+    if (buffer && (*buffer_size > 0)) {
+        DebugCommand *cmd = new DebugCommand(iface, buffer, buffer_size, type);
+        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+        wifi_error result = (wifi_error)cmd->start();
+        cmd->releaseRef();
+        return result;
+    } else {
+        ALOGE("%s version buffer NULL", type == GET_FW_VER ? "FW" : "Driver");
+        return  WIFI_ERROR_INVALID_ARGS;
+    }
+}
+
+/* API to collect a firmware version string */
+wifi_error wifi_get_firmware_version(wifi_interface_handle iface, char *buffer,
+        int buffer_size)
+{
+    return get_version(iface, buffer, &buffer_size, GET_FW_VER);
+}
+
+/* API to collect a driver version string */
+wifi_error wifi_get_driver_version(wifi_interface_handle iface, char *buffer, int buffer_size)
+{
+    return get_version(iface, buffer, &buffer_size, GET_DRV_VER);
+}
index af25f9cda19850e93fbfccb15820f0690dd0fae5..d4cfa690662bd549d0c330f7583bfdad77eeae66 100644 (file)
@@ -25,8 +25,6 @@
 #include "common.h"
 #include "cpp_bindings.h"
 
-//using namespace android;
-
 typedef enum {
     WIFI_OFFLOAD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
     WIFI_OFFLOAD_STOP_MKEEP_ALIVE,
index 115997a75614024dceb11ed1cba1d7f5f9e8521f..4d96f9dbcd8b9bd93bf0a0b0f45586fc45e6e07c 100644 (file)
@@ -18,6 +18,7 @@ LOCAL_PATH := $(call my-dir)
 ##### For Google SUPPLICANT #####
 ifeq ($(MTKPATH),)
     $(warning build BASIC wpa_supplicant)
+
     WPA_SUPPL_DIR = external/wpa_supplicant_8
     WPA_SRC_FILE :=
 
@@ -58,7 +59,10 @@ endif
 
 ########################
 include $(CLEAR_VARS)
+LOCAL_SANITIZE := cfi
 LOCAL_MODULE := lib_driver_cmd_mt66xx
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_OWNER := mtk
 LOCAL_SHARED_LIBRARIES := libc libcutils
 LOCAL_CFLAGS := $(L_CFLAGS)
 LOCAL_SRC_FILES := $(WPA_SRC_FILE)
index c59bcb578edf0f673928f7ecf17aa77e1ff45696..f505f23e3e43a7e33f658119c379eb349044eab2 100644 (file)
 #include "android_drv.h"
 #endif
 
+#include "mediatek_driver_nl80211.h"
 #include "driver_i.h"
 
+#include "p2p/p2p_i.h"
+
 #include "eloop.h"
+#define PRIV_CMD_SIZE 512
+
+typedef struct android_wifi_priv_cmd {
+    char buf[PRIV_CMD_SIZE];
+    int used_len;
+    int total_len;
+} android_wifi_priv_cmd;
+
+static int drv_errors = 0;
+
+static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
+{
+    drv_errors++;
+    if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
+        drv_errors = 0;
+        /* avoid the framework to handle  HANGED */
+        /*
+        * wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
+        */
+    }
+}
+
+static int testmode_sta_statistics_handler(struct nl_msg *msg, void *arg)
+{
+    struct nlattr *tb[NL80211_ATTR_MAX + 1] = {};
+    struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+    struct nlattr *sinfo[NL80211_TESTMODE_STA_STATISTICS_NUM] = {};
+    struct wpa_driver_sta_statistics_s *sta_statistics = (struct wpa_driver_sta_statistics_s *)arg;
+    unsigned char i = 0;
+    static struct nla_policy policy[NL80211_TESTMODE_STA_STATISTICS_NUM] = {
+        [NL80211_TESTMODE_STA_STATISTICS_VERSION]               = { .type = NLA_U8 },
+        [NL80211_TESTMODE_STA_STATISTICS_MAC]                   = { .type = NLA_UNSPEC },
+        [NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE]            = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_FLAG]                  = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_PER]                   = { .type = NLA_U8 },
+        [NL80211_TESTMODE_STA_STATISTICS_RSSI]                  = { .type = NLA_U8 },
+        [NL80211_TESTMODE_STA_STATISTICS_PHY_MODE]              = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_TX_RATE]               = { .type = NLA_U16 },
+        [NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT]              = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT]           = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME]          = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT]             = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT]         = { .type = NLA_U32 },
+
+        [NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME]      = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME]             = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME]         = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME]         = { .type = NLA_U32 },
+
+        [NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY]    = { .type = NLA_UNSPEC },
+        [NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY]      = { .type = NLA_UNSPEC },
+        [NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY]  = { .type = NLA_UNSPEC },
+        [NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY]  = { .type = NLA_UNSPEC },
+        /*
+         * how many packages TX during statistics interval
+         */
+        [NL80211_TESTMODE_STA_STATISTICS_ENQUEUE]              = { .type = NLA_U32 },
+        /*
+         * how many packages this sta TX during statistics interval
+         */
+        [NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE]          = { .type = NLA_U32 },
+
+        /*
+         * how many packages dequeue during statistics interval
+         */
+        [NL80211_TESTMODE_STA_STATISTICS_DEQUEUE]              = { .type = NLA_U32 },
+
+        /*
+         * how many packages this sta dequeue during statistics interval
+         */
+        [NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE]          = { .type = NLA_U32 },
+
+        /*
+         * how many TC[0-3] resource back from firmware during
+         * statistics interval
+         */
+        [NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY]             = { .type = NLA_UNSPEC },
+        [NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY]          = { .type = NLA_UNSPEC },
+        [NL80211_TESTMODE_STA_STATISTICS_TC_USED_ARRAY]                = { .type = NLA_UNSPEC },
+        [NL80211_TESTMODE_STA_STATISTICS_TC_WANTED_ARRAY]              = { .type = NLA_UNSPEC },
+
+        [NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT]          = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT]     = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT]         = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT]           = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT]           = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT]           = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT]           = { .type = NLA_U32 },
+        [NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY]        = { .type = NLA_UNSPEC }
+    };
+
+    nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+        genlmsg_attrlen(gnlh, 0), NULL);
+
+    if (!tb[NL80211_ATTR_TESTDATA] ||
+        nla_parse_nested(sinfo, NL80211_TESTMODE_STA_STATISTICS_MAX, tb[NL80211_ATTR_TESTDATA], policy))
+        return NL_SKIP;
+
+    for (i=1; i < NL80211_TESTMODE_STA_STATISTICS_NUM; i++) {
+
+        if (!sinfo[i])
+            continue;
+
+        switch(i) {
+        case NL80211_TESTMODE_STA_STATISTICS_VERSION:
+            sta_statistics->version = nla_get_u8(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_MAC:
+            nla_memcpy(sta_statistics->addr, sinfo[i], ETH_ALEN);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE:
+            sta_statistics->link_score = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_FLAG:
+            sta_statistics->flag = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_PER:
+            sta_statistics->per = nla_get_u8(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_RSSI:
+            sta_statistics->rssi = (((int)nla_get_u8(sinfo[i]) - 220) / 2);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_PHY_MODE:
+            sta_statistics->phy_mode = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_TX_RATE:
+            sta_statistics->tx_rate = (((double)nla_get_u16(sinfo[i])) / 2);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT:
+            sta_statistics->tx_fail_cnt = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT:
+            sta_statistics->tx_timeout_cnt = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME:
+            sta_statistics->tx_avg_air_time = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT:
+            sta_statistics->tx_total_cnt = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT:
+            sta_statistics->tx_exc_threshold_cnt = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME:
+            sta_statistics->tx_avg_process_time = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME:
+            sta_statistics->tx_max_process_time = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME:
+            sta_statistics->tx_avg_hif_process_time = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME:
+            sta_statistics->tx_max_hif_process_time = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY:
+            nla_memcpy(sta_statistics->tc_buf_full_cnt, sinfo[i], sizeof(sta_statistics->tc_buf_full_cnt));
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY:
+            nla_memcpy(sta_statistics->tc_que_len, sinfo[i], sizeof(sta_statistics->tc_que_len));
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY:
+            nla_memcpy(sta_statistics->tc_avg_que_len, sinfo[i], sizeof(sta_statistics->tc_avg_que_len));
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY:
+            nla_memcpy(sta_statistics->tc_cur_que_len, sinfo[i], sizeof(sta_statistics->tc_cur_que_len));
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_ENQUEUE:
+            sta_statistics->enqueue_total_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_DEQUEUE:
+            sta_statistics->dequeue_total_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE:
+            sta_statistics->enqueue_sta_total_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE:
+            sta_statistics->dequeue_sta_total_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT:
+            sta_statistics->isr_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT:
+            sta_statistics->isr_pass_cnt = nla_get_u32(sinfo[i]);
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT:
+            sta_statistics->isr_task_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT:
+            sta_statistics->isr_ab_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT:
+            sta_statistics->isr_sw_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT:
+            sta_statistics->isr_tx_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT:
+            sta_statistics->isr_rx_cnt = nla_get_u32(sinfo[i]);
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY:
+            nla_memcpy(sta_statistics->dequeue_no_tc_res, sinfo[i],
+                      sizeof(sta_statistics->dequeue_no_tc_res));
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_TC_USED_ARRAY:
+            nla_memcpy(sta_statistics->tc_used_res, sinfo[i],
+                      sizeof(sta_statistics->tc_used_res));
+            break;
+        case NL80211_TESTMODE_STA_STATISTICS_TC_WANTED_ARRAY:
+            nla_memcpy(sta_statistics->tc_wanted_res, sinfo[i],
+                      sizeof(sta_statistics->tc_wanted_res));
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY:
+            nla_memcpy(sta_statistics->tc_back_count, sinfo[i],
+                      sizeof(sta_statistics->tc_back_count));
+            break;
+
+        case NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY:
+             nla_memcpy(sta_statistics->reserved, sinfo[i], sizeof(sta_statistics->reserved));
+             break;
+        default:
+            break;
+        }
+    }
+
+    return NL_SKIP;
+}
+
+#ifdef CONFIG_MTK_LTE_COEX
+static int testmode_available_channel_handler(struct nl_msg *msg, void *arg)
+{
+    struct nlattr *tb[NL80211_ATTR_MAX + 1] = {};
+    struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+    struct nlattr *tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX + 1] = {};
+    struct wpa_driver_available_chan_s *available_chans = (struct wpa_driver_available_chan_s *)arg;
+    static struct nla_policy chan_policy[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX + 1] = {
+        [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1]   = { .type = NLA_U32 },
+        [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36]  = { .type = NLA_U32 },
+        [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52]  = { .type = NLA_U32 },
+        [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100] = { .type = NLA_U32 },
+        [NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149] = { .type = NLA_U32 },
+    };
+
+    nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+            genlmsg_attrlen(gnlh, 0), NULL);
+
+    if (!tb[NL80211_ATTR_TESTDATA] ||
+        nla_parse_nested(tb_chan, NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX, tb[NL80211_ATTR_TESTDATA], chan_policy))
+        return NL_SKIP;
+
+    if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1])
+        available_chans->ch_2g_base1 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1]);
+
+    if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36])
+        available_chans->ch_5g_base36 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36]);
+
+    if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52])
+        available_chans->ch_5g_base52 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52]);
+
+    if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100])
+        available_chans->ch_5g_base100 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100]);
+
+    if (tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149])
+        available_chans->ch_5g_base149 = nla_get_u32(tb_chan[NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149]);
+
+    return NL_SKIP;
+}
+#endif
+
+static int wpa_driver_nl80211_testmode(void *priv, const u8 *data, size_t data_len)
+{
+    struct i802_bss *bss = priv;
+    struct wpa_driver_nl80211_data *drv = bss->drv;
+    struct nl_msg *msg, *cqm = NULL;
+    struct wpa_driver_testmode_params *params;
+    int index;
+
+    msg = nlmsg_alloc();
+    if (!msg)
+        return -1;
+
+    wpa_printf(MSG_DEBUG, "nl80211 test mode: ifindex=%d", drv->ifindex);
+
+    nl80211_cmd(drv, msg, 0, NL80211_CMD_TESTMODE);
+
+    NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
+    NLA_PUT(msg, NL80211_ATTR_TESTDATA, data_len, data);
+
+    params = (struct wpa_driver_testmode_params *)data;
+
+    /* Mask version field */
+    index = params->hdr.index & BITS(0, 23);
+
+    switch(index) {
+        case 0x10:
+        {
+            struct wpa_driver_get_sta_statistics_params *sta_params =
+                           (struct wpa_driver_get_sta_statistics_params *)data;
+            return send_and_recv_msgs(drv, msg, testmode_sta_statistics_handler, sta_params->buf);
+        }
+#ifdef CONFIG_MTK_LTE_COEX
+        case 0x30:
+        {
+            struct wpa_driver_get_available_channel_params *chan_params =
+                           (struct wpa_driver_get_available_channel_params *)data;
+            return send_and_recv_msgs(drv, msg, testmode_available_channel_handler, chan_params->buf);
+        }
+#endif
+        default:
+        {
+            int ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+            wpa_printf(MSG_EXCESSIVE, "ret=%d, nl=%p", ret, drv->global->nl);
+            return ret;
+        }
+    }
+
+nla_put_failure:
+    nlmsg_free(msg);
+    return -ENOBUFS;
+}
+
+static int wpa_driver_nl80211_driver_sw_cmd(void *priv, int set, u32 *adr, u32 *dat)
+{
+    struct i802_bss *bss = priv;
+    struct wpa_driver_nl80211_data *drv = bss->drv;
+    struct wpa_driver_sw_cmd_params params;
+    struct nl_msg *msg, *cqm = NULL;
+    int ret = 0;
+
+    os_memset(&params, 0, sizeof(params));
+
+    params.hdr.index = NL80211_TESTMODE_SW_CMD;
+    params.hdr.index = params.hdr.index | (0x01 << 24);
+    params.hdr.buflen = sizeof(struct wpa_driver_sw_cmd_params);
+
+    params.adr = *adr;
+    params.data = *dat;
+
+    if (set)
+        params.set = 1;
+    else
+        params.set = 0;
+
+    wpa_driver_nl80211_testmode(priv, (u8 *)&params, sizeof(struct wpa_driver_sw_cmd_params));
+    return 0;
+}
+
+#ifdef CONFIG_HOTSPOT_MGR_SUPPORT
+static int wpa_driver_hotspot_block_list_update(void *priv, const u8 *bssid, int blocked)
+{
+    struct wpa_driver_hotspot_params params;
+
+    os_memset(&params, 0, sizeof(params));
+
+    if (bssid)
+        os_memcpy(params.bssid, bssid, ETH_ALEN);
+
+    params.blocked = (u8)blocked;
+
+    params.hdr.index = NL80211_TESTMODE_HS20;
+    params.hdr.index = params.hdr.index | (0x01 << 24);
+    params.hdr.buflen = sizeof(struct wpa_driver_hotspot_params);
+
+    return wpa_driver_nl80211_testmode(priv, (u8 *)&params,
+        sizeof(struct wpa_driver_hotspot_params));
+}
+
+static int wpa_driver_sta_block(void *priv, char *cmd)
+{
+    u8 bssid[ETH_ALEN] = {};
+    int blocked = 1;
+
+    /* Block client device */
+    if (hwaddr_aton(cmd, bssid)) {
+        wpa_printf(MSG_DEBUG, "STA block: invalid DEVICE ADDRESS '%s'", cmd);
+        return -1;
+    }
+
+    wpa_printf(MSG_DEBUG, "Block STA " MACSTR, MAC2STR(bssid));
+    return wpa_driver_hotspot_block_list_update(priv, bssid, blocked);
+}
+
+static int wpa_driver_sta_unblock(void *priv, char *cmd)
+{
+    u8 bssid[ETH_ALEN] = {};
+    int blocked = 0;
+
+    /* Unblock client device */
+    if (hwaddr_aton(cmd, bssid)) {
+        wpa_printf(MSG_DEBUG, "STA unblock : invalid DEVICE ADDRESS '%s'", cmd);
+        return -1;
+    }
+
+    wpa_printf(MSG_DEBUG, "Unblock STA " MACSTR, MAC2STR(bssid));
+    return wpa_driver_hotspot_block_list_update(priv, bssid, blocked);
+}
+
+static int wpa_driver_set_max_client(void *priv, char *cmd, char *buf, size_t buflen)
+{
+    char *str = NULL;
+    int len = 0;
+    int value = 0;
+    struct wpa_driver_hotspot_set_config_params params;
+
+    os_memset(&params, 0, sizeof(params));
+
+    value = atoi(cmd);
+
+    wpa_printf(MSG_DEBUG, "CTRL_IFACE set_max_connect value=%d\n", value);
+
+    params.hdr.index = NL80211_TESTMODE_HS_SET_CONFIG;
+    params.hdr.index = params.hdr.index | (0x01 << 24);
+    params.hdr.buflen = sizeof(struct wpa_driver_hotspot_set_config_params);
+
+    params.index = 1;
+    params.value = (u32)value;
+
+    return wpa_driver_nl80211_testmode(priv, (u8 *)&params,
+        sizeof(struct wpa_driver_hotspot_set_config_params));
+}
+#endif /* CONFIG_HOTSPOT_MGR_SUPPORT */
+
+#ifdef CONFIG_MTK_LTE_COEX
+int wpa_driver_get_lte_available_channels(void *priv, struct wpa_driver_available_chan_s *buf)
+{
+    struct wpa_driver_get_available_channel_params params;
+
+    os_memset(&params, 0, sizeof(params));
+
+    params.hdr.index = 0x30;
+    params.hdr.index = params.hdr.index | (0x01 << 24);
+    params.hdr.buflen = sizeof(struct wpa_driver_get_available_channel_params);
+    /* buffer for return structure */
+    params.buf = (u8 *)buf;
+    return wpa_driver_nl80211_testmode(priv, (u8 *)&params,
+        sizeof(struct wpa_driver_get_available_channel_params));
+}
+
+static u8 wpa_driver_do_mtk_acs(void *priv)
+{
+    struct wpa_driver_available_chan_s available_chans;
+    u8  ch[14];
+    int ch_num, i;
+    int wait_cnt = 0;
+
+    do {
+        os_memset(&available_chans, 0, sizeof(struct wpa_driver_available_chan_s));
+        wpa_driver_get_lte_available_channels(priv, &available_chans);
+
+        if (BIT(31) & available_chans.ch_2g_base1) {
+            wpa_printf(MSG_DEBUG, "2G Channel: 0x%08x", available_chans.ch_2g_base1);
+            break;
+        } else {
+            wpa_printf(MSG_DEBUG, "2G Channel: 0x%08x, waiting for scan complete",
+                available_chans.ch_2g_base1);
+            wait_cnt++;
+            if (wait_cnt > 5)
+                return 0;
+            os_sleep(0, 1000*350);
+        }
+    } while(1);
+
+    os_memset(ch, 0, sizeof(ch));
+    ch_num = 0;
+
+    for (i = 0; i < 14; i++) {
+        if (BIT(i) & available_chans.ch_2g_base1) {
+            ch[ch_num] = i + 1;
+            ch_num++;
+        } else
+            continue;
+    }
+
+    wpa_printf(MSG_DEBUG, "Driver report 2G available %d channel", ch_num);
+    for (i = 0; i < ch_num; i++)
+        wpa_printf(MSG_DEBUG,"Channel %d is fine", ch[i]);
+
+    return ch[0];
+}
+#endif /* CONFIG_MTK_LTE_COEX */
+
+#ifdef CONFIG_WAPI_SUPPORT
+int wpa_driver_nl80211_set_wapi_key(void *priv,
+    const u8 *addr, int key_idx,
+    int set_tx, const u8 *seq,
+    size_t seq_len,
+    const u8 *key, size_t key_len)
+{
+    struct i802_bss *bss = priv;
+    struct wpa_driver_nl80211_data *drv = bss->drv;
+    struct nl_msg *msg, *cqm = NULL;
+    struct wpa_driver_wapi_key_params params;
+    int ret = 0;
+
+    os_memset(&params, 0, sizeof(params));
+
+    params.hdr.index = NL80211_TESTMODE_WAPI;
+    params.hdr.index = params.hdr.index | (0x01 << 24);
+    params.hdr.buflen = sizeof(struct wpa_driver_wapi_key_params);
+
+    wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]1 %s: ", __FUNCTION__);
+
+    if (seq_len > IW_ENCODE_SEQ_MAX_SIZE * 2) {
+        wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]%s: Invalid seq_len %lu",
+            __FUNCTION__, (unsigned long)seq_len);
+        return -1;
+    }
+
+    params.key_index = key_idx + 1;
+    params.key_len = key_len;
+
+    if (addr == NULL ||
+        os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", ETH_ALEN) == 0)
+        params.extparams.ext_flags |= IW_ENCODE_EXT_GROUP_KEY;
+    if (set_tx)
+        params.extparams.ext_flags |= IW_ENCODE_EXT_SET_TX_KEY;
+
+    if (addr)
+        os_memcpy(params.extparams.addr, addr, ETH_ALEN);
+    else
+        os_memset(params.extparams.addr, 0xff, ETH_ALEN);
+
+    if (key && key_len) {
+        os_memcpy(params.extparams.key, key, key_len);
+        params.extparams.key_len = key_len;
+    }
+
+    wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]2 %s:", __FUNCTION__);
+
+    wpa_printf(MSG_DEBUG, "%s: Set IW_ENCODE_ALG_SMS4 to ext->alg",
+        __FUNCTION__);
+
+    params.extparams.alg = IW_ENCODE_ALG_SMS4;
+
+    wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]3 %s: ", __FUNCTION__);
+
+    if (seq && seq_len)
+        os_memcpy(params.extparams.tx_seq, seq, seq_len);
+
+    wpa_hexdump(MSG_DEBUG, "seq", seq, seq_len);
+
+    wpa_printf(MSG_DEBUG, "[WAPI-DEBUG]4 Copy buffer %s: ", __FUNCTION__);
+
+    wpa_driver_nl80211_testmode(priv, (u8 *)&params, sizeof(struct wpa_driver_wapi_key_params));
+
+    return 0;
+}
+
+/**
+* wpa_driver_nl80211_send_msg - send some information to driver
+* @priv: private driver interface data from init()
+* @msg_in: the message sent to driver
+* @msg_in_len: the length of sent message
+* @msg_out: the message given back from driver
+* @msg_out_len: the length of message given back from driver
+*
+* Returns: 0 on success, -1 on failure
+*
+*/
+static int wpa_driver_nl80211_send_msg(void *priv, const u8 *msg_in, int msg_in_len,
+    u8 *msg_out, int *msg_out_len)
+{
+    struct i802_bss *bss = priv;
+    struct wpa_driver_nl80211_data *drv = bss->drv;
+    int ret = 0;
+
+    if (msg_in_len > 1024) {
+        wpa_printf(MSG_DEBUG, "wpa_driver_nl80211_send_msg: msg too long");
+        return -1;
+    }
+
+    return ret;
+}
+#endif /* CONFIG_WAPI_SUPPORT */
+
+static inline int wpa_drv_set_test_mode(struct wpa_supplicant *wpa_s,
+    const u8 *buf, size_t buf_len)
+{
+    return wpa_driver_nl80211_testmode(wpa_s->drv_priv, buf, buf_len);
+}
+
+
+/**********************************************************************
+* OVERLAPPED functins, previous defination is in driver_nl80211.c,
+* it will be modified
+***********************************************************************/
+
+/**********************************************************************/
+extern int wpa_config_write(const char *name, struct wpa_config *config);
+
+static int wpa_driver_mediatek_set_country(void *priv, const char *alpha2_arg)
+{
+    struct i802_bss *bss = priv;
+    struct wpa_driver_nl80211_data *drv = bss->drv;
+    int ioctl_sock = -1;
+    struct iwreq iwr;
+    int ret = -1;
+    char buf[11];
+#ifdef MTK_TC1_FEATURE
+    char replace_ifname[IFNAMSIZ+1];
+
+    memset(replace_ifname, 0, IFNAMSIZ+1);
+    os_strlcpy(replace_ifname, "wlan0", os_strlen("wlan0")+1);
+#endif
+
+    ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
+    if (ioctl_sock < 0) {
+        wpa_printf(MSG_ERROR, "%s: socket(PF_INET,SOCK_DGRAM)", __func__);
+        return -1;
+    }
+    os_memset(&iwr, 0, sizeof(iwr));
+#ifdef MTK_TC1_FEATURE
+    // convert 'p2p0' -> 'wlan0' :
+    // when iface name is p2p0, COUNTRY driver command doesn't support in MTK solution.
+    if (os_strncmp(drv->first_bss->ifname, "p2p0", os_strlen("p2p0")) == 0) {
+        wpa_printf(MSG_DEBUG, "Change interface name : p2p0->wlan0");
+        os_strlcpy(iwr.ifr_name, replace_ifname, IFNAMSIZ );
+    } else {
+        os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ);
+    }
+#else
+    os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ);
+#endif
+    snprintf(buf, sizeof(buf), "COUNTRY %s", alpha2_arg);
+    iwr.u.data.pointer = buf;
+    iwr.u.data.length = strlen(buf);
+    if ((ret = ioctl(ioctl_sock, 0x8B0C, &iwr)) < 0) {  // SIOCSIWPRIV
+        wpa_printf(MSG_DEBUG, "ioctl[SIOCSIWPRIV]: %s", buf);
+        close(ioctl_sock);
+        return ret;
+    }
+    else {
+        close(ioctl_sock);
+        return 0;
+    }
+
+}
+
+/*
+* update channel list in wpa_supplicant
+* if coutry code chanaged
+*/
+static void wpa_driver_notify_country_change(struct wpa_global *global, char *cmd)
+{
+    struct wpa_supplicant *wpa_s;
+
+    if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
+        union wpa_event_data event;
+
+        os_memset(&event, 0, sizeof(event));
+        event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+        if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
+            event.channel_list_changed.type = REGDOM_TYPE_COUNTRY;
+            if (os_strlen(cmd) > 9) {
+                event.channel_list_changed.alpha2[0] = cmd[8];
+                event.channel_list_changed.alpha2[1] = cmd[9];
+            }
+        } else {
+            event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
+        }
+        // Notify all interfaces
+        for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+            wpa_supplicant_event(wpa_s, EVENT_CHANNEL_LIST_CHANGED, &event);
+        }
+    }
+}
+
+/**
+ * mtk_p2p_get_device - Fetch a peer entry
+ * @p2p: P2P module context from p2p_init()
+ * @addr: P2P Device Address of the peer
+ * Returns: Pointer to the device entry or %NULL if not found
+ */
+struct p2p_device *mtk_p2p_get_device(struct p2p_data *p2p, const u8 *addr)
+{
+    struct p2p_device *dev;
+
+    dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
+        if (memcmp(dev->info.p2p_device_addr, addr, ETH_ALEN) == 0)
+            return dev;
+    }
+    return NULL;
+}
+/*
+ * we should use interface MAC address
+ * instead of device MAC when query
+ * STA statistics, as driver uses interface addr
+ * to do TX/RX
+ * In most cases, the interface addr and device addr
+ * should be the same
+ */
+u8 *wpas_p2p_get_sta_mac(struct wpa_supplicant *wpa_s, u8 *org_addr)
+{
+    struct p2p_data *p2p = wpa_s->global->p2p;
+    struct wpa_ssid *ssid = wpa_s->current_ssid;
+    struct p2p_device *dev = NULL;
+    int is_p2p_client = 0;
+
+    if (!p2p) {
+        wpa_printf(MSG_DEBUG, "interface %s not support p2p", wpa_s->ifname);
+        return NULL;
+    }
+
+    if (!ssid) {
+        wpa_printf(MSG_DEBUG, "P2P: ssid not connected");
+        return NULL;
+    }
+
+    dev = mtk_p2p_get_device(p2p, org_addr);
+
+    if (!dev) {
+        wpa_printf(MSG_DEBUG, "P2P: device " MACSTR "not found",
+                   MAC2STR(org_addr));
+        return NULL;
+    }
+
+    is_p2p_client = ssid->mode == WPAS_MODE_INFRA ? 1 : 0;
+
+    if (is_p2p_client) {
+        if (memcmp(dev->info.p2p_device_addr, wpa_s->bssid, ETH_ALEN) &&
+            !is_zero_ether_addr(wpa_s->bssid)) {
+            wpa_printf(MSG_DEBUG, "P2P: we are GC, Use interface_addr "
+                        MACSTR "instead of " MACSTR,
+                        MAC2STR(wpa_s->bssid),
+                        MAC2STR(org_addr));
+            return wpa_s->bssid;
+        }
+    }
+
+    /*
+     * we are GO, interface_addr should be filled
+     * when RX NL80211_CMD_NEW_STA event
+     * if it is defferent between device addr and interface addr
+     */
+    if (memcmp(dev->info.p2p_device_addr, dev->interface_addr, ETH_ALEN) &&
+        !is_zero_ether_addr(dev->interface_addr)) {
+        wpa_printf(MSG_DEBUG, "P2P: we are GO, Use interface_addr " MACSTR
+                 "instead of " MACSTR,
+                 MAC2STR(dev->interface_addr),
+                 MAC2STR(org_addr));
+        return dev->interface_addr;
+    }
+    return NULL;
+}
+
+/* Move GET_STA_STATISTICS to "DRIVER GET_STA_STATISTICS", implement in 3rd part lib */
+/* [ALPS00618361] [WFD Quality Enhancement] */
+int wpas_get_sta_statistics(struct wpa_supplicant *wpa_s, u8 *sta_addr, u8 *buf)
+{
+    struct wpa_driver_get_sta_statistics_params params;
+
+    os_memset(&params, 0, sizeof(params));
+
+    if(sta_addr)
+        os_memcpy(params.addr, sta_addr, ETH_ALEN);
+
+    wpa_printf(MSG_DEBUG, "get_sta_statistics ["MACSTR"]", MAC2STR(params.addr));
+
+    params.hdr.index = NL80211_TESTMODE_STATISTICS;
+    params.hdr.index = params.hdr.index | (0x01 << 24);
+    params.hdr.buflen = sizeof(struct wpa_driver_get_sta_statistics_params);
+
+    /* buffer for return structure */
+    params.buf = buf;
+
+    return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&params,
+        sizeof(struct wpa_driver_get_sta_statistics_params));
+}
+
+/*  [ALPS00618361] [WFD Quality Enhancement] [changelist 1686130] */
+static int print_sta_statistics(struct wpa_supplicant *wpa_s, struct wpa_driver_sta_statistics_s *sta_stats,
+              unsigned long mask, char *buf, size_t buflen)
+{
+    size_t i;
+    int ret;
+    char *pos, *end;
+
+    pos = buf;
+    end = buf + buflen;
+
+    ret = os_snprintf(pos, end - pos, "sta_addr="MACSTR"\n", MAC2STR(sta_stats->addr));
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "link_score=%d\n", sta_stats->link_score);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "per=%d\n", sta_stats->per);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "rssi=%d\n", sta_stats->rssi);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "phy=0x%08X\n", sta_stats->phy_mode);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "rate=%.1f\n", sta_stats->tx_rate);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "total_cnt=%d\n", sta_stats->tx_total_cnt);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "threshold_cnt=%d\n", sta_stats->tx_exc_threshold_cnt);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "fail_cnt=%d\n", sta_stats->tx_fail_cnt);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "timeout_cnt=%d\n", sta_stats->tx_timeout_cnt);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "apt=%d\n", sta_stats->tx_avg_process_time);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "aat=%d\n", sta_stats->tx_avg_air_time);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "TC_buf_full_cnt=%d:%d:%d:%d\n",
+                      sta_stats->tc_buf_full_cnt[TC0_INDEX],
+                      sta_stats->tc_buf_full_cnt[TC1_INDEX],
+                      sta_stats->tc_buf_full_cnt[TC2_INDEX],
+                      sta_stats->tc_buf_full_cnt[TC3_INDEX]);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "TC_sta_que_len=%d:%d:%d:%d\n",
+                      sta_stats->tc_que_len[TC0_INDEX],
+                      sta_stats->tc_que_len[TC1_INDEX],
+                      sta_stats->tc_que_len[TC2_INDEX],
+                      sta_stats->tc_que_len[TC3_INDEX]);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "TC_avg_que_len=%d:%d:%d:%d\n",
+                      sta_stats->tc_avg_que_len[TC0_INDEX],
+                      sta_stats->tc_avg_que_len[TC1_INDEX],
+                      sta_stats->tc_avg_que_len[TC2_INDEX],
+                      sta_stats->tc_avg_que_len[TC3_INDEX]);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "TC_cur_que_len=%d:%d:%d:%d\n",
+                      sta_stats->tc_cur_que_len[TC0_INDEX],
+                      sta_stats->tc_cur_que_len[TC1_INDEX],
+                      sta_stats->tc_cur_que_len[TC2_INDEX],
+                      sta_stats->tc_cur_que_len[TC3_INDEX]);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "flag=0x%08X\n", sta_stats->flag);
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "reserved0=");
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+    for (i = 0; i < 16; i++) {
+        ret = os_snprintf(pos, end - pos, "%02X", sta_stats->reserved[i]);
+        if (ret < 0 || ret >= end - pos)
+            return 0;
+        pos += ret;
+
+        if (((i + 1) % 4) == 0) {
+            ret = os_snprintf(pos, end - pos, " ");
+            if (ret < 0 || ret >= end - pos)
+                return 0;
+            pos += ret;
+        }
+    }
+    ret = os_snprintf(pos, end - pos, "\n");
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "reserved1=");
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+    for (i = 16; i < 32; i++) {
+        ret = os_snprintf(pos, end - pos, "%02X", sta_stats->reserved[i]);
+        if (ret < 0 || ret >= end - pos)
+            return 0;
+        pos += ret;
+
+        if (((i + 1) % 4) == 0) {
+            ret = os_snprintf(pos, end - pos, " ");
+            if (ret < 0 || ret >= end - pos)
+                return 0;
+            pos += ret;
+        }
+    }
+    ret = os_snprintf(pos, end - pos, "\n");
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    ret = os_snprintf(pos, end - pos, "====\n");
+    if (ret < 0 || ret >= end - pos)
+        return 0;
+    pos += ret;
+
+    return pos - buf;
+}
+
+/*  [ALPS00618361] [WFD Quality Enhancement] [changelist 1686130] */
+static void format_sta_statistics(struct wpa_driver_sta_statistics_s *s)
+{
+       wpa_printf(MSG_DEBUG, "NWFD: Basic info* AVG:%4d:EN:%4d:DE:%4d:SEN:%4d:SDE:%4d:HIF:%4d",
+               s->tx_avg_process_time,
+               s->enqueue_total_cnt,
+               s->dequeue_total_cnt,
+               s->enqueue_sta_total_cnt,
+               s->dequeue_sta_total_cnt,
+               s->tx_total_cnt);
+
+       wpa_printf(MSG_DEBUG, "NWFD: Time info* TTL:%4d:AVG:%4d:MAX:%4d:HIFAVG:%4d:HIFMAX:%4d",
+               s->tx_total_cnt,
+               s->tx_avg_process_time,
+               s->tx_max_process_time,
+               s->tx_avg_hif_process_time,
+               s->tx_max_hif_process_time);
+
+       wpa_printf(MSG_DEBUG, "NWFD: No TC RES* Score:%4d:EN:%4d#%4d#%4d#%4d:DE:%4d#%4d#%4d#%4d",
+               s->link_score,
+               s->tc_buf_full_cnt[TC0_INDEX],
+               s->tc_buf_full_cnt[TC1_INDEX],
+               s->tc_buf_full_cnt[TC2_INDEX],
+               s->tc_buf_full_cnt[TC3_INDEX],
+               s->dequeue_no_tc_res[TC0_INDEX],
+               s->dequeue_no_tc_res[TC1_INDEX],
+               s->dequeue_no_tc_res[TC2_INDEX],
+               s->dequeue_no_tc_res[TC3_INDEX]);
+
+       wpa_printf(MSG_DEBUG, "NWFD: Irq info* T:%4d:P:%4d:TT:%4d:A:%4d:S:%4d:R:%4d:T:%4d",
+               s->isr_cnt,
+               s->isr_pass_cnt,
+               s->isr_task_cnt,
+               s->isr_ab_cnt,
+               s->isr_sw_cnt,
+               s->isr_rx_cnt,
+               s->isr_tx_cnt);
+
+       /*
+        * TC resouce information: format:
+        * 1. how many TC resource wanted during statistics intervals
+        * 2. how many TC resource acquire successfully
+        * 3. how many TC resource back during statistics intervals
+        */
+       wpa_printf(MSG_DEBUG, "NWFD: TC Res info[W:U:B]* Score:%4d:"
+               "#%5d:%5d:%5d#"
+               "#%5d:%5d:%5d#"
+               "#%5d:%5d:%5d#"
+               "#%5d:%5d:%5d#",
+               s->link_score,
+               s->tc_wanted_res[TC0_INDEX],
+               s->tc_used_res[TC0_INDEX],
+               s->tc_back_count[TC0_INDEX],
+
+               s->tc_wanted_res[TC1_INDEX],
+               s->tc_used_res[TC1_INDEX],
+               s->tc_back_count[TC1_INDEX],
+
+               s->tc_wanted_res[TC2_INDEX],
+               s->tc_used_res[TC2_INDEX],
+               s->tc_back_count[TC2_INDEX],
+
+               s->tc_wanted_res[TC3_INDEX],
+               s->tc_used_res[TC3_INDEX],
+               s->tc_back_count[TC3_INDEX]);
+}
+
+int wpa_driver_get_sta_statistics(struct wpa_supplicant *wpa_s, char *addr,
+                                char *buf, size_t buflen)
+{
+    char *str = NULL;
+    int len = 0;
+    u8 sta_addr[ETH_ALEN];
+    u8 *mac = NULL;
+    struct wpa_driver_sta_statistics_s sta_statistics;
+
+    memset(&sta_statistics, 0 ,sizeof(sta_statistics));
+
+    if (hwaddr_aton(addr, sta_addr)) {
+        wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_STA_STATISTICS: invalid "
+                   "address '%s'", addr);
+        return -1;
+    }
+
+    mac = wpas_p2p_get_sta_mac(wpa_s, sta_addr);
+
+    if (wpas_get_sta_statistics(wpa_s, mac ? mac : sta_addr,
+        (u8 *)&sta_statistics) < 0) {
+        wpa_printf(MSG_DEBUG, "CTRL_IFACE GET_STA_STATISTICS: command failed");
+        return -1;
+    }
+    len = print_sta_statistics(wpa_s, &sta_statistics, 0x00, buf, buflen);
+
+    format_sta_statistics(&sta_statistics);
+    return len;
+}
+
+#ifdef CONFIG_MTK_P2P_SIGMA
+static int wpas_p2p_sigma_test_mode(struct wpa_supplicant *wpa_s, int index, int value)
+{
+    struct wpa_driver_p2p_sigma_params params;
+
+    os_memset(&params, 0, sizeof(params));
+
+    params.hdr.index = 1;
+    params.hdr.index = params.hdr.index | (0x01 << 24);
+    params.hdr.buflen = sizeof(struct wpa_driver_p2p_sigma_params);
+
+    params.idx = (u32)index;
+    params.value = (u32)value;
+
+    return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&params,
+        sizeof(struct wpa_driver_p2p_sigma_params));
+}
+
+static int p2p_ctrl_iface_set_opps(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
+{
+    char *str = NULL;
+    u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+    int len = 0;
+    size_t ssid_len = 0;
+    char *ssid;
+    int CTWin;
+
+    wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps cmd=%s\n", cmd);
+
+    CTWin = atoi(cmd);
+
+    str = os_strchr(cmd, ' ');
+    if (str) {
+        *str ++ = '\0';
+
+        if (hwaddr_aton(str, addr))
+            return -1;
+    }
 
-/**********************************************************************
-* OVERLAPPED functins, previous defination is in driver_nl80211.c,
-* it will be modified
-***********************************************************************/
+    str = os_strchr(str, ' ');
+    if (str) {
+        *str ++ = '\0';
 
-/**********************************************************************/
-static int wpa_driver_mediatek_set_country(void *priv, const char *alpha2_arg)
+        ssid = wpa_config_parse_string(str, &ssid_len);
+        if (ssid) {
+            wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps CTWin=%d "MACSTR" SSID(%zu)%s\n",
+                CTWin, MAC2STR(addr), ssid_len, ssid);
+            os_free(ssid);
+        }
+        else {
+            wpa_printf(MSG_DEBUG, "CTRL_IFACE set_opps CTWin=%d "MACSTR" SSID(%zu)\n",
+                CTWin, MAC2STR(addr), ssid_len);
+        }
+    }
+
+    wpas_p2p_sigma_test_mode(wpa_s, 107, (int)CTWin);
+
+    //len = os_snprintf(buf, buflen, "return OK");
+
+    return len;
+}
+
+static int p2p_ctrl_iface_set_power_save(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
 {
-    struct i802_bss *bss = priv;
-    struct wpa_driver_nl80211_data *drv = bss->drv;
-    int ioctl_sock = -1;
-    struct iwreq iwr;
-    int ret = -1;
-    char buf[11];
-#ifdef MTK_TC1_FEATURE
-    char replace_ifname[IFNAMSIZ+1];
+    char *str = NULL;
+    int len = 0;
+    int value = 0;
 
-    memset(replace_ifname, 0, IFNAMSIZ+1);
-    os_strlcpy(replace_ifname, "wlan0", os_strlen("wlan0")+1);
-#endif
+    wpa_printf(MSG_DEBUG, "CTRL_IFACE set_power_save cmd=%s\n", cmd);
 
-    wpa_printf(MSG_DEBUG, "wpa_driver_nl80211_set_country");
-    ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
-    if (ioctl_sock < 0) {
-        wpa_printf(MSG_ERROR, "%s: socket(PF_INET,SOCK_DGRAM)", __func__);
+    value = atoi(cmd);
+
+    wpa_printf(MSG_DEBUG, "CTRL_IFACE set_power_save value=%d\n", value);
+
+    wpas_p2p_sigma_test_mode(wpa_s, 108, (int)value);
+
+    //len = os_snprintf(buf, buflen, "return OK");
+
+    return len;
+
+}
+
+static int p2p_ctrl_iface_set_sleep(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
+{
+    char *str = NULL;
+    u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+    int len = 0;
+    size_t ssid_len = 0;
+    char *ssid;
+
+    if (hwaddr_aton(cmd, addr))
         return -1;
+
+    str = os_strchr(cmd, ' ');
+    if (str) {
+        *str ++ = '\0';
+
+        ssid = wpa_config_parse_string(str, &ssid_len);
+        if (ssid) {
+            wpa_printf(MSG_DEBUG, "CTRL_IFACE set_sleep "MACSTR" SSID(%zu)%s\n",
+                MAC2STR(addr), ssid_len, ssid);
+            os_free(ssid);
+        }
+        else {
+            wpa_printf(MSG_DEBUG, "CTRL_IFACE set_sleep "MACSTR" SSID(%zu)\n",
+                MAC2STR(addr), ssid_len);
+        }
     }
-    os_memset(&iwr, 0, sizeof(iwr));
-#ifdef MTK_TC1_FEATURE
-    // convert 'p2p0' -> 'wlan0' :
-    // when iface name is p2p0, COUNTRY driver command doesn't support in MTK solution.
-    if (os_strncmp(drv->first_bss->ifname, "p2p0", os_strlen("p2p0")) == 0) {
-        wpa_printf(MSG_DEBUG, "Change interface name : p2p0->wlan0");
-        os_strlcpy(iwr.ifr_name, replace_ifname, IFNAMSIZ );
-    } else {
-        os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ);
+
+    wpas_p2p_sigma_test_mode(wpa_s, 106, 0);
+
+    //len = os_snprintf(buf, buflen, "return OK");
+
+    return len;
+
+}
+#endif /* CONFIG_MTK_P2P_SIGMA */
+
+/* utils for parse cmdline:
+ * cmd: paramters in cmd line
+ * argv: paramter vector
+ * len: cmd lenght
+ * example:
+ * cmd = "driver P2P_SET_NOA 1 2 3"
+ * argv[0] = "driver"
+ * argv[1] = "P2P_SET_NOA"
+ * argv[2] = "1"
+ * argv[3] = "2"
+ * argv[4] = "3"
+ */
+
+int tokenize_space(char *cmd, char *argv[], int len)
+{
+    char *pos;
+    char *start;
+    int argc = 0;
+
+    start = pos = cmd;
+    for (;;) {
+        argv[argc] = pos;
+        argc++;
+        while (*pos != '\n' && *pos != ' ' && *pos != '\0') {
+            pos++;
+            if (pos - start >= len)
+                break;
+        }
+
+        if (*pos == '\0')
+            break;
+
+        if (*pos == '\n' || *pos == ' ') {
+            *pos++ = '\0';
+            if (pos - start >= len)
+                break;
+        }
     }
-#else
-    os_strlcpy(iwr.ifr_name, drv->first_bss->ifname, IFNAMSIZ);
-#endif
-    sprintf(buf, "COUNTRY %s", alpha2_arg);
-    iwr.u.data.pointer = buf;
-    iwr.u.data.length = strlen(buf);
-    if ((ret = ioctl(ioctl_sock, 0x8B0C, &iwr)) < 0) {  // SIOCSIWPRIV
-        wpa_printf(MSG_DEBUG, "ioctl[SIOCSIWPRIV]: %s", buf);
-        close(ioctl_sock);
-        return ret;
+
+    return argc;
+}
+
+static int p2p_ctrl_iface_set_noa(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
+{
+    struct wpa_driver_p2p_noa_params {
+        struct wpa_driver_test_mode_info hdr;
+        u32 idx;
+        u32 value; /* should not be used in this case */
+        u32 count;
+        u32 interval;
+        u32 duration;
+    };
+    char *argv[64];
+    int argc;
+    struct wpa_driver_p2p_noa_params noa_param;
+
+    os_memset(&noa_param, 0, sizeof(noa_param));
+
+    /* P2P_SET_NOA 255 100 3 */
+    /*
+     * argv format:
+     * argv[0] = "P2P_SET_NOA"
+     * argv[1] = "255"
+     * argv[2] = "100"
+     * argv[3] = "3"
+     */
+    argc = tokenize_space(cmd, argv, os_strlen(cmd));
+
+    if (argc != 4) {
+        wpa_printf(MSG_DEBUG, "P2P: NOA: invalid cmd format");
+        return -1;
     }
-    else {
-        close(ioctl_sock);
+
+    /* fill in the params structure */
+    noa_param.hdr.index = 1;
+    noa_param.hdr.index = noa_param.hdr.index | (0x01 << 24);
+    noa_param.hdr.buflen = sizeof(struct wpa_driver_p2p_noa_params);
+
+    noa_param.idx = 4;
+    noa_param.count = (u32)atoi(argv[1]);
+    noa_param.interval= (u32)atoi(argv[2]);
+    noa_param.duration= (u32)atoi(argv[3]);
+
+    wpa_printf(MSG_DEBUG, "P2P: set noa: %d %d %d",
+               noa_param.count,
+               noa_param.interval,
+               noa_param.duration);
+
+    return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&noa_param,
+                  sizeof(struct wpa_driver_p2p_noa_params));
+}
+
+static int p2p_ctrl_iface_set_ps(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
+{
+    char *argv[64];
+    int argc;
+    int enable;
+    s32 ctw;
+    struct wpa_driver_p2p_sigma_params opps_param;
+
+    os_memset(&opps_param, 0, sizeof(opps_param));
+
+    /* P2P_SET_PS 2 1 3
+     * argv format:
+     * argv[0] = "P2P_SET_PS"
+     * argv[1] = "2"
+     * argv[2] = "1"
+     * argv[3] = "3"
+     */
+    argc = tokenize_space(cmd, argv, os_strlen(cmd));
+
+    if (argc != 4) {
+        wpa_printf(MSG_DEBUG, "P2P: Opps: invalid cmd format");
+        return -1;
+    }
+
+    /* fill in the params structure */
+    opps_param.hdr.index = 1;
+    opps_param.hdr.index = opps_param.hdr.index | (0x01 << 24);
+    opps_param.hdr.buflen = sizeof(struct wpa_driver_p2p_sigma_params);
+
+    opps_param.idx = 107;
+
+    enable = atoi(argv[2]);
+    ctw = atoi(argv[3]);
+
+    /* BIT 7 control OPPS on / off */
+    if (enable)
+        ctw |= BIT(7);
+
+    opps_param.value = ctw;
+
+    wpa_printf(MSG_DEBUG, "P2P: set opps: 0x%x",
+               opps_param.value);
+
+    return wpa_driver_nl80211_testmode(wpa_s->drv_priv, (u8 *)&opps_param,
+             sizeof(struct wpa_driver_p2p_sigma_params));
+}
+
+#ifdef CONFIG_MTK_WFD_SINK
+static int wpas_wfd_data_update(struct wpa_supplicant *wpa_s, struct wfd_data_s *p_wfd_data)
+{
+    struct wpa_driver_wfd_data_s params;
+    os_memset(&params, 0, sizeof(params));
+
+    wpa_printf(MSG_DEBUG, "WFD: wpas_wfd_data_update wfd_en %u wfd_dev_info 0x%x wfd_ctrl_port %u wfd_state 0x%x",
+        p_wfd_data->WfdEnable, p_wfd_data->WfdDevInfo, p_wfd_data->WfdControlPort, p_wfd_data->WfdState);
+
+
+    params.hdr.index = 2;
+    params.hdr.index = params.hdr.index | (0x01 << 24);
+    params.hdr.buflen = sizeof(struct wfd_data_s);
+
+    params.WfdCmdType = p_wfd_data->WfdCmdType;
+    params.WfdEnable = p_wfd_data->WfdEnable;
+    params.WfdCoupleSinkStatus = p_wfd_data->WfdCoupleSinkStatus;
+    params.WfdDevInfo = p_wfd_data->WfdDevInfo;
+    params.WfdControlPort = p_wfd_data->WfdControlPort;
+    params.WfdMaximumTp = p_wfd_data->WfdMaximumTp;
+    params.WfdExtendCap = p_wfd_data->WfdExtendCap;
+    os_memcpy(params.WfdCoupleSinkAddress, p_wfd_data->WfdCoupleSinkAddress, ETH_ALEN);
+    os_memcpy(params.WfdAssociatedBssid, p_wfd_data->WfdAssociatedBssid, ETH_ALEN);
+    os_memcpy(params.WfdVideoIp, p_wfd_data->WfdVideoIp, sizeof(p_wfd_data->WfdVideoIp));
+    os_memcpy(params.WfdAudioIp, p_wfd_data->WfdAudioIp, sizeof(p_wfd_data->WfdAudioIp));
+    params.WfdVideoPort = p_wfd_data->WfdVideoPort;
+    params.WfdAudioPort = p_wfd_data->WfdAudioPort;
+    params.WfdFlag = p_wfd_data->WfdFlag;
+    params.WfdPolicy = p_wfd_data->WfdPolicy;
+    params.WfdState = p_wfd_data->WfdState;
+    params.WfdSessionInformationIELen = p_wfd_data->WfdSessionInformationIELen;
+    os_memcpy(params.WfdSessionInformationIE, p_wfd_data->WfdSessionInformationIE,
+        p_wfd_data->WfdSessionInformationIELen);
+    os_memcpy(params.WfdPrimarySinkMac, p_wfd_data->WfdPrimarySinkMac, ETH_ALEN);
+    os_memcpy(params.WfdSecondarySinkMac, p_wfd_data->WfdSecondarySinkMac, ETH_ALEN);
+    params.WfdAdvancedFlag = p_wfd_data->WfdAdvancedFlag;
+
+    params.WfdSessionAvailable = p_wfd_data->WfdSessionAvailable;
+    params.WfdSigmaMode = p_wfd_data->WfdSigmaMode;
+    os_memcpy(params.WfdLocalIp, p_wfd_data->WfdLocalIp, sizeof(p_wfd_data->WfdLocalIp));
+
+    return wpa_drv_set_test_mode(wpa_s, (u8 *)&params, sizeof(struct wpa_driver_wfd_data_s));
+}
+
+static int p2p_get_capability(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
+{
+    int ret = 0;
+    struct p2p_data *p2p = wpa_s->global->p2p;
+    wpa_printf(MSG_DEBUG, "%s %d, %d", __func__, __LINE__, p2p->dev_capab);
+    if (os_strncmp(cmd, "p2p_dev_capa", os_strlen("p2p_dev_capa")) == 0) {
+        ret = snprintf(buf, buflen, "p2p_dev_capa=%d\n", p2p->dev_capab);
+        wpa_printf(MSG_DEBUG, "%s %d %d, %s", __func__, __LINE__, p2p->dev_capab, buf);
+    } else if (os_strncmp(cmd, "p2p_group_capa", os_strlen("p2p_group_capa")) == 0) {
+        wpa_printf(MSG_DEBUG, "%s not implement", __func__);
+        ret = -1;
+    }
+    return ret;
+}
+
+static int p2p_set_capability(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
+{
+    int ret = 0;
+    wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__);
+    struct p2p_data *p2p = wpa_s->global->p2p;
+    if (os_strncmp(cmd, "p2p_dev_capa ", os_strlen("p2p_dev_capa ")) == 0) {
+        int old_cap = p2p->dev_capab;
+        int dev_cap = atoi(cmd + os_strlen("p2p_dev_capa "));
+        p2p->dev_capab = dev_cap & 0xff;
+        wpa_printf(MSG_DEBUG, "%s %d %d, %d", __func__, __LINE__, p2p->dev_capab,
+                            old_cap);
+    } else if (os_strncmp(cmd, "p2p_group_capa ", os_strlen("p2p_group_capa ")) == 0) {
+        wpa_printf(MSG_DEBUG, "%s group not implement", __func__);
+        ret = -1;
+    }
+    return ret;
+}
+
+/**
+ * priv_p2p_freq_to_channel - Convert frequency into channel info
+ * @op_class: Buffer for returning operating class
+ * @channel: Buffer for returning channel number
+ * Returns: 0 on success, -1 if the specified frequency is unknown
+ */
+static int priv_p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel)
+{
+    /* TODO: more operating classes */
+    if (freq >= 2412 && freq <= 2472) {
+        if ((freq - 2407) % 5)
+            return -1;
+
+        *op_class = 81; /* 2.407 GHz, channels 1..13 */
+        *channel = (freq - 2407) / 5;
+        return 0;
+    }
+
+    if (freq == 2484) {
+        *op_class = 82; /* channel 14 */
+        *channel = 14;
+        return 0;
+    }
+
+    if (freq >= 5180 && freq <= 5240) {
+        if ((freq - 5000) % 5)
+            return -1;
+
+        *op_class = 115; /* 5 GHz, channels 36..48 */
+        *channel = (freq - 5000) / 5;
+        return 0;
+    }
+
+    if (freq >= 5260 && freq <= 5320) {
+        *op_class = 118; /* 5 GHz, channels 52..64 */
+        *channel = (freq - 5000) / 5;
+        return 0;
+    }
+
+    if (freq >= 5500 && freq <= 5700) {
+        *op_class = 121; /* 5 GHz, channels 100..140 */
+        *channel = (freq - 5000) / 5;
+        return 0;
+    }
+
+    if (freq >= 5745 && freq <= 5805) {
+        if ((freq - 5000) % 5)
+            return -1;
+
+        *op_class = 124; /* 5 GHz, channels 149..161 */
+        *channel = (freq - 5000) / 5;
         return 0;
     }
 
+    if (freq >= 5825 && freq <= 5845) {
+        *op_class = 125; /* 5 GHz, channels 149,153,157,161,165,169 */
+        *channel = (freq - 5000) / 5;
+        return 0;
+    }
+
+    return -1;
 }
 
-/*
-* update channel list in wpa_supplicant
-* if coutry code chanaged
-*/
-static void wpa_driver_notify_country_change(void *ctx, char *cmd)
+static int p2p_wfd_sink_config_scc(struct wpa_supplicant *wpa_s, int scc, unsigned int oper_freq)
 {
-    if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
-        union wpa_event_data event;
+    int ret = 0;
+    u8 op_reg_class = 0, op_channel = 0;
+    unsigned int r;
+    struct wpa_supplicant *iface;
+    struct p2p_data *p2p = wpa_s->global->p2p;
+    wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__);
+    if (!p2p) {
+        wpa_printf(MSG_DEBUG, "Not support p2p.");
+        return ret;
+    }
+    if (scc && oper_freq) {
+        priv_p2p_freq_to_channel(oper_freq, &op_reg_class, &op_channel);
+        p2p->op_channel = op_channel;
+        p2p->op_reg_class = op_reg_class;
+        p2p->channels.reg_classes = 1;
+        p2p->channels.reg_class[0].channels = 1;
+        p2p->channels.reg_class[0].reg_class = op_reg_class;
+        p2p->channels.reg_class[0].channel[0] = op_channel;
+        wpa_printf(MSG_DEBUG, "Enable SCC in WFD sink mode class %d, channel %d",
+                op_reg_class, op_channel);
+        return ret;
+    }
+    /* Get back to MCC */
+    wpa_printf(MSG_DEBUG, "Config MCC");
+    if (wpa_s->conf->p2p_oper_reg_class &&
+        wpa_s->conf->p2p_oper_channel) {
+        p2p->op_reg_class = wpa_s->conf->p2p_oper_reg_class;
+        p2p->op_channel = wpa_s->conf->p2p_oper_channel;
+        p2p->cfg->cfg_op_channel = 1;
+    } else {
+        p2p->op_reg_class = 81;
+        os_get_random((u8 *)&r, sizeof(r));
+        p2p->op_channel = 1 + (r % 3) * 5;
+        p2p->cfg->cfg_op_channel = 0;
+    }
 
-        os_memset(&event, 0, sizeof(event));
-        event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
-        if (os_strncasecmp(cmd, "COUNTRY", 7) == 0) {
-            event.channel_list_changed.type = REGDOM_TYPE_COUNTRY;
-            if (os_strlen(cmd) > 9) {
-                event.channel_list_changed.alpha2[0] = cmd[8];
-                event.channel_list_changed.alpha2[1] = cmd[9];
-            }
-        } else
-            event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
-        wpa_supplicant_event(ctx, EVENT_CHANNEL_LIST_CHANGED, &event);
+    os_memcpy(&p2p->channels, &p2p->cfg->channels, sizeof(struct p2p_channels));
+    return ret;
+}
+
+
+static int mtk_get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s,
+                               struct wpa_used_freq_data *freqs_data,
+                               unsigned int len)
+{
+    struct wpa_supplicant *ifs;
+    u8 bssid[ETH_ALEN];
+    int freq;
+    unsigned int idx = 0, i;
+
+    wpa_dbg(wpa_s, MSG_DEBUG,
+           "Determining shared radio frequencies (max len %u)", len);
+    os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len);
+
+    dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant,
+                    radio_list) {
+        wpa_printf(MSG_DEBUG, "Get shared freqs ifname %s", ifs->ifname);
+        if (idx == len)
+            break;
+
+        if (ifs->current_ssid == NULL || ifs->assoc_freq == 0)
+            continue;
+
+        if (ifs->current_ssid->mode == WPAS_MODE_AP ||
+            ifs->current_ssid->mode == WPAS_MODE_P2P_GO)
+            freq = ifs->current_ssid->frequency;
+        else if (wpa_drv_get_bssid(ifs, bssid) == 0)
+            freq = ifs->assoc_freq;
+        else
+            continue;
+
+        /* Hold only distinct freqs */
+        for (i = 0; i < idx; i++)
+            if (freqs_data[i].freq == freq)
+                break;
+
+        if (i == idx)
+            freqs_data[idx++].freq = freq;
+
+        if (ifs->current_ssid->mode == WPAS_MODE_INFRA) {
+            freqs_data[i].flags = ifs->current_ssid->p2p_group ?
+                                WPA_FREQ_USED_BY_P2P_CLIENT :
+                                WPA_FREQ_USED_BY_INFRA_STATION;
+        }
     }
+
+    return idx;
+}
+
+
+static int mtk_get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
+                          int *freq_array, unsigned int len)
+{
+    struct wpa_used_freq_data *freqs_data;
+    int num, i;
+
+    os_memset(freq_array, 0, sizeof(int) * len);
+
+    freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data));
+    if (!freqs_data)
+        return -1;
+
+    num = mtk_get_shared_radio_freqs_data(wpa_s, freqs_data, len);
+    for (i = 0; i < num; i++)
+        freq_array[i] = freqs_data[i].freq;
+
+    os_free(freqs_data);
+
+    return num;
 }
+#endif
 
 int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
                   size_t buf_len )
@@ -110,6 +1588,7 @@ int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
     struct i802_bss *bss = priv;
     struct wpa_driver_nl80211_data *drv = bss->drv;
     struct ifreq ifr;
+    android_wifi_priv_cmd priv_cmd;
     struct wpa_supplicant *wpa_s;
     struct hostapd_data *hapd;
     int handled = 0;
@@ -119,53 +1598,55 @@ int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
     int ret = -1;
 
     if (drv == NULL) {
-        wpa_printf(MSG_ERROR, "%s: drv is NULL. Exiting", __func__);
+        wpa_printf(MSG_ERROR, "%s: drv is NULL, exit", __func__);
         return -1;
     }
     if (drv->ctx == NULL) {
-        wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL. Exiting", __func__);
+        wpa_printf(MSG_ERROR, "%s: drv->ctx is NULL, exit", __func__);
         return -1;
     }
 
-    if (os_strcmp(bss->ifname, "ap0") == 0) {
+    if (bss->drv->nlmode == NL80211_IFTYPE_AP) {
         hapd = (struct hostapd_data *)(drv->ctx);
     }
     else {
         wpa_s = (struct wpa_supplicant *)(drv->ctx);
         if (wpa_s->conf == NULL) {
-            wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL. Exiting", __func__);
+            wpa_printf(MSG_ERROR, "%s: wpa_s->conf is NULL, exit", __func__);
             return -1;
         }
     }
 
-    wpa_printf(MSG_DEBUG, "iface %s recv cmd %s", bss->ifname, cmd);
+    wpa_printf(MSG_INFO, "%s: %s recv cmd %s", __func__, bss->ifname, cmd);
     handled = 1;
 
     if (os_strncasecmp(cmd, "POWERMODE ", 10) == 0) {
         int state;
         state = atoi(cmd + 10);
         wpa_printf(MSG_DEBUG, "POWERMODE=%d", state);
+    }  else if (os_strncasecmp(cmd, "GET_STA_STATISTICS ", 19) == 0) {
+        ret = wpa_driver_get_sta_statistics(wpa_s, cmd + 19, buf, buf_len);
     }  else if (os_strncmp(cmd, "MACADDR", os_strlen("MACADDR")) == 0) {
         u8 macaddr[ETH_ALEN] = {};
         os_memcpy(&macaddr, wpa_s->own_addr, ETH_ALEN);
         ret = snprintf(buf, buf_len, "Macaddr = " MACSTR "\n", MAC2STR(macaddr));
         wpa_printf(MSG_DEBUG, "%s", buf);
-    } else if(os_strncasecmp(cmd, "COUNTRY", os_strlen("COUNTRY"))==0) {
+    } else if(os_strncasecmp(cmd, "COUNTRY", os_strlen("COUNTRY")) == 0) {
         if (os_strlen(cmd) != os_strlen("COUNTRY") + 3) {
             wpa_printf(MSG_DEBUG, "Ignore COUNTRY cmd %s", cmd);
             ret = 0;
         } else {
-            wpa_printf(MSG_INFO, "set country: %s", cmd+8);
-            // ret = wpa_drv_set_country(wpa_s, cmd+8);
-            ret = wpa_driver_mediatek_set_country(priv, cmd+8);
+            wpa_printf(MSG_INFO, "Set country: %s", cmd + 8);
+            // ret = wpa_drv_set_country(wpa_s, cmd + 8);
+            ret = wpa_driver_mediatek_set_country(priv, cmd + 8);
             if (ret == 0) {
                 wpa_printf(MSG_DEBUG, "Update channel list after country code changed");
-                wpa_driver_notify_country_change(wpa_s, cmd);
+                wpa_driver_notify_country_change(wpa_s->global, cmd);
             }
         }
     } else if (os_strcasecmp(cmd, "start") == 0) {
-        if (ret = linux_set_iface_flags(drv->global->ioctl_sock,
-            drv->first_bss->ifname, 1)) {
+        if ((ret = linux_set_iface_flags(drv->global->ioctl_sock,
+            drv->first_bss->ifname, 1))) {
             wpa_printf(MSG_INFO, "nl80211: Could not set interface UP, ret=%d \n", ret);
         } else {
             wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-DRIVER-STATE STARTED");
@@ -179,14 +1660,14 @@ int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
             wpa_printf(MSG_INFO, "nl80211: not associated, no need to deauthenticate \n");
         }
 
-        if (ret = linux_set_iface_flags(drv->global->ioctl_sock,
-            drv->first_bss->ifname, 0)) {
+        if ((ret = linux_set_iface_flags(drv->global->ioctl_sock,
+            drv->first_bss->ifname, 0))) {
             wpa_printf(MSG_INFO, "nl80211: Could not set interface Down, ret=%d \n", ret);
         } else {
             wpa_msg(drv->ctx, MSG_INFO, "CTRL-EVENT-DRIVER-STATE STOPPED");
         }
     } else if (os_strncasecmp(cmd, "getpower", 8) == 0) {
-        u32 mode;
+        u32 mode = 0;
         // ret = wpa_driver_wext_driver_get_power(drv, &mode);
         if (ret == 0) {
             ret = snprintf(buf, buf_len, "powermode = %u\n", mode);
@@ -194,45 +1675,381 @@ int wpa_driver_nl80211_driver_cmd(void *priv, char *cmd, char *buf,
             if (ret < (int)buf_len)
                 return ret;
         }
-    } else if (os_strncasecmp(cmd, "get-rts-threshold", 17) == 0) {
-        u32 thd;
-        // ret = wpa_driver_wext_driver_get_rts(drv, &thd);
-        if (ret == 0) {
-            ret = snprintf(buf, buf_len, "rts-threshold = %u\n", thd);
-            wpa_printf(MSG_DEBUG, "%s", buf);
-            if (ret < (int)buf_len)
-                return ret;
+    } else if (os_strncasecmp(cmd, "rxfilter-add", 12) == 0) {
+        u32 sw_cmd = 0x9F000000;
+        u32 idx = 0;
+        char *cp = cmd + 12;
+        char *endp;
+
+        if (*cp != '\0') {
+            idx = (u32)strtol(cp, &endp, 0);
+            if (endp != cp) {
+                idx += 0x00900200;
+                wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx);
+                ret = 0;
+            }
         }
-    } else if (os_strncasecmp(cmd, "set-rts-threshold", 17) == 0) {
-        u32 thd = 0;
-        char *cp = cmd + 17;
+    } else if (os_strncasecmp(cmd, "rxfilter-remove", 15) == 0) {
+        u32 sw_cmd = 0x9F000000;
+        u32 idx = 0;
+        char *cp = cmd + 15;
         char *endp;
+
         if (*cp != '\0') {
-            thd = (u32)strtol(cp, &endp, 0);
-            // if (endp != cp)
-                // ret = wpa_driver_wext_driver_set_rts(drv, thd);
+            idx = (u32)strtol(cp, &endp, 0);
+            if (endp != cp) {
+                idx += 0x00900300;
+                wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx);
+                ret = 0;
+            }
         }
+    } else if (os_strncasecmp(cmd, "rxfilter-stop", 13) == 0) {
+        u32 sw_cmd = 0x9F000000;
+        u32 idx = 0x00900000;
+        wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx);
+        ret = 0;
+    } else if (os_strncasecmp(cmd, "rxfilter-start", 14) == 0) {
+        u32 sw_cmd = 0x9F000000;
+        u32 idx = 0x00900100;
+        wpa_driver_nl80211_driver_sw_cmd(priv, 1, &sw_cmd, &idx);
+        ret = 0;
     } else if (os_strcasecmp(cmd, "btcoexscan-start") == 0) {
         ret = 0; /* mt5921 linux driver not implement yet */
     } else if (os_strcasecmp(cmd, "btcoexscan-stop") == 0) {
         ret = 0; /* mt5921 linux driver not implement yet */
     } else if (os_strncasecmp(cmd, "btcoexmode", 10) == 0) {
         ret = 0; /* mt5921 linux driver not implement yet */
+#ifdef CONFIG_HOTSPOT_MGR_SUPPORT
+    } else if (os_strncmp(cmd, "STA-BLOCK ", 10) == 0) {
+        if (wpa_driver_sta_block(priv, cmd + 10)) {
+            ret = -1;
+        } else {
+            ret = 0;
+        }
+    } else if (os_strncmp(cmd, "STA-UNBLOCK ", 12) == 0) {
+        if (wpa_driver_sta_unblock(priv, cmd + 12)) {
+            ret = -1;
+        } else {
+            ret = 0;
+        }
+    } else if (os_strncasecmp(cmd, "set_max_client ", 15) == 0) {
+        wpa_driver_set_max_client(priv, cmd + 15, buf, buf_len);
+#endif /* CONFIG_HOTSPOT_MGR_SUPPORT */
+#ifdef CONFIG_MTK_LTE_COEX
+    } else if (os_strncmp(cmd, "MTK-ACS", 7) == 0) {
+        u8 ch = wpa_driver_do_mtk_acs(priv);
+        os_memcpy(buf, &ch, sizeof(u8));
+        ret = sizeof(u8);
+#endif /* CONFIG_MTK_LTE_COEX */
+#ifdef CONFIG_WAPI_SUPPORT
+    } else if (os_strncasecmp(cmd, "set-wapi-key", 12) == 0) {
+        struct wapi_key_param_type {
+            u8 *addr;
+            int key_idx;
+            int set_tx;
+            u8 *seq;
+            size_t seq_len;
+            u8 *key;
+            size_t key_len;
+        } *wapi_key_param;
+        wapi_key_param = (struct wapi_key_param_type*)buf;
+
+        ret = wpa_driver_nl80211_set_wapi_key(priv, (const u8*)wapi_key_param->addr,
+                      wapi_key_param->key_idx, wapi_key_param->set_tx,
+                      (const u8*)wapi_key_param->seq, wapi_key_param->seq_len,
+                      (const u8*)wapi_key_param->key, wapi_key_param->key_len);
+    } else if (os_strncasecmp(cmd, "wapi-msg-send", 13) == 0) {
+        struct wapi_msg_send_param_type {
+            u8 *msg_in;
+            int msg_in_len;
+            u8 *msg_out;
+            int *msg_out_len;
+        } *wapi_msg_send_param;
+        wapi_msg_send_param = (struct wapi_msg_send_param_type*)buf;
+        ret = wpa_driver_nl80211_send_msg(priv, (const u8*)wapi_msg_send_param->msg_in,
+                      wapi_msg_send_param->msg_in_len, wapi_msg_send_param->msg_out,
+                      wapi_msg_send_param->msg_out_len);
+#endif /* CONFIG_WAPI_SUPPORT */
+#ifdef CONFIG_MTK_WFD_SINK
+    } else if (os_strncmp(cmd, "p2p_get_cap ", os_strlen("p2p_get_cap ")) == 0) {
+        struct p2p_data *p2p = wpa_s->global->p2p;
+        if (p2p) {
+            wpa_printf(MSG_DEBUG, "%s %d, %d ",
+                    __func__, __LINE__, p2p->dev_capab);
+            ret = p2p_get_capability(wpa_s, cmd + os_strlen("p2p_get_cap "),
+                          buf, buf_len);
+        }
+    } else if (os_strncmp(cmd, "p2p_set_cap ", os_strlen("p2p_set_cap ")) == 0) {
+        struct p2p_data *p2p = wpa_s->global->p2p;
+        if (p2p) {
+            wpa_printf(MSG_DEBUG, "%s %d", __func__, __LINE__);
+            ret = p2p_set_capability(wpa_s, cmd + os_strlen("p2p_set_cap "),
+                          buf, buf_len);
+        }
+    } else if (os_strncmp(cmd, "MIRACAST ", os_strlen("MIRACAST ")) == 0) {
+        unsigned char miracast = atoi(cmd + os_strlen("MIRACAST "));
+        char *pos = os_strstr(cmd, " freq=");
+        unsigned int freq = 0;
+        int num;
+        wpa_printf(MSG_DEBUG, "MIRACAST %d", miracast);
+        switch (miracast) {
+        case 0:
+        case 1:
+            num = mtk_get_shared_radio_freqs(wpa_s, &freq, 1);
+            if (num > 0 && freq > 0) {
+                wpa_printf(MSG_DEBUG, "AIS connected %d", freq);
+                p2p_wfd_sink_config_scc(wpa_s, 1, freq);
+            } else
+                p2p_wfd_sink_config_scc(wpa_s, 0, 0);
+            handled = 0; /* DRIVER MIRACAST used as private cmd*/
+            break;
+        case 2:
+            if (pos) {
+                pos += 6;
+                freq = atoi(pos);
+                wpa_printf(MSG_DEBUG, "MIRACAST freq %d", freq);
+                p2p_wfd_sink_config_scc(wpa_s, 1, freq);
+                /* rebuild DRIVER MIRACAST 2  cmd */
+                os_memset(cmd, 0, os_strlen(cmd));
+                os_memcpy(cmd, "MIRACAST 2", os_strlen("MIRACAST 2"));
+            } else {
+                num = mtk_get_shared_radio_freqs(wpa_s, &freq, 1);
+                if (num > 0 && freq > 0) {
+                    wpa_printf(MSG_DEBUG, "AIS connected %d", freq);
+                    p2p_wfd_sink_config_scc(wpa_s, 1, freq);
+                } else
+                    p2p_wfd_sink_config_scc(wpa_s, 0, 0);
+            }
+
+            handled = 0; /* DRIVER MIRACAST used as private cmd*/
+
+            break;
+        default:
+            wpa_printf(MSG_DEBUG, "Unknown MIRACAST value %d", miracast);
+            handled = 0; /* DRIVER MIRACAST used as private cmd*/
+            break;
+        }
+    } else if (os_strncasecmp(cmd, "p2p_use_mcc=", os_strlen("p2p_use_mcc=")) == 0) {
+        unsigned char use_mcc = atoi(cmd + os_strlen("p2p_use_mcc="));
+        wpa_printf(MSG_DEBUG, "p2p_use_mcc %d", use_mcc);
+        // MCC/SCC should be determined by GO negotation
+        // wpa_s->global->p2p->p2p_use_mcc = use_mcc;
+        if (use_mcc) {
+            wpa_printf(MSG_DEBUG, "SCC_MCC, config MCC");
+            p2p_wfd_sink_config_scc(wpa_s, 0, 0);
+        } else {
+            int shared_freq;
+            int num = 0;
+            wpa_printf(MSG_DEBUG, "use_mcc=0");
+            num = mtk_get_shared_radio_freqs(wpa_s, &shared_freq, 1);
+            if (num > 0 && shared_freq > 0) {
+                wpa_printf(MSG_DEBUG, "p2p disconnected, AIS connected %d", shared_freq);
+                p2p_wfd_sink_config_scc(wpa_s, 1, shared_freq);
+            } else
+                p2p_wfd_sink_config_scc(wpa_s, 0, 0);
+        }
+    } else if (os_strncmp(cmd, "wfd_data_update", os_strlen("wfd_data_update")) == 0) {
+        wpa_printf(MSG_DEBUG, "CONFIG_MTK_P2P: Update wfd_data");
+        ret = wpas_wfd_data_update(wpa_s, (struct wfd_data_s *)buf);
+#endif
+#ifdef CONFIG_MTK_P2P_SIGMA
+    } else if (os_strncasecmp(cmd, "mcc", 3) == 0) {
+        if (wpa_s->drv_priv) {
+            int mcc = 0;
+            char *value = NULL;
+            value = os_strchr(cmd, ' ');
+            if (value == NULL)
+                return -1;
+            *value++ = '\0';
+            struct wpa_supplicant *_wpa_s;
+            mcc = atoi(value);
+            if (mcc) {
+                for (_wpa_s = wpa_s->global->ifaces; _wpa_s; _wpa_s = _wpa_s->next) {
+
+                   /*
+                   * 2 is appropriate?
+                   * just legacy wifi vs p2p wifi?
+                   */
+                    _wpa_s->num_multichan_concurrent = 2;
+                    _wpa_s->drv_flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
+                    if (_wpa_s->global->p2p && _wpa_s->global->p2p->cfg)
+                        _wpa_s->global->p2p->cfg->concurrent_operations = 1;
+                }
+            } else {
+                for (_wpa_s = wpa_s->global->ifaces; _wpa_s; _wpa_s = _wpa_s->next) {
+
+                    /*
+                    * assign as 0 beacause our driver will
+                    * not report iface_combination to supplicant
+                    */
+                    _wpa_s->num_multichan_concurrent = 0;
+                    _wpa_s->drv_flags &= ~WPA_DRIVER_FLAGS_P2P_CONCURRENT;
+                    if (_wpa_s->global->p2p && _wpa_s->global->p2p->cfg)
+                        _wpa_s->global->p2p->cfg->concurrent_operations = 0;
+                }
+            }
+
+            wpa_printf(MSG_DEBUG, "mcc = %d", mcc);
+            ret = 0;
+        }
+    } else if (os_strncmp(cmd, "p2p_set_opps ", 13) == 0) {
+        ret = p2p_ctrl_iface_set_opps(wpa_s, cmd + 13, buf, buf_len);
+    } else if (os_strncmp(cmd, "p2p_set_power_save ", 19) == 0) {
+        ret = p2p_ctrl_iface_set_power_save(wpa_s, cmd + 19, buf, buf_len);
+    } else if (os_strncmp(cmd, "p2p_set_sleep ", 14) == 0) {
+        ret = p2p_ctrl_iface_set_sleep(wpa_s, cmd + 14, buf, buf_len);
+    } else if (os_strncmp(cmd, "p2p_set_sleep", 13) == 0) {
+        char cmd2[] = {"ff:ff:ff:ff:ff:ff \"\""};
+        ret = p2p_ctrl_iface_set_sleep(wpa_s, cmd2, buf, buf_len);
+    } else if (os_strncasecmp(cmd, "sigma_mode", 10) == 0) {
+        int sigma = 0;
+        char *value = NULL;
+        value = os_strchr(cmd, ' ');
+        if (value == NULL)
+            return -1;
+        *value++ = '\0';
+        sigma = atoi(value);
+        wpa_printf(MSG_DEBUG, "p2p: sigma: set mode %d", sigma);
+        // we should not have workaround for sigma programs
+        // wpa_s->global->p2p->sigma_mode = sigma;
+        ret = 0;
+#endif /* CONFIG_MTK_P2P_SIGMA */
+    } else if (os_strncmp(cmd, "P2P_SET_NOA", os_strlen("P2P_SET_NOA")) == 0) {
+        ret = p2p_ctrl_iface_set_noa(wpa_s, cmd, buf, buf_len);
+    } else if (os_strncmp(cmd, "P2P_SET_PS", os_strlen("P2P_SET_PS")) == 0) {
+        ret = p2p_ctrl_iface_set_ps(wpa_s, cmd, buf, buf_len);
+    } else if (os_strncasecmp(cmd, "SETSUSPENDMODE ", 15) == 0) {
+        struct wpa_driver_suspendmode_params params;
+        params.hdr.index = NL80211_TESTMODE_SUSPEND;
+        params.hdr.index = params.hdr.index | (0x01 << 24);
+        params.hdr.buflen = sizeof(params);
+        params.suspend = *(cmd+15)-'0';
+        wpa_driver_nl80211_testmode(priv, (u8* )&params, sizeof(params));
+        handled = 0; /* 6630 driver handled this command in driver, so give a chance to 6630 driver */
+    }else if(os_strncasecmp(cmd, "mtk_rx_packet_filter ", 21) == 0) {
+        char buf[9] = {0}, *errChar = NULL;
+        char *pos = NULL;
+        /* mtk_rx_packet_filter 00000000000000FE 0000000000000000 0000000000000000 */
+        struct wpa_driver_rx_filter_params params;
+        params.hdr.index = NL80211_TESTMODE_RXFILTER;
+        params.hdr.index = params.hdr.index | (0x01 << 24);
+        params.hdr.buflen = sizeof(params);
+
+        pos = cmd;
+        pos = pos + 21;
+        if (pos == NULL || strlen(cmd) != 71 ) {
+            wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter] Error! \n");
+            return -1;
+        }
+
+        os_memcpy(buf,pos,8);
+        buf[8] = '\0';
+        params.Ipv4FilterHigh = strtol(buf,&errChar,16);
+        wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv4FilterHigh (0x%08x),errChar [%p]\n", params.Ipv4FilterHigh,errChar);
+
+        pos = pos + 8;
+        os_memcpy(buf,pos,8);
+        buf[8] = '\0';
+        params.Ipv4FilterLow = strtol(buf,&errChar,16);
+        wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv4FilterLow (0x%08x),errChar [%p]\n", params.Ipv4FilterLow,errChar);
+
+        pos = pos + 9;
+        os_memcpy(buf,pos,8);
+        buf[8] = '\0';
+        params.Ipv6FilterHigh = strtol(buf,&errChar,16);
+        wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv6FilterHigh (0x%08x),errChar [%p]\n", params.Ipv6FilterHigh,errChar);
+
+        pos = pos + 8;
+        os_memcpy(buf,pos,8);
+        buf[8] = '\0';
+        params.Ipv6FilterLow = strtol(buf,&errChar,16);
+        wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.Ipv6FilterLow (0x%08x),errChar [%p]\n", params.Ipv6FilterLow,errChar);
+
+        pos = pos + 9;
+        os_memcpy(buf,pos,8);
+        buf[8] = '\0';
+        params.SnapFilterHigh = strtol(buf,&errChar,16);
+        wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.SnapFilterHigh (0x%08x),errChar [%p]\n", params.SnapFilterHigh,errChar);
+
+        pos = pos + 8;
+        os_memcpy(buf,pos,8);
+        buf[8] = '\0';
+        params.SnapFilterLow = strtol(buf,&errChar,16);
+        wpa_printf(MSG_DEBUG, "[mtk_rx_packet_filter]params.SnapFilterLow (0x%08x),errChar [%p]\n", params.SnapFilterLow,errChar);
+
+        ret = wpa_driver_nl80211_testmode(priv, (u8 *)&params, sizeof(params));
     } else {
+        u8 buffer[100];
+        struct wpa_driver_test_mode_info *params = (struct wpa_driver_test_mode_info *)buffer;
+        params->index = NL80211_TESTMODE_STR_CMD | (0x01 << 24);
+        params->buflen = sizeof(*params) + strlen(cmd);
+        strncpy((char*)(params+1), cmd, sizeof(buffer)-sizeof(*params));
+        ret = wpa_driver_nl80211_testmode(priv, buffer, params->buflen);
         handled = 0;
-        wpa_printf(MSG_INFO, "Unsupported command");
+        wpa_printf(MSG_INFO, "Transparent command for driver nl80211, ret=%d", ret);
     }
 
+    if (handled == 0) {
+        cmd_len = strlen(cmd);
+
+        memset(&ifr, 0, sizeof(ifr));
+        memset(&priv_cmd, 0, sizeof(priv_cmd));
+        memset(buf, 0, buf_len);
+        strncpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
+        ifr.ifr_name[IFNAMSIZ - 1] = '\0';
+
+        if (cmd_len >= PRIV_CMD_SIZE) {
+            wpa_printf(MSG_INFO, "%s: cmd: %s overflow",
+                      __func__, cmd);
+            cmd_len = PRIV_CMD_SIZE - 1;
+        }
+
+        memcpy(priv_cmd.buf, cmd, cmd_len + 1);
+        priv_cmd.used_len = cmd_len + 1;
+        priv_cmd.total_len = PRIV_CMD_SIZE;
+        ifr.ifr_data = &priv_cmd;
+
+        ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
+        if (ret < 0) {
+            wpa_printf(MSG_ERROR, "%s: failed to issue private commands,"
+                    " error msg: %s\n", __func__, strerror(errno));
+            wpa_driver_send_hang_msg(drv);
+            ret = snprintf(buf, buf_len, "%s\n", "FAIL");
+        } else {
+
+            wpa_printf(MSG_INFO, "%s: ret = %d used = %u total = %u",
+                    __func__, ret , priv_cmd.used_len, priv_cmd.total_len);
+
+            drv_errors = 0;
+            ret = 0;
+            if ((os_strncasecmp(cmd, "WLS_BATCHING", 12) == 0))
+                ret = strlen(buf);
+            /*
+            * There no need to call wpa_supplicant_event func
+            * on which the cmd is SETBAND
+            */
+            if (os_strncasecmp(cmd, "SETBAND", 7) == 0) {
+                /*
+                 * wpa_supplicant_event(drv->ctx,
+                 *             EVENT_CHANNEL_LIST_CHANGED, NULL);
+                 */
+                wpa_printf(MSG_INFO, "%s: Unsupported command SETBAND\n", __func__);
+            }
+        }
+    } /* handled == 0 */
+
     return ret;
 }
 
 int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
 {
+    char buf[MAX_DRV_CMD_SIZE];
     struct i802_bss *bss = priv;
     struct wpa_driver_nl80211_data *drv = bss->drv;
 
-    wpa_printf(MSG_DEBUG, "iface %s P2P_SET_NOA %d %d %d, ignored", bss->ifname, count, start, duration);
-    return -1;
+    wpa_printf(MSG_DEBUG, "iface %s P2P_SET_NOA %d %d %d", bss->ifname, count, start, duration);
+    snprintf(buf, sizeof(buf), "P2P_SET_NOA %d %d %d", count, start, duration);
+    return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1);
 }
 
 int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
@@ -246,11 +2063,13 @@ int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
 
 int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
 {
+    char buf[MAX_DRV_CMD_SIZE];
     struct i802_bss *bss = priv;
     struct wpa_driver_nl80211_data *drv = bss->drv;
 
-    wpa_printf(MSG_DEBUG, "iface %s P2P_SET_PS, ignored", bss->ifname);
-    return -1;
+    wpa_printf(MSG_DEBUG, "iface %s P2P_SET_PS %d %d %d", bss->ifname, legacy_ps, opp_ps, ctwindow);
+    snprintf(buf, sizeof(buf), "P2P_SET_PS %d %d %d", legacy_ps, opp_ps, ctwindow);
+    return wpa_driver_nl80211_driver_cmd(priv, buf, buf, strlen(buf)+1);
 }
 
 int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
diff --git a/wpa_supplicant_8_lib/mediatek_driver_nl80211.h b/wpa_supplicant_8_lib/mediatek_driver_nl80211.h
new file mode 100644 (file)
index 0000000..9657ec1
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * Driver interaction with Linux nl80211/cfg80211
+ * Copyright (c) 2002-2010, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2004, Instant802 Networks, Inc.
+ * Copyright (c) 2005-2006, Devicescape Software, Inc.
+ * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright (c) 2009-2010, Atheros Communications
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef _MTK_DRIVER_NL80211_H_
+#define _MTK_DRIVER_NL80211_H_
+
+
+#ifndef BITS
+/* Eddie */
+/* bits range: for example BITS(16,23) = 0xFF0000
+ *   ==>  (BIT(m)-1)   = 0x0000FFFF     ~(BIT(m)-1)   => 0xFFFF0000
+ *   ==>  (BIT(n+1)-1) = 0x00FFFFFF
+ */
+#define BITS(m,n)                       (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n)))
+#endif /* BIT */
+
+
+enum nl80211_testmode_sta_link_statistics_attr{
+    __NL80211_TESTMODE_STA_STATISTICS_INVALID = 0,
+    NL80211_TESTMODE_STA_STATISTICS_VERSION,
+    NL80211_TESTMODE_STA_STATISTICS_MAC,
+    NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE,
+    NL80211_TESTMODE_STA_STATISTICS_FLAG,
+
+    NL80211_TESTMODE_STA_STATISTICS_PER,
+    NL80211_TESTMODE_STA_STATISTICS_RSSI,
+    NL80211_TESTMODE_STA_STATISTICS_PHY_MODE,
+    NL80211_TESTMODE_STA_STATISTICS_TX_RATE,
+
+    NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT,
+    NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT,
+
+    NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME,
+    NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME,
+    NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME,
+    NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME,
+
+
+    NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT,
+    NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT,
+    NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME,
+
+    NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY,
+    NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY,
+
+    NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY,
+    NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY,
+
+    /*
+     * how many packages TX during statistics interval
+     */
+    NL80211_TESTMODE_STA_STATISTICS_ENQUEUE,
+
+    /*
+     * how many packages TX during statistics interval
+     */
+    NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE,
+
+    /*
+     * how many packages dequeue during statistics interval
+     */
+    NL80211_TESTMODE_STA_STATISTICS_DEQUEUE,
+
+    /*
+     * how many packages dequeue during statistics interval
+     */
+    NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE,
+
+    /*
+     * how many TC[0-3] resource back from firmware during
+     * statistics interval
+     */
+    NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY,
+    NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY,
+    NL80211_TESTMODE_STA_STATISTICS_TC_USED_ARRAY,
+    NL80211_TESTMODE_STA_STATISTICS_TC_WANTED_ARRAY,
+
+    NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT,
+    NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT,
+    NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT,
+    NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT,
+    NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT,
+    NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT,
+    NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT,
+
+    NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY,
+
+    NL80211_TESTMODE_STA_STATISTICS_NUM,
+    NL80211_TESTMODE_STA_STATISTICS_MAX = NL80211_TESTMODE_STA_STATISTICS_NUM - 1
+};
+
+enum nl80211_testmode_link_detect_attr{
+    NL80211_TESTMODE_LINK_INVALID = 0,
+    NL80211_TESTMODE_LINK_TX_FAIL_CNT,
+    NL80211_TESTMODE_LINK_TX_RETRY_CNT,
+    NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT,
+    NL80211_TESTMODE_LINK_ACK_FAIL_CNT,
+    NL80211_TESTMODE_LINK_FCS_ERR_CNT,
+    NL80211_TESTMODE_LINK_TX_OK_CNT,
+    NL80211_TESTMODE_LINK_RX_OK_CNT,
+    NL80211_TESTMODE_LINK_RST_REASON,
+    NL80211_TESTMODE_LINK_RST_TIME,
+    NL80211_TESTMODE_LINK_ROAM_FAIL_TIMES,
+    NL80211_TESTMODE_LINK_ROAM_FAIL_TIME,
+    NL80211_TESTMODE_LINK_TX_DONE_DELAY_IS_ARP,
+    NL80211_TESTMODE_LINK_ARRIVE_DRV_TICK,
+    NL80211_TESTMODE_LINK_ENQUE_TICK,
+    NL80211_TESTMODE_LINK_DEQUE_TICK,
+    NL80211_TESTMODE_LINK_LEAVE_DRV_TICK,
+    NL80211_TESTMODE_LINK_CURR_TICK,
+    NL80211_TESTMODE_LINK_CURR_TIME,
+    NL80211_TESTMODE_LINK_DETECT_NUM,
+    NL80211_TESTMODE_LINK_DETECT_MAX = NL80211_TESTMODE_LINK_DETECT_NUM - 1
+};
+
+#define BUG_REPORT_NUM    47
+
+typedef enum _ENUM_TRAFFIC_CLASS_INDEX_T {
+    TC0_INDEX = 0,
+    TC1_INDEX,
+    TC2_INDEX,
+    TC3_INDEX,
+    TC_DATA_NUM,
+    TC4_INDEX = TC_DATA_NUM,
+    TC5_INDEX,
+    TC_NUM
+} ENUM_TRAFFIC_CLASS_INDEX_T;
+
+struct wpa_driver_sta_statistics_s {
+    u8      version;
+    u8      addr[ETH_ALEN];
+    u32     flag;
+
+    u32     link_score;
+    u8      per;
+    int     rssi;
+    u32     phy_mode;
+    double  tx_rate;
+
+    u32     tx_total_cnt;
+    u32     enqueue_total_cnt;
+    u32     dequeue_total_cnt;
+    u32     enqueue_sta_total_cnt;
+    u32     dequeue_sta_total_cnt;
+    u32     tx_exc_threshold_cnt;
+
+    u32     tx_avg_process_time;
+    u32     tx_max_process_time;
+    u32     tx_avg_hif_process_time;
+    u32     tx_max_hif_process_time;
+
+    u32     tx_fail_cnt;
+    u32     tx_timeout_cnt;
+    u32     tx_avg_air_time;
+
+    u32     tc_buf_full_cnt[TC_DATA_NUM];
+    u32     tc_que_len[TC_DATA_NUM];
+
+    /*
+     * how many TC[0-3] resource back from firmware during
+     * statistics intervals
+     */
+    u32     tc_back_count[TC_DATA_NUM];
+
+    /*
+     * how many times that no TC[0-3] resource when dequeue
+     * statistics intervals
+     */
+    u32     dequeue_no_tc_res[TC_DATA_NUM];
+    u32     tc_wanted_res[TC_DATA_NUM];
+    u32     tc_used_res[TC_DATA_NUM];
+
+    /*
+     * wlan interrupt info
+     * statistics intervals
+     */
+    u32     isr_cnt;
+    u32     isr_pass_cnt;
+    u32     isr_task_cnt;
+    u32     isr_ab_cnt;
+    u32     isr_sw_cnt;
+    u32     isr_tx_cnt;
+    u32     isr_rx_cnt;
+
+    u32     tc_avg_que_len[TC_DATA_NUM];
+    u32     tc_cur_que_len[TC_DATA_NUM];
+
+    u8      reserved[32];
+};
+
+struct wpa_driver_sta_link_detect_s {
+    u64     tx_fail_cnt;
+    u64     tx_retry_cnt;
+    u64     tx_multi_retry_cnt;
+    u64     ack_fail_cnt;
+    u64     fcs_err_cnt;
+    u64     tx_ok_cnt;
+    u64     rx_ok_cnt;
+    u32     rst_reason;
+    u64     rst_time;
+    u32     roam_fail_times;
+    u64     roam_fail_time;
+    u8      tx_done_delay_is_arp;
+    u32     arrive_drv_tick;
+    u32     en_que_tick;
+    u32     de_que_tick;
+    u32     leave_drv_tick;
+    u32     curr_tick;
+    u64     curr_time;
+    u32     bug_report[BUG_REPORT_NUM];
+};
+
+/* SIOCSIWENCODEEXT definitions */
+#define IW_ENCODE_ALG_SMS4  0x20
+
+/* P2P Sigma*/
+struct wpa_driver_test_mode_info {
+    u32  index;
+    u32  buflen;
+};
+
+struct wpa_driver_testmode_params {
+    struct wpa_driver_test_mode_info hdr;
+    u8  *buf;
+};
+
+struct wpa_driver_get_sta_statistics_params {
+    struct wpa_driver_test_mode_info hdr;
+    u32 version;
+    u32 flag;
+    u8  addr[ETH_ALEN];
+    u8  *buf;
+};
+
+struct wpa_driver_p2p_sigma_params {
+    struct wpa_driver_test_mode_info hdr;
+    u32 idx;
+    u32 value;
+};
+
+struct wpa_driver_get_sta_link_detect_params {
+    struct wpa_driver_test_mode_info hdr;
+    u8  *buf;
+};
+
+/* Hotspot Client Management */
+struct wpa_driver_hotspot_params {
+    struct wpa_driver_test_mode_info hdr;
+    u8  blocked;
+    u8  bssid[ETH_ALEN];
+};
+
+struct wpa_driver_hotspot_set_config_params {
+    struct wpa_driver_test_mode_info hdr;
+    u32 index;
+    u32 value;
+};
+
+#ifdef CONFIG_MTK_LTE_COEX
+enum nl80211_testmode_available_chan_attr{
+    __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_INVALID,
+    NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_2G_BASE_1,
+    NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_36,
+    NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_52,
+    NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_100,
+    NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_5G_BASE_149,
+
+    __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST,
+    NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_MAX = __NL80211_TESTMODE_AVAILABLE_CHAN_ATTR_AFTER_LAST - 1
+};
+
+struct wpa_driver_available_chan_s {
+    u32 ch_2g_base1;
+    u32 ch_5g_base36;
+    u32 ch_5g_base52;
+    u32 ch_5g_base100;
+    u32 ch_5g_base149;
+};
+
+struct wpa_driver_get_available_channel_params {
+    struct wpa_driver_test_mode_info hdr;
+    u8  *buf;
+};
+#endif
+
+/* SW CMD */
+struct wpa_driver_sw_cmd_params {
+    struct wpa_driver_test_mode_info hdr;
+    u8  set;
+    u32 adr;
+    u32 data;
+};
+
+struct wpa_driver_suspendmode_params {
+    struct wpa_driver_test_mode_info hdr;
+    u8  suspend;
+};
+
+/* WAPI */
+struct iw_encode_exts {
+    u32 ext_flags; /* IW_ENCODE_EXT_* */
+    u8  tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+    u8  rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+    u8  addr[ETH_ALEN]; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
+                              * (group) keys or unicast address for
+                              * individual keys */
+    u16 alg; /* IW_ENCODE_ALG_* */
+    u16 key_len;
+    u8  key[32];
+};
+
+struct wpa_driver_rx_filter_params {
+    struct wpa_driver_test_mode_info hdr;
+    u32 Ipv4FilterHigh;
+    u32 Ipv4FilterLow;
+    u32 Ipv6FilterHigh;
+    u32 Ipv6FilterLow;
+    u32 SnapFilterHigh;
+    u32 SnapFilterLow;
+};
+
+struct wpa_driver_wapi_key_params {
+    struct wpa_driver_test_mode_info hdr;
+    u8  key_index;
+    u8  key_len;
+    struct iw_encode_exts extparams;
+};
+
+/* CONFIG_MTK_P2P */
+struct wpa_driver_wfd_data_s {
+    struct wpa_driver_test_mode_info hdr;
+    u32 WfdCmdType;
+    u8  WfdEnable;
+    u8  WfdCoupleSinkStatus;
+    u8  WfdSessionAvailable;
+    u8  WfdSigmaMode;
+    u16 WfdDevInfo;
+    u16 WfdControlPort;
+    u16 WfdMaximumTp;
+    u16 WfdExtendCap;
+    u8  WfdCoupleSinkAddress[ETH_ALEN];
+    u8  WfdAssociatedBssid[ETH_ALEN];
+    u8  WfdVideoIp[4];
+    u8  WfdAudioIp[4];
+    u16 WfdVideoPort;
+    u16 WfdAudioPort;
+    u32 WfdFlag;
+    u32 WfdPolicy;
+    u32 WfdState;
+    u8  WfdSessionInformationIE[24*8];  /* Include Subelement ID, length */
+    u16 WfdSessionInformationIELen;
+    u8  Reverved1[2];
+    u8  WfdPrimarySinkMac[ETH_ALEN];
+    u8  WfdSecondarySinkMac[ETH_ALEN];
+    u32 WfdAdvancedFlag;
+    /* Group 1 64 bytes */
+    u8  WfdLocalIp[4];
+    u16 WfdLifetimeAc2; /* Unit is 2 TU */
+    u16 WfdLifetimeAc3; /* Unit is 2 TU */
+    u16 WfdCounterThreshold;  /* Unit is ms */
+    u8  Reverved2[54];
+    /* Group 2 64 bytes */
+    u8  Reverved3[64];
+    /* Group 3 64 bytes */
+    u8  Reverved4[64];
+} wfd_data;
+
+struct wpa_driver_set_beamplus_params {
+    struct wpa_driver_test_mode_info hdr;
+    u32 value;
+};
+
+enum nl80211_testmode_params {
+    /* Old test mode command id, compatible with exist testmode command */
+    NL80211_TESTMODE_SW_CMD = 1,
+    NL80211_TESTMODE_WAPI = 2,
+    NL80211_TESTMODE_HS20 = 3,
+    NL80211_TESTMODE_POORLINK = 4,
+    NL80211_TESTMODE_STATISTICS = 0x10,
+    NL80211_TESTMODE_LINK_DETECT = 0x20,
+
+    // Hotspot manager testmode command
+    NL80211_TESTMODE_HS_SET_CONFIG = 51,
+
+    /* New test mode command id, should greater than TESTMODE_CMD_ID_NEW_BEGIN */
+    NL80211_TESTMODE_NEW_BEGIN = 100,
+    NL80211_TESTMODE_SUSPEND = 101,
+    NL80211_TESTMODE_STR_CMD = 102,
+    NL80211_TESTMODE_RXFILTER = 103
+};
+
+#endif