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 #define FEATURE_SET                  0
     46 #define FEATURE_SET_MATRIX           1
     47 #define ATTR_NODFS_VALUE             3
     48 #define ATTR_COUNTRY_CODE            4
     49 
     50 static void internal_event_handler(wifi_handle handle, int events);
     51 static int internal_no_seq_check(nl_msg *msg, void *arg);
     52 static int internal_valid_message_handler(nl_msg *msg, void *arg);
     53 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group);
     54 static int wifi_add_membership(wifi_handle handle, const char *group);
     55 static wifi_error wifi_init_interfaces(wifi_handle handle);
     56 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
     57                         iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh);
     58 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface);
     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 } wifi_attr_t;
     65 
     66 enum wifi_rssi_monitor_attr {
     67     RSSI_MONITOR_ATTRIBUTE_MAX_RSSI,
     68     RSSI_MONITOR_ATTRIBUTE_MIN_RSSI,
     69     RSSI_MONITOR_ATTRIBUTE_START,
     70 };
     71 
     72 /* Initialize/Cleanup */
     73 
     74 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
     75 {
     76     uint32_t pid = getpid() & 0x3FFFFF;
     77     nl_socket_set_local_port(sock, pid + (port << 22));
     78 }
     79 
     80 static nl_sock * wifi_create_nl_socket(int port)
     81 {
     82     // ALOGI("Creating socket");
     83     struct nl_sock *sock = nl_socket_alloc();
     84     if (sock == NULL) {
     85         ALOGE("Could not create handle");
     86         return NULL;
     87     }
     88 
     89     wifi_socket_set_local_port(sock, port);
     90 
     91     struct sockaddr *addr = NULL;
     92     // ALOGI("sizeof(sockaddr) = %d, sizeof(sockaddr_nl) = %d", sizeof(*addr), sizeof(*addr_nl));
     93 
     94     // ALOGI("Connecting socket");
     95     if (nl_connect(sock, NETLINK_GENERIC)) {
     96         ALOGE("Could not connect handle");
     97         nl_socket_free(sock);
     98         return NULL;
     99     }
    100 
    101     // ALOGI("Making socket nonblocking");
    102     /*
    103     if (nl_socket_set_nonblocking(sock)) {
    104         ALOGE("Could make socket non-blocking");
    105         nl_socket_free(sock);
    106         return NULL;
    107     }
    108     */
    109 
    110     return sock;
    111 }
    112 
    113 /*initialize function pointer table with Broadcom HHAL API*/
    114 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn)
    115 {
    116     if (fn == NULL) {
    117         return WIFI_ERROR_UNKNOWN;
    118     }
    119     fn->wifi_initialize = wifi_initialize;
    120     fn->wifi_cleanup = wifi_cleanup;
    121     fn->wifi_event_loop = wifi_event_loop;
    122     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
    123     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
    124     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
    125     fn->wifi_get_ifaces = wifi_get_ifaces;
    126     fn->wifi_get_iface_name = wifi_get_iface_name;
    127     fn->wifi_start_gscan = wifi_start_gscan;
    128     fn->wifi_stop_gscan = wifi_stop_gscan;
    129     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
    130     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
    131     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
    132     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
    133     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
    134     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
    135     fn->wifi_get_link_stats = wifi_get_link_stats;
    136     fn->wifi_get_valid_channels = wifi_get_valid_channels;
    137     fn->wifi_rtt_range_request = wifi_rtt_range_request;
    138     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
    139     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
    140     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
    141     fn->wifi_start_logging = wifi_start_logging;
    142     fn->wifi_set_epno_list = wifi_set_epno_list;
    143     fn->wifi_set_country_code = wifi_set_country_code;
    144     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
    145     fn->wifi_set_log_handler = wifi_set_log_handler;
    146     fn->wifi_reset_log_handler = wifi_reset_log_handler;
    147     fn->wifi_set_alert_handler = wifi_set_alert_handler;
    148     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
    149     fn->wifi_get_firmware_version = wifi_get_firmware_version;
    150     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
    151     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
    152     fn->wifi_get_ring_data = wifi_get_ring_data;
    153     fn->wifi_get_driver_version = wifi_get_driver_version;
    154     fn->wifi_set_ssid_white_list = wifi_set_ssid_white_list;
    155     fn->wifi_set_gscan_roam_params = wifi_set_gscan_roam_params;
    156     fn->wifi_set_bssid_preference = wifi_set_bssid_preference;
    157     fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
    158     fn->wifi_enable_lazy_roam = wifi_enable_lazy_roam;
    159     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
    160     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
    161     fn->wifi_start_sending_offloaded_packet = wifi_start_sending_offloaded_packet;
    162     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
    163     return WIFI_SUCCESS;
    164 }
    165 
    166 wifi_error wifi_initialize(wifi_handle *handle)
    167 {
    168     srand(getpid());
    169 
    170     ALOGI("Initializing wifi");
    171     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
    172     if (info == NULL) {
    173         ALOGE("Could not allocate hal_info");
    174         return WIFI_ERROR_UNKNOWN;
    175     }
    176 
    177     memset(info, 0, sizeof(*info));
    178 
    179     ALOGI("Creating socket");
    180     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->cleanup_socks) == -1) {
    181         ALOGE("Could not create cleanup sockets");
    182         return WIFI_ERROR_UNKNOWN;
    183     }
    184 
    185     struct nl_sock *cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT);
    186     if (cmd_sock == NULL) {
    187         ALOGE("Could not create handle");
    188         return WIFI_ERROR_UNKNOWN;
    189     }
    190 
    191     struct nl_sock *event_sock = wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT);
    192     if (event_sock == NULL) {
    193         ALOGE("Could not create handle");
    194         nl_socket_free(cmd_sock);
    195         return WIFI_ERROR_UNKNOWN;
    196     }
    197 
    198     struct nl_cb *cb = nl_socket_get_cb(event_sock);
    199     if (cb == NULL) {
    200         ALOGE("Could not create handle");
    201         return WIFI_ERROR_UNKNOWN;
    202     }
    203 
    204     // ALOGI("cb->refcnt = %d", cb->cb_refcnt);
    205     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, internal_no_seq_check, info);
    206     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler, info);
    207     nl_cb_put(cb);
    208 
    209     info->cmd_sock = cmd_sock;
    210     info->event_sock = event_sock;
    211     info->clean_up = false;
    212     info->in_event_loop = false;
    213 
    214     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
    215     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
    216     info->num_event_cb = 0;
    217 
    218     info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
    219     info->alloc_cmd = DEFAULT_CMD_SIZE;
    220     info->num_cmd = 0;
    221 
    222     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
    223     if (info->nl80211_family_id < 0) {
    224         ALOGE("Could not resolve nl80211 familty id");
    225         nl_socket_free(cmd_sock);
    226         nl_socket_free(event_sock);
    227         free(info);
    228         return WIFI_ERROR_UNKNOWN;
    229     }
    230 
    231     pthread_mutex_init(&info->cb_lock, NULL);
    232 
    233     *handle = (wifi_handle) info;
    234 
    235     wifi_add_membership(*handle, "scan");
    236     wifi_add_membership(*handle, "mlme");
    237     wifi_add_membership(*handle, "regulatory");
    238     wifi_add_membership(*handle, "vendor");
    239 
    240     wifi_init_interfaces(*handle);
    241     // ALOGI("Found %d interfaces", info->num_interfaces);
    242 
    243 
    244     ALOGI("Initialized Wifi HAL Successfully; vendor cmd = %d", NL80211_CMD_VENDOR);
    245     return WIFI_SUCCESS;
    246 }
    247 
    248 static int wifi_add_membership(wifi_handle handle, const char *group)
    249 {
    250     hal_info *info = getHalInfo(handle);
    251 
    252     int id = wifi_get_multicast_id(handle, "nl80211", group);
    253     if (id < 0) {
    254         ALOGE("Could not find group %s", group);
    255         return id;
    256     }
    257 
    258     int ret = nl_socket_add_membership(info->event_sock, id);
    259     if (ret < 0) {
    260         ALOGE("Could not add membership to group %s", group);
    261     }
    262 
    263     // ALOGI("Successfully added membership for group %s", group);
    264     return ret;
    265 }
    266 
    267 static void internal_cleaned_up_handler(wifi_handle handle)
    268 {
    269     hal_info *info = getHalInfo(handle);
    270     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
    271 
    272     if (info->cmd_sock != 0) {
    273         close(info->cleanup_socks[0]);
    274         close(info->cleanup_socks[1]);
    275         nl_socket_free(info->cmd_sock);
    276         nl_socket_free(info->event_sock);
    277         info->cmd_sock = NULL;
    278         info->event_sock = NULL;
    279     }
    280 
    281     (*cleaned_up_handler)(handle);
    282     pthread_mutex_destroy(&info->cb_lock);
    283     free(info);
    284 
    285     ALOGI("Internal cleanup completed");
    286 }
    287 
    288 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
    289 {
    290     hal_info *info = getHalInfo(handle);
    291     info->cleaned_up_handler = handler;
    292     info->clean_up = true;
    293 
    294     pthread_mutex_lock(&info->cb_lock);
    295 
    296     int bad_commands = 0;
    297 
    298     for (int i = 0; i < info->num_event_cb; i++) {
    299         cb_info *cbi = &(info->event_cb[i]);
    300         WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
    301         ALOGE("Command left in event_cb %p:%s", cmd, cmd->getType());
    302     }
    303 
    304     while (info->num_cmd > bad_commands) {
    305         int num_cmd = info->num_cmd;
    306         cmd_info *cmdi = &(info->cmd[bad_commands]);
    307         WifiCommand *cmd = cmdi->cmd;
    308         if (cmd != NULL) {
    309             ALOGD("Cancelling command %p:%s", cmd, cmd->getType());
    310             pthread_mutex_unlock(&info->cb_lock);
    311             cmd->cancel();
    312             pthread_mutex_lock(&info->cb_lock);
    313             /* release reference added when command is saved */
    314             cmd->releaseRef();
    315             if (num_cmd == info->num_cmd) {
    316                 ALOGE("Cancelling command %p:%s did not work", cmd, cmd->getType());
    317                 bad_commands++;
    318             }
    319         }
    320     }
    321 
    322     for (int i = 0; i < info->num_event_cb; i++) {
    323         cb_info *cbi = &(info->event_cb[i]);
    324         WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
    325         ALOGE("Leaked command %p", cmd);
    326     }
    327 
    328     pthread_mutex_unlock(&info->cb_lock);
    329 
    330     if (write(info->cleanup_socks[0], "T", 1) < 1) {
    331         ALOGE("could not write to cleanup socket");
    332     } else {
    333         ALOGI("Wifi cleanup completed");
    334     }
    335 }
    336 
    337 static int internal_pollin_handler(wifi_handle handle)
    338 {
    339     hal_info *info = getHalInfo(handle);
    340     struct nl_cb *cb = nl_socket_get_cb(info->event_sock);
    341     int res = nl_recvmsgs(info->event_sock, cb);
    342     // ALOGD("nl_recvmsgs returned %d", res);
    343     nl_cb_put(cb);
    344     return res;
    345 }
    346 
    347 /* Run event handler */
    348 void wifi_event_loop(wifi_handle handle)
    349 {
    350     hal_info *info = getHalInfo(handle);
    351     if (info->in_event_loop) {
    352         return;
    353     } else {
    354         info->in_event_loop = true;
    355     }
    356 
    357     pollfd pfd[2];
    358     memset(&pfd[0], 0, sizeof(pollfd) * 2);
    359 
    360     pfd[0].fd = nl_socket_get_fd(info->event_sock);
    361     pfd[0].events = POLLIN;
    362     pfd[1].fd = info->cleanup_socks[1];
    363     pfd[1].events = POLLIN;
    364 
    365     char buf[2048];
    366     /* TODO: Add support for timeouts */
    367 
    368     do {
    369         int timeout = -1;                   /* Infinite timeout */
    370         pfd[0].revents = 0;
    371         pfd[1].revents = 0;
    372         // ALOGI("Polling socket");
    373         int result = poll(pfd, 2, timeout);
    374         if (result < 0) {
    375             // ALOGE("Error polling socket");
    376         } else if (pfd[0].revents & POLLERR) {
    377             ALOGE("POLL Error; error no = %d", errno);
    378             int result2 = read(pfd[0].fd, buf, sizeof(buf));
    379             ALOGE("Read after POLL returned %d, error no = %d", result2, errno);
    380         } else if (pfd[0].revents & POLLHUP) {
    381             ALOGE("Remote side hung up");
    382             break;
    383         } else if (pfd[0].revents & POLLIN) {
    384             // ALOGI("Found some events!!!");
    385             internal_pollin_handler(handle);
    386         } else if (pfd[1].revents & POLLIN) {
    387             ALOGI("Got a signal to exit!!!");
    388             int result2 = read(pfd[1].fd, buf, sizeof(buf));
    389             ALOGE("Read after POLL returned %d, error no = %d", result2, errno);
    390         } else {
    391             ALOGE("Unknown event - %0x, %0x", pfd[0].revents, pfd[1].revents);
    392         }
    393     } while (!info->clean_up);
    394 
    395     ALOGI("Cleaning up");
    396     internal_cleaned_up_handler(handle);
    397 }
    398 
    399 ///////////////////////////////////////////////////////////////////////////////////////
    400 
    401 static int internal_no_seq_check(struct nl_msg *msg, void *arg)
    402 {
    403     return NL_OK;
    404 }
    405 
    406 static int internal_valid_message_handler(nl_msg *msg, void *arg)
    407 {
    408     // ALOGI("got an event");
    409 
    410     wifi_handle handle = (wifi_handle)arg;
    411     hal_info *info = getHalInfo(handle);
    412 
    413     WifiEvent event(msg);
    414     int res = event.parse();
    415     if (res < 0) {
    416         ALOGE("Failed to parse event: %d", res);
    417         return NL_SKIP;
    418     }
    419 
    420     int cmd = event.get_cmd();
    421     uint32_t vendor_id = 0;
    422     int subcmd = 0;
    423 
    424     if (cmd == NL80211_CMD_VENDOR) {
    425         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
    426         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
    427         ALOGV("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
    428                 event.get_cmdString(), vendor_id, subcmd);
    429     } else {
    430         // ALOGV("event received %s", event.get_cmdString());
    431     }
    432 
    433     // ALOGV("event received %s, vendor_id = 0x%0x", event.get_cmdString(), vendor_id);
    434     // event.log();
    435 
    436     bool dispatched = false;
    437 
    438     pthread_mutex_lock(&info->cb_lock);
    439 
    440     for (int i = 0; i < info->num_event_cb; i++) {
    441         if (cmd == info->event_cb[i].nl_cmd) {
    442             if (cmd == NL80211_CMD_VENDOR
    443                 && ((vendor_id != info->event_cb[i].vendor_id)
    444                 || (subcmd != info->event_cb[i].vendor_subcmd)))
    445             {
    446                 /* event for a different vendor, ignore it */
    447                 continue;
    448             }
    449 
    450             cb_info *cbi = &(info->event_cb[i]);
    451             nl_recvmsg_msg_cb_t cb_func = cbi->cb_func;
    452             void *cb_arg = cbi->cb_arg;
    453             WifiCommand *cmd = (WifiCommand *)cbi->cb_arg;
    454             if (cmd != NULL) {
    455                 cmd->addRef();
    456             }
    457 
    458             pthread_mutex_unlock(&info->cb_lock);
    459 
    460             (*cb_func)(msg, cb_arg);
    461             if (cmd != NULL) {
    462                 cmd->releaseRef();
    463             }
    464 
    465             return NL_OK;
    466         }
    467     }
    468 
    469     pthread_mutex_unlock(&info->cb_lock);
    470     return NL_OK;
    471 }
    472 
    473 ///////////////////////////////////////////////////////////////////////////////////////
    474 
    475 class GetMulticastIdCommand : public WifiCommand
    476 {
    477 private:
    478     const char *mName;
    479     const char *mGroup;
    480     int   mId;
    481 public:
    482     GetMulticastIdCommand(wifi_handle handle, const char *name, const char *group)
    483         : WifiCommand("GetMulticastIdCommand", handle, 0)
    484     {
    485         mName = name;
    486         mGroup = group;
    487         mId = -1;
    488     }
    489 
    490     int getId() {
    491         return mId;
    492     }
    493 
    494     virtual int create() {
    495         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
    496         // ALOGI("ctrl family = %d", nlctrlFamily);
    497         int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
    498         if (ret < 0) {
    499             return ret;
    500         }
    501         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
    502         return ret;
    503     }
    504 
    505     virtual int handleResponse(WifiEvent& reply) {
    506 
    507         // ALOGI("handling reponse in %s", __func__);
    508 
    509         struct nlattr **tb = reply.attributes();
    510         struct genlmsghdr *gnlh = reply.header();
    511         struct nlattr *mcgrp = NULL;
    512         int i;
    513 
    514         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
    515             ALOGI("No multicast groups found");
    516             return NL_SKIP;
    517         } else {
    518             // ALOGI("Multicast groups attr size = %d", nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
    519         }
    520 
    521         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
    522 
    523             // ALOGI("Processing group");
    524             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
    525             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
    526                 nla_len(mcgrp), NULL);
    527             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID]) {
    528                 continue;
    529             }
    530 
    531             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
    532             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
    533 
    534             // ALOGI("Found group name %s", grpName);
    535 
    536             if (strncmp(grpName, mGroup, grpNameLen) != 0)
    537                 continue;
    538 
    539             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
    540             break;
    541         }
    542 
    543         return NL_SKIP;
    544     }
    545 
    546 };
    547 
    548 class SetPnoMacAddrOuiCommand : public WifiCommand {
    549 
    550 private:
    551     byte *mOui;
    552     feature_set *fset;
    553     feature_set *feature_matrix;
    554     int *fm_size;
    555     int set_size_max;
    556 public:
    557     SetPnoMacAddrOuiCommand(wifi_interface_handle handle, oui scan_oui)
    558         : WifiCommand("SetPnoMacAddrOuiCommand", handle, 0)
    559     {
    560         mOui = scan_oui;
    561     }
    562 
    563     int createRequest(WifiRequest& request, int subcmd, byte *scan_oui) {
    564         int result = request.create(GOOGLE_OUI, subcmd);
    565         if (result < 0) {
    566             return result;
    567         }
    568 
    569         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    570         result = request.put(ANDR_WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, scan_oui, DOT11_OUI_LEN);
    571         if (result < 0) {
    572             return result;
    573         }
    574 
    575         request.attr_end(data);
    576         return WIFI_SUCCESS;
    577 
    578     }
    579 
    580     int start() {
    581         ALOGD("Sending mac address OUI");
    582         WifiRequest request(familyId(), ifaceId());
    583         int result = createRequest(request, WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, mOui);
    584         if (result != WIFI_SUCCESS) {
    585             ALOGE("failed to create request; result = %d", result);
    586             return result;
    587         }
    588 
    589         result = requestResponse(request);
    590         if (result != WIFI_SUCCESS) {
    591             ALOGE("failed to set scanning mac OUI; result = %d", result);
    592         }
    593 
    594         return result;
    595     }
    596 protected:
    597     virtual int handleResponse(WifiEvent& reply) {
    598          ALOGD("Request complete!");
    599         /* Nothing to do on response! */
    600         return NL_SKIP;
    601     }
    602 };
    603 
    604 class SetNodfsCommand : public WifiCommand {
    605 
    606 private:
    607     u32 mNoDfs;
    608 public:
    609     SetNodfsCommand(wifi_interface_handle handle, u32 nodfs)
    610         : WifiCommand("SetNodfsCommand", handle, 0) {
    611         mNoDfs = nodfs;
    612     }
    613     virtual int create() {
    614         int ret;
    615 
    616         ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_NODFS_SET);
    617         if (ret < 0) {
    618             ALOGE("Can't create message to send to driver - %d", ret);
    619             return ret;
    620         }
    621 
    622         nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
    623         ret = mMsg.put_u32(ATTR_NODFS_VALUE, mNoDfs);
    624         if (ret < 0) {
    625              return ret;
    626         }
    627 
    628         mMsg.attr_end(data);
    629         return WIFI_SUCCESS;
    630     }
    631 };
    632 
    633 class SetCountryCodeCommand : public WifiCommand {
    634 private:
    635     const char *mCountryCode;
    636 public:
    637     SetCountryCodeCommand(wifi_interface_handle handle, const char *country_code)
    638         : WifiCommand("SetCountryCodeCommand", handle, 0) {
    639         mCountryCode = country_code;
    640         }
    641     virtual int create() {
    642         int ret;
    643 
    644         ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_SET_COUNTRY_CODE);
    645         if (ret < 0) {
    646              ALOGE("Can't create message to send to driver - %d", ret);
    647              return ret;
    648         }
    649 
    650         nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
    651         ret = mMsg.put_string(ATTR_COUNTRY_CODE, mCountryCode);
    652         if (ret < 0) {
    653             return ret;
    654         }
    655 
    656         mMsg.attr_end(data);
    657         return WIFI_SUCCESS;
    658 
    659     }
    660 };
    661 
    662 class SetRSSIMonitorCommand : public WifiCommand {
    663 private:
    664     s8 mMax_rssi;
    665     s8 mMin_rssi;
    666     wifi_rssi_event_handler mHandler;
    667 public:
    668     SetRSSIMonitorCommand(wifi_request_id id, wifi_interface_handle handle,
    669                 s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
    670         : WifiCommand("SetRSSIMonitorCommand", handle, id), mMax_rssi(max_rssi), mMin_rssi
    671         (min_rssi), mHandler(eh)
    672         {
    673         }
    674    int createRequest(WifiRequest& request, int enable) {
    675         int result = request.create(GOOGLE_OUI, WIFI_SUBCMD_SET_RSSI_MONITOR);
    676         if (result < 0) {
    677             return result;
    678         }
    679 
    680         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
    681         result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MAX_RSSI, (enable ? mMax_rssi: 0));
    682         if (result < 0) {
    683             return result;
    684         }
    685         ALOGD("create request");
    686         result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_MIN_RSSI, (enable? mMin_rssi: 0));
    687         if (result < 0) {
    688             return result;
    689         }
    690         result = request.put_u32(RSSI_MONITOR_ATTRIBUTE_START, enable);
    691         if (result < 0) {
    692             return result;
    693         }
    694         request.attr_end(data);
    695         return result;
    696     }
    697 
    698     int start() {
    699         WifiRequest request(familyId(), ifaceId());
    700         int result = createRequest(request, 1);
    701         if (result < 0) {
    702             return result;
    703         }
    704         result = requestResponse(request);
    705         if (result < 0) {
    706             ALOGI("Failed to set RSSI Monitor, result = %d", result);
    707             return result;
    708         }
    709         ALOGI("Successfully set RSSI monitoring");
    710         registerVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
    711 
    712 
    713         if (result < 0) {
    714             unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
    715             return result;
    716         }
    717         ALOGI("Done!");
    718         return result;
    719     }
    720 
    721     virtual int cancel() {
    722 
    723         WifiRequest request(familyId(), ifaceId());
    724         int result = createRequest(request, 0);
    725         if (result != WIFI_SUCCESS) {
    726             ALOGE("failed to create request; result = %d", result);
    727         } else {
    728             result = requestResponse(request);
    729             if (result != WIFI_SUCCESS) {
    730                 ALOGE("failed to stop RSSI monitoring = %d", result);
    731             }
    732         }
    733         unregisterVendorHandler(GOOGLE_OUI, GOOGLE_RSSI_MONITOR_EVENT);
    734         return WIFI_SUCCESS;
    735     }
    736 
    737     virtual int handleResponse(WifiEvent& reply) {
    738         /* Nothing to do on response! */
    739         return NL_SKIP;
    740     }
    741 
    742    virtual int handleEvent(WifiEvent& event) {
    743         ALOGI("Got a RSSI monitor event");
    744 
    745         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
    746         int len = event.get_vendor_data_len();
    747 
    748         if (vendor_data == NULL || len == 0) {
    749             ALOGI("RSSI monitor: No data");
    750             return NL_SKIP;
    751         }
    752         /* driver<->HAL event structure */
    753         #define RSSI_MONITOR_EVT_VERSION   1
    754         typedef struct {
    755             u8 version;
    756             s8 cur_rssi;
    757             mac_addr BSSID;
    758         } rssi_monitor_evt;
    759 
    760         rssi_monitor_evt *data = (rssi_monitor_evt *)event.get_vendor_data();
    761 
    762         if (data->version != RSSI_MONITOR_EVT_VERSION) {
    763             ALOGI("Event version mismatch %d, expected %d", data->version, RSSI_MONITOR_EVT_VERSION);
    764             return NL_SKIP;
    765         }
    766 
    767         if (*mHandler.on_rssi_threshold_breached) {
    768             (*mHandler.on_rssi_threshold_breached)(id(), data->BSSID, data->cur_rssi);
    769         } else {
    770             ALOGW("No RSSI monitor handler registered");
    771         }
    772 
    773         return NL_SKIP;
    774     }
    775 
    776 };
    777 
    778 class GetFeatureSetCommand : public WifiCommand {
    779 
    780 private:
    781     int feature_type;
    782     feature_set *fset;
    783     feature_set *feature_matrix;
    784     int *fm_size;
    785     int set_size_max;
    786 public:
    787     GetFeatureSetCommand(wifi_interface_handle handle, int feature, feature_set *set,
    788          feature_set set_matrix[], int *size, int max_size)
    789         : WifiCommand("GetFeatureSetCommand", handle, 0)
    790     {
    791         feature_type = feature;
    792         fset = set;
    793         feature_matrix = set_matrix;
    794         fm_size = size;
    795         set_size_max = max_size;
    796     }
    797 
    798     virtual int create() {
    799         int ret;
    800 
    801         if(feature_type == FEATURE_SET) {
    802             ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET);
    803         } else if (feature_type == FEATURE_SET_MATRIX) {
    804             ret = mMsg.create(GOOGLE_OUI, WIFI_SUBCMD_GET_FEATURE_SET_MATRIX);
    805         } else {
    806             ALOGE("Unknown feature type %d", feature_type);
    807             return -1;
    808         }
    809 
    810         if (ret < 0) {
    811             ALOGE("Can't create message to send to driver - %d", ret);
    812         }
    813 
    814         return ret;
    815     }
    816 
    817 protected:
    818     virtual int handleResponse(WifiEvent& reply) {
    819 
    820         ALOGV("In GetFeatureSetCommand::handleResponse");
    821 
    822         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
    823             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
    824             return NL_SKIP;
    825         }
    826 
    827         int id = reply.get_vendor_id();
    828         int subcmd = reply.get_vendor_subcmd();
    829 
    830         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
    831         int len = reply.get_vendor_data_len();
    832 
    833         ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
    834         if (vendor_data == NULL || len == 0) {
    835             ALOGE("no vendor data in GetFeatureSetCommand response; ignoring it");
    836             return NL_SKIP;
    837         }
    838         if(feature_type == FEATURE_SET) {
    839             void *data = reply.get_vendor_data();
    840             if(!fset) {
    841                 ALOGE("Buffers pointers not set");
    842                 return NL_SKIP;
    843             }
    844             memcpy(fset, data, min(len, (int) sizeof(*fset)));
    845         } else {
    846             int num_features_set = 0;
    847             int i = 0;
    848 
    849             if(!feature_matrix || !fm_size) {
    850                 ALOGE("Buffers pointers not set");
    851                 return NL_SKIP;
    852             }
    853 
    854             for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
    855                 if (it.get_type() == ANDR_WIFI_ATTRIBUTE_NUM_FEATURE_SET) {
    856                     num_features_set = it.get_u32();
    857                     ALOGV("Got feature list with %d concurrent sets", num_features_set);
    858                     if(set_size_max && (num_features_set > set_size_max))
    859                         num_features_set = set_size_max;
    860                     *fm_size = num_features_set;
    861                 } else if ((it.get_type() == ANDR_WIFI_ATTRIBUTE_FEATURE_SET) &&
    862                              i < num_features_set) {
    863                     feature_matrix[i] = it.get_u32();
    864                     i++;
    865                 } else {
    866                     ALOGW("Ignoring invalid attribute type = %d, size = %d",
    867                             it.get_type(), it.get_len());
    868                 }
    869             }
    870 
    871         }
    872         return NL_OK;
    873     }
    874 
    875 };
    876 
    877 static int wifi_get_multicast_id(wifi_handle handle, const char *name, const char *group)
    878 {
    879     GetMulticastIdCommand cmd(handle, name, group);
    880     int res = cmd.requestResponse();
    881     if (res < 0)
    882         return res;
    883     else
    884         return cmd.getId();
    885 }
    886 
    887 /////////////////////////////////////////////////////////////////////////
    888 
    889 static bool is_wifi_interface(const char *name)
    890 {
    891     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
    892         /* not a wifi interface; ignore it */
    893         return false;
    894     } else {
    895         return true;
    896     }
    897 }
    898 
    899 static int get_interface(const char *name, interface_info *info)
    900 {
    901     strcpy(info->name, name);
    902     info->id = if_nametoindex(name);
    903     // ALOGI("found an interface : %s, id = %d", name, info->id);
    904     return WIFI_SUCCESS;
    905 }
    906 
    907 wifi_error wifi_init_interfaces(wifi_handle handle)
    908 {
    909     hal_info *info = (hal_info *)handle;
    910 
    911     struct dirent *de;
    912 
    913     DIR *d = opendir("/sys/class/net");
    914     if (d == 0)
    915         return WIFI_ERROR_UNKNOWN;
    916 
    917     int n = 0;
    918     while ((de = readdir(d))) {
    919         if (de->d_name[0] == '.')
    920             continue;
    921         if (is_wifi_interface(de->d_name) ) {
    922             n++;
    923         }
    924     }
    925 
    926     closedir(d);
    927 
    928     d = opendir("/sys/class/net");
    929     if (d == 0)
    930         return WIFI_ERROR_UNKNOWN;
    931 
    932     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
    933 
    934     int i = 0;
    935     while ((de = readdir(d))) {
    936         if (de->d_name[0] == '.')
    937             continue;
    938         if (is_wifi_interface(de->d_name)) {
    939             interface_info *ifinfo = (interface_info *)malloc(sizeof(interface_info));
    940             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
    941                 free(ifinfo);
    942                 continue;
    943             }
    944             ifinfo->handle = handle;
    945             info->interfaces[i] = ifinfo;
    946             i++;
    947         }
    948     }
    949 
    950     closedir(d);
    951 
    952     info->num_interfaces = n;
    953     return WIFI_SUCCESS;
    954 }
    955 
    956 wifi_error wifi_get_ifaces(wifi_handle handle, int *num, wifi_interface_handle **interfaces)
    957 {
    958     hal_info *info = (hal_info *)handle;
    959 
    960     *interfaces = (wifi_interface_handle *)info->interfaces;
    961     *num = info->num_interfaces;
    962 
    963     return WIFI_SUCCESS;
    964 }
    965 
    966 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name, size_t size)
    967 {
    968     interface_info *info = (interface_info *)handle;
    969     strcpy(name, info->name);
    970     return WIFI_SUCCESS;
    971 }
    972 
    973 wifi_error wifi_get_supported_feature_set(wifi_interface_handle handle, feature_set *set)
    974 {
    975     GetFeatureSetCommand command(handle, FEATURE_SET, set, NULL, NULL, 1);
    976     return (wifi_error) command.requestResponse();
    977 }
    978 
    979 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle, int set_size_max,
    980        feature_set set[], int *set_size)
    981 {
    982     GetFeatureSetCommand command(handle, FEATURE_SET_MATRIX, NULL, set, set_size, set_size_max);
    983     return (wifi_error) command.requestResponse();
    984 }
    985 
    986 wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui)
    987 {
    988     SetPnoMacAddrOuiCommand command(handle, scan_oui);
    989     return (wifi_error)command.start();
    990 
    991 }
    992 
    993 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
    994 {
    995     SetNodfsCommand command(handle, nodfs);
    996     return (wifi_error) command.requestResponse();
    997 }
    998 
    999 wifi_error wifi_set_country_code(wifi_interface_handle handle, const char *country_code)
   1000 {
   1001     SetCountryCodeCommand command(handle, country_code);
   1002     return (wifi_error) command.requestResponse();
   1003 }
   1004 
   1005 static wifi_error wifi_start_rssi_monitoring(wifi_request_id id, wifi_interface_handle
   1006                         iface, s8 max_rssi, s8 min_rssi, wifi_rssi_event_handler eh)
   1007 {
   1008     ALOGD("Start RSSI monitor %d", id);
   1009     wifi_handle handle = getWifiHandle(iface);
   1010     SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface, max_rssi, min_rssi, eh);
   1011     wifi_register_cmd(handle, id, cmd);
   1012     return (wifi_error)cmd->start();
   1013 }
   1014 
   1015 
   1016 static wifi_error wifi_stop_rssi_monitoring(wifi_request_id id, wifi_interface_handle iface)
   1017 {
   1018     ALOGD("Stopping RSSI monitor");
   1019 
   1020     if(id == -1) {
   1021         wifi_rssi_event_handler handler;
   1022         s8 max_rssi = 0, min_rssi = 0;
   1023         wifi_handle handle = getWifiHandle(iface);
   1024         memset(&handler, 0, sizeof(handler));
   1025         SetRSSIMonitorCommand *cmd = new SetRSSIMonitorCommand(id, iface,
   1026                                                     max_rssi, min_rssi, handler);
   1027         cmd->cancel();
   1028         cmd->releaseRef();
   1029         return WIFI_SUCCESS;
   1030     }
   1031     return wifi_cancel_cmd(id, iface);
   1032 }
   1033 
   1034 /////////////////////////////////////////////////////////////////////////////
   1035