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