Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)

Bug: 166295507
Merged-In: I3ef9471c3daf6846f9e9ee56df2f57661d4ddb00
Change-Id: I1e02ed042efd096b4d664707cab17560adfa2de7
diff --git a/bcmdhd/wifi_hal/Android.mk b/bcmdhd/wifi_hal/Android.mk
old mode 100644
new mode 100755
index b4fe46e..5763789
--- a/bcmdhd/wifi_hal/Android.mk
+++ b/bcmdhd/wifi_hal/Android.mk
@@ -27,12 +27,18 @@
     -Wno-unused-parameter \
     -Wno-unused-private-field \
     -Wno-unused-variable \
+    -Wno-unused-parameter
 
 LOCAL_C_INCLUDES += \
 	external/libnl/include \
 	$(call include-path-for, libhardware_legacy)/hardware_legacy \
 	external/wpa_supplicant_8/src/drivers
 
+LOCAL_C_INCLUDES += \
+        external/boringssl/include \
+        external/boringssl/src/crypto/digest \
+        external/boringssl/src/crypto/evp/
+
 LOCAL_HEADER_LIBRARIES := libutils_headers liblog_headers
 
 LOCAL_SRC_FILES := \
@@ -41,6 +47,7 @@
 	common.cpp \
 	cpp_bindings.cpp \
 	gscan.cpp \
+	nan.cpp \
 	link_layer_stats.cpp \
 	wifi_logger.cpp \
 	wifi_offload.cpp
diff --git a/bcmdhd/wifi_hal/brcm_version.h b/bcmdhd/wifi_hal/brcm_version.h
new file mode 100755
index 0000000..14efbee
--- /dev/null
+++ b/bcmdhd/wifi_hal/brcm_version.h
@@ -0,0 +1 @@
+#define HAL_VERSION "Android-10-FRC2-SDK_29 59.0 (r854927) 2019-12-06 23:33:52 +0530 (Fri, 06 Dec 2019)"
diff --git a/bcmdhd/wifi_hal/common.cpp b/bcmdhd/wifi_hal/common.cpp
old mode 100644
new mode 100755
index 3540d49..c164ba4
--- a/bcmdhd/wifi_hal/common.cpp
+++ b/bcmdhd/wifi_hal/common.cpp
@@ -37,6 +37,8 @@
 #include "common.h"
 #include "cpp_bindings.h"
 
+/* test mode flag for halutil only */
+bool halutil_mode = false;
 interface_info *getIfaceInfo(wifi_interface_handle handle)
 {
     return (interface_info *)handle;
@@ -261,3 +263,11 @@
     return WIFI_ERROR_INVALID_ARGS;
 }
 
+void set_hautil_mode(bool util_mode)
+{
+    halutil_mode = util_mode;
+}
+bool get_halutil_mode()
+{
+    return halutil_mode;
+}
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h
old mode 100644
new mode 100755
index 28e2156..98801b2
--- a/bcmdhd/wifi_hal/common.h
+++ b/bcmdhd/wifi_hal/common.h
@@ -34,6 +34,8 @@
 #define DOT11_OUI_LEN             3
 #define DOT11_MAX_SSID_LEN        32
 
+#define ETHERTYPE_IP            0x0800          /* IP */
+#define ETHERTYPE_IPV6          0x86dd          /* IP protocol version 6 */
 #define MAX_PROBE_RESP_IE_LEN      2048
 /*
  Vendor OUI - This is a unique identifier that identifies organization. Lets
@@ -45,12 +47,21 @@
 /* TODO: define vendor OUI here */
 
 
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+
+#define NMR2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5], (a)[6], (a)[7]
+#define NMRSTR "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
+#define NAN_MASTER_RANK_LEN 8
+
+
 /*
  This enum defines ranges for various commands; commands themselves
  can be defined in respective feature headers; i.e. find gscan command
  definitions in gscan.cpp
  */
 
+typedef int (*nl_recvmsg_msg_cb_t)(struct nl_msg *msg, void *arg);
 typedef enum {
     /* don't use 0 as a valid subcommand */
     VENDOR_NL80211_SUBCMD_UNSPECIFIED,
@@ -90,6 +101,10 @@
     ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START = 0x1800,
     ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_END   = 0x18FF,
 
+    /* define all tx power related commands between 0x1900 and 0x1910 */
+    ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START	= 0x1900,
+    ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_END	= 0x1910,
+
     /* This is reserved for future usage */
 
 } ANDROID_VENDOR_SUB_COMMAND;
@@ -115,42 +130,92 @@
     WIFI_SUBCMD_GET_FEATURE_SET_MATRIX,                  /* 0x100B */
     WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI,                  /* 0x100C */
     WIFI_SUBCMD_NODFS_SET,                               /* 0x100D */
-    WIFI_SUBCMD_SET_COUNTRY_CODE,                             /* 0x100E */
+    WIFI_SUBCMD_SET_COUNTRY_CODE,                        /* 0x100E */
     /* Add more sub commands here */
     GSCAN_SUBCMD_SET_EPNO_SSID,                          /* 0x100F */
 
-    WIFI_SUBCMD_SET_SSID_WHITE_LIST,                    /* 0x1010 */
-    WIFI_SUBCMD_SET_ROAM_PARAMS,                        /* 0x1011 */
-    WIFI_SUBCMD_ENABLE_LAZY_ROAM,                       /* 0x1012 */
-    WIFI_SUBCMD_SET_BSSID_PREF,                         /* 0x1013 */
+    WIFI_SUBCMD_SET_SSID_WHITE_LIST,                     /* 0x1010 */
+    WIFI_SUBCMD_SET_ROAM_PARAMS,                         /* 0x1011 */
+    WIFI_SUBCMD_ENABLE_LAZY_ROAM,                        /* 0x1012 */
+    WIFI_SUBCMD_SET_BSSID_PREF,                          /* 0x1013 */
     WIFI_SUBCMD_SET_BSSID_BLACKLIST,                     /* 0x1014 */
 
-    GSCAN_SUBCMD_ANQPO_CONFIG,                          /* 0x1015 */
-    WIFI_SUBCMD_SET_RSSI_MONITOR,                       /* 0x1016 */
-    WIFI_SUBCMD_CONFIG_ND_OFFLOAD,                      /* 0x1017 */
-    /* Add more sub commands here */
+    GSCAN_SUBCMD_ANQPO_CONFIG,                           /* 0x1015 */
+    WIFI_SUBCMD_SET_RSSI_MONITOR,                        /* 0x1016 */
+    WIFI_SUBCMD_CONFIG_ND_OFFLOAD,                       /* 0x1017 */
+    WIFI_SUBCMD_CONFIG_TCPACK_SUP,                       /* 0x1018 */
+    WIFI_SUBCMD_FW_ROAM_POLICY,                          /* 0x1019 */
+    WIFI_SUBCMD_ROAM_CAPABILITY,                         /* 0x101a */
+    WIFI_SUBCMD_SET_LATENCY_MODE,                        /* 0x101b */
 
     GSCAN_SUBCMD_MAX,
 
+    /* NAN related */
+    NAN_SUBCMD_ENABLE = ANDROID_NL80211_SUBCMD_NAN_RANGE_START,
+    NAN_SUBCMD_DISABLE,                                 /* 0x1701 */
+    NAN_SUBCMD_PUBLISH,                                 /* 0x1702 */
+    NAN_SUBCMD_SUBSCRIBE,                               /* 0x1703 */
+    NAN_SUBCMD_PUBLISH_CANCEL,                          /* 0x1704 */
+    NAN_SUBCMD_SUBSCRIBE_CANCEL,                        /* 0x1705 */
+    NAN_SUBCMD_TRANSMIT_FOLLOWUP,                       /* 0x1706 */
+    NAN_SUBCMD_CONFIG,                                  /* 0x1707 */
+    NAN_SUBCMD_TCA,                                     /* 0x1708 */
+    NAN_SUBCMD_STATS,                                   /* 0x1709 */
+    NAN_SUBCMD_GET_CAPABILITIES,                        /* 0x170A */
+    NAN_SUBCMD_DATA_PATH_IFACE_CREATE,                  /* 0x170B */
+    NAN_SUBCMD_DATA_PATH_IFACE_DELETE,                  /* 0x170C */
+    NAN_SUBCMD_DATA_PATH_REQUEST,                       /* 0x170D */
+    NAN_SUBCMD_DATA_PATH_RESPONSE,                      /* 0x170E */
+    NAN_SUBCMD_DATA_PATH_END,                           /* 0x170F */
+    NAN_SUBCMD_DATA_PATH_SEC_INFO,                      /* 0x1710 */
+    NAN_SUBCMD_VERSION_INFO,                            /* 0x1711 */
+    NAN_SUBCMD_ENABLE_MERGE,                            /* 0x1712 */
     APF_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_PKT_FILTER_RANGE_START,
     APF_SUBCMD_SET_FILTER,
+    WIFI_SUBCMD_TX_POWER_SCENARIO = ANDROID_NL80211_SUBCMD_TX_POWER_RANGE_START,
 } WIFI_SUB_COMMAND;
 
 typedef enum {
-    BRCM_RESERVED1,
-    BRCM_RESERVED2,
-    GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS ,
-    GSCAN_EVENT_HOTLIST_RESULTS_FOUND,
-    GSCAN_EVENT_SCAN_RESULTS_AVAILABLE,
-    GSCAN_EVENT_FULL_SCAN_RESULTS,
-    RTT_EVENT_COMPLETE,
-    GSCAN_EVENT_COMPLETE_SCAN,
-    GSCAN_EVENT_HOTLIST_RESULTS_LOST,
-    GSCAN_EVENT_EPNO_EVENT,
-    GOOGLE_DEBUG_RING_EVENT,
-    GOOGLE_DEBUG_MEM_DUMP_EVENT,
-    GSCAN_EVENT_ANQPO_HOTSPOT_MATCH,
-    GOOGLE_RSSI_MONITOR_EVENT
+    BRCM_RESERVED1				= 0,
+    BRCM_RESERVED2				= 1,
+    GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS	= 2,
+    GSCAN_EVENT_HOTLIST_RESULTS_FOUND		= 3,
+    GSCAN_EVENT_SCAN_RESULTS_AVAILABLE		= 4,
+    GSCAN_EVENT_FULL_SCAN_RESULTS		= 5,
+    RTT_EVENT_COMPLETE				= 6,
+    GSCAN_EVENT_COMPLETE_SCAN			= 7,
+    GSCAN_EVENT_HOTLIST_RESULTS_LOST		= 8,
+    GSCAN_EVENT_EPNO_EVENT			= 9,
+    GOOGLE_DEBUG_RING_EVENT			= 10,
+    GOOGLE_DEBUG_MEM_DUMP_EVENT			= 11,
+    GSCAN_EVENT_ANQPO_HOTSPOT_MATCH		= 12,
+    GOOGLE_RSSI_MONITOR_EVENT			= 13,
+    GOOGLE_MKEEP_ALIVE				= 14,
+
+    /*
+     * BRCM specific events should be placed after the Generic events
+     * in order to match between the DHD and HAL
+     */
+    NAN_EVENT_ENABLED				= 15,
+    NAN_EVENT_DISABLED				= 16,
+    NAN_EVENT_SUBSCRIBE_MATCH			= 17,
+    NAN_EVENT_PUBLISH_REPLIED_IND		= 18,
+    NAN_EVENT_PUBLISH_TERMINATED		= 19,
+    NAN_EVENT_SUBSCRIBE_TERMINATED		= 20,
+    NAN_EVENT_DE_EVENT				= 21,
+    NAN_EVENT_FOLLOWUP				= 22,
+    NAN_EVENT_TRANSMIT_FOLLOWUP_IND		= 23,
+    NAN_EVENT_DATA_REQUEST			= 24,
+    NAN_EVENT_DATA_CONFIRMATION			= 25,
+    NAN_EVENT_DATA_END				= 26,
+    NAN_EVENT_BEACON				= 27,
+    NAN_EVENT_SDF				= 28,
+    NAN_EVENT_TCA				= 29,
+    NAN_EVENT_SUBSCRIBE_UNMATCH			= 30,
+    NAN_EVENT_UNKNOWN,
+    ROAM_EVENT_START,
+    GOOGLE_FILE_DUMP_EVENT			= 37,
+    NAN_ASYNC_RESPONSE_DISABLED			= 40
 } WIFI_EVENT;
 
 typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events);
@@ -256,6 +321,17 @@
 wifi_handle getWifiHandle(hal_info *info);
 wifi_interface_handle getIfaceHandle(interface_info *info);
 wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface);
+wifi_error nan_deinit_handler();
+wifi_error wifi_start_hal(wifi_interface_handle iface);
+wifi_error wifi_stop_hal(wifi_interface_handle iface);
+wifi_interface_handle wifi_get_wlan_interface(wifi_handle info,
+	    wifi_interface_handle *ifaceHandles, int numIfaceHandles);
+wifi_error wifi_hal_preInit(wifi_interface_handle iface);
+/* API to get wake reason statistics */
+wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
+        WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
+void set_hautil_mode(bool halutil_mode);
+bool get_halutil_mode();
 
 // some common macros
 
diff --git a/bcmdhd/wifi_hal/cpp_bindings.cpp b/bcmdhd/wifi_hal/cpp_bindings.cpp
old mode 100644
new mode 100755
index 0ac4c08..5ca6431
--- a/bcmdhd/wifi_hal/cpp_bindings.cpp
+++ b/bcmdhd/wifi_hal/cpp_bindings.cpp
@@ -34,11 +34,22 @@
 #include <netlink/handlers.h>
 
 #include <ctype.h>
+#include <errno.h>
 
 #include "wifi_hal.h"
 #include "common.h"
 #include "cpp_bindings.h"
 
+pthread_mutex_t ResponseMutex;
+void InitResponseLock() {
+    pthread_mutex_init(&ResponseMutex, NULL);
+}
+
+void DestroyResponseLock()
+{
+    pthread_mutex_destroy(&ResponseMutex);
+}
+
 void appendFmt(char *buf, int &offset, const char *fmt, ...)
 {
     va_list params;
@@ -607,7 +618,8 @@
 }
 
 int WifiCommand::requestResponse(WifiRequest& request) {
-    int err = 0;
+    pthread_mutex_lock(&ResponseMutex);
+    int err = 0, res = 0;
 
     struct nl_cb *cb = nl_cb_alloc(NL_CB_DEFAULT);
     if (!cb)
@@ -633,6 +645,7 @@
     }
 out:
     nl_cb_put(cb);
+    pthread_mutex_unlock(&ResponseMutex);
     return err;
 }
 
diff --git a/bcmdhd/wifi_hal/cpp_bindings.h b/bcmdhd/wifi_hal/cpp_bindings.h
old mode 100644
new mode 100755
index 2c1aa05..8839a72
--- a/bcmdhd/wifi_hal/cpp_bindings.h
+++ b/bcmdhd/wifi_hal/cpp_bindings.h
@@ -101,6 +101,9 @@
         return mAttributes[attribute] ? nla_data(mAttributes[attribute]) : NULL;
     }
 
+    void *get_string(int attribute) {
+        return mAttributes[attribute] ? nla_get_string(mAttributes[attribute]) : NULL;
+    }
 private:
     WifiEvent(const WifiEvent&);        // hide copy constructor to prevent copies
 };
@@ -143,6 +146,9 @@
     int get_len() {
         return nla_len(pos);
     }
+    void* get_string() {
+        return nla_get_string(pos);
+    }
 private:
     nl_iterator(const nl_iterator&);    // hide copy constructor to prevent copies
 };
@@ -193,6 +199,9 @@
     int put(int attribute, void *ptr, unsigned len) {
         return nla_put(mMsg, attribute, len, ptr);
     }
+    int put_s8(int attribute, int8_t value) {
+        return nla_put(mMsg, attribute, sizeof(value), &value);
+    }
     int put_u8(int attribute, uint8_t value) {
         return nla_put(mMsg, attribute, sizeof(value), &value);
     }
@@ -367,3 +376,5 @@
         nla_ok(pos, rem); \
         pos = (nlattr *)nla_next(pos, &(rem)))
 
+extern void InitResponseLock();
+extern void DestroyResponseLock();
diff --git a/bcmdhd/wifi_hal/gscan.cpp b/bcmdhd/wifi_hal/gscan.cpp
old mode 100644
new mode 100755
index 4e4ee93..f5722f2
--- a/bcmdhd/wifi_hal/gscan.cpp
+++ b/bcmdhd/wifi_hal/gscan.cpp
@@ -159,10 +159,16 @@
     GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
     GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
 
+    /* Roaming features */
+    GSCAN_ATTRIBUTE_ROAM_STATE_SET = 140,
     GSCAN_ATTRIBUTE_MAX
 
 } GSCAN_ATTRIBUTE;
 
+typedef struct {
+    int num_bssid;                          // number of blacklisted BSSIDs
+    mac_addr bssids[MAX_BLACKLIST_BSSID];   // blacklisted BSSIDs
+} wifi_bssid_params;
 
 // helper methods
 wifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface,
@@ -190,18 +196,22 @@
 
 class GetCapabilitiesCommand : public WifiCommand
 {
-    wifi_gscan_capabilities *mCapabilities;
-public:
-    GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites)
-        : WifiCommand("GetGscanCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
+    void *mCapabilities;
+    uint16_t mRequesttype;
+    int mRequestsize;
+    public:
+    GetCapabilitiesCommand(wifi_interface_handle iface, void *capabitlites, uint16_t request_type,
+            int request_size)
+        : WifiCommand("GetGscanCapabilitiesCommand", iface, 0), mCapabilities(capabitlites), mRequesttype(request_type),
+        mRequestsize(request_size)
     {
-        memset(mCapabilities, 0, sizeof(*mCapabilities));
+        memset(mCapabilities, 0, mRequestsize);
     }
 
     virtual int create() {
         ALOGV("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
 
-        int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES);
+        int ret = mMsg.create(GOOGLE_OUI, mRequesttype);
         if (ret < 0) {
             return ret;
         }
@@ -209,7 +219,7 @@
         return ret;
     }
 
-protected:
+    protected:
     virtual int handleResponse(WifiEvent& reply) {
 
         ALOGV("In GetCapabilities::handleResponse");
@@ -225,20 +235,28 @@
         void *data = reply.get_vendor_data();
         int len = reply.get_vendor_data_len();
 
-        ALOGV("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
-                    sizeof(*mCapabilities));
+        ALOGV("Id = %0x, subcmd = 0x%x, len = %d, expected len = %zd", id, subcmd, len,
+            mRequestsize);
 
-        memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
+        memcpy(mCapabilities, data, min(len, mRequestsize));
 
         return NL_OK;
     }
 };
 
-
 wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
         wifi_gscan_capabilities *capabilities)
 {
-    GetCapabilitiesCommand command(handle, capabilities);
+    GetCapabilitiesCommand command(handle, capabilities, GSCAN_SUBCMD_GET_CAPABILITIES,
+            (int)sizeof(wifi_gscan_capabilities));
+    return (wifi_error) command.requestResponse();
+}
+
+wifi_error wifi_get_roaming_capabilities(wifi_interface_handle handle,
+        wifi_roaming_capabilities *capabilities)
+{
+    GetCapabilitiesCommand command(handle, capabilities, WIFI_SUBCMD_ROAM_CAPABILITY,
+            (int)sizeof(wifi_roaming_capabilities));
     return (wifi_error) command.requestResponse();
 }
 
@@ -1676,6 +1694,174 @@
     return result;
 }
 
+class BssidBlacklistCommand : public WifiCommand
+{
+    private:
+        wifi_bssid_params *mParams;
+    public:
+        BssidBlacklistCommand(wifi_interface_handle handle, int id,
+                wifi_bssid_params *params)
+            : WifiCommand("BssidBlacklistCommand", handle, id), mParams(params)
+        { }
+        int createRequest(WifiRequest& request) {
+            if ((mParams->num_bssid < 0) || (mParams->num_bssid > MAX_BLACKLIST_BSSID)) {
+                return WIFI_ERROR_INVALID_ARGS;
+            }
+            int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_BSSID_BLACKLIST);
+            if (result < 0) {
+                return result;
+            }
+
+            nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+            if (!mParams->num_bssid) {
+                result = request.put_u32(GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH, 1);
+                if (result < 0) {
+                    return result;
+                }
+            } else {
+                result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BSSID, mParams->num_bssid);
+                if (result < 0) {
+                    return result;
+                }
+                for (int i = 0; i < mParams->num_bssid; i++) {
+                    result = request.put_addr(GSCAN_ATTRIBUTE_BLACKLIST_BSSID, mParams->bssids[i]);
+                    if (result < 0) {
+                        return result;
+                    }
+               }
+            }
+            request.attr_end(data);
+            return result;
+        }
+
+        int start() {
+            ALOGV("Executing bssid blacklist request, num = %d", mParams->num_bssid);
+            WifiRequest request(familyId(), ifaceId());
+            int result = createRequest(request);
+            if (result < 0) {
+                return result;
+            }
+
+            result = requestResponse(request);
+            if (result < 0) {
+                ALOGE("Failed to execute bssid blacklist request, result = %d", result);
+                return result;
+            }
+
+            ALOGI("Successfully added %d blacklist bssids", mParams->num_bssid);
+            return result;
+        }
+
+        virtual int handleResponse(WifiEvent& reply) {
+            /* Nothing to do on response! */
+            return NL_SKIP;
+        }
+};
+
+wifi_error wifi_set_bssid_blacklist(wifi_request_id id, wifi_interface_handle iface,
+        wifi_bssid_params params)
+{
+    wifi_handle handle = getWifiHandle(iface);
+
+    BssidBlacklistCommand *cmd = new BssidBlacklistCommand(iface, id, &params);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    wifi_error result = (wifi_error)cmd->start();
+    //release the reference of command as well
+    cmd->releaseRef();
+    return result;
+}
+
+wifi_error wifi_configure_roaming(wifi_interface_handle iface,
+		wifi_roaming_config *roam_config)
+{
+    wifi_error ret;
+    wifi_bssid_params bssid_params;
+    unsigned int i;
+    wifi_request_id id = 0;
+
+    /* Set bssid blacklist */
+    if (roam_config->num_blacklist_bssid == 0) {
+        /* Flush request */
+        ALOGI("%s: num_blacklist_bssid == 0 (flush)", __FUNCTION__);
+    }
+
+    bssid_params.num_bssid = roam_config->num_blacklist_bssid;
+
+    for (i = 0; i < roam_config->num_blacklist_bssid; i++) {
+        mac_addr &addr1 = roam_config->blacklist_bssid[i];
+        memcpy(&bssid_params.bssids[i], &roam_config->blacklist_bssid[i],
+            sizeof(mac_addr));
+        ALOGI("%02x:%02x:%02x:%02x:%02x:%02x\n", addr1[0],
+            addr1[1], addr1[2], addr1[3], addr1[4], addr1[5]);
+    }
+    ret = wifi_set_bssid_blacklist(id, iface, bssid_params);
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s: Failed to configure blacklist bssids", __FUNCTION__);
+        return ret;
+    }
+
+    return ret;
+}
+
+class FirmwareRoamingStateCommand : public WifiCommand
+{
+    private:
+        fw_roaming_state_t roam_state;
+    public:
+        FirmwareRoamingStateCommand(wifi_interface_handle handle,
+                fw_roaming_state_t state)
+            : WifiCommand("FirmwareRoamingStateCommand", handle, -1), roam_state(state)
+        { }
+        int createRequest(WifiRequest& request) {
+            int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_FW_ROAM_POLICY);
+            if (result < 0) {
+                return result;
+            }
+
+            nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+            result = request.put_u32(GSCAN_ATTRIBUTE_ROAM_STATE_SET, roam_state);
+            if (result < 0) {
+                return result;
+            }
+            request.attr_end(data);
+            return result;
+        }
+
+        int start() {
+            ALOGV("Executing firmware roam state set, state = %d", roam_state);
+            WifiRequest request(familyId(), ifaceId());
+            int result = createRequest(request);
+            if (result < 0) {
+                return result;
+            }
+
+            result = requestResponse(request);
+            if (result < 0) {
+                ALOGE("Failed to execute firmware roam state set, result = %d", result);
+                return result;
+            }
+
+            ALOGI("Successfully set firmware roam state - %d", roam_state);
+            return result;
+        }
+
+        virtual int handleResponse(WifiEvent& reply) {
+            /* Nothing to do on response! */
+            return NL_SKIP;
+        }
+};
+
+wifi_error wifi_enable_firmware_roaming(wifi_interface_handle iface,
+            fw_roaming_state_t state)
+{
+    /* Set firmware roaming state */
+    FirmwareRoamingStateCommand *cmd = new FirmwareRoamingStateCommand(iface, state);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    wifi_error result = (wifi_error)cmd->start();
+    //release the reference of command as well
+    cmd->releaseRef();
+    return result;
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 
diff --git a/bcmdhd/wifi_hal/link_layer_stats.cpp b/bcmdhd/wifi_hal/link_layer_stats.cpp
index 42e3f2f..34226f4 100644
--- a/bcmdhd/wifi_hal/link_layer_stats.cpp
+++ b/bcmdhd/wifi_hal/link_layer_stats.cpp
@@ -106,21 +106,6 @@
             ALOGE("Invalid stats pointer received");
             return NL_SKIP;
         }
-        if (radio_stat->num_channels > 11) {
-            ALOGE("Incorrect number of channels = %d", radio_stat->num_channels);
-            // dump data before num_channels
-            ALOGE("radio: = %d", radio_stat->radio);
-            ALOGE("on_time: = %d", radio_stat->on_time);
-            ALOGE("tx_time: = %d", radio_stat->tx_time);
-            ALOGE("rx_time: = %d", radio_stat->rx_time);
-            ALOGE("on_time_scan: = %d", radio_stat->on_time_scan);
-            ALOGE("on_time_nbd: = %d", radio_stat->on_time_nbd);
-            ALOGE("on_time_gscan: = %d", radio_stat->on_time_gscan);
-            ALOGE("on_time_pno_scan: = %d", radio_stat->on_time_pno_scan);
-            ALOGE("on_time_hs20: = %d", radio_stat->on_time_hs20);
-            free(radio_stat);
-            return NL_SKIP;
-        }
         wifi_iface_stat *iface_stat =
             (wifi_iface_stat *)((char *)&((wifi_radio_stat_internal *)data)->channels
                 + radio_stat->num_channels * sizeof(wifi_channel_stat));
