merge in mnc-dr-release history after reset to mnc-dr-dev
diff --git a/bcmdhd/config/wpa_supplicant_overlay.conf b/bcmdhd/config/wpa_supplicant_overlay.conf
index 84d19d8..740792b 100644
--- a/bcmdhd/config/wpa_supplicant_overlay.conf
+++ b/bcmdhd/config/wpa_supplicant_overlay.conf
@@ -1,4 +1,5 @@
 disable_scan_offload=1
 wowlan_triggers=any
 p2p_disabled=1
+filter_rssi=-75
 no_ctrl_interface=
\ No newline at end of file
diff --git a/bcmdhd/firmware/bcm4354/fw_bcm4354.bin b/bcmdhd/firmware/bcm4354/fw_bcm4354.bin
old mode 100755
new mode 100644
index 3952589..fd7b0ca
--- a/bcmdhd/firmware/bcm4354/fw_bcm4354.bin
+++ b/bcmdhd/firmware/bcm4354/fw_bcm4354.bin
Binary files differ
diff --git a/bcmdhd/firmware/bcm4354/fw_bcm4354_ap.bin b/bcmdhd/firmware/bcm4354/fw_bcm4354_ap.bin
old mode 100755
new mode 100644
index dcc2f11..27fd7cc
--- a/bcmdhd/firmware/bcm4354/fw_bcm4354_ap.bin
+++ b/bcmdhd/firmware/bcm4354/fw_bcm4354_ap.bin
Binary files differ
diff --git a/bcmdhd/firmware/bcm4356/fw_bcm4356_ap_pcie.bin b/bcmdhd/firmware/bcm4356/fw_bcm4356_ap_pcie.bin
old mode 100755
new mode 100644
index 7ebe5ed..37b4776
--- a/bcmdhd/firmware/bcm4356/fw_bcm4356_ap_pcie.bin
+++ b/bcmdhd/firmware/bcm4356/fw_bcm4356_ap_pcie.bin
Binary files differ
diff --git a/bcmdhd/firmware/bcm4356/fw_bcm4356_pcie.bin b/bcmdhd/firmware/bcm4356/fw_bcm4356_pcie.bin
old mode 100755
new mode 100644
index 26fbe54..a6e5cdd
--- a/bcmdhd/firmware/bcm4356/fw_bcm4356_pcie.bin
+++ b/bcmdhd/firmware/bcm4356/fw_bcm4356_pcie.bin
Binary files differ
diff --git a/bcmdhd/wifi_hal/Android.mk b/bcmdhd/wifi_hal/Android.mk
index bb8514a..ea19efd 100644
--- a/bcmdhd/wifi_hal/Android.mk
+++ b/bcmdhd/wifi_hal/Android.mk
@@ -32,7 +32,8 @@
 	cpp_bindings.cpp \
 	gscan.cpp \
 	link_layer_stats.cpp \
-	wifi_logger.cpp
+	wifi_logger.cpp \
+	wifi_offload.cpp
 
 LOCAL_MODULE := libwifi-hal-bcm
 
diff --git a/bcmdhd/wifi_hal/common.cpp b/bcmdhd/wifi_hal/common.cpp
index 61f4475..9182114 100644
--- a/bcmdhd/wifi_hal/common.cpp
+++ b/bcmdhd/wifi_hal/common.cpp
@@ -1,11 +1,23 @@
+#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 <stdlib.h>
 #include <linux/pkt_sched.h>
 #include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
 #include <netlink/handlers.h>
 
 #include "wifi_hal.h"
 #include "common.h"
+#include "cpp_bindings.h"
 
 interface_info *getIfaceInfo(wifi_interface_handle handle)
 {
@@ -208,3 +220,19 @@
         }
     }
 }
+
+wifi_error wifi_cancel_cmd(wifi_request_id id, wifi_interface_handle iface)
+{
+    wifi_handle handle = getWifiHandle(iface);
+
+    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
+    ALOGV("Cancel WifiCommand = %p", cmd);
+    if (cmd) {
+        cmd->cancel();
+        cmd->releaseRef();
+        return WIFI_SUCCESS;
+    }
+
+    return WIFI_ERROR_INVALID_ARGS;
+}
+
diff --git a/bcmdhd/wifi_hal/common.h b/bcmdhd/wifi_hal/common.h
index 26bb9a6..8c09c16 100644
--- a/bcmdhd/wifi_hal/common.h
+++ b/bcmdhd/wifi_hal/common.h
@@ -59,6 +59,10 @@
     ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400,
     ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END   = 0x14FF,
 
+    /* define all wifi offload related commands between 0x1600 and 0x16FF */
+    ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600,
+    ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END   = 0x16FF,
+
     /* This is reserved for future usage */
 
 } ANDROID_VENDOR_SUB_COMMAND;
