Add wifi offload feature: mkeep_alive
Ecco Park [Fri, 19 Jun 2015 00:02:35 +0000 (17:02 -0700)]
    b/21405946

Change-Id: I8e9a2f2b2f76d1d689fcd645b9332b290d710ae6
Signed-off-by: JerryLee <jerrylee@broadcom.com>

bcmdhd/wifi_hal/Android.mk
bcmdhd/wifi_hal/common.h
bcmdhd/wifi_hal/wifi_hal.cpp
bcmdhd/wifi_hal/wifi_offload.cpp [new file with mode: 0644]

index bb8514a..ea19efd 100644 (file)
@@ -32,7 +32,8 @@ LOCAL_SRC_FILES := \
        cpp_bindings.cpp \
        gscan.cpp \
        link_layer_stats.cpp \
-       wifi_logger.cpp
+       wifi_logger.cpp \
+       wifi_offload.cpp
 
 LOCAL_MODULE := libwifi-hal-bcm
 
index 5df02fe..8c09c16 100644 (file)
@@ -59,6 +59,10 @@ typedef enum {
     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;
index 51cf7d6..1d02b7b 100644 (file)
@@ -157,6 +157,8 @@ wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
     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;
 }
 
diff --git a/bcmdhd/wifi_hal/wifi_offload.cpp b/bcmdhd/wifi_hal/wifi_offload.cpp
new file mode 100644 (file)
index 0000000..936ca40
--- /dev/null
@@ -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;
+    }
+}