net: wireless: bcmdhd: update bcm4358 FW (7.112.201.3) am: 38cfc377c2 am: 0c97e9a22b
[android/platform/hardware/broadcom/wlan.git] / bcmdhd / wifi_hal / wifi_hal.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 #include <errno.h>
12
13 #include <linux/pkt_sched.h>
14 #include <netlink/object-api.h>
15 #include <netlink/netlink.h>
16 #include <netlink/socket.h>
17 #include <netlink/attr.h>
18 #include <netlink/handlers.h>
19 #include <netlink/msg.h>
20
21 #include <dirent.h>
22 #include <net/if.h>
23
24 #include "sync.h"
25
26 #define LOG_TAG  "WifiHAL"
27
28 #include <utils/Log.h>
29
30 #include "wifi_hal.h"
31 #include "common.h"
32 #include "cpp_bindings.h"
33 #include "rtt.h"
34 /*
35  BUGBUG: normally, libnl allocates ports for all connections it makes; but
36  being a static library, it doesn't really know how many other netlink connections
37  are made by the same process, if connections come from different shared libraries.
38  These port assignments exist to solve that problem - temporarily. We need to fix
39  libnl to try and allocate ports across the entire process.
40  */
41
42 #define WIFI_HAL_CMD_SOCK_PORT       644
43 #define WIFI_HAL_EVENT_SOCK_PORT     645
44
45 static void internal_event_handler(wifi_handle handle, int events);
46 static int internal_no_seq_check(nl_msg *msg, void *arg);
47 static int internal_valid_message_handler(nl_msg *msg, void *arg);
48 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
49 static int wifi_add_membership(wifi_handle handle, const char *group);
50 static wifi_error wifi_init_interfaces(wifi_handle handle);
51 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
52                         iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
53 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
54 static wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
55                             const u8 *program, u32 len);
56 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
57                 u32 *version, u32 *max_len);
58 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, u8 enable);
59
60 typedef enum wifi_attr {
61     ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
62     ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
63     ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
64     ANDR_WIFI_ATTRIBUTE_NODFS_SET,
65     ANDR_WIFI_ATTRIBUTE_COUNTRY,
66     ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE
67     // Add more attribute here
68 } wifi_attr_t;
69
70 enum wifi_rssi_monitor_attr {
71     RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
72     RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
73     RSSI_MONITOR_ATTRIBUTE_START,
74 };
75
76 enum wifi_apf_attr {
77     APF_ATTRIBUTE_VERSION,
78     APF_ATTRIBUTE_MAX_LEN,
79     APF_ATTRIBUTE_PROGRAM,
80     APF_ATTRIBUTE_PROGRAM_LEN
81 };
82
83 enum apf_request_type {
84     GET_APF_CAPABILITIES,
85     SET_APF_PROGRAM
86 };
87
88 /* Initialize/Cleanup */
89
90 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
91 {
92     uint32_t pid = getpid() & 0x3FFFFF;
93     nl_socket_set_local_port(sock, pid + (port << 22));
94 }
95
96 static nl_sock * wifi_create_nl_socket(int port)
97 {
98     // ALOGI("Creating socket");
99     struct nl_sock *sock = nl_socket_alloc();
100     if (sock == NULL) {
101         ALOGE("Could not create handle");
102         return NULL;
103     }
104
105     wifi_socket_set_local_port(sock, port);
106
107     struct sockaddr *addr = NULL;
108     // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
109
110     // ALOGI("Connecting socket");
111     if (nl_connect(sock, NETLINK_GENERIC)) {
112         ALOGE("Could not connect handle");
113         nl_socket_free(sock);
114         return NULL;
115     }
116
117     // ALOGI("Making socket nonblocking");
118     /*
119     if (nl_socket_set_nonblocking(sock)) {
120         ALOGE("Could make socket non-blocking");
121         nl_socket_free(sock);
122         return NULL;
123     }
124     */
125
126     return sock;
127 }
128
129 /*initialize function pointer table with Broadcom HHAL API*/
130 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
131 {
132     if (fn == NULL) {
133         return WIFI_ERROR_UNKNOWN;
134     }
135     fn->wifi_initialize = wifi_initialize;
136     fn->wifi_cleanup = wifi_cleanup;
137     fn->wifi_event_loop = wifi_event_loop;
138     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
139     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
140     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
141     fn->wifi_get_ifaces = wifi_get_ifaces;
142     fn->wifi_get_iface_name = wifi_get_iface_name;
143     fn->wifi_start_gscan = wifi_start_gscan;
144     fn->wifi_stop_gscan = wifi_stop_gscan;
145     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
146     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
147     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
148     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
149     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
150     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
151     fn->wifi_get_link_stats = wifi_get_link_stats;
152     fn->wifi_get_valid_channels = wifi_get_valid_channels;
153     fn->wifi_rtt_range_request = wifi_rtt_range_request;
154     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
155     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
156     fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
157     fn->wifi_enable_responder = wifi_enable_responder;
158     fn->wifi_disable_responder = wifi_disable_responder;
159     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
160     fn->wifi_start_logging = wifi_start_logging;
161     fn->wifi_set_epno_list = wifi_set_epno_list;
162     fn->wifi_reset_epno_list = wifi_reset_epno_list;
163     fn->wifi_set_country_code = wifi_set_country_code;
164     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
165     fn->wifi_set_log_handler = wifi_set_log_handler;
166     fn->wifi_reset_log_handler = wifi_reset_log_handler;
167     fn->wifi_set_alert_handler = wifi_set_alert_handler;
168     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
169     fn->wifi_get_firmware_version = wifi_get_firmware_version;
170     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
171     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
172     fn->wifi_get_ring_data = wifi_get_ring_data;
173     fn->wifi_get_driver_version = wifi_get_driver_version;
174     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
175     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
176     fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
177     fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
178     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
179     fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
180     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
181     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
182     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
183     fn->wifi_set_packet_filter = wifi_set_packet_filter;
184     return WIFI_SUCCESS;
185 }
186
187 wifi_error wifi_initialize(wifi_handle *handle)
188 {
189     srand(getpid());
190
191     ALOGI("Initializing wifi");
192     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
193     if (info == NULL) {
194         ALOGE("Could not allocate hal_info");
195         return WIFI_ERROR_UNKNOWN;
196     }
197
198     memset(info, 0, sizeof(*info));
199
200     ALOGI("Creating socket");
201     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
202         ALOGE("Could not create cleanup sockets");
203         free(info);
204         return WIFI_ERROR_UNKNOWN;
205     }
206
207     struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
208     if (cmd_sock == NULL) {
209         ALOGE("Could not create handle");
210         free(info);
211         return WIFI_ERROR_UNKNOWN;
212     }
213
214     struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
215     if (event_sock == NULL) {
216         ALOGE("Could not create handle");
217         nl_socket_free(cmd_sock);
218         free(info);
219         return WIFI_ERROR_UNKNOWN;
220     }
221
222     struct nl_cb *cb = nl_socket_get_cb(event_sock);
223     if (cb == NULL) {
224         ALOGE("Could not create handle");
225         nl_socket_free(cmd_sock);
226         nl_socket_free(event_sock);
227         free(info);
228         return WIFI_ERROR_UNKNOWN;
229     }
230
231     // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
232     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
233     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
234     nl_cb_put(cb);
235
236     info->cmd_sock = cmd_sock;
237     info->event_sock = event_sock;
238     info->clean_up = false;
239     info->in_event_loop = false;
240
241     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
242     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
243     info->num_event_cb = 0;
244
245     info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
246     info->alloc_cmd = DEFAULT_CMD_SIZE;
247     info->num_cmd = 0;
248
249     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
250     if (info->nl80211_family_id < 0) {
251         ALOGE("Could not resolve nl80211 familty id");
252         nl_socket_free(cmd_sock);
253         nl_socket_free(event_sock);
254         free(info);
255         return WIFI_ERROR_UNKNOWN;
256     }
257
258     pthread_mutex_init(&info->cb_lock, NULL);
259
260     *handle = (wifi_handle) info;
261
262     wifi_add_membership(*handle, "scan");
263     wifi_add_membership(*handle, "mlme");
264     wifi_add_membership(*handle, "regulatory");
265     wifi_add_membership(*handle, "vendor");
266
267     wifi_init_interfaces(*handle);
268     // ALOGI("Found %d interfaces", info->num_interfaces);
269
270
271     ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
272     return WIFI_SUCCESS;
273 }
274
275 static int wifi_add_membership(wifi_handle handle, const char *group)
276 {
277     hal_info *info = getHalInfo(handle);
278
279     int id = wifi_get_multicast_id(handle, "nl80211", group);
280     if (id < 0) {
281         ALOGE("Could not find group %s", group);
282         return id;
283     }
284
285     int ret = nl_socket_add_membership(info->event_sock, id);
286     if (ret < 0) {
287         ALOGE("Could not add membership to group %s", group);
288     }
289
290     // ALOGI("Successfully added membership for group %s", group);
291     return ret;
292 }
293
294 static void internal_cleaned_up_handler(wifi_handle handle)
295 {
296     hal_info *info = getHalInfo(handle);
297     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
298
299     if (info->cmd_sock != 0) {
300         close(info->cleanup_socks[0]);
301         close(info->cleanup_socks[1]);
302         nl_socket_free(info->cmd_sock);
303         nl_socket_free(info->event_sock);
304         info->cmd_sock = NULL;
305         info->event_sock = NULL;
306     }
307
308     (*cleaned_up_handler)(handle);
309     pthread_mutex_destroy(&info->cb_lock);
310     free(info);
311
312     ALOGI("Internal cleanup completed");
313 }
314
315 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
316 {
317     hal_info *info = getHalInfo(handle);
318     char buf[64];
319
320     info->cleaned_up_handler = handler;
321     if (write(info->cleanup_socks[0], "Exit", 4) < 1) {
322         // As a fallback set the cleanup flag to TRUE
323         ALOGE("could not write to the cleanup socket");
324     } else {
325         // Listen to the response
326         // Hopefully we dont get errors or get hung up
327         // Not much can be done in that case, but assume that
328         // it has rx'ed the Exit message to exit the thread.
329         // As a fallback set the cleanup flag to TRUE
330         memset(buf, 0, sizeof(buf));
331         int result = read(info->cleanup_socks[0], buf, sizeof(buf));
332         ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno);
333         if (strncmp(buf, "Done", 4) == 0) {
334             ALOGE("Event processing terminated");
335         } else {
336             ALOGD("Rx'ed %s", buf);
337         }
338     }
339     info->clean_up = true;
340     pthread_mutex_lock(&info->cb_lock);
341
342     int bad_commands = 0;
343
344     for (int i = 0; i < info->num_event_cb; i++) {
345         cb_info *cbi = &(info->event_cb[i]);
346         WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
347         ALOGI("Command left in event_cb %p:%s", cmd, (cmd ? cmd->getType(): ""));
348     }
349
350     while (info->num_cmd > bad_commands) {
351         int num_cmd = info->num_cmd;
352         cmd_info *cmdi = &(info->cmd[bad_commands]);
353         WifiCommand *cmd = cmdi->cmd;
354         if (cmd != NULL) {
355             ALOGI("Cancelling command %p:%s", cmd, cmd->getType());
356             pthread_mutex_unlock(&info->cb_lock);
357             cmd->cancel();
358             pthread_mutex_lock(&info->cb_lock);
359             if (num_cmd == info->num_cmd) {
360                 ALOGI("Cancelling command %p:%s did not work", cmd, (cmd ? cmd->getType(): ""));
361                 bad_commands++;
362             }
363             /* release reference added when command is saved */
364             cmd->releaseRef();
365         }
366     }
367
368     for (int i = 0; i < info->num_event_cb; i++) {
369         cb_info *cbi = &(info->event_cb[i]);
370         WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
371         ALOGE("Leaked command %p", cmd);
372     }
373     pthread_mutex_unlock(&info->cb_lock);
374     internal_cleaned_up_handler(handle);
375 }
376
377 static int internal_pollin_handler(wifi_handle handle)
378 {
379     hal_info *info = getHalInfo(handle);
380     struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
381     int res = nl_recvmsgs(info->event_sock, cb);
382     // ALOGD("nl_recvmsgs returned %d", res);
383     nl_cb_put(cb);
384     return res;
385 }
386
387 /* Run event handler */
388 void wifi_event_loop(wifi_handle handle)
389 {
390     hal_info *info = getHalInfo(handle);
391     if (info->in_event_loop) {
392         return;
393     } else {
394         info->in_event_loop = true;
395     }
396
397     pollfd pfd[2];
398     memset(&pfd[0], 0, sizeof(pollfd) * 2);
399
400     pfd[0].fd = nl_socket_get_fd(info->event_sock);
401     pfd[0].events = POLLIN;
402     pfd[1].fd = info->cleanup_socks[1];
403     pfd[1].events = POLLIN;
404
405     char buf[2048];
406     /* TODO: Add support for timeouts */
407
408     do {
409         int timeout = -1;                   /* Infinite timeout */
410         pfd[0].revents = 0;
411         pfd[1].revents = 0;
412         // ALOGI("Polling socket");
413         int result = poll(pfd, 2, timeout);
414         if (result < 0) {
415             // ALOGE("Error polling socket");
416         } else if (pfd[0].revents & POLLERR) {
417             ALOGE("POLL Error; error no = %d", errno);
418             int result2 = read(pfd[0].fd, buf, sizeof(buf));
419             ALOGE("Read after POLL returned %d, error no = %d", result2, errno);
420         } else if (pfd[0].revents & POLLHUP) {
421             ALOGE("Remote side hung up");
422             break;
423         } else if (pfd[0].revents & POLLIN) {
424             // ALOGI("Found some events!!!");
425             internal_pollin_handler(handle);
426         } else if (pfd[1].revents & POLLIN) {
427             memset(buf, 0, sizeof(buf));
428             int result2 = read(pfd[1].fd, buf, sizeof(buf));
429             ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno);
430             if (strncmp(buf, "Exit", 4) == 0) {
431                 ALOGD("Got a signal to exit!!!");
432                 if (write(pfd[1].fd, "Done", 4) < 1) {
433                     ALOGE("could not write to the cleanup socket");
434                 }
435                 break;
436             } else {
437                 ALOGD("Rx'ed %s on the cleanup socket\n", buf);
438             }
439         } else {
440             ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
441         }
442     } while (!info->clean_up);
443     ALOGI("Exit %s", __FUNCTION__);
444 }
445
446 ///////////////////////////////////////////////////////////////////////////////////////
447
448 static int internal_no_seq_check(struct nl_msg *msg, void *arg)
449 {
450     return NL_OK;
451 }
452
453 static int internal_valid_message_handler(nl_msg *msg, void *arg)
454 {
455     // ALOGI("got an event");
456
457     wifi_handle handle = (wifi_handle)arg;
458     hal_info *info = getHalInfo(handle);
459
460     WifiEvent event(msg);
461     int res = event.parse();
462     if (res < 0) {
463         ALOGE("Failed to parse event: %d", res);
464         return NL_SKIP;
465     }
466
467     int cmd = event.get_cmd();
468     uint32_t vendor_id = 0;
469     int subcmd = 0;
470
471     if (cmd == NL80211_CMD_VENDOR) {
472         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
473         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
474         ALOGV("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
475                 event.get_cmdString(), vendor_id, subcmd);
476     } else {
477         // ALOGV("event received %s", event.get_cmdString());
478     }
479
480     // ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
481     // event.log();
482
483     bool dispatched = false;
484
485     pthread_mutex_lock(&info->cb_lock);
486
487     for (int i = 0; i < info->num_event_cb; i++) {
488         if (cmd == info->event_cb[i].nl_cmd) {
489             if (cmd == NL80211_CMD_VENDOR
490                 && ((vendor_id != info->event_cb[i].vendor_id)
491                 || (subcmd != info->event_cb[i].vendor_subcmd)))
492             {
493                 /* event for a different vendor, ignore it */
494                 continue;
495             }
496
497             cb_info *cbi = &(info->event_cb[i]);
498             nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
499             void *cb_arg = cbi->cb_arg;
500             WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
501             if (cmd != NULL) {
502                 cmd->addRef();
503             }
504             pthread_mutex_unlock(&info->cb_lock);
505             if (cb_func)
506                 (*cb_func)(msg, cb_arg);
507             if (cmd != NULL) {
508                 cmd->releaseRef();
509             }
510
511             return NL_OK;
512         }
513     }
514
515     pthread_mutex_unlock(&info->cb_lock);
516     return NL_OK;
517 }
518
519 ///////////////////////////////////////////////////////////////////////////////////////
520
521 class GetMulticastIdCommand : public WifiCommand
522 {
523 private:
524     const char *mName;
525     const char *mGroup;
526     int   mId;
527 public:
528     GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
529         : WifiCommand("GetMulticastIdCommand", handle, 0)
530     {
531         mName = name;
532         mGroup = group;
533         mId = -1;
534     }
535
536     int getId() {
537         return mId;
538     }
539
540     virtual int create() {
541         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
542         // ALOGI("ctrl family = %d", nlctrlFamily);
543         int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
544         if (ret < 0) {
545             return ret;
546         }
547         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
548         return ret;
549     }
550
551     virtual int handleResponse(WifiEvent& reply) {
552
553         // ALOGI("handling reponse in %s", __func__);
554
555         struct nlattr **tb = reply.attributes();
556         struct genlmsghdr *gnlh = reply.header();
557         struct nlattr *mcgrp = NULL;
558         int i;
559
560         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
561             ALOGI("No multicast groups found");
562             return NL_SKIP;
563         } else {
564             // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
565         }
566
567         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
568
569             // ALOGI("Processing group");
570             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
571             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
572                 nla_len(mcgrp), NULL);
573             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
574                 continue;
575             }
576
577             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
578             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
579
580             // ALOGI("Found group name %s", grpName);
581
582             if (strncmp(grpName, mGroup, grpNameLen) != 0)
583                 continue;
584
585             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
586             break;
587         }
588
589         return NL_SKIP;
590     }
591
592 };
593
594 class SetPnoMacAddrOuiCommand : public WifiCommand {
595
596 private:
597     byte *mOui;
598     feature_set *fset;
599     feature_set *feature_matrix;
600     int *fm_size;
601     int set_size_max;
602 public:
603     SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
604         : WifiCommand("SetPnoMacAddrOuiCommand", handle, 0)
605     {
606         mOui = scan_oui;
607     }
608
609     int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
610         int result = request.create(GOOGLE_OUI, subcmd);
611         if (result < 0) {
612             return result;
613         }
614
615         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
616         result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
617         if (result < 0) {
618             return result;
619         }
620
621         request.attr_end(data);
622         return WIFI_SUCCESS;
623
624     }
625
626     int start() {
627         ALOGD("Sending mac address OUI");
628         WifiRequest request(familyId(), ifaceId());
629         int result = createRequest(request, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, mOui);
630         if (result != WIFI_SUCCESS) {
631             ALOGE("failed to create request; result = %d", result);
632             return result;
633         }
634
635         result = requestResponse(request);
636         if (result != WIFI_SUCCESS) {
637             ALOGE("failed to set scanning mac OUI; result = %d", result);
638         }
639
640         return result;
641     }
642 protected:
643     virtual int handleResponse(WifiEvent& reply) {
644          ALOGD("Request complete!");
645         /* Nothing to do on response! */
646         return NL_SKIP;
647     }
648 };
649
650 class SetNodfsCommand : public WifiCommand {
651
652 private:
653     u32 mNoDfs;
654 public:
655     SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
656         : WifiCommand("SetNodfsCommand", handle, 0) {
657         mNoDfs = nodfs;
658     }
659     virtual int create() {
660         int ret;
661
662         ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_NODFS_SET);
663         if (ret < 0) {
664             ALOGE("Can't create message to send to driver - %d", ret);
665             return ret;
666         }
667
668         nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
669         ret = mMsg.put_u32(ANDR_WIFI_ATTRIBUTE_NODFS_SET, mNoDfs);
670         if (ret < 0) {
671              return ret;
672         }
673
674         mMsg.attr_end(data);
675         return WIFI_SUCCESS;
676     }
677 };
678
679 class SetCountryCodeCommand : public WifiCommand {
680 private:
681     const char *mCountryCode;
682 public:
683     SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
684         : WifiCommand("SetCountryCodeCommand", handle, 0) {
685         mCountryCode = country_code;
686         }
687     virtual int create() {
688         int ret;
689
690         ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_COUNTRY_CODE);
691         if (ret < 0) {
692              ALOGE("Can't create message to send to driver - %d", ret);
693              return ret;
694         }
695
696         nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
697         ret = mMsg.put_string(ANDR_WIFI_ATTRIBUTE_COUNTRY, mCountryCode);
698         if (ret < 0) {
699             return ret;
700         }
701
702         mMsg.attr_end(data);
703         return WIFI_SUCCESS;
704
705     }
706 };
707
708 class SetRSSIMonitorCommand : public WifiCommand {
709 private:
710     s8 mMax_rssi;
711     s8 mMin_rssi;
712     wifi_rssi_event_handler mHandler;
713 public:
714     SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
715                 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
716         : WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi
717         (min_rssi), mHandler(eh)
718         {
719         }
720    int createRequest(WifiRequest& request, int enable) {
721         int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
722         if (result < 0) {
723             return result;
724         }
725
726         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
727         result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
728         if (result < 0) {
729             return result;
730         }
731         ALOGD("create request");
732         result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
733         if (result < 0) {
734             return result;
735         }
736         result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable);
737         if (result < 0) {
738             return result;
739         }
740         request.attr_end(data);
741         return result;
742     }
743
744     int start() {
745         WifiRequest request(familyId(), ifaceId());
746         int result = createRequest(request, 1);
747         if (result < 0) {
748             return result;
749         }
750         result = requestResponse(request);
751         if (result < 0) {
752             ALOGI("Failed to set RSSI Monitor, result = %d", result);
753             return result;
754         }
755         ALOGI("Successfully set RSSI monitoring");
756         registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
757
758
759         if (result < 0) {
760             unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
761             return result;
762         }
763         ALOGI("Done!");
764         return result;
765     }
766
767     virtual int cancel() {
768
769         WifiRequest request(familyId(), ifaceId());
770         int result = createRequest(request, 0);
771         if (result != WIFI_SUCCESS) {
772             ALOGE("failed to create request; result = %d", result);
773         } else {
774             result = requestResponse(request);
775             if (result != WIFI_SUCCESS) {
776                 ALOGE("failed to stop RSSI monitoring = %d", result);
777             }
778         }
779         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
780         return WIFI_SUCCESS;
781     }
782
783     virtual int handleResponse(WifiEvent& reply) {
784         /* Nothing to do on response! */
785         return NL_SKIP;
786     }
787
788    virtual int handleEvent(WifiEvent& event) {
789         ALOGI("Got a RSSI monitor event");
790
791         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
792         int len = event.get_vendor_data_len();
793
794         if (vendor_data == NULL || len == 0) {
795             ALOGI("RSSI monitor: No data");
796             return NL_SKIP;
797         }
798         /* driver<->HAL event structure */
799         #define RSSI_MONITOR_EVT_VERSION   1
800         typedef struct {
801             u8 version;
802             s8 cur_rssi;
803             mac_addr BSSID;
804         } rssi_monitor_evt;
805
806         rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
807
808         if (data->version != RSSI_MONITOR_EVT_VERSION) {
809             ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION);
810             return NL_SKIP;
811         }
812
813         if (*mHandler.on_rssi_threshold_breached) {
814             (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
815         } else {
816             ALOGW("No RSSI monitor handler registered");
817         }
818
819         return NL_SKIP;
820     }
821
822 };
823
824 class AndroidPktFilterCommand : public WifiCommand {
825     private:
826         const u8* mProgram;
827         u32 mProgramLen;
828         u32* mVersion;
829         u32* mMaxLen;
830         int mReqType;
831     public:
832         AndroidPktFilterCommand(wifi_interface_handle handle,
833                 u32* version, u32* max_len)
834             : WifiCommand("AndroidPktFilterCommand", handle, 0),
835                     mVersion(version), mMaxLen(max_len),
836                     mReqType(GET_APF_CAPABILITIES)
837         {
838         }
839
840         AndroidPktFilterCommand(wifi_interface_handle handle,
841                 const u8* program, u32 len)
842             : WifiCommand("AndroidPktFilterCommand", handle, 0),
843                     mProgram(program), mProgramLen(len),
844                     mReqType(SET_APF_PROGRAM)
845         {
846         }
847
848     int createRequest(WifiRequest& request) {
849         if (mReqType == SET_APF_PROGRAM) {
850             ALOGI("\n%s: APF set program request\n", __FUNCTION__);
851             return createSetPktFilterRequest(request);
852         } else if (mReqType == GET_APF_CAPABILITIES) {
853             ALOGI("\n%s: APF get capabilities request\n", __FUNCTION__);
854             return createGetPktFilterCapabilitesRequest(request);
855         } else {
856             ALOGE("\n%s Unknown APF request\n", __FUNCTION__);
857             return WIFI_ERROR_NOT_SUPPORTED;
858         }
859         return WIFI_SUCCESS;
860     }
861
862     int createSetPktFilterRequest(WifiRequest& request) {
863         u8 *program = new u8[mProgramLen];
864         NULL_CHECK_RETURN(program, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
865         int result = request.create(GOOGLE_OUI, APF_SUBCMD_SET_FILTER);
866         if (result < 0) {
867             return result;
868         }
869
870         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
871         result = request.put_u32(APF_ATTRIBUTE_PROGRAM_LEN, mProgramLen);
872         if (result < 0) {
873             return result;
874         }
875         memcpy(program, mProgram, mProgramLen);
876         result = request.put(APF_ATTRIBUTE_PROGRAM, program, mProgramLen);
877         if (result < 0) {
878             return result;
879         }
880         request.attr_end(data);
881         delete[] program;
882         return result;
883     }
884
885     int createGetPktFilterCapabilitesRequest(WifiRequest& request) {
886         int result = request.create(GOOGLE_OUI, APF_SUBCMD_GET_CAPABILITIES);
887         if (result < 0) {
888             return result;
889         }
890
891         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
892         request.attr_end(data);
893         return result;
894     }
895
896     int start() {
897         WifiRequest request(familyId(), ifaceId());
898         int result = createRequest(request);
899         if (result < 0) {
900             return result;
901         }
902         result = requestResponse(request);
903         if (result < 0) {
904             ALOGI("Request Response failed for APF, result = %d", result);
905             return result;
906         }
907         ALOGI("Done!");
908         return result;
909     }
910
911     int cancel() {
912         return WIFI_SUCCESS;
913     }
914
915     int handleResponse(WifiEvent& reply) {
916         ALOGD("In SetAPFCommand::handleResponse");
917
918         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
919             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
920             return NL_SKIP;
921         }
922
923         int id = reply.get_vendor_id();
924         int subcmd = reply.get_vendor_subcmd();
925
926         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
927         int len = reply.get_vendor_data_len();
928
929         ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
930         if (vendor_data == NULL || len == 0) {
931             ALOGE("no vendor data in SetAPFCommand response; ignoring it");
932             return NL_SKIP;
933         }
934         if( mReqType == SET_APF_PROGRAM) {
935             ALOGD("Response recieved for set packet filter command\n");
936         } else if (mReqType == GET_APF_CAPABILITIES) {
937             *mVersion = 0;
938             *mMaxLen = 0;
939             ALOGD("Response recieved for get packet filter capabilities command\n");
940             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
941                 if (it.get_type() == APF_ATTRIBUTE_VERSION) {
942                     *mVersion = it.get_u32();
943                     ALOGI("APF version is %d\n", *mVersion);
944                 } else if (it.get_type() == APF_ATTRIBUTE_MAX_LEN) {
945                     *mMaxLen = it.get_u32();
946                     ALOGI("APF max len is %d\n", *mMaxLen);
947                 } else {
948                     ALOGE("Ignoring invalid attribute type = %d, size = %d",
949                             it.get_type(), it.get_len());
950                 }
951             }
952         }
953         return NL_OK;
954     }
955
956     int handleEvent(WifiEvent& event) {
957         /* No Event to recieve for APF commands */
958         return NL_SKIP;
959     }
960 };
961
962 class SetNdoffloadCommand : public WifiCommand {
963
964 private:
965     u8 mEnable;
966 public:
967     SetNdoffloadCommand(wifi_interface_handle handle, u8 enable)
968         : WifiCommand("SetNdoffloadCommand", handle, 0) {
969         mEnable = enable;
970     }
971     virtual int create() {
972         int ret;
973
974         ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_CONFIG_ND_OFFLOAD);
975         if (ret < 0) {
976             ALOGE("Can't create message to send to driver - %d", ret);
977             return ret;
978         }
979
980         nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
981         ret = mMsg.put_u8(ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE, mEnable);
982         if (ret < 0) {
983              return ret;
984         }
985
986         mMsg.attr_end(data);
987         return WIFI_SUCCESS;
988     }
989 };
990
991 class GetFeatureSetCommand : public WifiCommand {
992
993 private:
994     int feature_type;
995     feature_set *fset;
996     feature_set *feature_matrix;
997     int *fm_size;
998     int set_size_max;
999 public:
1000     GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set,
1001          feature_set set_matrix[], int *size, int max_size)
1002         : WifiCommand("GetFeatureSetCommand", handle, 0)
1003     {
1004         feature_type = feature;
1005         fset = set;
1006         feature_matrix = set_matrix;
1007         fm_size = size;
1008         set_size_max = max_size;
1009     }
1010
1011     virtual int create() {
1012         int ret;
1013
1014         if(feature_type == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
1015             ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET);
1016         } else if (feature_type == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) {
1017             ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX);
1018         } else {
1019             ALOGE("Unknown feature type %d", feature_type);
1020             return -1;
1021         }
1022
1023         if (ret < 0) {
1024             ALOGE("Can't create message to send to driver - %d", ret);
1025         }
1026
1027         return ret;
1028     }
1029
1030 protected:
1031     virtual int handleResponse(WifiEvent& reply) {
1032
1033         ALOGV("In GetFeatureSetCommand::handleResponse");
1034
1035         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
1036             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
1037             return NL_SKIP;
1038         }
1039
1040         int id = reply.get_vendor_id();
1041         int subcmd = reply.get_vendor_subcmd();
1042
1043         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
1044         int len = reply.get_vendor_data_len();
1045
1046         ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
1047         if (vendor_data == NULL || len == 0) {
1048             ALOGE("no vendor data in GetFeatureSetCommand response; ignoring it");
1049             return NL_SKIP;
1050         }
1051         if(feature_type == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
1052             void *data = reply.get_vendor_data();
1053             if(!fset) {
1054                 ALOGE("Buffers pointers not set");
1055                 return NL_SKIP;
1056             }
1057             memcpy(fset, data, min(len, (int) sizeof(*fset)));
1058         } else {
1059             int num_features_set = 0;
1060             int i = 0;
1061
1062             if(!feature_matrix || !fm_size) {
1063                 ALOGE("Buffers pointers not set");
1064                 return NL_SKIP;
1065             }
1066
1067             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
1068                 if (it.get_type() == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
1069                     num_features_set = it.get_u32();
1070                     ALOGV("Got feature list with %d concurrent sets", num_features_set);
1071                     if(set_size_max && (num_features_set > set_size_max))
1072                         num_features_set = set_size_max;
1073                     *fm_size = num_features_set;
1074                 } else if ((it.get_type() == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) &&
1075                              i < num_features_set) {
1076                     feature_matrix[i] = it.get_u32();
1077                     i++;
1078                 } else {
1079                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
1080                             it.get_type(), it.get_len());
1081                 }
1082             }
1083
1084         }
1085         return NL_OK;
1086     }
1087
1088 };
1089
1090 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
1091 {
1092     GetMulticastIdCommand cmd(handle, name, group);
1093     int res = cmd.requestResponse();
1094     if (res < 0)
1095         return res;
1096     else
1097         return cmd.getId();
1098 }
1099
1100 /////////////////////////////////////////////////////////////////////////
1101
1102 static bool is_wifi_interface(const char *name)
1103 {
1104     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
1105         /* not a wifi interface; ignore it */
1106         return false;
1107     } else {
1108         return true;
1109     }
1110 }
1111
1112 static int get_interface(const char *name, interface_info *info)
1113 {
1114     strcpy(info->name, name);
1115     info->id = if_nametoindex(name);
1116     // ALOGI("found an interface : %s, id = %d", name, info->id);
1117     return WIFI_SUCCESS;
1118 }
1119
1120 wifi_error wifi_init_interfaces(wifi_handle handle)
1121 {
1122     hal_info *info = (hal_info *)handle;
1123
1124     struct dirent *de;
1125
1126     DIR *d = opendir("/sys/class/net");
1127     if (d == 0)
1128         return WIFI_ERROR_UNKNOWN;
1129
1130     int n = 0;
1131     while ((de = readdir(d))) {
1132         if (de->d_name[0] == '.')
1133             continue;
1134         if (is_wifi_interface(de->d_name) ) {
1135             n++;
1136         }
1137     }
1138
1139     closedir(d);
1140
1141     d = opendir("/sys/class/net");
1142     if (d == 0)
1143         return WIFI_ERROR_UNKNOWN;
1144
1145     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
1146
1147     int i = 0;
1148     while ((de = readdir(d))) {
1149         if (de->d_name[0] == '.')
1150             continue;
1151         if (is_wifi_interface(de->d_name)) {
1152             interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
1153             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
1154                 free(ifinfo);
1155                 continue;
1156             }
1157             ifinfo->handle = handle;
1158             info->interfaces[i] = ifinfo;
1159             i++;
1160         }
1161     }
1162
1163     closedir(d);
1164
1165     info->num_interfaces = n;
1166     return WIFI_SUCCESS;
1167 }
1168
1169 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
1170 {
1171     hal_info *info = (hal_info *)handle;
1172
1173     *interfaces = (wifi_interface_handle *)info->interfaces;
1174     *num = info->num_interfaces;
1175
1176     return WIFI_SUCCESS;
1177 }
1178
1179 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
1180 {
1181     interface_info *info = (interface_info *)handle;
1182     strcpy(name, info->name);
1183     return WIFI_SUCCESS;
1184 }
1185
1186 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
1187 {
1188     GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, set, NULL, NULL, 1);
1189     return (wifi_error) command.requestResponse();
1190 }
1191
1192 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
1193        feature_set set[], int *set_size)
1194 {
1195     GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, NULL,
1196             set, set_size, set_size_max);
1197     return (wifi_error) command.requestResponse();
1198 }
1199
1200 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1201 {
1202     SetPnoMacAddrOuiCommand command(handle, scan_oui);
1203     return (wifi_error)command.start();
1204
1205 }
1206
1207 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1208 {
1209     SetNodfsCommand command(handle, nodfs);
1210     return (wifi_error) command.requestResponse();
1211 }
1212
1213 wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
1214 {
1215     SetCountryCodeCommand command(handle, country_code);
1216     return (wifi_error) command.requestResponse();
1217 }
1218
1219 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
1220                         iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
1221 {
1222     ALOGD("Start RSSI monitor %d", id);
1223     wifi_handle handle = getWifiHandle(iface);
1224     SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
1225     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1226     wifi_error result = wifi_register_cmd(handle, id, cmd);
1227     if (result != WIFI_SUCCESS) {
1228         cmd->releaseRef();
1229         return result;
1230     }
1231     result = (wifi_error)cmd->start();
1232     if (result != WIFI_SUCCESS) {
1233         wifi_unregister_cmd(handle, id);
1234         cmd->releaseRef();
1235         return result;
1236     }
1237     return result;
1238 }
1239
1240 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
1241 {
1242     ALOGD("Stopping RSSI monitor");
1243
1244     if(id == -1) {
1245         wifi_rssi_event_handler handler;
1246         s8 max_rssi = 0, min_rssi = 0;
1247         wifi_handle handle = getWifiHandle(iface);
1248         memset(&handler, 0, sizeof(handler));
1249         SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
1250                                                     max_rssi, min_rssi, handler);
1251         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1252         cmd->cancel();
1253         cmd->releaseRef();
1254         return WIFI_SUCCESS;
1255     }
1256     return wifi_cancel_cmd(id, iface);
1257 }
1258
1259 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
1260         u32 *version, u32 *max_len)
1261 {
1262     ALOGD("Getting APF capabilities, halHandle = %p\n", handle);
1263     AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, version, max_len);
1264     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1265     wifi_error result = (wifi_error)cmd->start();
1266     if (result == WIFI_SUCCESS) {
1267         ALOGD("Getting APF capability, version = %d, max_len = %d\n", *version, *max_len);
1268     }
1269     cmd->releaseRef();
1270     return result;
1271 }
1272
1273 static wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
1274         const u8 *program, u32 len)
1275 {
1276     ALOGD("Setting APF program, halHandle = %p\n", handle);
1277     AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, program, len);
1278     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1279     wifi_error result = (wifi_error)cmd->start();
1280     cmd->releaseRef();
1281     return result;
1282 }
1283
1284 static wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable)
1285 {
1286     SetNdoffloadCommand command(handle, enable);
1287     return (wifi_error) command.requestResponse();
1288 }
1289
1290 /////////////////////////////////////////////////////////////////////////////