@@ -95,6 +99,7 @@
     WIFI_SUBCMD_SET_BSSID_BLACKLIST,                     /* 0x1014 */
 
     GSCAN_SUBCMD_ANQPO_CONFIG,                          /* 0x1015 */
+    WIFI_SUBCMD_SET_RSSI_MONITOR,                       /* 0x1016 */
     /* Add more sub commands here */
 
     GSCAN_SUBCMD_MAX
@@ -114,7 +119,8 @@
     GSCAN_EVENT_EPNO_EVENT,
     GOOGLE_DEBUG_RING_EVENT,
     GOOGLE_DEBUG_MEM_DUMP_EVENT,
-    GSCAN_EVENT_ANQPO_HOTSPOT_MATCH
+    GSCAN_EVENT_ANQPO_HOTSPOT_MATCH,
+    GOOGLE_RSSI_MONITOR_EVENT
 } WIFI_EVENT;
 
 typedef void (*wifi_internal_event_handler) (wifi_handle handle, int events);
@@ -199,7 +205,7 @@
 hal_info *getHalInfo(wifi_interface_handle handle);
 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);
 
 // some common macros
 
diff --git a/bcmdhd/wifi_hal/gscan.cpp b/bcmdhd/wifi_hal/gscan.cpp
index d513f28..21ec30d 100644
--- a/bcmdhd/wifi_hal/gscan.cpp
+++ b/bcmdhd/wifi_hal/gscan.cpp
@@ -19,6 +19,7 @@
 #include "sync.h"
 
 #define LOG_TAG  "WifiHAL"
+//#define LOG_NDEBUG 1         //uncomment to enable verbose logging
 
 #include <utils/Log.h>
 
@@ -155,7 +156,7 @@
     }
 
     virtual int create() {
-        ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
+        ALOGV("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
 
         int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES);
         if (ret < 0) {
@@ -168,7 +169,7 @@
 protected:
     virtual int handleResponse(WifiEvent& reply) {
 
-        ALOGD("In GetCapabilities::handleResponse");
+        ALOGV("In GetCapabilities::handleResponse");
 
         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
@@ -181,7 +182,7 @@
         void *data = reply.get_vendor_data();
         int len = reply.get_vendor_data_len();
 
-        ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
+        ALOGV("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
                     sizeof(*mCapabilities));
 
         memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
@@ -213,7 +214,7 @@
         memset(channels, 0, sizeof(wifi_channel) * max_channels);
     }
     virtual int create() {
-        ALOGD("Creating message to get channel list; iface = %d", mIfaceInfo->id);
+        ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id);
 
         int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CHANNEL_LIST);
         if (ret < 0) {
@@ -234,7 +235,7 @@
 protected:
     virtual int handleResponse(WifiEvent& reply) {
 
-        ALOGD("In GetChannelList::handleResponse");
+        ALOGV("In GetChannelList::handleResponse");
 
         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
@@ -248,7 +249,7 @@
         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
         int len = reply.get_vendor_data_len();
 
-        ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
+        ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
         if (vendor_data == NULL || len == 0) {
             ALOGE("no vendor data in GetChannelList response; ignoring it");
             return NL_SKIP;
@@ -371,7 +372,7 @@
     }
 
     int start() {
-        // ALOGD("Enabling Full scan results");
+        ALOGV("Enabling Full scan results");
         WifiRequest request(familyId(), ifaceId());
         int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1);
         if (result != WIFI_SUCCESS) {
@@ -392,7 +393,7 @@
     }
 
     virtual int cancel() {
-        // ALOGD("Disabling Full scan results");
+        ALOGV("Disabling Full scan results");
 
         WifiRequest request(familyId(), ifaceId());
         int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0);
@@ -416,9 +417,8 @@
     }
 
     virtual int handleEvent(WifiEvent& event) {
-        //ALOGI("Full scan results:  Got an event");
-
-        // event.log();
+        ALOGV("Full scan results:  Got an event");
+        event.log();
 
         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
         unsigned int len = event.get_vendor_data_len();
@@ -578,20 +578,20 @@
                 nBuckets++;
             }
         }
-        
-        // ALOGI("enableFullScanResultsIfRequired num %u needed %u global %u",
-        //    mParams->num_buckets, nBuckets, mGlobalFullScanBuckets);
+
+        ALOGV("enableFullScanResultsIfRequired num %u needed %u global %u",
+            mParams->num_buckets, nBuckets, mGlobalFullScanBuckets);
 
         if (mGlobalFullScanBuckets == 0 && nBuckets != 0) {
             int result = wifi_enable_full_scan_results(0x1000, ifaceHandle(), mHandler);
             if (result != WIFI_SUCCESS) {
-                ALOGI("failed to enable full scan results");
+                ALOGE("failed to enable full scan results");
                 return result;
             } else {
-                // ALOGI("successfully enabled full scan results");
+                ALOGV("successfully enabled full scan results");
             }
         } else {
-            // ALOGI("mGlobalFullScanBuckets = %d, nBuckets = %d", mGlobalFullScanBuckets, nBuckets);
+            ALOGV("mGlobalFullScanBuckets = %d, nBuckets = %d", mGlobalFullScanBuckets, nBuckets);
         }
 
         mLocalFullScanBuckets = nBuckets;
@@ -610,9 +610,9 @@
         if (mGlobalFullScanBuckets == 0) {
             int result = wifi_disable_full_scan_results(0x1000, ifaceHandle());
             if (result != WIFI_SUCCESS) {
-                ALOGI("failed to disable full scan results");
+                ALOGE("failed to disable full scan results");
             } else {
-                // ALOGI("successfully disable full scan results");
+                ALOGV("successfully disable full scan results");
             }
         }
 
@@ -620,7 +620,7 @@
     }
 
     int start() {
-        // ALOGD("GSCAN start");
+        ALOGV("GSCAN start");
         WifiRequest request(familyId(), ifaceId());
         int result = createSetupRequest(request);
         if (result != WIFI_SUCCESS) {
@@ -648,7 +648,7 @@
             return result;
         }
 
-        // ALOGD(" ....starting scan");
+        ALOGV(" ....starting scan");
 
         result = createStartRequest(request);
         if (result != WIFI_SUCCESS) {
@@ -672,7 +672,7 @@
     }
 
     virtual int cancel() {
-        // ALOGD("Stopping scan");
+        ALOGV("Stopping scan");
 
         WifiRequest request(familyId(), ifaceId());
         int result = createStopRequest(request);
@@ -698,9 +698,8 @@
     }
 
     virtual int handleEvent(WifiEvent& event) {
-        // ALOGI("Got a scan results event");
-
-        // event.log();
+        ALOGV("Got a scan results event");
+        event.log();
 
         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
         int len = event.get_vendor_data_len();
@@ -714,7 +713,7 @@
             wifi_scan_event evt_type;
 
             evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA);
-            // ALOGI("Scan complete: Received event type %d", evt_type);
+            ALOGV("Scan complete: Received event type %d", evt_type);
             if(*mHandler.on_scan_event)
                 (*mHandler.on_scan_event)(evt_type, evt_type);
         } else {
@@ -725,7 +724,7 @@
             }
 
             int num = event.get_u32(NL80211_ATTR_VENDOR_DATA);