diff --git a/bcmdhd/wifi_hal/nan.cpp b/bcmdhd/wifi_hal/nan.cpp
new file mode 100755
index 0000000..cfabfa8
--- /dev/null
+++ b/bcmdhd/wifi_hal/nan.cpp
@@ -0,0 +1,5292 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Portions copyright (C) 2019 Broadcom Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#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 <ctype.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 <log/log.h>
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+#include "netinet/in.h"
+#include "arpa/inet.h"
+#include <openssl/sha.h>
+#include <openssl/evp.h> 
+#include <sys/ioctl.h>
+
+/* Changes between incompatible Version of NAN */
+#define NAN_MAJOR_REL_VERSION       1
+/* Changes between Source and Binary compatible Version of NAN */
+#define NAN_MINOR_REL_VERSION       2
+/* Changes between perfectly compatible Version of NAN */
+#define NAN_PATCH_REL_VERSION       3
+
+#define SVC_NAME_TO_HASH            1
+#define NAN_SVC_HASH_SIZE           6
+#define C2S(x)  case x: return #x;
+#define NAN_PUB_RECV_FLAG_MAX 15
+#define NAN_SUB_RECV_FLAG_MAX 7
+#define NAN_DISC_IND_MAX 7
+#define NAN_MAX 255
+#define NAN_MIN 0
+#define INVALID 0xFF
+#define NAN_MAX_PERIOD 16
+#define ISGREATER(i, x) (i > x) ? 1 : 0
+#define NAN_MAX_RSSI 90
+#define NAN_SECURITY_SALT_SIZE	14
+#define NAN_MAC_INVALID_TRANSID 0xFFFF
+
+#define SVCHASH_ISNULL(svc_hash) ((((u8 *)(svc_hash))[0] |		\
+            ((u8 *)(svc_hash))[1] |		\
+            ((u8 *)(svc_hash))[2] |		\
+            ((u8 *)(svc_hash))[3] |		\
+            ((u8 *)(svc_hash))[4] |		\
+            ((u8 *)(svc_hash))[5]) == 0)
+#define ETHER_ISNULLADDR(ea) ((((u8 *)(ea))[0] |		\
+            ((u8 *)(ea))[1] |		\
+            ((u8 *)(ea))[2] |		\
+            ((u8 *)(ea))[3] |		\
+            ((u8 *)(ea))[4] |		\
+            ((u8 *)(ea))[5]) == 0)
+
+/* NAN structs versioning b/w DHD and HAL
+ * TODO:add versions for each struct*/
+#define NAN_HAL_VERSION_1	0x2
+struct nan_dbg_cntrs {
+    u32 dp_req; /* cmd */
+    u32 dp_resp; /* cmd */
+    u32 dp_req_evt;
+    u32 dp_confirm_evt;
+    u32 transmit_req; /* cmd */
+    u32 transmit_txs; /* event */
+    u32 transmit_recv; /* event */
+};
+nan_dbg_cntrs counters;
+
+u32 current_dhd_hal_ver = 0;
+
+/* TODO: Known bug in Android which was discovered too late and then left in for backward compatibility.
+ * The issue is that the Service Name selected by the framework is invalid - it contains a space.
+ * Therefore, the underlying implementation partially converts it to lower case and uses the results for PMK generation.
+ * I.e. the PMK is generated based on the following service name: "Wi-Fi Aware Data Path"
+ */
+/* SVC Hash generated for svc name string "Wi-Fi Aware Data Path" */
+u8 NAN_OOB_INTEROP_SVC_HASH[NAN_SVC_HASH_SIZE] = {0x05, 0x9e, 0xd4, 0xcf, 0x89, 0x1a};
+#define NAN_OOB_INTEROP_SVC_NAME "Wi-Fi Aware Data Path"
+
+static const char *NanStatusToString(NanStatusType status)
+{
+    switch (status) {
+        C2S(NAN_STATUS_SUCCESS)
+            C2S(NAN_STATUS_INTERNAL_FAILURE)
+            C2S(NAN_STATUS_PROTOCOL_FAILURE)
+            C2S(NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID)
+            C2S(NAN_STATUS_NO_RESOURCE_AVAILABLE)
+            C2S(NAN_STATUS_INVALID_PARAM)
+            C2S(NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID)
+            C2S(NAN_STATUS_INVALID_NDP_ID)
+            C2S(NAN_STATUS_NAN_NOT_ALLOWED)
+            C2S(NAN_STATUS_NO_OTA_ACK)
+            C2S(NAN_STATUS_ALREADY_ENABLED)
+            C2S(NAN_STATUS_FOLLOWUP_QUEUE_FULL)
+            C2S(NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED)
+
+        default:
+            return "NAN_STATUS_INTERNAL_FAILURE";
+    }
+}
+
+/* Nan Data Path Security Information */
+typedef struct {
+    /*
+       Unique Instance Id identifying the Responder's service.
+       This is same as publish_id notified on the subscribe side
+       in a publish/subscribe scenario
+     */
+    u32 requestor_instance_id; /* Value 0 for no publish/subscribe */
+    /*
+       Discovery MAC addr of the publisher/peer
+     */
+    u8 peer_disc_mac_addr[NAN_MAC_ADDR_LEN];
+    /*
+       Unique token Id generated on the initiator/responder
+       side used for a NDP session between two NAN devices
+     */
+    NanDataPathId ndp_instance_id;
+} NanDataPathSecInfoRequest;
+/*
+ * Note: NAN_ATTRIBUTE should match with one that on driver side, wl_cfgnan.h and
+ * NanAttrToString as well for enum to string.
+ */
+typedef enum {
+    NAN_ATTRIBUTE_HEADER                            = 100,
+    NAN_ATTRIBUTE_HANDLE                            = 101,
+    NAN_ATTRIBUTE_TRANSAC_ID                        = 102,
+
+    /* NAN Enable request attributes */
+    NAN_ATTRIBUTE_2G_SUPPORT                        = 103,
+    NAN_ATTRIBUTE_5G_SUPPORT                        = 104,
+    NAN_ATTRIBUTE_CLUSTER_LOW                       = 105,
+    NAN_ATTRIBUTE_CLUSTER_HIGH                      = 106,
+    NAN_ATTRIBUTE_SID_BEACON                        = 107,
+    NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON               = 108,
+    NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON               = 109,
+    NAN_ATTRIBUTE_SDF_2G_SUPPORT                    = 110,
+    NAN_ATTRIBUTE_SDF_5G_SUPPORT                    = 111,
+    NAN_ATTRIBUTE_RSSI_CLOSE                        = 112,
+    NAN_ATTRIBUTE_RSSI_MIDDLE                       = 113,
+    NAN_ATTRIBUTE_RSSI_PROXIMITY                    = 114,
+    NAN_ATTRIBUTE_HOP_COUNT_LIMIT                   = 115,
+    NAN_ATTRIBUTE_RANDOM_FACTOR                       = 116,
+    NAN_ATTRIBUTE_MASTER_PREF                       = 117,
+    NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL            = 118,
+
+    /* Nan Publish/Subscribe request attributes */
+    NAN_ATTRIBUTE_PUBLISH_ID                        = 119,
+    NAN_ATTRIBUTE_TTL                               = 120,
+    NAN_ATTRIBUTE_PERIOD                            = 121,
+    NAN_ATTRIBUTE_REPLIED_EVENT_FLAG                = 122,
+    NAN_ATTRIBUTE_PUBLISH_TYPE                      = 123,
+    NAN_ATTRIBUTE_TX_TYPE                           = 124,
+    NAN_ATTRIBUTE_PUBLISH_COUNT                     = 125,
+    NAN_ATTRIBUTE_SERVICE_NAME_LEN                  = 126,
+    NAN_ATTRIBUTE_SERVICE_NAME                      = 127,
+    NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN         = 128,
+    NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO             = 129,
+    NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN               = 130,
+    NAN_ATTRIBUTE_RX_MATCH_FILTER                   = 131,
+    NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN               = 132,
+    NAN_ATTRIBUTE_TX_MATCH_FILTER                   = 133,
+    NAN_ATTRIBUTE_SUBSCRIBE_ID                      = 134,
+    NAN_ATTRIBUTE_SUBSCRIBE_TYPE                    = 135,
+    NAN_ATTRIBUTE_SERVICERESPONSEFILTER             = 136,
+    NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE            = 137,
+    NAN_ATTRIBUTE_USESERVICERESPONSEFILTER          = 138,
+    NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION     = 139,
+    NAN_ATTRIBUTE_SUBSCRIBE_MATCH                   = 140,
+    NAN_ATTRIBUTE_SUBSCRIBE_COUNT                   = 141,
+    NAN_ATTRIBUTE_MAC_ADDR                          = 142,
+    NAN_ATTRIBUTE_MAC_ADDR_LIST                     = 143,
+    NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES         = 144,
+    NAN_ATTRIBUTE_PUBLISH_MATCH                     = 145,
+
+    /* Nan Event attributes */
+    NAN_ATTRIBUTE_ENABLE_STATUS                     = 146,
+    NAN_ATTRIBUTE_JOIN_STATUS                       = 147,
+    NAN_ATTRIBUTE_ROLE                              = 148,
+    NAN_ATTRIBUTE_MASTER_RANK                       = 149,
+    NAN_ATTRIBUTE_ANCHOR_MASTER_RANK                = 150,
+    NAN_ATTRIBUTE_CNT_PEND_TXFRM                    = 151,
+    NAN_ATTRIBUTE_CNT_BCN_TX                        = 152,
+    NAN_ATTRIBUTE_CNT_BCN_RX                        = 153,
+    NAN_ATTRIBUTE_CNT_SVC_DISC_TX                   = 154,
+    NAN_ATTRIBUTE_CNT_SVC_DISC_RX                   = 155,
+    NAN_ATTRIBUTE_AMBTT                             = 156,
+    NAN_ATTRIBUTE_CLUSTER_ID                        = 157,
+    NAN_ATTRIBUTE_INST_ID                           = 158,
+    NAN_ATTRIBUTE_OUI                               = 159,
+    NAN_ATTRIBUTE_STATUS                            = 160,
+    NAN_ATTRIBUTE_DE_EVENT_TYPE                     = 161,
+    NAN_ATTRIBUTE_MERGE                             = 162,
+    NAN_ATTRIBUTE_IFACE                             = 163,
+    NAN_ATTRIBUTE_CHANNEL                           = 164,
+    NAN_ATTRIBUTE_PEER_ID                           = 165,
+    NAN_ATTRIBUTE_NDP_ID                            = 167,
+    NAN_ATTRIBUTE_SECURITY                          = 168,
+    NAN_ATTRIBUTE_QOS                               = 169,
+    NAN_ATTRIBUTE_RSP_CODE                          = 170,
+    NAN_ATTRIBUTE_INST_COUNT                        = 171,
+    NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR                = 172,
+    NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR                 = 173,
+    NAN_ATTRIBUTE_IF_ADDR                           = 174,
+    NAN_ATTRIBUTE_WARMUP_TIME                       = 175,
+    NAN_ATTRIBUTE_RECV_IND_CFG                      = 176,
+    NAN_ATTRIBUTE_RSSI_CLOSE_5G                     = 177,
+    NAN_ATTRIBUTE_RSSI_MIDDLE_5G                    = 178,
+    NAN_ATTRIBUTE_RSSI_PROXIMITY_5G                 = 179,
+    NAN_ATTRIBUTE_CONNMAP                           = 180,
+    NAN_ATTRIBUTE_24G_CHANNEL                       = 181,
+    NAN_ATTRIBUTE_5G_CHANNEL                        = 182,
+    NAN_ATTRIBUTE_DWELL_TIME                        = 183,
+    NAN_ATTRIBUTE_SCAN_PERIOD                       = 184,
+    NAN_ATTRIBUTE_RSSI_WINDOW_SIZE                  = 185,
+    NAN_ATTRIBUTE_CONF_CLUSTER_VAL                  = 186,
+    NAN_ATTRIBUTE_AVAIL_BIT_MAP                     = 187,
+    NAN_ATTRIBUTE_ENTRY_CONTROL                     = 188,
+    NAN_ATTRIBUTE_CIPHER_SUITE_TYPE                 = 189,
+    NAN_ATTRIBUTE_KEY_TYPE                          = 190,
+    NAN_ATTRIBUTE_KEY_LEN                           = 191,
+    NAN_ATTRIBUTE_SCID                              = 192,
+    NAN_ATTRIBUTE_SCID_LEN                          = 193,
+    NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP             = 194,
+    NAN_ATTRIBUTE_SDE_CONTROL_SECURITY              = 195,
+    NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE               = 196,
+    NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT         = 197,
+    NAN_ATTRIBUTE_NO_CONFIG_AVAIL                   = 198,
+    NAN_ATTRIBUTE_2G_AWAKE_DW                       = 199,
+    NAN_ATTRIBUTE_5G_AWAKE_DW                       = 200,
+    NAN_ATTRIBUTE_RANGING_INTERVAL                  = 201,
+    NAN_ATTRIBUTE_RANGING_INDICATION                = 202,
+    NAN_ATTRIBUTE_RANGING_INGRESS_LIMIT             = 203,
+    NAN_ATTRIBUTE_RANGING_EGRESS_LIMIT              = 204,
+    NAN_ATTRIBUTE_RANGING_AUTO_ACCEPT               = 205,
+    NAN_ATTRIBUTE_RANGING_RESULT                    = 206,
+    NAN_ATTRIBUTE_DISC_IND_CFG                      = 207,
+    NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG               = 208,
+    NAN_ATTRIBUTE_KEY_DATA                          = 209,
+    NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN    = 210,
+    NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO        = 211,
+    NAN_ATTRIBUTE_REASON                            = 212,
+    NAN_ATTRIBUTE_MATCH_OCCURRED_FLAG               = 213,
+    NAN_ATTRIBUTE_OUT_OF_RESOURCE_FLAG              = 214,
+    NAN_ATTRIBUTE_DWELL_TIME_5G                     = 215,
+    NAN_ATTRIBUTE_SCAN_PERIOD_5G                    = 216,
+    NAN_ATTRIBUTE_SVC_RESPONDER_POLICY              = 217,
+    NAN_ATTRIBUTE_EVENT_MASK                        = 218,
+    NAN_ATTRIBUTE_SUB_SID_BEACON                    = 219,
+    NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL            = 220,
+    NAN_ATTRIBUTE_CMD_RESP_DATA                     = 221,
+    NAN_ATTRIBUTE_CMD_USE_NDPE                      = 222,
+    NAN_ATTRIBUTE_ENABLE_MERGE                      = 223,
+    NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL         = 224,
+    NAN_ATTRIBUTE_NSS                               = 225,
+    NAN_ATTRIBUTE_ENABLE_RANGING                    = 226,
+    NAN_ATTRIBUTE_DW_EARLY_TERM                     = 227
+} NAN_ATTRIBUTE;
+
+typedef enum {
+    NAN_REQUEST_ENABLE                          = 0,
+    NAN_REQUEST_DISABLE                         = 1,
+    NAN_REQUEST_PUBLISH                         = 2,
+    NAN_REQUEST_PUBLISH_CANCEL                  = 3,
+    NAN_REQUEST_TRANSMIT_FOLLOWUP               = 4,
+    NAN_REQUEST_SUBSCRIBE                       = 5,
+    NAN_REQUEST_SUBSCRIBE_CANCEL                = 6,
+    NAN_REQUEST_STATS                           = 7,
+    NAN_REQUEST_CONFIG                          = 8,
+    NAN_REQUEST_TCA                             = 9,
+    NAN_REQUEST_EVENT_CHECK                     = 10,
+    NAN_REQUEST_GET_CAPABILTIES                 = 11,
+    NAN_DATA_PATH_IFACE_CREATE                  = 12,
+    NAN_DATA_PATH_IFACE_DELETE                  = 13,
+    NAN_DATA_PATH_INIT_REQUEST                  = 14,
+    NAN_DATA_PATH_IND_RESPONSE                  = 15,
+    NAN_DATA_PATH_END                           = 16,
+    NAN_DATA_PATH_IFACE_UP                      = 17,
+    NAN_DATA_PATH_SEC_INFO                      = 18,
+    NAN_VERSION_INFO                            = 19,
+    NAN_REQUEST_ENABLE_MERGE		    = 20,
+    NAN_REQUEST_LAST                            = 0xFFFF
+} NanRequestType;
+
+/*
+ * The enum is based on the BCME Response defs
+ * used in the firmware and defined at
+ * path: src/include/bcmeutils.h
+ */
+enum nan_response_status {
+    BCME_OK                  = 0,
+    BCME_ERROR               = -1,
+    BCME_BADARG              = -2,
+    BCME_BADRATESET          = -12,
+    BCME_BADBAND             = -13,
+    BCME_BUSY                = -16,
+    BCME_BADCHAN             = -20,
+    BCME_UNSUPPORTED         = -23,
+    BCME_BADLEN              = -24,
+    BCME_NOTREADY            = -25,
+    BCME_NOMEM               = -27,
+    BCME_NOTFOUND            = -30,
+    BCME_TXFAIL              = -38,
+    BCME_RXFAIL              = -39,
+    BCME_SCANREJECT          = -43,
+    BCME_USAGE_ERROR         = -44,
+    BCME_IOCTL_ERROR         = -45
+};
+
+enum nan_de_event_type {
+    NAN_EVENT_IFACE       = 0,
+    NAN_EVENT_START       = 1,
+    NAN_EVENT_JOIN        = 2,
+    NAN_EVENT_ROLE_CHANGE = 3,
+    NAN_EVENT_MERGE       = 4
+};
+
+typedef struct _nan_hal_resp {
+    u16 instance_id;
+    u16  subcmd;
+    int32_t status;
+    int32_t value;
+    /* Identifier for the instance of the NDP */
+    u16 ndp_instance_id;
+    /* Publisher NMI */
+    u8 pub_nmi[NAN_MAC_ADDR_LEN];
+    /* SVC_HASH */
+    u8 svc_hash[NAN_SVC_HASH_SIZE];
+    char nan_reason[NAN_ERROR_STR_LEN]; /* Describe the NAN reason type */
+    char pad[3];
+    NanCapabilities capabilities;
+} nan_hal_resp_t;
+
+typedef int (*match_fn)(void *p1, void *data);
+
+typedef struct _nan_hal_info {
+    void *nan_handle;
+    void *nan_mac_control;
+    void *nan_disc_control;
+    void *nan_dp_control;
+} nan_hal_info_t;
+
+u8 mNmi[NAN_MAC_ADDR_LEN];
+/* Static functions */
+static int is_de_event(int cmd);
+static int is_dp_event(int cmd);
+static int is_cmd_response(int cmd);
+
+static int get_svc_hash(unsigned char *svc_name, u16 svc_name_len,
+        u8 *svc_hash, u16 svc_hash_len);
+NanResponseType get_response_type(WIFI_SUB_COMMAND nan_subcmd);
+static NanStatusType nan_map_term_status(u32 vendor_reason);
+static NanStatusType nan_map_response_status(int vendor_status);
+static int ioctl_sock = 0;
+
+static int setFlags(int s, struct ifreq *ifr, int set, int clr)
+{
+    if(ioctl(s, SIOCGIFFLAGS, ifr) < 0) {
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    ifr->ifr_flags = (ifr->ifr_flags & (~clr)) | set;
+    if (ioctl(s, SIOCSIFFLAGS, ifr) < 0) {
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    return WIFI_SUCCESS;
+}
+
+static inline void init_sockaddr_in(struct sockaddr_in *sin, const char *addr)
+{
+    sin->sin_family = AF_INET;
+    sin->sin_port = 0;
+    sin->sin_addr.s_addr = inet_addr(addr);
+}
+
+static int setAddr(int s, struct ifreq *ifr, const char *addr)
+{
+    init_sockaddr_in((struct sockaddr_in *) &ifr->ifr_addr, addr);
+
+    if (ioctl(s, SIOCSIFADDR, ifr) < 0) {
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    return WIFI_SUCCESS;
+}
+
+/* Function to separate the common events to NAN1.0 events */
+static int is_de_event(int cmd) {
+    bool is_de_evt = false;
+
+    switch(cmd) {
+        case NAN_EVENT_SUBSCRIBE_UNMATCH:
+        case NAN_EVENT_SUBSCRIBE_TERMINATED:
+        case NAN_EVENT_PUBLISH_TERMINATED:
+        case NAN_EVENT_SUBSCRIBE_MATCH:
+        case NAN_EVENT_FOLLOWUP:
+        case NAN_EVENT_TRANSMIT_FOLLOWUP_IND:
+        case NAN_EVENT_PUBLISH_REPLIED_IND:
+            is_de_evt = true;
+            break;
+        default:
+            /* Not used */
+            break;
+    }
+    return is_de_evt;
+}
+
+/* Function to separate NAN2.0 events */
+static int is_dp_event(int cmd) {
+    bool is_dp_evt = false;
+
+    switch(cmd) {
+        case NAN_EVENT_DATA_REQUEST:
+        case NAN_EVENT_DATA_CONFIRMATION:
+        case NAN_EVENT_DATA_END:
+            is_dp_evt = true;
+            break;
+        default:
+            /* Not used */
+            break;
+    }
+    return is_dp_evt;
+}
+
+static int is_cmd_response(int cmd) {
+    bool is_cmd_resp = false;
+
+    switch(cmd) {
+        case NAN_ASYNC_RESPONSE_DISABLED:
+            is_cmd_resp = true;
+            break;
+        default:
+            break;
+    }
+    return is_cmd_resp;
+}
+
+static NanStatusType nan_map_response_status (int vendor_status) {
+    NanStatusType hal_status;
+
+    switch(vendor_status) {
+        case BCME_OK:
+            hal_status = NAN_STATUS_SUCCESS;
+            break;
+        case BCME_BUSY:
+            hal_status = NAN_STATUS_NO_RESOURCE_AVAILABLE;
+            break;
+        case BCME_NOTREADY:
+            hal_status = NAN_STATUS_NAN_NOT_ALLOWED;
+            break;
+        case BCME_BADLEN:
+        case BCME_BADBAND:
+            hal_status = NAN_STATUS_INVALID_PARAM;
+            break;
+        case BCME_NOMEM:
+            hal_status = NAN_STATUS_NO_RESOURCE_AVAILABLE;
+            break;
+        case NAN_STATUS_INTERNAL_FAILURE:
+        case NAN_STATUS_PROTOCOL_FAILURE:
+        case NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID:
+        case NAN_STATUS_NO_RESOURCE_AVAILABLE:
+        case NAN_STATUS_INVALID_PARAM:
+        case NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID:
+        case NAN_STATUS_INVALID_NDP_ID:
+        case NAN_STATUS_NAN_NOT_ALLOWED:
+        case NAN_STATUS_NO_OTA_ACK:
+        case NAN_STATUS_ALREADY_ENABLED:
+        case NAN_STATUS_FOLLOWUP_QUEUE_FULL:
+        case NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED:
+            hal_status = (NanStatusType)vendor_status;
+            break;
+        default:
+            ALOGE("%s Unknown vendor status, status = %d\n",
+                    __func__, vendor_status);
+            /* Generic error */
+            hal_status = NAN_STATUS_INTERNAL_FAILURE;
+    }
+    return hal_status;
+}
+
+static void prhex(const char *msg, u8 *buf, u32 nbytes);
+static const char *NanAttrToString(u16 cmd);
+static const char *NanCmdToString(int cmd);
+static const char *NanRspToString(int cmd);
+
+#define NAN_DBG_ENTER() {ALOGI("Enter: %s\n", __func__);}
+#define NAN_DBG_EXIT() {ALOGI("Exit: %s\n", __func__);}
+
+static int passphrase_to_pmk(u8 *peer_mac, u32 cipher_type,
+        u8 *svc_hash, NanSecurityKeyInfo *key_info, u8 *pmk_hex) {
+    int result = NAN_STATUS_SUCCESS;
+    u8 salt[NAN_SECURITY_SALT_SIZE];
+
+    NAN_DBG_ENTER();
+    salt[0] = 0; /* salt_version */
+    salt[1] = cipher_type;
+    if (svc_hash && peer_mac) {
+        memcpy(&salt[2], svc_hash, NAN_SVC_HASH_SIZE);
+        memcpy(&salt[2 + NAN_SVC_HASH_SIZE], peer_mac,
+                ETHER_ADDR_LEN);
+        prhex("Salt", salt, NAN_SECURITY_SALT_SIZE);
+    } else {
+        ALOGE("Mandory parameters are not present\n");
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+    if (key_info->body.passphrase_info.passphrase_len < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+            key_info->body.passphrase_info.passphrase_len > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+        ALOGE("passphrase must be between %d and %d characters long\n",
+                NAN_SECURITY_MIN_PASSPHRASE_LEN,
+                NAN_SECURITY_MAX_PASSPHRASE_LEN);
+        return WIFI_ERROR_INVALID_ARGS;
+    }
+
+    result = PKCS5_PBKDF2_HMAC((const char *) key_info->body.passphrase_info.passphrase,
+            key_info->body.passphrase_info.passphrase_len, salt, sizeof(salt),
+            4096, ((cipher_type == NAN_CIPHER_SUITE_SHARED_KEY_128_MASK) ?
+                (const EVP_MD *)EVP_sha256():(const EVP_MD *)EVP_sha384()), NAN_PMK_INFO_LEN,  pmk_hex);
+    prhex("PMK_HEX", pmk_hex, 32);
+    NAN_DBG_EXIT();
+    return result;
+}
+
+typedef void *NanRequest;
+nan_hal_info_t info;
+
+#define SVC_LIST(info)                    ((info).svc_list)
+#define SVC_LIST_SIZE(info)               ((info).svc_list.total_items)
+#define DP_SVC_LIST(info)                 ((info).dp_svc_list)
+#define DP_SVC_LIST_SIZE(info)            ((info).dp_svc_list.total_items)
+#define NAN_HANDLE(info)                  ((info).nan_handle)
+#define GET_NAN_HANDLE(info)              ((NanHandle *)info.nan_handle)
+#define NAN_MAC_CONTROL(info)             ((info).nan_mac_control)
+
+///////////////////////////////////////////////////////////////////////////////
+class NanHandle
+{
+    public:
+        NanCallbackHandler mHandlers;
+        NanHandle(wifi_handle handle, NanCallbackHandler handlers):mHandlers(handlers)
+    {}
+
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+class NanDiscEnginePrimitive : public WifiCommand
+{
+    NanRequest mParams;
+    NanRequestType mType;
+    u16 mInstId;
+    u32 mPeerId;
+    u16 mTxId;
+
+    public:
+    NanDiscEnginePrimitive(wifi_interface_handle iface, int id,
+            NanRequest params, NanRequestType cmdType)
+        : WifiCommand("NanCommand", iface, id), mParams(params), mType(cmdType)
+    {
+        mInstId = 0;
+        mPeerId = 0;
+        setTransactionId(id);
+    }
+
+    ~NanDiscEnginePrimitive() {
+        ALOGE("NanDiscEnginePrimitive destroyed\n");
+    }
+
+    void setType(NanRequestType type) {
+        mType = type;
+    }
+
+    void setInstId(u16 inst_id) {
+        mInstId = inst_id;
+    }
+
+    int getInstanceId() {
+        return mInstId;
+    }
+
+    void setTransactionId(u16 tx_id) {
+        mTxId = tx_id;
+    }
+
+    int getTransactionId() {
+        return mTxId;
+    }
+
+    void setParams(NanRequest params) {
+        mParams = params;
+    }
+
+    int createRequest(WifiRequest& request)
+    {
+        ALOGI("NAN CMD: %s\n", NanCmdToString(mType));
+        if (mType == NAN_REQUEST_SUBSCRIBE) {
+            return createSubscribeRequest(request,
+                    (NanSubscribeRequest *)mParams);
+        } else if (mType == NAN_REQUEST_SUBSCRIBE_CANCEL) {
+            return createSubscribeCancelRequest(request,
+                    (NanSubscribeCancelRequest *)mParams);
+        } else if (mType == NAN_REQUEST_PUBLISH) {
+            return createPublishRequest(request,
+                    (NanPublishRequest *)mParams);
+        } else if (mType == NAN_REQUEST_PUBLISH_CANCEL) {
+            return createPublishCancelRequest(request,
+                    (NanPublishCancelRequest *)mParams);
+        } else if (mType == NAN_REQUEST_TRANSMIT_FOLLOWUP) {
+            return createTransmitFollowupRequest(request,
+                    (NanTransmitFollowupRequest *)mParams);
+        } else if (mType == NAN_REQUEST_GET_CAPABILTIES) {
+            return getCapabilitiesRequest(request);
+        } else {
+            ALOGE("%s Unknown Nan request\n", __func__);
+        }
+        return WIFI_SUCCESS;
+    }
+
+    int createPublishRequest(WifiRequest& request, NanPublishRequest *mParams)
+    {
+        NAN_DBG_ENTER();
+        u8 pmk_hex[NAN_PMK_INFO_LEN];
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_PUBLISH);
+        if (result < 0) {
+            ALOGE("%s Failed to create request, result = %d\n", __func__, result);
+            return result;
+        }
+
+        /* If handle is 0xFFFF, then update instance_id in response of this request
+         * otherwise, update not needed
+         */
+        mInstId = mParams->publish_id;
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        result = request.put_u16(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill pub id, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u16(NAN_ATTRIBUTE_TTL, mParams->ttl);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ttl, result = %d\n", __func__, result);
+            return result;
+        }
+
+        if (ISGREATER(mParams->period, NAN_MAX_PERIOD)) {
+            ALOGE("%s:Invalid period value.\n", __FUNCTION__);
+            return WIFI_ERROR_NOT_SUPPORTED;
+        }
+        result = request.put_u16(NAN_ATTRIBUTE_PERIOD, mParams->period);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill period, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_TYPE, mParams->publish_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill pub type, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_TX_TYPE, mParams->tx_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill tx type, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_COUNT, mParams->publish_count);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill pub cnt, result = %d\n", __func__, result);
+            return result;
+        }
+
+        if (mParams->service_name_len) {
+            u8 svc_hash[NAN_SVC_HASH_SIZE];
+
+            result = get_svc_hash(mParams->service_name, mParams->service_name_len,
+                    svc_hash, NAN_SVC_HASH_SIZE);
+            if (result < 0) {
+                ALOGE("%s: Failed to get hashed svc name\n", __func__);
+                return result;
+            }
+
+            mParams->service_name_len = NAN_SVC_HASH_SIZE;
+            memcpy(mParams->service_name, svc_hash, mParams->service_name_len);
+
+            result = request.put_u16(NAN_ATTRIBUTE_SERVICE_NAME_LEN, mParams->service_name_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc name len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            result = request.put(NAN_ATTRIBUTE_SERVICE_NAME, (void *)mParams->service_name,
+                    mParams->service_name_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc name, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->service_specific_info_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+                    mParams->service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc info len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+                    (void *)mParams->service_specific_info, mParams->service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc info, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->rx_match_filter_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN,
+                    mParams->rx_match_filter_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill rx match filter len, result = %d\n",
+                        __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->rx_match_filter, mParams->rx_match_filter_len);
+            result = request.put(NAN_ATTRIBUTE_RX_MATCH_FILTER,
+                    (void *)mParams->rx_match_filter, mParams->rx_match_filter_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill rx match filter, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->tx_match_filter_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN,
+                    mParams->tx_match_filter_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill tx match filter, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->tx_match_filter, mParams->tx_match_filter_len);
+            result = request.put(NAN_ATTRIBUTE_TX_MATCH_FILTER,
+                    (void *)mParams->tx_match_filter, mParams->tx_match_filter_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill tx match filter, result = %d\n",
+                        __func__, result);
+                return result;
+            }
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_MATCH, mParams->publish_match_indicator);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_PUBLISH_MATCH, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        if (ISGREATER(mParams->recv_indication_cfg, NAN_PUB_RECV_FLAG_MAX)) {
+            ALOGE("%s:Invalid recv_flag value.\n", __FUNCTION__);
+            return WIFI_ERROR_NOT_SUPPORTED;
+        }
+        result = request.put_u8(NAN_ATTRIBUTE_RECV_IND_CFG,
+                mParams->recv_indication_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_RECV_IND_CFG, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE,
+                mParams->cipher_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_CIPHER_SUITE_TYPE, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_KEY_TYPE,
+                mParams->key_info.key_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_KEY_TYPE, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) {
+            if (mParams->key_info.body.pmk_info.pmk_len) {
+                result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN,
+                        mParams->key_info.body.pmk_info.pmk_len);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill pmk len, result = %d\n", __func__, result);
+                    return result;
+                }
+                result = request.put(NAN_ATTRIBUTE_KEY_DATA,
+                        (void *)mParams->key_info.body.pmk_info.pmk,
+                        mParams->key_info.body.pmk_info.pmk_len);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill pmk, result = %d\n", __func__, result);
+                    return result;
+                }
+            }
+        }
+
+        if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+            if (mParams->key_info.body.passphrase_info.passphrase_len < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+                    mParams->key_info.body.passphrase_info.passphrase_len > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+                ALOGE("passphrase must be between %d and %d characters long\n",
+                        NAN_SECURITY_MIN_PASSPHRASE_LEN,
+                        NAN_SECURITY_MAX_PASSPHRASE_LEN);
+                return NAN_STATUS_INVALID_PARAM;
+            } else {
+                memset(pmk_hex, 0, NAN_PMK_INFO_LEN);
+                result = passphrase_to_pmk(mNmi, mParams->cipher_type,
+                        mParams->service_name, &mParams->key_info, pmk_hex);
+                if (result < 0) {
+                    ALOGE("%s: Failed to convert passphrase to key data, result = %d\n", __func__, result);
+                    return result;
+                }
+                result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN, NAN_PMK_INFO_LEN);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill passphrase len, result = %d\n", __func__, result);
+                    return result;
+                }
+                result = request.put(NAN_ATTRIBUTE_KEY_DATA, pmk_hex, NAN_PMK_INFO_LEN);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill passphrase, result = %d\n", __func__, result);
+                    return result;
+                }
+            }
+        }
+
+        if (mParams->scid_len) {
+            result = request.put_u32(NAN_ATTRIBUTE_SCID_LEN,
+                    mParams->scid_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill scid len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->scid, mParams->scid_len);
+            result = request.put(NAN_ATTRIBUTE_SCID,
+                    (void *)mParams->scid, mParams->scid_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill scid, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP,
+                mParams->sdea_params.config_nan_data_path);
+
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_SECURITY,
+                mParams->sdea_params.security_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SDE_CONTROL_SECURITY, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE,
+                mParams->sdea_params.ndp_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT,
+                mParams->sdea_params.ranging_state);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG,
+                mParams->rssi_threshold_flag);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        if (mParams->sdea_service_specific_info_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN,
+                    mParams->sdea_service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill sdea svc info len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+            result = request.put(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO,
+                    (void *)mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill sdea svc info, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SVC_RESPONDER_POLICY,
+                mParams->service_responder_policy);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_SVC_RESPONDER_POLICY, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        request.attr_end(data);
+
+        ALOGI("Returning successfully\n");
+        NAN_DBG_EXIT();
+        return result;
+    }
+
+    int createPublishCancelRequest(WifiRequest& request, NanPublishCancelRequest *mParams)
+    {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_PUBLISH_CANCEL);
+        if (result < 0) {
+            ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+            return result;
+        }
+
+        NAN_DBG_ENTER();
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        if (ISGREATER(mInstId, NAN_MAX)) {
+            ALOGE("%s:Invalid publish count value.\n", __FUNCTION__);
+            return WIFI_ERROR_NOT_SUPPORTED;
+        }
+        ALOGI("%s: pub id = %d, inst_id = %d\n", __func__, mParams->publish_id, mInstId);
+
+        result = request.put_u16(NAN_ATTRIBUTE_PUBLISH_ID, mInstId);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_PUBLISH_ID, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+        request.attr_end(data);
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int createSubscribeRequest(WifiRequest& request, NanSubscribeRequest *mParams)
+    {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_SUBSCRIBE);
+        if (result < 0) {
+            ALOGE("%s Failed to create request\n", __func__);
+            return result;
+        }
+
+        NAN_DBG_ENTER();
+
+        /* If handle is 0xFFFF, then update instance_id in response of this request
+         * otherwise, update not needed
+         */
+        mInstId = mParams->subscribe_id;
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        result = request.put_u16(NAN_ATTRIBUTE_SUBSCRIBE_ID, mInstId);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill sub id, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u16(NAN_ATTRIBUTE_TTL, mParams->ttl);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ttl, result = %d\n", __func__, result);
+            return result;
+        }
+
+        if (ISGREATER(mParams->period, NAN_MAX_PERIOD)) {
+            ALOGE("%s:Invalid period value.\n", __FUNCTION__);
+            return WIFI_ERROR_NOT_SUPPORTED;
+        }
+        result = request.put_u16(NAN_ATTRIBUTE_PERIOD, mParams->period);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill period, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SUBSCRIBE_TYPE, mParams->subscribe_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill sub type, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SERVICERESPONSEFILTER,
+                mParams->serviceResponseFilter);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill svc resp filter, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE,
+                mParams->serviceResponseInclude);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill svc resp include, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_USESERVICERESPONSEFILTER,
+                mParams->useServiceResponseFilter);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill use svc resp filter, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION,
+                mParams->ssiRequiredForMatchIndication);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ssi req match ind, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SUBSCRIBE_MATCH,
+                mParams->subscribe_match_indicator);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill sub match, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SUBSCRIBE_COUNT, mParams->subscribe_count);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill sub cnt, result = %d\n", __func__, result);
+            return result;
+        }
+
+        if (mParams->service_name_len) {
+            u8 svc_hash[NAN_SVC_HASH_SIZE];
+
+            result = get_svc_hash(mParams->service_name, mParams->service_name_len,
+                    svc_hash, NAN_SVC_HASH_SIZE);
+            if (result < 0) {
+                ALOGE("%s: Failed to get hashed svc name\n", __func__);
+                return result;
+            }
+
+            mParams->service_name_len = NAN_SVC_HASH_SIZE;
+            memcpy(mParams->service_name, svc_hash, mParams->service_name_len);
+
+            result = request.put_u16(NAN_ATTRIBUTE_SERVICE_NAME_LEN, mParams->service_name_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc hash len, result = %d\n",
+                        __func__, result);
+                return result;
+            }
+
+            result = request.put(NAN_ATTRIBUTE_SERVICE_NAME, (void *)mParams->service_name,
+                    mParams->service_name_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill hashed svc name, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->service_specific_info_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+                    mParams->service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc info len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+                    (void *)mParams->service_specific_info, mParams->service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc info, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->rx_match_filter_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN,
+                    mParams->rx_match_filter_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill rx match filter len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->rx_match_filter, mParams->rx_match_filter_len);
+            result = request.put(NAN_ATTRIBUTE_RX_MATCH_FILTER,
+                    (void *)mParams->rx_match_filter, mParams->rx_match_filter_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill rx match filter, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->tx_match_filter_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN,
+                    mParams->tx_match_filter_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill tx match filter len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->tx_match_filter, mParams->tx_match_filter_len);
+            result = request.put(NAN_ATTRIBUTE_TX_MATCH_FILTER,
+                    (void *)mParams->tx_match_filter, mParams->tx_match_filter_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill tx match filter, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) {
+            ALOGE("%s: Number of mac addrs: %d have crossed the threshold, fail to subscribe\n",
+                    __func__, mParams->num_intf_addr_present);
+            return WIFI_ERROR_NOT_SUPPORTED;
+        } else if (mParams->num_intf_addr_present) {
+            result = request.put_u16(NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES,
+                    mParams->num_intf_addr_present);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill mac addr list no, result = %d\n",
+                        __func__, result);
+                return result;
+            }
+
+            prhex(NULL, (u8 *)mParams->intf_addr,
+                    (mParams->num_intf_addr_present * NAN_MAC_ADDR_LEN));
+            result = request.put(NAN_ATTRIBUTE_MAC_ADDR_LIST, (void *)mParams->intf_addr,
+                    (mParams->num_intf_addr_present * NAN_MAC_ADDR_LEN));
+            if (result < 0) {
+                ALOGE("%s: Failed to fill mac addr list, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (ISGREATER(mParams->recv_indication_cfg, NAN_SUB_RECV_FLAG_MAX)) {
+            ALOGE("%s:Invalid recv_flag value.\n", __FUNCTION__);
+            return WIFI_ERROR_NOT_SUPPORTED;
+        }
+        result = request.put_u8(NAN_ATTRIBUTE_RECV_IND_CFG,
+                mParams->recv_indication_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill recv_indication_cfg, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        if (mParams->scid_len) {
+            result = request.put_u32(NAN_ATTRIBUTE_SCID_LEN,
+                    mParams->scid_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill scid len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->scid, mParams->scid_len);
+            result = request.put(NAN_ATTRIBUTE_SCID,
+                    (void *)mParams->scid, mParams->scid_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill scid, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP,
+                mParams->sdea_params.config_nan_data_path);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill config_nan_data_path, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_SECURITY,
+                mParams->sdea_params.security_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill security_cfg, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE,
+                mParams->sdea_params.ndp_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ndp_type, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT,
+                mParams->sdea_params.ranging_state);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ranging state, result = %d\n", __func__, result);
+            return result;
+        }
+
+        if (mParams->sdea_params.ranging_state == NAN_RANGING_ENABLE) {
+            result = request.put_u32(NAN_ATTRIBUTE_RANGING_INTERVAL,
+                    mParams->ranging_cfg.ranging_interval_msec);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill ranging_interval_msec, result = %d\n", __func__, result);
+                return result;
+            }
+
+            result = request.put_u32(NAN_ATTRIBUTE_RANGING_EGRESS_LIMIT,
+                    mParams->ranging_cfg.distance_egress_mm);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill distance_egress_mm, result = %d\n", __func__, result);
+                return result;
+            }
+
+            result = request.put_u32(NAN_ATTRIBUTE_RANGING_INDICATION,
+                    mParams->ranging_cfg.config_ranging_indications);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill config_ranging_indications, result = %d\n", __func__, result);
+                return result;
+            }
+
+            result = request.put_u32(NAN_ATTRIBUTE_RANGING_INGRESS_LIMIT,
+                    mParams->ranging_cfg.distance_ingress_mm);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill distance_ingress_mm, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        ALOGI("%s:RSSI threshold flag %d", __func__, mParams->rssi_threshold_flag);
+        result = request.put_u8(NAN_ATTRIBUTE_RSSI_THRESHOLD_FLAG,
+                mParams->rssi_threshold_flag);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill rssi_threshold_flag, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        if (mParams->sdea_service_specific_info_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN,
+                    mParams->sdea_service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill sdea svc info len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+            result = request.put(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO,
+                    (void *)mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill sdea svc info, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        request.attr_end(data);
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int createSubscribeCancelRequest(WifiRequest& request,
+            NanSubscribeCancelRequest *mParams) {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_SUBSCRIBE_CANCEL);
+        if (result < 0) {
+            ALOGE("%s Failed to create request \n", __func__);
+            return result;
+        }
+
+        NAN_DBG_ENTER();
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        if (ISGREATER(mInstId, NAN_MAX)) {
+            ALOGE("%s:Invalid subscribe id value.\n", __FUNCTION__);
+            return WIFI_ERROR_NOT_SUPPORTED;
+        }
+        ALOGI("%s: sub id = %u\n", __func__, mInstId);
+
+        result = request.put_u16(NAN_ATTRIBUTE_SUBSCRIBE_ID, mInstId);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill sub id, result = %d\n", __func__, result);
+            return result;
+        }
+
+        request.attr_end(data);
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int createTransmitFollowupRequest(WifiRequest& request,
+            NanTransmitFollowupRequest *mParams)
+    {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_TRANSMIT_FOLLOWUP);
+        if (result < 0) {
+            ALOGE("%s Failed to create request \n", __func__);
+            return result;
+        }
+
+        NAN_DBG_ENTER();
+
+        /* If handle is 0xFFFF, then update instance_id in response of this request
+         * otherwise, update not needed
+         */
+        mInstId = mParams->publish_subscribe_id;
+        mPeerId = mParams->requestor_instance_id;
+        mTxId = getTransactionId();
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        result = request.put_u32(NAN_ATTRIBUTE_PEER_ID, mPeerId);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill peer id, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u16(NAN_ATTRIBUTE_INST_ID, mInstId);
+        if (result < 0) {
+            ALOGE("%s Failed to fill inst id = %d \n", __func__, mInstId);
+            return result;
+        }
+
+        result = request.put_addr(NAN_ATTRIBUTE_MAC_ADDR, mParams->addr);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill mac addr\n", __func__);
+            return result;
+        }
+
+        if (mParams->service_specific_info_len > 0) {
+            result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+                    mParams->service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc info len \n", __func__);
+                return result;
+            }
+
+            prhex(NULL, mParams->service_specific_info, mParams->service_specific_info_len);
+            result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+                    (void *)mParams->service_specific_info, mParams->service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to put svc info, result = %d", __func__, result);
+                return result;
+            }
+            mParams->service_specific_info[mParams->service_specific_info_len] = '\0';
+            ALOGI("Transmit service info string is %s\n", mParams->service_specific_info);
+        }
+
+        if (ISGREATER(mParams->recv_indication_cfg, NAN_PUB_RECV_FLAG_MAX)) {
+            ALOGE("%s:Invalid recv_flag value.\n", __FUNCTION__);
+            return WIFI_ERROR_NOT_SUPPORTED;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_RECV_IND_CFG,
+                mParams->recv_indication_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_RECV_IND_CFG, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+        result = request.put_u16(NAN_ATTRIBUTE_TRANSAC_ID, mTxId);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_TRANSAC_ID, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        if (mParams->sdea_service_specific_info_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN,
+                    mParams->sdea_service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill sdea svc info len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+            result = request.put(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO,
+                    (void *)mParams->sdea_service_specific_info, mParams->sdea_service_specific_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill sdea svc info, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        request.attr_end(data);
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int getCapabilitiesRequest(WifiRequest& request) {
+        int result = 0;
+        NAN_DBG_ENTER();
+
+        result = request.create(GOOGLE_OUI, NAN_SUBCMD_GET_CAPABILITIES);
+        if (result < 0) {
+            ALOGE("%s Failed to create request \n", __func__);
+            return result;
+        }
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        request.attr_end(data);
+
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int start()
+    {
+        int result = 0;
+        WifiRequest request(familyId(), ifaceId());
+        result = createRequest(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("%s: Failed to create setup request; result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("%s: Failed to configure setup; result = %d\n", __func__, result);
+            return result;
+        }
+
+        request.destroy();
+        return WIFI_SUCCESS;
+    }
+
+    virtual bool valid_disc_response_type(int response_type) {
+        bool valid = false;
+        switch(response_type) {
+            case NAN_RESPONSE_PUBLISH:
+            case NAN_RESPONSE_SUBSCRIBE:
+            case NAN_GET_CAPABILITIES:
+            case NAN_RESPONSE_PUBLISH_CANCEL:
+            case NAN_RESPONSE_SUBSCRIBE_CANCEL:
+            case NAN_RESPONSE_TRANSMIT_FOLLOWUP:
+                valid = true;
+                break;
+            default:
+                ALOGE("NanDiscEnginePrmitive:Unknown cmd Response: %d\n", response_type);
+                break;
+        }
+        return valid;
+    }
+
+    int handleResponse(WifiEvent& reply)
+    {
+        nan_hal_resp_t *rsp_vndr_data = NULL;
+        NanResponseMsg rsp_data;
+        if (reply.get_cmd() != NL80211_CMD_VENDOR || reply.get_vendor_data() == NULL) {
+            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+            return NL_SKIP;
+        }
+        rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data();
+        ALOGI("NanDiscEnginePrmitive::handle response\n");
+        memset(&rsp_data, 0, sizeof(NanResponseMsg));
+        rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+        if (!valid_disc_response_type(rsp_data.response_type))
+            return NL_SKIP;
+
+        rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+        ALOGE("Mapped hal status = %d\n", rsp_data.status);
+        if (rsp_vndr_data->nan_reason[0] == '\0') {
+            memcpy(rsp_data.nan_error, NanStatusToString(rsp_data.status),
+                    strlen(NanStatusToString(rsp_data.status)));
+            rsp_data.nan_error[strlen(NanStatusToString(rsp_data.status))] = '\0';
+        }
+        rsp_data.nan_error[NAN_ERROR_STR_LEN - 1] = '\0';
+        ALOGI("\n Received nan_error string %s\n", (u8*)rsp_data.nan_error);
+
+        if (mInstId == 0 &&
+                (rsp_data.response_type == NAN_RESPONSE_PUBLISH ||
+                 rsp_data.response_type == NAN_RESPONSE_SUBSCRIBE)) {
+            ALOGI("Received service instance_id %d\n", rsp_vndr_data->instance_id);
+            mInstId = rsp_vndr_data->instance_id;
+        }
+
+        if (rsp_data.response_type == NAN_RESPONSE_PUBLISH) {
+            rsp_data.body.publish_response.publish_id = mInstId;
+        } else if (rsp_data.response_type == NAN_RESPONSE_SUBSCRIBE) {
+            rsp_data.body.subscribe_response.subscribe_id = mInstId;
+        } else if (rsp_data.response_type == NAN_GET_CAPABILITIES) {
+            memcpy((void *)&rsp_data.body.nan_capabilities, (void *)&rsp_vndr_data->capabilities,
+                    sizeof(rsp_data.body.nan_capabilities));
+        }
+
+        GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(id(), &rsp_data);
+        ALOGI("NanDiscEnginePrmitive:Received response for cmd [%s], ret %d\n",
+                NanRspToString(rsp_data.response_type), rsp_data.status);
+
+        return NL_SKIP;
+    }
+
+    int handleEvent(WifiEvent& event) {
+        int cmd = event.get_vendor_subcmd();
+        u16 attr_type;
+        int result;
+
+        ALOGI("Received NanDiscEnginePrimitive event: %d\n", event.get_cmd());
+        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+
+        switch(cmd) {
+            case NAN_EVENT_PUBLISH_TERMINATED:
+                NanPublishTerminatedInd pub_term_event;
+
+                memset(&pub_term_event, 0, sizeof(NanPublishTerminatedInd));
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+                        pub_term_event.publish_id = it.get_u16();
+                        ALOGI("pub id = %u", pub_term_event.publish_id);
+                    } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+                        pub_term_event.reason = (NanStatusType)it.get_u8();
+                        ALOGI("pub termination status %u", pub_term_event.reason);
+                    } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+                        memcpy(pub_term_event.nan_reason, it.get_data(),
+                                sizeof(pub_term_event.nan_reason));
+                        ALOGI("pub termination reason: %s", pub_term_event.nan_reason);
+                    } else {
+                        ALOGE("Unknown attr: %u\n", attr_type);
+                    }
+                }
+
+                GET_NAN_HANDLE(info)->mHandlers.EventPublishTerminated(&pub_term_event);
+                break;
+
+            case NAN_EVENT_SUBSCRIBE_MATCH:
+                NanMatchInd subscribe_event;
+
+                memset(&subscribe_event, 0, sizeof(NanMatchInd));
+
+                /* By default FW is unable to cache this match */
+                subscribe_event.out_of_resource_flag = true;
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+                        ALOGI("sub id: %u", it.get_u16());
+                        subscribe_event.publish_subscribe_id = it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+                        ALOGI("pub id: %u", it.get_u16());
+                        subscribe_event.requestor_instance_id = it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                        memcpy(subscribe_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+                        ALOGI("Publisher mac: " MACSTR, MAC2STR(subscribe_event.addr));
+                    } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                        ALOGI("svc length %d", it.get_u16());
+                        subscribe_event.service_specific_info_len = it.get_u16();
+                    } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                        memcpy(subscribe_event.service_specific_info, it.get_data(),
+                                subscribe_event.service_specific_info_len);
+                        subscribe_event.service_specific_info
+                            [subscribe_event.service_specific_info_len] = '\0';
+                        ALOGI("service info: %s", subscribe_event.service_specific_info);
+                    } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN) {
+                        ALOGI("sdf match filter length: %d", subscribe_event.sdf_match_filter_len);
+                        subscribe_event.sdf_match_filter_len = it.get_u16();
+                    } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER) {
+                        memcpy(subscribe_event.sdf_match_filter, it.get_data(),
+                                subscribe_event.sdf_match_filter_len);
+                        subscribe_event.sdf_match_filter
+                            [subscribe_event.sdf_match_filter_len] = '\0';
+                        ALOGI("sdf match filter: %s", subscribe_event.sdf_match_filter);
+                    } else if (attr_type == NAN_ATTRIBUTE_CIPHER_SUITE_TYPE) {
+                        ALOGI("Peer Cipher suite type: %u", it.get_u8());
+                        subscribe_event.peer_cipher_type = it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_SCID_LEN) {
+                        ALOGI("scid length %d", it.get_u32());
+                        subscribe_event.scid_len= it.get_u32();
+                    } else if (attr_type == NAN_ATTRIBUTE_SCID) {
+                        memcpy(subscribe_event.scid, it.get_data(),
+                                subscribe_event.scid_len);
+                        subscribe_event.scid
+                            [subscribe_event.scid_len] = '\0';
+                        ALOGI("scid: %s", subscribe_event.scid);
+                    } else if (attr_type == NAN_ATTRIBUTE_RANGING_INDICATION) {
+                        subscribe_event.range_info.ranging_event_type = it.get_u32();
+                        ALOGI("ranging indication %d", it.get_u32());
+                    } else if (attr_type == NAN_ATTRIBUTE_RANGING_RESULT) {
+                        subscribe_event.range_info.range_measurement_mm = it.get_u32();
+                        ALOGI("ranging result %d", it.get_u32());
+                    } else if (attr_type == NAN_ATTRIBUTE_RSSI_PROXIMITY) {
+                        subscribe_event.rssi_value = it.get_u8();
+                        ALOGI("rssi value : %u", it.get_u8());
+                    } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+                        ALOGI("sdea svc length %d", it.get_u16());
+                        subscribe_event.sdea_service_specific_info_len = it.get_u16();
+                    } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
+                        memcpy(subscribe_event.sdea_service_specific_info, it.get_data(),
+                                subscribe_event.sdea_service_specific_info_len);
+                        subscribe_event.sdea_service_specific_info
+                            [subscribe_event.sdea_service_specific_info_len] = '\0';
+                        ALOGI("sdea service info: %s", subscribe_event.sdea_service_specific_info);
+                    } else if (attr_type == NAN_ATTRIBUTE_MATCH_OCCURRED_FLAG) {
+                        ALOGI("match occurred flag: %u", it.get_u8());
+                        subscribe_event.match_occured_flag = it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_OUT_OF_RESOURCE_FLAG) {
+                        ALOGI("Out of resource flag: %u", it.get_u8());
+                        subscribe_event.out_of_resource_flag = it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP) {
+                        ALOGI("Peer config for data path needed: %u", it.get_u8());
+                        subscribe_event.peer_sdea_params.config_nan_data_path = it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE) {
+                        ALOGI("Data Path type: %u", it.get_u8());
+                        subscribe_event.peer_sdea_params.ndp_type = (NdpType)it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_SECURITY) {
+                        ALOGI("Security configuration: %u", it.get_u8());
+                        subscribe_event.peer_sdea_params.security_cfg =
+                            (NanDataPathSecurityCfgStatus)it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT) {
+                        ALOGI("Ranging report state: %u", it.get_u8());
+                        subscribe_event.peer_sdea_params.range_report = (NanRangeReport)it.get_u8();
+                    }
+                }
+
+                GET_NAN_HANDLE(info)->mHandlers.EventMatch(&subscribe_event);
+                break;
+
+            case NAN_EVENT_SUBSCRIBE_UNMATCH:
+                ALOGE("%s: Not applicable yet\n", __func__);
+                break;
+
+            case NAN_EVENT_SUBSCRIBE_TERMINATED:
+                NanSubscribeTerminatedInd sub_term_event;
+                memset(&sub_term_event, 0, sizeof(NanSubscribeTerminatedInd));
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+                        sub_term_event.subscribe_id = it.get_u16();
+                        ALOGI("sub id = %u", sub_term_event.subscribe_id);
+                    } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+                        sub_term_event.reason = (NanStatusType)it.get_u16();
+                        ALOGI("sub termination status %u", sub_term_event.reason);
+                    } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+                        memcpy(sub_term_event.nan_reason, it.get_data(),
+                                sizeof(sub_term_event.nan_reason));
+                        ALOGI("sub termination reason: %s", sub_term_event.nan_reason);
+                    } else {
+                        ALOGI("Unknown attr: %d\n", attr_type);
+                    }
+                }
+
+                GET_NAN_HANDLE(info)->mHandlers.EventSubscribeTerminated(&sub_term_event);
+                break;
+
+            case NAN_EVENT_FOLLOWUP:
+                NanFollowupInd followup_event;
+                memset(&followup_event, 0, sizeof(NanFollowupInd));
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                        memcpy(followup_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+                    } else if (attr_type == NAN_ATTRIBUTE_PEER_ID) {
+                        followup_event.publish_subscribe_id = it.get_u16();
+                    } else if (attr_type == NAN_ATTRIBUTE_INST_ID) {
+                        followup_event.requestor_instance_id = it.get_u32();
+                    } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                        followup_event.service_specific_info_len = it.get_u16();
+                    } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                        memcpy(followup_event.service_specific_info, it.get_data(),
+                                followup_event.service_specific_info_len);
+                    } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
+                        memcpy(followup_event.sdea_service_specific_info, it.get_data(),
+                                followup_event.sdea_service_specific_info_len);
+                    }
+                }
+                counters.transmit_recv++;
+                GET_NAN_HANDLE(info)->mHandlers.EventFollowup(&followup_event);
+                break;
+
+            case NAN_EVENT_TRANSMIT_FOLLOWUP_IND:
+                NanTransmitFollowupInd followup_ind;
+                counters.transmit_txs++;
+                memset(&followup_ind, 0, sizeof(NanTransmitFollowupInd));
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+                    if (attr_type == NAN_ATTRIBUTE_TRANSAC_ID) {
+                        followup_ind.id = it.get_u16();
+                    } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+                        followup_ind.reason = (NanStatusType)it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+                        memcpy(followup_ind.nan_reason, it.get_data(),
+                                sizeof(followup_ind.nan_reason));
+                        ALOGI("nan transmit followup ind: reason: %s", followup_ind.nan_reason);
+                    }
+                }
+                GET_NAN_HANDLE(info)->mHandlers.EventTransmitFollowup(&followup_ind);
+                break;
+#ifdef NOT_YET
+            case NAN_EVENT_PUBLISH_REPLIED_IND:
+                NanPublishRepliedInd pub_reply_event;
+                memset(&pub_reply_event, 0, sizeof(pub_reply_event));
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+                        ALOGI("sub id: %u", it.get_u16());
+                        pub_reply_event.requestor_instance_id = it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                        memcpy(pub_reply_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+                        ALOGI("Subscriber mac: " MACSTR, MAC2STR(pub_reply_event.addr));
+                    } else if (attr_type == NAN_ATTRIBUTE_RSSI_PROXIMITY) {
+                        pub_reply_event.rssi_value = it.get_u8();
+                        ALOGI("Received rssi value : %u", it.get_u8());
+                    }
+                }
+                GET_NAN_HANDLE(info)->mHandlers.EventPublishReplied(&pub_reply_event);
+                break;
+#endif /* NOT_YET */
+        } // end-of-switch-case
+        return NL_SKIP;
+    }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+class NanDataPathPrimitive : public WifiCommand
+{
+    NanRequest reqContext;
+    u32 mNdpId;
+    NanRequestType mType;
+    u8 count;
+
+    public:
+    NanDataPathPrimitive(wifi_interface_handle iface, int id,
+            NanRequest params, NanRequestType cmdType)
+        : WifiCommand("NanCommand", iface, id), reqContext(params), mType(cmdType)
+    {
+        mNdpId = 0;
+        count = 0;
+    }
+    ~NanDataPathPrimitive() {
+        ALOGE("NanDataPathPrimitive destroyed\n");
+    }
+    u8 mSvcHash[NAN_SVC_HASH_SIZE];
+    u8 mPubNmi[NAN_MAC_ADDR_LEN];
+
+    void setType(NanRequestType type ) {
+        mType = type;
+    }
+
+    int getNdpId() {
+        return mNdpId;
+    }
+
+    int createRequest(WifiRequest& request)
+    {
+        ALOGI("NAN CMD: %s\n", NanCmdToString(mType));
+        if (mType == NAN_DATA_PATH_IFACE_CREATE) {
+            return createDataPathIfaceRequest(request, (char *)reqContext);
+        } else if (mType == NAN_DATA_PATH_IFACE_DELETE) {
+            return deleteDataPathIfaceRequest(request, (char *)reqContext);
+        } else if (mType == NAN_DATA_PATH_INIT_REQUEST) {
+            return createDataPathInitRequest(request,
+                    (NanDataPathInitiatorRequest *)reqContext);
+        } else if (mType == NAN_DATA_PATH_IND_RESPONSE) {
+            return createDataPathIndResponse(request,
+                    (NanDataPathIndicationResponse *)reqContext);
+        } else if (mType == NAN_DATA_PATH_END) {
+            return createDataPathEndRequest(request,
+                    (NanDataPathEndRequest *)reqContext);
+        } else if (mType == NAN_DATA_PATH_SEC_INFO) {
+            return createDataPathSecInfoRequest(request,
+                    (NanDataPathSecInfoRequest *)reqContext);
+        } else {
+            ALOGE("%s: Unknown NDP request: %d\n", __func__, mType);
+        }
+
+        return WIFI_SUCCESS;
+    }
+
+    int createDataPathIfaceRequest(WifiRequest& request, char *iface_name)
+    {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_IFACE_CREATE);
+        if (result < 0) {
+            ALOGE("%s Failed to create request\n", __func__);
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+        result = request.put_string(NAN_ATTRIBUTE_IFACE, (char *)iface_name);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill iface, result = %d\n", __func__, result);
+            return result;
+        }
+
+        request.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+
+    int deleteDataPathIfaceRequest(WifiRequest& request, char *iface_name)
+    {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_IFACE_DELETE);
+        if (result < 0) {
+            ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        result = request.put_string(NAN_ATTRIBUTE_IFACE, (char *)iface_name);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill iface, result = %d\n", __func__, result);
+            return result;
+        }
+
+        request.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+
+    int createDataPathSecInfoRequest(WifiRequest& request, NanDataPathSecInfoRequest *mParams)
+    {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_SEC_INFO);
+        if (result < 0) {
+            ALOGE("%s Failed to create request\n", __func__);
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        result = request.put_u8(NAN_ATTRIBUTE_PUBLISH_ID, mParams->requestor_instance_id);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill instance id = %d, result = %d\n",
+                    __func__, mParams->requestor_instance_id, result);
+            return result;
+        }
+
+        result = request.put_addr(NAN_ATTRIBUTE_MAC_ADDR, mParams->peer_disc_mac_addr);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill mac addr, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u32(NAN_ATTRIBUTE_NDP_ID,  mParams->ndp_instance_id);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ndp_instance_id = %d, result = %d\n",
+                    __func__, mParams->ndp_instance_id, result);
+            return result;
+        }
+
+        request.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+
+    int createDataPathInitRequest(WifiRequest& request, NanDataPathInitiatorRequest *mParams)
+    {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_REQUEST);
+        u8 pmk_hex[NAN_PMK_INFO_LEN];
+        if (result < 0) {
+            ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+            return result;
+        }
+
+        mNdpId = mParams->requestor_instance_id;
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        result = request.put_u32(NAN_ATTRIBUTE_PUBLISH_ID, mParams->requestor_instance_id);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill pub id = %d, result = %d\n",
+                    __func__, mParams->requestor_instance_id, result);
+            return result;
+        }
+
+        result = request.put_u32(NAN_ATTRIBUTE_CHANNEL, (u32)mParams->channel);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill channel = %d, result = %d\n",
+                    __func__, mParams->channel, result);
+            return result;
+        }
+
+        result = request.put_addr(NAN_ATTRIBUTE_MAC_ADDR, mParams->peer_disc_mac_addr);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill mac addr, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_string(NAN_ATTRIBUTE_IFACE, mParams->ndp_iface);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ndp_iface, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SECURITY,
+                (NanDataPathSecurityCfgStatus)mParams->ndp_cfg.security_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill security, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_QOS,
+                (NanDataPathQosCfg) mParams->ndp_cfg.qos_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill QoS, result = %d\n", __func__, result);
+            return result;
+        }
+
+        if (mParams->app_info.ndp_app_info_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+                    mParams->app_info.ndp_app_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc info len = %d, result = %d\n",
+                        __func__, mParams->app_info.ndp_app_info_len, result);
+                return result;
+            }
+
+            result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+                    (void *)mParams->app_info.ndp_app_info, mParams->app_info.ndp_app_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc info, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE,
+                mParams->cipher_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_CIPHER_SUITE_TYPE, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_KEY_TYPE,
+                mParams->key_info.key_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_KEY_TYPE, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+
+        if (mParams->service_name_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_SERVICE_NAME_LEN, mParams->service_name_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc name len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->service_name, mParams->service_name_len);
+            result = request.put(NAN_ATTRIBUTE_SERVICE_NAME, (void *)mParams->service_name,
+                    mParams->service_name_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc name, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) {
+            if (mParams->key_info.body.pmk_info.pmk_len) {
+                result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN,
+                        mParams->key_info.body.pmk_info.pmk_len);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill pmk len, result = %d\n", __func__, result);
+                    return result;
+                }
+                result = request.put(NAN_ATTRIBUTE_KEY_DATA,
+                        (void *)mParams->key_info.body.pmk_info.pmk,
+                        mParams->key_info.body.pmk_info.pmk_len);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill pmk, result = %d\n", __func__, result);
+                    return result;
+                }
+            }
+        }
+
+        if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+            if (mParams->key_info.body.passphrase_info.passphrase_len < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+                    mParams->key_info.body.passphrase_info.passphrase_len > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+                ALOGE("passphrase must be between %d and %d characters long\n",
+                        NAN_SECURITY_MIN_PASSPHRASE_LEN,
+                        NAN_SECURITY_MAX_PASSPHRASE_LEN);
+                return NAN_STATUS_INVALID_PARAM;
+            } else {
+                memset(pmk_hex, 0, NAN_PMK_INFO_LEN);
+                result = passphrase_to_pmk(mParams->peer_disc_mac_addr, mParams->cipher_type,
+                        mParams->service_name, &mParams->key_info, pmk_hex);
+                if (result < 0) {
+                    ALOGE("%s: Failed to convert passphrase to key data, result = %d\n", __func__, result);
+                    return result;
+                }
+                result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN, NAN_PMK_INFO_LEN);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill passphrase len, result = %d\n", __func__, result);
+                    return result;
+                }
+                result = request.put(NAN_ATTRIBUTE_KEY_DATA, pmk_hex, NAN_PMK_INFO_LEN);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill passphrase, result = %d\n", __func__, result);
+                    return result;
+                }
+                prhex("PMK", pmk_hex, NAN_PMK_INFO_LEN);
+            }
+        }
+
+        request.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+
+    int createDataPathIndResponse(WifiRequest& request,
+            NanDataPathIndicationResponse *mParams)
+    {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_RESPONSE);
+        u8 pmk_hex[NAN_PMK_INFO_LEN];
+        if (result < 0) {
+            ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        result = request.put_u32(NAN_ATTRIBUTE_NDP_ID,  mParams->ndp_instance_id);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ndp_instance_id = %d, result = %d\n",
+                    __func__, mParams->ndp_instance_id, result);
+            return result;
+        }
+
+        result = request.put_string(NAN_ATTRIBUTE_IFACE, mParams->ndp_iface);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill ndp_iface, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_SECURITY,
+                (NanDataPathSecurityCfgStatus)mParams->ndp_cfg.security_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill security_cfg, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_QOS,
+                (NanDataPathQosCfg)mParams->ndp_cfg.qos_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill qos_cfg, result = %d\n", __func__, result);
+            return result;
+        }
+
+        if (mParams->app_info.ndp_app_info_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN,
+                    mParams->app_info.ndp_app_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc info len = %d, result = %d\n",
+                        __func__, mParams->app_info.ndp_app_info_len, result);
+                return result;
+            }
+
+            result = request.put(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO,
+                    (void *)mParams->app_info.ndp_app_info, mParams->app_info.ndp_app_info_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc info, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_RSP_CODE, mParams->rsp_code);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill resp code = %d, result = %d\n",
+                    __func__, mParams->rsp_code, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_CIPHER_SUITE_TYPE,
+                mParams->cipher_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill cipher_type, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_KEY_TYPE,
+                mParams->key_info.key_type);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill key type, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        if (mParams->service_name_len) {
+            result = request.put_u16(NAN_ATTRIBUTE_SERVICE_NAME_LEN, mParams->service_name_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc name len, result = %d\n", __func__, result);
+                return result;
+            }
+
+            prhex(NULL, mParams->service_name, mParams->service_name_len);
+            result = request.put(NAN_ATTRIBUTE_SERVICE_NAME, (void *)mParams->service_name,
+                    mParams->service_name_len);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill svc name, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PMK) {
+            if (mParams->key_info.body.pmk_info.pmk_len) {
+                result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN,
+                        mParams->key_info.body.pmk_info.pmk_len);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill pmk len, result = %d\n", __func__, result);
+                    return result;
+                }
+                result = request.put(NAN_ATTRIBUTE_KEY_DATA,
+                        (void *)mParams->key_info.body.pmk_info.pmk,
+                        mParams->key_info.body.pmk_info.pmk_len);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill pmk, result = %d\n", __func__, result);
+                    return result;
+                }
+            }
+        }
+
+        if (mParams->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+            if (mParams->key_info.body.passphrase_info.passphrase_len < NAN_SECURITY_MIN_PASSPHRASE_LEN ||
+                    mParams->key_info.body.passphrase_info.passphrase_len > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+                ALOGE("passphrase must be between %d and %d characters long\n",
+                        NAN_SECURITY_MIN_PASSPHRASE_LEN,
+                        NAN_SECURITY_MAX_PASSPHRASE_LEN);
+                return NAN_STATUS_INVALID_PARAM;
+            } else {
+                memset(pmk_hex, 0, NAN_PMK_INFO_LEN);
+                result = passphrase_to_pmk(mPubNmi, mParams->cipher_type,
+                        mParams->service_name, &mParams->key_info, pmk_hex);
+                if (result < 0) {
+                    ALOGE("%s: Failed to convert passphrase to key data, result = %d\n", __func__, result);
+                    return result;
+                }
+                result = request.put_u32(NAN_ATTRIBUTE_KEY_LEN, NAN_PMK_INFO_LEN);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill passphrase len, result = %d\n", __func__, result);
+                    return result;
+                }
+                result = request.put(NAN_ATTRIBUTE_KEY_DATA, pmk_hex, NAN_PMK_INFO_LEN);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill passphrase, result = %d\n", __func__, result);
+                    return result;
+                }
+            }
+        }
+
+        request.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+
+    int createDataPathEndRequest(WifiRequest& request, NanDataPathEndRequest *mParams)
+    {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DATA_PATH_END);
+        if (result < 0) {
+            ALOGE("%s: Failed to create request, result = %d\n", __func__, result);
+            return result;
+        }
+
+        count = mParams->num_ndp_instances;
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        result = request.put_u8(NAN_ATTRIBUTE_INST_COUNT, mParams->num_ndp_instances);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill num_ndp_instances = %d, result = %d\n",
+                    __func__, mParams->num_ndp_instances, result);
+            return result;
+        }
+
+        while (count) {
+            result = request.put_u32(NAN_ATTRIBUTE_NDP_ID, mParams->ndp_instance_id[count-1]);
+            if (result < 0) {
+                ALOGE("%s: Failed to fill ndp id = %d, result = %d\n",
+                        __func__, mParams->ndp_instance_id[count-1], result);
+                return result;
+            }
+            ALOGE("%s:NDP ID = %d\n", __func__, mParams->ndp_instance_id[count-1]);
+            count -= 1;
+        }
+
+        request.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+
+    int open()
+    {
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("%s: failed to create setup request; result = %d", __func__, result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("%s: failed to configure setup; result = %d", __func__, result);
+            return result;
+        }
+
+        request.destroy();
+        return WIFI_SUCCESS;
+    }
+
+    virtual bool valid_dp_response_type(int response_type) {
+        bool valid = false;
+        switch(response_type) {
+            case NAN_DP_INTERFACE_CREATE:
+            case NAN_DP_INTERFACE_DELETE:
+            case NAN_DP_INITIATOR_RESPONSE:
+            case NAN_DP_RESPONDER_RESPONSE:
+            case NAN_DP_END: 
+                valid = true;
+                break;
+            default: 
+                ALOGE("NanDataPathPrmitive::Unknown cmd Response: %d\n", response_type);
+                break;
+        }
+        return valid;
+    }
+
+    int handleResponse(WifiEvent& reply)
+    {
+        nan_hal_resp_t *rsp_vndr_data = NULL;
+
+        if (reply.get_cmd() != NL80211_CMD_VENDOR || reply.get_vendor_data() == NULL) {
+            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+            return NL_SKIP;
+        }
+
+        rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data();
+        ALOGI("NanDataPathPrmitive::handle response\n");
+        int32_t result = rsp_vndr_data->value;
+        NanResponseMsg rsp_data;
+
+        memset(&rsp_data, 0, sizeof(NanResponseMsg));
+        rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+
+        if ((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd == NAN_SUBCMD_DATA_PATH_SEC_INFO) {
+            /* Follow through */
+        } else if (!valid_dp_response_type(rsp_data.response_type)) {
+            return NL_SKIP;
+        }
+        rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+        ALOGE("Mapped hal status = %d\n", rsp_data.status);
+
+        if (rsp_vndr_data->nan_reason[0] == '\0') {
+            memcpy(rsp_data.nan_error, NanStatusToString(rsp_data.status),
+                    strlen(NanStatusToString(rsp_data.status)));
+            rsp_data.nan_error[strlen(NanStatusToString(rsp_data.status))] = '\0';
+        }
+        rsp_data.nan_error[NAN_ERROR_STR_LEN - 1] = '\0';
+        ALOGI("\n Received nan_error string %s\n", (u8*)rsp_data.nan_error);
+
+        if (rsp_data.response_type == NAN_DP_INITIATOR_RESPONSE) {
+            ALOGI("received ndp instance_id %d and ret = %d\n", rsp_vndr_data->ndp_instance_id, result);
+            rsp_data.body.data_request_response.ndp_instance_id = rsp_vndr_data->ndp_instance_id;
+            mNdpId = rsp_vndr_data->ndp_instance_id;
+        } else if ((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd == NAN_SUBCMD_DATA_PATH_SEC_INFO) {
+            memcpy(mPubNmi, rsp_vndr_data->pub_nmi, NAN_MAC_ADDR_LEN);
+            memcpy(mSvcHash, rsp_vndr_data->svc_hash, NAN_SVC_HASH_SIZE);
+            return NL_SKIP;
+        }
+
+        ALOGI("NanDataPathPrmitive:Received response for cmd [%s], ret %d\n",
+                NanRspToString(rsp_data.response_type), rsp_data.status);
+        GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(id(), &rsp_data);
+        return NL_SKIP;
+    }
+
+    int handleEvent(WifiEvent& event)
+    {
+        int cmd = event.get_vendor_subcmd();
+        u16 attr_type;
+
+        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+
+        switch(cmd) {
+            case NAN_EVENT_DATA_REQUEST: {
+                NanDataPathRequestInd ndp_request_event;
+                memset(&ndp_request_event, 0, sizeof(NanDataPathRequestInd));
+                u16 ndp_ind_app_info_len = 0;
+                counters.dp_req_evt++;
+                ALOGI("Received NAN_EVENT_DATA_REQUEST_INDICATION\n");
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+                        ALOGI("publish_id: %u", it.get_u16());
+                        ndp_request_event.service_instance_id = it.get_u16();
+
+                    } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                        memcpy(ndp_request_event.peer_disc_mac_addr,
+                                it.get_data(), NAN_MAC_ADDR_LEN);
+                        ALOGI("Discovery MAC addr of the peer/initiator: " MACSTR "\n",
+                                MAC2STR(ndp_request_event.peer_disc_mac_addr));
+
+                    } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+                        ALOGI("ndp id: %u", it.get_u32());
+                        ndp_request_event.ndp_instance_id = it.get_u32();
+
+                    } else if (attr_type == NAN_ATTRIBUTE_SECURITY) {
+                        ALOGI("security: %u",
+                                (NanDataPathSecurityCfgStatus)it.get_u8());
+                        ndp_request_event.ndp_cfg.security_cfg =
+                            (NanDataPathSecurityCfgStatus)it.get_u8();
+
+                    } else if (attr_type == NAN_ATTRIBUTE_QOS) {
+                        ALOGI("QoS: %u", (NanDataPathQosCfg)it.get_u8());
+                        ndp_request_event.ndp_cfg.qos_cfg = (NanDataPathQosCfg)it.get_u8();
+
+                    } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                        ndp_request_event.app_info.ndp_app_info_len = it.get_u16();
+                        ndp_ind_app_info_len = ndp_request_event.app_info.ndp_app_info_len;
+
+                    } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                        memcpy(ndp_request_event.app_info.ndp_app_info, it.get_data(),
+                                ndp_ind_app_info_len);
+                        ndp_request_event.app_info.ndp_app_info
+                            [ndp_ind_app_info_len] = '\0';
+                        ALOGI("service info: %s", ndp_request_event.app_info.ndp_app_info);
+
+                    }
+                }
+
+                GET_NAN_HANDLE(info)->mHandlers.EventDataRequest(&ndp_request_event);
+                break;
+            }
+            case NAN_EVENT_DATA_CONFIRMATION: {
+                NanDataPathConfirmInd ndp_create_confirmation_event;
+                memset(&ndp_create_confirmation_event, 0, sizeof(NanDataPathConfirmInd));
+                u16 ndp_conf_app_info_len = 0;
+                counters.dp_confirm_evt++;
+                ALOGI("Received NAN_EVENT_DATA_CONFIRMATION\n");
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+                        ALOGI("ndp id: %u", it.get_u32());
+                        ndp_create_confirmation_event.ndp_instance_id = it.get_u32();
+
+                    } else if (attr_type == NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR) {
+                        memcpy(ndp_create_confirmation_event.peer_ndi_mac_addr, it.get_data(),
+                                NAN_MAC_ADDR_LEN);
+                        ALOGI("NDI mac address of the peer: " MACSTR "\n",
+                                MAC2STR(ndp_create_confirmation_event.peer_ndi_mac_addr));
+
+                    } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                        ALOGI("service info len: %d", it.get_u16());
+                        ndp_create_confirmation_event.app_info.ndp_app_info_len = it.get_u16();
+                        ndp_conf_app_info_len = ndp_create_confirmation_event.app_info.ndp_app_info_len;
+                    } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                        memcpy(ndp_create_confirmation_event.app_info.ndp_app_info,
+                                it.get_data(), ndp_conf_app_info_len);
+                        ndp_create_confirmation_event.app_info.ndp_app_info[ndp_conf_app_info_len]
+                            = '\0';
+                        ALOGI("service info: %s",
+                                ndp_create_confirmation_event.app_info.ndp_app_info);
+
+                    } else if (attr_type == NAN_ATTRIBUTE_RSP_CODE) {
+                        ALOGI("response code: %u", (NanDataPathResponseCode)it.get_u8());
+                        ndp_create_confirmation_event.rsp_code =
+                            (NanDataPathResponseCode)it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+                        ALOGI("reason code %u", (NanDataPathResponseCode)it.get_u8());
+                        ndp_create_confirmation_event.rsp_code =
+                            (NanDataPathResponseCode)it.get_u8();
+                    }
+                }
+
+                GET_NAN_HANDLE(info)->mHandlers.EventDataConfirm(&ndp_create_confirmation_event);
+                break;
+            }
+            case NAN_EVENT_DATA_END: {
+                NanDataPathEndInd ndp_end_event;
+                memset(&ndp_end_event, 0, sizeof(NanDataPathEndInd));
+                u16 attr_type;
+                ALOGI("Received NAN_EVENT_DATA_END\n");
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_INST_COUNT) {
+                        ALOGI("ndp count: %u\n", it.get_u8());
+                        ndp_end_event.num_ndp_instances = it.get_u8();
+                        count = it.get_u8();
+                    } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+                        while (count) {
+                            ndp_end_event.ndp_instance_id[count-1] = it.get_u32();
+                            ALOGI("NDP Id from the Event = %u\n", ndp_end_event.ndp_instance_id[count-1]);
+                            count -= 1;
+                        }
+                    } else {
+                        ALOGI("Unknown attr_type: %s\n", NanAttrToString(attr_type));
+                    }
+                }
+
+                GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(&ndp_end_event);
+                break;
+            }
+        } // end-of-switch
+        return NL_SKIP;
+    }
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+class NanMacControl : public WifiCommand
+{
+    NanRequest mParams;
+    transaction_id mId = NAN_MAC_INVALID_TRANSID;
+    wifi_interface_handle mIface;
+    NanRequestType mType;
+    u32 mVersion;
+
+    public:
+    NanMacControl(wifi_interface_handle iface, int id,
+            NanRequest params, NanRequestType cmdType)
+        : WifiCommand("NanCommand", iface, id), mParams(params), mType(cmdType)
+    {
+        mVersion = 0;
+        setIface(iface);
+        setId(id);
+    }
+    ~NanMacControl() {
+        ALOGE("NanMacControl destroyed\n");
+    }
+
+    void setIface(wifi_interface_handle iface ) {
+        mIface = iface;
+    }
+
+    void setId(transaction_id id) {
+        if (id != NAN_MAC_INVALID_TRANSID) {
+            mId = id;
+        }
+    }
+
+    transaction_id getId() {
+        return mId;
+    }
+
+    void setType(NanRequestType type) {
+        mType = type;
+    }
+    u32 getVersion() {
+        return mVersion;
+    }
+
+    void setMsg(NanRequest params) {
+        mParams = params;
+    }
+
+    int createRequest(WifiRequest& request) {
+        ALOGI("NAN CMD: %s\n", NanCmdToString(mType));
+        if (mType == NAN_REQUEST_ENABLE) {
+            return createEnableRequest(request, (NanEnableRequest *)mParams);
+        } else if (mType == NAN_REQUEST_DISABLE) {
+            return createDisableRequest(request);
+        } else if (mType == NAN_REQUEST_CONFIG) {
+            return createConfigRequest(request, (NanConfigRequest*)mParams);
+        } else if (mType == NAN_REQUEST_STATS) {
+            /* TODO: Not yet implemented */
+        } else if (mType == NAN_REQUEST_TCA) {
+            /* TODO: Not yet implemented */
+        } else if (mType == NAN_VERSION_INFO) {
+            return createVersionRequest(request);
+#ifdef NAN_CLUSTER_MERGE
+        } else if (mType == NAN_REQUEST_ENABLE_MERGE) {
+            return createEnableMergeRequest(request, (NanEnableMergeRequest *)mParams);
+#endif /* NAN_CLUSTER_MERGE */
+        } else {
+            ALOGE("Unknown Nan request\n");
+        }
+
+        return WIFI_SUCCESS;
+    }
+
+    int createVersionRequest(WifiRequest& request) {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_VERSION_INFO);
+        if (result < 0) {
+            ALOGE("%s: Fail to create request\n", __func__);
+            return result;
+        }
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+        request.attr_end(data);
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int createEnableRequest(WifiRequest& request, NanEnableRequest *mParams) {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_ENABLE);
+        s8 rssi;
+        if (result < 0) {
+            ALOGE("%s: Fail to create request\n", __func__);
+            return result;
+        }
+
+        NAN_DBG_ENTER();
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        if (mParams->config_2dot4g_support) {
+            result = request.put_u8(NAN_ATTRIBUTE_2G_SUPPORT, mParams->support_2dot4g_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 2g support, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_support_5g) {
+            result = request.put_u8(NAN_ATTRIBUTE_5G_SUPPORT, mParams->support_5g_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g support, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        result = request.put_u16(NAN_ATTRIBUTE_CLUSTER_LOW, mParams->cluster_low);
+        if (result < 0) {
+            ALOGE("%s: Failing in cluster low, result = %d\n", __func__, result);
+            return result;
+        }
+
+        result = request.put_u16(NAN_ATTRIBUTE_CLUSTER_HIGH, mParams->cluster_high);
+        if (result < 0) {
+            ALOGE("%s: Failing in cluster high, result = %d\n", __func__, result);
+            return result;
+        }
+
+        if (mParams->config_sid_beacon) {
+            result = request.put_u8(NAN_ATTRIBUTE_SID_BEACON, mParams->sid_beacon_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in sid beacon, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_subscribe_sid_beacon) {
+            result = request.put_u8(NAN_ATTRIBUTE_SUB_SID_BEACON, mParams->subscribe_sid_beacon_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in sub sid beacon, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_2dot4g_beacons) {
+            result = request.put_u8(NAN_ATTRIBUTE_SYNC_DISC_2G_BEACON, mParams->beacon_2dot4g_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in beacon_2dot4g_val, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_5g_beacons) {
+            result = request.put_u8(NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON, mParams->beacon_5g_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g beacon, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_2dot4g_sdf) {
+            result = request.put_u8(NAN_ATTRIBUTE_SDF_2G_SUPPORT, mParams->sdf_2dot4g_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 2dot4g sdf, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_5g_sdf) {
+            result = request.put_u8(NAN_ATTRIBUTE_SDF_5G_SUPPORT, mParams->sdf_5g_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g sdf, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_2dot4g_rssi_close) {
+            if (ISGREATER(mParams->rssi_close_2dot4g_val, NAN_MAX_RSSI)) {
+                ALOGI("%s: Invalid rssi param \n", __func__);
+                return WIFI_ERROR_INVALID_ARGS;
+            }
+            rssi = -mParams->rssi_close_2dot4g_val;
+            result = request.put_s8(NAN_ATTRIBUTE_RSSI_CLOSE, rssi);
+            if (result < 0) {
+                ALOGE("%s: Failing in 2g rssi close, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_2dot4g_rssi_middle) {
+            if (ISGREATER(mParams->rssi_middle_2dot4g_val, NAN_MAX_RSSI)) {
+                ALOGI("%s: Invalid rssi param \n", __func__);
+                return WIFI_ERROR_INVALID_ARGS;
+            }
+            rssi = -mParams->rssi_middle_2dot4g_val;
+            result = request.put_s8(NAN_ATTRIBUTE_RSSI_MIDDLE, rssi);
+            if (result < 0) {
+                ALOGE("%s: Failing in 2g rssi middle, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_2dot4g_rssi_proximity) {
+            if (ISGREATER(mParams->rssi_proximity_2dot4g_val, NAN_MAX_RSSI)) {
+                ALOGI("%s: Invalid rssi param \n", __func__);
+                return WIFI_ERROR_INVALID_ARGS;
+            }
+            rssi = -mParams->rssi_proximity_2dot4g_val;
+            result = request.put_s8(NAN_ATTRIBUTE_RSSI_PROXIMITY, rssi);
+            if (result < 0) {
+                ALOGE("%s: Failing in 2g rssi proximity, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_5g_rssi_close) {
+            if (ISGREATER(mParams->rssi_close_5g_val, NAN_MAX_RSSI)) {
+                ALOGI("%s: Invalid rssi param \n", __func__);
+                return WIFI_ERROR_INVALID_ARGS;
+            }
+            rssi = -mParams->rssi_close_5g_val;
+            result = request.put_s8(NAN_ATTRIBUTE_RSSI_CLOSE_5G, rssi);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g rssi close, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_5g_rssi_middle) {
+            if (ISGREATER(mParams->rssi_middle_5g_val, NAN_MAX_RSSI)) {
+                ALOGI("%s: Invalid rssi param \n", __func__);
+                return WIFI_ERROR_INVALID_ARGS;
+            }
+            rssi = -mParams->rssi_middle_5g_val;
+            result = request.put_s8(NAN_ATTRIBUTE_RSSI_MIDDLE_5G, rssi);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g rssi middle, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_5g_rssi_close_proximity) {
+            if (ISGREATER(mParams->rssi_close_proximity_5g_val, NAN_MAX_RSSI)) {
+                ALOGI("%s: Invalid rssi param \n", __func__);
+                return WIFI_ERROR_INVALID_ARGS;
+            }
+            rssi = -mParams->rssi_close_proximity_5g_val;
+            result = request.put_s8(NAN_ATTRIBUTE_RSSI_PROXIMITY_5G, rssi);
+            if (result < 0) {
+                ALOGE("%s: Failing in rssi_close_proximity_5g_val, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_cluster_attribute_val) {
+            result = request.put_u8(NAN_ATTRIBUTE_CONF_CLUSTER_VAL, mParams->config_cluster_attribute_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in config_cluster_attribute_val, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_hop_count_limit) {
+            result = request.put_u8(NAN_ATTRIBUTE_HOP_COUNT_LIMIT,
+                    mParams->hop_count_limit_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in hop cnt limit, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_oui) {
+            ALOGI("%s: oui = 0x%04x\n", __func__, mParams->oui_val);
+            result = request.put_u32(NAN_ATTRIBUTE_OUI, mParams->oui_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in oui, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_MASTER_PREF, mParams->master_pref);
+        if (result < 0) {
+            ALOGE("%s: Failing in master pref, result = %d\n", __func__, result);
+            return result;
+        }
+        if (mParams->config_random_factor_force) {
+            result = request.put_u8(NAN_ATTRIBUTE_RANDOM_FACTOR, mParams->random_factor_force_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in random factor, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_24g_channel) {
+            result = request.put_u32(NAN_ATTRIBUTE_24G_CHANNEL, mParams->channel_24g_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 2.4g channel, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_5g_channel) {
+            result = request.put_u32(NAN_ATTRIBUTE_5G_CHANNEL, mParams->channel_5g_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g channel, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_intf_addr) {
+            result = request.put_addr(NAN_ATTRIBUTE_IF_ADDR, mParams->intf_addr_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in intf addr val, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_dw.config_2dot4g_dw_band) {
+            result = request.put_u32(NAN_ATTRIBUTE_2G_AWAKE_DW, mParams->config_dw.dw_2dot4g_interval_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 2dot4g awake dw, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_dw.config_5g_dw_band) {
+            result = request.put_u32(NAN_ATTRIBUTE_5G_AWAKE_DW, mParams->config_dw.dw_5g_interval_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g awake dw, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (ISGREATER(mParams->discovery_indication_cfg, NAN_DISC_IND_MAX)) {
+            ALOGE("%s:Invalid disc_ind_cfg value.\n", __FUNCTION__);
+            return WIFI_ERROR_INVALID_ARGS;
+        }
+
+        result = request.put_u8(NAN_ATTRIBUTE_DISC_IND_CFG,
+                mParams->discovery_indication_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_DISC_IND_CFG, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+
+        if (mParams->config_rssi_window_size) {
+            result = request.put_u8(NAN_ATTRIBUTE_RSSI_WINDOW_SIZE,
+                    mParams->rssi_window_size_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in rssi_window_size_val, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_scan_params) {
+            result = request.put_u8(NAN_ATTRIBUTE_DWELL_TIME,
+                    mParams->scan_params_val.dwell_time[0]);
+            if (result < 0) {
+                ALOGE("%s: Failing in dwell time, result = %d\n", __func__, result);
+                return result;
+            }
+            result = request.put_u8(NAN_ATTRIBUTE_DWELL_TIME_5G,
+                    mParams->scan_params_val.dwell_time[1]);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g dwell time, result = %d\n", __func__, result);
+                return result;
+            }
+            result = request.put_u16(NAN_ATTRIBUTE_SCAN_PERIOD,
+                    mParams->scan_params_val.scan_period[0]);
+            if (result < 0) {
+                ALOGE("%s: Failing in scan_period, result = %d\n", __func__, result);
+                return result;
+            }
+            result = request.put_u16(NAN_ATTRIBUTE_SCAN_PERIOD_5G,
+                    mParams->scan_params_val.scan_period[1]);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g scan_period, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_disc_mac_addr_randomization) {
+            result = request.put_u32(NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL,
+                    mParams->disc_mac_addr_rand_interval_sec);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill rand mac address interval, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_discovery_beacon_int) {
+            result = request.put_u32(NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL,
+                    mParams->discovery_beacon_interval);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill disc beacon interval, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_nss) {
+            result = request.put_u32(NAN_ATTRIBUTE_NSS, mParams->nss);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill nss, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_enable_ranging) {
+            result = request.put_u32(NAN_ATTRIBUTE_ENABLE_RANGING, mParams->enable_ranging);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill enable ranging value, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_dw_early_termination) {
+            result = request.put_u32(NAN_ATTRIBUTE_DW_EARLY_TERM, mParams->enable_dw_termination);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill enable dw termination value, result = %d\n",
+                        __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_ndpe_attr) {
+            result = request.put_u32(NAN_ATTRIBUTE_CMD_USE_NDPE,
+                    mParams->use_ndpe_attr);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill use_ndpe, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        request.attr_end(data);
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int createDisableRequest(WifiRequest& request) {
+        NAN_DBG_ENTER();
+
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_DISABLE);
+        if (result < 0) {
+            ALOGE("%s: Fail to create request, result = %d\n", __func__, result);
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        request.attr_end(data);
+
+        NAN_DBG_EXIT();
+        return result;
+    }
+
+#ifdef NAN_CLUSTER_MERGE
+    int createEnableMergeRequest(WifiRequest& request,
+            NanEnableMergeRequest *mParams) {
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_ENABLE_MERGE);
+        if (result < 0) {
+            ALOGE("%s: Fail to create request\n", __func__);
+            return result;
+        }
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+        result = request.put_u8(NAN_ATTRIBUTE_ENABLE_MERGE, mParams->enable);
+        if (result < 0) {
+            ALOGE("%s: Failing in enable merge, result = %d\n", __func__, result);
+            return result;
+        }
+        request.attr_end(data);
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+#endif /* NAN_CLUSTER_MERGE */
+
+    int createConfigRequest(WifiRequest& request, NanConfigRequest *mParams) {
+
+        int result = request.create(GOOGLE_OUI, NAN_SUBCMD_CONFIG);
+        s8 rssi;
+        if (result < 0) {
+            ALOGE("%s: Fail to create config request\n", __func__);
+            return result;
+        }
+
+        NAN_DBG_ENTER();
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        if (mParams->config_sid_beacon) {
+            result = request.put_u8(NAN_ATTRIBUTE_SID_BEACON, mParams->sid_beacon);
+            if (result < 0) {
+                ALOGE("%s: Failing in sid beacon, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_subscribe_sid_beacon) {
+            result = request.put_u8(NAN_ATTRIBUTE_SUB_SID_BEACON, mParams->subscribe_sid_beacon_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in sub sid beacon, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_rssi_proximity) {
+            if (ISGREATER(mParams->rssi_proximity, NAN_MAX_RSSI)) {
+                ALOGI("%s: Invalid rssi param \n", __func__);
+                return WIFI_ERROR_INVALID_ARGS;
+            }
+            rssi = -mParams->rssi_proximity;
+            result = request.put_s8(NAN_ATTRIBUTE_RSSI_PROXIMITY, rssi);
+            if (result < 0) {
+                ALOGE("%s: Failing in rssi_proximity, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_master_pref) {
+            ALOGI("%s: master pref = %u\n", __func__, mParams->master_pref);
+            result = request.put_u8(NAN_ATTRIBUTE_MASTER_PREF, mParams->master_pref);
+            if (result < 0) {
+                ALOGE("%s: Failing in master pref, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_5g_rssi_close_proximity) {
+            if (ISGREATER(mParams->rssi_close_proximity_5g_val, NAN_MAX_RSSI)) {
+                ALOGI("%s: Invalid rssi param \n", __func__);
+                return WIFI_ERROR_INVALID_ARGS;
+            }
+            rssi = -mParams->rssi_close_proximity_5g_val;
+            result = request.put_s8(NAN_ATTRIBUTE_RSSI_PROXIMITY_5G, rssi);
+            if (result < 0) {
+                ALOGE("%s: Failing in rssi_close_proximity_5g_val, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_rssi_window_size) {
+            result = request.put_u8(NAN_ATTRIBUTE_RSSI_WINDOW_SIZE,
+                    mParams->rssi_window_size_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in rssi_window_size_val, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_scan_params) {
+            result = request.put_u8(NAN_ATTRIBUTE_DWELL_TIME,
+                    mParams->scan_params_val.dwell_time[0]);
+            if (result < 0) {
+                ALOGE("%s: Failing in dwell time, result = %d\n", __func__, result);
+                return result;
+            }
+
+            result = request.put_u8(NAN_ATTRIBUTE_DWELL_TIME_5G,
+                    mParams->scan_params_val.dwell_time[1]);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g dwell time, result = %d\n", __func__, result);
+                return result;
+            }
+            result = request.put_u16(NAN_ATTRIBUTE_SCAN_PERIOD,
+                    mParams->scan_params_val.scan_period[0]);
+            if (result < 0) {
+                ALOGE("%s: Failing in scan_period, result = %d\n", __func__, result);
+                return result;
+            }
+
+            result = request.put_u16(NAN_ATTRIBUTE_SCAN_PERIOD_5G,
+                    mParams->scan_params_val.scan_period[1]);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g scan_period, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_random_factor_force) {
+            result = request.put_u8(NAN_ATTRIBUTE_RANDOM_FACTOR, mParams->random_factor_force_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in random factor, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_hop_count_force) {
+            result = request.put_u8(NAN_ATTRIBUTE_HOP_COUNT_LIMIT,
+                    mParams->hop_count_force_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in hop cnt limit, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_cluster_attribute_val) {
+            result = request.put_u8(NAN_ATTRIBUTE_CONF_CLUSTER_VAL, mParams->config_cluster_attribute_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in config_cluster_attribute_val, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_fam) {
+            while (mParams->fam_val.numchans) {
+                result = request.put_u8(NAN_ATTRIBUTE_ENTRY_CONTROL,
+                        mParams->fam_val.famchan[mParams->fam_val.numchans].entry_control);
+                if (result < 0) {
+                    ALOGE("%s: Failing in entry control, result = %d\n", __func__, result);
+                    return result;
+                }
+
+                result = request.put_u32(NAN_ATTRIBUTE_CHANNEL,
+                        (u32)mParams->fam_val.famchan[mParams->fam_val.numchans].channel);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill channel = %d, result = %d\n", __func__,
+                            mParams->fam_val.famchan[mParams->fam_val.numchans].channel, result);
+                    return result;
+                }
+
+                result = request.put_u32(NAN_ATTRIBUTE_AVAIL_BIT_MAP,
+                        (u32)mParams->fam_val.famchan[mParams->fam_val.numchans].avail_interval_bitmap);
+                if (result < 0) {
+                    ALOGE("%s: Failed to fill avail interval bitmap = %d, result = %d\n", __func__,
+                            mParams->fam_val.famchan[mParams->fam_val.numchans].avail_interval_bitmap, result);
+                    return result;
+                }
+                mParams->fam_val.numchans -= 1;
+            }
+
+        }
+
+        if (mParams->config_dw.config_2dot4g_dw_band) {
+            result = request.put_u32(NAN_ATTRIBUTE_2G_AWAKE_DW, mParams->config_dw.dw_2dot4g_interval_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 2dot4g awake dw, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_dw.config_5g_dw_band) {
+            result = request.put_u32(NAN_ATTRIBUTE_5G_AWAKE_DW, mParams->config_dw.dw_5g_interval_val);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g awake dw, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+        if (ISGREATER(mParams->discovery_indication_cfg, NAN_DISC_IND_MAX)) {
+            ALOGE("%s:Invalid disc_ind_cfg value.\n", __FUNCTION__);
+            return WIFI_ERROR_INVALID_ARGS;
+        }
+        result = request.put_u8(NAN_ATTRIBUTE_DISC_IND_CFG,
+                mParams->discovery_indication_cfg);
+        if (result < 0) {
+            ALOGE("%s: Failed to fill NAN_ATTRIBUTE_DISC_IND_CFG, result = %d\n",
+                    __func__, result);
+            return result;
+        }
+        if (mParams->config_disc_mac_addr_randomization) {
+            result = request.put_u32(NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL,
+                    mParams->disc_mac_addr_rand_interval_sec);
+            if (result < 0) {
+                ALOGE("%s: Failing in 5g scan_period, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+        if (mParams->config_ndpe_attr) {
+            result = request.put_u32(NAN_ATTRIBUTE_CMD_USE_NDPE,
+                    mParams->use_ndpe_attr);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill use_ndpe, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_disc_mac_addr_randomization) {
+            result = request.put_u32(NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL,
+                    mParams->disc_mac_addr_rand_interval_sec);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill rand mac interval, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_discovery_beacon_int) {
+            result = request.put_u32(NAN_ATTRIBUTE_DISCOVERY_BEACON_INTERVAL,
+                    mParams->discovery_beacon_interval);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill disc beacon interval, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_nss) {
+            result = request.put_u32(NAN_ATTRIBUTE_NSS, mParams->nss);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill nss, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_enable_ranging) {
+            result = request.put_u32(NAN_ATTRIBUTE_ENABLE_RANGING, mParams->enable_ranging);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill enable ranging value, result = %d\n", __func__, result);
+                return result;
+            }
+        }
+
+        if (mParams->config_dw_early_termination) {
+            result = request.put_u32(NAN_ATTRIBUTE_DW_EARLY_TERM, mParams->enable_dw_termination);
+            if (result < 0) {
+                ALOGE("%s: Failing to fill enable dw termination value, result = %d\n",
+                        __func__, result);
+                return result;
+            }
+        }
+        request.attr_end(data);
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int start()
+    {
+        NAN_DBG_ENTER();
+
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("%s: Failed to create setup request; result = %d", __func__, result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("%s: Failed to configure setup; result = %d", __func__, result);
+            return result;
+        }
+
+        request.destroy();
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int cancel()
+    {
+        NAN_DBG_ENTER();
+
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("%s: Failed to create setup request; result = %d", __func__, result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("%s: Failed to configure setup; result = %d", __func__, result);
+            return result;
+        }
+
+        request.destroy();
+        NAN_DBG_EXIT();
+        return WIFI_SUCCESS;
+    }
+
+    int handleResponse(WifiEvent& reply) {
+        nan_hal_resp_t *rsp_vndr_data = NULL;
+
+        if (reply.get_cmd() != NL80211_CMD_VENDOR || reply.get_vendor_data() == NULL) {
+            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+            return NL_SKIP;
+        }
+
+        rsp_vndr_data = (nan_hal_resp_t *)reply.get_vendor_data();
+        ALOGI("NanMacControl::handleResponse\n");
+        if (mType == NAN_VERSION_INFO) {
+            mVersion = *((u32*)reply.get_vendor_data());
+            ALOGI("Response not required for version cmd %d\n", mVersion);
+            return NL_SKIP;
+        }
+        if (rsp_vndr_data->subcmd == NAN_SUBCMD_CONFIG) {
+            NanResponseMsg rsp_data;
+            memset(&rsp_data, 0, sizeof(NanResponseMsg));
+            rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+            rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+
+            ALOGI("NanMacControl:Received response for cmd [%s], TxID %d ret %d\n",
+                    NanRspToString(rsp_data.response_type), id(), rsp_data.status);
+
+            GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(id(), &rsp_data);
+        }
+        if (rsp_vndr_data->subcmd == NAN_SUBCMD_ENABLE) {
+            NanResponseMsg rsp_data;
+            memset(&rsp_data, 0, sizeof(NanResponseMsg));
+            rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+            rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+
+            ALOGI("NanMacControl:Received response for cmd [%s], TxID %d ret %d\n",
+                  NanRspToString(rsp_data.response_type), mId, rsp_data.status);
+
+            if( rsp_data.status != NAN_STATUS_SUCCESS) {
+                GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(mId, &rsp_data);
+            }
+        }
+        return NL_SKIP;
+    }
+
+    int handleAsyncResponse(nan_hal_resp_t *rsp_vndr_data) {
+        NanResponseMsg rsp_data;
+        ALOGI("NanMacControl::handleAsyncResponse\n");
+        /* Enable response will be provided to framework in event path */
+        if (rsp_vndr_data->subcmd == NAN_SUBCMD_ENABLE) {
+            return NL_SKIP;
+        }
+        memset(&rsp_data, 0, sizeof(NanResponseMsg));
+        rsp_data.response_type = get_response_type((WIFI_SUB_COMMAND)rsp_vndr_data->subcmd);
+        rsp_data.status = nan_map_response_status(rsp_vndr_data->status);
+        ALOGE("Mapped hal status = %d\n", rsp_data.status);
+
+        /* populate error string if not coming from DHD */
+        if (rsp_vndr_data->nan_reason[0] == '\0') {
+            memcpy(rsp_data.nan_error, NanStatusToString(rsp_data.status),
+                    strlen(NanStatusToString(rsp_data.status)));
+            rsp_data.nan_error[strlen(NanStatusToString(rsp_data.status))] = '\0';
+        }
+        rsp_data.nan_error[NAN_ERROR_STR_LEN - 1] = '\0';
+        ALOGI("\n Received nan_error string %s\n", (u8*)rsp_data.nan_error);
+        ALOGI("Retrieved ID = %d\n", mId);
+
+        if ((rsp_vndr_data->subcmd == NAN_SUBCMD_DISABLE) &&
+                (mId != NAN_MAC_INVALID_TRANSID)) {
+            GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(mId, &rsp_data);
+            mId = NAN_MAC_INVALID_TRANSID;
+        }
+        return NL_SKIP;
+    }
+
+    int handleEvent(WifiEvent& event) {
+        u16 inst_id;
+        u32 ndp_instance_id = 0;
+        int event_id = event.get_vendor_subcmd();
+        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+        int len = event.get_vendor_data_len();
+        u16 attr_type;
+        nan_hal_resp_t *rsp_vndr_data = NULL;
+
+        ALOGI("%s: Received NanMacControl event = %d (len=%d)\n",
+                __func__, event.get_cmd(), len);
+        if (!vendor_data || len == 0) {
+            ALOGE("No event data found");
+            return NL_SKIP;
+        }
+
+        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+            attr_type = it.get_type();
+
+            if (it.get_type() == NAN_ATTRIBUTE_HANDLE) {
+                inst_id = it.get_u8();
+            } else if (it.get_type() == NAN_ATTRIBUTE_NDP_ID) {
+                ndp_instance_id = it.get_u32();
+                ALOGI("handleEvent: ndp_instance_id = [%d]\n", ndp_instance_id);
+            } else if (attr_type == NAN_ATTRIBUTE_CMD_RESP_DATA) {
+                ALOGI("sizeof cmd response data: %d, it.get_len() = %d\n",
+                        sizeof(nan_hal_resp_t), it.get_len());
+                if (it.get_len() == sizeof(nan_hal_resp_t)) {
+                    rsp_vndr_data = (nan_hal_resp_t*)it.get_data();
+                } else {
+                    ALOGE("Wrong cmd response data received\n");
+                    return NL_SKIP;
+                }
+            }
+        }
+
+        ALOGI("Received vendor sub cmd %d\n", event_id);
+        if (is_de_event(event_id)) {
+
+            NanDiscEnginePrimitive *de_prim =
+                (NanDiscEnginePrimitive *)(info.nan_disc_control);
+            if (de_prim != NULL) {
+                de_prim->handleEvent(event);
+            } else {
+                ALOGE("%s: de_primitive is no more available\n", __func__);
+            }
+            return NL_SKIP;
+
+        } else if (is_dp_event(event_id)) {
+
+            NanDataPathPrimitive *dp_prim =
+                (NanDataPathPrimitive *)(info.nan_dp_control);
+            ALOGI("ndp_instance_id = [%d]\n", ndp_instance_id);
+            if (dp_prim != NULL) {
+                dp_prim->handleEvent(event);
+            } else {
+                ALOGE("%s: dp_primitive is no more available\n", __func__);
+            }
+            return NL_SKIP;
+        } else {
+            if (is_cmd_response(event_id)) {
+                ALOGE("Handling cmd response asynchronously\n");
+                handleAsyncResponse(rsp_vndr_data);
+            }
+        }
+
+        switch(event_id) {
+            case NAN_EVENT_DE_EVENT:
+                NanDiscEngEventInd de_event;
+                memset(&de_event, 0, sizeof(de_event));
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_CLUSTER_ID) {
+                        memcpy(&de_event.data.cluster.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+                        ALOGI("cluster id = " MACSTR "\n", MAC2STR(de_event.data.cluster.addr));
+                    } else if (attr_type == NAN_ATTRIBUTE_ENABLE_STATUS) {
+                        ALOGI("nan enable status = %u\n", it.get_u16());
+                    } else if (attr_type == NAN_ATTRIBUTE_JOIN_STATUS) {
+                        ALOGI("nan joined status = %u\n", it.get_u16());
+                    } else if (attr_type == NAN_ATTRIBUTE_DE_EVENT_TYPE) {
+                        u8 de_type = it.get_u8();
+                        ALOGI("nan de event type = %u\n", de_type);
+                        if (de_type == NAN_EVENT_IFACE) {
+                            de_event.event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+                            ALOGI("received NAN_EVENT_ID_DISC_MAC_ADDR event\n");
+                        } else if (de_type == NAN_EVENT_START) {
+                            de_event.event_type = NAN_EVENT_ID_STARTED_CLUSTER;
+                            ALOGI("received NAN cluster started event\n");
+                        } else if (de_type == NAN_EVENT_JOIN) {
+                            /* To be deprecated */
+                            de_event.event_type = NAN_EVENT_ID_JOINED_CLUSTER;
+                            ALOGI("received join event\n");
+                        } else if (de_type == NAN_EVENT_ROLE_CHANGE) {
+                            ALOGI("received device role change event\n");
+                        } else if (de_type == NAN_EVENT_MERGE) {
+                            ALOGI("received merge event\n");
+                        } else {
+                            ALOGI("received unknown DE event, [%d]\n", de_type);
+                        }
+                    } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                        memcpy(&de_event.data.mac_addr.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+                        memcpy(mNmi, it.get_data(), NAN_MAC_ADDR_LEN);
+                        ALOGI("Primary discovery mac address = " MACSTR "\n",
+                                MAC2STR(mNmi));
+                    }
+                }
+                GET_NAN_HANDLE(info)->mHandlers.EventDiscEngEvent(&de_event);
+                /* XXX: WAR for sending intf addr to generate Identity
+                 * change callback in framework
+                 * Also WAR for enable response
+                 */
+                if (de_event.event_type == NAN_EVENT_ID_STARTED_CLUSTER) {
+                    NanResponseMsg rsp_data;
+                    memcpy(&de_event.data.mac_addr.addr, mNmi, NAN_MAC_ADDR_LEN);
+                    de_event.event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+                    GET_NAN_HANDLE(info)->mHandlers.EventDiscEngEvent(&de_event);
+                    rsp_data.response_type = NAN_RESPONSE_ENABLED;
+                    rsp_data.status = NAN_STATUS_SUCCESS;
+                    memcpy(rsp_data.nan_error, NanStatusToString(rsp_data.status),
+                            strlen(NanStatusToString(rsp_data.status)));
+                    GET_NAN_HANDLE(info)->mHandlers.NotifyResponse(mId, &rsp_data);
+                    /* clean up mId to distinguish duplciated disable command */
+                    mId = NAN_MAC_INVALID_TRANSID;
+                }
+                break;
+
+            case NAN_EVENT_DISABLED:
+                ALOGI("Received NAN_EVENT_DISABLED\n");
+                NanDisabledInd disabled_ind;
+                memset(&disabled_ind, 0, sizeof(NanDisabledInd));
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+                    if (attr_type == NAN_ATTRIBUTE_STATUS) {
+                        disabled_ind.reason = (NanStatusType)it.get_u8();
+                        ALOGI("Nan Disable:status %u", disabled_ind.reason);
+                    } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+                        memcpy(disabled_ind.nan_reason, it.get_data(),
+                                sizeof(disabled_ind.nan_reason));
+                        ALOGI("Disable nan reason: %s", disabled_ind.nan_reason);
+                    }
+                }
+
+                GET_NAN_HANDLE(info)->mHandlers.EventDisabled(&disabled_ind);
+                /* unregister Nan vendor events */
+                unRegisterNanVendorEvents();
+                break;
+
+            case NAN_EVENT_SDF:
+                ALOGI("Received NAN_EVENT_SDF:\n");
+                NanBeaconSdfPayloadInd sdfInd;
+                memset(&sdfInd, 0, sizeof(sdfInd));
+
+                for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                    attr_type = it.get_type();
+
+                    if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                        sdfInd.data.frame_len = it.get_u32();
+                        if (sdfInd.data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
+                            sdfInd.data.frame_len = NAN_MAX_FRAME_DATA_LEN;
+                        }
+                        ALOGI("Received NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN: 0x%x(%d)\n",
+                                sdfInd.data.frame_len, sdfInd.data.frame_len);
+
+                    } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                        ALOGI("Received NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO\n");
+                        memcpy(&sdfInd.data.frame_data, it.get_data(), sdfInd.data.frame_len);
+                        prhex("sdfInd.data.frame_data: ", (u8*)sdfInd.data.frame_data,
+                                sdfInd.data.frame_len);
+                    }
+                }
+                GET_NAN_HANDLE(info)->mHandlers.EventBeaconSdfPayload(&sdfInd);
+                break;
+
+            case NAN_EVENT_TCA:
+                ALOGI("Received NAN_EVENT_TCA\n");
+                break;
+
+            case NAN_EVENT_UNKNOWN:
+                ALOGI("Received NAN_EVENT_UNKNOWN\n");
+                break;
+        } // end-of-switch
+
+        return NL_SKIP;
+    }
+    void unRegisterNanVendorEvents()
+    {
+        int i = 0;
+        for (i = NAN_EVENT_ENABLED; i <= NAN_EVENT_DATA_END; i++) {
+            unregisterVendorHandler(GOOGLE_OUI, i);
+        }
+        unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+    }
+    void registerNanVendorEvents()
+    {
+        int i = 0;
+        for (i = NAN_EVENT_ENABLED; i <= NAN_EVENT_DATA_END; i++) {
+            registerVendorHandler(GOOGLE_OUI, i);
+        }
+        registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+    }
+};
+
+/* pretty hex print a contiguous buffer */
+static void prhex(const char *msg, u8 *buf, u32 nbytes)
+{
+    char line[128];
+    char *p;
+    int len = sizeof(line);
+    int nchar;
+    u32 i;
+
+    if (msg && (msg[0] != '\0')) {
+        printf("%s:\n", msg);
+    }
+
+    p = line;
+    for (i = 0; i < nbytes; i++) {
+        if (i % 16 == 0) {
+            nchar = snprintf(p, len, "  %04d: ", i);    /* line prefix */
+            p += nchar;
+            len -= nchar;
+        }
+
+        if (len > 0) {
+            nchar = snprintf(p, len, "%02x ", buf[i]);
+            p += nchar;
+            len -= nchar;
+        }
+
+        if (i % 16 == 15) {
+            ALOGE("%s\n", line);       /* flush line */
+            p = line;
+            len = sizeof(line);
+        }
+    }
+
+    /* flush last partial line */
+    if (p != line) {
+        ALOGE("%s\n", line);
+    }
+}
+
+
+static const char *NanRspToString(int cmd_resp)
+{
+    switch (cmd_resp) {
+        C2S(NAN_RESPONSE_ENABLED)
+            C2S(NAN_RESPONSE_DISABLED)
+            C2S(NAN_RESPONSE_PUBLISH)
+            C2S(NAN_RESPONSE_SUBSCRIBE)
+            C2S(NAN_RESPONSE_PUBLISH_CANCEL)
+            C2S(NAN_RESPONSE_SUBSCRIBE_CANCEL)
+            C2S(NAN_RESPONSE_TRANSMIT_FOLLOWUP)
+            C2S(NAN_RESPONSE_CONFIG)
+            C2S(NAN_RESPONSE_TCA)
+            C2S(NAN_RESPONSE_STATS)
+            C2S(NAN_DP_INTERFACE_CREATE)
+            C2S(NAN_DP_INTERFACE_DELETE)
+            C2S(NAN_DP_INITIATOR_RESPONSE)
+            C2S(NAN_DP_RESPONDER_RESPONSE)
+            C2S(NAN_DP_END)
+            C2S(NAN_GET_CAPABILITIES)
+
+        default:
+            return "UNKNOWN_NAN_CMD_RESPONSE";
+    }
+}
+
+static const char *NanCmdToString(int cmd)
+{
+    switch (cmd) {
+        C2S(NAN_REQUEST_ENABLE)
+            C2S(NAN_REQUEST_DISABLE)
+            C2S(NAN_REQUEST_PUBLISH)
+            C2S(NAN_REQUEST_PUBLISH_CANCEL)
+            C2S(NAN_REQUEST_TRANSMIT_FOLLOWUP)
+            C2S(NAN_REQUEST_SUBSCRIBE)
+            C2S(NAN_REQUEST_SUBSCRIBE_CANCEL)
+            C2S(NAN_REQUEST_STATS)
+            C2S(NAN_REQUEST_CONFIG)
+            C2S(NAN_REQUEST_TCA)
+            C2S(NAN_REQUEST_EVENT_CHECK)
+            C2S(NAN_REQUEST_GET_CAPABILTIES)
+            C2S(NAN_DATA_PATH_IFACE_CREATE)
+            C2S(NAN_DATA_PATH_IFACE_DELETE)
+            C2S(NAN_DATA_PATH_INIT_REQUEST)
+            C2S(NAN_DATA_PATH_IND_RESPONSE)
+            C2S(NAN_DATA_PATH_END)
+            C2S(NAN_DATA_PATH_IFACE_UP)
+            C2S(NAN_DATA_PATH_SEC_INFO)
+            C2S(NAN_VERSION_INFO)
+            C2S(NAN_REQUEST_ENABLE_MERGE)
+
+        default:
+            return "UNKNOWN_NAN_CMD";
+    }
+}
+
+static const char *NanAttrToString(u16 cmd)
+{
+    switch (cmd) {
+        C2S(NAN_ATTRIBUTE_HEADER)
+            C2S(NAN_ATTRIBUTE_HANDLE)
+            C2S(NAN_ATTRIBUTE_TRANSAC_ID)
+            C2S(NAN_ATTRIBUTE_5G_SUPPORT)
+            C2S(NAN_ATTRIBUTE_CLUSTER_LOW)
+            C2S(NAN_ATTRIBUTE_CLUSTER_HIGH)
+            C2S(NAN_ATTRIBUTE_SID_BEACON)
+            C2S(NAN_ATTRIBUTE_SYNC_DISC_5G_BEACON)
+            C2S(NAN_ATTRIBUTE_RSSI_CLOSE)
+            C2S(NAN_ATTRIBUTE_RSSI_MIDDLE)
+            C2S(NAN_ATTRIBUTE_RSSI_PROXIMITY)
+            C2S(NAN_ATTRIBUTE_HOP_COUNT_LIMIT)
+            C2S(NAN_ATTRIBUTE_RANDOM_FACTOR)
+            C2S(NAN_ATTRIBUTE_MASTER_PREF)
+            C2S(NAN_ATTRIBUTE_PERIODIC_SCAN_INTERVAL)
+            C2S(NAN_ATTRIBUTE_PUBLISH_ID)
+            C2S(NAN_ATTRIBUTE_TTL)
+            C2S(NAN_ATTRIBUTE_PERIOD)
+            C2S(NAN_ATTRIBUTE_REPLIED_EVENT_FLAG)
+            C2S(NAN_ATTRIBUTE_PUBLISH_TYPE)
+            C2S(NAN_ATTRIBUTE_TX_TYPE)
+            C2S(NAN_ATTRIBUTE_PUBLISH_COUNT)
+            C2S(NAN_ATTRIBUTE_SERVICE_NAME_LEN)
+            C2S(NAN_ATTRIBUTE_SERVICE_NAME)
+            C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN)
+            C2S(NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO)
+            C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER_LEN)
+            C2S(NAN_ATTRIBUTE_RX_MATCH_FILTER)
+            C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN)
+            C2S(NAN_ATTRIBUTE_TX_MATCH_FILTER)
+            C2S(NAN_ATTRIBUTE_SUBSCRIBE_ID)
+            C2S(NAN_ATTRIBUTE_SUBSCRIBE_TYPE)
+            C2S(NAN_ATTRIBUTE_SERVICERESPONSEFILTER)
+            C2S(NAN_ATTRIBUTE_SERVICERESPONSEINCLUDE)
+            C2S(NAN_ATTRIBUTE_USESERVICERESPONSEFILTER)
+            C2S(NAN_ATTRIBUTE_SSIREQUIREDFORMATCHINDICATION)
+            C2S(NAN_ATTRIBUTE_SUBSCRIBE_MATCH)
+            C2S(NAN_ATTRIBUTE_SUBSCRIBE_COUNT)
+            C2S(NAN_ATTRIBUTE_MAC_ADDR)
+            C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST)
+            C2S(NAN_ATTRIBUTE_MAC_ADDR_LIST_NUM_ENTRIES)
+            C2S(NAN_ATTRIBUTE_PUBLISH_MATCH)
+            C2S(NAN_ATTRIBUTE_ENABLE_STATUS)
+            C2S(NAN_ATTRIBUTE_JOIN_STATUS)
+            C2S(NAN_ATTRIBUTE_ROLE)
+            C2S(NAN_ATTRIBUTE_MASTER_RANK)
+            C2S(NAN_ATTRIBUTE_ANCHOR_MASTER_RANK)
+            C2S(NAN_ATTRIBUTE_CNT_PEND_TXFRM)
+            C2S(NAN_ATTRIBUTE_CNT_BCN_TX)
+            C2S(NAN_ATTRIBUTE_CNT_BCN_RX)
+            C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_TX)
+            C2S(NAN_ATTRIBUTE_CNT_SVC_DISC_RX)
+            C2S(NAN_ATTRIBUTE_AMBTT)
+            C2S(NAN_ATTRIBUTE_CLUSTER_ID)
+            C2S(NAN_ATTRIBUTE_INST_ID)
+            C2S(NAN_ATTRIBUTE_OUI)
+            C2S(NAN_ATTRIBUTE_STATUS)
+            C2S(NAN_ATTRIBUTE_DE_EVENT_TYPE)
+            C2S(NAN_ATTRIBUTE_MERGE)
+            C2S(NAN_ATTRIBUTE_IFACE)
+            C2S(NAN_ATTRIBUTE_CHANNEL)
+            C2S(NAN_ATTRIBUTE_PEER_ID)
+            C2S(NAN_ATTRIBUTE_NDP_ID)
+            C2S(NAN_ATTRIBUTE_SECURITY)
+            C2S(NAN_ATTRIBUTE_QOS)
+            C2S(NAN_ATTRIBUTE_RSP_CODE)
+            C2S(NAN_ATTRIBUTE_INST_COUNT)
+            C2S(NAN_ATTRIBUTE_PEER_DISC_MAC_ADDR)
+            C2S(NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR)
+            C2S(NAN_ATTRIBUTE_IF_ADDR)
+            C2S(NAN_ATTRIBUTE_WARMUP_TIME)
+            C2S(NAN_ATTRIBUTE_RANGING_RESULT)
+            C2S(NAN_ATTRIBUTE_RANGING_INDICATION)
+            C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN)
+            C2S(NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO)
+            C2S(NAN_ATTRIBUTE_RANDOMIZATION_INTERVAL)
+            C2S(NAN_ATTRIBUTE_ENABLE_MERGE)
+
+        default:
+            return "NAN_ATTRIBUTE_UNKNOWN";
+    }
+}
+
+NanResponseType get_response_type(WIFI_SUB_COMMAND nan_subcmd)
+{
+    NanResponseType response_type;
+
+    switch(nan_subcmd) {
+        case NAN_SUBCMD_ENABLE:
+            response_type = NAN_RESPONSE_ENABLED;
+            break;
+        case NAN_SUBCMD_DISABLE:
+            response_type = NAN_RESPONSE_DISABLED;
+            break;
+        case NAN_SUBCMD_PUBLISH:
+            response_type = NAN_RESPONSE_PUBLISH;
+            break;
+        case NAN_SUBCMD_SUBSCRIBE:
+            response_type = NAN_RESPONSE_SUBSCRIBE;
+            break;
+        case NAN_SUBCMD_PUBLISH_CANCEL:
+            response_type = NAN_RESPONSE_PUBLISH_CANCEL;
+            break;
+        case NAN_SUBCMD_SUBSCRIBE_CANCEL:
+            response_type = NAN_RESPONSE_SUBSCRIBE_CANCEL;
+            break;
+        case NAN_SUBCMD_TRANSMIT_FOLLOWUP:
+            response_type = NAN_RESPONSE_TRANSMIT_FOLLOWUP;
+            break;
+        case NAN_SUBCMD_CONFIG:
+            response_type = NAN_RESPONSE_CONFIG;
+            break;
+        case NAN_SUBCMD_TCA:
+            response_type = NAN_RESPONSE_TCA;
+            break;
+        case NAN_SUBCMD_STATS:
+            response_type = NAN_RESPONSE_STATS;
+            break;
+        case NAN_SUBCMD_DATA_PATH_IFACE_CREATE:
+            response_type = NAN_DP_INTERFACE_CREATE;
+            break;
+        case NAN_SUBCMD_DATA_PATH_IFACE_DELETE:
+            response_type = NAN_DP_INTERFACE_DELETE;
+            break;
+        case NAN_SUBCMD_DATA_PATH_REQUEST:
+            response_type = NAN_DP_INITIATOR_RESPONSE;
+            break;
+        case NAN_SUBCMD_DATA_PATH_RESPONSE:
+            response_type = NAN_DP_RESPONDER_RESPONSE;
+            break;
+        case NAN_SUBCMD_DATA_PATH_END:
+            response_type = NAN_DP_END;
+            break;
+        case NAN_SUBCMD_GET_CAPABILITIES:
+            response_type = NAN_GET_CAPABILITIES;
+            break;
+        default:
+            /* unknown response for a command */
+            response_type = NAN_RESPONSE_ERROR;
+            break;
+    }
+
+    return response_type;
+}
+
+static int get_svc_hash(unsigned char *svc_name,
+        u16 svc_name_len, u8 *svc_hash, u16 svc_hash_len)
+{
+    SHA256_CTX sha_ctx;
+    u8 sha_hash[SHA256_DIGEST_LENGTH];
+    unsigned char *p;
+    int len = svc_name_len;
+
+    if (!svc_name || !svc_hash) {
+        ALOGE("Bad arguments!!\n");
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    if (svc_hash_len < NAN_SVC_HASH_SIZE) {
+        ALOGE("Bad len!!\n");
+        return WIFI_ERROR_UNKNOWN;
+    }
+    for (p = svc_name; *p; p++)
+    {
+        *p = tolower((int)*p);
+    }
+    SHA256_Init(&sha_ctx);
+    SHA256_Update(&sha_ctx, svc_name, len);
+    SHA256_Final(sha_hash, &sha_ctx);
+
+    memcpy(svc_hash, sha_hash, NAN_SVC_HASH_SIZE);
+    ALOGI("svc_name: %s\n", svc_name);
+    prhex("svc_hash:", svc_hash, NAN_SVC_HASH_SIZE);
+
+    return WIFI_SUCCESS;
+}
+
+#ifdef CONFIG_BRCM
+static int dump_NanEnableRequest(NanEnableRequest* msg)
+{
+    ALOGI("%s: Dump NanEnableRequest msg:\n", __func__);
+
+    if (msg == NULL) {
+        ALOGE("Invalid msg\n");
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    ALOGI("master_pref=%u\n", msg->master_pref);
+    ALOGI("cluster_low=%u\n", msg->cluster_low);
+    ALOGI("cluster_high=%u\n", msg->cluster_high);
+    ALOGI("config_support_5g=%u\n", msg->config_support_5g);
+    ALOGI("support_5g_val=%u\n", msg->support_5g_val);
+    ALOGI("config_sid_beacon=%u\n", msg->config_sid_beacon);
+    ALOGI("sid beacon=%u\n", msg->sid_beacon_val);
+    ALOGI("config_sub_sid_beacon=%u\n", msg->config_subscribe_sid_beacon);
+    ALOGI("sub sid beacon=%u\n", msg->subscribe_sid_beacon_val);
+    ALOGI("config_2dot4g_rssi_close=%u\n", msg->config_2dot4g_rssi_close);
+    ALOGI("rssi_close_2dot4g_val=%u\n", msg->rssi_close_2dot4g_val);
+    ALOGI("config_2dot4g_rssi_middle=%u\n", msg->config_2dot4g_rssi_middle);
+    ALOGI("rssi_middle_2dot4g_val=%u\n", msg->rssi_middle_2dot4g_val);
+    ALOGI("config_2dot4g_rssi_proximity=%u\n", msg->config_2dot4g_rssi_proximity);
+    ALOGI("rssi_proximity_2dot4g_val=%u\n", msg->rssi_proximity_2dot4g_val);
+    ALOGI("config_hop_count_limit=%u\n", msg->config_hop_count_limit);
+    ALOGI("hop_count_limit_val=%u\n", msg->hop_count_limit_val);
+    ALOGI("config_2dot4g_support=%u\n", msg->config_2dot4g_support);
+    ALOGI("support_2dot4g_val=%u\n", msg->support_2dot4g_val);
+    ALOGI("config_2dot4g_beacons=%u\n", msg->config_2dot4g_beacons);
+    ALOGI("beacon_2dot4g_val=%u\n", msg->beacon_2dot4g_val);
+    ALOGI("config_2dot4g_sdf=%u\n", msg->config_2dot4g_sdf);
+    ALOGI("sdf_2dot4g_val=%u\n", msg->sdf_2dot4g_val);
+    ALOGI("config_5g_beacons=%u\n", msg->config_5g_beacons);
+    ALOGI("beacon_5g_val=%u\n", msg->beacon_5g_val);
+    ALOGI("config_5g_sdf=%u\n", msg->config_5g_sdf);
+    ALOGI("config_5g_rssi_close=%u\n", msg->config_5g_rssi_close);
+    ALOGI("rssi_close_5g_val=%u\n", msg->rssi_close_5g_val);
+    ALOGI("config_5g_rssi_middle=%u\n", msg->config_5g_rssi_middle);
+    ALOGI("rssi_middle_5g_val=%u\n", msg->rssi_middle_5g_val);
+    ALOGI("config_5g_rssi_close_proximity=%u\n", msg->config_5g_rssi_close_proximity);
+    ALOGI("rssi_close_proximity_5g_val=%u\n", msg->rssi_close_proximity_5g_val);
+    ALOGI("config_rssi_window_size=%u\n", msg->config_rssi_window_size);
+    ALOGI("rssi_window_size_val=%u\n", msg->rssi_window_size_val);
+    ALOGI("config_oui=%u\n", msg->config_oui);
+    ALOGI("oui_val=%u\n", msg->oui_val);
+    ALOGI("config_intf_addr=%u\n", msg->config_intf_addr);
+    ALOGI("intf_addr_val=" MACSTR "\n", MAC2STR(msg->intf_addr_val));
+    ALOGI("config_cluster_attribute_val=%u\n", msg->config_cluster_attribute_val);
+    ALOGI("config_scan_params=%u\n", msg->config_scan_params);
+    if (msg->config_scan_params) {
+        ALOGI("dwell_time=%u\n", msg->scan_params_val.dwell_time[0]);
+        ALOGI("scan_period=%u\n", msg->scan_params_val.scan_period[0]);
+    }
+    ALOGI("config_random_factor_force=%u\n", msg->config_random_factor_force);
+    ALOGI("random_factor_force_val=%u\n", msg->random_factor_force_val);
+    ALOGI("config_hop_count_force=%u\n", msg->config_hop_count_force);
+    ALOGI("config_24g_channel=%u\n", msg->config_24g_channel);
+    ALOGI("channel_24g_val=%u\n", msg->channel_24g_val);
+    ALOGI("config_5g_channel=%u\n", msg->config_5g_channel);
+    ALOGI("channel_5g_val=%u\n", msg->channel_5g_val);
+    ALOGI("config_dw.config_2dot4g_dw_band=%u\n", msg->config_dw.config_2dot4g_dw_band);
+    if (msg->config_dw.config_2dot4g_dw_band) {
+        ALOGI("dw_2dot4g_interval_val=%u\n", msg->config_dw.dw_2dot4g_interval_val);
+    }
+    ALOGI("config_dw.config_5g_dw_band=%u\n", msg->config_dw.config_5g_dw_band);
+    if (msg->config_dw.config_5g_dw_band) {
+        ALOGI("dw_5g_interval_val=%u\n", msg->config_dw.dw_5g_interval_val);
+    }
+    ALOGI("discovery_indication_cfg=%u\n", msg->discovery_indication_cfg);
+    ALOGI("config_ndpe_attr=%u\n", msg->config_ndpe_attr);
+    if (msg->config_ndpe_attr) {
+        ALOGI("use_ndpe_attr=%u\n", msg->use_ndpe_attr);
+    }
+    ALOGI("config_discovery_beacon_int=%u\n", msg->config_discovery_beacon_int);
+    if (msg->config_discovery_beacon_int) {
+        ALOGI("discovery beacon interval =%u\n", msg->discovery_beacon_interval);
+    }
+    ALOGI("config_nss=%u\n", msg->config_nss);
+    if (msg->config_nss) {
+        ALOGI("nss =%u\n", msg->nss);
+    }
+    ALOGI("config_enable_ranging =%u\n", msg->config_enable_ranging);
+    if (msg->config_enable_ranging) {
+        ALOGI("enable_ranging =%u\n", msg->enable_ranging);
+    }
+    ALOGI("config_dw_early_termination =%u\n", msg->config_dw_early_termination);
+    if (msg->config_dw_early_termination) {
+        ALOGI("enable_dw_termination =%u\n", msg->enable_dw_termination);
+    }
+    ALOGI("config_disc_mac_addr_randomization=%u\n", msg->config_disc_mac_addr_randomization);
+    if (msg->config_disc_mac_addr_randomization) {
+        ALOGI("disc_mac_addr_rand_interval_sec =%u\n", msg->disc_mac_addr_rand_interval_sec);
+    }
+
+    return WIFI_SUCCESS;
+}
+
+static int dump_NanConfigRequestRequest(NanConfigRequest* msg)
+{
+    ALOGI("%s: Dump NanConfigRequest msg:\n", __func__);
+
+    if (msg == NULL) {
+        ALOGE("Invalid msg\n");
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    ALOGI("master_pref=%u\n", msg->master_pref);
+    ALOGI("sid beacon=%u\n", msg->sid_beacon);
+    ALOGI("config_sub_sid_beacon=%u\n", msg->config_subscribe_sid_beacon);
+    ALOGI("sub sid beacon=%u\n", msg->subscribe_sid_beacon_val);
+    ALOGI("rssi_proximity=%u\n", msg->rssi_proximity);
+    ALOGI("rssi_close_proximity_5g_val=%u\n", msg->rssi_close_proximity_5g_val);
+    ALOGI("rssi_window_size_val=%u\n", msg->rssi_window_size_val);
+    ALOGI("scan_params_val.dwell_time[0]=%u\n", msg->scan_params_val.dwell_time[0]);
+    ALOGI("scan_params_val.scan_period[0]=%u\n", msg->scan_params_val.scan_period[0]);
+    ALOGI("config_scan_params=%u\n", msg->config_scan_params);
+    ALOGI("random_factor_force_val=%u\n", msg->random_factor_force_val);
+    ALOGI("hop_count_force_val=%u\n", msg->hop_count_force_val);
+    ALOGI("fam_val.numchans=%u\n", msg->fam_val.numchans);
+    ALOGI("fam_val.famchan[0].entry_control=%u\n", msg->fam_val.famchan[0].entry_control);
+    ALOGI("fam_val.famchan[0].class_val=%u\n", msg->fam_val.famchan[0].class_val);
+    ALOGI("fam_val.famchan[0].channel=%u\n", msg->fam_val.famchan[0].channel);
+    ALOGI("fam_val.famchan[0].mapid=%u\n", msg->fam_val.famchan[0].mapid);
+    ALOGI("fam_val.famchan[0].avail_interval_bitmap=%u\n", msg->fam_val.famchan[0].avail_interval_bitmap);
+    ALOGI("config_dw.config_2dot4g_dw_band=%u\n", msg->config_dw.config_2dot4g_dw_band);
+    if (msg->config_dw.config_2dot4g_dw_band) {
+        ALOGI("dw_2dot4g_interval_val=%u\n", msg->config_dw.dw_2dot4g_interval_val);
+    }
+    ALOGI("config_dw.config_5g_dw_band=%u\n", msg->config_dw.config_5g_dw_band);
+    if (msg->config_dw.config_5g_dw_band) {
+        ALOGI("dw_5g_interval_val=%u\n", msg->config_dw.dw_5g_interval_val);
+    }
+    ALOGI("discovery_indication_cfg=%u\n", msg->discovery_indication_cfg);
+    ALOGI("config_ndpe_attr=%u\n", msg->config_ndpe_attr);
+    if (msg->config_ndpe_attr) {
+        ALOGI("use_ndpe_attr=%u\n", msg->use_ndpe_attr);
+    }
+    ALOGI("config_discovery_beacon_int=%u\n", msg->config_discovery_beacon_int);
+    if (msg->config_discovery_beacon_int) {
+        ALOGI("discovery beacon interval =%u\n", msg->discovery_beacon_interval);
+    }
+    ALOGI("config_nss=%u\n", msg->config_nss);
+    if (msg->config_nss) {
+        ALOGI("nss =%u\n", msg->nss);
+    }
+    ALOGI("config_enable_ranging =%u\n", msg->config_enable_ranging);
+    if (msg->config_enable_ranging) {
+        ALOGI("enable_ranging =%u\n", msg->enable_ranging);
+    }
+    ALOGI("config_dw_early_termination =%u\n", msg->config_dw_early_termination);
+    if (msg->config_dw_early_termination) {
+        ALOGI("enable_dw_termination =%u\n", msg->enable_dw_termination);
+    }
+
+    ALOGI("config_disc_mac_addr_randomization=%u\n", msg->config_disc_mac_addr_randomization);
+    if (msg->config_disc_mac_addr_randomization) {
+        ALOGI("disc_mac_addr_rand_interval_sec =%u\n", msg->disc_mac_addr_rand_interval_sec);
+    }
+    return WIFI_SUCCESS;
+}
+
+static int dump_NanPublishRequest(NanPublishRequest* msg)
+{
+    ALOGI("%s: Dump NanPublishRequest msg:\n", __func__);
+    u8 i = 0;
+    if (msg == NULL) {
+        ALOGE("Invalid msg\n");
+        return WIFI_ERROR_UNKNOWN;
+    }
+    ALOGI("publish_id=%u\n", msg->publish_id);
+    ALOGI("ttl=%u\n", msg->ttl);
+    ALOGI("period=%u\n", msg->period);
+    ALOGI("publish_type=%u\n", msg->publish_type);
+    ALOGI("tx_type=%u\n", msg->tx_type);
+    ALOGI("publish_count=%u\n", msg->publish_count);
+    ALOGI("publish_match_indicator=%u\n", msg->publish_match_indicator);
+    ALOGI("service_responder_policy=%u\n", msg->service_responder_policy);
+    ALOGI("service_name_len=%u\n", msg->service_name_len);
+    if (msg->service_name_len)
+        ALOGI("service_name=%s\n", msg->service_name);
+    ALOGI("service_specific_info_len=%u\n", msg->service_specific_info_len);
+    if (msg->service_specific_info_len)
+        ALOGI("service_specific_info=%s\n", msg->service_specific_info);
+    ALOGI("rx_match_filter_len=%u\n", msg->rx_match_filter_len);
+    if (msg->rx_match_filter_len)
+        prhex("rx_match_filter", msg->rx_match_filter, msg->rx_match_filter_len);
+    ALOGI("tx_match_filter_len=%u\n", msg->tx_match_filter_len);
+    if (msg->tx_match_filter_len)
+        prhex("tx_match_filter", msg->tx_match_filter, msg->tx_match_filter_len);
+    ALOGI("rssi_threshold_flag=%u\n", msg->rssi_threshold_flag);
+    ALOGI("connmap=%u\n", msg->connmap);
+    ALOGI("recv_indication_cfg=%u\n", msg->recv_indication_cfg);
+    ALOGI("cipher_type=%u\n", msg->cipher_type);
+    ALOGI("key_info: key_type =%u\n", msg->key_info.key_type);
+    ALOGI("key_info: pmk info=%s\n", msg->key_info.body.pmk_info.pmk);
+    ALOGI("key_info: passphrase_info=%s\n", msg->key_info.body.passphrase_info.passphrase);
+    ALOGI("scid_len=%u\n", msg->scid_len);
+    if (msg->scid_len)
+        ALOGI("scid=%s\n", msg->scid);
+    ALOGI("NanSdeaCtrlParams NdpType=%u\n", msg->sdea_params.ndp_type);
+    ALOGI("NanSdeaCtrlParams security_cfg=%u\n", msg->sdea_params.security_cfg);
+    ALOGI("NanSdeaCtrlParams ranging_state=%u\n", msg->sdea_params.ranging_state);
+    ALOGI("NanSdeaCtrlParams range_report=%u\n", msg->sdea_params.range_report);
+    ALOGI("NanRangingCfg ranging_interval_msec=%u\n", msg->ranging_cfg.ranging_interval_msec);
+    ALOGI("NanRangingCfg config_ranging_indications=%u\n", msg->ranging_cfg.config_ranging_indications);
+    ALOGI("NanRangingCfg distance_ingress_mm=%u\n", msg->ranging_cfg.distance_ingress_mm);
+    ALOGI("NanRangingCfg distance_egress_mm=%u\n", msg->ranging_cfg.distance_egress_mm);
+    ALOGI("NanRangingAutoResponse = %u\n", msg->ranging_auto_response);
+    ALOGI("range_response_cfg=%u\n", msg->range_response_cfg.ranging_response);
+
+    ALOGI("sdea_service_specific_info_len=%u\n", msg->sdea_service_specific_info_len);
+    if (msg->sdea_service_specific_info_len)
+        ALOGI("sdea_service_specific_info=%s\n", msg->sdea_service_specific_info);
+
+    return WIFI_SUCCESS;
+}
+
+static int dump_NanSubscribeRequest(NanSubscribeRequest* msg)
+{
+    ALOGI("%s: Dump NanSubscribeRequest msg:\n", __func__);
+    u8 i = 0;
+    if (msg == NULL) {
+        ALOGE("Invalid msg\n");
+        return WIFI_ERROR_UNKNOWN;
+    }
+    ALOGI("subscribe_id=%u\n", msg->subscribe_id);
+    ALOGI("ttl=%u\n", msg->ttl);
+    ALOGI("period=%u\n", msg->period);
+    ALOGI("subscribe_type=%u\n", msg->subscribe_type);
+    ALOGI("serviceResponseFilter=%u\n", msg->serviceResponseFilter);
+    ALOGI("serviceResponseInclude=%u\n", msg->serviceResponseInclude);
+    ALOGI("useServiceResponseFilter=%u\n", msg->useServiceResponseFilter);
+    ALOGI("ssiRequiredForMatchIndication=%u\n", msg->ssiRequiredForMatchIndication);
+    ALOGI("subscribe_count=%u\n", msg->subscribe_count);
+    ALOGI("subscribe_match_indicator=%u\n", msg->subscribe_match_indicator);
+    ALOGI("service_name_len=%u\n", msg->service_name_len);
+    if (msg->service_name_len)
+        ALOGI("service_name=%s\n", msg->service_name);
+    ALOGI("service_specific_info_len=%u\n", msg->service_specific_info_len);
+    if (msg->service_specific_info_len)
+        ALOGI("service_specific_info=%s\n", msg->service_specific_info);
+    ALOGI("rx_match_filter_len=%u\n", msg->rx_match_filter_len);
+    if (msg->rx_match_filter_len)
+        prhex("rx_match_filter", msg->rx_match_filter, msg->rx_match_filter_len);
+    ALOGI("tx_match_filter_len=%u\n", msg->tx_match_filter_len);
+    if (msg->tx_match_filter_len)
+        prhex("tx_match_filter", msg->tx_match_filter, msg->tx_match_filter_len);
+    ALOGI("rssi_threshold_flag=%u\n", msg->rssi_threshold_flag);
+    ALOGI("connmap=%u\n", msg->connmap);
+    ALOGI("num_intf_addr_present=%u\n", msg->num_intf_addr_present);
+    if (msg->num_intf_addr_present) {
+        for (i = 0; i < NAN_MAX_SUBSCRIBE_MAX_ADDRESS; i++) {
+            ALOGI("peer_disc_mac_addr=" MACSTR "\n", MAC2STR(msg->intf_addr[i]));
+        }
+    }
+    ALOGI("recv_indication_cfg=%u\n", msg->recv_indication_cfg);
+    ALOGI("cipher_type=%u\n", msg->cipher_type);
+    ALOGI("key_info: key_type =%u\n", msg->key_info.key_type);
+    ALOGI("key_info: pmk info=%s\n", msg->key_info.body.pmk_info.pmk);
+    ALOGI("key_info: passphrase_info=%s\n", msg->key_info.body.passphrase_info.passphrase);
+    ALOGI("scid_len=%u\n", msg->scid_len);
+    if (msg->scid_len)
+        ALOGI("scid=%s\n", msg->scid);
+    ALOGI("NanSdeaCtrlParams NdpType=%u\n", msg->sdea_params.ndp_type);
+    ALOGI("NanSdeaCtrlParams security_cfg=%u\n", msg->sdea_params.security_cfg);
+    ALOGI("NanSdeaCtrlParams ranging_state=%u\n", msg->sdea_params.ranging_state);
+    ALOGI("NanSdeaCtrlParams range_report=%u\n", msg->sdea_params.range_report);
+    ALOGI("NanRangingCfg ranging_interval_msec=%u\n", msg->ranging_cfg.ranging_interval_msec);
+    ALOGI("NanRangingCfg config_ranging_indications=%u\n", msg->ranging_cfg.config_ranging_indications);
+    ALOGI("NanRangingCfg distance_ingress_mm=%u\n", msg->ranging_cfg.distance_ingress_mm);
+    ALOGI("NanRangingCfg distance_egress_mm=%u\n", msg->ranging_cfg.distance_egress_mm);
+    ALOGI("NanRangingAutoResponse = %u\n", msg->ranging_auto_response);
+    ALOGI("range_response = %u\n", msg->range_response_cfg.ranging_response);
+
+    ALOGI("sdea_service_specific_info_len=%u\n", msg->sdea_service_specific_info_len);
+    if (msg->sdea_service_specific_info_len)
+        ALOGI("sdea_service_specific_info=%s\n", msg->sdea_service_specific_info);
+
+    return WIFI_SUCCESS;
+}
+
+static int dump_NanTransmitFollowupRequest(NanTransmitFollowupRequest* msg)
+{
+    ALOGI("%s: Dump NanTransmitFollowupRequest msg:\n", __func__);
+    u8 i = 0;
+    if (msg == NULL) {
+        ALOGE("Invalid msg\n");
+        return WIFI_ERROR_UNKNOWN;
+    }
+    ALOGI("publish_subscribe_id=%u\n", msg->publish_subscribe_id);
+    ALOGI("requestor_instance_id=%u\n", msg->requestor_instance_id);
+    ALOGI("addr=" MACSTR "\n", MAC2STR(msg->addr));
+    ALOGI("priority=%u\n", msg->priority);
+    ALOGI("dw_or_faw=%u\n", msg->dw_or_faw);
+    ALOGI("service_specific_info_len=%u\n", msg->service_specific_info_len);
+    if (msg->service_specific_info_len)
+        ALOGI("service_specific_info=%s\n", msg->service_specific_info);
+    ALOGI("recv_indication_cfg=%u\n", msg->recv_indication_cfg);
+    ALOGI("sdea_service_specific_info_len=%u\n", msg->sdea_service_specific_info_len);
+    if (msg->sdea_service_specific_info_len)
+        ALOGI("sdea_service_specific_info=%s\n", msg->sdea_service_specific_info);
+
+    return WIFI_SUCCESS;
+}
+
+static int dump_NanDataPathInitiatorRequest(NanDataPathInitiatorRequest* msg)
+{
+    ALOGI("%s: Dump NanDataPathInitiatorRequest msg:\n", __func__);
+
+    if (msg == NULL) {
+        ALOGE("Invalid msg\n");
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    ALOGI("requestor_instance_id=%d\n", msg->requestor_instance_id);
+    ALOGI("channel_request_type=%d\n", msg->channel_request_type);
+    ALOGI("channel=%u\n", msg->channel);
+    ALOGI("peer_disc_mac_addr=" MACSTR "\n", MAC2STR(msg->peer_disc_mac_addr));
+    ALOGI("ndp_iface=%s\n", msg->ndp_iface);
+    ALOGI("ndp_cfg: security_cfg =%u\n", msg->ndp_cfg.security_cfg);
+    ALOGI("ndp_cfg: qos_cfg=%u\n", msg->ndp_cfg.qos_cfg);
+    ALOGI("dp app info len=%u\n", msg->app_info.ndp_app_info_len);
+    if (msg->app_info.ndp_app_info_len) {
+        prhex("dp app info=: ", (u8*)msg->app_info.ndp_app_info,
+                msg->app_info.ndp_app_info_len);
+    }
+    ALOGI("cipher_type=%u\n", msg->cipher_type);
+    ALOGI("key_info: key_type =%u\n", msg->key_info.key_type);
+    ALOGI("key_info: pmk info=%s\n", msg->key_info.body.pmk_info.pmk);
+    ALOGI("key_info: passphrase_info=%s\n", msg->key_info.body.passphrase_info.passphrase);
+    if (msg->service_name_len) {
+        ALOGI("service_name=%s\n", msg->service_name);
+    }
+    return WIFI_SUCCESS;
+}
+
+static int dump_NanDataPathIndicationResponse(NanDataPathIndicationResponse* msg)
+{
+    ALOGI("%s: Dump NanDataPathIndicationResponse msg:\n", __func__);
+
+    if (msg == NULL) {
+        ALOGE("Invalid msg\n");
+        return WIFI_ERROR_UNKNOWN;
+    }
+
+    ALOGI("ndp_instance_id=%d\n", msg->ndp_instance_id);
+    ALOGI("ndp_iface=%s\n", msg->ndp_iface);
+    ALOGI("ndp_cfg: security_cfg =%u\n", msg->ndp_cfg.security_cfg);
+    ALOGI("response code =%u\n", msg->rsp_code);
+    ALOGI("ndp_cfg: qos_cfg=%u\n", msg->ndp_cfg.qos_cfg);
+    ALOGI("dp app info len=%u\n", msg->app_info.ndp_app_info_len);
+    if (msg->app_info.ndp_app_info_len) {
+        prhex("dp app info=: ", (u8*)msg->app_info.ndp_app_info,
+                msg->app_info.ndp_app_info_len);
+    }
+    ALOGI("cipher_type=%u\n", msg->cipher_type);
+    ALOGI("key_info: key_type =%u\n", msg->key_info.key_type);
+    ALOGI("key_info: pmk info=%s\n", msg->key_info.body.pmk_info.pmk);
+    ALOGI("key_info: passphrase_info=%s\n", msg->key_info.body.passphrase_info.passphrase);
+    ALOGI("service_name_len=%u\n", msg->service_name_len);
+    if (msg->service_name_len) {
+        ALOGI("service_name=%s\n", msg->service_name);
+    }
+    return WIFI_SUCCESS;
+}
+#endif /* CONFIG_BRCM */
+
+void nan_reset_dbg_counters()
+{
+    memset(&counters, 0, sizeof(counters));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+wifi_error nan_enable_request(transaction_id id,
+        wifi_interface_handle iface, NanEnableRequest* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+    NanRequestType cmdType = NAN_REQUEST_ENABLE;
+
+    ALOGI("Enabling Nan, Handle = %p\n", handle);
+
+#ifdef CONFIG_BRCM
+    // check up nan enable params from Nan manager level
+    dump_NanEnableRequest(msg);
+#endif /* CONFIG_BRCM */
+    nan_reset_dbg_counters();
+    /* XXX: WAR posting async enable response */
+    //NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType);
+    NanMacControl *cmd = (NanMacControl*)(info.nan_mac_control);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    cmd->setType(cmdType);
+    cmd->setId(id);
+    cmd->setMsg((void *)msg);
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+    }
+    //cmd->releaseRef();
+    return ret;
+}
+
+void nan_dump_dbg_counters()
+{
+    ALOGI("Num Data Path Requests %d\n", counters.dp_req);
+    ALOGI("Num Data Path Responses %d\n", counters.dp_resp);
+    ALOGI("Num Data Path Confirms %d\n", counters.dp_confirm_evt);
+    ALOGI("Num Data Path Request Events %d\n", counters.dp_req_evt);
+    ALOGI("Num Transmit Requests %d\n", counters.transmit_req);
+    ALOGI("Num Followup Transmits Recvd %d\n", counters.transmit_recv);
+    ALOGI("Num Transmit Success %d\n", counters.transmit_txs);
+}
+
+wifi_error nan_disable_request(transaction_id id,
+        wifi_interface_handle iface)
+{
+    wifi_handle handle = getWifiHandle(iface);
+    NanRequestType cmdType = NAN_REQUEST_DISABLE;
+    wifi_error ret = WIFI_SUCCESS;
+
+    ALOGI("Disabling Nan, Handle = %p\n", handle);
+    NanMacControl *cmd = new NanMacControl(iface, id, NULL, cmdType);
+    NanMacControl *mac_prim = (NanMacControl*)(info.nan_mac_control);
+
+    if (id != NAN_MAC_INVALID_TRANSID) {
+        ALOGE("Disable NAN MAC transId= %d\n", id);
+        mac_prim->setId(id);
+    } else {
+        ALOGE("Invalid transId= %d cur= %d\n", id, mac_prim->getId());
+    }
+
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    nan_dump_dbg_counters();
+
+    ret = (wifi_error)cmd->cancel();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("cancel failed, error = %d\n", ret);
+    } else {
+        ALOGE("Deinitializing Nan Mac Control = %p\n", cmd);
+    }
+    cmd->releaseRef();
+    return ret;
+}
+
+wifi_error nan_publish_request(transaction_id id,
+        wifi_interface_handle iface, NanPublishRequest* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+
+    ALOGI("Publish Nan, halHandle = %p\n", handle);
+#ifdef CONFIG_BRCM
+    dump_NanPublishRequest(msg);
+#endif /* CONFIG_BRCM */
+
+    NanRequestType cmdType = NAN_REQUEST_PUBLISH;
+    NanDiscEnginePrimitive *cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+    return ret;
+}
+
+/* Function to send NAN request to the wifi driver */
+wifi_error nan_publish_cancel_request(transaction_id id,
+        wifi_interface_handle iface, NanPublishCancelRequest* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    NanDiscEnginePrimitive *cmd;
+    wifi_handle handle = getWifiHandle(iface);
+    NanRequestType cmdType = NAN_REQUEST_PUBLISH_CANCEL;
+
+    ALOGE("Cancellling publish request %d\n", msg->publish_id);
+    cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+    cmd->setInstId(msg->publish_id);
+    cmd->setType(cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+    return ret;
+}
+
+/* Function to send NAN request to the wifi driver */
+wifi_error nan_subscribe_request(transaction_id id,
+        wifi_interface_handle iface, NanSubscribeRequest* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+    ALOGI("Subscribe Nan, halHandle = %p handle[%d]\n", handle, msg->subscribe_id);
+    NanDiscEnginePrimitive *cmd;
+#ifdef CONFIG_BRCM
+    dump_NanSubscribeRequest(msg);
+#endif /* CONFIG_BRCM */
+
+    NanRequestType cmdType = NAN_REQUEST_SUBSCRIBE;
+    cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+    return ret;
+
+}
+
+/*  Function to send NAN request to the wifi driver.*/
+wifi_error nan_subscribe_cancel_request(transaction_id id,
+        wifi_interface_handle iface, NanSubscribeCancelRequest* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    NanDiscEnginePrimitive *cmd;
+    wifi_handle handle = getWifiHandle(iface);
+    NanRequestType cmdType = NAN_REQUEST_SUBSCRIBE_CANCEL;
+
+    ALOGE("creating new instance + %d\n", msg->subscribe_id);
+    cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+    cmd->setInstId(msg->subscribe_id);
+    cmd->setType(cmdType);
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+
+    return ret;
+}
+
+#ifdef NAN_CLUSTER_MERGE
+/*  Function to send NAN cluster merge enable/disable request to the wifi driver.*/
+wifi_error nan_enable_cluster_merge_request(transaction_id id,
+        wifi_interface_handle iface, NanEnableMergeRequest* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+    NanRequestType cmdType = NAN_REQUEST_ENABLE_MERGE;
+
+    NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    cmd->setType(cmdType);
+    cmd->setId(id);
+    cmd->setMsg((void *)msg);
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s :enable nan cluster merge failed in start, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+
+    return ret;
+}
+#endif /* NAN_CLUSTER_MERGE */
+
+/*  Function to send nan transmit followup Request to the wifi driver.*/
+wifi_error nan_transmit_followup_request(transaction_id id,
+        wifi_interface_handle iface, NanTransmitFollowupRequest* msg)
+{
+    NanDiscEnginePrimitive *cmd = NULL;
+    wifi_handle handle = getWifiHandle(iface);
+    NanRequestType cmdType = NAN_REQUEST_TRANSMIT_FOLLOWUP;
+    wifi_error ret = WIFI_SUCCESS;
+
+#ifdef CONFIG_BRCM
+    dump_NanTransmitFollowupRequest(msg);
+#endif /* CONFIG_BRCM */
+    counters.transmit_req++;
+    cmd = new NanDiscEnginePrimitive(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    cmd->setTransactionId(id);
+
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+    return ret;
+}
+
+/* Function to send NAN statistics request to the wifi driver */
+wifi_error nan_stats_request(transaction_id id,
+        wifi_interface_handle iface, NanStatsRequest* msg)
+{
+    wifi_handle handle = getWifiHandle(iface);
+
+    ALOGI("Nan Stats, halHandle = %p", handle);
+    NanRequestType cmdType = NAN_REQUEST_STATS;
+
+#ifdef NOT_SUPPORTED
+    wifi_error ret = WIFI_SUCCESS;
+    NanCommand *cmd = new NanCommand(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+    return ret;
+#else
+    return WIFI_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+/* Function to send NAN configuration request to the wifi driver */
+wifi_error nan_config_request(transaction_id id,
+        wifi_interface_handle iface, NanConfigRequest* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+    NanRequestType cmdType = NAN_REQUEST_CONFIG;
+
+    ALOGI("Configuring Nan, halHandle = %p\n", handle);
+
+#ifdef CONFIG_BRCM
+    /* check up nan config params from Nan manager level */
+    dump_NanConfigRequestRequest(msg);
+#endif /* CONFIG_BRCM */
+
+    NanMacControl *cmd = new NanMacControl(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    cmd->setType(cmdType);
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("start failed, error = %d\n", ret);
+    } else {
+        ALOGE("Initializing Nan Mac Control = %p\n", cmd);
+    }
+    cmd->releaseRef();
+    return ret;
+}
+
+/* Function to send NAN request to the wifi driver */
+wifi_error nan_tca_request(transaction_id id,
+        wifi_interface_handle iface, NanTCARequest* msg)
+{
+    wifi_handle handle = getWifiHandle(iface);
+
+    ALOGI("Nan TCA, halHandle = %p", handle);
+    NanRequestType cmdType = NAN_REQUEST_TCA;
+
+#ifdef NOT_SUPPORTED
+    wifi_error ret = WIFI_SUCCESS;
+    NanCommand *cmd = new NanCommand(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+    return ret;
+#else
+    return WIFI_ERROR_NOT_SUPPORTED;
+#endif
+}
+
+wifi_error nan_beacon_sdf_payload_request(transaction_id id,
+        wifi_interface_handle iface, NanBeaconSdfPayloadRequest* msg)
+{
+    ALOGI("Nan Beacon Sdf Payload Request");
+    return WIFI_ERROR_NOT_SUPPORTED;
+}
+
+wifi_error nan_get_capabilities(transaction_id id, wifi_interface_handle iface)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+    ALOGI("Get Nan Capabilties, id=%d, halHandle=%p\n", id, handle);
+
+    NanRequestType cmdType = NAN_REQUEST_GET_CAPABILTIES;
+    NanDiscEnginePrimitive *cmd = new NanDiscEnginePrimitive(iface, id, NULL, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+    return ret;
+}
+wifi_error nan_check_dhd_hal_version(wifi_interface_handle iface,
+        wifi_handle handle)
+{
+    NanRequestType cmdType = NAN_VERSION_INFO;
+    NanMacControl *cmd = new NanMacControl(iface, 0, NULL, cmdType);
+    wifi_error ret = WIFI_SUCCESS;
+    u32 version;
+
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    cmd->setType(cmdType);
+
+    ret = (wifi_error)cmd->start();
+    if (ret != WIFI_SUCCESS) {
+        ALOGI("\nVersion subcmd failed ret = %x\n", ret);
+        ret = WIFI_ERROR_NOT_SUPPORTED;
+        goto done;
+    }
+    version = cmd->getVersion();
+    /* check if version handled..can support multiple versions */
+    if (version == NAN_HAL_VERSION_1) {
+        ALOGI("\nGot the supported version %d\n", version);
+        current_dhd_hal_ver = version;
+        ret = WIFI_SUCCESS;
+        goto done;
+    } else {
+        ALOGI("\nGot the unsupported version %d\n", version);
+        ret = WIFI_ERROR_NOT_SUPPORTED;
+        goto done;
+    }
+done:
+    cmd->releaseRef();
+    return ret;
+}
+wifi_error nan_deinit_handler()
+{
+    if (info.nan_mac_control) {
+        /* register for Nan vendor events with info mac class*/
+        NanMacControl *cmd_event = (NanMacControl*)(info.nan_mac_control);
+        cmd_event->unRegisterNanVendorEvents();
+        delete (NanMacControl*)info.nan_mac_control;
+        info.nan_mac_control = NULL;
+    }
+    if (info.nan_disc_control) {
+        delete (NanDiscEnginePrimitive*)info.nan_disc_control;
+        info.nan_disc_control = NULL;
+    }
+    if (info.nan_dp_control) {
+        delete (NanDataPathPrimitive*)info.nan_dp_control;
+        info.nan_dp_control = NULL;
+    }
+    if (NAN_HANDLE(info)) {
+        delete GET_NAN_HANDLE(info);
+        NAN_HANDLE(info) = NULL;
+    }
+    return WIFI_SUCCESS;
+}
+wifi_error nan_register_handler(wifi_interface_handle iface,
+        NanCallbackHandler handlers)
+{
+    wifi_handle handle = getWifiHandle(iface);
+    if (NAN_HANDLE(info)) {
+        /* cleanup and re-register */
+        nan_deinit_handler();
+    }
+    ALOGI("\nChecking version compat\n");
+    /* checking version compat b/w DHD and HAL */
+    if (nan_check_dhd_hal_version(iface, handle) != WIFI_SUCCESS) {
+        ALOGE("\n Get version failed..check DHD\n");
+        return WIFI_ERROR_NOT_SUPPORTED;
+    }
+    memset(&info, 0, sizeof(info));
+    NAN_HANDLE(info) = new NanHandle(handle, handlers);
+    info.nan_mac_control =
+        (void*)new NanMacControl(iface, 0, NULL, NAN_REQUEST_LAST);
+    NULL_CHECK_RETURN(info.nan_mac_control, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    info.nan_disc_control =
+        (void*)new NanDiscEnginePrimitive(iface, 0, NULL, NAN_REQUEST_LAST);
+    NULL_CHECK_RETURN(info.nan_disc_control, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    info.nan_dp_control =
+        (void*)new NanDataPathPrimitive(iface, 0, NULL, NAN_REQUEST_LAST);
+    NULL_CHECK_RETURN(info.nan_dp_control, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    /* register for Nan vendor events with info mac class*/
+    NanMacControl *cmd_event = (NanMacControl*)(info.nan_mac_control);
+    cmd_event->registerNanVendorEvents();
+    return WIFI_SUCCESS;
+}
+
+wifi_error nan_get_version(wifi_handle handle, NanVersion* version)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    if (version) {
+        *version = (NAN_MAJOR_REL_VERSION << 16 | NAN_MINOR_REL_VERSION << 8 |
+                NAN_PATCH_REL_VERSION);
+    } else {
+        ret = WIFI_ERROR_INVALID_ARGS;
+    }
+
+    return ret;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+class NanEventCap : public WifiCommand
+{
+    public:
+        NanEventCap(wifi_interface_handle iface, int id)
+            : WifiCommand("NanCommand", iface, id)
+        {}
+
+        int start()
+        {
+            registerNanVendorEvents();
+            return WIFI_SUCCESS;
+        }
+
+        int handleResponse(WifiEvent& reply) {
+            return NL_SKIP;
+        }
+        void unRegisterNanVendorEvents()
+        {
+            int i = 0;
+            for (i = NAN_EVENT_ENABLED; i <= NAN_EVENT_DATA_END; i++) {
+                unregisterVendorHandler(GOOGLE_OUI, i);
+            }
+            unregisterVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+        }
+        void registerNanVendorEvents()
+        {
+            int i = 0;
+            for (i = NAN_EVENT_ENABLED; i <= NAN_EVENT_DATA_END; i++) {
+                registerVendorHandler(GOOGLE_OUI, i);
+            }
+            registerVendorHandler(GOOGLE_OUI, NAN_ASYNC_RESPONSE_DISABLED);
+        }
+
+        int handleEvent(WifiEvent& event) {
+            int cmd = event.get_vendor_subcmd();
+            u16 attr_type;
+            nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+
+            switch(cmd) {
+                case NAN_EVENT_DE_EVENT: {
+                    u16 attr_type;
+                    NanDiscEngEventInd de_event;
+                    memset(&de_event, 0, sizeof(NanDiscEngEventInd));
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+                        if (attr_type == NAN_ATTRIBUTE_CLUSTER_ID) {
+                            memcpy(&de_event.data.cluster.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+                            ALOGI("cluster id = " MACSTR "\n", MAC2STR(de_event.data.cluster.addr));
+                        } else if (attr_type == NAN_ATTRIBUTE_ENABLE_STATUS) {
+                            ALOGI("nan enable status = %u\n", it.get_u16());
+                        } else if (attr_type == NAN_ATTRIBUTE_JOIN_STATUS) {
+                            ALOGI("nan joined status = %u\n", it.get_u16());
+                        } else if (attr_type == NAN_ATTRIBUTE_DE_EVENT_TYPE) {
+                            u8 de_type = it.get_u8();
+                            ALOGI("nan de event type = %u\n", de_type);
+                            if (de_type == NAN_EVENT_IFACE) {
+                                de_event.event_type = NAN_EVENT_ID_DISC_MAC_ADDR;
+                                ALOGI("received NAN_EVENT_ID_DISC_MAC_ADDR event\n");
+                            } else if (de_type == NAN_EVENT_START) {
+                                de_event.event_type = NAN_EVENT_ID_STARTED_CLUSTER;
+                                ALOGI("received NAN cluster started event\n");
+                            } else if (de_type == NAN_EVENT_JOIN) {
+                                /* To be deprecated */
+                                de_event.event_type = NAN_EVENT_ID_JOINED_CLUSTER;
+                                ALOGI("received join event\n");
+                            } else if (de_type == NAN_EVENT_ROLE_CHANGE) {
+                                ALOGI("received device role change event\n");
+                            } else if (de_type == NAN_EVENT_MERGE) {
+                                ALOGI("received Merge Event\n");
+                            } else {
+                                ALOGI("received unknown DE event, [%d]\n", de_type);
+                            }
+                        } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                            memcpy(&de_event.data.cluster.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+                            memcpy(mNmi, it.get_data(), NAN_MAC_ADDR_LEN);
+                            ALOGI("Primary discovery mac address = " MACSTR "\n",
+                                    MAC2STR(mNmi));
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventDiscEngEvent(&de_event);
+                    break;
+                }
+                case NAN_EVENT_DISABLED: {
+                    ALOGI("Received NAN_EVENT_DISABLED\n");
+                    NanDisabledInd disabled_ind;
+                    memset(&disabled_ind, 0, sizeof(NanDisabledInd));
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+                        if (attr_type == NAN_ATTRIBUTE_STATUS) {
+                            disabled_ind.reason = (NanStatusType)it.get_u8();
+                            ALOGI("Nan Disable:status %u", disabled_ind.reason);
+                        } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+                            memcpy(disabled_ind.nan_reason, it.get_data(),
+                                    sizeof(disabled_ind.nan_reason));
+                            ALOGI("nan disable reason: %s", disabled_ind.nan_reason);
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventDisabled(&disabled_ind);
+                    unRegisterNanVendorEvents();
+                    break;
+                }
+                case NAN_EVENT_PUBLISH_TERMINATED: {
+                    ALOGI("Received NAN_EVENT_PUBLISH_TERMINATED\n");
+                    NanPublishTerminatedInd pub_term_event;
+                    memset(&pub_term_event, 0, sizeof(NanPublishTerminatedInd));
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+
+                        if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+                            pub_term_event.publish_id = it.get_u16();
+                            ALOGI("pub id %u", pub_term_event.publish_id);
+                        } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+                            pub_term_event.reason = (NanStatusType)it.get_u8();
+                            ALOGI("pub termination status %u", pub_term_event.reason);
+                        } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+                            memcpy(pub_term_event.nan_reason, it.get_data(),
+                                    sizeof(pub_term_event.nan_reason));
+                            ALOGI("Pub termination nan reason: %s", pub_term_event.nan_reason);
+                        } else {
+                            ALOGE("Unknown attr\n");
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventPublishTerminated(&pub_term_event);
+                    break;
+                }
+                case NAN_EVENT_SUBSCRIBE_MATCH: {
+                    NanMatchInd subscribe_event;
+                    memset(&subscribe_event, 0, sizeof(NanMatchInd));
+                    ALOGI("Received NAN_EVENT_SUBSCRIBE_MATCH\n");
+
+                    /* By default FW is unable to cache this match */
+                    subscribe_event.out_of_resource_flag = true;
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+
+                        if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+                            ALOGI("sub id: %u", it.get_u16());
+                            subscribe_event.publish_subscribe_id = it.get_u16();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+                            ALOGI("pub id %u", it.get_u32());
+                            subscribe_event.requestor_instance_id = it.get_u32();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                            memcpy(subscribe_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+                            ALOGI("publisher mac: " MACSTR, MAC2STR(subscribe_event.addr));
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                            ALOGI("svc length: %d", it.get_u16());
+                            subscribe_event.service_specific_info_len = it.get_u16();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                            memcpy(subscribe_event.service_specific_info, it.get_data(),
+                                    subscribe_event.service_specific_info_len);
+                            subscribe_event.service_specific_info
+                                [subscribe_event.service_specific_info_len] = '\0';
+                            ALOGI("service info: %s", subscribe_event.service_specific_info);
+
+                        } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER_LEN) {
+                            ALOGI("sdf match filter length: %d", subscribe_event.sdf_match_filter_len);
+                            subscribe_event.sdf_match_filter_len = it.get_u16();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_TX_MATCH_FILTER) {
+                            memcpy(subscribe_event.sdf_match_filter, it.get_data(),
+                                    subscribe_event.sdf_match_filter_len);
+                            subscribe_event.sdf_match_filter
+                                [subscribe_event.sdf_match_filter_len] = '\0';
+                            ALOGI("sdf match filter: %s", subscribe_event.sdf_match_filter);
+                        } else if (attr_type == NAN_ATTRIBUTE_CIPHER_SUITE_TYPE) {
+                            ALOGI("Peer Cipher suite type: %u", it.get_u8());
+                            subscribe_event.peer_cipher_type = it.get_u8();
+                        } else if (attr_type == NAN_ATTRIBUTE_SCID_LEN) {
+                            ALOGI("scid length %d", it.get_u32());
+                            subscribe_event.scid_len= it.get_u32();
+                        } else if (attr_type == NAN_ATTRIBUTE_SCID) {
+                            memcpy(subscribe_event.scid, it.get_data(),
+                                    subscribe_event.scid_len);
+                            subscribe_event.scid
+                                [subscribe_event.scid_len] = '\0';
+                            ALOGI("scid: %s", subscribe_event.scid);
+                        } else if (attr_type == NAN_ATTRIBUTE_RANGING_INDICATION) {
+                            subscribe_event.range_info.ranging_event_type = it.get_u32();
+                            ALOGI("ranging indication %d", it.get_u32());
+                        } else if (attr_type == NAN_ATTRIBUTE_RANGING_RESULT) {
+                            subscribe_event.range_info.range_measurement_mm = it.get_u32();
+                            ALOGI("ranging result %d", it.get_u32());
+                        } else if (attr_type == NAN_ATTRIBUTE_RSSI_PROXIMITY) {
+                            subscribe_event.rssi_value = it.get_u8();
+                            ALOGI("rssi value : %u", it.get_u8());
+                        } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+                            ALOGI("sdea svc length %d", it.get_u16());
+                            subscribe_event.sdea_service_specific_info_len = it.get_u16();
+                        } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
+                            memcpy(subscribe_event.sdea_service_specific_info, it.get_data(),
+                                    subscribe_event.sdea_service_specific_info_len);
+                            subscribe_event.sdea_service_specific_info
+                                [subscribe_event.sdea_service_specific_info_len] = '\0';
+                            ALOGI("sdea service info: %s", subscribe_event.sdea_service_specific_info);
+                        } else if (attr_type == NAN_ATTRIBUTE_MATCH_OCCURRED_FLAG) {
+                            ALOGI("match occurred flag: %u", it.get_u8());
+                            subscribe_event.match_occured_flag = it.get_u8();
+                        } else if (attr_type == NAN_ATTRIBUTE_OUT_OF_RESOURCE_FLAG) {
+                            ALOGI("Out of resource flag: %u", it.get_u8());
+                            subscribe_event.out_of_resource_flag = it.get_u8();
+                        } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_CONFIG_DP) {
+                            ALOGI("Peer config for data path needed: %u", it.get_u8());
+                            subscribe_event.peer_sdea_params.config_nan_data_path = it.get_u8();
+                        } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_DP_TYPE) {
+                            ALOGI("Data Path type: %u", it.get_u8());
+                            subscribe_event.peer_sdea_params.ndp_type = (NdpType)it.get_u8();
+                        } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_SECURITY) {
+                            ALOGI("Security configuration: %u", it.get_u8());
+                            subscribe_event.peer_sdea_params.security_cfg =
+                                (NanDataPathSecurityCfgStatus)it.get_u8();
+                        } else if (attr_type == NAN_ATTRIBUTE_SDE_CONTROL_RANGE_SUPPORT) {
+                            ALOGI("Ranging report state: %u", it.get_u8());
+                            subscribe_event.peer_sdea_params.range_report = (NanRangeReport)it.get_u8();
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventMatch(&subscribe_event);
+                    break;
+                }
+                case NAN_EVENT_SUBSCRIBE_UNMATCH: {
+                    ALOGI("Received NAN_EVENT_SUBSCRIBE_UNMATCH\n");
+                    ALOGE("%s: Not applicable yet\n", __func__);
+                    break;
+                }
+                case NAN_EVENT_SUBSCRIBE_TERMINATED: {
+                    NanSubscribeTerminatedInd sub_term_event;
+                    memset(&sub_term_event, 0, sizeof(NanSubscribeTerminatedInd));
+                    ALOGI("Received NAN_EVENT_SUBSCRIBE_TERMINATED\n");
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+
+                        if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+                            sub_term_event.subscribe_id = it.get_u16();
+                            ALOGI("sub id: %u", sub_term_event.subscribe_id);
+                        } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+                            sub_term_event.reason = (NanStatusType)it.get_u8();
+                            ALOGI("sub termination status %u", sub_term_event.reason);
+                        } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+                            memcpy(sub_term_event.nan_reason, it.get_data(),
+                                    sizeof(sub_term_event.nan_reason));
+                            ALOGI("sub termination nan reason: %s", sub_term_event.nan_reason);
+                        } else {
+                            ALOGE("Unknown attr: %u\n", attr_type);
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventSubscribeTerminated(&sub_term_event);
+                    break;
+                }
+                case NAN_EVENT_FOLLOWUP: {
+                    NanFollowupInd followup_event;
+                    memset(&followup_event, 0, sizeof(NanFollowupInd));
+                    ALOGI("Received NAN_EVENT_FOLLOWUP\n");
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+
+                        if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                            memcpy(followup_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+
+                        } else if (attr_type == NAN_ATTRIBUTE_PEER_ID) {
+                            followup_event.publish_subscribe_id = it.get_u16();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_INST_ID) {
+                            followup_event.requestor_instance_id = it.get_u32();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                            followup_event.service_specific_info_len = it.get_u16();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                            memcpy(followup_event.service_specific_info, it.get_data(),
+                                    followup_event.service_specific_info_len);
+                            followup_event.service_specific_info[followup_event.service_specific_info_len] =
+                                '\0';
+                        } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+                            ALOGI("sdea svc length %d", it.get_u16());
+                            followup_event.sdea_service_specific_info_len = it.get_u16();
+                        } else if (attr_type == NAN_ATTRIBUTE_SDEA_SERVICE_SPECIFIC_INFO) {
+                            memcpy(followup_event.sdea_service_specific_info, it.get_data(),
+                                    followup_event.sdea_service_specific_info_len);
+                            followup_event.sdea_service_specific_info[followup_event.sdea_service_specific_info_len] = '\0';
+                            ALOGI("sdea service info: %s", followup_event.sdea_service_specific_info);
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventFollowup(&followup_event);
+                    break;
+                }
+                case NAN_EVENT_SDF: {
+                    ALOGI("Received NAN_EVENT_SDF:\n");
+                    NanBeaconSdfPayloadInd sdfInd;
+                    memset(&sdfInd, 0, sizeof(sdfInd));
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+
+                        if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                            sdfInd.data.frame_len = it.get_u32();
+                            if (sdfInd.data.frame_len > NAN_MAX_FRAME_DATA_LEN) {
+                                sdfInd.data.frame_len = NAN_MAX_FRAME_DATA_LEN;
+                            }
+                            ALOGI("Received NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN: 0x%x(%d)\n",
+                                    sdfInd.data.frame_len, sdfInd.data.frame_len);
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                            ALOGI("Received NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO\n");
+                            memcpy(&sdfInd.data.frame_data, it.get_data(), sdfInd.data.frame_len);
+                            prhex("sdfInd.data.frame_data: ", (u8*)sdfInd.data.frame_data,
+                                    sdfInd.data.frame_len);
+                        }
+                    }
+                    GET_NAN_HANDLE(info)->mHandlers.EventBeaconSdfPayload(&sdfInd);
+                    break;
+                }
+#ifdef NOT_YET
+                case NAN_EVENT_PUBLISH_REPLIED_IND: {
+                    ALOGI("Received NAN_EVENT_PUBLISH_REPLIED_IND\n");
+                    NanPublishRepliedInd pub_reply_event;
+                    memset(&pub_reply_event, 0, sizeof(pub_reply_event));
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+
+                        if (attr_type == NAN_ATTRIBUTE_SUBSCRIBE_ID) {
+                            ALOGI("sub id: %u", it.get_u32());
+                            pub_reply_event.requestor_instance_id = it.get_u32();
+                        } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                            memcpy(pub_reply_event.addr, it.get_data(), NAN_MAC_ADDR_LEN);
+                            ALOGI("Subscriber mac: " MACSTR, MAC2STR(pub_reply_event.addr));
+                        } else if (attr_type == NAN_ATTRIBUTE_RSSI_PROXIMITY) {
+                            pub_reply_event.rssi_value = it.get_u8();
+                            ALOGI("Received rssi value : %u", it.get_u8());
+                        }
+                    }
+                    GET_NAN_HANDLE(info)->mHandlers.EventPublishReplied(&pub_reply_event);
+                    break;
+                }
+#endif /* NOT_YET */
+                case NAN_EVENT_TCA: {
+                    ALOGI("Received NAN_EVENT_TCA\n");
+                    //GET_NAN_HANDLE(info)->mHandlers.EventTca(&sdfPayload);
+                    break;
+                }
+                case NAN_EVENT_DATA_REQUEST: {
+                    ALOGI("Received NAN_EVENT_DATA_REQUEST_INDICATION\n");
+                    NanDataPathRequestInd ndp_request_event;
+                    memset(&ndp_request_event, 0, sizeof(NanDataPathRequestInd));
+                    u16 ndp_ind_app_info_len = 0;
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+
+                        if (attr_type == NAN_ATTRIBUTE_PUBLISH_ID) {
+                            ALOGI("publish_id: %u\n", it.get_u16());
+                            ndp_request_event.service_instance_id = it.get_u16();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_MAC_ADDR) {
+                            memcpy(ndp_request_event.peer_disc_mac_addr,
+                                    it.get_data(), NAN_MAC_ADDR_LEN);
+                            ALOGI("Discovery MAC addr of the peer/initiator: " MACSTR "\n",
+                                    MAC2STR(ndp_request_event.peer_disc_mac_addr));
+
+                        } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+                            ALOGI("ndp id: %u\n", it.get_u32());
+                            ndp_request_event.ndp_instance_id = it.get_u32();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SECURITY) {
+                            ALOGI("security: %u\n", (NanDataPathSecurityCfgStatus) it.get_u8());
+                            ndp_request_event.ndp_cfg.security_cfg =
+                                (NanDataPathSecurityCfgStatus)it.get_u8();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_QOS) {
+                            ALOGI("QoS: %u", (NanDataPathQosCfg)it.get_u8());
+                            ndp_request_event.ndp_cfg.qos_cfg = (NanDataPathQosCfg)it.get_u8();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                            ALOGI("service info len: %d\n", it.get_u16());
+                            ndp_ind_app_info_len = it.get_u16();
+                            ndp_request_event.app_info.ndp_app_info_len = ndp_ind_app_info_len;
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                            memcpy(ndp_request_event.app_info.ndp_app_info,
+                                    it.get_data(), ndp_ind_app_info_len);
+                            ndp_request_event.app_info.ndp_app_info[ndp_ind_app_info_len] = '\0';
+                            ALOGI("service info: %s\n", ndp_request_event.app_info.ndp_app_info);
+
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventDataRequest(&ndp_request_event);
+                    break;
+                }
+                case NAN_EVENT_DATA_CONFIRMATION: {
+                    ALOGI("Received NAN_EVENT_DATA_CONFIRMATION\n");
+                    NanDataPathConfirmInd ndp_create_confirmation_event;
+                    memset(&ndp_create_confirmation_event, 0, sizeof(NanDataPathConfirmInd));
+                    u16 ndp_conf_app_info_len = 0;
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+
+                        if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+                            ALOGI("ndp id: %u", it.get_u32());
+                            ndp_create_confirmation_event.ndp_instance_id = it.get_u32();
+
+                        } else if (attr_type == NAN_ATTRIBUTE_PEER_NDI_MAC_ADDR) {
+                            memcpy(ndp_create_confirmation_event.peer_ndi_mac_addr,
+                                    it.get_data(), NAN_MAC_ADDR_LEN);
+                            ALOGI("NDI mac address of the peer: " MACSTR "\n",
+                                    MAC2STR(ndp_create_confirmation_event.peer_ndi_mac_addr));
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO_LEN) {
+                            ALOGI("service info string len: %d\n", it.get_u16());
+                            ndp_conf_app_info_len = it.get_u16();
+                            ndp_create_confirmation_event.app_info.ndp_app_info_len =
+                                ndp_conf_app_info_len;
+
+                        } else if (attr_type == NAN_ATTRIBUTE_SERVICE_SPECIFIC_INFO) {
+                            memcpy(ndp_create_confirmation_event.app_info.ndp_app_info, it.get_data(),
+                                    ndp_conf_app_info_len);
+                            ndp_create_confirmation_event.app_info.ndp_app_info[ndp_conf_app_info_len] =
+                                '\0';
+                            ALOGI("service info string: %s\n",
+                                    ndp_create_confirmation_event.app_info.ndp_app_info);
+
+                        } else if (attr_type == NAN_ATTRIBUTE_RSP_CODE) {
+                            ALOGI("response code %u\n", (NanDataPathResponseCode) it.get_u8());
+                            ndp_create_confirmation_event.rsp_code =
+                                (NanDataPathResponseCode)it.get_u8();
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventDataConfirm(&ndp_create_confirmation_event);
+                    break;
+                }
+                case NAN_EVENT_DATA_END: {
+                    ALOGI("Received NAN_EVENT_DATA_END\n");
+                    NanDataPathEndInd ndp_end_event;
+                    memset(&ndp_end_event, 0, sizeof(NanDataPathEndInd));
+                    u8 count = 0;
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+                        if (attr_type == NAN_ATTRIBUTE_INST_COUNT) {
+                            ALOGI("ndp count: %u\n", it.get_u8());
+                            ndp_end_event.num_ndp_instances = it.get_u8();
+                            count = it.get_u8();
+                        } else if (attr_type == NAN_ATTRIBUTE_NDP_ID) {
+                            ALOGI("count: %u\n", count);
+                            while (count) {
+                                ndp_end_event.ndp_instance_id[count-1] = it.get_u32();
+                                ALOGI("ndp id: %u\n", ndp_end_event.ndp_instance_id[count-1]);
+                                count -= 1;
+                            }
+                        } else {
+                            ALOGI("Unknown attr_type: %s\n", NanAttrToString(attr_type));
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventDataEnd(&ndp_end_event);
+                    break;
+                }
+                case NAN_EVENT_TRANSMIT_FOLLOWUP_IND: {
+                    ALOGI("Received NAN_EVENT_TRANSMIT_FOLLOWUP_IND\n");
+                    NanTransmitFollowupInd followup_ind;
+                    memset(&followup_ind, 0, sizeof(NanTransmitFollowupInd));
+
+                    for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+                        attr_type = it.get_type();
+                        if (attr_type == NAN_ATTRIBUTE_TRANSAC_ID) {
+                            followup_ind.id = it.get_u16();
+                        } else if (attr_type == NAN_ATTRIBUTE_STATUS) {
+                            followup_ind.reason = (NanStatusType)it.get_u8();
+                        } else if (attr_type == NAN_ATTRIBUTE_REASON) {
+                            memcpy(followup_ind.nan_reason, it.get_data(),
+                                    sizeof(followup_ind.nan_reason));
+                            ALOGI("nan transmit followup ind: reason: %s", followup_ind.nan_reason);
+                        }
+                    }
+
+                    GET_NAN_HANDLE(info)->mHandlers.EventTransmitFollowup(&followup_ind);
+                    break;
+                }
+                case NAN_EVENT_UNKNOWN:
+                    ALOGI("Received NAN_EVENT_UNKNOWN\n");
+                    break;
+            } // end-of-switch
+            return NL_SKIP;
+        }
+};
+
+/* To see event prints in console */
+wifi_error nan_event_check_request(transaction_id id, wifi_interface_handle iface)
+{
+    wifi_handle handle = getWifiHandle(iface);
+    NanEventCap *cmd = new NanEventCap(iface, id);
+    if (cmd == NULL) {
+        return WIFI_ERROR_NOT_SUPPORTED;
+    }
+    return (wifi_error)cmd->start();
+}
+
+/* Create NAN Data Interface */
+wifi_error nan_data_interface_create(transaction_id id,
+        wifi_interface_handle iface, char* iface_name)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+    NAN_DBG_ENTER();
+
+    NanRequestType cmdType = NAN_DATA_PATH_IFACE_CREATE;
+    NanDataPathPrimitive *cmd =
+        new NanDataPathPrimitive(iface, id, (void *)iface_name, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    ret = (wifi_error)cmd->open();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+
+    NAN_DBG_EXIT();
+    return ret;
+}
+
+/* Delete NAN Data Interface */
+wifi_error nan_data_interface_delete(transaction_id id,
+        wifi_interface_handle iface, char* iface_name)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+    NAN_DBG_ENTER();
+
+    NanRequestType cmdType = NAN_DATA_PATH_IFACE_DELETE;
+    NanDataPathPrimitive *cmd =
+        new NanDataPathPrimitive(iface, id, (void *)iface_name, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    ret = (wifi_error)cmd->open();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+
+    NAN_DBG_EXIT();
+    return ret;
+}
+
+/* Initiate a NDP session: Initiator */
+wifi_error nan_data_request_initiator(transaction_id id,
+        wifi_interface_handle iface, NanDataPathInitiatorRequest* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+
+    NAN_DBG_ENTER();
+    NanRequestType cmdType;
+    NanDataPathPrimitive *cmd = NULL;
+
+#ifdef CONFIG_BRCM
+    dump_NanDataPathInitiatorRequest(msg);
+#endif /* CONFIG_BRCM */
+    counters.dp_req++;
+    if (msg->service_name_len) {
+        if (strncmp(NAN_OOB_INTEROP_SVC_NAME,
+                    (char*)msg->service_name, msg->service_name_len) == 0) {
+            ALOGI("Use Hardcoded svc_hash\n");
+            msg->service_name_len = NAN_SVC_HASH_SIZE;
+            memcpy(msg->service_name, NAN_OOB_INTEROP_SVC_HASH, NAN_SVC_HASH_SIZE);
+        } else {
+            u8 svc_hash[NAN_SVC_HASH_SIZE];
+
+            ret = (wifi_error)get_svc_hash(msg->service_name, msg->service_name_len,
+                    svc_hash, NAN_SVC_HASH_SIZE);
+            if (ret < 0) {
+                ALOGE("%s: Failed to get hashed svc name\n", __func__);
+                goto done;
+            }
+
+            ALOGI("Created svc_hash\n");
+            msg->service_name_len = NAN_SVC_HASH_SIZE;
+            memcpy(msg->service_name, svc_hash, msg->service_name_len);
+        }
+    } else if (msg->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+        NanDataPathSecInfoRequest msg_sec_info;
+        if (msg->requestor_instance_id == 0) {
+            ALOGE("Invalid Pub ID = %d, Mandatory param is missing\n", msg->requestor_instance_id);
+            ret = WIFI_ERROR_INVALID_ARGS;
+            goto done;
+        } else {
+            ALOGI("Pub ID = %d, Mandatory param is present\n", msg->requestor_instance_id);
+        }
+        if (ETHER_ISNULLADDR(msg->peer_disc_mac_addr)) {
+            ALOGE("Invalid Pub NMI, Mandatory param is missing\n");
+            ret = WIFI_ERROR_INVALID_ARGS;
+            goto done;
+        }
+
+        msg_sec_info.requestor_instance_id = msg->requestor_instance_id;
+        memcpy(msg_sec_info.peer_disc_mac_addr, msg->peer_disc_mac_addr, NAN_MAC_ADDR_LEN);
+        msg_sec_info.ndp_instance_id = 0;
+        cmdType = NAN_DATA_PATH_SEC_INFO;
+        cmd = new NanDataPathPrimitive(iface, id, (void *)&msg_sec_info, cmdType);
+        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+        ret = (wifi_error)cmd->open();
+        if (ret != WIFI_SUCCESS) {
+            ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+            goto done;
+        }
+        memcpy(msg->service_name, cmd->mSvcHash, NAN_SVC_HASH_SIZE);
+    }
+    /* free old command */
+    if (cmd) {
+        cmd->releaseRef();
+    }
+    cmdType = NAN_DATA_PATH_INIT_REQUEST;
+    cmd = new NanDataPathPrimitive(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    ret = (wifi_error)cmd->open();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+        goto done;
+    }
+done:
+    if (cmd) {
+        cmd->releaseRef();
+    }
+
+    NAN_DBG_EXIT();
+    return ret;
+}
+
+/* Response to a data indication received corresponding to a NDP session.
+ * An indication is received with a data request and the responder will send a data response
+ */
+wifi_error nan_data_indication_response(transaction_id id,
+        wifi_interface_handle iface, NanDataPathIndicationResponse* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    wifi_handle handle = getWifiHandle(iface);
+    NAN_DBG_ENTER();
+    NanRequestType cmdType;
+    u8 pub_nmi[NAN_MAC_ADDR_LEN] = {0};
+    NanDataPathPrimitive *cmd = NULL;
+
+#ifdef CONFIG_BRCM
+    dump_NanDataPathIndicationResponse(msg);
+#endif /* CONFIG_BRCM */
+    counters.dp_resp++;
+    if (msg->service_name_len) {
+        if (strncmp(NAN_OOB_INTEROP_SVC_NAME,
+                    (char*)msg->service_name, msg->service_name_len) == 0) {
+            ALOGI("Use Hardcoded svc_hash\n");
+            msg->service_name_len = NAN_SVC_HASH_SIZE;
+            memcpy(msg->service_name, NAN_OOB_INTEROP_SVC_HASH, NAN_SVC_HASH_SIZE);
+        } else {
+            u8 svc_hash[NAN_SVC_HASH_SIZE];
+
+            ret = (wifi_error)get_svc_hash(msg->service_name, msg->service_name_len,
+                    svc_hash, NAN_SVC_HASH_SIZE);
+            if (ret < 0) {
+                ALOGE("%s: Failed to get hashed svc name\n", __func__);
+                goto done;
+            }
+            ALOGI("Created svc_hash\n");
+            msg->service_name_len = NAN_SVC_HASH_SIZE;
+            memcpy(msg->service_name, svc_hash, msg->service_name_len);
+        }
+    }
+    if (msg->key_info.key_type == NAN_SECURITY_KEY_INPUT_PASSPHRASE) {
+        NanDataPathSecInfoRequest msg_sec_info;
+
+        if (msg->ndp_instance_id == 0) {
+            ALOGE("Invalid NDP ID, Mandatory info is not present\n");
+            ret = WIFI_ERROR_INVALID_ARGS;
+            goto done;
+        } else {
+            ALOGI("NDP ID = %d, Mandatory info is present\n", msg->ndp_instance_id);
+        }
+        msg_sec_info.ndp_instance_id = msg->ndp_instance_id;
+        msg_sec_info.requestor_instance_id = 0;
+        cmdType = NAN_DATA_PATH_SEC_INFO;
+        cmd = new NanDataPathPrimitive(iface, id, (void *)&msg_sec_info, cmdType);
+        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+        ret = (wifi_error)cmd->open();
+        if (ret != WIFI_SUCCESS) {
+            ALOGE("%s : failed in start, error = %d\n", __func__, ret);
+            goto done;
+        }
+
+        if (ETHER_ISNULLADDR(cmd->mPubNmi)) {
+            ALOGE("Invalid Pub NMI\n");
+            ret = WIFI_ERROR_INVALID_ARGS;
+            goto done;
+        }
+        memcpy(pub_nmi, cmd->mPubNmi, NAN_MAC_ADDR_LEN);
+
+        if (!msg->service_name_len) {
+            if (SVCHASH_ISNULL(cmd->mSvcHash)) {
+                ALOGE("Invalid svc_hash\n");
+                ret = WIFI_ERROR_INVALID_ARGS;
+                goto done;
+            }
+            memcpy(msg->service_name, cmd->mSvcHash, NAN_SVC_HASH_SIZE);
+        }
+    }
+    /* free old command */
+    if (cmd) {
+        cmd->releaseRef();
+    }
+    cmdType = NAN_DATA_PATH_IND_RESPONSE;
+    cmd = new NanDataPathPrimitive(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    memcpy(cmd->mPubNmi, pub_nmi, NAN_MAC_ADDR_LEN);
+    ret = (wifi_error)cmd->open();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+        goto done;
+    }
+
+done:
+    if (cmd) {
+        cmd->releaseRef();
+    }
+    NAN_DBG_EXIT();
+    return ret;
+}
+
+/* NDL termination request: from either Initiator/Responder */
+wifi_error nan_data_end(transaction_id id,
+        wifi_interface_handle iface, NanDataPathEndRequest* msg)
+{
+    wifi_error ret = WIFI_SUCCESS;
+    NanDataPathPrimitive *cmd;
+    wifi_handle handle = getWifiHandle(iface);
+    NanRequestType cmdType = NAN_DATA_PATH_END;
+    NAN_DBG_ENTER();
+
+    cmd = new NanDataPathPrimitive(iface, id, (void *)msg, cmdType);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+
+    ret = (wifi_error)cmd->open();
+    if (ret != WIFI_SUCCESS) {
+        ALOGE("%s : failed in open, error = %d\n", __func__, ret);
+    }
+    cmd->releaseRef();
+    NAN_DBG_EXIT();
+    return ret;
+}
diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp
old mode 100644
new mode 100755
index 508268e..258725c
--- a/bcmdhd/wifi_hal/wifi_hal.cpp
+++ b/bcmdhd/wifi_hal/wifi_hal.cpp
@@ -45,13 +45,14 @@
 #include "sync.h"
 
 #define LOG_TAG  "WifiHAL"
-
 #include <log/log.h>
 
 #include "wifi_hal.h"
 #include "common.h"
 #include "cpp_bindings.h"
 #include "rtt.h"
+#include "brcm_version.h"
+#include <stdio.h>
 /*
  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
@@ -69,6 +70,7 @@
  */
 #define POLL_DRIVER_DURATION_US (100000)
 #define POLL_DRIVER_MAX_TIME_MS (10000)
+#define EVENT_BUF_SIZE 2048
 
 static void internal_event_handler(wifi_handle handle, int events);
 static int internal_no_seq_check(nl_msg *msg, void *arg);
@@ -91,7 +93,11 @@
     ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
     ANDR_WIFI_ATTRIBUTE_NODFS_SET,
     ANDR_WIFI_ATTRIBUTE_COUNTRY,
-    ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE
+    ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE,
+    ANDR_WIFI_ATTRIBUTE_TCPACK_SUP_VALUE,
+    ANDR_WIFI_ATTRIBUTE_LATENCY_MODE,
+    ANDR_WIFI_ATTRIBUTE_RANDOM_MAC,
+    ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO
     // Add more attribute here
 } wifi_attr_t;
 
@@ -211,109 +217,218 @@
     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
+    fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
     fn->wifi_set_packet_filter = wifi_set_packet_filter;
+    fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
+    fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
+    fn->wifi_configure_roaming = wifi_configure_roaming;
+    fn->wifi_nan_register_handler = nan_register_handler;
+    fn->wifi_nan_enable_request = nan_enable_request;
+    fn->wifi_nan_disable_request = nan_disable_request;
+    fn->wifi_nan_publish_request = nan_publish_request;
+    fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
+    fn->wifi_nan_subscribe_request = nan_subscribe_request;
+    fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
+    fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
+    fn->wifi_nan_stats_request = nan_stats_request;
+    fn->wifi_nan_config_request = nan_config_request;
+    fn->wifi_nan_tca_request = nan_tca_request;
+    fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
+    fn->wifi_nan_get_version = nan_get_version;
+    fn->wifi_nan_get_capabilities = nan_get_capabilities;
+    fn->wifi_nan_data_interface_create = nan_data_interface_create;
+    fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
+    fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
+    fn->wifi_nan_data_indication_response = nan_data_indication_response;
+    fn->wifi_nan_data_end = nan_data_end;
+    fn->wifi_set_latency_mode = wifi_set_latency_mode;
+#ifdef NAN_CLUSTER_MERGE
+    fn->wifi_nan_enable_merge_request = nan_enable_cluster_merge_request;
+#endif /* NAN_CLUSTER_MERGE */
+    fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
+    fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
+
     return WIFI_SUCCESS;
 }
 
-wifi_error wifi_initialize(wifi_handle *handle)
+hal_info *halInfo = NULL;
+wifi_error wifi_pre_initialize(void)
 {
     srand(getpid());
 
-    ALOGI("Initializing wifi");
-    hal_info *info = (hal_info *)malloc(sizeof(hal_info));
-    if (info == NULL) {
+    int numIfaceHandles = 0;
+    wifi_interface_handle *ifaceHandles = NULL;
+    wifi_interface_handle wlan0Handle;
+    wifi_error result = WIFI_SUCCESS;
+    wifi_handle handle;
+
+    ALOGE("wifi_pre_initialize");
+    ALOGE("--- HAL version: %s ---\n", HAL_VERSION);
+    halInfo = (hal_info *)malloc(sizeof(hal_info));
+    if (halInfo == NULL) {
         ALOGE("Could not allocate hal_info");
         return WIFI_ERROR_UNKNOWN;
     }
 
-    memset(info, 0, sizeof(*info));
+    memset(halInfo, 0, sizeof(*halInfo));
 
     ALOGI("Creating socket");
-    if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, halInfo->cleanup_socks) == -1) {
         ALOGE("Could not create cleanup sockets");
-        free(info);
+        free(halInfo);
         return WIFI_ERROR_UNKNOWN;
     }
 
     struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
     if (cmd_sock == NULL) {
         ALOGE("Could not create handle");
-        free(info);
+        free(halInfo);
         return WIFI_ERROR_UNKNOWN;
     }
 
+    /* Set the socket buffer size */
+    if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
+        ALOGE("Could not set size for cmd_sock: %s",
+               strerror(errno));
+    } else {
+        ALOGV("nl_socket_set_buffer_size successful for cmd_sock");
+    }
     struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
     if (event_sock == NULL) {
         ALOGE("Could not create handle");
         nl_socket_free(cmd_sock);
-        free(info);
+        free(halInfo);
         return WIFI_ERROR_UNKNOWN;
     }
 
+    /* Set the socket buffer size */
+    if (nl_socket_set_buffer_size(event_sock, (512*1024), 0) < 0) {
+        ALOGE("Could not set size for event_sock: %s",
+               strerror(errno));
+    } else {
+        ALOGV("nl_socket_set_buffer_size successful for event_sock");
+    }
+
     struct nl_cb *cb = nl_socket_get_cb(event_sock);
     if (cb == NULL) {
         ALOGE("Could not create handle");
         nl_socket_free(cmd_sock);
         nl_socket_free(event_sock);
-        free(info);
+        free(halInfo);
         return WIFI_ERROR_UNKNOWN;
     }
 
-    // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
-    nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
-    nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
+    nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, halInfo);
+    nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, halInfo);
     nl_cb_put(cb);
 
-    info->cmd_sock = cmd_sock;
-    info->event_sock = event_sock;
-    info->clean_up = false;
-    info->in_event_loop = false;
+    halInfo->cmd_sock = cmd_sock;
+    halInfo->event_sock = event_sock;
+    halInfo->clean_up = false;
+    halInfo->in_event_loop = false;
 
-    info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
-    info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
-    info->num_event_cb = 0;
+    halInfo->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
+    halInfo->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
+    halInfo->num_event_cb = 0;
 
-    info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
-    info->alloc_cmd = DEFAULT_CMD_SIZE;
-    info->num_cmd = 0;
+    halInfo->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
+    halInfo->alloc_cmd = DEFAULT_CMD_SIZE;
+    halInfo->num_cmd = 0;
 
-    info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
-    if (info->nl80211_family_id < 0) {
+    halInfo->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
+    if (halInfo->nl80211_family_id < 0) {
         ALOGE("Could not resolve nl80211 familty id");
         nl_socket_free(cmd_sock);
         nl_socket_free(event_sock);
-        free(info);
+        free(halInfo);
         return WIFI_ERROR_UNKNOWN;
     }
 
-    pthread_mutex_init(&info->cb_lock, NULL);
+    pthread_mutex_init(&halInfo->cb_lock, NULL);
+    InitResponseLock();
 
-    *handle = (wifi_handle) info;
+    handle = (wifi_handle) halInfo;
 
-    if (wifi_init_interfaces(*handle) != WIFI_SUCCESS) {
+    if (wifi_init_interfaces(handle) != WIFI_SUCCESS) {
         ALOGE("No wifi interface found");
         nl_socket_free(cmd_sock);
         nl_socket_free(event_sock);
-        pthread_mutex_destroy(&info->cb_lock);
-        free(info);
+        pthread_mutex_destroy(&halInfo->cb_lock);
+        free(halInfo);
         return WIFI_ERROR_NOT_AVAILABLE;
     }
 
-    if ((wifi_add_membership(*handle, "scan") < 0) ||
-        (wifi_add_membership(*handle, "mlme")  < 0) ||
-        (wifi_add_membership(*handle, "regulatory") < 0) ||
-        (wifi_add_membership(*handle, "vendor") < 0)) {
+    if ((wifi_add_membership(handle, "scan") < 0) ||
+            (wifi_add_membership(handle, "mlme")  < 0) ||
+            (wifi_add_membership(handle, "regulatory") < 0) ||
+            (wifi_add_membership(handle, "vendor") < 0)) {
         ALOGE("Add membership failed");
         nl_socket_free(cmd_sock);
         nl_socket_free(event_sock);
-        pthread_mutex_destroy(&info->cb_lock);
-        free(info);
+        pthread_mutex_destroy(&halInfo->cb_lock);
+        free(halInfo);
         return WIFI_ERROR_NOT_AVAILABLE;
     }
 
-    // ALOGI("Found %d interfaces", info->num_interfaces);
-
     ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
+    wlan0Handle = wifi_get_wlan_interface((wifi_handle)halInfo, ifaceHandles, numIfaceHandles);
+
+    if (wlan0Handle != NULL) {
+        ALOGE("Calling preInit");
+        if (!get_halutil_mode()) {
+            result = wifi_hal_preInit(wlan0Handle);
+            if (result != WIFI_SUCCESS) {
+                ALOGE("wifi_hal_preInit failed");
+            }
+        }
+    }
+
+    return WIFI_SUCCESS;
+}
+
+wifi_error wifi_initialize(wifi_handle *handle)
+{
+
+    int numIfaceHandles = 0;
+    wifi_interface_handle *ifaceHandles = NULL;
+    wifi_interface_handle wlan0Handle;
+    wifi_error result = WIFI_SUCCESS;
+
+    ALOGE("wifi_initialize");
+
+    if (halInfo == NULL) {
+        result = wifi_pre_initialize();
+        if (result != WIFI_SUCCESS) {
+            ALOGE("wifi_initialize wifi_pre_initialize failed");
+            return result;
+        } else {
+            ALOGE("wifi_initialize wifi_pre_initialize succeeded");
+        }
+    }
+
+    *handle = (wifi_handle) halInfo;
+    wlan0Handle = wifi_get_wlan_interface((wifi_handle)halInfo, ifaceHandles, numIfaceHandles);
+
+    if (wlan0Handle != NULL) {
+        ALOGE("Calling Hal_init");
+        if (!get_halutil_mode()) {
+            result = wifi_start_hal(wlan0Handle);
+            if (result != WIFI_SUCCESS) {
+                ALOGE("wifi_start_hal failed");
+            }
+#ifdef FILE_DUMP
+            else {
+                ALOGE("Calling start file dump");
+                result = wifi_start_file_dump(wlan0Handle);
+                if (result != WIFI_SUCCESS) {
+                    ALOGE("wifi_start_file_dump failed");
+                }
+            }
+#endif /* FILE_DUMP */
+        }
+    } else {
+        ALOGI("Not Calling set alert handler as global_iface is NULL");
+    }
     return WIFI_SUCCESS;
 }
 
@@ -327,6 +442,7 @@
     do {
         if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
             fclose(fd);
+            wifi_pre_initialize();
             return WIFI_SUCCESS;
         }
         usleep(POLL_DRIVER_DURATION_US);
@@ -360,7 +476,10 @@
     hal_info *info = getHalInfo(handle);
     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
 
+    ALOGI("internal clean up");
+
     if (info->cmd_sock != 0) {
+        ALOGI("cmd_sock non null. clean up");
         close(info->cleanup_socks[0]);
         close(info->cleanup_socks[1]);
         nl_socket_free(info->cmd_sock);
@@ -369,19 +488,57 @@
         info->event_sock = NULL;
     }
 
-    (*cleaned_up_handler)(handle);
+    if (cleaned_up_handler) {
+        ALOGI("cleanup_handler cb");
+        (*cleaned_up_handler)(handle);
+    } else {
+        ALOGI("!! clean up handler is null!!");
+    }
+    DestroyResponseLock();
     pthread_mutex_destroy(&info->cb_lock);
     free(info);
 
     ALOGI("Internal cleanup completed");
 }
+void wifi_internal_module_cleanup()
+{
+    nan_deinit_handler();
+}
 
 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
 {
     hal_info *info = getHalInfo(handle);
     char buf[64];
+    wifi_error result;
+
+    int numIfaceHandles = 0;
+    wifi_interface_handle *ifaceHandles = NULL;
+    wifi_interface_handle wlan0Handle;
 
     info->cleaned_up_handler = handler;
+
+    wlan0Handle = wifi_get_wlan_interface((wifi_handle) info, ifaceHandles, numIfaceHandles);
+
+    if (wlan0Handle != NULL) {
+        ALOGE("Calling hal cleanup");
+        if (!get_halutil_mode()) {
+            result = wifi_stop_hal(wlan0Handle);
+            if (result != WIFI_SUCCESS) {
+                ALOGE("wifi_stop_hal failed");
+            }
+        }
+
+#ifdef FILE_DUMP
+        ALOGE("Calling stop file dump");
+        result = wifi_stop_file_dump(wlan0Handle);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("wifi_stop_file_dump failed");
+        }
+#endif /* FILE_DUMP */
+    } else {
+        ALOGE("Not cleaning up hal as global_iface is NULL");
+    }
+
     if (TEMP_FAILURE_RETRY(write(info->cleanup_socks[0], "Exit", 4)) < 1) {
         // As a fallback set the cleanup flag to TRUE
         ALOGE("could not write to the cleanup socket");
@@ -402,16 +559,28 @@
         }
     }
     info->clean_up = true;
+    wifi_internal_module_cleanup();
+    ALOGI("wifi nan internal clean up done");
     pthread_mutex_lock(&info->cb_lock);
 
     int bad_commands = 0;
 
+    ALOGI("event_cb callbacks left: %d ", info->num_event_cb);
     for (int i = 0; i < info->num_event_cb; i++) {
+        ALOGI("event_cb cleanup. index:%d", i);
         cb_info *cbi = &(info->event_cb[i]);
+        if (!cbi) {
+            ALOGE("cbi null for index %d", i);
+            continue;
+        }
+        ALOGI("event_cb cleanup. vendor cmd:%d sub_cmd:%d", cbi->vendor_id, cbi->vendor_subcmd);
         WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
-        ALOGI("Command left in event_cb %p:%s", cmd, (cmd ? cmd->getType(): ""));
+        if (cmd != NULL) {
+            ALOGI("Command left in event_cb %p", cmd);
+        }
     }
 
+    ALOGI("Check bad commands: num_cmd:%d bad_commands:%d", info->num_cmd, bad_commands);
     while (info->num_cmd > bad_commands) {
         int num_cmd = info->num_cmd;
         cmd_info *cmdi = &(info->cmd[bad_commands]);
@@ -432,11 +601,16 @@
 
     for (int i = 0; i < info->num_event_cb; i++) {
         cb_info *cbi = &(info->event_cb[i]);
+        if (!cbi) {
+            ALOGE("cbi null for index %d", i);
+            continue;
+        }
         WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
         ALOGE("Leaked command %p", cmd);
     }
     pthread_mutex_unlock(&info->cb_lock);
     internal_cleaned_up_handler(handle);
+    ALOGE("wifi_clean_up done");
 }
 
 static int internal_pollin_handler(wifi_handle handle)
@@ -671,6 +845,10 @@
         : WifiCommand("SetPnoMacAddrOuiCommand", handle, 0)
     {
         mOui = scan_oui;
+        fset = NULL;
+        feature_matrix = NULL;
+        fm_size = NULL;
+        set_size_max = 0;
     }
 
     int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
@@ -820,7 +998,7 @@
             return result;
         }
         ALOGI("Successfully set RSSI monitoring");
-        registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+        result = registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
 
 
         if (result < 0) {
@@ -902,6 +1080,8 @@
                     mVersion(version), mMaxLen(max_len),
                     mReqType(GET_APF_CAPABILITIES)
         {
+            mProgram = NULL;
+            mProgramLen = 0;
         }
 
         AndroidPktFilterCommand(wifi_interface_handle handle,
@@ -910,6 +1090,8 @@
                     mProgram(program), mProgramLen(len),
                     mReqType(SET_APF_PROGRAM)
         {
+            mVersion = NULL;
+            mMaxLen = NULL;
         }
 
     int createRequest(WifiRequest& request) {
@@ -931,20 +1113,21 @@
         NULL_CHECK_RETURN(program, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
         int result = request.create(GOOGLE_OUI, APF_SUBCMD_SET_FILTER);
         if (result < 0) {
+            delete[] program;
             return result;
         }
 
         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
         result = request.put_u32(APF_ATTRIBUTE_PROGRAM_LEN, mProgramLen);
         if (result < 0) {
-            return result;
+            goto exit;
         }
         memcpy(program, mProgram, mProgramLen);
         result = request.put(APF_ATTRIBUTE_PROGRAM, program, mProgramLen);
         if (result < 0) {
-            return result;
+            goto exit;
         }
-        request.attr_end(data);
+exit:   request.attr_end(data);
         delete[] program;
         return result;
     }
@@ -1066,8 +1249,7 @@
 public:
     GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set,
          feature_set set_matrix[], int *size, int max_size)
-        : WifiCommand("GetFeatureSetCommand", handle, 0)
-    {
+        : WifiCommand("GetFeatureSetCommand", handle, 0) {
         feature_type = feature;
         fset = set;
         feature_matrix = set_matrix;
@@ -1154,6 +1336,41 @@
 
 };
 
+class SetLatencyModeCommand : public WifiCommand {
+private:
+    u32 mLatencyMode;
+public:
+    SetLatencyModeCommand(wifi_interface_handle handle, u32 LatencyMode)
+        : WifiCommand("SetLatencyModeCommand", handle, 0) {
+            mLatencyMode = LatencyMode;
+    }
+
+    virtual int create() {
+        int ret;
+
+        /* Check for invalid latency Mode */
+        if ((mLatencyMode != WIFI_LATENCY_MODE_NORMAL) &&
+            (mLatencyMode != WIFI_LATENCY_MODE_LOW)) {
+            ALOGE("SetLatencyModeCommand: Invalid mode: %d", mLatencyMode);
+            return WIFI_ERROR_UNKNOWN;
+        }
+
+        ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_LATENCY_MODE);
+        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(ANDR_WIFI_ATTRIBUTE_LATENCY_MODE, mLatencyMode);
+        if (ret < 0) {
+            return ret;
+        }
+
+        mMsg.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+};
 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
 {
     GetMulticastIdCommand cmd(handle, name, group);
@@ -1168,7 +1385,7 @@
 
 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, "swlan", 5) != 0 && strncmp(name, "p2p", 3) != 0) {
         /* not a wifi interface; ignore it */
         return false;
     } else {
@@ -1178,7 +1395,7 @@
 
 static int get_interface(const char *name, interface_info *info)
 {
-    strcpy(info->name, name);
+    strlcpy(info->name, name, sizeof(info->name));
     info->id = if_nametoindex(name);
     // ALOGI("found an interface : %s, id = %d", name, info->id);
     return WIFI_SUCCESS;
@@ -1213,6 +1430,11 @@
         return WIFI_ERROR_UNKNOWN;
 
     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
+    if (!info->interfaces) {
+        info->num_interfaces = 0;
+        closedir(d);
+        return WIFI_ERROR_OUT_OF_MEMORY;
+    }
 
     int i = 0;
     while ((de = readdir(d))) {
@@ -1220,6 +1442,12 @@
             continue;
         if (is_wifi_interface(de->d_name)) {
             interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
+            if (!ifinfo) {
+                free(info->interfaces);
+                info->num_interfaces = 0;
+                closedir(d);
+                return WIFI_ERROR_OUT_OF_MEMORY;
+            }
             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
                 free(ifinfo);
                 continue;
@@ -1246,10 +1474,30 @@
     return WIFI_SUCCESS;
 }
 
+wifi_interface_handle wifi_get_wlan_interface(wifi_handle info, wifi_interface_handle *ifaceHandles, int numIfaceHandles)
+{
+    char buf[EVENT_BUF_SIZE];
+    wifi_interface_handle wlan0Handle;
+    wifi_error res = wifi_get_ifaces((wifi_handle)info, &numIfaceHandles, &ifaceHandles);
+    if (res < 0) {
+        return NULL;
+    }
+    for (int i = 0; i < numIfaceHandles; i++) {
+        if (wifi_get_iface_name(ifaceHandles[i], buf, sizeof(buf)) == WIFI_SUCCESS) {
+            if (strcmp(buf, "wlan0") == 0) {
+                ALOGI("found interface %s\n", buf);
+                wlan0Handle = ifaceHandles[i];
+                return wlan0Handle;
+            }
+        }
+    }
+    return NULL;
+}
 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
 {
     interface_info *info = (interface_info *)handle;
-    strcpy(name, info->name);
+    strncpy(name, info->name, (IFNAMSIZ));
+    name[IFNAMSIZ - 1] = '\0';
     return WIFI_SUCCESS;
 }
 
@@ -1356,5 +1604,89 @@
     SetNdoffloadCommand command(handle, enable);
     return (wifi_error) command.requestResponse();
 }
+wifi_error wifi_set_latency_mode(wifi_interface_handle handle, wifi_latency_mode mode)
+{
+    ALOGD("Setting Wifi Latency mode, halHandle = %p LatencyMode = %d\n", handle, mode);
+    SetLatencyModeCommand command(handle, mode);
+    return (wifi_error) command.requestResponse();
+}
+
+/////////////////////////////////////////////////////////////////////////
+class TxPowerScenario : public WifiCommand {
+    wifi_power_scenario mScenario;
+public:
+    // constructor for tx power scenario setting
+    TxPowerScenario(wifi_interface_handle handle, wifi_power_scenario scenario)
+    : WifiCommand("TxPowerScenario", handle, 0), mScenario(scenario)
+    {
+        mScenario = scenario;
+    }
+
+    // constructor for tx power scenario resetting
+    TxPowerScenario(wifi_interface_handle handle)
+    : WifiCommand("TxPowerScenario", handle, 0)
+    {
+        mScenario = WIFI_POWER_SCENARIO_DEFAULT;
+    }
+
+    int createRequest(WifiRequest& request, int subcmd, wifi_power_scenario mScenario) {
+        int result = request.create(GOOGLE_OUI, subcmd);
+        if (result < 0) {
+            return result;
+        }
+
+        if ((mScenario <= WIFI_POWER_SCENARIO_INVALID) ||
+           (mScenario > WIFI_POWER_SCENARIO_ON_BODY_BT)) {
+            ALOGE("Unsupported tx power value:%d\n", mScenario);
+            return WIFI_ERROR_NOT_SUPPORTED;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+        result = request.put_s8(ANDR_WIFI_ATTRIBUTE_TX_POWER_SCENARIO, mScenario);
+        if (result < 0) {
+            ALOGE("Failed to put tx power scenario request; result = %d", result);
+            return result;
+        }
+        request.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+
+    int start(wifi_power_scenario mScenario) {
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request, WIFI_SUBCMD_TX_POWER_SCENARIO, mScenario);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("failed to create request; result = %d", result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("failed to send tx power scenario; result = %d", result);
+        }
+        return result;
+    }
+protected:
+    virtual int handleResponse(WifiEvent& reply) {
+        ALOGD("Request complete!");
+        /* Nothing to do on response! */
+        return NL_SKIP;
+    }
+};
+
+
+wifi_error wifi_select_tx_power_scenario(wifi_interface_handle handle, wifi_power_scenario scenario)
+{
+    ALOGE("wifi_select_tx_power_scenario");
+    TxPowerScenario command(handle);
+    return (wifi_error)command.start(scenario);
+}
+
+wifi_error wifi_reset_tx_power_scenario(wifi_interface_handle handle)
+{
+    wifi_power_scenario scenario = WIFI_POWER_SCENARIO_DEFAULT;
+    ALOGE("wifi_reset_tx_power_scenario");
+    TxPowerScenario command(handle);
+    return (wifi_error)command.start(scenario);
+}
 
 /////////////////////////////////////////////////////////////////////////////
diff --git a/bcmdhd/wifi_hal/wifi_logger.cpp b/bcmdhd/wifi_hal/wifi_logger.cpp
old mode 100644
new mode 100755
index 7a38883..e35bf9b
--- a/bcmdhd/wifi_hal/wifi_logger.cpp
+++ b/bcmdhd/wifi_hal/wifi_logger.cpp
@@ -33,6 +33,8 @@
 #include <netlink/socket.h>
 #include <netlink-private/object-api.h>
 #include <netlink-private/types.h>
+#include <unistd.h>
+
 
 #include "nl80211_copy.h"
 #include "sync.h"
@@ -44,7 +46,10 @@
 #include "wifi_hal.h"
 #include "common.h"
 #include "cpp_bindings.h"
+#include "brcm_version.h"
+#define WIFI_HAL_EVENT_SOCK_PORT     645
 
+#define ARRAYSIZE(a)	(u8)(sizeof(a) / sizeof(a[0]))
 typedef enum {
     LOGGER_START_LOGGING = ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START,
     LOGGER_TRIGGER_MEM_DUMP,
@@ -59,6 +64,12 @@
     LOGGER_START_PKT_FATE_MONITORING,
     LOGGER_GET_TX_PKT_FATES,
     LOGGER_GET_RX_PKT_FATES,
+    LOGGER_GET_WAKE_REASON_STATS,
+    LOGGER_DEBUG_GET_DUMP,
+    LOGGER_FILE_DUMP_DONE_IND,
+    LOGGER_SET_HAL_START,
+    LOGGER_HAL_STOP,
+    LOGGER_SET_HAL_PID
 } DEBUG_SUB_COMMAND;
 
 typedef enum {
@@ -72,7 +83,7 @@
     LOGGER_ATTRIBUTE_LOG_MIN_DATA_SIZE,
     LOGGER_ATTRIBUTE_FW_DUMP_LEN,
     LOGGER_ATTRIBUTE_FW_DUMP_DATA,
-    // LOGGER_ATTRIBUTE_FW_ERR_CODE,
+    LOGGER_ATTRIBUTE_FW_ERR_CODE,
     LOGGER_ATTRIBUTE_RING_DATA,
     LOGGER_ATTRIBUTE_RING_STATUS,
     LOGGER_ATTRIBUTE_RING_NUM,
@@ -105,6 +116,37 @@
     RX_PACKET_FATE,
 } PktFateReqType;
 
+enum wake_stat_attributes {
+    WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT,
+    WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE,
+    WAKE_STAT_ATTRIBUTE_CMD_EVENT_COUNT,
+    WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED,
+    WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW,
+    WAKE_STAT_ATTRIBUTE_DRIVER_FW_WAKE,
+    WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT,
+    WAKE_STAT_ATTRIBUTE_DRIVER_FW_COUNT_USED,
+    WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE,
+    WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT,
+    WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT,
+    WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT,
+    WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT,
+    WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT,
+    WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA,
+    WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA,
+    WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS,
+    WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT,
+    WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT,
+    WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT,
+    WAKE_STAT_ATTRIBUTE_RX_MULTICAST_PKT_INFO
+};
+
+typedef enum {
+    SET_HAL_START_ATTRIBUTE_DEINIT = 0x0001,
+    SET_HAL_START_ATTRIBUTE_PRE_INIT = 0x0002,
+    SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID = 0x0003
+} SET_HAL_START_ATTRIBUTE;
+
+#define HAL_START_REQUEST_ID 2
 
 ///////////////////////////////////////////////////////////////////////////////
 class DebugCommand : public WifiCommand
@@ -129,26 +171,62 @@
         : WifiCommand("DebugCommand", iface, 0), mBuff(buffer), mBuffSize(buffer_size), mType
         (cmdType)
     {
+        mNumRings =  NULL;
+        mStatus = NULL;
+        mSupport = NULL;
+        mVerboseLevel = 0;
+        mFlags = 0;
+        mMaxIntervalSec = 0;
+        mMinDataSize = 0;
+        mRingName = NULL;
         memset(mBuff, 0, *mBuffSize);
     }
 
     // constructor for ring data
     DebugCommand(wifi_interface_handle iface, char *ring_name, GetCmdType cmdType)
         : WifiCommand("DebugCommand", iface, 0), mRingName(ring_name), mType(cmdType)
-    { }
+    {
+        mBuff = NULL;
+        mBuffSize = NULL;
+        mNumRings =  NULL;
+        mStatus = NULL;
+        mSupport = NULL;
+        mVerboseLevel = 0;
+        mFlags = 0;
+        mMaxIntervalSec = 0;
+        mMinDataSize = 0;
+    }
 
     // constructor for ring status
     DebugCommand(wifi_interface_handle iface, u32 *num_rings,
             wifi_ring_buffer_status *status, GetCmdType cmdType)
         : WifiCommand("DebugCommand", iface, 0), mNumRings(num_rings), mStatus(status), mType(cmdType)
     {
+        mBuff = NULL;
+        mBuffSize = NULL;
+        mSupport = NULL;
+        mVerboseLevel = 0;
+        mFlags = 0;
+        mMaxIntervalSec = 0;
+        mMinDataSize = 0;
+        mRingName = NULL;
         memset(mStatus, 0, sizeof(wifi_ring_buffer_status) * (*mNumRings));
     }
 
     // constructor for feature set
     DebugCommand(wifi_interface_handle iface, unsigned int *support, GetCmdType cmdType)
         : WifiCommand("DebugCommand", iface, 0), mSupport(support), mType(cmdType)
-    { }
+    {
+        mBuff = NULL;
+        mBuffSize = NULL;
+        mNumRings =  NULL;
+        mStatus = NULL;
+        mVerboseLevel = 0;
+        mFlags = 0;
+        mMaxIntervalSec = 0;
+        mMinDataSize = 0;
+        mRingName = NULL;
+    }
 
     // constructor for ring params
     DebugCommand(wifi_interface_handle iface, u32 verbose_level, u32 flags,
@@ -156,7 +234,13 @@
         : WifiCommand("DebugCommand", iface, 0), mVerboseLevel(verbose_level), mFlags(flags),
         mMaxIntervalSec(max_interval_sec), mMinDataSize(min_data_size),
         mRingName(ring_name), mType(cmdType)
-    { }
+    {
+        mBuff = NULL;
+        mBuffSize = NULL;
+        mNumRings =  NULL;
+        mStatus = NULL;
+        mSupport = NULL;
+    }
 
     int createRingRequest(WifiRequest& request) {
         int result = request.create(GOOGLE_OUI, LOGGER_START_LOGGING);
@@ -500,8 +584,38 @@
 
     int start() {
         ALOGV("Register loghandler");
+        int result;
+        uint32_t event_sock_pid = getpid() + (WIFI_HAL_EVENT_SOCK_PORT << 22);
         registerVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
-        return WIFI_SUCCESS;
+
+        WifiRequest request(familyId(), ifaceId());
+
+        /* set hal event socket port to driver */
+        result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_PID);
+        if (result != WIFI_SUCCESS) {
+            ALOGV("Failed to set Hal preInit; result = %d", result);
+            return result;
+        }
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+        result = request.put_u32(SET_HAL_START_ATTRIBUTE_EVENT_SOCK_PID, event_sock_pid);
+        if (result != WIFI_SUCCESS) {
+            ALOGV("Hal preInit Failed to put pic = %d", result);
+            return result;
+        }
+
+        if (result != WIFI_SUCCESS) {
+            ALOGV("Hal preInit Failed to put pid= %d", result);
+            return result;
+        } 
+
+        request.attr_end(data);
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to register set Hal preInit; result = %d", result);
+            return result;
+        }
+        return result;
     }
 
     virtual int cancel() {
@@ -561,8 +675,13 @@
 
             // ALOGI("Retrieved Debug data");
             if (mHandler.on_ring_buffer_data) {
-                (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,
-                        &status);
+                /* Skip msg header. Retrieved log */
+                char *pBuff;
+                wifi_ring_buffer_entry *buffer_entry = 
+                            (wifi_ring_buffer_entry *) buffer;
+                pBuff = (char *) (buffer_entry + 1);
+                (*mHandler.on_ring_buffer_data)((char *)status.name, pBuff, 
+                    buffer_entry->entry_size, &status);
             }
         } else {
             ALOGE("Unknown Event");
@@ -679,7 +798,7 @@
         wifi_ring_buffer_id ring_id;
         char *buffer = NULL;
         int buffer_size = 0;
-
+        bool is_err_alert = false;
 
         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
         int len = event.get_vendor_data_len();
@@ -698,15 +817,37 @@
                 } else if (it.get_type() == LOGGER_ATTRIBUTE_RING_DATA) {
                     buffer_size = it.get_len();
                     buffer = (char *)it.get_data();
-            /*
                 } else if (it.get_type() == LOGGER_ATTRIBUTE_FW_ERR_CODE) {
+                    /* Error code is for error alert event only */
                     mErrCode = it.get_u32();
-            */
+                    is_err_alert = true;
                 } else {
                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
                             it.get_type(), it.get_len());
                 }
             }
+
+            if(is_err_alert) {
+                mBuffSize = sizeof(mErrCode);
+                if (mBuff) free(mBuff);
+                mBuff = (char *)malloc(mBuffSize);
+                if (!mBuff) {
+                  ALOGE("Buffer allocation failed");
+                  return NL_SKIP;
+                }
+                memcpy(mBuff, (char *)&mErrCode, mBuffSize);
+                ALOGI("Initiating alert callback");
+                if (mHandler.on_alert) {
+                  (*mHandler.on_alert)(id(), mBuff, mBuffSize, mErrCode);
+                }
+                if (mBuff) {
+                  free(mBuff);
+                  mBuff = NULL;
+                }
+                mBuffSize = 0;
+                return NL_OK;
+            }
+
             if (mBuffSize) {
                 ALOGD("dump size: %d meta data size: %d", mBuffSize, buffer_size);
                 if (mBuff) free(mBuff);
@@ -755,6 +896,147 @@
     }
 };
 
+///////////////////////////////////////////////////////////////////////////////
+class HalInit : public WifiCommand
+{
+    int mErrCode;
+
+    public:
+    HalInit(wifi_interface_handle iface, int id)
+        : WifiCommand("HalInit", iface, id), mErrCode(0)
+    { }
+
+    int start() {
+        ALOGE("Start Set Hal");
+        WifiRequest request(familyId(), ifaceId());
+
+        int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to set hal start; result = %d", result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to register set hal start response; result = %d", result);
+        }
+        return result;
+    }
+
+
+    virtual int cancel() {
+        ALOGE("Cancel: Stop Hal");
+        WifiRequest request(familyId(), ifaceId());
+
+        int result = request.create(GOOGLE_OUI, LOGGER_HAL_STOP);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to stop hal ; result = %d", result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to register set hal start response; result = %d", result);
+        }
+        wifi_unregister_cmd(wifiHandle(), id());
+        return result;
+    }
+
+    int preInit() {
+        ALOGE("Hal preInit");
+        WifiRequest request(familyId(), ifaceId());
+
+        int result = request.create(GOOGLE_OUI, LOGGER_SET_HAL_START);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to set Hal preInit; result = %d", result);
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+        result = request.put_string(SET_HAL_START_ATTRIBUTE_PRE_INIT, (char *)HAL_VERSION);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Hal preInit Failed to put data= %d", result);
+            return result;
+        }
+        request.attr_end(data);
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to register set Hal preInit; result = %d", result);
+        }
+        return result;
+    }
+
+    virtual int handleResponse(WifiEvent& reply) {
+        ALOGE("In SetHalStarted::handleResponse");
+
+        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+            return NL_SKIP;
+        }
+        return NL_OK;
+    }
+
+    virtual int handleEvent(WifiEvent& event) {
+        /* NO events! */
+        return NL_SKIP;
+    }
+};
+
+
+wifi_error wifi_start_hal(wifi_interface_handle iface)
+{
+    wifi_handle handle = getWifiHandle(iface);
+    ALOGV("HAL INIT start, handle = %p", handle);
+
+    HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
+    if (result != WIFI_SUCCESS) {
+        cmd->releaseRef();
+        return result;
+    }
+    result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
+        cmd->releaseRef();
+        return result;
+    }
+    return result;
+}
+
+wifi_error wifi_hal_preInit(wifi_interface_handle iface)
+{
+    wifi_handle handle = getWifiHandle(iface);
+    ALOGV("wifi_hal_preInit, handle = %p", handle);
+
+    HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    wifi_error result = wifi_register_cmd(handle, HAL_START_REQUEST_ID, cmd);
+    if (result != WIFI_SUCCESS) {
+        cmd->releaseRef();
+        return result;
+    }
+    result = (wifi_error)cmd->preInit();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle,HAL_START_REQUEST_ID);
+        cmd->releaseRef();
+        return result;
+    }
+    return result;
+}
+
+wifi_error wifi_stop_hal(wifi_interface_handle iface)
+{
+    wifi_handle handle = getWifiHandle(iface);
+
+    HalInit *cmd = new HalInit(iface, HAL_START_REQUEST_ID);
+    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
+    cmd->cancel();
+    cmd->releaseRef();
+    return WIFI_SUCCESS;
+}
+
 wifi_error wifi_set_alert_handler(wifi_request_id id, wifi_interface_handle iface,
         wifi_alert_handler handler)
 {
@@ -923,7 +1205,11 @@
 public:
     PacketFateCommand(wifi_interface_handle handle)
         : WifiCommand("PacketFateCommand", handle, 0), mReqType(PACKET_MONITOR_START)
-    { }
+    {
+        mReportBufs = NULL;
+        mNoReqFates = 0;
+        mNoProvidedFates = NULL;
+    }
 
     PacketFateCommand(wifi_interface_handle handle, wifi_tx_report *tx_report_bufs,
             size_t n_requested_fates, size_t *n_provided_fates)
@@ -1075,6 +1361,143 @@
     }
 };
 
+class GetWakeReasonCountCommand : public WifiCommand {
+    WLAN_DRIVER_WAKE_REASON_CNT *mWakeReasonCnt;
+    void *mCmdEventWakeCount;
+    public:
+    GetWakeReasonCountCommand(wifi_interface_handle handle,
+        WLAN_DRIVER_WAKE_REASON_CNT *wlanDriverWakeReasonCount) :
+        WifiCommand("GetWakeReasonCountCommand", handle, 0),
+        mWakeReasonCnt(wlanDriverWakeReasonCount)
+    {
+        mCmdEventWakeCount = mWakeReasonCnt->cmd_event_wake_cnt;
+    }
+
+    int createRequest(WifiRequest& request) {
+        int result = request.create(GOOGLE_OUI, LOGGER_GET_WAKE_REASON_STATS);
+        if (result < 0) {
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+        request.attr_end(data);
+        return WIFI_SUCCESS;
+    }
+
+    int start() {
+        ALOGD("Start get wake stats command\n");
+        WifiRequest request(familyId(), ifaceId());
+
+        int result = createRequest(request);
+        if (result < 0) {
+            ALOGE("Failed to create request result = %d\n", result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to register wake stats  response; result = %d\n", result);
+        }
+        return result;
+    }
+
+    protected:
+    int handleResponse(WifiEvent& reply) {
+        ALOGE("In GetWakeReasonCountCommand::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();
+
+        nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
+        int len = reply.get_vendor_data_len();
+
+        ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
+        if (vendor_data == NULL || len == 0) {
+            ALOGE("no vendor data in GetGetWakeReasonCountCommand response; ignoring it");
+            return NL_SKIP;
+        }
+
+        for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
+            switch (it.get_type()) {
+                case WAKE_STAT_ATTRIBUTE_TOTAL_DRIVER_FW:
+                    mWakeReasonCnt->total_driver_fw_local_wake =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_TOTAL_CMD_EVENT:
+                    mWakeReasonCnt->total_cmd_event_wake =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_CMD_COUNT_USED:
+                    mWakeReasonCnt->cmd_event_wake_cnt_used =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_CMD_EVENT_WAKE:
+                    memcpy(mCmdEventWakeCount, it.get_data(),
+                            (mWakeReasonCnt->cmd_event_wake_cnt_used * sizeof(int)));
+                    break;
+                case WAKE_STAT_ATTRIBUTE_TOTAL_RX_DATA_WAKE:
+                    mWakeReasonCnt->total_rx_data_wake =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_RX_UNICAST_COUNT:
+                    mWakeReasonCnt->rx_wake_details.rx_unicast_cnt =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_RX_MULTICAST_COUNT:
+                    mWakeReasonCnt->rx_wake_details.rx_multicast_cnt =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_RX_BROADCAST_COUNT:
+                    mWakeReasonCnt->rx_wake_details.rx_broadcast_cnt =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_RX_ICMP_PKT:
+                    mWakeReasonCnt->rx_wake_pkt_classification_info.icmp_pkt =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_RX_ICMP6_PKT:
+                    mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_pkt =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_RX_ICMP6_RA:
+                    mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ra =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NA:
+                    mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_na =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_RX_ICMP6_NS:
+                    mWakeReasonCnt->rx_wake_pkt_classification_info.icmp6_ns =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_IPV4_RX_MULTICAST_ADD_CNT:
+                    mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_IPV6_RX_MULTICAST_ADD_CNT:
+                    mWakeReasonCnt->rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt =
+                        it.get_u32();
+                    break;
+                case WAKE_STAT_ATTRIBUTE_OTHER__RX_MULTICAST_ADD_CNT:
+                    mWakeReasonCnt->rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt =
+                        it.get_u32();
+                    break;
+                default:
+                    break;
+            }
+
+        }
+        return NL_OK;
+    }
+};
+
 wifi_error wifi_start_pkt_fate_monitoring(wifi_interface_handle handle)
 {
     PacketFateCommand *cmd = new PacketFateCommand(handle);
@@ -1107,3 +1530,13 @@
     cmd->releaseRef();
     return result;
 }
+
+wifi_error wifi_get_wake_reason_stats(wifi_interface_handle handle,
+        WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt)
+{
+    GetWakeReasonCountCommand *cmd =
+        new GetWakeReasonCountCommand(handle, wifi_wake_reason_cnt);
+    wifi_error result = (wifi_error)cmd->start();
+    cmd->releaseRef();
+    return result;
+}
diff --git a/bcmdhd/wifi_hal/wifi_offload.cpp b/bcmdhd/wifi_hal/wifi_offload.cpp
index 99c2fec..8054f49 100644
--- a/bcmdhd/wifi_hal/wifi_offload.cpp
+++ b/bcmdhd/wifi_hal/wifi_offload.cpp
@@ -57,7 +57,8 @@
     MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
     MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
     MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
-    MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
+    MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC,
+    MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE
 } WIFI_MKEEP_ALIVE_ATTRIBUTE;
 
 typedef enum {
@@ -75,13 +76,14 @@
     u8 *mDstMacAddr;
     u32 mPeriodMsec;
     GetCmdType mType;
+    u16 mEther_type;
 
 public:
 
     // constructor for start sending
-    MKeepAliveCommand(wifi_interface_handle iface, u8 index, u8 *ip_packet, u16 ip_packet_len,
+    MKeepAliveCommand(wifi_interface_handle iface, u8 index, u16 ether_type, u8 *ip_packet, u16 ip_packet_len,
             u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec, GetCmdType cmdType)
-        : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mIpPkt(ip_packet),
+        : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mEther_type(ether_type), mIpPkt(ip_packet),
         mIpPktLen(ip_packet_len), mSrcMacAddr(src_mac_addr), mDstMacAddr(dst_mac_addr),
         mPeriodMsec(period_msec), mType(cmdType)
     { }
@@ -89,10 +91,17 @@
     // constructor for stop sending
     MKeepAliveCommand(wifi_interface_handle iface, u8 index, GetCmdType cmdType)
         : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mType(cmdType)
-    { }
+    {
+        mIpPkt = NULL;
+        mIpPktLen = 0;
+        mSrcMacAddr = NULL;
+        mDstMacAddr = NULL;
+        mPeriodMsec = 0;
+        mEther_type = 0;
+    }
 
     int createRequest(WifiRequest &request) {
-        int result;
+        int result = WIFI_SUCCESS;
 
         switch (mType) {
             case START_MKEEP_ALIVE:
@@ -140,6 +149,11 @@
                     ALOGE("Failed to put period request; result = %d", result);
                     return result;
                 }
+                result = request.put_u16(MKEEP_ALIVE_ATTRIBUTE_ETHER_TYPE, mEther_type);
+                if (result < 0) {
+                    ALOGE("Failed to put ether type; result = %d", result);
+                    return result;
+                }
 
                 request.attr_end(data);
                 break;
@@ -216,13 +230,14 @@
 
 /* API to send specified mkeep_alive packet periodically. */
 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface,
-        u16 /* ether_type */, u8 *ip_packet, u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr,
+        u16 ether_type, u8 *ip_packet, u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr,
         u32 period_msec)
 {
     if ((index > 0 && index <= N_AVAIL_ID) && (ip_packet != NULL) && (src_mac_addr != NULL)
             && (dst_mac_addr != NULL) && (period_msec > 0)
-            && (ip_packet_len <= MKEEP_ALIVE_IP_PKT_MAX)) {
-        MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, ip_packet, ip_packet_len,
+            && (ip_packet_len <= MKEEP_ALIVE_IP_PKT_MAX) && ((ether_type == ETHERTYPE_IP) ||
+            (ether_type == ETHERTYPE_IPV6))) {
+        MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, ether_type, ip_packet, ip_packet_len,
                 src_mac_addr, dst_mac_addr, period_msec, START_MKEEP_ALIVE);
         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
         wifi_error result = (wifi_error)cmd->start();