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