-            // ALOGI("Found %d scan results", num);
+            ALOGV("Found %d scan results", num);
             if(*mHandler.on_scan_results_available)
                 (*mHandler.on_scan_results_available)(id(), num);
         }
@@ -743,17 +742,21 @@
 {
     wifi_handle handle = getWifiHandle(iface);
 
-    // ALOGD("Starting GScan, halHandle = %p", handle);
+    ALOGV("Starting GScan, halHandle = %p", handle);
 
     ScanCommand *cmd = new ScanCommand(iface, id, &params, handler);
     wifi_register_cmd(handle, id, cmd);
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
 {
-    // ALOGD("Stopping GScan");
     wifi_handle handle = getWifiHandle(iface);
+    ALOGV("Stopping GScan, wifi_request_id = %d, halHandle = %p", id, handle);
 
     if(id == -1) {
         wifi_scan_result_handler handler;
@@ -767,15 +770,7 @@
         return WIFI_SUCCESS;
     }
 
-
-    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
-    if (cmd) {
-        cmd->cancel();
-        cmd->releaseRef();
-        return WIFI_SUCCESS;
-    }
-
-    return WIFI_ERROR_INVALID_ARGS;
+    return wifi_cancel_cmd(id, iface);
 }
 
 
@@ -786,18 +781,22 @@
 {
     wifi_handle handle = getWifiHandle(iface);
     int params_dummy;
-    
-    // ALOGD("Enabling full scan results, halHandle = %p", handle);
+
+    ALOGV("Enabling full scan results, halHandle = %p", handle);
 
     FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, &params_dummy, handler);
     wifi_register_cmd(handle, id, cmd);
 
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface)
 {
-    // ALOGD("Disabling full scan results");
+    ALOGV("Disabling full scan results");
     wifi_handle handle = getWifiHandle(iface);
 
     if(id == -1) {
@@ -812,14 +811,7 @@
         return WIFI_SUCCESS;
     }
 
-    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
-    if (cmd) {
-        cmd->cancel();
-        cmd->releaseRef();
-        return WIFI_SUCCESS;
-    }
-
-    return WIFI_ERROR_INVALID_ARGS;
+    return wifi_cancel_cmd(id, iface);
 }
 
 
