11a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <stdint.h>
21a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <fcntl.h>
31a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <sys/socket.h>
41a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/genl/genl.h>
51a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/genl/family.h>
61a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/genl/ctrl.h>
71a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/rtnetlink.h>
81a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netpacket/packet.h>
91a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/filter.h>
101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/errqueue.h>
11508ee337afdefb09b15a8de9f7a61660269b39e8Prerepa Viswanadham#include <errno.h>
121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <linux/pkt_sched.h>
141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/object-api.h>
151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/netlink.h>
161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <netlink/socket.h>
17642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande#include <netlink/attr.h>
18642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande#include <netlink/handlers.h>
19642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande#include <netlink/msg.h>
201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <dirent.h>
221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <net/if.h>
231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "sync.h"
251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#define LOG_TAG  "WifiHAL"
271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include <utils/Log.h>
291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "wifi_hal.h"
311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "common.h"
321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#include "cpp_bindings.h"
33cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe#include "rtt.h"
341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/*
351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde BUGBUG: normally, libnl allocates ports for all connections it makes; but
361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde being a static library, it doesn't really know how many other netlink connections
371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde are made by the same process, if connections come from different shared libraries.
381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde These port assignments exist to solve that problem - temporarily. We need to fix
391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde libnl to try and allocate ports across the entire process.
401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde */
411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#define WIFI_HAL_CMD_SOCK_PORT       644
431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde#define WIFI_HAL_EVENT_SOCK_PORT     645
441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic void internal_event_handler(wifi_handle handle, int events);
46642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpandestatic int internal_no_seq_check(nl_msg *msg, void *arg);
471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int internal_valid_message_handler(nl_msg *msg, void *arg);
481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int wifi_add_membership(wifi_handle handle, const char *group);
501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic wifi_error wifi_init_interfaces(wifi_handle handle);
51fef13c11034313585be68c32322b9a53c43a37b2Ashwinstatic wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
52fef13c11034313585be68c32322b9a53c43a37b2Ashwin                        iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
53fef13c11034313585be68c32322b9a53c43a37b2Ashwinstatic wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
54dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharmastatic wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
55dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                            const u8 *program, u32 len);
56dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharmastatic wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
57dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                u32 *version, u32 *max_len);
5865f9c6fbd929be309642cdaf255e8394aad2b0caJun Limstatic wifi_error wifi_configure_nd_offload(wifi_interface_handle iface, u8 enable);
591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
60f0d5070a931327e6356d765478069b9e66452a5bAshwintypedef enum wifi_attr {
619a23388d5a9f58f106169700bb179de0a4af7840Ashwin    ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET,
62f0d5070a931327e6356d765478069b9e66452a5bAshwin    ANDR_WIFI_ATTRIBUTE_FEATURE_SET,
6365f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI,
6465f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    ANDR_WIFI_ATTRIBUTE_NODFS_SET,
6565f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    ANDR_WIFI_ATTRIBUTE_COUNTRY,
6665f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE
6765f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    // Add more attribute here
68f0d5070a931327e6356d765478069b9e66452a5bAshwin} wifi_attr_t;
699a23388d5a9f58f106169700bb179de0a4af7840Ashwin
70fef13c11034313585be68c32322b9a53c43a37b2Ashwinenum wifi_rssi_monitor_attr {
71fef13c11034313585be68c32322b9a53c43a37b2Ashwin    RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
72fef13c11034313585be68c32322b9a53c43a37b2Ashwin    RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
73fef13c11034313585be68c32322b9a53c43a37b2Ashwin    RSSI_MONITOR_ATTRIBUTE_START,
74fef13c11034313585be68c32322b9a53c43a37b2Ashwin};
75fef13c11034313585be68c32322b9a53c43a37b2Ashwin
76dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharmaenum wifi_apf_attr {
77dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    APF_ATTRIBUTE_VERSION,
78dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    APF_ATTRIBUTE_MAX_LEN,
79dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    APF_ATTRIBUTE_PROGRAM,
80dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    APF_ATTRIBUTE_PROGRAM_LEN
81dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma};
82dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
83dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharmaenum apf_request_type {
84dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    GET_APF_CAPABILITIES,
85dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    SET_APF_PROGRAM
86dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma};
87dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/* Initialize/Cleanup */
891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndevoid wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
92642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande    uint32_t pid = getpid() & 0x3FFFFF;
93642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande    nl_socket_set_local_port(sock, pid + (port << 22));
941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic nl_sock * wifi_create_nl_socket(int port)
971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    // ALOGI("Creating socket");
991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    struct nl_sock *sock = nl_socket_alloc();
1001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (sock == NULL) {
1011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could not create handle");
1021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NULL;
1031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
1041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_socket_set_local_port(sock, port);
1061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    struct sockaddr *addr = NULL;
1081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
1091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    // ALOGI("Connecting socket");
1111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (nl_connect(sock, NETLINK_GENERIC)) {
1121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could not connect handle");
1131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nl_socket_free(sock);
1141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NULL;
1151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
1161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    // ALOGI("Making socket nonblocking");
1181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    /*
1191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (nl_socket_set_nonblocking(sock)) {
1201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could make socket non-blocking");
1211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nl_socket_free(sock);
1221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NULL;
1231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
1241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    */
1251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return sock;
1271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
1281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
129cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe/*initialize function pointer table with Broadcom HHAL API*/
130cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhewifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
131cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe{
132cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    if (fn == NULL) {
133cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe        return WIFI_ERROR_UNKNOWN;
134cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    }
135cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_initialize = wifi_initialize;
136cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_cleanup = wifi_cleanup;
137cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_event_loop = wifi_event_loop;
138cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
139cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
140cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
141cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_get_ifaces = wifi_get_ifaces;
142cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_get_iface_name = wifi_get_iface_name;
143cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_start_gscan = wifi_start_gscan;
144cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_stop_gscan = wifi_stop_gscan;
145cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
146cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
147cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
148cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
149cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
150cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
151cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_get_link_stats = wifi_get_link_stats;
152cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_get_valid_channels = wifi_get_valid_channels;
153cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_rtt_range_request = wifi_rtt_range_request;
154cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
155cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
156d122c5c4cbdb8fdee2576789733e42ea0ecb9d9cgautam    fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
15789b86262c90552a05a6177944d0ced6b01f27d80gautam    fn->wifi_enable_responder = wifi_enable_responder;
15889b86262c90552a05a6177944d0ced6b01f27d80gautam    fn->wifi_disable_responder = wifi_disable_responder;
159cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
160cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_start_logging = wifi_start_logging;
161cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_set_epno_list = wifi_set_epno_list;
16289296a7fc953e68649cdb1366d22376c034ace05Mitchell Wills    fn->wifi_reset_epno_list = wifi_reset_epno_list;
163cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    fn->wifi_set_country_code = wifi_set_country_code;
164cab099c7be6490bad1e0402b630840f8d0fcc99bxinhe    fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
165cab099c7be6490bad1e0402b630840f8d0fcc99bxinhe    fn->wifi_set_log_handler = wifi_set_log_handler;
166c604b53461cfea0a1e6f6f5ad84b0a35be69b8e0JerryLee    fn->wifi_reset_log_handler = wifi_reset_log_handler;
167cab099c7be6490bad1e0402b630840f8d0fcc99bxinhe    fn->wifi_set_alert_handler = wifi_set_alert_handler;
16856deba26a624507fc2e0e6b134f8bd88d091a141Jerry Lee    fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
169cab099c7be6490bad1e0402b630840f8d0fcc99bxinhe    fn->wifi_get_firmware_version = wifi_get_firmware_version;
170cab099c7be6490bad1e0402b630840f8d0fcc99bxinhe    fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
171cab099c7be6490bad1e0402b630840f8d0fcc99bxinhe    fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
172cab099c7be6490bad1e0402b630840f8d0fcc99bxinhe    fn->wifi_get_ring_data = wifi_get_ring_data;
173cab099c7be6490bad1e0402b630840f8d0fcc99bxinhe    fn->wifi_get_driver_version = wifi_get_driver_version;
174f060fbe12899e67fc4c491af52718ef5e5f1e3eePierre Vandwalle    fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
175fef13c11034313585be68c32322b9a53c43a37b2Ashwin    fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
176fef13c11034313585be68c32322b9a53c43a37b2Ashwin    fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
17765f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
1788f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park    fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
1798f1ec7e8e43ec37e94806764b2873c93368cf137Ecco Park    fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
1807e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
1817e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
1827e8b4497898f0de16faa50d0b65fcd7d09085e24Sreenath Sharma    fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
183dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
184dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    fn->wifi_set_packet_filter = wifi_set_packet_filter;
185cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe    return WIFI_SUCCESS;
186cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe}
187cbbc31d5d0d387068be5b84251f53d6b74bfc6f5xinhe
1881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_initialize(wifi_handle *handle)
1891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
1901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    srand(getpid());
1911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ALOGI("Initializing wifi");
1931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    hal_info *info = (hal_info *)malloc(sizeof(hal_info));
1941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (info == NULL) {
1951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could not allocate hal_info");
1969a23388d5a9f58f106169700bb179de0a4af7840Ashwin        return WIFI_ERROR_UNKNOWN;
1971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
1981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    memset(info, 0, sizeof(*info));
2001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ALOGI("Creating socket");
20205e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
20305e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        ALOGE("Could not create cleanup sockets");
20456c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        free(info);
20505e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        return WIFI_ERROR_UNKNOWN;
20605e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    }
20705e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande
2081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
2091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (cmd_sock == NULL) {
2101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could not create handle");
21156c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        free(info);
2121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_ERROR_UNKNOWN;
2131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
2141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
2161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (event_sock == NULL) {
2171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could not create handle");
2181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nl_socket_free(cmd_sock);
21956c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        free(info);
2201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_ERROR_UNKNOWN;
2211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
2221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    struct nl_cb *cb = nl_socket_get_cb(event_sock);
2241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (cb == NULL) {
2251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could not create handle");
22656c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        nl_socket_free(cmd_sock);
22756c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        nl_socket_free(event_sock);
22856c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        free(info);
2291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_ERROR_UNKNOWN;
2301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
2311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
233642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande    nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
2341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
2351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    nl_cb_put(cb);
2361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->cmd_sock = cmd_sock;
2381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->event_sock = event_sock;
2391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->clean_up = false;
2401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->in_event_loop = false;
2411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
2431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
2441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->num_event_cb = 0;
2451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
2471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->alloc_cmd = DEFAULT_CMD_SIZE;
2481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->num_cmd = 0;
2491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
2511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (info->nl80211_family_id < 0) {
2521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could not resolve nl80211 familty id");
2531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nl_socket_free(cmd_sock);
2541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nl_socket_free(event_sock);
2551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        free(info);
2569a23388d5a9f58f106169700bb179de0a4af7840Ashwin        return WIFI_ERROR_UNKNOWN;
2571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
2581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
259bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande    pthread_mutex_init(&info->cb_lock, NULL);
260bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande
2611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    *handle = (wifi_handle) info;
2621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_add_membership(*handle, "scan");
2641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_add_membership(*handle, "mlme");
2651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_add_membership(*handle, "regulatory");
2661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_add_membership(*handle, "vendor");
2671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_init_interfaces(*handle);
2691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    // ALOGI("Found %d interfaces", info->num_interfaces);
2701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
271bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande
2721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
2731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return WIFI_SUCCESS;
2741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
2751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int wifi_add_membership(wifi_handle handle, const char *group)
2771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
2781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    hal_info *info = getHalInfo(handle);
2791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int id = wifi_get_multicast_id(handle, "nl80211", group);
2811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (id < 0) {
2821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could not find group %s", group);
2831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return id;
2841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
2851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int ret = nl_socket_add_membership(info->event_sock, id);
2871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (ret < 0) {
2881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Could not add membership to group %s", group);
2891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
2901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    // ALOGI("Successfully added membership for group %s", group);
2921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return ret;
2931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
2941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
2951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic void internal_cleaned_up_handler(wifi_handle handle)
2961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
2971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    hal_info *info = getHalInfo(handle);
2981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
2991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (info->cmd_sock != 0) {
30105e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        close(info->cleanup_socks[0]);
30205e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        close(info->cleanup_socks[1]);
3031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nl_socket_free(info->cmd_sock);
3041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        nl_socket_free(info->event_sock);
3051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        info->cmd_sock = NULL;
3061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        info->event_sock = NULL;
3071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
3081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    (*cleaned_up_handler)(handle);
310bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande    pthread_mutex_destroy(&info->cb_lock);
3111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    free(info);
3121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    ALOGI("Internal cleanup completed");
3141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
3151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndevoid wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
3171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
3181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    hal_info *info = getHalInfo(handle);
31956c89ca266b11be506192f3a13a1dba3f109c2cfAshwin    char buf[64];
32056c89ca266b11be506192f3a13a1dba3f109c2cfAshwin
3211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->cleaned_up_handler = handler;
32256c89ca266b11be506192f3a13a1dba3f109c2cfAshwin    if (write(info->cleanup_socks[0], "Exit", 4) < 1) {
32356c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        // As a fallback set the cleanup flag to TRUE
32456c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        ALOGE("could not write to the cleanup socket");
32556c89ca266b11be506192f3a13a1dba3f109c2cfAshwin    } else {
32656c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        // Listen to the response
32756c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        // Hopefully we dont get errors or get hung up
32856c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        // Not much can be done in that case, but assume that
32956c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        // it has rx'ed the Exit message to exit the thread.
33056c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        // As a fallback set the cleanup flag to TRUE
33156c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        memset(buf, 0, sizeof(buf));
33256c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        int result = read(info->cleanup_socks[0], buf, sizeof(buf));
33356c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result, errno);
33456c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        if (strncmp(buf, "Done", 4) == 0) {
33556c89ca266b11be506192f3a13a1dba3f109c2cfAshwin            ALOGE("Event processing terminated");
33656c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        } else {
33756c89ca266b11be506192f3a13a1dba3f109c2cfAshwin            ALOGD("Rx'ed %s", buf);
33856c89ca266b11be506192f3a13a1dba3f109c2cfAshwin        }
33956c89ca266b11be506192f3a13a1dba3f109c2cfAshwin    }
3401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->clean_up = true;
34105e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    pthread_mutex_lock(&info->cb_lock);
34205e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande
343d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande    int bad_commands = 0;
344d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande
3456d9f23bf01b35074e29c6319c4009a1295cb4aa6Vinit Deshpande    for (int i = 0; i < info->num_event_cb; i++) {
3466d9f23bf01b35074e29c6319c4009a1295cb4aa6Vinit Deshpande        cb_info *cbi = &(info->event_cb[i]);
3476d9f23bf01b35074e29c6319c4009a1295cb4aa6Vinit Deshpande        WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
3485cbe0dca22a31ea90201e47989df44b124f6f13eAshwin        ALOGI("Command left in event_cb %p:%s", cmd, (cmd ? cmd->getType(): ""));
3496d9f23bf01b35074e29c6319c4009a1295cb4aa6Vinit Deshpande    }
3506d9f23bf01b35074e29c6319c4009a1295cb4aa6Vinit Deshpande
351d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande    while (info->num_cmd > bad_commands) {
352d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        int num_cmd = info->num_cmd;
353d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        cmd_info *cmdi = &(info->cmd[bad_commands]);
354d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        WifiCommand *cmd = cmdi->cmd;
35505e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        if (cmd != NULL) {
3565cbe0dca22a31ea90201e47989df44b124f6f13eAshwin            ALOGI("Cancelling command %p:%s", cmd, cmd->getType());
357974df1c535fa4aa5c191d47877aa27c79fad0263Vinit Deshpande            pthread_mutex_unlock(&info->cb_lock);
35805e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande            cmd->cancel();
359974df1c535fa4aa5c191d47877aa27c79fad0263Vinit Deshpande            pthread_mutex_lock(&info->cb_lock);
360d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande            if (num_cmd == info->num_cmd) {
3615cbe0dca22a31ea90201e47989df44b124f6f13eAshwin                ALOGI("Cancelling command %p:%s did not work", cmd, (cmd ? cmd->getType(): ""));
362d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande                bad_commands++;
363d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande            }
364d7f3cb9915d9ac514393d0ad7767662958054b8fPaul Stewart            /* release reference added when command is saved */
365d7f3cb9915d9ac514393d0ad7767662958054b8fPaul Stewart            cmd->releaseRef();
36605e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        }
36705e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    }
36805e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande
369d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande    for (int i = 0; i < info->num_event_cb; i++) {
370d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        cb_info *cbi = &(info->event_cb[i]);
371d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
3726d9f23bf01b35074e29c6319c4009a1295cb4aa6Vinit Deshpande        ALOGE("Leaked command %p", cmd);
373d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande    }
37405e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    pthread_mutex_unlock(&info->cb_lock);
37556c89ca266b11be506192f3a13a1dba3f109c2cfAshwin    internal_cleaned_up_handler(handle);
3761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
3771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int internal_pollin_handler(wifi_handle handle)
3791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
3801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    hal_info *info = getHalInfo(handle);
3811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
3821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int res = nl_recvmsgs(info->event_sock, cb);
383642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande    // ALOGD("nl_recvmsgs returned %d", res);
3841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    nl_cb_put(cb);
3851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return res;
3861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
3871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
3881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/* Run event handler */
3891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndevoid wifi_event_loop(wifi_handle handle)
3901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
3911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    hal_info *info = getHalInfo(handle);
3921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (info->in_event_loop) {
3931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return;
3941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    } else {
3951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        info->in_event_loop = true;
3961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
3971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
39805e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    pollfd pfd[2];
39905e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    memset(&pfd[0], 0, sizeof(pollfd) * 2);
4001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
40105e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    pfd[0].fd = nl_socket_get_fd(info->event_sock);
40205e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    pfd[0].events = POLLIN;
40305e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    pfd[1].fd = info->cleanup_socks[1];
40405e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    pfd[1].events = POLLIN;
4051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
40605e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande    char buf[2048];
4071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    /* TODO: Add support for timeouts */
4081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    do {
4101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int timeout = -1;                   /* Infinite timeout */
41105e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        pfd[0].revents = 0;
41205e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        pfd[1].revents = 0;
413642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande        // ALOGI("Polling socket");
41405e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        int result = poll(pfd, 2, timeout);
4151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (result < 0) {
416e16283338c9f0e8798228c400e31415d612f7d09Vinit Deshpande            // ALOGE("Error polling socket");
41705e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        } else if (pfd[0].revents & POLLERR) {
418cc370437327c04d82dc8b3addc556d5bc30efc77Vinit Deshpande            ALOGE("POLL Error; error no = %d", errno);
41905e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande            int result2 = read(pfd[0].fd, buf, sizeof(buf));
420cc370437327c04d82dc8b3addc556d5bc30efc77Vinit Deshpande            ALOGE("Read after POLL returned %d, error no = %d", result2, errno);
42105e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        } else if (pfd[0].revents & POLLHUP) {
422cc370437327c04d82dc8b3addc556d5bc30efc77Vinit Deshpande            ALOGE("Remote side hung up");
423cc370437327c04d82dc8b3addc556d5bc30efc77Vinit Deshpande            break;
42405e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        } else if (pfd[0].revents & POLLIN) {
425854a437fc5530b1555cd469319d1f96ba184b178Vinit Deshpande            // ALOGI("Found some events!!!");
426cc370437327c04d82dc8b3addc556d5bc30efc77Vinit Deshpande            internal_pollin_handler(handle);
42705e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande        } else if (pfd[1].revents & POLLIN) {
42856c89ca266b11be506192f3a13a1dba3f109c2cfAshwin            memset(buf, 0, sizeof(buf));
42905e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande            int result2 = read(pfd[1].fd, buf, sizeof(buf));
43056c89ca266b11be506192f3a13a1dba3f109c2cfAshwin            ALOGE("%s: Read after POLL returned %d, error no = %d", __FUNCTION__, result2, errno);
43156c89ca266b11be506192f3a13a1dba3f109c2cfAshwin            if (strncmp(buf, "Exit", 4) == 0) {
43256c89ca266b11be506192f3a13a1dba3f109c2cfAshwin                ALOGD("Got a signal to exit!!!");
43356c89ca266b11be506192f3a13a1dba3f109c2cfAshwin                if (write(pfd[1].fd, "Done", 4) < 1) {
43456c89ca266b11be506192f3a13a1dba3f109c2cfAshwin                    ALOGE("could not write to the cleanup socket");
43556c89ca266b11be506192f3a13a1dba3f109c2cfAshwin                }
43656c89ca266b11be506192f3a13a1dba3f109c2cfAshwin                break;
43756c89ca266b11be506192f3a13a1dba3f109c2cfAshwin            } else {
43856c89ca266b11be506192f3a13a1dba3f109c2cfAshwin                ALOGD("Rx'ed %s on the cleanup socket\n", buf);
43956c89ca266b11be506192f3a13a1dba3f109c2cfAshwin            }
440cc370437327c04d82dc8b3addc556d5bc30efc77Vinit Deshpande        } else {
44105e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande            ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
4421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
4431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    } while (!info->clean_up);
44456c89ca266b11be506192f3a13a1dba3f109c2cfAshwin    ALOGI("Exit %s", __FUNCTION__);
4451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
4461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////////////////
4481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
449642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpandestatic int internal_no_seq_check(struct nl_msg *msg, void *arg)
450642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande{
451642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande    return NL_OK;
452642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande}
453642bfbe829f5438db3d99ce4678bcb770359a632Vinit Deshpande
4541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int internal_valid_message_handler(nl_msg *msg, void *arg)
4551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
456854a437fc5530b1555cd469319d1f96ba184b178Vinit Deshpande    // ALOGI("got an event");
45705e31d445f52da4746ff0cc0703d83814cea98d0Vinit Deshpande
4581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    wifi_handle handle = (wifi_handle)arg;
4591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    hal_info *info = getHalInfo(handle);
4601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    WifiEvent event(msg);
4621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int res = event.parse();
4631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (res < 0) {
4641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ALOGE("Failed to parse event: %d", res);
4651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
4661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
4671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int cmd = event.get_cmd();
4691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    uint32_t vendor_id = 0;
4701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int subcmd = 0;
4711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (cmd == NL80211_CMD_VENDOR) {
4731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
4741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
475ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande        ALOGV("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
4761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                event.get_cmdString(), vendor_id, subcmd);
4771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    } else {
478ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande        // ALOGV("event received %s", event.get_cmdString());
4791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
4801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
481ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande    // ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
4821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    // event.log();
4831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    bool dispatched = false;
485bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande
486bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande    pthread_mutex_lock(&info->cb_lock);
487bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande
4881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    for (int i = 0; i < info->num_event_cb; i++) {
4891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (cmd == info->event_cb[i].nl_cmd) {
4901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (cmd == NL80211_CMD_VENDOR
4911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                && ((vendor_id != info->event_cb[i].vendor_id)
4921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                || (subcmd != info->event_cb[i].vendor_subcmd)))
4931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            {
4941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                /* event for a different vendor, ignore it */
4951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                continue;
4961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
4971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
4981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            cb_info *cbi = &(info->event_cb[i]);
49928237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande            nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
50028237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande            void *cb_arg = cbi->cb_arg;
50128237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande            WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
50228237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande            if (cmd != NULL) {
50328237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande                cmd->addRef();
50428237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande            }
50528237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande            pthread_mutex_unlock(&info->cb_lock);
50656c89ca266b11be506192f3a13a1dba3f109c2cfAshwin            if (cb_func)
50756c89ca266b11be506192f3a13a1dba3f109c2cfAshwin                (*cb_func)(msg, cb_arg);
50828237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande            if (cmd != NULL) {
50928237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande                cmd->releaseRef();
51028237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande            }
51128237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande
51228237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande            return NL_OK;
51328237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        }
5141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
5151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
516bb8a4d506769d7dc8b33445c6725a40b7523063cVinit Deshpande    pthread_mutex_unlock(&info->cb_lock);
5171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return NL_OK;
5181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
5191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde///////////////////////////////////////////////////////////////////////////////////////
5211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeclass GetMulticastIdCommand : public WifiCommand
5231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
5241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndeprivate:
5251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    const char *mName;
5261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    const char *mGroup;
5271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int   mId;
5281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndepublic:
5291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
530d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("GetMulticastIdCommand", handle, 0)
5311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    {
5321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        mName = name;
5331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        mGroup = group;
5341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        mId = -1;
5351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
5361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int getId() {
5381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return mId;
5391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
5401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int create() {
5421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
5431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        // ALOGI("ctrl family = %d", nlctrlFamily);
5441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
5451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (ret < 0) {
5461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return ret;
5471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
5481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
5491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return ret;
5501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
5511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    virtual int handleResponse(WifiEvent& reply) {
5531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        // ALOGI("handling reponse in %s", __func__);
5551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        struct nlattr **tb = reply.attributes();
5571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        struct genlmsghdr *gnlh = reply.header();
5581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        struct nlattr *mcgrp = NULL;
5591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        int i;
5601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
5621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ALOGI("No multicast groups found");
5631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            return NL_SKIP;
5641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        } else {
5651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
5661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
5671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
5691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            // ALOGI("Processing group");
5711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
5721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
5731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                nla_len(mcgrp), NULL);
5741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
5751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                continue;
5761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
5771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
5791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
5801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            // ALOGI("Found group name %s", grpName);
5821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (strncmp(grpName, mGroup, grpNameLen) != 0)
5841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                continue;
5851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
5871a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            break;
5881a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
5891a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5901a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return NL_SKIP;
5911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
5921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
5931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde};
5941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
595f0d5070a931327e6356d765478069b9e66452a5bAshwinclass SetPnoMacAddrOuiCommand : public WifiCommand {
596f0d5070a931327e6356d765478069b9e66452a5bAshwin
597f0d5070a931327e6356d765478069b9e66452a5bAshwinprivate:
598f0d5070a931327e6356d765478069b9e66452a5bAshwin    byte *mOui;
599f0d5070a931327e6356d765478069b9e66452a5bAshwin    feature_set *fset;
600f0d5070a931327e6356d765478069b9e66452a5bAshwin    feature_set *feature_matrix;
601f0d5070a931327e6356d765478069b9e66452a5bAshwin    int *fm_size;
602f0d5070a931327e6356d765478069b9e66452a5bAshwin    int set_size_max;
603f0d5070a931327e6356d765478069b9e66452a5bAshwinpublic:
604f0d5070a931327e6356d765478069b9e66452a5bAshwin    SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
605d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("SetPnoMacAddrOuiCommand", handle, 0)
606f0d5070a931327e6356d765478069b9e66452a5bAshwin    {
607f0d5070a931327e6356d765478069b9e66452a5bAshwin        mOui = scan_oui;
608f0d5070a931327e6356d765478069b9e66452a5bAshwin    }
609f0d5070a931327e6356d765478069b9e66452a5bAshwin
610f0d5070a931327e6356d765478069b9e66452a5bAshwin    int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
611f0d5070a931327e6356d765478069b9e66452a5bAshwin        int result = request.create(GOOGLE_OUI, subcmd);
612f0d5070a931327e6356d765478069b9e66452a5bAshwin        if (result < 0) {
613f0d5070a931327e6356d765478069b9e66452a5bAshwin            return result;
614f0d5070a931327e6356d765478069b9e66452a5bAshwin        }
615f0d5070a931327e6356d765478069b9e66452a5bAshwin
616f0d5070a931327e6356d765478069b9e66452a5bAshwin        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
617f0d5070a931327e6356d765478069b9e66452a5bAshwin        result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
618f0d5070a931327e6356d765478069b9e66452a5bAshwin        if (result < 0) {
619f0d5070a931327e6356d765478069b9e66452a5bAshwin            return result;
620f0d5070a931327e6356d765478069b9e66452a5bAshwin        }
621f0d5070a931327e6356d765478069b9e66452a5bAshwin
622f0d5070a931327e6356d765478069b9e66452a5bAshwin        request.attr_end(data);
623f0d5070a931327e6356d765478069b9e66452a5bAshwin        return WIFI_SUCCESS;
624f0d5070a931327e6356d765478069b9e66452a5bAshwin
625f0d5070a931327e6356d765478069b9e66452a5bAshwin    }
626f0d5070a931327e6356d765478069b9e66452a5bAshwin
627f0d5070a931327e6356d765478069b9e66452a5bAshwin    int start() {
628f0d5070a931327e6356d765478069b9e66452a5bAshwin        ALOGD("Sending mac address OUI");
629f0d5070a931327e6356d765478069b9e66452a5bAshwin        WifiRequest request(familyId(), ifaceId());
630f0d5070a931327e6356d765478069b9e66452a5bAshwin        int result = createRequest(request, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, mOui);
631f0d5070a931327e6356d765478069b9e66452a5bAshwin        if (result != WIFI_SUCCESS) {
632f0d5070a931327e6356d765478069b9e66452a5bAshwin            ALOGE("failed to create request; result = %d", result);
633f0d5070a931327e6356d765478069b9e66452a5bAshwin            return result;
634f0d5070a931327e6356d765478069b9e66452a5bAshwin        }
635f0d5070a931327e6356d765478069b9e66452a5bAshwin
636f0d5070a931327e6356d765478069b9e66452a5bAshwin        result = requestResponse(request);
637f0d5070a931327e6356d765478069b9e66452a5bAshwin        if (result != WIFI_SUCCESS) {
638f0d5070a931327e6356d765478069b9e66452a5bAshwin            ALOGE("failed to set scanning mac OUI; result = %d", result);
639f0d5070a931327e6356d765478069b9e66452a5bAshwin        }
640f0d5070a931327e6356d765478069b9e66452a5bAshwin
641f0d5070a931327e6356d765478069b9e66452a5bAshwin        return result;
642f0d5070a931327e6356d765478069b9e66452a5bAshwin    }
643f0d5070a931327e6356d765478069b9e66452a5bAshwinprotected:
644f0d5070a931327e6356d765478069b9e66452a5bAshwin    virtual int handleResponse(WifiEvent& reply) {
645f0d5070a931327e6356d765478069b9e66452a5bAshwin         ALOGD("Request complete!");
646f0d5070a931327e6356d765478069b9e66452a5bAshwin        /* Nothing to do on response! */
647f0d5070a931327e6356d765478069b9e66452a5bAshwin        return NL_SKIP;
648f0d5070a931327e6356d765478069b9e66452a5bAshwin    }
649f0d5070a931327e6356d765478069b9e66452a5bAshwin};
650f0d5070a931327e6356d765478069b9e66452a5bAshwin
651b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidtclass SetNodfsCommand : public WifiCommand {
652b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt
653b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidtprivate:
654b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt    u32 mNoDfs;
655b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidtpublic:
656b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt    SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
657d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("SetNodfsCommand", handle, 0) {
658b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        mNoDfs = nodfs;
659b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt    }
660b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt    virtual int create() {
661b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        int ret;
662f0d5070a931327e6356d765478069b9e66452a5bAshwin
663b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_NODFS_SET);
664b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        if (ret < 0) {
665b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt            ALOGE("Can't create message to send to driver - %d", ret);
666b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt            return ret;
667b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        }
668b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt
669b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
67065f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        ret = mMsg.put_u32(ANDR_WIFI_ATTRIBUTE_NODFS_SET, mNoDfs);
671b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        if (ret < 0) {
672b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt             return ret;
673b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        }
674b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt
675b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        mMsg.attr_end(data);
676b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt        return WIFI_SUCCESS;
677b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt    }
678b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt};
679f0d5070a931327e6356d765478069b9e66452a5bAshwin
680c02e00563882d87ab29822c43097cbb1ce04b55dxinheclass SetCountryCodeCommand : public WifiCommand {
681c02e00563882d87ab29822c43097cbb1ce04b55dxinheprivate:
682c02e00563882d87ab29822c43097cbb1ce04b55dxinhe    const char *mCountryCode;
683c02e00563882d87ab29822c43097cbb1ce04b55dxinhepublic:
684c02e00563882d87ab29822c43097cbb1ce04b55dxinhe    SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
685d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("SetCountryCodeCommand", handle, 0) {
686c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        mCountryCode = country_code;
687c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        }
688c02e00563882d87ab29822c43097cbb1ce04b55dxinhe    virtual int create() {
689c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        int ret;
690c02e00563882d87ab29822c43097cbb1ce04b55dxinhe
691c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_COUNTRY_CODE);
692c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        if (ret < 0) {
693c02e00563882d87ab29822c43097cbb1ce04b55dxinhe             ALOGE("Can't create message to send to driver - %d", ret);
694c02e00563882d87ab29822c43097cbb1ce04b55dxinhe             return ret;
695c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        }
696c02e00563882d87ab29822c43097cbb1ce04b55dxinhe
697c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
69865f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        ret = mMsg.put_string(ANDR_WIFI_ATTRIBUTE_COUNTRY, mCountryCode);
699c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        if (ret < 0) {
700c02e00563882d87ab29822c43097cbb1ce04b55dxinhe            return ret;
701c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        }
702c02e00563882d87ab29822c43097cbb1ce04b55dxinhe
703c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        mMsg.attr_end(data);
704c02e00563882d87ab29822c43097cbb1ce04b55dxinhe        return WIFI_SUCCESS;
705c02e00563882d87ab29822c43097cbb1ce04b55dxinhe
706c02e00563882d87ab29822c43097cbb1ce04b55dxinhe    }
707c02e00563882d87ab29822c43097cbb1ce04b55dxinhe};
708c02e00563882d87ab29822c43097cbb1ce04b55dxinhe
709fef13c11034313585be68c32322b9a53c43a37b2Ashwinclass SetRSSIMonitorCommand : public WifiCommand {
710fef13c11034313585be68c32322b9a53c43a37b2Ashwinprivate:
711fef13c11034313585be68c32322b9a53c43a37b2Ashwin    s8 mMax_rssi;
712fef13c11034313585be68c32322b9a53c43a37b2Ashwin    s8 mMin_rssi;
713fef13c11034313585be68c32322b9a53c43a37b2Ashwin    wifi_rssi_event_handler mHandler;
714fef13c11034313585be68c32322b9a53c43a37b2Ashwinpublic:
715fef13c11034313585be68c32322b9a53c43a37b2Ashwin    SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
716fef13c11034313585be68c32322b9a53c43a37b2Ashwin                s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
717d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi
718d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        (min_rssi), mHandler(eh)
719fef13c11034313585be68c32322b9a53c43a37b2Ashwin        {
720fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
721fef13c11034313585be68c32322b9a53c43a37b2Ashwin   int createRequest(WifiRequest& request, int enable) {
722fef13c11034313585be68c32322b9a53c43a37b2Ashwin        int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
723fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (result < 0) {
724fef13c11034313585be68c32322b9a53c43a37b2Ashwin            return result;
725fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
726fef13c11034313585be68c32322b9a53c43a37b2Ashwin
727fef13c11034313585be68c32322b9a53c43a37b2Ashwin        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
728fef13c11034313585be68c32322b9a53c43a37b2Ashwin        result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
729fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (result < 0) {
730fef13c11034313585be68c32322b9a53c43a37b2Ashwin            return result;
731fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
732fef13c11034313585be68c32322b9a53c43a37b2Ashwin        ALOGD("create request");
733fef13c11034313585be68c32322b9a53c43a37b2Ashwin        result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
734fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (result < 0) {
735fef13c11034313585be68c32322b9a53c43a37b2Ashwin            return result;
736fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
737fef13c11034313585be68c32322b9a53c43a37b2Ashwin        result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable);
738fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (result < 0) {
739fef13c11034313585be68c32322b9a53c43a37b2Ashwin            return result;
740fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
741fef13c11034313585be68c32322b9a53c43a37b2Ashwin        request.attr_end(data);
742fef13c11034313585be68c32322b9a53c43a37b2Ashwin        return result;
743fef13c11034313585be68c32322b9a53c43a37b2Ashwin    }
744fef13c11034313585be68c32322b9a53c43a37b2Ashwin
745fef13c11034313585be68c32322b9a53c43a37b2Ashwin    int start() {
746fef13c11034313585be68c32322b9a53c43a37b2Ashwin        WifiRequest request(familyId(), ifaceId());
747fef13c11034313585be68c32322b9a53c43a37b2Ashwin        int result = createRequest(request, 1);
748fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (result < 0) {
749fef13c11034313585be68c32322b9a53c43a37b2Ashwin            return result;
750fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
751fef13c11034313585be68c32322b9a53c43a37b2Ashwin        result = requestResponse(request);
752fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (result < 0) {
753fef13c11034313585be68c32322b9a53c43a37b2Ashwin            ALOGI("Failed to set RSSI Monitor, result = %d", result);
754fef13c11034313585be68c32322b9a53c43a37b2Ashwin            return result;
755fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
756fef13c11034313585be68c32322b9a53c43a37b2Ashwin        ALOGI("Successfully set RSSI monitoring");
757fef13c11034313585be68c32322b9a53c43a37b2Ashwin        registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
758fef13c11034313585be68c32322b9a53c43a37b2Ashwin
759fef13c11034313585be68c32322b9a53c43a37b2Ashwin
760fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (result < 0) {
761fef13c11034313585be68c32322b9a53c43a37b2Ashwin            unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
762fef13c11034313585be68c32322b9a53c43a37b2Ashwin            return result;
763fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
764fef13c11034313585be68c32322b9a53c43a37b2Ashwin        ALOGI("Done!");
765fef13c11034313585be68c32322b9a53c43a37b2Ashwin        return result;
766fef13c11034313585be68c32322b9a53c43a37b2Ashwin    }
767fef13c11034313585be68c32322b9a53c43a37b2Ashwin
768fef13c11034313585be68c32322b9a53c43a37b2Ashwin    virtual int cancel() {
769fef13c11034313585be68c32322b9a53c43a37b2Ashwin
770fef13c11034313585be68c32322b9a53c43a37b2Ashwin        WifiRequest request(familyId(), ifaceId());
771fef13c11034313585be68c32322b9a53c43a37b2Ashwin        int result = createRequest(request, 0);
772fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (result != WIFI_SUCCESS) {
773fef13c11034313585be68c32322b9a53c43a37b2Ashwin            ALOGE("failed to create request; result = %d", result);
774fef13c11034313585be68c32322b9a53c43a37b2Ashwin        } else {
775fef13c11034313585be68c32322b9a53c43a37b2Ashwin            result = requestResponse(request);
776fef13c11034313585be68c32322b9a53c43a37b2Ashwin            if (result != WIFI_SUCCESS) {
777fef13c11034313585be68c32322b9a53c43a37b2Ashwin                ALOGE("failed to stop RSSI monitoring = %d", result);
778fef13c11034313585be68c32322b9a53c43a37b2Ashwin            }
779fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
780fef13c11034313585be68c32322b9a53c43a37b2Ashwin        unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
781fef13c11034313585be68c32322b9a53c43a37b2Ashwin        return WIFI_SUCCESS;
782fef13c11034313585be68c32322b9a53c43a37b2Ashwin    }
783fef13c11034313585be68c32322b9a53c43a37b2Ashwin
784fef13c11034313585be68c32322b9a53c43a37b2Ashwin    virtual int handleResponse(WifiEvent& reply) {
785fef13c11034313585be68c32322b9a53c43a37b2Ashwin        /* Nothing to do on response! */
786fef13c11034313585be68c32322b9a53c43a37b2Ashwin        return NL_SKIP;
787fef13c11034313585be68c32322b9a53c43a37b2Ashwin    }
788fef13c11034313585be68c32322b9a53c43a37b2Ashwin
789fef13c11034313585be68c32322b9a53c43a37b2Ashwin   virtual int handleEvent(WifiEvent& event) {
790fef13c11034313585be68c32322b9a53c43a37b2Ashwin        ALOGI("Got a RSSI monitor event");
791fef13c11034313585be68c32322b9a53c43a37b2Ashwin
792fef13c11034313585be68c32322b9a53c43a37b2Ashwin        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
793fef13c11034313585be68c32322b9a53c43a37b2Ashwin        int len = event.get_vendor_data_len();
794fef13c11034313585be68c32322b9a53c43a37b2Ashwin
795fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (vendor_data == NULL || len == 0) {
796fef13c11034313585be68c32322b9a53c43a37b2Ashwin            ALOGI("RSSI monitor: No data");
797fef13c11034313585be68c32322b9a53c43a37b2Ashwin            return NL_SKIP;
798fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
799fef13c11034313585be68c32322b9a53c43a37b2Ashwin        /* driver<->HAL event structure */
800fef13c11034313585be68c32322b9a53c43a37b2Ashwin        #define RSSI_MONITOR_EVT_VERSION   1
801fef13c11034313585be68c32322b9a53c43a37b2Ashwin        typedef struct {
802fef13c11034313585be68c32322b9a53c43a37b2Ashwin            u8 version;
803fef13c11034313585be68c32322b9a53c43a37b2Ashwin            s8 cur_rssi;
804fef13c11034313585be68c32322b9a53c43a37b2Ashwin            mac_addr BSSID;
805fef13c11034313585be68c32322b9a53c43a37b2Ashwin        } rssi_monitor_evt;
806fef13c11034313585be68c32322b9a53c43a37b2Ashwin
807fef13c11034313585be68c32322b9a53c43a37b2Ashwin        rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
808fef13c11034313585be68c32322b9a53c43a37b2Ashwin
809fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (data->version != RSSI_MONITOR_EVT_VERSION) {
810fef13c11034313585be68c32322b9a53c43a37b2Ashwin            ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION);
811fef13c11034313585be68c32322b9a53c43a37b2Ashwin            return NL_SKIP;
812fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
813fef13c11034313585be68c32322b9a53c43a37b2Ashwin
814fef13c11034313585be68c32322b9a53c43a37b2Ashwin        if (*mHandler.on_rssi_threshold_breached) {
815fef13c11034313585be68c32322b9a53c43a37b2Ashwin            (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
816fef13c11034313585be68c32322b9a53c43a37b2Ashwin        } else {
817fef13c11034313585be68c32322b9a53c43a37b2Ashwin            ALOGW("No RSSI monitor handler registered");
818fef13c11034313585be68c32322b9a53c43a37b2Ashwin        }
819fef13c11034313585be68c32322b9a53c43a37b2Ashwin
820fef13c11034313585be68c32322b9a53c43a37b2Ashwin        return NL_SKIP;
821fef13c11034313585be68c32322b9a53c43a37b2Ashwin    }
822fef13c11034313585be68c32322b9a53c43a37b2Ashwin
823fef13c11034313585be68c32322b9a53c43a37b2Ashwin};
824fef13c11034313585be68c32322b9a53c43a37b2Ashwin
825dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharmaclass AndroidPktFilterCommand : public WifiCommand {
826dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    private:
827dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        const u8* mProgram;
828dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        u32 mProgramLen;
829dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        u32* mVersion;
830dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        u32* mMaxLen;
831dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        int mReqType;
832dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    public:
833dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        AndroidPktFilterCommand(wifi_interface_handle handle,
834dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                u32* version, u32* max_len)
835dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            : WifiCommand("AndroidPktFilterCommand", handle, 0),
836dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                    mVersion(version), mMaxLen(max_len),
837dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                    mReqType(GET_APF_CAPABILITIES)
838dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        {
839dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
840dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
841dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        AndroidPktFilterCommand(wifi_interface_handle handle,
842dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                const u8* program, u32 len)
843dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            : WifiCommand("AndroidPktFilterCommand", handle, 0),
844dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                    mProgram(program), mProgramLen(len),
845dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                    mReqType(SET_APF_PROGRAM)
846dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        {
847dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
848dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
849dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    int createRequest(WifiRequest& request) {
850dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if (mReqType == SET_APF_PROGRAM) {
851dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            ALOGI("\n%s: APF set program request\n", __FUNCTION__);
852dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return createSetPktFilterRequest(request);
853dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        } else if (mReqType == GET_APF_CAPABILITIES) {
854dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            ALOGI("\n%s: APF get capabilities request\n", __FUNCTION__);
855dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return createGetPktFilterCapabilitesRequest(request);
856dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        } else {
857dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            ALOGE("\n%s Unknown APF request\n", __FUNCTION__);
858dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return WIFI_ERROR_NOT_SUPPORTED;
859dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
860dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        return WIFI_SUCCESS;
861dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    }
862dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
863dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    int createSetPktFilterRequest(WifiRequest& request) {
864dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        u8 *program = new u8[mProgramLen];
8656af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(program, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
866dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        int result = request.create(GOOGLE_OUI, APF_SUBCMD_SET_FILTER);
867dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if (result < 0) {
868dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return result;
869dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
870dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
871dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
872dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        result = request.put_u32(APF_ATTRIBUTE_PROGRAM_LEN, mProgramLen);
873dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if (result < 0) {
874dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return result;
875dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
876dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        memcpy(program, mProgram, mProgramLen);
877dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        result = request.put(APF_ATTRIBUTE_PROGRAM, program, mProgramLen);
878dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if (result < 0) {
879dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return result;
880dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
881dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        request.attr_end(data);
8826587f308b0c2d658dfe7cd988518d158cbd2f202Sreenath Sharma        delete[] program;
883dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        return result;
884dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    }
885dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
886dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    int createGetPktFilterCapabilitesRequest(WifiRequest& request) {
887dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        int result = request.create(GOOGLE_OUI, APF_SUBCMD_GET_CAPABILITIES);
888dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if (result < 0) {
889dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return result;
890dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
891dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
892dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
893dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        request.attr_end(data);
894dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        return result;
895dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    }
896dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
897dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    int start() {
898dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        WifiRequest request(familyId(), ifaceId());
899dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        int result = createRequest(request);
900dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if (result < 0) {
901dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return result;
902dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
903dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        result = requestResponse(request);
904dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if (result < 0) {
905dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            ALOGI("Request Response failed for APF, result = %d", result);
906dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return result;
907dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
908dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        ALOGI("Done!");
909dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        return result;
910dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    }
911dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
912dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    int cancel() {
913dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        return WIFI_SUCCESS;
914dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    }
915dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
916dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    int handleResponse(WifiEvent& reply) {
917dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        ALOGD("In SetAPFCommand::handleResponse");
918dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
919dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
920dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
921dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return NL_SKIP;
922dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
923dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
924dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        int id = reply.get_vendor_id();
925dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        int subcmd = reply.get_vendor_subcmd();
926dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
927dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
928dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        int len = reply.get_vendor_data_len();
929dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
930dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
931dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if (vendor_data == NULL || len == 0) {
932dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            ALOGE("no vendor data in SetAPFCommand response; ignoring it");
933dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            return NL_SKIP;
934dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
935dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        if( mReqType == SET_APF_PROGRAM) {
936dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            ALOGD("Response recieved for set packet filter command\n");
937dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        } else if (mReqType == GET_APF_CAPABILITIES) {
938dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            *mVersion = 0;
939dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            *mMaxLen = 0;
940dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            ALOGD("Response recieved for get packet filter capabilities command\n");
941dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
942dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                if (it.get_type() == APF_ATTRIBUTE_VERSION) {
943dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                    *mVersion = it.get_u32();
944dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                    ALOGI("APF version is %d\n", *mVersion);
945dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                } else if (it.get_type() == APF_ATTRIBUTE_MAX_LEN) {
946dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                    *mMaxLen = it.get_u32();
947dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                    ALOGI("APF max len is %d\n", *mMaxLen);
948dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                } else {
949dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                    ALOGE("Ignoring invalid attribute type = %d, size = %d",
950dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                            it.get_type(), it.get_len());
951dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma                }
952dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma            }
953dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        }
954dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        return NL_OK;
955dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    }
956dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
957dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    int handleEvent(WifiEvent& event) {
958dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        /* No Event to recieve for APF commands */
959dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        return NL_SKIP;
960dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    }
961dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma};
962dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
96365f9c6fbd929be309642cdaf255e8394aad2b0caJun Limclass SetNdoffloadCommand : public WifiCommand {
96465f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim
96565f9c6fbd929be309642cdaf255e8394aad2b0caJun Limprivate:
96665f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    u8 mEnable;
96765f9c6fbd929be309642cdaf255e8394aad2b0caJun Limpublic:
96865f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    SetNdoffloadCommand(wifi_interface_handle handle, u8 enable)
96965f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        : WifiCommand("SetNdoffloadCommand", handle, 0) {
97065f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        mEnable = enable;
97165f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    }
97265f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    virtual int create() {
97365f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        int ret;
97465f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim
97565f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_CONFIG_ND_OFFLOAD);
97665f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        if (ret < 0) {
97765f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim            ALOGE("Can't create message to send to driver - %d", ret);
97865f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim            return ret;
97965f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        }
98065f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim
98165f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
98265f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        ret = mMsg.put_u8(ANDR_WIFI_ATTRIBUTE_ND_OFFLOAD_VALUE, mEnable);
98365f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        if (ret < 0) {
98465f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim             return ret;
98565f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        }
98665f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim
98765f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        mMsg.attr_end(data);
98865f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        return WIFI_SUCCESS;
98965f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    }
99065f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim};
99165f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim
9929a23388d5a9f58f106169700bb179de0a4af7840Ashwinclass GetFeatureSetCommand : public WifiCommand {
9939a23388d5a9f58f106169700bb179de0a4af7840Ashwin
9949a23388d5a9f58f106169700bb179de0a4af7840Ashwinprivate:
9959a23388d5a9f58f106169700bb179de0a4af7840Ashwin    int feature_type;
9969a23388d5a9f58f106169700bb179de0a4af7840Ashwin    feature_set *fset;
9979a23388d5a9f58f106169700bb179de0a4af7840Ashwin    feature_set *feature_matrix;
9989a23388d5a9f58f106169700bb179de0a4af7840Ashwin    int *fm_size;
9999a23388d5a9f58f106169700bb179de0a4af7840Ashwin    int set_size_max;
10009a23388d5a9f58f106169700bb179de0a4af7840Ashwinpublic:
10019a23388d5a9f58f106169700bb179de0a4af7840Ashwin    GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set,
10029a23388d5a9f58f106169700bb179de0a4af7840Ashwin         feature_set set_matrix[], int *size, int max_size)
1003d4f6adc737f93d75d3a1be8427a144f907a4dde6Vinit Deshpande        : WifiCommand("GetFeatureSetCommand", handle, 0)
10049a23388d5a9f58f106169700bb179de0a4af7840Ashwin    {
10059a23388d5a9f58f106169700bb179de0a4af7840Ashwin        feature_type = feature;
10069a23388d5a9f58f106169700bb179de0a4af7840Ashwin        fset = set;
10079a23388d5a9f58f106169700bb179de0a4af7840Ashwin        feature_matrix = set_matrix;
10089a23388d5a9f58f106169700bb179de0a4af7840Ashwin        fm_size = size;
10099a23388d5a9f58f106169700bb179de0a4af7840Ashwin        set_size_max = max_size;
10109a23388d5a9f58f106169700bb179de0a4af7840Ashwin    }
10119a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10129a23388d5a9f58f106169700bb179de0a4af7840Ashwin    virtual int create() {
10139a23388d5a9f58f106169700bb179de0a4af7840Ashwin        int ret;
10149a23388d5a9f58f106169700bb179de0a4af7840Ashwin
101565f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        if(feature_type == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
10169a23388d5a9f58f106169700bb179de0a4af7840Ashwin            ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET);
101765f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        } else if (feature_type == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) {
10189a23388d5a9f58f106169700bb179de0a4af7840Ashwin            ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX);
10199a23388d5a9f58f106169700bb179de0a4af7840Ashwin        } else {
10209a23388d5a9f58f106169700bb179de0a4af7840Ashwin            ALOGE("Unknown feature type %d", feature_type);
10219a23388d5a9f58f106169700bb179de0a4af7840Ashwin            return -1;
10229a23388d5a9f58f106169700bb179de0a4af7840Ashwin        }
10239a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10249a23388d5a9f58f106169700bb179de0a4af7840Ashwin        if (ret < 0) {
10259a23388d5a9f58f106169700bb179de0a4af7840Ashwin            ALOGE("Can't create message to send to driver - %d", ret);
10269a23388d5a9f58f106169700bb179de0a4af7840Ashwin        }
10279a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10289a23388d5a9f58f106169700bb179de0a4af7840Ashwin        return ret;
10299a23388d5a9f58f106169700bb179de0a4af7840Ashwin    }
10309a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10319a23388d5a9f58f106169700bb179de0a4af7840Ashwinprotected:
10329a23388d5a9f58f106169700bb179de0a4af7840Ashwin    virtual int handleResponse(WifiEvent& reply) {
10339a23388d5a9f58f106169700bb179de0a4af7840Ashwin
1034ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande        ALOGV("In GetFeatureSetCommand::handleResponse");
10359a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10369a23388d5a9f58f106169700bb179de0a4af7840Ashwin        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
10379a23388d5a9f58f106169700bb179de0a4af7840Ashwin            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
10389a23388d5a9f58f106169700bb179de0a4af7840Ashwin            return NL_SKIP;
10399a23388d5a9f58f106169700bb179de0a4af7840Ashwin        }
10409a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10419a23388d5a9f58f106169700bb179de0a4af7840Ashwin        int id = reply.get_vendor_id();
10429a23388d5a9f58f106169700bb179de0a4af7840Ashwin        int subcmd = reply.get_vendor_subcmd();
10439a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10449a23388d5a9f58f106169700bb179de0a4af7840Ashwin        nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
10459a23388d5a9f58f106169700bb179de0a4af7840Ashwin        int len = reply.get_vendor_data_len();
10469a23388d5a9f58f106169700bb179de0a4af7840Ashwin
1047ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande        ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
10489a23388d5a9f58f106169700bb179de0a4af7840Ashwin        if (vendor_data == NULL || len == 0) {
10499a23388d5a9f58f106169700bb179de0a4af7840Ashwin            ALOGE("no vendor data in GetFeatureSetCommand response; ignoring it");
10509a23388d5a9f58f106169700bb179de0a4af7840Ashwin            return NL_SKIP;
10519a23388d5a9f58f106169700bb179de0a4af7840Ashwin        }
105265f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim        if(feature_type == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
10539a23388d5a9f58f106169700bb179de0a4af7840Ashwin            void *data = reply.get_vendor_data();
10549a23388d5a9f58f106169700bb179de0a4af7840Ashwin            if(!fset) {
10559a23388d5a9f58f106169700bb179de0a4af7840Ashwin                ALOGE("Buffers pointers not set");
10569a23388d5a9f58f106169700bb179de0a4af7840Ashwin                return NL_SKIP;
10579a23388d5a9f58f106169700bb179de0a4af7840Ashwin            }
10589a23388d5a9f58f106169700bb179de0a4af7840Ashwin            memcpy(fset, data, min(len, (int) sizeof(*fset)));
10599a23388d5a9f58f106169700bb179de0a4af7840Ashwin        } else {
10609a23388d5a9f58f106169700bb179de0a4af7840Ashwin            int num_features_set = 0;
10619a23388d5a9f58f106169700bb179de0a4af7840Ashwin            int i = 0;
10629a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10639a23388d5a9f58f106169700bb179de0a4af7840Ashwin            if(!feature_matrix || !fm_size) {
10649a23388d5a9f58f106169700bb179de0a4af7840Ashwin                ALOGE("Buffers pointers not set");
10659a23388d5a9f58f106169700bb179de0a4af7840Ashwin                return NL_SKIP;
10669a23388d5a9f58f106169700bb179de0a4af7840Ashwin            }
10679a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10689a23388d5a9f58f106169700bb179de0a4af7840Ashwin            for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
10699a23388d5a9f58f106169700bb179de0a4af7840Ashwin                if (it.get_type() == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
10709a23388d5a9f58f106169700bb179de0a4af7840Ashwin                    num_features_set = it.get_u32();
1071ec74fa4fcb49a35e6af54e086e63692b37d21b02Vinit Deshpande                    ALOGV("Got feature list with %d concurrent sets", num_features_set);
10729a23388d5a9f58f106169700bb179de0a4af7840Ashwin                    if(set_size_max && (num_features_set > set_size_max))
10739a23388d5a9f58f106169700bb179de0a4af7840Ashwin                        num_features_set = set_size_max;
10749a23388d5a9f58f106169700bb179de0a4af7840Ashwin                    *fm_size = num_features_set;
10759a23388d5a9f58f106169700bb179de0a4af7840Ashwin                } else if ((it.get_type() == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) &&
10769a23388d5a9f58f106169700bb179de0a4af7840Ashwin                             i < num_features_set) {
10779a23388d5a9f58f106169700bb179de0a4af7840Ashwin                    feature_matrix[i] = it.get_u32();
10789a23388d5a9f58f106169700bb179de0a4af7840Ashwin                    i++;
10799a23388d5a9f58f106169700bb179de0a4af7840Ashwin                } else {
10809a23388d5a9f58f106169700bb179de0a4af7840Ashwin                    ALOGW("Ignoring invalid attribute type = %d, size = %d",
10819a23388d5a9f58f106169700bb179de0a4af7840Ashwin                            it.get_type(), it.get_len());
10829a23388d5a9f58f106169700bb179de0a4af7840Ashwin                }
10839a23388d5a9f58f106169700bb179de0a4af7840Ashwin            }
10849a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10859a23388d5a9f58f106169700bb179de0a4af7840Ashwin        }
10869a23388d5a9f58f106169700bb179de0a4af7840Ashwin        return NL_OK;
10879a23388d5a9f58f106169700bb179de0a4af7840Ashwin    }
10889a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10899a23388d5a9f58f106169700bb179de0a4af7840Ashwin};
10909a23388d5a9f58f106169700bb179de0a4af7840Ashwin
10911a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
10921a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
10931a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    GetMulticastIdCommand cmd(handle, name, group);
10941a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int res = cmd.requestResponse();
10951a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (res < 0)
10961a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return res;
10971a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    else
10981a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return cmd.getId();
10991a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
11001a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11011a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde/////////////////////////////////////////////////////////////////////////
11021a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11031a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic bool is_wifi_interface(const char *name)
11041a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
11051a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
11061a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        /* not a wifi interface; ignore it */
11071a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return false;
11081a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    } else {
11091a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return true;
11101a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
11111a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
11121a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndestatic int get_interface(const char *name, interface_info *info)
11141a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
11151a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    strcpy(info->name, name);
11161a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->id = if_nametoindex(name);
11171a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    // ALOGI("found an interface : %s, id = %d", name, info->id);
11181a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return WIFI_SUCCESS;
11191a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
11201a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11211a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_init_interfaces(wifi_handle handle)
11221a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
11231a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    hal_info *info = (hal_info *)handle;
11241a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11251a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    struct dirent *de;
11261a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11271a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    DIR *d = opendir("/sys/class/net");
11281a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (d == 0)
11291a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_ERROR_UNKNOWN;
11301a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11311a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int n = 0;
11321a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    while ((de = readdir(d))) {
11331a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (de->d_name[0] == '.')
11341a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            continue;
11351a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (is_wifi_interface(de->d_name) ) {
11361a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            n++;
11371a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11381a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
11391a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11401a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    closedir(d);
11411a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11421a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    d = opendir("/sys/class/net");
11431a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    if (d == 0)
11441a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        return WIFI_ERROR_UNKNOWN;
11451a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11461a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
11471a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11481a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    int i = 0;
11491a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    while ((de = readdir(d))) {
11501a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (de->d_name[0] == '.')
11511a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            continue;
11521a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        if (is_wifi_interface(de->d_name)) {
11531a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
11541a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
11551a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                free(ifinfo);
11561a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde                continue;
11571a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            }
11581a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            ifinfo->handle = handle;
11591a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            info->interfaces[i] = ifinfo;
11601a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde            i++;
11611a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde        }
11621a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    }
11631a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11641a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    closedir(d);
11651a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11661a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    info->num_interfaces = n;
11671a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return WIFI_SUCCESS;
11681a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
11691a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11701a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
11711a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
11721a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    hal_info *info = (hal_info *)handle;
11731a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11741a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    *interfaces = (wifi_interface_handle *)info->interfaces;
11751a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    *num = info->num_interfaces;
11761a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11771a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return WIFI_SUCCESS;
11781a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
11791a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11801a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapndewifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
11811a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde{
11821a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    interface_info *info = (interface_info *)handle;
11831a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    strcpy(name, info->name);
11841a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde    return WIFI_SUCCESS;
11851a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde}
11861a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
11879a23388d5a9f58f106169700bb179de0a4af7840Ashwinwifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
11889a23388d5a9f58f106169700bb179de0a4af7840Ashwin{
118965f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET, set, NULL, NULL, 1);
11909a23388d5a9f58f106169700bb179de0a4af7840Ashwin    return (wifi_error) command.requestResponse();
11919a23388d5a9f58f106169700bb179de0a4af7840Ashwin}
11929a23388d5a9f58f106169700bb179de0a4af7840Ashwin
11939a23388d5a9f58f106169700bb179de0a4af7840Ashwinwifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
11949a23388d5a9f58f106169700bb179de0a4af7840Ashwin       feature_set set[], int *set_size)
11959a23388d5a9f58f106169700bb179de0a4af7840Ashwin{
119665f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    GetFeatureSetCommand command(handle, ANDR_WIFI_ATTRIBUTE_FEATURE_SET, NULL,
119765f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim            set, set_size, set_size_max);
11989a23388d5a9f58f106169700bb179de0a4af7840Ashwin    return (wifi_error) command.requestResponse();
11999a23388d5a9f58f106169700bb179de0a4af7840Ashwin}
12009a23388d5a9f58f106169700bb179de0a4af7840Ashwin
1201f0d5070a931327e6356d765478069b9e66452a5bAshwinwifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
1202f0d5070a931327e6356d765478069b9e66452a5bAshwin{
1203f0d5070a931327e6356d765478069b9e66452a5bAshwin    SetPnoMacAddrOuiCommand command(handle, scan_oui);
1204f0d5070a931327e6356d765478069b9e66452a5bAshwin    return (wifi_error)command.start();
1205f0d5070a931327e6356d765478069b9e66452a5bAshwin
1206f0d5070a931327e6356d765478069b9e66452a5bAshwin}
1207f0d5070a931327e6356d765478069b9e66452a5bAshwin
1208b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidtwifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
1209b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt{
1210b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt    SetNodfsCommand command(handle, nodfs);
1211b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt    return (wifi_error) command.requestResponse();
1212b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt}
12131a526434ae215b48970501ccb463d4e77af39c9eVinit Deshapnde
1214c02e00563882d87ab29822c43097cbb1ce04b55dxinhewifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
1215c02e00563882d87ab29822c43097cbb1ce04b55dxinhe{
1216c02e00563882d87ab29822c43097cbb1ce04b55dxinhe    SetCountryCodeCommand command(handle, country_code);
1217c02e00563882d87ab29822c43097cbb1ce04b55dxinhe    return (wifi_error) command.requestResponse();
1218c02e00563882d87ab29822c43097cbb1ce04b55dxinhe}
1219c02e00563882d87ab29822c43097cbb1ce04b55dxinhe
1220fef13c11034313585be68c32322b9a53c43a37b2Ashwinstatic wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
1221fef13c11034313585be68c32322b9a53c43a37b2Ashwin                        iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
1222fef13c11034313585be68c32322b9a53c43a37b2Ashwin{
1223fef13c11034313585be68c32322b9a53c43a37b2Ashwin    ALOGD("Start RSSI monitor %d", id);
1224fef13c11034313585be68c32322b9a53c43a37b2Ashwin    wifi_handle handle = getWifiHandle(iface);
1225fef13c11034313585be68c32322b9a53c43a37b2Ashwin    SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
12266af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
12276af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = wifi_register_cmd(handle, id, cmd);
12286af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result != WIFI_SUCCESS) {
12296af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
12306af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
12316af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    }
12326af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    result = (wifi_error)cmd->start();
1233340c22b114039948cbdc124797fd84d58a80462cAshwin    if (result != WIFI_SUCCESS) {
1234340c22b114039948cbdc124797fd84d58a80462cAshwin        wifi_unregister_cmd(handle, id);
12356af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        cmd->releaseRef();
12366af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        return result;
1237340c22b114039948cbdc124797fd84d58a80462cAshwin    }
1238340c22b114039948cbdc124797fd84d58a80462cAshwin    return result;
1239fef13c11034313585be68c32322b9a53c43a37b2Ashwin}
1240fef13c11034313585be68c32322b9a53c43a37b2Ashwin
1241fef13c11034313585be68c32322b9a53c43a37b2Ashwinstatic wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
1242fef13c11034313585be68c32322b9a53c43a37b2Ashwin{
1243fef13c11034313585be68c32322b9a53c43a37b2Ashwin    ALOGD("Stopping RSSI monitor");
1244fef13c11034313585be68c32322b9a53c43a37b2Ashwin
1245fef13c11034313585be68c32322b9a53c43a37b2Ashwin    if(id == -1) {
1246fef13c11034313585be68c32322b9a53c43a37b2Ashwin        wifi_rssi_event_handler handler;
1247fef13c11034313585be68c32322b9a53c43a37b2Ashwin        s8 max_rssi = 0, min_rssi = 0;
1248fef13c11034313585be68c32322b9a53c43a37b2Ashwin        wifi_handle handle = getWifiHandle(iface);
1249fef13c11034313585be68c32322b9a53c43a37b2Ashwin        memset(&handler, 0, sizeof(handler));
1250fef13c11034313585be68c32322b9a53c43a37b2Ashwin        SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
1251fef13c11034313585be68c32322b9a53c43a37b2Ashwin                                                    max_rssi, min_rssi, handler);
12526af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma        NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1253fef13c11034313585be68c32322b9a53c43a37b2Ashwin        cmd->cancel();
1254fef13c11034313585be68c32322b9a53c43a37b2Ashwin        cmd->releaseRef();
1255fef13c11034313585be68c32322b9a53c43a37b2Ashwin        return WIFI_SUCCESS;
1256fef13c11034313585be68c32322b9a53c43a37b2Ashwin    }
1257fef13c11034313585be68c32322b9a53c43a37b2Ashwin    return wifi_cancel_cmd(id, iface);
1258fef13c11034313585be68c32322b9a53c43a37b2Ashwin}
1259fef13c11034313585be68c32322b9a53c43a37b2Ashwin
1260dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharmastatic wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
1261dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        u32 *version, u32 *max_len)
1262dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma{
1263dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    ALOGD("Getting APF capabilities, halHandle = %p\n", handle);
1264dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, version, max_len);
12656af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
12666af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = (wifi_error)cmd->start();
12676af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    if (result == WIFI_SUCCESS) {
1268dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        ALOGD("Getting APF capability, version = %d, max_len = %d\n", *version, *max_len);
1269dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    }
12706af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    cmd->releaseRef();
12716af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
1272dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma}
1273dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
1274dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharmastatic wifi_error wifi_set_packet_filter(wifi_interface_handle handle,
1275dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma        const u8 *program, u32 len)
1276dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma{
1277dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    ALOGD("Setting APF program, halHandle = %p\n", handle);
1278dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma    AndroidPktFilterCommand *cmd = new AndroidPktFilterCommand(handle, program, len);
12796af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
12806af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    wifi_error result = (wifi_error)cmd->start();
12816af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    cmd->releaseRef();
12826af064b77bfdc84a6f425a7c9d0941fad11f4489Sreenath Sharma    return result;
1283dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma}
1284dfe5b594561312993f587dc29e524d400e8fbc77Sreenath Sharma
128565f9c6fbd929be309642cdaf255e8394aad2b0caJun Limstatic wifi_error wifi_configure_nd_offload(wifi_interface_handle handle, u8 enable)
128665f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim{
128765f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    SetNdoffloadCommand command(handle, enable);
128865f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim    return (wifi_error) command.requestResponse();
128965f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim}
129065f9c6fbd929be309642cdaf255e8394aad2b0caJun Lim
1291b4ac10a4e1eddf00ddad32f3307cc050bb4e0963Dmitry Shmidt/////////////////////////////////////////////////////////////////////////////
1292