Home | History | Annotate | Download | only in wifi_hal
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdint.h>
     18 #include <errno.h>
     19 #include <fcntl.h>
     20 #include <sys/socket.h>
     21 #include <netlink/genl/genl.h>
     22 #include <netlink/genl/family.h>
     23 #include <netlink/genl/ctrl.h>
     24 #include <linux/rtnetlink.h>
     25 #include <netpacket/packet.h>
     26 #include <linux/filter.h>
     27 #include <linux/errqueue.h>
     28 
     29 #include <linux/pkt_sched.h>
     30 #include <netlink/object-api.h>
     31 #include <netlink/netlink.h>
     32 #include <netlink/socket.h>
     33 #include <netlink-types.h>
     34 
     35 #include "nl80211_copy.h"
     36 
     37 #include <dirent.h>
     38 #include <net/if.h>
     39 #include <netinet/in.h>
     40 
     41 #include "sync.h"
     42 
     43 #define LOG_TAG  "WifiHAL"
     44 
     45 #include "hardware_legacy/wifi.h"
     46 
     47 #include "wifi_hal.h"
     48 #include "common.h"
     49 #include "cpp_bindings.h"
     50 #include "ifaceeventhandler.h"
     51 #include "wifiloggercmd.h"
     52 #include "vendor_definitions.h"
     53 
     54 /*
     55  BUGBUG: normally, libnl allocates ports for all connections it makes; but
     56  being a static library, it doesn't really know how many other netlink
     57  connections are made by the same process, if connections come from different
     58  shared libraries. These port assignments exist to solve that
     59  problem - temporarily. We need to fix libnl to try and allocate ports across
     60  the entire process.
     61  */
     62 
     63 #define WIFI_HAL_CMD_SOCK_PORT       644
     64 #define WIFI_HAL_EVENT_SOCK_PORT     645
     65 
     66 static void internal_event_handler(wifi_handle handle, int events,
     67                                    struct nl_sock *sock);
     68 static int internal_valid_message_handler(nl_msg *msg, void *arg);
     69 static int user_sock_message_handler(nl_msg *msg, void *arg);
     70 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
     71         const char *group);
     72 static int wifi_add_membership(wifi_handle handle, const char *group);
     73 static wifi_error wifi_init_interfaces(wifi_handle handle);
     74 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
     75                                          const u8 *program, u32 len);
     76 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
     77                                               u32 *version, u32 *max_len);
     78 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
     79                                             u8 enable);
     80 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
     81                              WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
     82 
     83 /* Initialize/Cleanup */
     84 
     85 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
     86 {
     87     hal_info *info = (hal_info *)handle;
     88     for (int i=0;i<info->num_interfaces;i++)
     89     {
     90         if (!strcmp(info->interfaces[i]->name, name))
     91         {
     92             return ((wifi_interface_handle )(info->interfaces)[i]);
     93         }
     94     }
     95     return NULL;
     96 }
     97 
     98 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
     99 {
    100     /* Release local port pool maintained by libnl and assign a own port
    101      * identifier to the socket.
    102      */
    103     nl_socket_set_local_port(sock, ((uint32_t)getpid() & 0x3FFFFFU) | (port << 22));
    104 }
    105 
    106 static nl_sock * wifi_create_nl_socket(int port, int protocol)
    107 {
    108     // ALOGI("Creating socket");
    109     struct nl_sock *sock = nl_socket_alloc();
    110     if (sock == NULL) {
    111         ALOGE("Failed to create NL socket");
    112         return NULL;
    113     }
    114 
    115     wifi_socket_set_local_port(sock, port);
    116 
    117     if (nl_connect(sock, protocol)) {
    118         ALOGE("Could not connect handle");
    119         nl_socket_free(sock);
    120         return NULL;
    121     }
    122 
    123     return sock;
    124 }
    125 
    126 int ack_handler(struct nl_msg *msg, void *arg)
    127 {
    128     int *err = (int *)arg;
    129     *err = 0;
    130     return NL_STOP;
    131 }
    132 
    133 int finish_handler(struct nl_msg *msg, void *arg)
    134 {
    135     int *ret = (int *)arg;
    136     *ret = 0;
    137     return NL_SKIP;
    138 }
    139 
    140 int error_handler(struct sockaddr_nl *nla,
    141                   struct nlmsgerr *err, void *arg)
    142 {
    143     int *ret = (int *)arg;
    144     *ret = err->error;
    145 
    146     ALOGV("%s invoked with error: %d", __func__, err->error);
    147     return NL_SKIP;
    148 }
    149 static int no_seq_check(struct nl_msg *msg, void *arg)
    150 {
    151     return NL_OK;
    152 }
    153 
    154 static wifi_error acquire_supported_features(wifi_interface_handle iface,
    155         feature_set *set)
    156 {
    157     int ret = 0;
    158     interface_info *iinfo = getIfaceInfo(iface);
    159     wifi_handle handle = getWifiHandle(iface);
    160     *set = 0;
    161 
    162     WifihalGeneric supportedFeatures(handle, 0,
    163             OUI_QCA,
    164             QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
    165 
    166     /* create the message */
    167     ret = supportedFeatures.create();
    168     if (ret < 0)
    169         goto cleanup;
    170 
    171     ret = supportedFeatures.set_iface_id(iinfo->name);
    172     if (ret < 0)
    173         goto cleanup;
    174 
    175     ret = supportedFeatures.requestResponse();
    176     if (ret != 0) {
    177         ALOGE("%s: requestResponse Error:%d",__func__, ret);
    178         goto cleanup;
    179     }
    180 
    181     supportedFeatures.getResponseparams(set);
    182 
    183 cleanup:
    184     return (wifi_error)ret;
    185 }
    186 
    187 static wifi_error get_firmware_bus_max_size_supported(
    188                                                 wifi_interface_handle iface)
    189 {
    190     int ret = 0;
    191     interface_info *iinfo = getIfaceInfo(iface);
    192     wifi_handle handle = getWifiHandle(iface);
    193     hal_info *info = (hal_info *)handle;
    194 
    195     WifihalGeneric busSizeSupported(handle, 0,
    196                                     OUI_QCA,
    197                                     QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
    198 
    199     /* create the message */
    200     ret = busSizeSupported.create();
    201     if (ret < 0)
    202         goto cleanup;
    203 
    204     ret = busSizeSupported.set_iface_id(iinfo->name);
    205     if (ret < 0)
    206         goto cleanup;
    207 
    208     ret = busSizeSupported.requestResponse();
    209     if (ret != 0) {
    210         ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
    211         goto cleanup;
    212     }
    213     info->firmware_bus_max_size = busSizeSupported.getBusSize();
    214 
    215 cleanup:
    216     return (wifi_error)ret;
    217 }
    218 
    219 static wifi_error wifi_init_user_sock(hal_info *info)
    220 {
    221     struct nl_sock *user_sock =
    222         wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
    223     if (user_sock == NULL) {
    224         ALOGE("Could not create diag sock");
    225         return WIFI_ERROR_UNKNOWN;
    226     }
    227 
    228     /* Set the socket buffer size */
    229     if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
    230         ALOGE("Could not set size for user_sock: %s",
    231                    strerror(errno));
    232         /* continue anyway with the default (smaller) buffer */
    233     }
    234     else {
    235         ALOGV("nl_socket_set_buffer_size successful for user_sock");
    236     }
    237 
    238     struct nl_cb *cb = nl_socket_get_cb(user_sock);
    239     if (cb == NULL) {
    240         ALOGE("Could not get cb");
    241         return WIFI_ERROR_UNKNOWN;
    242     }
    243 
    244     info->user_sock_arg = 1;
    245     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
    246     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
    247     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
    248     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
    249 
    250     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
    251     nl_cb_put(cb);
    252 
    253     int ret = nl_socket_add_membership(user_sock, 1);
    254     if (ret < 0) {
    255         ALOGE("Could not add membership");
    256         return WIFI_ERROR_UNKNOWN;
    257     }
    258 
    259     info->user_sock = user_sock;
    260     ALOGV("Initiialized diag sock successfully");
    261     return WIFI_SUCCESS;
    262 }
    263 
    264 /*initialize function pointer table with Qualcomm HAL API*/
    265 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
    266     if (fn == NULL) {
    267         return WIFI_ERROR_UNKNOWN;
    268     }
    269 
    270     fn->wifi_initialize = wifi_initialize;
    271     fn->wifi_cleanup = wifi_cleanup;
    272     fn->wifi_event_loop = wifi_event_loop;
    273     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
    274     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
    275     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
    276     fn->wifi_get_ifaces = wifi_get_ifaces;
    277     fn->wifi_get_iface_name = wifi_get_iface_name;
    278     fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
    279     fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
    280     fn->wifi_start_gscan = wifi_start_gscan;
    281     fn->wifi_stop_gscan = wifi_stop_gscan;
    282     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
    283     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
    284     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
    285     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
    286     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
    287     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
    288     fn->wifi_set_link_stats = wifi_set_link_stats;
    289     fn->wifi_get_link_stats = wifi_get_link_stats;
    290     fn->wifi_clear_link_stats = wifi_clear_link_stats;
    291     fn->wifi_get_valid_channels = wifi_get_valid_channels;
    292     fn->wifi_rtt_range_request = wifi_rtt_range_request;
    293     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
    294     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
    295     fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
    296     fn->wifi_enable_responder = wifi_enable_responder;
    297     fn->wifi_disable_responder = wifi_disable_responder;
    298     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
    299     fn->wifi_start_logging = wifi_start_logging;
    300     fn->wifi_set_epno_list = wifi_set_epno_list;
    301     fn->wifi_reset_epno_list = wifi_reset_epno_list;
    302     fn->wifi_set_country_code = wifi_set_country_code;
    303     fn->wifi_enable_tdls = wifi_enable_tdls;
    304     fn->wifi_disable_tdls = wifi_disable_tdls;
    305     fn->wifi_get_tdls_status = wifi_get_tdls_status;
    306     fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
    307     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
    308     fn->wifi_set_log_handler = wifi_set_log_handler;
    309     fn->wifi_reset_log_handler = wifi_reset_log_handler;
    310     fn->wifi_set_alert_handler = wifi_set_alert_handler;
    311     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
    312     fn->wifi_get_firmware_version = wifi_get_firmware_version;
    313     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
    314     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
    315     fn->wifi_get_ring_data = wifi_get_ring_data;
    316     fn->wifi_get_driver_version = wifi_get_driver_version;
    317     fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
    318     fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
    319     fn->wifi_set_bssid_blacklist = wifi_set_bssid_blacklist;
    320     fn->wifi_set_lci = wifi_set_lci;
    321     fn->wifi_set_lcr = wifi_set_lcr;
    322     fn->wifi_start_sending_offloaded_packet =
    323             wifi_start_sending_offloaded_packet;
    324     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
    325     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
    326     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
    327     fn->wifi_nan_enable_request = nan_enable_request;
    328     fn->wifi_nan_disable_request = nan_disable_request;
    329     fn->wifi_nan_publish_request = nan_publish_request;
    330     fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
    331     fn->wifi_nan_subscribe_request = nan_subscribe_request;
    332     fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
    333     fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
    334     fn->wifi_nan_stats_request = nan_stats_request;
    335     fn->wifi_nan_config_request = nan_config_request;
    336     fn->wifi_nan_tca_request = nan_tca_request;
    337     fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
    338     fn->wifi_nan_register_handler = nan_register_handler;
    339     fn->wifi_nan_get_version = nan_get_version;
    340     fn->wifi_set_packet_filter = wifi_set_packet_filter;
    341     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
    342     fn->wifi_nan_get_capabilities = nan_get_capabilities;
    343     fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
    344     fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
    345     fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
    346     fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
    347     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
    348     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
    349 
    350     return WIFI_SUCCESS;
    351 }
    352 
    353 wifi_error wifi_initialize(wifi_handle *handle)
    354 {
    355     int err = 0;
    356     bool driver_loaded = false;
    357     wifi_error ret = WIFI_SUCCESS;
    358     wifi_interface_handle iface_handle;
    359     struct nl_sock *cmd_sock = NULL;
    360     struct nl_sock *event_sock = NULL;
    361     struct nl_cb *cb = NULL;
    362 
    363     ALOGI("Initializing wifi");
    364     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
    365     if (info == NULL) {
    366         ALOGE("Could not allocate hal_info");
    367         return WIFI_ERROR_OUT_OF_MEMORY;
    368     }
    369 
    370     memset(info, 0, sizeof(*info));
    371 
    372     cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
    373                                                      NETLINK_GENERIC);
    374     if (cmd_sock == NULL) {
    375         ALOGE("Failed to create command socket port");
    376         ret = WIFI_ERROR_UNKNOWN;
    377         goto unload;
    378     }
    379 
    380     /* Set the socket buffer size */
    381     if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
    382         ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
    383                    strerror(errno));
    384         /* continue anyway with the default (smaller) buffer */
    385     }
    386 
    387     event_sock =
    388         wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
    389     if (event_sock == NULL) {
    390         ALOGE("Failed to create event socket port");
    391         ret = WIFI_ERROR_UNKNOWN;
    392         goto unload;
    393     }
    394 
    395     /* Set the socket buffer size */
    396     if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
    397         ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
    398                    strerror(errno));
    399         /* continue anyway with the default (smaller) buffer */
    400     }
    401 
    402     cb = nl_socket_get_cb(event_sock);
    403     if (cb == NULL) {
    404         ALOGE("Failed to get NL control block for event socket port");
    405         ret = WIFI_ERROR_UNKNOWN;
    406         goto unload;
    407     }
    408 
    409     err = 1;
    410     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
    411     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
    412     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
    413     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
    414 
    415     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
    416             info);
    417     nl_cb_put(cb);
    418 
    419     info->cmd_sock = cmd_sock;
    420     info->event_sock = event_sock;
    421     info->clean_up = false;
    422     info->in_event_loop = false;
    423 
    424     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
    425     if (info->event_cb == NULL) {
    426         ALOGE("Could not allocate event_cb");
    427         ret = WIFI_ERROR_OUT_OF_MEMORY;
    428         goto unload;
    429     }
    430     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
    431     info->num_event_cb = 0;
    432 
    433     info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
    434     if (info->cmd == NULL) {
    435         ALOGE("Could not allocate cmd info");
    436         ret = WIFI_ERROR_OUT_OF_MEMORY;
    437         goto unload;
    438     }
    439     info->alloc_cmd = DEFAULT_CMD_SIZE;
    440     info->num_cmd = 0;
    441 
    442     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
    443     if (info->nl80211_family_id < 0) {
    444         ALOGE("Could not resolve nl80211 familty id");
    445         ret = WIFI_ERROR_UNKNOWN;
    446         goto unload;
    447     }
    448 
    449     pthread_mutex_init(&info->cb_lock, NULL);
    450     pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
    451 
    452     *handle = (wifi_handle) info;
    453 
    454     wifi_add_membership(*handle, "scan");
    455     wifi_add_membership(*handle, "mlme");
    456     wifi_add_membership(*handle, "regulatory");
    457     wifi_add_membership(*handle, "vendor");
    458 
    459     ret = wifi_init_user_sock(info);
    460     if (ret != WIFI_SUCCESS) {
    461         ALOGE("Failed to alloc user socket");
    462         goto unload;
    463     }
    464 
    465     if (!is_wifi_driver_loaded()) {
    466         ret = (wifi_error)wifi_load_driver();
    467         if(ret != WIFI_SUCCESS) {
    468             ALOGE("%s Failed to load wifi driver : %d\n", __func__, ret);
    469             goto unload;
    470         }
    471         driver_loaded = true;
    472     }
    473 
    474     ret = wifi_init_interfaces(*handle);
    475     if (ret != WIFI_SUCCESS) {
    476         ALOGE("Failed to init interfaces");
    477         goto unload;
    478     }
    479 
    480     if (info->num_interfaces == 0) {
    481         ALOGE("No interfaces found");
    482         ret = WIFI_ERROR_UNINITIALIZED;
    483         goto unload;
    484     }
    485 
    486     iface_handle = wifi_get_iface_handle((info->interfaces[0])->handle,
    487             (info->interfaces[0])->name);
    488     if (iface_handle == NULL) {
    489         int i;
    490         for (i = 0; i < info->num_interfaces; i++)
    491         {
    492             free(info->interfaces[i]);
    493         }
    494         ALOGE("%s no iface with %s\n", __func__, info->interfaces[0]->name);
    495         goto unload;
    496     }
    497 
    498     ret = acquire_supported_features(iface_handle,
    499             &info->supported_feature_set);
    500     if (ret != WIFI_SUCCESS) {
    501         ALOGI("Failed to get supported feature set : %d", ret);
    502         //acquire_supported_features failure is acceptable condition as legacy
    503         //drivers might not support the required vendor command. So, do not
    504         //consider it as failure of wifi_initialize
    505         ret = WIFI_SUCCESS;
    506     }
    507 
    508     ret = get_firmware_bus_max_size_supported(iface_handle);
    509     if (ret != WIFI_SUCCESS) {
    510         ALOGE("Failed to get supported bus size, error : %d", ret);
    511         info->firmware_bus_max_size = 1520;
    512     }
    513 
    514     ret = wifi_logger_ring_buffers_init(info);
    515     if (ret != WIFI_SUCCESS) {
    516         ALOGE("Wifi Logger Ring Initialization Failed");
    517         goto unload;
    518     }
    519 
    520     info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
    521     if (!info->pkt_stats) {
    522         ALOGE("%s: malloc Failed for size: %zu",
    523                 __FUNCTION__, sizeof(struct pkt_stats_s));
    524         ret = WIFI_ERROR_OUT_OF_MEMORY;
    525         goto unload;
    526     }
    527 
    528     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
    529                                   * PKT_STATS_BUF_SIZE;
    530 
    531     info->rx_aggr_pkts =
    532         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
    533     if (!info->rx_aggr_pkts) {
    534         ALOGE("%s: malloc Failed for size: %d",
    535                 __FUNCTION__, info->rx_buf_size_allocated);
    536         ret = WIFI_ERROR_OUT_OF_MEMORY;
    537         info->rx_buf_size_allocated = 0;
    538         goto unload;
    539     }
    540     memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
    541 
    542     info->exit_sockets[0] = -1;
    543     info->exit_sockets[1] = -1;
    544 
    545     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
    546         ALOGE("Failed to create exit socket pair");
    547         ret = WIFI_ERROR_UNKNOWN;
    548         goto unload;
    549     }
    550 
    551     ALOGV("Initializing Gscan Event Handlers");
    552     ret = initializeGscanHandlers(info);
    553     if (ret != WIFI_SUCCESS) {
    554         ALOGE("Initializing Gscan Event Handlers Failed");
    555         goto unload;
    556     }
    557 
    558     ret = initializeRSSIMonitorHandler(info);
    559     if (ret != WIFI_SUCCESS) {
    560         ALOGE("Initializing RSSI Event Handler Failed");
    561         goto unload;
    562     }
    563 
    564     ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
    565             " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
    566 
    567 unload:
    568     if (ret != WIFI_SUCCESS) {
    569         if (cmd_sock)
    570             nl_socket_free(cmd_sock);
    571         if (event_sock)
    572             nl_socket_free(event_sock);
    573         if (info) {
    574             if (info->cmd) free(info->cmd);
    575             if (info->event_cb) free(info->event_cb);
    576             if (info->user_sock) nl_socket_free(info->user_sock);
    577             if (info->pkt_stats) free(info->pkt_stats);
    578             if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
    579             cleanupGscanHandlers(info);
    580             cleanupRSSIMonitorHandler(info);
    581             free(info);
    582         }
    583     }
    584 
    585     if (driver_loaded)
    586         wifi_unload_driver();
    587     return ret;
    588 }
    589 
    590 static int wifi_add_membership(wifi_handle handle, const char *group)
    591 {
    592     hal_info *info = getHalInfo(handle);
    593 
    594     int id = wifi_get_multicast_id(handle, "nl80211", group);
    595     if (id < 0) {
    596         ALOGE("Could not find group %s", group);
    597         return id;
    598     }
    599 
    600     int ret = nl_socket_add_membership(info->event_sock, id);
    601     if (ret < 0) {
    602         ALOGE("Could not add membership to group %s", group);
    603     }
    604 
    605     return ret;
    606 }
    607 
    608 static void internal_cleaned_up_handler(wifi_handle handle)
    609 {
    610     hal_info *info = getHalInfo(handle);
    611     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
    612 
    613     if (info->cmd_sock != 0) {
    614         nl_socket_free(info->cmd_sock);
    615         nl_socket_free(info->event_sock);
    616         info->cmd_sock = NULL;
    617         info->event_sock = NULL;
    618     }
    619 
    620     if (info->user_sock != 0) {
    621         nl_socket_free(info->user_sock);
    622         info->user_sock = NULL;
    623     }
    624 
    625     if (info->pkt_stats)
    626         free(info->pkt_stats);
    627     if (info->rx_aggr_pkts)
    628         free(info->rx_aggr_pkts);
    629     wifi_logger_ring_buffers_deinit(info);
    630     cleanupGscanHandlers(info);
    631     cleanupRSSIMonitorHandler(info);
    632 
    633     if (info->exit_sockets[0] >= 0) {
    634         close(info->exit_sockets[0]);
    635         info->exit_sockets[0] = -1;
    636     }
    637 
    638     if (info->exit_sockets[1] >= 0) {
    639         close(info->exit_sockets[1]);
    640         info->exit_sockets[1] = -1;
    641     }
    642 
    643     if (info->pkt_fate_stats) {
    644         free(info->pkt_fate_stats);
    645         info->pkt_fate_stats = NULL;
    646     }
    647 
    648     (*cleaned_up_handler)(handle);
    649     pthread_mutex_destroy(&info->cb_lock);
    650     pthread_mutex_destroy(&info->pkt_fate_stats_lock);
    651     free(info);
    652 }
    653 
    654 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
    655 {
    656     if (!handle) {
    657         ALOGE("Handle is null");
    658         return;
    659     }
    660 
    661     hal_info *info = getHalInfo(handle);
    662     info->cleaned_up_handler = handler;
    663     info->clean_up = true;
    664 
    665     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
    666     ALOGI("Sent msg on exit sock to unblock poll()");
    667 }
    668 
    669 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
    670 {
    671     struct nl_cb *cb = nl_socket_get_cb(sock);
    672 
    673     int res = nl_recvmsgs(sock, cb);
    674     if(res)
    675         ALOGE("Error :%d while reading nl msg", res);
    676     nl_cb_put(cb);
    677     return res;
    678 }
    679 
    680 static void internal_event_handler(wifi_handle handle, int events,
    681                                    struct nl_sock *sock)
    682 {
    683     if (events & POLLERR) {
    684         ALOGE("Error reading from socket");
    685         internal_pollin_handler(handle, sock);
    686     } else if (events & POLLHUP) {
    687         ALOGE("Remote side hung up");
    688     } else if (events & POLLIN) {
    689         //ALOGI("Found some events!!!");
    690         internal_pollin_handler(handle, sock);
    691     } else {
    692         ALOGE("Unknown event - %0x", events);
    693     }
    694 }
    695 
    696 /* Run event handler */
    697 void wifi_event_loop(wifi_handle handle)
    698 {
    699     hal_info *info = getHalInfo(handle);
    700     if (info->in_event_loop) {
    701         return;
    702     } else {
    703         info->in_event_loop = true;
    704     }
    705 
    706     pollfd pfd[3];
    707     memset(&pfd, 0, 3*sizeof(pfd[0]));
    708 
    709     pfd[0].fd = nl_socket_get_fd(info->event_sock);
    710     pfd[0].events = POLLIN;
    711 
    712     pfd[1].fd = nl_socket_get_fd(info->user_sock);
    713     pfd[1].events = POLLIN;
    714 
    715     pfd[2].fd = info->exit_sockets[1];
    716     pfd[2].events = POLLIN;
    717 
    718     /* TODO: Add support for timeouts */
    719 
    720     do {
    721         pfd[0].revents = 0;
    722         pfd[1].revents = 0;
    723         pfd[2].revents = 0;
    724         //ALOGI("Polling sockets");
    725         int result = poll(pfd, 3, -1);
    726         if (result < 0) {
    727             ALOGE("Error polling socket");
    728         } else {
    729             if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
    730                 internal_event_handler(handle, pfd[0].revents, info->event_sock);
    731             }
    732             if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
    733                 internal_event_handler(handle, pfd[1].revents, info->user_sock);
    734             }
    735         }
    736         rb_timerhandler(info);
    737     } while (!info->clean_up);
    738     internal_cleaned_up_handler(handle);
    739 }
    740 
    741 static int user_sock_message_handler(nl_msg *msg, void *arg)
    742 {
    743     wifi_handle handle = (wifi_handle)arg;
    744     hal_info *info = getHalInfo(handle);
    745 
    746     diag_message_handler(info, msg);
    747 
    748     return NL_OK;
    749 }
    750 
    751 static int internal_valid_message_handler(nl_msg *msg, void *arg)
    752 {
    753     wifi_handle handle = (wifi_handle)arg;
    754     hal_info *info = getHalInfo(handle);
    755 
    756     WifiEvent event(msg);
    757     int res = event.parse();
    758     if (res < 0) {
    759         ALOGE("Failed to parse event: %d", res);
    760         return NL_SKIP;
    761     }
    762 
    763     int cmd = event.get_cmd();
    764     uint32_t vendor_id = 0;
    765     int subcmd = 0;
    766 
    767     if (cmd == NL80211_CMD_VENDOR) {
    768         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
    769         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
    770         /* Restrict printing GSCAN_FULL_RESULT which is causing lot
    771            of logs in bug report */
    772         if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
    773             ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
    774                   event.get_cmdString(), vendor_id, subcmd);
    775         }
    776     } else {
    777         ALOGV("event received %s", event.get_cmdString());
    778     }
    779 
    780     // event.log();
    781 
    782     bool dispatched = false;
    783 
    784     pthread_mutex_lock(&info->cb_lock);
    785 
    786     for (int i = 0; i < info->num_event_cb; i++) {
    787         if (cmd == info->event_cb[i].nl_cmd) {
    788             if (cmd == NL80211_CMD_VENDOR
    789                 && ((vendor_id != info->event_cb[i].vendor_id)
    790                 || (subcmd != info->event_cb[i].vendor_subcmd)))
    791             {
    792                 /* event for a different vendor, ignore it */
    793                 continue;
    794             }
    795 
    796             cb_info *cbi = &(info->event_cb[i]);
    797             pthread_mutex_unlock(&info->cb_lock);
    798             if (cbi->cb_func) {
    799                 (*(cbi->cb_func))(msg, cbi->cb_arg);
    800                 dispatched = true;
    801             }
    802             return NL_OK;
    803         }
    804     }
    805 
    806 #ifdef QC_HAL_DEBUG
    807     if (!dispatched) {
    808         ALOGI("event ignored!!");
    809     }
    810 #endif
    811 
    812     pthread_mutex_unlock(&info->cb_lock);
    813     return NL_OK;
    814 }
    815 
    816 ////////////////////////////////////////////////////////////////////////////////
    817 
    818 class GetMulticastIdCommand : public WifiCommand
    819 {
    820 private:
    821     const char *mName;
    822     const char *mGroup;
    823     int   mId;
    824 public:
    825     GetMulticastIdCommand(wifi_handle handle, const char *name,
    826             const char *group) : WifiCommand(handle, 0)
    827     {
    828         mName = name;
    829         mGroup = group;
    830         mId = -1;
    831     }
    832 
    833     int getId() {
    834         return mId;
    835     }
    836 
    837     virtual int create() {
    838         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
    839         // ALOGI("ctrl family = %d", nlctrlFamily);
    840         int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
    841         if (ret < 0) {
    842             return ret;
    843         }
    844         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
    845         return ret;
    846     }
    847 
    848     virtual int handleResponse(WifiEvent& reply) {
    849 
    850         // ALOGI("handling reponse in %s", __func__);
    851 
    852         struct nlattr **tb = reply.attributes();
    853         struct nlattr *mcgrp = NULL;
    854         int i;
    855 
    856         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
    857             ALOGI("No multicast groups found");
    858             return NL_SKIP;
    859         } else {
    860             // ALOGI("Multicast groups attr size = %d",
    861             // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
    862         }
    863 
    864         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
    865 
    866             // ALOGI("Processing group");
    867             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
    868             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
    869                 nla_len(mcgrp), NULL);
    870             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
    871             {
    872                 continue;
    873             }
    874 
    875             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
    876             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
    877 
    878             // ALOGI("Found group name %s", grpName);
    879 
    880             if (strncmp(grpName, mGroup, grpNameLen) != 0)
    881                 continue;
    882 
    883             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
    884             break;
    885         }
    886 
    887         return NL_SKIP;
    888     }
    889 
    890 };
    891 
    892 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
    893         const char *group)
    894 {
    895     GetMulticastIdCommand cmd(handle, name, group);
    896     int res = cmd.requestResponse();
    897     if (res < 0)
    898         return res;
    899     else
    900         return cmd.getId();
    901 }
    902 
    903 /////////////////////////////////////////////////////////////////////////
    904 
    905 static bool is_wifi_interface(const char *name)
    906 {
    907     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
    908         /* not a wifi interface; ignore it */
    909         return false;
    910     } else {
    911         return true;
    912     }
    913 }
    914 
    915 static int get_interface(const char *name, interface_info *info)
    916 {
    917     strlcpy(info->name, name, (IFNAMSIZ + 1));
    918     info->id = if_nametoindex(name);
    919     // ALOGI("found an interface : %s, id = %d", name, info->id);
    920     return WIFI_SUCCESS;
    921 }
    922 
    923 wifi_error wifi_init_interfaces(wifi_handle handle)
    924 {
    925     hal_info *info = (hal_info *)handle;
    926 
    927     struct dirent *de;
    928 
    929     DIR *d = opendir("/sys/class/net");
    930     if (d == 0)
    931         return WIFI_ERROR_UNKNOWN;
    932 
    933     int n = 0;
    934     while ((de = readdir(d))) {
    935         if (de->d_name[0] == '.')
    936             continue;
    937         if (is_wifi_interface(de->d_name) ) {
    938             n++;
    939         }
    940     }
    941 
    942     closedir(d);
    943 
    944     d = opendir("/sys/class/net");
    945     if (d == 0)
    946         return WIFI_ERROR_UNKNOWN;
    947 
    948     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
    949     if (info->interfaces == NULL) {
    950         ALOGE("%s: Error info->interfaces NULL", __func__);
    951         return WIFI_ERROR_OUT_OF_MEMORY;
    952     }
    953 
    954     int i = 0;
    955     while ((de = readdir(d))) {
    956         if (de->d_name[0] == '.')
    957             continue;
    958         if (is_wifi_interface(de->d_name)) {
    959             interface_info *ifinfo
    960                 = (interface_info *)malloc(sizeof(interface_info));
    961             if (ifinfo == NULL) {
    962                 ALOGE("%s: Error ifinfo NULL", __func__);
    963                 while (i > 0) {
    964                     free(info->interfaces[i-1]);
    965                     i--;
    966                 }
    967                 free(info->interfaces);
    968                 return WIFI_ERROR_OUT_OF_MEMORY;
    969             }
    970             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
    971                 free(ifinfo);
    972                 continue;
    973             }
    974             ifinfo->handle = handle;
    975             info->interfaces[i] = ifinfo;
    976             i++;
    977         }
    978     }
    979 
    980     closedir(d);
    981 
    982     info->num_interfaces = n;
    983 
    984     return WIFI_SUCCESS;
    985 }
    986 
    987 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
    988         wifi_interface_handle **interfaces)
    989 {
    990     hal_info *info = (hal_info *)handle;
    991 
    992     *interfaces = (wifi_interface_handle *)info->interfaces;
    993     *num = info->num_interfaces;
    994 
    995     return WIFI_SUCCESS;
    996 }
    997 
    998 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
    999         size_t size)
   1000 {
   1001     interface_info *info = (interface_info *)handle;
   1002     strlcpy(name, info->name, size);
   1003     return WIFI_SUCCESS;
   1004 }
   1005 
   1006 /* Get the supported Feature set */
   1007 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
   1008         feature_set *set)
   1009 {
   1010     int ret = 0;
   1011     wifi_handle handle = getWifiHandle(iface);
   1012     *set = 0;
   1013     hal_info *info = getHalInfo(handle);
   1014 
   1015     ret = acquire_supported_features(iface, set);
   1016     if (ret != WIFI_SUCCESS) {
   1017         *set = info->supported_feature_set;
   1018         ALOGV("Supported feature set acquired at initialization : %x", *set);
   1019     } else {
   1020         info->supported_feature_set = *set;
   1021         ALOGV("Supported feature set acquired : %x", *set);
   1022     }
   1023     return WIFI_SUCCESS;
   1024 }
   1025 
   1026 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
   1027                                        int set_size_max,
   1028                                        feature_set set[], int *set_size)
   1029 {
   1030     int ret = 0;
   1031     struct nlattr *nlData;
   1032     WifihalGeneric *vCommand = NULL;
   1033     interface_info *ifaceInfo = getIfaceInfo(handle);
   1034     wifi_handle wifiHandle = getWifiHandle(handle);
   1035 
   1036     if (set == NULL) {
   1037         ALOGE("%s: NULL set pointer provided. Exit.",
   1038             __func__);
   1039         return WIFI_ERROR_INVALID_ARGS;
   1040     }
   1041 
   1042     vCommand = new WifihalGeneric(wifiHandle, 0,
   1043             OUI_QCA,
   1044             QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
   1045     if (vCommand == NULL) {
   1046         ALOGE("%s: Error vCommand NULL", __func__);
   1047         return WIFI_ERROR_OUT_OF_MEMORY;
   1048     }
   1049 
   1050     /* Create the message */
   1051     ret = vCommand->create();
   1052     if (ret < 0)
   1053         goto cleanup;
   1054 
   1055     ret = vCommand->set_iface_id(ifaceInfo->name);
   1056     if (ret < 0)
   1057         goto cleanup;
   1058 
   1059     /* Add the vendor specific attributes for the NL command. */
   1060     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1061     if (!nlData)
   1062         goto cleanup;
   1063 
   1064     if (vCommand->put_u32(
   1065         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
   1066         set_size_max))
   1067     {
   1068         goto cleanup;
   1069     }
   1070     vCommand->attr_end(nlData);
   1071 
   1072     /* Populate the input received from caller/framework. */
   1073     vCommand->setMaxSetSize(set_size_max);
   1074     vCommand->setSizePtr(set_size);
   1075     vCommand->setConcurrencySet(set);
   1076 
   1077     ret = vCommand->requestResponse();
   1078     if (ret) {
   1079         ALOGE("%s: requestResponse() error: %d", __func__, ret);
   1080     }
   1081 
   1082 cleanup:
   1083     delete vCommand;
   1084     if (ret) {
   1085         *set_size = 0;
   1086     }
   1087     return (wifi_error)ret;
   1088 }
   1089 
   1090 
   1091 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
   1092 {
   1093     int ret = 0;
   1094     struct nlattr *nlData;
   1095     WifiVendorCommand *vCommand = NULL;
   1096     interface_info *ifaceInfo = getIfaceInfo(handle);
   1097     wifi_handle wifiHandle = getWifiHandle(handle);
   1098 
   1099     vCommand = new WifiVendorCommand(wifiHandle, 0,
   1100             OUI_QCA,
   1101             QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
   1102     if (vCommand == NULL) {
   1103         ALOGE("%s: Error vCommand NULL", __func__);
   1104         return WIFI_ERROR_OUT_OF_MEMORY;
   1105     }
   1106 
   1107     /* Create the message */
   1108     ret = vCommand->create();
   1109     if (ret < 0)
   1110         goto cleanup;
   1111 
   1112     ret = vCommand->set_iface_id(ifaceInfo->name);
   1113     if (ret < 0)
   1114         goto cleanup;
   1115 
   1116     /* Add the vendor specific attributes for the NL command. */
   1117     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1118     if (!nlData)
   1119         goto cleanup;
   1120 
   1121     /* Add the fixed part of the mac_oui to the nl command */
   1122     if (vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs)) {
   1123         goto cleanup;
   1124     }
   1125 
   1126     vCommand->attr_end(nlData);
   1127 
   1128     ret = vCommand->requestResponse();
   1129     /* Don't check response since we aren't expecting one */
   1130 
   1131 cleanup:
   1132     delete vCommand;
   1133     return (wifi_error)ret;
   1134 }
   1135 
   1136 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
   1137                                                wifi_interface_handle iface,
   1138                                                u8 *ip_packet,
   1139                                                u16 ip_packet_len,
   1140                                                u8 *src_mac_addr,
   1141                                                u8 *dst_mac_addr,
   1142                                                u32 period_msec)
   1143 {
   1144     int ret = WIFI_SUCCESS;
   1145     struct nlattr *nlData;
   1146     WifiVendorCommand *vCommand = NULL;
   1147 
   1148     ret = initialize_vendor_cmd(iface, id,
   1149                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
   1150                                 &vCommand);
   1151     if (ret != WIFI_SUCCESS) {
   1152         ALOGE("%s: Initialization failed", __func__);
   1153         return (wifi_error)ret;
   1154     }
   1155 
   1156     ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
   1157     hexdump(ip_packet, ip_packet_len);
   1158     ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
   1159           "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
   1160           MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
   1161 
   1162     /* Add the vendor specific attributes for the NL command. */
   1163     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1164     if (!nlData)
   1165         goto cleanup;
   1166 
   1167     if (vCommand->put_u32(
   1168             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
   1169             QCA_WLAN_OFFLOADED_PACKETS_SENDING_START) ||
   1170         vCommand->put_u32(
   1171             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
   1172             id) ||
   1173         vCommand->put_bytes(
   1174             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET,
   1175             (const char *)ip_packet, ip_packet_len) ||
   1176         vCommand->put_addr(
   1177             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
   1178             src_mac_addr) ||
   1179         vCommand->put_addr(
   1180             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
   1181             dst_mac_addr) ||
   1182         vCommand->put_u32(
   1183             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
   1184             period_msec))
   1185     {
   1186         goto cleanup;
   1187     }
   1188 
   1189     vCommand->attr_end(nlData);
   1190 
   1191     ret = vCommand->requestResponse();
   1192     if (ret < 0)
   1193         goto cleanup;
   1194 
   1195 cleanup:
   1196     delete vCommand;
   1197     return (wifi_error)ret;
   1198 }
   1199 
   1200 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
   1201                                               wifi_interface_handle iface)
   1202 {
   1203     int ret = WIFI_SUCCESS;
   1204     struct nlattr *nlData;
   1205     WifiVendorCommand *vCommand = NULL;
   1206 
   1207     ret = initialize_vendor_cmd(iface, id,
   1208                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
   1209                                 &vCommand);
   1210     if (ret != WIFI_SUCCESS) {
   1211         ALOGE("%s: Initialization failed", __func__);
   1212         return (wifi_error)ret;
   1213     }
   1214 
   1215     /* Add the vendor specific attributes for the NL command. */
   1216     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1217     if (!nlData)
   1218         goto cleanup;
   1219 
   1220     if (vCommand->put_u32(
   1221             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
   1222             QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP) ||
   1223         vCommand->put_u32(
   1224             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
   1225             id))
   1226     {
   1227         goto cleanup;
   1228     }
   1229 
   1230 
   1231     vCommand->attr_end(nlData);
   1232 
   1233     ret = vCommand->requestResponse();
   1234     if (ret < 0)
   1235         goto cleanup;
   1236 
   1237 cleanup:
   1238     delete vCommand;
   1239     return (wifi_error)ret;
   1240 }
   1241 
   1242 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
   1243                                          const u8 *program, u32 len)
   1244 {
   1245     int ret = WIFI_SUCCESS;
   1246     struct nlattr *nlData;
   1247     WifiVendorCommand *vCommand = NULL;
   1248     u32 current_offset = 0;
   1249     wifi_handle wifiHandle = getWifiHandle(iface);
   1250     hal_info *info = getHalInfo(wifiHandle);
   1251 
   1252     /* len=0 clears the filters in driver/firmware */
   1253     if (len != 0 && program == NULL) {
   1254         ALOGE("%s: No valid program provided. Exit.",
   1255             __func__);
   1256         return WIFI_ERROR_INVALID_ARGS;
   1257     }
   1258 
   1259     do {
   1260         ret = initialize_vendor_cmd(iface, get_requestid(),
   1261                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
   1262                                     &vCommand);
   1263         if (ret != WIFI_SUCCESS) {
   1264             ALOGE("%s: Initialization failed", __FUNCTION__);
   1265             return (wifi_error)ret;
   1266         }
   1267 
   1268         /* Add the vendor specific attributes for the NL command. */
   1269         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1270         if (!nlData)
   1271             goto cleanup;
   1272 
   1273         if (vCommand->put_u32(
   1274                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
   1275                 QCA_WLAN_SET_PACKET_FILTER) ||
   1276             vCommand->put_u32(
   1277                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
   1278                 PACKET_FILTER_ID) ||
   1279             vCommand->put_u32(
   1280                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
   1281                 len) ||
   1282             vCommand->put_u32(
   1283                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
   1284                 current_offset)) {
   1285             ALOGE("%s: failed to put subcmd/program", __FUNCTION__);
   1286             goto cleanup;
   1287         }
   1288 
   1289         if (len) {
   1290             if(vCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
   1291                                    (char *)&program[current_offset],
   1292                                    min(info->firmware_bus_max_size,
   1293                                    len-current_offset))) {
   1294                 ALOGE("%s: failed to put subcmd", __FUNCTION__);
   1295                 goto cleanup;
   1296             }
   1297         }
   1298 
   1299         vCommand->attr_end(nlData);
   1300 
   1301         ret = vCommand->requestResponse();
   1302         if (ret < 0) {
   1303             ALOGE("%s: requestResponse Error:%d",__func__, ret);
   1304             goto cleanup;
   1305         }
   1306 
   1307         /* destroy the object after sending each fragment to driver */
   1308         delete vCommand;
   1309         vCommand = NULL;
   1310 
   1311         current_offset += min(info->firmware_bus_max_size, len);
   1312     } while (current_offset < len);
   1313 
   1314 cleanup:
   1315     if (vCommand)
   1316         delete vCommand;
   1317     return (wifi_error)ret;
   1318 }
   1319 
   1320 static wifi_error wifi_get_packet_filter_capabilities(
   1321                 wifi_interface_handle handle, u32 *version, u32 *max_len)
   1322 {
   1323     int ret = 0;
   1324     struct nlattr *nlData;
   1325     WifihalGeneric *vCommand = NULL;
   1326     interface_info *ifaceInfo = getIfaceInfo(handle);
   1327     wifi_handle wifiHandle = getWifiHandle(handle);
   1328 
   1329     if (version == NULL || max_len == NULL) {
   1330         ALOGE("%s: NULL version/max_len pointer provided. Exit.",
   1331             __FUNCTION__);
   1332         return WIFI_ERROR_INVALID_ARGS;
   1333     }
   1334 
   1335     vCommand = new WifihalGeneric(wifiHandle, 0,
   1336             OUI_QCA,
   1337             QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
   1338     if (vCommand == NULL) {
   1339         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
   1340         return WIFI_ERROR_OUT_OF_MEMORY;
   1341     }
   1342 
   1343     /* Create the message */
   1344     ret = vCommand->create();
   1345     if (ret < 0)
   1346         goto cleanup;
   1347 
   1348     ret = vCommand->set_iface_id(ifaceInfo->name);
   1349     if (ret < 0)
   1350         goto cleanup;
   1351 
   1352     /* Add the vendor specific attributes for the NL command. */
   1353     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1354     if (!nlData)
   1355         goto cleanup;
   1356 
   1357     if (vCommand->put_u32(
   1358             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
   1359             QCA_WLAN_GET_PACKET_FILTER_SIZE))
   1360     {
   1361         goto cleanup;
   1362     }
   1363     vCommand->attr_end(nlData);
   1364 
   1365     ret = vCommand->requestResponse();
   1366     if (ret) {
   1367         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
   1368         if (ret == -ENOTSUP) {
   1369             /* Packet filtering is not supported currently, so return version
   1370              * and length as 0
   1371              */
   1372             ALOGI("Packet filtering is not supprted");
   1373             *version = 0;
   1374             *max_len = 0;
   1375             ret = WIFI_SUCCESS;
   1376         }
   1377         goto cleanup;
   1378     }
   1379 
   1380     *version = vCommand->getFilterVersion();
   1381     *max_len = vCommand->getFilterLength();
   1382 cleanup:
   1383     delete vCommand;
   1384     return (wifi_error)ret;
   1385 }
   1386 
   1387 
   1388 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
   1389                                             u8 enable)
   1390 {
   1391     int ret = WIFI_SUCCESS;
   1392     struct nlattr *nlData;
   1393     WifiVendorCommand *vCommand = NULL;
   1394 
   1395     ret = initialize_vendor_cmd(iface, get_requestid(),
   1396                                 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
   1397                                 &vCommand);
   1398     if (ret != WIFI_SUCCESS) {
   1399         ALOGE("%s: Initialization failed", __func__);
   1400         return (wifi_error)ret;
   1401     }
   1402 
   1403     ALOGV("ND offload : %s", enable?"Enable":"Disable");
   1404 
   1405     /* Add the vendor specific attributes for the NL command. */
   1406     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1407     if (!nlData)
   1408         goto cleanup;
   1409 
   1410     if (vCommand->put_u8(
   1411             QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG,
   1412             enable))
   1413     {
   1414         goto cleanup;
   1415     }
   1416 
   1417     vCommand->attr_end(nlData);
   1418 
   1419     ret = vCommand->requestResponse();
   1420 
   1421 cleanup:
   1422     delete vCommand;
   1423     return (wifi_error)ret;
   1424 }
   1425