@@ -865,7 +857,7 @@
 
     int execute() {
         WifiRequest request(familyId(), ifaceId());
-        // ALOGI("retrieving %d scan results", mMax);
+        ALOGV("retrieving %d scan results", mMax);
 
         for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
             int num_to_retrieve = mMax - mRetrieved;
@@ -899,7 +891,7 @@
     }
 
     virtual int handleResponse(WifiEvent& reply) {
-        // ALOGD("In GetScanResultsCommand::handleResponse");
+        ALOGV("In GetScanResultsCommand::handleResponse");
 
         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
@@ -909,7 +901,7 @@
         int id = reply.get_vendor_id();
         int subcmd = reply.get_vendor_subcmd();
 
-        // ALOGD("Id = %0x, subcmd = %d", id, subcmd);
+        ALOGV("Id = %0x, subcmd = %d", id, subcmd);
 
         /*
         if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) {
@@ -984,8 +976,7 @@
 
 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
         int max, wifi_cached_scan_results *results, int *num) {
-
-    // ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface, *num);
+    ALOGV("Getting cached scan results, iface handle = %p, num = %d", iface, *num);
 
     GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
     wifi_error err = (wifi_error) cmd->execute();
@@ -1335,21 +1326,16 @@
 
     BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
     wifi_register_cmd(handle, id, cmd);
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
 {
-    wifi_handle handle = getWifiHandle(iface);
-
-    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
-    if (cmd) {
-        cmd->cancel();
-        cmd->releaseRef();
-        return WIFI_SUCCESS;
-    }
-
-    return WIFI_ERROR_INVALID_ARGS;
+    return wifi_cancel_cmd(id, iface);
 }
 
 
@@ -1505,7 +1491,7 @@
     }
 
     virtual int handleEvent(WifiEvent& event) {
-        ALOGI("Got a significant wifi change event");
+        ALOGV("Got a significant wifi change event");
 
         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
         int len = event.get_vendor_data_len();
@@ -1534,7 +1520,7 @@
             mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
         }
 
-        ALOGI("Retrieved %d scan results", num);
+        ALOGV("Retrieved %d scan results", num);
 
         if (num != 0) {
             (*mHandler.on_significant_change)(id(), num, mResults);
@@ -1554,34 +1540,21 @@
     SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
             iface, id, params, handler);
     wifi_register_cmd(handle, id, cmd);
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
 {
-    wifi_handle handle = getWifiHandle(iface);
-
-    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
-    if (cmd) {
-        cmd->cancel();
-        cmd->releaseRef();
-        return WIFI_SUCCESS;
-    }
-
-    return WIFI_ERROR_INVALID_ARGS;
+    return wifi_cancel_cmd(id, iface);
 }
 
 wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
 {
-    wifi_handle handle = getWifiHandle(iface);
-
-    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
-    if (cmd) {
-        cmd->cancel();
-        cmd->releaseRef();
-        return WIFI_SUCCESS;
-    }
-    return WIFI_ERROR_INVALID_ARGS;
+    return wifi_cancel_cmd(id, iface);
 }
 
 wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface,
@@ -1594,7 +1567,11 @@
      if (num_networks == 0 || networks == NULL) {
          return wifi_reset_epno_list(id, iface);
      }
-     return (wifi_error)cmd->start();
+     wifi_error result = (wifi_error)cmd->start();
+     if (result != WIFI_SUCCESS) {
+         wifi_unregister_cmd(handle, id);
+     }
+     return result;
 }
 
 class SSIDWhitelistCommand : public WifiCommand
@@ -1680,7 +1657,11 @@
 
     SSIDWhitelistCommand *cmd = new SSIDWhitelistCommand(iface, id, num_networks, ssids);
     wifi_register_cmd(handle, id, cmd);
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 
@@ -1734,7 +1715,7 @@
     }
 
     int start() {
-        ALOGI("Executing roam params set request");
+        ALOGV("Executing roam params set request");
         WifiRequest request(familyId(), ifaceId());
         int result = createRequest(request);
         if (result < 0) {
@@ -1743,7 +1724,7 @@
 
         result = requestResponse(request);
         if (result < 0) {
-            ALOGI("Failed to execute Roam params set request, result = %d", result);
+            ALOGE("Failed to execute Roam params set request, result = %d", result);
             return result;
         }
 
@@ -1769,7 +1750,11 @@
 
     RoamParamsCommand *cmd = new RoamParamsCommand(iface, id, params);
     wifi_register_cmd(handle, id, cmd);
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 class LazyRoamCommand : public WifiCommand
@@ -1830,7 +1815,11 @@
 
     LazyRoamCommand *cmd = new LazyRoamCommand(iface, id, enable);
     wifi_register_cmd(handle, id, cmd);
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 class BssidBlacklistCommand : public WifiCommand
@@ -1870,7 +1859,7 @@
     }
 
     int start() {
-        ALOGI("Executing bssid blacklist request, num = %d", mParams->num_bssid);
+        ALOGV("Executing bssid blacklist request, num = %d", mParams->num_bssid);
         WifiRequest request(familyId(), ifaceId());
         int result = createRequest(request);
         if (result < 0) {
@@ -1879,7 +1868,7 @@
 
         result = requestResponse(request);
         if (result < 0) {
-            ALOGI("Failed to execute bssid blacklist request, result = %d", result);
+            ALOGE("Failed to execute bssid blacklist request, result = %d", result);
             return result;
         }
 
@@ -1904,7 +1893,11 @@
 
     BssidBlacklistCommand *cmd = new BssidBlacklistCommand(iface, id, &params);
     wifi_register_cmd(handle, id, cmd);
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 class BssidPreferenceCommand : public WifiCommand
@@ -1963,7 +1956,7 @@
     }
 
     int start() {
-        ALOGI("Executing bssid prefernce change request, num = %d", mNumBssid);
+        ALOGV("Executing bssid prefernce change request, num = %d", mNumBssid);
         WifiRequest request(familyId(), ifaceId());
         int result = createRequest(request);
         if (result < 0) {
@@ -1972,7 +1965,7 @@
 
         result = requestResponse(request);
         if (result < 0) {
-            ALOGI("Failed to execute bssid preference change request, result = %d", result);
+            ALOGE("Failed to execute bssid preference change request, result = %d", result);
             return result;
         }
 
@@ -1998,7 +1991,11 @@
 
     BssidPreferenceCommand *cmd = new BssidPreferenceCommand(iface, id, num_bssid, prefs);
     wifi_register_cmd(handle, id, cmd);
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2153,19 +2150,15 @@
 
     AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler);
     wifi_register_cmd(handle, id, cmd);
-    return (wifi_error)cmd->start();
+    wifi_error result = (wifi_error)cmd->start();
+    if (result != WIFI_SUCCESS) {
+        wifi_unregister_cmd(handle, id);
+    }
+    return result;
 }
 
 wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
 {
-    wifi_handle handle = getWifiHandle(iface);
-
-    WifiCommand *cmd = wifi_unregister_cmd(handle, id);
-    if (cmd) {
-        cmd->cancel();
-        cmd->releaseRef();
-        return WIFI_SUCCESS;
-    }
-
-    return WIFI_ERROR_INVALID_ARGS;
+    return wifi_cancel_cmd(id, iface);
 }
+
diff --git a/bcmdhd/wifi_hal/link_layer_stats.cpp b/bcmdhd/wifi_hal/link_layer_stats.cpp
index 3226da8..25502af 100644
--- a/bcmdhd/wifi_hal/link_layer_stats.cpp
+++ b/bcmdhd/wifi_hal/link_layer_stats.cpp
@@ -68,9 +68,19 @@
 
         void *data = reply.get_vendor_data();
         int len = reply.get_vendor_data_len();
-	int num_chan = ((wifi_radio_stat *)data)->num_channels;
-        if (num_chan > 32) {
+	unsigned int num_chan = ((wifi_radio_stat *)data)->num_channels;
+        if (num_chan > 11) {
            ALOGE("Incorrect number of channels = %d", num_chan);
+           // dump data before num_channels
+           ALOGE("radio: = %d", ((wifi_radio_stat *)data)->radio);
+           ALOGE("on_time: = %d", ((wifi_radio_stat *)data)->on_time);
+           ALOGE("tx_time: = %d", ((wifi_radio_stat *)data)->tx_time);
+           ALOGE("rx_time: = %d", ((wifi_radio_stat *)data)->rx_time);
+           ALOGE("on_time_scan: = %d", ((wifi_radio_stat *)data)->on_time_scan);
+           ALOGE("on_time_nbd: = %d", ((wifi_radio_stat *)data)->on_time_nbd);
+           ALOGE("on_time_gscan: = %d", ((wifi_radio_stat *)data)->on_time_gscan);
+           ALOGE("on_time_pno_scan: = %d", ((wifi_radio_stat *)data)->on_time_pno_scan);
+           ALOGE("on_time_hs20: = %d", ((wifi_radio_stat *)data)->on_time_hs20);
            return NL_SKIP;
         }
 	(*mHandler.on_link_stats_results)(id,
diff --git a/bcmdhd/wifi_hal/wifi_hal.cpp b/bcmdhd/wifi_hal/wifi_hal.cpp
index 6f14a66..1d02b7b 100644
--- a/bcmdhd/wifi_hal/wifi_hal.cpp
+++ b/bcmdhd/wifi_hal/wifi_hal.cpp
@@ -53,6 +53,9 @@
 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
 static int wifi_add_membership(wifi_handle handle, const char *group);
 static wifi_error wifi_init_interfaces(wifi_handle handle);
+static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
+                        iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
+static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
 
 typedef enum wifi_attr {
     ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
@@ -60,6 +63,12 @@
     ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI
 } wifi_attr_t;
 
+enum wifi_rssi_monitor_attr {
+    RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
+    RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
+    RSSI_MONITOR_ATTRIBUTE_START,
+};
+
 /* Initialize/Cleanup */
 
 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
@@ -134,6 +143,7 @@
     fn->wifi_set_country_code = wifi_set_country_code;
     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
     fn->wifi_set_log_handler = wifi_set_log_handler;
+    fn->wifi_reset_log_handler = wifi_reset_log_handler;
     fn->wifi_set_alert_handler = wifi_set_alert_handler;
     fn->wifi_get_firmware_version = wifi_get_firmware_version;
     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
@@ -145,6 +155,10 @@
     fn->wifi_set_bssid_preference = wifi_set_bssid_preference;
     fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
     fn->wifi_enable_lazy_roam = wifi_enable_lazy_roam;
+    fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
+    fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
+    fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
+    fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
     return WIFI_SUCCESS;
 }
 
