1cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song/* 2cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * Copyright (C) 2017 The Android Open Source Project 3cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * 4cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * Portions copyright (C) 2017 Broadcom Limited 5cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * 6cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * Licensed under the Apache License, Version 2.0 (the "License"); 7cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * you may not use this file except in compliance with the License. 8cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * You may obtain a copy of the License at 9cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * 10cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * http://www.apache.org/licenses/LICENSE-2.0 11cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * 12cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * Unless required by applicable law or agreed to in writing, software 13cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * distributed under the License is distributed on an "AS IS" BASIS, 14cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * See the License for the specific language governing permissions and 16cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song * limitations under the License. 17cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song */ 18cb8188ea5d3dbce3bf46522bc9e562ffa04db2e7Insun Song 198f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <stdint.h> 208f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <fcntl.h> 218f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <sys/socket.h> 228f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <netlink/genl/genl.h> 238f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <netlink/genl/family.h> 248f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <netlink/genl/ctrl.h> 258f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <linux/rtnetlink.h> 268f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <netpacket/packet.h> 278f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <linux/filter.h> 288f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <linux/errqueue.h> 298f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 308f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <linux/pkt_sched.h> 318f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <netlink/object-api.h> 328f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <netlink/netlink.h> 338f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include <netlink/socket.h> 34c4ca0d79752e6262b0800c971ea2b4bb6d4e0c58Paul Stewart#include <netlink-private/object-api.h> 35c4ca0d79752e6262b0800c971ea2b4bb6d4e0c58Paul Stewart#include <netlink-private/types.h> 36c4ca0d79752e6262b0800c971ea2b4bb6d4e0c58Paul Stewart 378f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 388f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include "nl80211_copy.h" 398f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include "sync.h" 408f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 418f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#define LOG_TAG "WifiHAL" 428f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 433d58fa92a87578b0944aec2c47ca23ebbf5720e3Tom Cherry#include <log/log.h> 448f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 458f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include "wifi_hal.h" 468f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include "common.h" 478f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park#include "cpp_bindings.h" 488f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 498f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Parktypedef enum { 508f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park WIFI_OFFLOAD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START, 518f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park WIFI_OFFLOAD_STOP_MKEEP_ALIVE, 528f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park} WIFI_OFFLOAD_SUB_COMMAND; 538f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 548f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Parktypedef enum { 558f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKEEP_ALIVE_ATTRIBUTE_ID, 568f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKEEP_ALIVE_ATTRIBUTE_IP_PKT, 578f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, 588f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, 598f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, 608f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC 618f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park} WIFI_MKEEP_ALIVE_ATTRIBUTE; 628f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 638f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Parktypedef enum { 648f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park START_MKEEP_ALIVE, 658f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park STOP_MKEEP_ALIVE, 668f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park} GetCmdType; 678f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 688f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park/////////////////////////////////////////////////////////////////////////////// 698f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Parkclass MKeepAliveCommand : public WifiCommand 708f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park{ 718f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park u8 mIndex; 728f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park u8 *mIpPkt; 738f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park u16 mIpPktLen; 748f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park u8 *mSrcMacAddr; 758f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park u8 *mDstMacAddr; 768f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park u32 mPeriodMsec; 778f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park GetCmdType mType; 788f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 798f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Parkpublic: 808f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 818f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park // constructor for start sending 828f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKeepAliveCommand(wifi_interface_handle iface, u8 index, u8 *ip_packet, u16 ip_packet_len, 838f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec, GetCmdType cmdType) 84d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mIpPkt(ip_packet), 85d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande mIpPktLen(ip_packet_len), mSrcMacAddr(src_mac_addr), mDstMacAddr(dst_mac_addr), 86d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande mPeriodMsec(period_msec), mType(cmdType) 878f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park { } 888f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 898f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park // constructor for stop sending 908f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKeepAliveCommand(wifi_interface_handle iface, u8 index, GetCmdType cmdType) 91d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mType(cmdType) 928f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park { } 938f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 948f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park int createRequest(WifiRequest &request) { 958f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park int result; 968f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 978f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park switch (mType) { 988f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park case START_MKEEP_ALIVE: 998f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park { 1008f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_START_MKEEP_ALIVE); 1018f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result != WIFI_SUCCESS) { 1028f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to create start keep alive request; result = %d", result); 1038f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1048f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1058f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1068f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1078f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1088f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex); 1098f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result < 0) { 1108f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to put id request; result = %d", result); 1118f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1128f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1138f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1148f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = request.put_u16(MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, mIpPktLen); 1158f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result < 0) { 1168f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to put ip pkt len request; result = %d", result); 1178f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1188f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1198f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1208f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = request.put(MKEEP_ALIVE_ATTRIBUTE_IP_PKT, (u8*)mIpPkt, mIpPktLen); 1218f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result < 0) { 1228f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to put ip pkt request; result = %d", result); 1238f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1248f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1258f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1268f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, mSrcMacAddr); 1278f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result < 0) { 1288f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to put src mac address request; result = %d", result); 1298f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1308f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1318f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1328f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, mDstMacAddr); 1338f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result < 0) { 1348f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to put dst mac address request; result = %d", result); 1358f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1368f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1378f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1388f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = request.put_u32(MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, mPeriodMsec); 1398f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result < 0) { 1408f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to put period request; result = %d", result); 1418f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1428f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1438f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1448f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park request.attr_end(data); 1458f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park break; 1468f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1478f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1488f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park case STOP_MKEEP_ALIVE: 1498f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park { 1508f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_STOP_MKEEP_ALIVE); 1518f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result != WIFI_SUCCESS) { 1528f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to create stop keep alive request; result = %d", result); 1538f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1548f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1558f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1568f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1578f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1588f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex); 1598f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result < 0) { 1608f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to put id request; result = %d", result); 1618f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1628f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1638f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1648f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park request.attr_end(data); 1658f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park break; 1668f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1678f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1688f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park default: 1698f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Unknown wifi keep alive command"); 1708f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = WIFI_ERROR_UNKNOWN; 1718f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1728f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1738f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1748f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1758f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park int start() { 1768f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGD("Start mkeep_alive command"); 1778f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park WifiRequest request(familyId(), ifaceId()); 1788f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park int result = createRequest(request); 1798f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result != WIFI_SUCCESS) { 1808f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to create keep alive request; result = %d", result); 1818f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1828f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1838f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1848f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park result = requestResponse(request); 1858f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (result != WIFI_SUCCESS) { 1868f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Failed to register keep alive response; result = %d", result); 1878f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1888f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 1898f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1908f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1918f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park virtual int handleResponse(WifiEvent& reply) { 1928f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGD("In MKeepAliveCommand::handleResponse"); 1938f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1948f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (reply.get_cmd() != NL80211_CMD_VENDOR) { 1958f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 1968f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return NL_SKIP; 1978f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 1988f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 1998f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park switch (mType) { 2008f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park case START_MKEEP_ALIVE: 2018f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park case STOP_MKEEP_ALIVE: 2028f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park break; 2038f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 2048f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park default: 2058f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGW("Unknown mkeep_alive command"); 2068f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 2078f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return NL_OK; 2088f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 2098f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 2108f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park virtual int handleEvent(WifiEvent& event) { 2118f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park /* NO events! */ 2128f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return NL_SKIP; 2138f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 2148f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park}; 2158f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 2168f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 2178f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park/* API to send specified mkeep_alive packet periodically. */ 2188f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Parkwifi_error wifi_start_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface, 2198f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park u8 *ip_packet, u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec) 2208f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park{ 2218f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if ((index > 0 && index <= N_AVAIL_ID) && (ip_packet != NULL) && (src_mac_addr != NULL) 2228f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park && (dst_mac_addr != NULL) && (period_msec > 0) 2238f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park && (ip_packet_len <= MKEEP_ALIVE_IP_PKT_MAX)) { 2248f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, ip_packet, ip_packet_len, 2258f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park src_mac_addr, dst_mac_addr, period_msec, START_MKEEP_ALIVE); 2266af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 2278f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park wifi_error result = (wifi_error)cmd->start(); 2286af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma cmd->releaseRef(); 2298f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 2308f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } else { 2318f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Invalid mkeep_alive parameters"); 2328f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return WIFI_ERROR_INVALID_ARGS; 2338f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 2348f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park} 2358f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park 2368f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park/* API to stop sending mkeep_alive packet. */ 2378f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Parkwifi_error wifi_stop_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface) 2388f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park{ 2398f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park if (index > 0 && index <= N_AVAIL_ID) { 2408f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, STOP_MKEEP_ALIVE); 2416af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 2428f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park wifi_error result = (wifi_error)cmd->start(); 2436af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma cmd->releaseRef(); 2448f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return result; 2458f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } else { 2468f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park ALOGE("Invalid mkeep_alive parameters"); 2478f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park return WIFI_ERROR_INVALID_ARGS; 2488f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park } 2498f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park} 250