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