@@ -624,6 +638,121 @@
     }
 };
 
+class SetRSSIMonitorCommand : public WifiCommand {
+private:
+    s8 mMax_rssi;
+    s8 mMin_rssi;
+    wifi_rssi_event_handler mHandler;
+public:
+    SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
+                s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
+        : WifiCommand(handle, id), mMax_rssi(max_rssi), mMin_rssi(min_rssi), mHandler(eh)
+        {
+        }
+   int createRequest(WifiRequest& request, int enable) {
+        int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
+        if (result < 0) {
+            return result;
+        }
+
+        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+        result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
+        if (result < 0) {
+            return result;
+        }
+        ALOGD("create request");
+        result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
+        if (result < 0) {
+            return result;
+        }
+        result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable);
+        if (result < 0) {
+            return result;
+        }
+        request.attr_end(data);
+        return result;
+    }
+
+    int start() {
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request, 1);
+        if (result < 0) {
+            return result;
+        }
+        result = requestResponse(request);
+        if (result < 0) {
+            ALOGI("Failed to set RSSI Monitor, result = %d", result);
+            return result;
+        }
+        ALOGI("Successfully set RSSI monitoring");
+        registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+
+
+        if (result < 0) {
+            unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+            return result;
+        }
+        ALOGI("Done!");
+        return result;
+    }
+
+    virtual int cancel() {
+
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request, 0);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("failed to create request; result = %d", result);
+        } else {
+            result = requestResponse(request);
+            if (result != WIFI_SUCCESS) {
+                ALOGE("failed to stop RSSI monitoring = %d", result);
+            }
+        }
+        unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
+        return WIFI_SUCCESS;
+    }
+
+    virtual int handleResponse(WifiEvent& reply) {
+        /* Nothing to do on response! */
+        return NL_SKIP;
+    }
+
+   virtual int handleEvent(WifiEvent& event) {
+        ALOGI("Got a RSSI monitor event");
+
+        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
+        int len = event.get_vendor_data_len();
+
+        if (vendor_data == NULL || len == 0) {
+            ALOGI("RSSI monitor: No data");
+            return NL_SKIP;
+        }
+        /* driver<->HAL event structure */
+        #define RSSI_MONITOR_EVT_VERSION   1
+        typedef struct {
+            u8 version;
+            s8 cur_rssi;
+            mac_addr BSSID;
+        } rssi_monitor_evt;
+
+        rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
+
+        if (data->version != RSSI_MONITOR_EVT_VERSION) {
+            ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION);
+            return NL_SKIP;
+        }
+
+        if (*mHandler.on_rssi_threshold_breached) {
+            (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
+        } else {
+            ALOGW("No RSSI monitor handler registered");
+        }
+
+        return NL_SKIP;
+    }
+
+};
+
 class GetFeatureSetCommand : public WifiCommand {
 
 private:
@@ -851,4 +980,33 @@
     return (wifi_error) command.requestResponse();
 }
 
