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