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-private/object-api.h>
     34 #include <netlink-private/types.h>
     35 
     36 #include "nl80211_copy.h"
     37 
     38 #include <dirent.h>
     39 #include <net/if.h>
     40 #include <netinet/in.h>
     41 #include <cld80211_lib.h>
     42 
     43 #include "sync.h"
     44 
     45 #define LOG_TAG  "WifiHAL"
     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 wifi_get_capabilities(wifi_interface_handle handle)
    188 {
    189     wifi_error ret;
    190     int requestId;
    191     WifihalGeneric *wifihalGeneric;
    192     wifi_handle wifiHandle = getWifiHandle(handle);
    193     hal_info *info = getHalInfo(wifiHandle);
    194 
    195     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
    196         ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
    197         return WIFI_ERROR_NOT_SUPPORTED;
    198     }
    199 
    200     /* No request id from caller, so generate one and pass it on to the driver.
    201      * Generate it randomly.
    202      */
    203     requestId = get_requestid();
    204 
    205     wifihalGeneric = new WifihalGeneric(
    206                             wifiHandle,
    207                             requestId,
    208                             OUI_QCA,
    209                             QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
    210     if (!wifihalGeneric) {
    211         ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
    212         return WIFI_ERROR_UNKNOWN;
    213     }
    214 
    215     ret = wifihalGeneric->wifiGetCapabilities(handle);
    216 
    217     delete wifihalGeneric;
    218     return ret;
    219 }
    220 
    221 static wifi_error get_firmware_bus_max_size_supported(
    222                                                 wifi_interface_handle iface)
    223 {
    224     int ret = 0;
    225     interface_info *iinfo = getIfaceInfo(iface);
    226     wifi_handle handle = getWifiHandle(iface);
    227     hal_info *info = (hal_info *)handle;
    228 
    229     WifihalGeneric busSizeSupported(handle, 0,
    230                                     OUI_QCA,
    231                                     QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
    232 
    233     /* create the message */
    234     ret = busSizeSupported.create();
    235     if (ret < 0)
    236         goto cleanup;
    237 
    238     ret = busSizeSupported.set_iface_id(iinfo->name);
    239     if (ret < 0)
    240         goto cleanup;
    241 
    242     ret = busSizeSupported.requestResponse();
    243     if (ret != 0) {
    244         ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
    245         goto cleanup;
    246     }
    247     info->firmware_bus_max_size = busSizeSupported.getBusSize();
    248 
    249 cleanup:
    250     return (wifi_error)ret;
    251 }
    252 
    253 static wifi_error wifi_init_user_sock(hal_info *info)
    254 {
    255     struct nl_sock *user_sock =
    256         wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
    257     if (user_sock == NULL) {
    258         ALOGE("Could not create diag sock");
    259         return WIFI_ERROR_UNKNOWN;
    260     }
    261 
    262     /* Set the socket buffer size */
    263     if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
    264         ALOGE("Could not set size for user_sock: %s",
    265                    strerror(errno));
    266         /* continue anyway with the default (smaller) buffer */
    267     }
    268     else {
    269         ALOGV("nl_socket_set_buffer_size successful for user_sock");
    270     }
    271 
    272     struct nl_cb *cb = nl_socket_get_cb(user_sock);
    273     if (cb == NULL) {
    274         ALOGE("Could not get cb");
    275         return WIFI_ERROR_UNKNOWN;
    276     }
    277 
    278     info->user_sock_arg = 1;
    279     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
    280     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
    281     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
    282     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
    283 
    284     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
    285     nl_cb_put(cb);
    286 
    287     int ret = nl_socket_add_membership(user_sock, 1);
    288     if (ret < 0) {
    289         ALOGE("Could not add membership");
    290         return WIFI_ERROR_UNKNOWN;
    291     }
    292 
    293     info->user_sock = user_sock;
    294     ALOGV("Initiialized diag sock successfully");
    295     return WIFI_SUCCESS;
    296 }
    297 
    298 static wifi_error wifi_init_cld80211_sock_cb(hal_info *info)
    299 {
    300     struct nl_cb *cb = nl_socket_get_cb(info->cldctx->sock);
    301     if (cb == NULL) {
    302         ALOGE("Could not get cb");
    303         return WIFI_ERROR_UNKNOWN;
    304     }
    305 
    306     info->user_sock_arg = 1;
    307     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
    308     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
    309     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
    310     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
    311 
    312     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
    313     nl_cb_put(cb);
    314 
    315     return WIFI_SUCCESS;
    316 }
    317 
    318 
    319 /*initialize function pointer table with Qualcomm HAL API*/
    320 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
    321     if (fn == NULL) {
    322         return WIFI_ERROR_UNKNOWN;
    323     }
    324 
    325     fn->wifi_initialize = wifi_initialize;
    326     fn->wifi_cleanup = wifi_cleanup;
    327     fn->wifi_event_loop = wifi_event_loop;
    328     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
    329     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
    330     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
    331     fn->wifi_get_ifaces = wifi_get_ifaces;
    332     fn->wifi_get_iface_name = wifi_get_iface_name;
    333     fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
    334     fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
    335     fn->wifi_start_gscan = wifi_start_gscan;
    336     fn->wifi_stop_gscan = wifi_stop_gscan;
    337     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
    338     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
    339     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
    340     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
    341     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
    342     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
    343     fn->wifi_set_link_stats = wifi_set_link_stats;
    344     fn->wifi_get_link_stats = wifi_get_link_stats;
    345     fn->wifi_clear_link_stats = wifi_clear_link_stats;
    346     fn->wifi_get_valid_channels = wifi_get_valid_channels;
    347     fn->wifi_rtt_range_request = wifi_rtt_range_request;
    348     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
    349     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
    350     fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
    351     fn->wifi_enable_responder = wifi_enable_responder;
    352     fn->wifi_disable_responder = wifi_disable_responder;
    353     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
    354     fn->wifi_start_logging = wifi_start_logging;
    355     fn->wifi_set_epno_list = wifi_set_epno_list;
    356     fn->wifi_reset_epno_list = wifi_reset_epno_list;
    357     fn->wifi_set_country_code = wifi_set_country_code;
    358     fn->wifi_enable_tdls = wifi_enable_tdls;
    359     fn->wifi_disable_tdls = wifi_disable_tdls;
    360     fn->wifi_get_tdls_status = wifi_get_tdls_status;
    361     fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
    362     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
    363     fn->wifi_set_log_handler = wifi_set_log_handler;
    364     fn->wifi_reset_log_handler = wifi_reset_log_handler;
    365     fn->wifi_set_alert_handler = wifi_set_alert_handler;
    366     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
    367     fn->wifi_get_firmware_version = wifi_get_firmware_version;
    368     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
    369     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
    370     fn->wifi_get_ring_data = wifi_get_ring_data;
    371     fn->wifi_get_driver_version = wifi_get_driver_version;
    372     fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
    373     fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
    374     fn->wifi_set_lci = wifi_set_lci;
    375     fn->wifi_set_lcr = wifi_set_lcr;
    376     fn->wifi_start_sending_offloaded_packet =
    377             wifi_start_sending_offloaded_packet;
    378     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
    379     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
    380     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
    381     fn->wifi_nan_enable_request = nan_enable_request;
    382     fn->wifi_nan_disable_request = nan_disable_request;
    383     fn->wifi_nan_publish_request = nan_publish_request;
    384     fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
    385     fn->wifi_nan_subscribe_request = nan_subscribe_request;
    386     fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
    387     fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
    388     fn->wifi_nan_stats_request = nan_stats_request;
    389     fn->wifi_nan_config_request = nan_config_request;
    390     fn->wifi_nan_tca_request = nan_tca_request;
    391     fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
    392     fn->wifi_nan_register_handler = nan_register_handler;
    393     fn->wifi_nan_get_version = nan_get_version;
    394     fn->wifi_set_packet_filter = wifi_set_packet_filter;
    395     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
    396     fn->wifi_nan_get_capabilities = nan_get_capabilities;
    397     fn->wifi_nan_data_interface_create = nan_data_interface_create;
    398     fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
    399     fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
    400     fn->wifi_nan_data_indication_response = nan_data_indication_response;
    401     fn->wifi_nan_data_end = nan_data_end;
    402     fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
    403     fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
    404     fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
    405     fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
    406     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
    407     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
    408     fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
    409     fn->wifi_configure_roaming = wifi_configure_roaming;
    410     fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
    411 
    412     return WIFI_SUCCESS;
    413 }
    414 
    415 static void cld80211lib_cleanup(hal_info *info)
    416 {
    417     if (!info->cldctx)
    418         return;
    419     cld80211_remove_mcast_group(info->cldctx, "host_logs");
    420     cld80211_remove_mcast_group(info->cldctx, "fw_logs");
    421     cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
    422     cld80211_remove_mcast_group(info->cldctx, "diag_events");
    423     cld80211_remove_mcast_group(info->cldctx, "fatal_events");
    424     exit_cld80211_recv(info->cldctx);
    425     cld80211_deinit(info->cldctx);
    426     info->cldctx = NULL;
    427 }
    428 
    429 wifi_error wifi_initialize(wifi_handle *handle)
    430 {
    431     int err = 0;
    432     wifi_error ret = WIFI_SUCCESS;
    433     wifi_interface_handle iface_handle;
    434     struct nl_sock *cmd_sock = NULL;
    435     struct nl_sock *event_sock = NULL;
    436     struct nl_cb *cb = NULL;
    437     int status = 0;
    438 
    439     ALOGI("Initializing wifi");
    440     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
    441     if (info == NULL) {
    442         ALOGE("Could not allocate hal_info");
    443         return WIFI_ERROR_OUT_OF_MEMORY;
    444     }
    445 
    446     memset(info, 0, sizeof(*info));
    447 
    448     cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
    449                                                      NETLINK_GENERIC);
    450     if (cmd_sock == NULL) {
    451         ALOGE("Failed to create command socket port");
    452         ret = WIFI_ERROR_UNKNOWN;
    453         goto unload;
    454     }
    455 
    456     /* Set the socket buffer size */
    457     if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
    458         ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
    459                    strerror(errno));
    460         /* continue anyway with the default (smaller) buffer */
    461     }
    462 
    463     event_sock =
    464         wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
    465     if (event_sock == NULL) {
    466         ALOGE("Failed to create event socket port");
    467         ret = WIFI_ERROR_UNKNOWN;
    468         goto unload;
    469     }
    470 
    471     /* Set the socket buffer size */
    472     if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
    473         ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
    474                    strerror(errno));
    475         /* continue anyway with the default (smaller) buffer */
    476     }
    477 
    478     cb = nl_socket_get_cb(event_sock);
    479     if (cb == NULL) {
    480         ALOGE("Failed to get NL control block for event socket port");
    481         ret = WIFI_ERROR_UNKNOWN;
    482         goto unload;
    483     }
    484 
    485     err = 1;
    486     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
    487     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
    488     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
    489     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
    490 
    491     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
    492             info);
    493     nl_cb_put(cb);
    494 
    495     info->cmd_sock = cmd_sock;
    496     info->event_sock = event_sock;
    497     info->clean_up = false;
    498     info->in_event_loop = false;
    499 
    500     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
    501     if (info->event_cb == NULL) {
    502         ALOGE("Could not allocate event_cb");
    503         ret = WIFI_ERROR_OUT_OF_MEMORY;
    504         goto unload;
    505     }
    506     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
    507     info->num_event_cb = 0;
    508 
    509     info->cmd = (cmd_info *)malloc(sizeof(cmd_info) * DEFAULT_CMD_SIZE);
    510     if (info->cmd == NULL) {
    511         ALOGE("Could not allocate cmd info");
    512         ret = WIFI_ERROR_OUT_OF_MEMORY;
    513         goto unload;
    514     }
    515     info->alloc_cmd = DEFAULT_CMD_SIZE;
    516     info->num_cmd = 0;
    517 
    518     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
    519     if (info->nl80211_family_id < 0) {
    520         ALOGE("Could not resolve nl80211 familty id");
    521         ret = WIFI_ERROR_UNKNOWN;
    522         goto unload;
    523     }
    524 
    525     pthread_mutex_init(&info->cb_lock, NULL);
    526     pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
    527 
    528     *handle = (wifi_handle) info;
    529 
    530     wifi_add_membership(*handle, "scan");
    531     wifi_add_membership(*handle, "mlme");
    532     wifi_add_membership(*handle, "regulatory");
    533     wifi_add_membership(*handle, "vendor");
    534 
    535     info->cldctx = cld80211_init();
    536     if (info->cldctx != NULL) {
    537         info->user_sock = info->cldctx->sock;
    538         ret = wifi_init_cld80211_sock_cb(info);
    539         if (ret != WIFI_SUCCESS) {
    540             ALOGE("Could not set cb for CLD80211 family");
    541             goto cld80211_cleanup;
    542         }
    543 
    544         status = cld80211_add_mcast_group(info->cldctx, "host_logs");
    545         if (status) {
    546             ALOGE("Failed to add mcast group host_logs :%d", status);
    547             goto cld80211_cleanup;
    548         }
    549         status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
    550         if (status) {
    551             ALOGE("Failed to add mcast group fw_logs :%d", status);
    552             goto cld80211_cleanup;
    553         }
    554         status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
    555         if (status) {
    556             ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
    557             goto cld80211_cleanup;
    558         }
    559         status = cld80211_add_mcast_group(info->cldctx, "diag_events");
    560         if (status) {
    561             ALOGE("Failed to add mcast group diag_events :%d", status);
    562             goto cld80211_cleanup;
    563         }
    564         status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
    565         if (status) {
    566             ALOGE("Failed to add mcast group fatal_events :%d", status);
    567             goto cld80211_cleanup;
    568         }
    569     } else {
    570         ret = wifi_init_user_sock(info);
    571         if (ret != WIFI_SUCCESS) {
    572             ALOGE("Failed to alloc user socket");
    573             goto unload;
    574         }
    575     }
    576 
    577     ret = wifi_init_interfaces(*handle);
    578     if (ret != WIFI_SUCCESS) {
    579         ALOGE("Failed to init interfaces");
    580         goto unload;
    581     }
    582 
    583     if (info->num_interfaces == 0) {
    584         ALOGE("No interfaces found");
    585         ret = WIFI_ERROR_UNINITIALIZED;
    586         goto unload;
    587     }
    588 
    589     iface_handle = wifi_get_iface_handle((info->interfaces[0])->handle,
    590             (info->interfaces[0])->name);
    591     if (iface_handle == NULL) {
    592         int i;
    593         for (i = 0; i < info->num_interfaces; i++)
    594         {
    595             free(info->interfaces[i]);
    596         }
    597         ALOGE("%s no iface with %s\n", __func__, info->interfaces[0]->name);
    598         goto unload;
    599     }
    600 
    601     ret = acquire_supported_features(iface_handle,
    602             &info->supported_feature_set);
    603     if (ret != WIFI_SUCCESS) {
    604         ALOGI("Failed to get supported feature set : %d", ret);
    605         //acquire_supported_features failure is acceptable condition as legacy
    606         //drivers might not support the required vendor command. So, do not
    607         //consider it as failure of wifi_initialize
    608         ret = WIFI_SUCCESS;
    609     }
    610 
    611     ret = get_firmware_bus_max_size_supported(iface_handle);
    612     if (ret != WIFI_SUCCESS) {
    613         ALOGE("Failed to get supported bus size, error : %d", ret);
    614         info->firmware_bus_max_size = 1520;
    615     }
    616 
    617     ret = wifi_logger_ring_buffers_init(info);
    618     if (ret != WIFI_SUCCESS) {
    619         ALOGE("Wifi Logger Ring Initialization Failed");
    620         goto unload;
    621     }
    622 
    623     ret = wifi_get_capabilities(iface_handle);
    624     if (ret != WIFI_SUCCESS)
    625         ALOGE("Failed to get wifi Capabilities, error: %d", ret);
    626 
    627     info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
    628     if (!info->pkt_stats) {
    629         ALOGE("%s: malloc Failed for size: %zu",
    630                 __FUNCTION__, sizeof(struct pkt_stats_s));
    631         ret = WIFI_ERROR_OUT_OF_MEMORY;
    632         goto unload;
    633     }
    634 
    635     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
    636                                   * PKT_STATS_BUF_SIZE;
    637 
    638     info->rx_aggr_pkts =
    639         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
    640     if (!info->rx_aggr_pkts) {
    641         ALOGE("%s: malloc Failed for size: %d",
    642                 __FUNCTION__, info->rx_buf_size_allocated);
    643         ret = WIFI_ERROR_OUT_OF_MEMORY;
    644         info->rx_buf_size_allocated = 0;
    645         goto unload;
    646     }
    647     memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
    648 
    649     info->exit_sockets[0] = -1;
    650     info->exit_sockets[1] = -1;
    651 
    652     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
    653         ALOGE("Failed to create exit socket pair");
    654         ret = WIFI_ERROR_UNKNOWN;
    655         goto unload;
    656     }
    657 
    658     ALOGV("Initializing Gscan Event Handlers");
    659     ret = initializeGscanHandlers(info);
    660     if (ret != WIFI_SUCCESS) {
    661         ALOGE("Initializing Gscan Event Handlers Failed");
    662         goto unload;
    663     }
    664 
    665     ret = initializeRSSIMonitorHandler(info);
    666     if (ret != WIFI_SUCCESS) {
    667         ALOGE("Initializing RSSI Event Handler Failed");
    668         goto unload;
    669     }
    670 
    671     ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
    672             " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
    673 
    674 cld80211_cleanup:
    675     if (status != 0 || ret != WIFI_SUCCESS) {
    676         ret = WIFI_ERROR_UNKNOWN;
    677         cld80211lib_cleanup(info);
    678     }
    679 unload:
    680     if (ret != WIFI_SUCCESS) {
    681         if (cmd_sock)
    682             nl_socket_free(cmd_sock);
    683         if (event_sock)
    684             nl_socket_free(event_sock);
    685         if (info) {
    686             if (info->cmd) free(info->cmd);
    687             if (info->event_cb) free(info->event_cb);
    688             if (info->cldctx) {
    689                 cld80211lib_cleanup(info);
    690             } else if (info->user_sock) {
    691                 nl_socket_free(info->user_sock);
    692             }
    693             if (info->pkt_stats) free(info->pkt_stats);
    694             if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
    695             cleanupGscanHandlers(info);
    696             cleanupRSSIMonitorHandler(info);
    697             free(info);
    698         }
    699     }
    700 
    701     return ret;
    702 }
    703 
    704 static int wifi_add_membership(wifi_handle handle, const char *group)
    705 {
    706     hal_info *info = getHalInfo(handle);
    707 
    708     int id = wifi_get_multicast_id(handle, "nl80211", group);
    709     if (id < 0) {
    710         ALOGE("Could not find group %s", group);
    711         return id;
    712     }
    713 
    714     int ret = nl_socket_add_membership(info->event_sock, id);
    715     if (ret < 0) {
    716         ALOGE("Could not add membership to group %s", group);
    717     }
    718 
    719     return ret;
    720 }
    721 
    722 static void internal_cleaned_up_handler(wifi_handle handle)
    723 {
    724     hal_info *info = getHalInfo(handle);
    725     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
    726 
    727     if (info->cmd_sock != 0) {
    728         nl_socket_free(info->cmd_sock);
    729         nl_socket_free(info->event_sock);
    730         info->cmd_sock = NULL;
    731         info->event_sock = NULL;
    732     }
    733 
    734     if (info->cldctx != NULL) {
    735         cld80211lib_cleanup(info);
    736     } else if (info->user_sock != 0) {
    737         nl_socket_free(info->user_sock);
    738         info->user_sock = NULL;
    739     }
    740 
    741     if (info->pkt_stats)
    742         free(info->pkt_stats);
    743     if (info->rx_aggr_pkts)
    744         free(info->rx_aggr_pkts);
    745     wifi_logger_ring_buffers_deinit(info);
    746     cleanupGscanHandlers(info);
    747     cleanupRSSIMonitorHandler(info);
    748 
    749     if (info->exit_sockets[0] >= 0) {
    750         close(info->exit_sockets[0]);
    751         info->exit_sockets[0] = -1;
    752     }
    753 
    754     if (info->exit_sockets[1] >= 0) {
    755         close(info->exit_sockets[1]);
    756         info->exit_sockets[1] = -1;
    757     }
    758 
    759     if (info->pkt_fate_stats) {
    760         free(info->pkt_fate_stats);
    761         info->pkt_fate_stats = NULL;
    762     }
    763 
    764     (*cleaned_up_handler)(handle);
    765     pthread_mutex_destroy(&info->cb_lock);
    766     pthread_mutex_destroy(&info->pkt_fate_stats_lock);
    767     free(info);
    768 }
    769 
    770 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
    771 {
    772     if (!handle) {
    773         ALOGE("Handle is null");
    774         return;
    775     }
    776 
    777     hal_info *info = getHalInfo(handle);
    778     info->cleaned_up_handler = handler;
    779     info->clean_up = true;
    780 
    781     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
    782     ALOGI("Sent msg on exit sock to unblock poll()");
    783 }
    784 
    785 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
    786 {
    787     struct nl_cb *cb = nl_socket_get_cb(sock);
    788 
    789     int res = nl_recvmsgs(sock, cb);
    790     if(res)
    791         ALOGE("Error :%d while reading nl msg", res);
    792     nl_cb_put(cb);
    793     return res;
    794 }
    795 
    796 static void internal_event_handler(wifi_handle handle, int events,
    797                                    struct nl_sock *sock)
    798 {
    799     if (events & POLLERR) {
    800         ALOGE("Error reading from socket");
    801         internal_pollin_handler(handle, sock);
    802     } else if (events & POLLHUP) {
    803         ALOGE("Remote side hung up");
    804     } else if (events & POLLIN) {
    805         //ALOGI("Found some events!!!");
    806         internal_pollin_handler(handle, sock);
    807     } else {
    808         ALOGE("Unknown event - %0x", events);
    809     }
    810 }
    811 
    812 /* Run event handler */
    813 void wifi_event_loop(wifi_handle handle)
    814 {
    815     hal_info *info = getHalInfo(handle);
    816     if (info->in_event_loop) {
    817         return;
    818     } else {
    819         info->in_event_loop = true;
    820     }
    821 
    822     pollfd pfd[3];
    823     memset(&pfd, 0, 3*sizeof(pfd[0]));
    824 
    825     pfd[0].fd = nl_socket_get_fd(info->event_sock);
    826     pfd[0].events = POLLIN;
    827 
    828     pfd[1].fd = nl_socket_get_fd(info->user_sock);
    829     pfd[1].events = POLLIN;
    830 
    831     pfd[2].fd = info->exit_sockets[1];
    832     pfd[2].events = POLLIN;
    833 
    834     /* TODO: Add support for timeouts */
    835 
    836     do {
    837         pfd[0].revents = 0;
    838         pfd[1].revents = 0;
    839         pfd[2].revents = 0;
    840         //ALOGI("Polling sockets");
    841         int result = poll(pfd, 3, -1);
    842         if (result < 0) {
    843             ALOGE("Error polling socket");
    844         } else {
    845             if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
    846                 internal_event_handler(handle, pfd[0].revents, info->event_sock);
    847             }
    848             if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
    849                 internal_event_handler(handle, pfd[1].revents, info->user_sock);
    850             }
    851         }
    852         rb_timerhandler(info);
    853     } while (!info->clean_up);
    854     internal_cleaned_up_handler(handle);
    855 }
    856 
    857 static int user_sock_message_handler(nl_msg *msg, void *arg)
    858 {
    859     wifi_handle handle = (wifi_handle)arg;
    860     hal_info *info = getHalInfo(handle);
    861 
    862     diag_message_handler(info, msg);
    863 
    864     return NL_OK;
    865 }
    866 
    867 static int internal_valid_message_handler(nl_msg *msg, void *arg)
    868 {
    869     wifi_handle handle = (wifi_handle)arg;
    870     hal_info *info = getHalInfo(handle);
    871 
    872     WifiEvent event(msg);
    873     int res = event.parse();
    874     if (res < 0) {
    875         ALOGE("Failed to parse event: %d", res);
    876         return NL_SKIP;
    877     }
    878 
    879     int cmd = event.get_cmd();
    880     uint32_t vendor_id = 0;
    881     int subcmd = 0;
    882 
    883     if (cmd == NL80211_CMD_VENDOR) {
    884         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
    885         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
    886         /* Restrict printing GSCAN_FULL_RESULT which is causing lot
    887            of logs in bug report */
    888         if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
    889             ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
    890                   event.get_cmdString(), vendor_id, subcmd);
    891         }
    892     } else {
    893         ALOGV("event received %s", event.get_cmdString());
    894     }
    895 
    896     // event.log();
    897 
    898     bool dispatched = false;
    899 
    900     pthread_mutex_lock(&info->cb_lock);
    901 
    902     for (int i = 0; i < info->num_event_cb; i++) {
    903         if (cmd == info->event_cb[i].nl_cmd) {
    904             if (cmd == NL80211_CMD_VENDOR
    905                 && ((vendor_id != info->event_cb[i].vendor_id)
    906                 || (subcmd != info->event_cb[i].vendor_subcmd)))
    907             {
    908                 /* event for a different vendor, ignore it */
    909                 continue;
    910             }
    911 
    912             cb_info *cbi = &(info->event_cb[i]);
    913             pthread_mutex_unlock(&info->cb_lock);
    914             if (cbi->cb_func) {
    915                 (*(cbi->cb_func))(msg, cbi->cb_arg);
    916                 dispatched = true;
    917             }
    918             return NL_OK;
    919         }
    920     }
    921 
    922 #ifdef QC_HAL_DEBUG
    923     if (!dispatched) {
    924         ALOGI("event ignored!!");
    925     }
    926 #endif
    927 
    928     pthread_mutex_unlock(&info->cb_lock);
    929     return NL_OK;
    930 }
    931 
    932 ////////////////////////////////////////////////////////////////////////////////
    933 
    934 class GetMulticastIdCommand : public WifiCommand
    935 {
    936 private:
    937     const char *mName;
    938     const char *mGroup;
    939     int   mId;
    940 public:
    941     GetMulticastIdCommand(wifi_handle handle, const char *name,
    942             const char *group) : WifiCommand(handle, 0)
    943     {
    944         mName = name;
    945         mGroup = group;
    946         mId = -1;
    947     }
    948 
    949     int getId() {
    950         return mId;
    951     }
    952 
    953     virtual int create() {
    954         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
    955         // ALOGI("ctrl family = %d", nlctrlFamily);
    956         int ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
    957         if (ret < 0) {
    958             return ret;
    959         }
    960         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
    961         return ret;
    962     }
    963 
    964     virtual int handleResponse(WifiEvent& reply) {
    965 
    966         // ALOGI("handling reponse in %s", __func__);
    967 
    968         struct nlattr **tb = reply.attributes();
    969         struct nlattr *mcgrp = NULL;
    970         int i;
    971 
    972         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
    973             ALOGI("No multicast groups found");
    974             return NL_SKIP;
    975         } else {
    976             // ALOGI("Multicast groups attr size = %d",
    977             // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
    978         }
    979 
    980         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
    981 
    982             // ALOGI("Processing group");
    983             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
    984             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
    985                 nla_len(mcgrp), NULL);
    986             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
    987             {
    988                 continue;
    989             }
    990 
    991             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
    992             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
    993 
    994             // ALOGI("Found group name %s", grpName);
    995 
    996             if (strncmp(grpName, mGroup, grpNameLen) != 0)
    997                 continue;
    998 
    999             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
   1000             break;
   1001         }
   1002 
   1003         return NL_SKIP;
   1004     }
   1005 
   1006 };
   1007 
   1008 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
   1009         const char *group)
   1010 {
   1011     GetMulticastIdCommand cmd(handle, name, group);
   1012     int res = cmd.requestResponse();
   1013     if (res < 0)
   1014         return res;
   1015     else
   1016         return cmd.getId();
   1017 }
   1018 
   1019 /////////////////////////////////////////////////////////////////////////
   1020 
   1021 static bool is_wifi_interface(const char *name)
   1022 {
   1023     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
   1024         /* not a wifi interface; ignore it */
   1025         return false;
   1026     } else {
   1027         return true;
   1028     }
   1029 }
   1030 
   1031 static int get_interface(const char *name, interface_info *info)
   1032 {
   1033     strlcpy(info->name, name, (IFNAMSIZ + 1));
   1034     info->id = if_nametoindex(name);
   1035     // ALOGI("found an interface : %s, id = %d", name, info->id);
   1036     return WIFI_SUCCESS;
   1037 }
   1038 
   1039 wifi_error wifi_init_interfaces(wifi_handle handle)
   1040 {
   1041     hal_info *info = (hal_info *)handle;
   1042 
   1043     struct dirent *de;
   1044 
   1045     DIR *d = opendir("/sys/class/net");
   1046     if (d == 0)
   1047         return WIFI_ERROR_UNKNOWN;
   1048 
   1049     int n = 0;
   1050     while ((de = readdir(d))) {
   1051         if (de->d_name[0] == '.')
   1052             continue;
   1053         if (is_wifi_interface(de->d_name) ) {
   1054             n++;
   1055         }
   1056     }
   1057 
   1058     closedir(d);
   1059 
   1060     d = opendir("/sys/class/net");
   1061     if (d == 0)
   1062         return WIFI_ERROR_UNKNOWN;
   1063 
   1064     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
   1065     if (info->interfaces == NULL) {
   1066         ALOGE("%s: Error info->interfaces NULL", __func__);
   1067         return WIFI_ERROR_OUT_OF_MEMORY;
   1068     }
   1069 
   1070     int i = 0;
   1071     while ((de = readdir(d))) {
   1072         if (de->d_name[0] == '.')
   1073             continue;
   1074         if (is_wifi_interface(de->d_name)) {
   1075             interface_info *ifinfo
   1076                 = (interface_info *)malloc(sizeof(interface_info));
   1077             if (ifinfo == NULL) {
   1078                 ALOGE("%s: Error ifinfo NULL", __func__);
   1079                 while (i > 0) {
   1080                     free(info->interfaces[i-1]);
   1081                     i--;
   1082                 }
   1083                 free(info->interfaces);
   1084                 return WIFI_ERROR_OUT_OF_MEMORY;
   1085             }
   1086             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
   1087                 free(ifinfo);
   1088                 continue;
   1089             }
   1090             ifinfo->handle = handle;
   1091             info->interfaces[i] = ifinfo;
   1092             i++;
   1093         }
   1094     }
   1095 
   1096     closedir(d);
   1097 
   1098     info->num_interfaces = n;
   1099 
   1100     return WIFI_SUCCESS;
   1101 }
   1102 
   1103 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
   1104         wifi_interface_handle **interfaces)
   1105 {
   1106     hal_info *info = (hal_info *)handle;
   1107 
   1108     *interfaces = (wifi_interface_handle *)info->interfaces;
   1109     *num = info->num_interfaces;
   1110 
   1111     return WIFI_SUCCESS;
   1112 }
   1113 
   1114 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
   1115         size_t size)
   1116 {
   1117     interface_info *info = (interface_info *)handle;
   1118     strlcpy(name, info->name, size);
   1119     return WIFI_SUCCESS;
   1120 }
   1121 
   1122 /* Get the supported Feature set */
   1123 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
   1124         feature_set *set)
   1125 {
   1126     int ret = 0;
   1127     wifi_handle handle = getWifiHandle(iface);
   1128     *set = 0;
   1129     hal_info *info = getHalInfo(handle);
   1130 
   1131     ret = acquire_supported_features(iface, set);
   1132     if (ret != WIFI_SUCCESS) {
   1133         *set = info->supported_feature_set;
   1134         ALOGV("Supported feature set acquired at initialization : %x", *set);
   1135     } else {
   1136         info->supported_feature_set = *set;
   1137         ALOGV("Supported feature set acquired : %x", *set);
   1138     }
   1139     return WIFI_SUCCESS;
   1140 }
   1141 
   1142 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
   1143                                        int set_size_max,
   1144                                        feature_set set[], int *set_size)
   1145 {
   1146     int ret = 0;
   1147     struct nlattr *nlData;
   1148     WifihalGeneric *vCommand = NULL;
   1149     interface_info *ifaceInfo = getIfaceInfo(handle);
   1150     wifi_handle wifiHandle = getWifiHandle(handle);
   1151 
   1152     if (set == NULL) {
   1153         ALOGE("%s: NULL set pointer provided. Exit.",
   1154             __func__);
   1155         return WIFI_ERROR_INVALID_ARGS;
   1156     }
   1157 
   1158     vCommand = new WifihalGeneric(wifiHandle, 0,
   1159             OUI_QCA,
   1160             QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
   1161     if (vCommand == NULL) {
   1162         ALOGE("%s: Error vCommand NULL", __func__);
   1163         return WIFI_ERROR_OUT_OF_MEMORY;
   1164     }
   1165 
   1166     /* Create the message */
   1167     ret = vCommand->create();
   1168     if (ret < 0)
   1169         goto cleanup;
   1170 
   1171     ret = vCommand->set_iface_id(ifaceInfo->name);
   1172     if (ret < 0)
   1173         goto cleanup;
   1174 
   1175     /* Add the vendor specific attributes for the NL command. */
   1176     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1177     if (!nlData)
   1178         goto cleanup;
   1179 
   1180     if (vCommand->put_u32(
   1181         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
   1182         set_size_max))
   1183     {
   1184         goto cleanup;
   1185     }
   1186     vCommand->attr_end(nlData);
   1187 
   1188     /* Populate the input received from caller/framework. */
   1189     vCommand->setMaxSetSize(set_size_max);
   1190     vCommand->setSizePtr(set_size);
   1191     vCommand->setConcurrencySet(set);
   1192 
   1193     ret = vCommand->requestResponse();
   1194     if (ret) {
   1195         ALOGE("%s: requestResponse() error: %d", __func__, ret);
   1196     }
   1197 
   1198 cleanup:
   1199     delete vCommand;
   1200     if (ret) {
   1201         *set_size = 0;
   1202     }
   1203     return (wifi_error)ret;
   1204 }
   1205 
   1206 
   1207 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
   1208 {
   1209     int ret = 0;
   1210     struct nlattr *nlData;
   1211     WifiVendorCommand *vCommand = NULL;
   1212     interface_info *ifaceInfo = getIfaceInfo(handle);
   1213     wifi_handle wifiHandle = getWifiHandle(handle);
   1214 
   1215     vCommand = new WifiVendorCommand(wifiHandle, 0,
   1216             OUI_QCA,
   1217             QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
   1218     if (vCommand == NULL) {
   1219         ALOGE("%s: Error vCommand NULL", __func__);
   1220         return WIFI_ERROR_OUT_OF_MEMORY;
   1221     }
   1222 
   1223     /* Create the message */
   1224     ret = vCommand->create();
   1225     if (ret < 0)
   1226         goto cleanup;
   1227 
   1228     ret = vCommand->set_iface_id(ifaceInfo->name);
   1229     if (ret < 0)
   1230         goto cleanup;
   1231 
   1232     /* Add the vendor specific attributes for the NL command. */
   1233     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1234     if (!nlData)
   1235         goto cleanup;
   1236 
   1237     /* Add the fixed part of the mac_oui to the nl command */
   1238     if (vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs)) {
   1239         goto cleanup;
   1240     }
   1241 
   1242     vCommand->attr_end(nlData);
   1243 
   1244     ret = vCommand->requestResponse();
   1245     /* Don't check response since we aren't expecting one */
   1246 
   1247 cleanup:
   1248     delete vCommand;
   1249     return (wifi_error)ret;
   1250 }
   1251 
   1252 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
   1253                                                wifi_interface_handle iface,
   1254                                                u8 *ip_packet,
   1255                                                u16 ip_packet_len,
   1256                                                u8 *src_mac_addr,
   1257                                                u8 *dst_mac_addr,
   1258                                                u32 period_msec)
   1259 {
   1260     int ret = WIFI_SUCCESS;
   1261     struct nlattr *nlData;
   1262     WifiVendorCommand *vCommand = NULL;
   1263 
   1264     ret = initialize_vendor_cmd(iface, id,
   1265                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
   1266                                 &vCommand);
   1267     if (ret != WIFI_SUCCESS) {
   1268         ALOGE("%s: Initialization failed", __func__);
   1269         return (wifi_error)ret;
   1270     }
   1271 
   1272     ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
   1273     hexdump(ip_packet, ip_packet_len);
   1274     ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
   1275           "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
   1276           MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
   1277 
   1278     /* Add the vendor specific attributes for the NL command. */
   1279     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1280     if (!nlData)
   1281         goto cleanup;
   1282 
   1283     if (vCommand->put_u32(
   1284             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
   1285             QCA_WLAN_OFFLOADED_PACKETS_SENDING_START) ||
   1286         vCommand->put_u32(
   1287             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
   1288             id) ||
   1289         vCommand->put_bytes(
   1290             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET,
   1291             (const char *)ip_packet, ip_packet_len) ||
   1292         vCommand->put_addr(
   1293             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
   1294             src_mac_addr) ||
   1295         vCommand->put_addr(
   1296             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
   1297             dst_mac_addr) ||
   1298         vCommand->put_u32(
   1299             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
   1300             period_msec))
   1301     {
   1302         goto cleanup;
   1303     }
   1304 
   1305     vCommand->attr_end(nlData);
   1306 
   1307     ret = vCommand->requestResponse();
   1308     if (ret < 0)
   1309         goto cleanup;
   1310 
   1311 cleanup:
   1312     delete vCommand;
   1313     return (wifi_error)ret;
   1314 }
   1315 
   1316 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
   1317                                               wifi_interface_handle iface)
   1318 {
   1319     int ret = WIFI_SUCCESS;
   1320     struct nlattr *nlData;
   1321     WifiVendorCommand *vCommand = NULL;
   1322 
   1323     ret = initialize_vendor_cmd(iface, id,
   1324                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
   1325                                 &vCommand);
   1326     if (ret != WIFI_SUCCESS) {
   1327         ALOGE("%s: Initialization failed", __func__);
   1328         return (wifi_error)ret;
   1329     }
   1330 
   1331     /* Add the vendor specific attributes for the NL command. */
   1332     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1333     if (!nlData)
   1334         goto cleanup;
   1335 
   1336     if (vCommand->put_u32(
   1337             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
   1338             QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP) ||
   1339         vCommand->put_u32(
   1340             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
   1341             id))
   1342     {
   1343         goto cleanup;
   1344     }
   1345 
   1346 
   1347     vCommand->attr_end(nlData);
   1348 
   1349     ret = vCommand->requestResponse();
   1350     if (ret < 0)
   1351         goto cleanup;
   1352 
   1353 cleanup:
   1354     delete vCommand;
   1355     return (wifi_error)ret;
   1356 }
   1357 
   1358 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
   1359                                          const u8 *program, u32 len)
   1360 {
   1361     int ret = WIFI_SUCCESS;
   1362     struct nlattr *nlData;
   1363     WifiVendorCommand *vCommand = NULL;
   1364     u32 current_offset = 0;
   1365     wifi_handle wifiHandle = getWifiHandle(iface);
   1366     hal_info *info = getHalInfo(wifiHandle);
   1367 
   1368     /* len=0 clears the filters in driver/firmware */
   1369     if (len != 0 && program == NULL) {
   1370         ALOGE("%s: No valid program provided. Exit.",
   1371             __func__);
   1372         return WIFI_ERROR_INVALID_ARGS;
   1373     }
   1374 
   1375     do {
   1376         ret = initialize_vendor_cmd(iface, get_requestid(),
   1377                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
   1378                                     &vCommand);
   1379         if (ret != WIFI_SUCCESS) {
   1380             ALOGE("%s: Initialization failed", __FUNCTION__);
   1381             return (wifi_error)ret;
   1382         }
   1383 
   1384         /* Add the vendor specific attributes for the NL command. */
   1385         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1386         if (!nlData)
   1387             goto cleanup;
   1388 
   1389         if (vCommand->put_u32(
   1390                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
   1391                 QCA_WLAN_SET_PACKET_FILTER) ||
   1392             vCommand->put_u32(
   1393                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
   1394                 PACKET_FILTER_ID) ||
   1395             vCommand->put_u32(
   1396                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
   1397                 len) ||
   1398             vCommand->put_u32(
   1399                 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
   1400                 current_offset)) {
   1401             ALOGE("%s: failed to put subcmd/program", __FUNCTION__);
   1402             goto cleanup;
   1403         }
   1404 
   1405         if (len) {
   1406             if(vCommand->put_bytes(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
   1407                                    (char *)&program[current_offset],
   1408                                    min(info->firmware_bus_max_size,
   1409                                    len-current_offset))) {
   1410                 ALOGE("%s: failed to put subcmd", __FUNCTION__);
   1411                 goto cleanup;
   1412             }
   1413         }
   1414 
   1415         vCommand->attr_end(nlData);
   1416 
   1417         ret = vCommand->requestResponse();
   1418         if (ret < 0) {
   1419             ALOGE("%s: requestResponse Error:%d",__func__, ret);
   1420             goto cleanup;
   1421         }
   1422 
   1423         /* destroy the object after sending each fragment to driver */
   1424         delete vCommand;
   1425         vCommand = NULL;
   1426 
   1427         current_offset += min(info->firmware_bus_max_size, len);
   1428     } while (current_offset < len);
   1429 
   1430 cleanup:
   1431     if (vCommand)
   1432         delete vCommand;
   1433     return (wifi_error)ret;
   1434 }
   1435 
   1436 static wifi_error wifi_get_packet_filter_capabilities(
   1437                 wifi_interface_handle handle, u32 *version, u32 *max_len)
   1438 {
   1439     int ret = 0;
   1440     struct nlattr *nlData;
   1441     WifihalGeneric *vCommand = NULL;
   1442     interface_info *ifaceInfo = getIfaceInfo(handle);
   1443     wifi_handle wifiHandle = getWifiHandle(handle);
   1444 
   1445     if (version == NULL || max_len == NULL) {
   1446         ALOGE("%s: NULL version/max_len pointer provided. Exit.",
   1447             __FUNCTION__);
   1448         return WIFI_ERROR_INVALID_ARGS;
   1449     }
   1450 
   1451     vCommand = new WifihalGeneric(wifiHandle, 0,
   1452             OUI_QCA,
   1453             QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
   1454     if (vCommand == NULL) {
   1455         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
   1456         return WIFI_ERROR_OUT_OF_MEMORY;
   1457     }
   1458 
   1459     /* Create the message */
   1460     ret = vCommand->create();
   1461     if (ret < 0)
   1462         goto cleanup;
   1463 
   1464     ret = vCommand->set_iface_id(ifaceInfo->name);
   1465     if (ret < 0)
   1466         goto cleanup;
   1467 
   1468     /* Add the vendor specific attributes for the NL command. */
   1469     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1470     if (!nlData)
   1471         goto cleanup;
   1472 
   1473     if (vCommand->put_u32(
   1474             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
   1475             QCA_WLAN_GET_PACKET_FILTER_SIZE))
   1476     {
   1477         goto cleanup;
   1478     }
   1479     vCommand->attr_end(nlData);
   1480 
   1481     ret = vCommand->requestResponse();
   1482     if (ret) {
   1483         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
   1484         if (ret == -ENOTSUP) {
   1485             /* Packet filtering is not supported currently, so return version
   1486              * and length as 0
   1487              */
   1488             ALOGI("Packet filtering is not supprted");
   1489             *version = 0;
   1490             *max_len = 0;
   1491             ret = WIFI_SUCCESS;
   1492         }
   1493         goto cleanup;
   1494     }
   1495 
   1496     *version = vCommand->getFilterVersion();
   1497     *max_len = vCommand->getFilterLength();
   1498 cleanup:
   1499     delete vCommand;
   1500     return (wifi_error)ret;
   1501 }
   1502 
   1503 
   1504 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
   1505                                             u8 enable)
   1506 {
   1507     int ret = WIFI_SUCCESS;
   1508     struct nlattr *nlData;
   1509     WifiVendorCommand *vCommand = NULL;
   1510 
   1511     ret = initialize_vendor_cmd(iface, get_requestid(),
   1512                                 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
   1513                                 &vCommand);
   1514     if (ret != WIFI_SUCCESS) {
   1515         ALOGE("%s: Initialization failed", __func__);
   1516         return (wifi_error)ret;
   1517     }
   1518 
   1519     ALOGV("ND offload : %s", enable?"Enable":"Disable");
   1520 
   1521     /* Add the vendor specific attributes for the NL command. */
   1522     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1523     if (!nlData)
   1524         goto cleanup;
   1525 
   1526     if (vCommand->put_u8(
   1527             QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG,
   1528             enable))
   1529     {
   1530         goto cleanup;
   1531     }
   1532 
   1533     vCommand->attr_end(nlData);
   1534 
   1535     ret = vCommand->requestResponse();
   1536 
   1537 cleanup:
   1538     delete vCommand;
   1539     return (wifi_error)ret;
   1540 }
   1541