+static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
+                        iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
+{
+    ALOGD("Start RSSI monitor %d", id);
+    wifi_handle handle = getWifiHandle(iface);
+    SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
+    wifi_register_cmd(handle, id, cmd);
+    return (wifi_error)cmd->start();
+}
+
+
+static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
+{
+    ALOGD("Stopping RSSI monitor");
+
+    if(id == -1) {
+        wifi_rssi_event_handler handler;
+        s8 max_rssi = 0, min_rssi = 0;
+        wifi_handle handle = getWifiHandle(iface);
+        memset(&handler, 0, sizeof(handler));
+        SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
+                                                    max_rssi, min_rssi, handler);
+        cmd->cancel();
+        cmd->releaseRef();
+        return WIFI_SUCCESS;
+    }
+    return wifi_cancel_cmd(id, iface);
+}
+
 /////////////////////////////////////////////////////////////////////////////
diff --git a/bcmdhd/wifi_hal/wifi_logger.cpp b/bcmdhd/wifi_hal/wifi_logger.cpp
index e93ae97..1ef307c 100644
--- a/bcmdhd/wifi_hal/wifi_logger.cpp
+++ b/bcmdhd/wifi_hal/wifi_logger.cpp
@@ -36,6 +36,7 @@
     LOGGER_GET_RING_STATUS,
     LOGGER_GET_RING_DATA,
     LOGGER_GET_FEATURE,
