]> nv-tegra.nvidia Code Review - android/platform/hardware/broadcom/wlan.git/blob - bcmdhd/wifi_hal/wifi_offload.cpp
net: wireless: bcmdhd: update bcm4358 FW (7.112.201.3) am: 38cfc377c2
[android/platform/hardware/broadcom/wlan.git] / bcmdhd / wifi_hal / wifi_offload.cpp
1 #include <stdint.h>
2 #include <fcntl.h>
3 #include <sys/socket.h>
4 #include <netlink/genl/genl.h>
5 #include <netlink/genl/family.h>
6 #include <netlink/genl/ctrl.h>
7 #include <linux/rtnetlink.h>
8 #include <netpacket/packet.h>
9 #include <linux/filter.h>
10 #include <linux/errqueue.h>
11
12 #include <linux/pkt_sched.h>
13 #include <netlink/object-api.h>
14 #include <netlink/netlink.h>
15 #include <netlink/socket.h>
16 #include <netlink-types.h>
17
18 #include "nl80211_copy.h"
19 #include "sync.h"
20
21 #define LOG_TAG  "WifiHAL"
22
23 #include <utils/Log.h>
24
25 #include "wifi_hal.h"
26 #include "common.h"
27 #include "cpp_bindings.h"
28
29 using namespace android;
30
31 typedef enum {
32     WIFI_OFFLOAD_START_MKEEP_ALIVE = ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START,
33     WIFI_OFFLOAD_STOP_MKEEP_ALIVE,
34 } WIFI_OFFLOAD_SUB_COMMAND;
35
36 typedef enum {
37     MKEEP_ALIVE_ATTRIBUTE_ID,
38     MKEEP_ALIVE_ATTRIBUTE_IP_PKT,
39     MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN,
40     MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR,
41     MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR,
42     MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC
43 } WIFI_MKEEP_ALIVE_ATTRIBUTE;
44
45 typedef enum {
46     START_MKEEP_ALIVE,
47     STOP_MKEEP_ALIVE,
48 } GetCmdType;
49
50 ///////////////////////////////////////////////////////////////////////////////
51 class MKeepAliveCommand : public WifiCommand
52 {
53     u8 mIndex;
54     u8 *mIpPkt;
55     u16 mIpPktLen;
56     u8 *mSrcMacAddr;
57     u8 *mDstMacAddr;
58     u32 mPeriodMsec;
59     GetCmdType mType;
60
61 public:
62
63     // constructor for start sending
64     MKeepAliveCommand(wifi_interface_handle iface, u8 index, u8 *ip_packet, u16 ip_packet_len,
65             u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec, GetCmdType cmdType)
66         : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mIpPkt(ip_packet),
67         mIpPktLen(ip_packet_len), mSrcMacAddr(src_mac_addr), mDstMacAddr(dst_mac_addr),
68         mPeriodMsec(period_msec), mType(cmdType)
69     { }
70
71     // constructor for stop sending
72     MKeepAliveCommand(wifi_interface_handle iface, u8 index, GetCmdType cmdType)
73         : WifiCommand("MKeepAliveCommand", iface, 0), mIndex(index), mType(cmdType)
74     { }
75
76     int createRequest(WifiRequest &request) {
77         int result;
78
79         switch (mType) {
80             case START_MKEEP_ALIVE:
81             {
82                 result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_START_MKEEP_ALIVE);
83                 if (result != WIFI_SUCCESS) {
84                     ALOGE("Failed to create start keep alive request; result = %d", result);
85                     return result;
86                 }
87
88                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
89
90                 result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex);
91                 if (result < 0) {
92                     ALOGE("Failed to put id request; result = %d", result);
93                     return result;
94                 }
95
96                 result = request.put_u16(MKEEP_ALIVE_ATTRIBUTE_IP_PKT_LEN, mIpPktLen);
97                 if (result < 0) {
98                     ALOGE("Failed to put ip pkt len request; result = %d", result);
99                     return result;
100                 }
101
102                 result = request.put(MKEEP_ALIVE_ATTRIBUTE_IP_PKT, (u8*)mIpPkt, mIpPktLen);
103                 if (result < 0) {
104                     ALOGE("Failed to put ip pkt request; result = %d", result);
105                     return result;
106                 }
107
108                 result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_SRC_MAC_ADDR, mSrcMacAddr);
109                 if (result < 0) {
110                     ALOGE("Failed to put src mac address request; result = %d", result);
111                     return result;
112                 }
113
114                 result = request.put_addr(MKEEP_ALIVE_ATTRIBUTE_DST_MAC_ADDR, mDstMacAddr);
115                 if (result < 0) {
116                     ALOGE("Failed to put dst mac address request; result = %d", result);
117                     return result;
118                 }
119
120                 result = request.put_u32(MKEEP_ALIVE_ATTRIBUTE_PERIOD_MSEC, mPeriodMsec);
121                 if (result < 0) {
122                     ALOGE("Failed to put period request; result = %d", result);
123                     return result;
124                 }
125
126                 request.attr_end(data);
127                 break;
128             }
129
130             case STOP_MKEEP_ALIVE:
131             {
132                 result = request.create(GOOGLE_OUI, WIFI_OFFLOAD_STOP_MKEEP_ALIVE);
133                 if (result != WIFI_SUCCESS) {
134                     ALOGE("Failed to create stop keep alive request; result = %d", result);
135                     return result;
136                 }
137
138                 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
139
140                 result = request.put_u8(MKEEP_ALIVE_ATTRIBUTE_ID, mIndex);
141                 if (result < 0) {
142                     ALOGE("Failed to put id request; result = %d", result);
143                     return result;
144                 }
145
146                 request.attr_end(data);
147                 break;
148             }
149
150             default:
151                 ALOGE("Unknown wifi keep alive command");
152                 result = WIFI_ERROR_UNKNOWN;
153         }
154         return result;
155     }
156
157     int start() {
158         ALOGD("Start mkeep_alive command");
159         WifiRequest request(familyId(), ifaceId());
160         int result = createRequest(request);
161         if (result != WIFI_SUCCESS) {
162             ALOGE("Failed to create keep alive request; result = %d", result);
163             return result;
164         }
165
166         result = requestResponse(request);
167         if (result != WIFI_SUCCESS) {
168             ALOGE("Failed to register keep alive response; result = %d", result);
169         }
170         return result;
171     }
172
173     virtual int handleResponse(WifiEvent& reply) {
174         ALOGD("In MKeepAliveCommand::handleResponse");
175
176         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
177             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
178             return NL_SKIP;
179         }
180
181         switch (mType) {
182             case START_MKEEP_ALIVE:
183             case STOP_MKEEP_ALIVE:
184                 break;
185
186             default:
187                 ALOGW("Unknown mkeep_alive command");
188         }
189         return NL_OK;
190     }
191
192     virtual int handleEvent(WifiEvent& event) {
193         /* NO events! */
194         return NL_SKIP;
195     }
196 };
197
198
199 /* API to send specified mkeep_alive packet periodically. */
200 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface,
201         u8 *ip_packet, u16 ip_packet_len, u8 *src_mac_addr, u8 *dst_mac_addr, u32 period_msec)
202 {
203     if ((index > 0 && index <= N_AVAIL_ID) && (ip_packet != NULL) && (src_mac_addr != NULL)
204             && (dst_mac_addr != NULL) && (period_msec > 0)
205             && (ip_packet_len <= MKEEP_ALIVE_IP_PKT_MAX)) {
206         MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, ip_packet, ip_packet_len,
207                 src_mac_addr, dst_mac_addr, period_msec, START_MKEEP_ALIVE);
208         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
209         wifi_error result = (wifi_error)cmd->start();
210         cmd->releaseRef();
211         return result;
212     } else {
213         ALOGE("Invalid mkeep_alive parameters");
214         return  WIFI_ERROR_INVALID_ARGS;
215     }
216 }
217
218 /* API to stop sending mkeep_alive packet. */
219 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id index, wifi_interface_handle iface)
220 {
221     if (index > 0 && index <= N_AVAIL_ID) {
222         MKeepAliveCommand *cmd = new MKeepAliveCommand(iface, index, STOP_MKEEP_ALIVE);
223         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
224         wifi_error result = (wifi_error)cmd->start();
225         cmd->releaseRef();
226         return result;
227     } else {
228         ALOGE("Invalid mkeep_alive parameters");
229         return  WIFI_ERROR_INVALID_ARGS;
230     }
231 }