+    LOGGER_RESET_LOGGING,
 } DEBUG_SUB_COMMAND;
 
 typedef enum {
@@ -260,7 +261,7 @@
     }
 
     int start() {
-        ALOGD("Start debug command");
+        // ALOGD("Start debug command");
         WifiRequest request(familyId(), ifaceId());
         int result = createRequest(request);
         if (result != WIFI_SUCCESS) {
@@ -445,6 +446,9 @@
     SetLogHandler(wifi_interface_handle iface, int id, wifi_ring_buffer_data_handler handler)
         : WifiCommand(iface, id), mHandler(handler)
     { }
+    SetLogHandler(wifi_interface_handle iface, int id)
+        : WifiCommand(iface, id)
+    { }
 
     int start() {
         ALOGD("Register log handler");
@@ -453,10 +457,26 @@
     }
 
     virtual int cancel() {
-        /* TODO: send a command to driver to stop generating logging events */
+        /* Send a command to driver to stop generating logging events */
+        ALOGD("Reset event handler");
+
+        WifiRequest request(familyId(), ifaceId());
+        int result = request.create(GOOGLE_OUI, LOGGER_RESET_LOGGING);
+
+        if (result != WIFI_SUCCESS) {
+            ALOGE("failed to create reset request; result = %d", result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("failed to request reset; result = %d", result);
+            return result;
+        }
 
         /* unregister event handler */
         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_DEBUG_RING_EVENT);
+        ALOGD("Success to reset event handler");
         return WIFI_SUCCESS;
     }
 
@@ -464,11 +484,11 @@
         char *buffer = NULL;
         int buffer_size = 0;
 
-        ALOGD("In SetLogHandler::handleEvent");
+        // ALOGD("In SetLogHandler::handleEvent");
         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
         int len = event.get_vendor_data_len();
         int event_id = event.get_vendor_subcmd();
-        ALOGI("Got Logger event: %d", event_id);
+        // ALOGI("Got Logger event: %d", event_id);
 
         if (vendor_data == NULL || len == 0) {
             ALOGE("No Debug data found");
@@ -491,7 +511,7 @@
                 }
             }
 
-            ALOGI("Retrieved Debug data");
+            // ALOGI("Retrieved Debug data");
             if (mHandler.on_ring_buffer_data) {
                 (*mHandler.on_ring_buffer_data)((char *)status.name, buffer, buffer_size,
                         &status);
@@ -520,6 +540,20 @@
     }
 }
 
+wifi_error wifi_reset_log_handler(wifi_request_id id, wifi_interface_handle iface)
+{
+    wifi_handle handle = getWifiHandle(iface);
+    SetLogHandler *cmd = new SetLogHandler(iface, id);
+
+    ALOGI("Logger reset, handle = %p", handle);
+    if (cmd) {
+        cmd->cancel();
+        cmd->releaseRef();
+        return WIFI_SUCCESS;
+    }
+    return WIFI_ERROR_INVALID_ARGS;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 class SetAlertHandler : public WifiCommand
 {
diff --git a/bcmdhd/wifi_hal/wifi_offload.cpp b/bcmdhd/wifi_hal/wifi_offload.cpp
new file mode 100644
index 0000000..936ca40
--- /dev/null
+++ b/bcmdhd/wifi_hal/wifi_offload.cpp
@@ -0,0 +1,229 @@
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <linux/rtnetlink.h>
+#include <netpacket/packet.h>
+#include <linux/filter.h>
+#include <linux/errqueue.h>
+
+#include <linux/pkt_sched.h>
+#include <netlink/object-api.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink-types.h>
+
+#include "nl80211_copy.h"
+#include "sync.h"
+
+#define LOG_TAG  "WifiHAL"
+
+#include <utils/Log.h>
+
+#include "wifi_hal.h"
+#include "common.h"
+#include "cpp_bindings.h"
+
+using namespace android;
+
+typedef enum {
+    WIFI_OFFLOAD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
+    WIFI_OFFLOAD_STOP_MKEEP_ALIVE,
+} WIFI_OFFLOAD_SUB_COMMAND;
+
+typedef enum {
+    MKEEP_ALIVE_ATTRIBUTE_ID,
+    MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
+    MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
+    MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
+    MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
+    MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
+} WIFI_MKEEP_ALIVE_ATTRIBUTE;
+
+typedef enum {
+    START_MKEEP_ALIVE,
+    STOP_MKEEP_ALIVE,
+} GetCmdType;
+
+///////////////////////////////////////////////////////////////////////////////
+class MKeepAliveCommand : public WifiCommand
+{
+    u8 mIndex;
+    u8 *mIpPkt;
+    u16 mIpPktLen;
+    u8 *mSrcMacAddr;
+    u8 *mDstMacAddr;
+    u32 mPeriodMsec;
+    GetCmdType mType;
+
+public:
+
+    // constructor for start sending
+    MKeepAliveCommand(wifi_interface_handle iface, u8 index, u8 *ip_packet, u16 ip_packet_len,
+            u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec, GetCmdType cmdType)
+        : WifiCommand(iface, 0), mIndex(index), mIpPkt(ip_packet), mIpPktLen(ip_packet_len),
+        mSrcMacAddr(src_mac_addr), mDstMacAddr(dst_mac_addr), mPeriodMsec(period_msec),
+        mType(cmdType)
+    { }
+
+    // constructor for stop sending
+    MKeepAliveCommand(wifi_interface_handle iface, u8 index, GetCmdType cmdType)
+        : WifiCommand(iface, 0), mIndex(index), mType(cmdType)
+    { }
+
+    int createRequest(WifiRequest &request) {
+        int result;
+
+        switch (mType) {
+            case START_MKEEP_ALIVE:
+            {
+                result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_START_MKEEP_ALIVE);
+                if (result != WIFI_SUCCESS) {
+                    ALOGE("Failed to create start keep alive request; result = %d", result);
+                    return result;
+                }
+
+                nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+                result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex);
+                if (result < 0) {
+                    ALOGE("Failed to put id request; result = %d", result);
+                    return result;
+                }
+
+                result = request.put_u16(MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, mIpPktLen);
+                if (result < 0) {
+                    ALOGE("Failed to put ip pkt len request; result = %d", result);
+                    return result;
+                }
+
+                result = request.put(MKEEP_ALIVE_ATTRIBUTE_IP_PKT, (u8*)mIpPkt, mIpPktLen);
+                if (result < 0) {
+                    ALOGE("Failed to put ip pkt request; result = %d", result);
+                    return result;
+                }
+
+                result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, mSrcMacAddr);
+                if (result < 0) {
+                    ALOGE("Failed to put src mac address request; result = %d", result);
+                    return result;
+                }
+
+                result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, mDstMacAddr);
+                if (result < 0) {
+                    ALOGE("Failed to put dst mac address request; result = %d", result);
+                    return result;
+                }
+
+                result = request.put_u32(MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, mPeriodMsec);
+                if (result < 0) {
+                    ALOGE("Failed to put period request; result = %d", result);
+                    return result;
+                }
+
+                request.attr_end(data);
+                break;
+            }
+
+            case STOP_MKEEP_ALIVE:
+            {
+                result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_STOP_MKEEP_ALIVE);
+                if (result != WIFI_SUCCESS) {
+                    ALOGE("Failed to create stop keep alive request; result = %d", result);
+                    return result;
+                }
+
+                nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
+
+                result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex);
+                if (result < 0) {
+                    ALOGE("Failed to put id request; result = %d", result);
+                    return result;
+                }
+
+                request.attr_end(data);
+                break;
+            }
+
+            default:
+                ALOGE("Unknown wifi keep alive command");
+                result = WIFI_ERROR_UNKNOWN;
+        }
+        return result;
+    }
+
+    int start() {
+        ALOGD("Start mkeep_alive command");
+        WifiRequest request(familyId(), ifaceId());
+        int result = createRequest(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to create keep alive request; result = %d", result);
+            return result;
+        }
+
+        result = requestResponse(request);
+        if (result != WIFI_SUCCESS) {
+            ALOGE("Failed to register keep alive response; result = %d", result);
+        }
+        return result;
+    }
+
+    virtual int handleResponse(WifiEvent& reply) {
+        ALOGD("In MKeepAliveCommand::handleResponse");
+
+        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
+            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
+            return NL_SKIP;
+        }
+
+        switch (mType) {
+            case START_MKEEP_ALIVE:
+            case STOP_MKEEP_ALIVE:
+                break;
+
+            default:
+                ALOGW("Unknown mkeep_alive command");
+        }
+        return NL_OK;
+    }
+
+    virtual int handleEvent(WifiEvent& event) {
+        /* NO events! */
+        return NL_SKIP;
+    }
+};
+
+
+/* API to send specified mkeep_alive packet periodically. */
+wifi_error wifi_start_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface,
+        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,
+                src_mac_addr, dst_mac_addr, period_msec, START_MKEEP_ALIVE);
+        wifi_error result = (wifi_error)cmd->start();
+        delete cmd;
+        return result;
+    } else {
+        ALOGE("Invalid mkeep_alive parameters");
+        return  WIFI_ERROR_INVALID_ARGS;
+    }
+}
+
+/* API to stop sending mkeep_alive packet. */
+wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface)
+{
+    if (index > 0 && index <= N_AVAIL_ID) {
+        MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, STOP_MKEEP_ALIVE);
+        wifi_error result = (wifi_error)cmd->start();
+        delete cmd;
+        return result;
+    } else {
+        ALOGE("Invalid mkeep_alive parameters");
+        return  WIFI_ERROR_INVALID_ARGS;
+    }
+}