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 /*
     70  * Defines for wifi_wait_for_driver_ready()
     71  * Specify durations between polls and max wait time
     72  */
     73 #define POLL_DRIVER_DURATION_US (100000)
     74 #define POLL_DRIVER_MAX_TIME_MS (10000)
     75 
     76 static void internal_event_handler(wifi_handle handle, int events,
     77                                    struct nl_sock *sock);
     78 static int internal_valid_message_handler(nl_msg *msg, void *arg);
     79 static int user_sock_message_handler(nl_msg *msg, void *arg);
     80 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
     81         const char *group);
     82 static int wifi_add_membership(wifi_handle handle, const char *group);
     83 static wifi_error wifi_init_interfaces(wifi_handle handle);
     84 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
     85                                          const u8 *program, u32 len);
     86 static wifi_error wifi_get_packet_filter_capabilities(wifi_interface_handle handle,
     87                                               u32 *version, u32 *max_len);
     88 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
     89                                    u32 src_offset, u8 *host_dst, u32 length);
     90 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
     91                                             u8 enable);
     92 wifi_error wifi_get_wake_reason_stats(wifi_interface_handle iface,
     93                              WLAN_DRIVER_WAKE_REASON_CNT *wifi_wake_reason_cnt);
     94 
     95 /* Initialize/Cleanup */
     96 
     97 wifi_interface_handle wifi_get_iface_handle(wifi_handle handle, char *name)
     98 {
     99     hal_info *info = (hal_info *)handle;
    100     for (int i=0;i<info->num_interfaces;i++)
    101     {
    102         if (!strcmp(info->interfaces[i]->name, name))
    103         {
    104             return ((wifi_interface_handle )(info->interfaces)[i]);
    105         }
    106     }
    107     return NULL;
    108 }
    109 
    110 void wifi_socket_set_local_port(struct nl_sock *sock, uint32_t port)
    111 {
    112     /* Release local port pool maintained by libnl and assign a own port
    113      * identifier to the socket.
    114      */
    115     nl_socket_set_local_port(sock, ((uint32_t)getpid() & 0x3FFFFFU) | (port << 22));
    116 }
    117 
    118 static nl_sock * wifi_create_nl_socket(int port, int protocol)
    119 {
    120     // ALOGI("Creating socket");
    121     struct nl_sock *sock = nl_socket_alloc();
    122     if (sock == NULL) {
    123         ALOGE("Failed to create NL socket");
    124         return NULL;
    125     }
    126 
    127     wifi_socket_set_local_port(sock, port);
    128 
    129     if (nl_connect(sock, protocol)) {
    130         ALOGE("Could not connect handle");
    131         nl_socket_free(sock);
    132         return NULL;
    133     }
    134 
    135     return sock;
    136 }
    137 
    138 int ack_handler(struct nl_msg *msg, void *arg)
    139 {
    140     int *err = (int *)arg;
    141     *err = 0;
    142     return NL_STOP;
    143 }
    144 
    145 int finish_handler(struct nl_msg *msg, void *arg)
    146 {
    147     int *ret = (int *)arg;
    148     *ret = 0;
    149     return NL_SKIP;
    150 }
    151 
    152 int error_handler(struct sockaddr_nl *nla,
    153                   struct nlmsgerr *err, void *arg)
    154 {
    155     int *ret = (int *)arg;
    156     *ret = err->error;
    157 
    158     ALOGV("%s invoked with error: %d", __func__, err->error);
    159     return NL_SKIP;
    160 }
    161 static int no_seq_check(struct nl_msg *msg, void *arg)
    162 {
    163     return NL_OK;
    164 }
    165 
    166 static wifi_error acquire_supported_features(wifi_interface_handle iface,
    167         feature_set *set)
    168 {
    169     wifi_error ret;
    170     interface_info *iinfo = getIfaceInfo(iface);
    171     wifi_handle handle = getWifiHandle(iface);
    172     *set = 0;
    173 
    174     WifihalGeneric supportedFeatures(handle, 0,
    175             OUI_QCA,
    176             QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);
    177 
    178     /* create the message */
    179     ret = supportedFeatures.create();
    180     if (ret != WIFI_SUCCESS)
    181         goto cleanup;
    182 
    183     ret = supportedFeatures.set_iface_id(iinfo->name);
    184     if (ret != WIFI_SUCCESS)
    185         goto cleanup;
    186 
    187     ret = supportedFeatures.requestResponse();
    188     if (ret != WIFI_SUCCESS) {
    189         ALOGE("%s: requestResponse Error:%d",__func__, ret);
    190         goto cleanup;
    191     }
    192 
    193     supportedFeatures.getResponseparams(set);
    194 
    195 cleanup:
    196     return ret;
    197 }
    198 
    199 static wifi_error wifi_get_capabilities(wifi_interface_handle handle)
    200 {
    201     wifi_error ret;
    202     int requestId;
    203     WifihalGeneric *wifihalGeneric;
    204     wifi_handle wifiHandle = getWifiHandle(handle);
    205     hal_info *info = getHalInfo(wifiHandle);
    206 
    207     if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) {
    208         ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__);
    209         return WIFI_ERROR_NOT_SUPPORTED;
    210     }
    211 
    212     /* No request id from caller, so generate one and pass it on to the driver.
    213      * Generate it randomly.
    214      */
    215     requestId = get_requestid();
    216 
    217     wifihalGeneric = new WifihalGeneric(
    218                             wifiHandle,
    219                             requestId,
    220                             OUI_QCA,
    221                             QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES);
    222     if (!wifihalGeneric) {
    223         ALOGE("%s: Failed to create object of WifihalGeneric class", __FUNCTION__);
    224         return WIFI_ERROR_OUT_OF_MEMORY;
    225     }
    226 
    227     ret = wifihalGeneric->wifiGetCapabilities(handle);
    228 
    229     delete wifihalGeneric;
    230     return ret;
    231 }
    232 
    233 static wifi_error get_firmware_bus_max_size_supported(
    234                                                 wifi_interface_handle iface)
    235 {
    236     wifi_error ret;
    237     interface_info *iinfo = getIfaceInfo(iface);
    238     wifi_handle handle = getWifiHandle(iface);
    239     hal_info *info = (hal_info *)handle;
    240 
    241     WifihalGeneric busSizeSupported(handle, 0,
    242                                     OUI_QCA,
    243                                     QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);
    244 
    245     /* create the message */
    246     ret = busSizeSupported.create();
    247     if (ret != WIFI_SUCCESS)
    248         goto cleanup;
    249 
    250     ret = busSizeSupported.set_iface_id(iinfo->name);
    251     if (ret != WIFI_SUCCESS)
    252         goto cleanup;
    253 
    254     ret = busSizeSupported.requestResponse();
    255     if (ret != WIFI_SUCCESS) {
    256         ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
    257         goto cleanup;
    258     }
    259     info->firmware_bus_max_size = busSizeSupported.getBusSize();
    260 
    261 cleanup:
    262     return ret;
    263 }
    264 
    265 static wifi_error wifi_init_user_sock(hal_info *info)
    266 {
    267     struct nl_sock *user_sock =
    268         wifi_create_nl_socket(WIFI_HAL_USER_SOCK_PORT, NETLINK_USERSOCK);
    269     if (user_sock == NULL) {
    270         ALOGE("Could not create diag sock");
    271         return WIFI_ERROR_UNKNOWN;
    272     }
    273 
    274     /* Set the socket buffer size */
    275     if (nl_socket_set_buffer_size(user_sock, (256*1024), 0) < 0) {
    276         ALOGE("Could not set size for user_sock: %s",
    277                    strerror(errno));
    278         /* continue anyway with the default (smaller) buffer */
    279     }
    280     else {
    281         ALOGV("nl_socket_set_buffer_size successful for user_sock");
    282     }
    283 
    284     struct nl_cb *cb = nl_socket_get_cb(user_sock);
    285     if (cb == NULL) {
    286         ALOGE("Could not get cb");
    287         return WIFI_ERROR_UNKNOWN;
    288     }
    289 
    290     info->user_sock_arg = 1;
    291     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
    292     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
    293     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
    294     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
    295 
    296     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
    297     nl_cb_put(cb);
    298 
    299     int ret = nl_socket_add_membership(user_sock, 1);
    300     if (ret < 0) {
    301         ALOGE("Could not add membership");
    302         return WIFI_ERROR_UNKNOWN;
    303     }
    304 
    305     info->user_sock = user_sock;
    306     ALOGV("Initiialized diag sock successfully");
    307     return WIFI_SUCCESS;
    308 }
    309 
    310 static wifi_error wifi_init_cld80211_sock_cb(hal_info *info)
    311 {
    312     struct nl_cb *cb = nl_socket_get_cb(info->cldctx->sock);
    313     if (cb == NULL) {
    314         ALOGE("Could not get cb");
    315         return WIFI_ERROR_UNKNOWN;
    316     }
    317 
    318     info->user_sock_arg = 1;
    319     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
    320     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &info->user_sock_arg);
    321     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &info->user_sock_arg);
    322     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &info->user_sock_arg);
    323 
    324     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, user_sock_message_handler, info);
    325     nl_cb_put(cb);
    326 
    327     return WIFI_SUCCESS;
    328 }
    329 
    330 
    331 /*initialize function pointer table with Qualcomm HAL API*/
    332 wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {
    333     if (fn == NULL) {
    334         return WIFI_ERROR_UNKNOWN;
    335     }
    336 
    337     fn->wifi_initialize = wifi_initialize;
    338     fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;
    339     fn->wifi_cleanup = wifi_cleanup;
    340     fn->wifi_event_loop = wifi_event_loop;
    341     fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;
    342     fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;
    343     fn->wifi_set_scanning_mac_oui =  wifi_set_scanning_mac_oui;
    344     fn->wifi_get_ifaces = wifi_get_ifaces;
    345     fn->wifi_get_iface_name = wifi_get_iface_name;
    346     fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;
    347     fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;
    348     fn->wifi_start_gscan = wifi_start_gscan;
    349     fn->wifi_stop_gscan = wifi_stop_gscan;
    350     fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;
    351     fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;
    352     fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;
    353     fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;
    354     fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;
    355     fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;
    356     fn->wifi_set_link_stats = wifi_set_link_stats;
    357     fn->wifi_get_link_stats = wifi_get_link_stats;
    358     fn->wifi_clear_link_stats = wifi_clear_link_stats;
    359     fn->wifi_get_valid_channels = wifi_get_valid_channels;
    360     fn->wifi_rtt_range_request = wifi_rtt_range_request;
    361     fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;
    362     fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;
    363     fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;
    364     fn->wifi_enable_responder = wifi_enable_responder;
    365     fn->wifi_disable_responder = wifi_disable_responder;
    366     fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;
    367     fn->wifi_start_logging = wifi_start_logging;
    368     fn->wifi_set_epno_list = wifi_set_epno_list;
    369     fn->wifi_reset_epno_list = wifi_reset_epno_list;
    370     fn->wifi_set_country_code = wifi_set_country_code;
    371     fn->wifi_enable_tdls = wifi_enable_tdls;
    372     fn->wifi_disable_tdls = wifi_disable_tdls;
    373     fn->wifi_get_tdls_status = wifi_get_tdls_status;
    374     fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;
    375     fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;
    376     fn->wifi_set_log_handler = wifi_set_log_handler;
    377     fn->wifi_reset_log_handler = wifi_reset_log_handler;
    378     fn->wifi_set_alert_handler = wifi_set_alert_handler;
    379     fn->wifi_reset_alert_handler = wifi_reset_alert_handler;
    380     fn->wifi_get_firmware_version = wifi_get_firmware_version;
    381     fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;
    382     fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;
    383     fn->wifi_get_ring_data = wifi_get_ring_data;
    384     fn->wifi_get_driver_version = wifi_get_driver_version;
    385     fn->wifi_set_passpoint_list = wifi_set_passpoint_list;
    386     fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;
    387     fn->wifi_set_lci = wifi_set_lci;
    388     fn->wifi_set_lcr = wifi_set_lcr;
    389     fn->wifi_start_sending_offloaded_packet =
    390             wifi_start_sending_offloaded_packet;
    391     fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;
    392     fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;
    393     fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;
    394     fn->wifi_nan_enable_request = nan_enable_request;
    395     fn->wifi_nan_disable_request = nan_disable_request;
    396     fn->wifi_nan_publish_request = nan_publish_request;
    397     fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;
    398     fn->wifi_nan_subscribe_request = nan_subscribe_request;
    399     fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;
    400     fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;
    401     fn->wifi_nan_stats_request = nan_stats_request;
    402     fn->wifi_nan_config_request = nan_config_request;
    403     fn->wifi_nan_tca_request = nan_tca_request;
    404     fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;
    405     fn->wifi_nan_register_handler = nan_register_handler;
    406     fn->wifi_nan_get_version = nan_get_version;
    407     fn->wifi_set_packet_filter = wifi_set_packet_filter;
    408     fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;
    409     fn->wifi_read_packet_filter = wifi_read_packet_filter;
    410     fn->wifi_nan_get_capabilities = nan_get_capabilities;
    411     fn->wifi_nan_data_interface_create = nan_data_interface_create;
    412     fn->wifi_nan_data_interface_delete = nan_data_interface_delete;
    413     fn->wifi_nan_data_request_initiator = nan_data_request_initiator;
    414     fn->wifi_nan_data_indication_response = nan_data_indication_response;
    415     fn->wifi_nan_data_end = nan_data_end;
    416     fn->wifi_configure_nd_offload = wifi_configure_nd_offload;
    417     fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;
    418     fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;
    419     fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;
    420     fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;
    421     fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;
    422     fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;
    423     fn->wifi_configure_roaming = wifi_configure_roaming;
    424     fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;
    425     fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;
    426     fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;
    427     fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;
    428 
    429     return WIFI_SUCCESS;
    430 }
    431 
    432 static void cld80211lib_cleanup(hal_info *info)
    433 {
    434     if (!info->cldctx)
    435         return;
    436     cld80211_remove_mcast_group(info->cldctx, "host_logs");
    437     cld80211_remove_mcast_group(info->cldctx, "fw_logs");
    438     cld80211_remove_mcast_group(info->cldctx, "per_pkt_stats");
    439     cld80211_remove_mcast_group(info->cldctx, "diag_events");
    440     cld80211_remove_mcast_group(info->cldctx, "fatal_events");
    441     exit_cld80211_recv(info->cldctx);
    442     cld80211_deinit(info->cldctx);
    443     info->cldctx = NULL;
    444 }
    445 
    446 static int wifi_get_iface_id(hal_info *info, const char *iface)
    447 {
    448     int i;
    449     for (i = 0; i < info->num_interfaces; i++)
    450         if (!strcmp(info->interfaces[i]->name, iface))
    451             return i;
    452     return -1;
    453 }
    454 
    455 wifi_error wifi_initialize(wifi_handle *handle)
    456 {
    457     int err = 0;
    458     wifi_error ret = WIFI_SUCCESS;
    459     wifi_interface_handle iface_handle;
    460     struct nl_sock *cmd_sock = NULL;
    461     struct nl_sock *event_sock = NULL;
    462     struct nl_cb *cb = NULL;
    463     int status = 0;
    464     int index;
    465 
    466     ALOGI("Initializing wifi");
    467     hal_info *info = (hal_info *)malloc(sizeof(hal_info));
    468     if (info == NULL) {
    469         ALOGE("Could not allocate hal_info");
    470         return WIFI_ERROR_OUT_OF_MEMORY;
    471     }
    472 
    473     memset(info, 0, sizeof(*info));
    474 
    475     cmd_sock = wifi_create_nl_socket(WIFI_HAL_CMD_SOCK_PORT,
    476                                                      NETLINK_GENERIC);
    477     if (cmd_sock == NULL) {
    478         ALOGE("Failed to create command socket port");
    479         ret = WIFI_ERROR_UNKNOWN;
    480         goto unload;
    481     }
    482 
    483     /* Set the socket buffer size */
    484     if (nl_socket_set_buffer_size(cmd_sock, (256*1024), 0) < 0) {
    485         ALOGE("Could not set nl_socket RX buffer size for cmd_sock: %s",
    486                    strerror(errno));
    487         /* continue anyway with the default (smaller) buffer */
    488     }
    489 
    490     event_sock =
    491         wifi_create_nl_socket(WIFI_HAL_EVENT_SOCK_PORT, NETLINK_GENERIC);
    492     if (event_sock == NULL) {
    493         ALOGE("Failed to create event socket port");
    494         ret = WIFI_ERROR_UNKNOWN;
    495         goto unload;
    496     }
    497 
    498     /* Set the socket buffer size */
    499     if (nl_socket_set_buffer_size(event_sock, (256*1024), 0) < 0) {
    500         ALOGE("Could not set nl_socket RX buffer size for event_sock: %s",
    501                    strerror(errno));
    502         /* continue anyway with the default (smaller) buffer */
    503     }
    504 
    505     cb = nl_socket_get_cb(event_sock);
    506     if (cb == NULL) {
    507         ALOGE("Failed to get NL control block for event socket port");
    508         ret = WIFI_ERROR_UNKNOWN;
    509         goto unload;
    510     }
    511 
    512     err = 1;
    513     nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, no_seq_check, NULL);
    514     nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
    515     nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err);
    516     nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
    517 
    518     nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, internal_valid_message_handler,
    519             info);
    520     nl_cb_put(cb);
    521 
    522     info->cmd_sock = cmd_sock;
    523     info->event_sock = event_sock;
    524     info->clean_up = false;
    525     info->in_event_loop = false;
    526 
    527     info->event_cb = (cb_info *)malloc(sizeof(cb_info) * DEFAULT_EVENT_CB_SIZE);
    528     if (info->event_cb == NULL) {
    529         ALOGE("Could not allocate event_cb");
    530         ret = WIFI_ERROR_OUT_OF_MEMORY;
    531         goto unload;
    532     }
    533     info->alloc_event_cb = DEFAULT_EVENT_CB_SIZE;
    534     info->num_event_cb = 0;
    535 
    536     info->nl80211_family_id = genl_ctrl_resolve(cmd_sock, "nl80211");
    537     if (info->nl80211_family_id < 0) {
    538         ALOGE("Could not resolve nl80211 familty id");
    539         ret = WIFI_ERROR_UNKNOWN;
    540         goto unload;
    541     }
    542 
    543     pthread_mutex_init(&info->cb_lock, NULL);
    544     pthread_mutex_init(&info->pkt_fate_stats_lock, NULL);
    545 
    546     *handle = (wifi_handle) info;
    547 
    548     wifi_add_membership(*handle, "scan");
    549     wifi_add_membership(*handle, "mlme");
    550     wifi_add_membership(*handle, "regulatory");
    551     wifi_add_membership(*handle, "vendor");
    552 
    553     info->cldctx = cld80211_init();
    554     if (info->cldctx != NULL) {
    555         info->user_sock = info->cldctx->sock;
    556         ret = wifi_init_cld80211_sock_cb(info);
    557         if (ret != WIFI_SUCCESS) {
    558             ALOGE("Could not set cb for CLD80211 family");
    559             goto cld80211_cleanup;
    560         }
    561 
    562         status = cld80211_add_mcast_group(info->cldctx, "host_logs");
    563         if (status) {
    564             ALOGE("Failed to add mcast group host_logs :%d", status);
    565             goto cld80211_cleanup;
    566         }
    567         status = cld80211_add_mcast_group(info->cldctx, "fw_logs");
    568         if (status) {
    569             ALOGE("Failed to add mcast group fw_logs :%d", status);
    570             goto cld80211_cleanup;
    571         }
    572         status = cld80211_add_mcast_group(info->cldctx, "per_pkt_stats");
    573         if (status) {
    574             ALOGE("Failed to add mcast group per_pkt_stats :%d", status);
    575             goto cld80211_cleanup;
    576         }
    577         status = cld80211_add_mcast_group(info->cldctx, "diag_events");
    578         if (status) {
    579             ALOGE("Failed to add mcast group diag_events :%d", status);
    580             goto cld80211_cleanup;
    581         }
    582         status = cld80211_add_mcast_group(info->cldctx, "fatal_events");
    583         if (status) {
    584             ALOGE("Failed to add mcast group fatal_events :%d", status);
    585             goto cld80211_cleanup;
    586         }
    587     } else {
    588         ret = wifi_init_user_sock(info);
    589         if (ret != WIFI_SUCCESS) {
    590             ALOGE("Failed to alloc user socket");
    591             goto unload;
    592         }
    593     }
    594 
    595     ret = wifi_init_interfaces(*handle);
    596     if (ret != WIFI_SUCCESS) {
    597         ALOGE("Failed to init interfaces");
    598         goto unload;
    599     }
    600 
    601     if (info->num_interfaces == 0) {
    602         ALOGE("No interfaces found");
    603         ret = WIFI_ERROR_UNINITIALIZED;
    604         goto unload;
    605     }
    606 
    607     index = wifi_get_iface_id(info, "wlan0");
    608     if (index == -1) {
    609         int i;
    610         for (i = 0; i < info->num_interfaces; i++)
    611         {
    612             free(info->interfaces[i]);
    613         }
    614         ALOGE("%s no iface with wlan0", __func__);
    615         goto unload;
    616     }
    617     iface_handle = (wifi_interface_handle)info->interfaces[index];
    618 
    619     ret = acquire_supported_features(iface_handle,
    620             &info->supported_feature_set);
    621     if (ret != WIFI_SUCCESS) {
    622         ALOGI("Failed to get supported feature set : %d", ret);
    623         //acquire_supported_features failure is acceptable condition as legacy
    624         //drivers might not support the required vendor command. So, do not
    625         //consider it as failure of wifi_initialize
    626         ret = WIFI_SUCCESS;
    627     }
    628 
    629     ret =  wifi_get_logger_supported_feature_set(iface_handle,
    630                          &info->supported_logger_feature_set);
    631     if (ret != WIFI_SUCCESS)
    632         ALOGE("Failed to get supported logger feature set: %d", ret);
    633 
    634     ret = get_firmware_bus_max_size_supported(iface_handle);
    635     if (ret != WIFI_SUCCESS) {
    636         ALOGE("Failed to get supported bus size, error : %d", ret);
    637         info->firmware_bus_max_size = 1520;
    638     }
    639 
    640     ret = wifi_logger_ring_buffers_init(info);
    641     if (ret != WIFI_SUCCESS)
    642         ALOGE("Wifi Logger Ring Initialization Failed");
    643 
    644     ret = wifi_get_capabilities(iface_handle);
    645     if (ret != WIFI_SUCCESS)
    646         ALOGE("Failed to get wifi Capabilities, error: %d", ret);
    647 
    648     info->pkt_stats = (struct pkt_stats_s *)malloc(sizeof(struct pkt_stats_s));
    649     if (!info->pkt_stats) {
    650         ALOGE("%s: malloc Failed for size: %zu",
    651                 __FUNCTION__, sizeof(struct pkt_stats_s));
    652         ret = WIFI_ERROR_OUT_OF_MEMORY;
    653         goto unload;
    654     }
    655 
    656     info->rx_buf_size_allocated = MAX_RXMPDUS_PER_AMPDU * MAX_MSDUS_PER_MPDU
    657                                   * PKT_STATS_BUF_SIZE;
    658 
    659     info->rx_aggr_pkts =
    660         (wifi_ring_buffer_entry  *)malloc(info->rx_buf_size_allocated);
    661     if (!info->rx_aggr_pkts) {
    662         ALOGE("%s: malloc Failed for size: %d",
    663                 __FUNCTION__, info->rx_buf_size_allocated);
    664         ret = WIFI_ERROR_OUT_OF_MEMORY;
    665         info->rx_buf_size_allocated = 0;
    666         goto unload;
    667     }
    668     memset(info->rx_aggr_pkts, 0, info->rx_buf_size_allocated);
    669 
    670     info->exit_sockets[0] = -1;
    671     info->exit_sockets[1] = -1;
    672 
    673     if (socketpair(AF_UNIX, SOCK_STREAM, 0, info->exit_sockets) == -1) {
    674         ALOGE("Failed to create exit socket pair");
    675         ret = WIFI_ERROR_UNKNOWN;
    676         goto unload;
    677     }
    678 
    679     ALOGV("Initializing Gscan Event Handlers");
    680     ret = initializeGscanHandlers(info);
    681     if (ret != WIFI_SUCCESS) {
    682         ALOGE("Initializing Gscan Event Handlers Failed");
    683         goto unload;
    684     }
    685 
    686     ret = initializeRSSIMonitorHandler(info);
    687     if (ret != WIFI_SUCCESS) {
    688         ALOGE("Initializing RSSI Event Handler Failed");
    689         goto unload;
    690     }
    691 
    692     ALOGV("Initialized Wifi HAL Successfully; vendor cmd = %d Supported"
    693             " features : %x", NL80211_CMD_VENDOR, info->supported_feature_set);
    694 
    695 cld80211_cleanup:
    696     if (status != 0 || ret != WIFI_SUCCESS) {
    697         ret = WIFI_ERROR_UNKNOWN;
    698         cld80211lib_cleanup(info);
    699     }
    700 unload:
    701     if (ret != WIFI_SUCCESS) {
    702         if (cmd_sock)
    703             nl_socket_free(cmd_sock);
    704         if (event_sock)
    705             nl_socket_free(event_sock);
    706         if (info) {
    707             if (info->cldctx) {
    708                 cld80211lib_cleanup(info);
    709             } else if (info->user_sock) {
    710                 nl_socket_free(info->user_sock);
    711             }
    712             if (info->pkt_stats) free(info->pkt_stats);
    713             if (info->rx_aggr_pkts) free(info->rx_aggr_pkts);
    714             wifi_logger_ring_buffers_deinit(info);
    715             cleanupGscanHandlers(info);
    716             cleanupRSSIMonitorHandler(info);
    717             free(info->event_cb);
    718             free(info);
    719         }
    720     }
    721 
    722     return ret;
    723 }
    724 
    725 wifi_error wifi_wait_for_driver_ready(void)
    726 {
    727     // This function will wait to make sure basic client netdev is created
    728     // Function times out after 10 seconds
    729     int count = (POLL_DRIVER_MAX_TIME_MS * 1000) / POLL_DRIVER_DURATION_US;
    730     FILE *fd;
    731 
    732     do {
    733         if ((fd = fopen("/sys/class/net/wlan0", "r")) != NULL) {
    734             fclose(fd);
    735             return WIFI_SUCCESS;
    736         }
    737         usleep(POLL_DRIVER_DURATION_US);
    738     } while(--count > 0);
    739 
    740     ALOGE("Timed out wating on Driver ready ... ");
    741     return WIFI_ERROR_TIMED_OUT;
    742 }
    743 
    744 static int wifi_add_membership(wifi_handle handle, const char *group)
    745 {
    746     hal_info *info = getHalInfo(handle);
    747 
    748     int id = wifi_get_multicast_id(handle, "nl80211", group);
    749     if (id < 0) {
    750         ALOGE("Could not find group %s", group);
    751         return id;
    752     }
    753 
    754     int ret = nl_socket_add_membership(info->event_sock, id);
    755     if (ret < 0) {
    756         ALOGE("Could not add membership to group %s", group);
    757     }
    758 
    759     return ret;
    760 }
    761 
    762 static void internal_cleaned_up_handler(wifi_handle handle)
    763 {
    764     hal_info *info = getHalInfo(handle);
    765     wifi_cleaned_up_handler cleaned_up_handler = info->cleaned_up_handler;
    766 
    767     if (info->cmd_sock != 0) {
    768         nl_socket_free(info->cmd_sock);
    769         nl_socket_free(info->event_sock);
    770         info->cmd_sock = NULL;
    771         info->event_sock = NULL;
    772     }
    773 
    774     if (info->interfaces) {
    775         for (int i = 0; i < info->num_interfaces; i++)
    776             free(info->interfaces[i]);
    777         free(info->interfaces);
    778     }
    779 
    780     if (info->cldctx != NULL) {
    781         cld80211lib_cleanup(info);
    782     } else if (info->user_sock != 0) {
    783         nl_socket_free(info->user_sock);
    784         info->user_sock = NULL;
    785     }
    786 
    787     if (info->pkt_stats)
    788         free(info->pkt_stats);
    789     if (info->rx_aggr_pkts)
    790         free(info->rx_aggr_pkts);
    791     wifi_logger_ring_buffers_deinit(info);
    792     cleanupGscanHandlers(info);
    793     cleanupRSSIMonitorHandler(info);
    794 
    795     if (info->num_event_cb)
    796         ALOGE("%d events were leftover without being freed",
    797               info->num_event_cb);
    798     free(info->event_cb);
    799 
    800     if (info->exit_sockets[0] >= 0) {
    801         close(info->exit_sockets[0]);
    802         info->exit_sockets[0] = -1;
    803     }
    804 
    805     if (info->exit_sockets[1] >= 0) {
    806         close(info->exit_sockets[1]);
    807         info->exit_sockets[1] = -1;
    808     }
    809 
    810     if (info->pkt_fate_stats) {
    811         free(info->pkt_fate_stats);
    812         info->pkt_fate_stats = NULL;
    813     }
    814 
    815     (*cleaned_up_handler)(handle);
    816     pthread_mutex_destroy(&info->cb_lock);
    817     pthread_mutex_destroy(&info->pkt_fate_stats_lock);
    818     free(info);
    819 }
    820 
    821 void wifi_cleanup(wifi_handle handle, wifi_cleaned_up_handler handler)
    822 {
    823     if (!handle) {
    824         ALOGE("Handle is null");
    825         return;
    826     }
    827 
    828     hal_info *info = getHalInfo(handle);
    829     info->cleaned_up_handler = handler;
    830     info->clean_up = true;
    831 
    832     TEMP_FAILURE_RETRY(write(info->exit_sockets[0], "E", 1));
    833     ALOGI("Sent msg on exit sock to unblock poll()");
    834 }
    835 
    836 static int internal_pollin_handler(wifi_handle handle, struct nl_sock *sock)
    837 {
    838     struct nl_cb *cb = nl_socket_get_cb(sock);
    839 
    840     int res = nl_recvmsgs(sock, cb);
    841     if(res)
    842         ALOGE("Error :%d while reading nl msg", res);
    843     nl_cb_put(cb);
    844     return res;
    845 }
    846 
    847 static void internal_event_handler(wifi_handle handle, int events,
    848                                    struct nl_sock *sock)
    849 {
    850     if (events & POLLERR) {
    851         ALOGE("Error reading from socket");
    852         internal_pollin_handler(handle, sock);
    853     } else if (events & POLLHUP) {
    854         ALOGE("Remote side hung up");
    855     } else if (events & POLLIN) {
    856         //ALOGI("Found some events!!!");
    857         internal_pollin_handler(handle, sock);
    858     } else {
    859         ALOGE("Unknown event - %0x", events);
    860     }
    861 }
    862 
    863 /* Run event handler */
    864 void wifi_event_loop(wifi_handle handle)
    865 {
    866     hal_info *info = getHalInfo(handle);
    867     if (info->in_event_loop) {
    868         return;
    869     } else {
    870         info->in_event_loop = true;
    871     }
    872 
    873     pollfd pfd[3];
    874     memset(&pfd, 0, 3*sizeof(pfd[0]));
    875 
    876     pfd[0].fd = nl_socket_get_fd(info->event_sock);
    877     pfd[0].events = POLLIN;
    878 
    879     pfd[1].fd = nl_socket_get_fd(info->user_sock);
    880     pfd[1].events = POLLIN;
    881 
    882     pfd[2].fd = info->exit_sockets[1];
    883     pfd[2].events = POLLIN;
    884 
    885     /* TODO: Add support for timeouts */
    886 
    887     do {
    888         pfd[0].revents = 0;
    889         pfd[1].revents = 0;
    890         pfd[2].revents = 0;
    891         //ALOGI("Polling sockets");
    892         int result = poll(pfd, 3, -1);
    893         if (result < 0) {
    894             ALOGE("Error polling socket");
    895         } else {
    896             if (pfd[0].revents & (POLLIN | POLLHUP | POLLERR)) {
    897                 internal_event_handler(handle, pfd[0].revents, info->event_sock);
    898             }
    899             if (pfd[1].revents & (POLLIN | POLLHUP | POLLERR)) {
    900                 internal_event_handler(handle, pfd[1].revents, info->user_sock);
    901             }
    902         }
    903         rb_timerhandler(info);
    904     } while (!info->clean_up);
    905     internal_cleaned_up_handler(handle);
    906 }
    907 
    908 static int user_sock_message_handler(nl_msg *msg, void *arg)
    909 {
    910     wifi_handle handle = (wifi_handle)arg;
    911     hal_info *info = getHalInfo(handle);
    912 
    913     diag_message_handler(info, msg);
    914 
    915     return NL_OK;
    916 }
    917 
    918 static int internal_valid_message_handler(nl_msg *msg, void *arg)
    919 {
    920     wifi_handle handle = (wifi_handle)arg;
    921     hal_info *info = getHalInfo(handle);
    922 
    923     WifiEvent event(msg);
    924     int res = event.parse();
    925     if (res < 0) {
    926         ALOGE("Failed to parse event: %d", res);
    927         return NL_SKIP;
    928     }
    929 
    930     int cmd = event.get_cmd();
    931     uint32_t vendor_id = 0;
    932     int subcmd = 0;
    933 
    934     if (cmd == NL80211_CMD_VENDOR) {
    935         vendor_id = event.get_u32(NL80211_ATTR_VENDOR_ID);
    936         subcmd = event.get_u32(NL80211_ATTR_VENDOR_SUBCMD);
    937         /* Restrict printing GSCAN_FULL_RESULT which is causing lot
    938            of logs in bug report */
    939         if (subcmd != QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) {
    940             ALOGI("event received %s, vendor_id = 0x%0x, subcmd = 0x%0x",
    941                   event.get_cmdString(), vendor_id, subcmd);
    942         }
    943     } else {
    944         ALOGV("event received %s", event.get_cmdString());
    945     }
    946 
    947     // event.log();
    948 
    949     bool dispatched = false;
    950 
    951     pthread_mutex_lock(&info->cb_lock);
    952 
    953     for (int i = 0; i < info->num_event_cb; i++) {
    954         if (cmd == info->event_cb[i].nl_cmd) {
    955             if (cmd == NL80211_CMD_VENDOR
    956                 && ((vendor_id != info->event_cb[i].vendor_id)
    957                 || (subcmd != info->event_cb[i].vendor_subcmd)))
    958             {
    959                 /* event for a different vendor, ignore it */
    960                 continue;
    961             }
    962 
    963             cb_info *cbi = &(info->event_cb[i]);
    964             pthread_mutex_unlock(&info->cb_lock);
    965             if (cbi->cb_func) {
    966                 (*(cbi->cb_func))(msg, cbi->cb_arg);
    967                 dispatched = true;
    968             }
    969             return NL_OK;
    970         }
    971     }
    972 
    973 #ifdef QC_HAL_DEBUG
    974     if (!dispatched) {
    975         ALOGI("event ignored!!");
    976     }
    977 #endif
    978 
    979     pthread_mutex_unlock(&info->cb_lock);
    980     return NL_OK;
    981 }
    982 
    983 ////////////////////////////////////////////////////////////////////////////////
    984 
    985 class GetMulticastIdCommand : public WifiCommand
    986 {
    987 private:
    988     const char *mName;
    989     const char *mGroup;
    990     int   mId;
    991 public:
    992     GetMulticastIdCommand(wifi_handle handle, const char *name,
    993             const char *group) : WifiCommand(handle, 0)
    994     {
    995         mName = name;
    996         mGroup = group;
    997         mId = -1;
    998     }
    999 
   1000     int getId() {
   1001         return mId;
   1002     }
   1003 
   1004     virtual wifi_error create() {
   1005         int nlctrlFamily = genl_ctrl_resolve(mInfo->cmd_sock, "nlctrl");
   1006         // ALOGI("ctrl family = %d", nlctrlFamily);
   1007         wifi_error ret = mMsg.create(nlctrlFamily, CTRL_CMD_GETFAMILY, 0, 0);
   1008         if (ret != WIFI_SUCCESS)
   1009             return ret;
   1010 
   1011         ret = mMsg.put_string(CTRL_ATTR_FAMILY_NAME, mName);
   1012         return ret;
   1013     }
   1014 
   1015     virtual int handleResponse(WifiEvent& reply) {
   1016 
   1017         // ALOGI("handling reponse in %s", __func__);
   1018 
   1019         struct nlattr **tb = reply.attributes();
   1020         struct nlattr *mcgrp = NULL;
   1021         int i;
   1022 
   1023         if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
   1024             ALOGI("No multicast groups found");
   1025             return NL_SKIP;
   1026         } else {
   1027             // ALOGI("Multicast groups attr size = %d",
   1028             // nla_len(tb[CTRL_ATTR_MCAST_GROUPS]));
   1029         }
   1030 
   1031         for_each_attr(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], i) {
   1032 
   1033             // ALOGI("Processing group");
   1034             struct nlattr *tb2[CTRL_ATTR_MCAST_GRP_MAX + 1];
   1035             nla_parse(tb2, CTRL_ATTR_MCAST_GRP_MAX, (nlattr *)nla_data(mcgrp),
   1036                 nla_len(mcgrp), NULL);
   1037             if (!tb2[CTRL_ATTR_MCAST_GRP_NAME] || !tb2[CTRL_ATTR_MCAST_GRP_ID])
   1038             {
   1039                 continue;
   1040             }
   1041 
   1042             char *grpName = (char *)nla_data(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
   1043             int grpNameLen = nla_len(tb2[CTRL_ATTR_MCAST_GRP_NAME]);
   1044 
   1045             // ALOGI("Found group name %s", grpName);
   1046 
   1047             if (strncmp(grpName, mGroup, grpNameLen) != 0)
   1048                 continue;
   1049 
   1050             mId = nla_get_u32(tb2[CTRL_ATTR_MCAST_GRP_ID]);
   1051             break;
   1052         }
   1053 
   1054         return NL_SKIP;
   1055     }
   1056 
   1057 };
   1058 
   1059 static int wifi_get_multicast_id(wifi_handle handle, const char *name,
   1060         const char *group)
   1061 {
   1062     GetMulticastIdCommand cmd(handle, name, group);
   1063     int res = cmd.requestResponse();
   1064     if (res < 0)
   1065         return res;
   1066     else
   1067         return cmd.getId();
   1068 }
   1069 
   1070 /////////////////////////////////////////////////////////////////////////
   1071 
   1072 static bool is_wifi_interface(const char *name)
   1073 {
   1074     if (strncmp(name, "wlan", 4) != 0 && strncmp(name, "p2p", 3) != 0) {
   1075         /* not a wifi interface; ignore it */
   1076         return false;
   1077     } else {
   1078         return true;
   1079     }
   1080 }
   1081 
   1082 static int get_interface(const char *name, interface_info *info)
   1083 {
   1084     strlcpy(info->name, name, (IFNAMSIZ + 1));
   1085     info->id = if_nametoindex(name);
   1086     // ALOGI("found an interface : %s, id = %d", name, info->id);
   1087     return WIFI_SUCCESS;
   1088 }
   1089 
   1090 wifi_error wifi_init_interfaces(wifi_handle handle)
   1091 {
   1092     hal_info *info = (hal_info *)handle;
   1093 
   1094     struct dirent *de;
   1095 
   1096     DIR *d = opendir("/sys/class/net");
   1097     if (d == 0)
   1098         return WIFI_ERROR_UNKNOWN;
   1099 
   1100     int n = 0;
   1101     while ((de = readdir(d))) {
   1102         if (de->d_name[0] == '.')
   1103             continue;
   1104         if (is_wifi_interface(de->d_name) ) {
   1105             n++;
   1106         }
   1107     }
   1108 
   1109     closedir(d);
   1110 
   1111     d = opendir("/sys/class/net");
   1112     if (d == 0)
   1113         return WIFI_ERROR_UNKNOWN;
   1114 
   1115     info->interfaces = (interface_info **)malloc(sizeof(interface_info *) * n);
   1116     if (info->interfaces == NULL) {
   1117         ALOGE("%s: Error info->interfaces NULL", __func__);
   1118         return WIFI_ERROR_OUT_OF_MEMORY;
   1119     }
   1120 
   1121     int i = 0;
   1122     while ((de = readdir(d))) {
   1123         if (de->d_name[0] == '.')
   1124             continue;
   1125         if (is_wifi_interface(de->d_name)) {
   1126             interface_info *ifinfo
   1127                 = (interface_info *)malloc(sizeof(interface_info));
   1128             if (ifinfo == NULL) {
   1129                 ALOGE("%s: Error ifinfo NULL", __func__);
   1130                 while (i > 0) {
   1131                     free(info->interfaces[i-1]);
   1132                     i--;
   1133                 }
   1134                 free(info->interfaces);
   1135                 return WIFI_ERROR_OUT_OF_MEMORY;
   1136             }
   1137             if (get_interface(de->d_name, ifinfo) != WIFI_SUCCESS) {
   1138                 free(ifinfo);
   1139                 continue;
   1140             }
   1141             ifinfo->handle = handle;
   1142             info->interfaces[i] = ifinfo;
   1143             i++;
   1144         }
   1145     }
   1146 
   1147     closedir(d);
   1148 
   1149     info->num_interfaces = n;
   1150 
   1151     return WIFI_SUCCESS;
   1152 }
   1153 
   1154 wifi_error wifi_get_ifaces(wifi_handle handle, int *num,
   1155         wifi_interface_handle **interfaces)
   1156 {
   1157     hal_info *info = (hal_info *)handle;
   1158 
   1159     *interfaces = (wifi_interface_handle *)info->interfaces;
   1160     *num = info->num_interfaces;
   1161 
   1162     return WIFI_SUCCESS;
   1163 }
   1164 
   1165 wifi_error wifi_get_iface_name(wifi_interface_handle handle, char *name,
   1166         size_t size)
   1167 {
   1168     interface_info *info = (interface_info *)handle;
   1169     strlcpy(name, info->name, size);
   1170     return WIFI_SUCCESS;
   1171 }
   1172 
   1173 /* Get the supported Feature set */
   1174 wifi_error wifi_get_supported_feature_set(wifi_interface_handle iface,
   1175         feature_set *set)
   1176 {
   1177     int ret = 0;
   1178     wifi_handle handle = getWifiHandle(iface);
   1179     *set = 0;
   1180     hal_info *info = getHalInfo(handle);
   1181 
   1182     ret = acquire_supported_features(iface, set);
   1183     if (ret != WIFI_SUCCESS) {
   1184         *set = info->supported_feature_set;
   1185         ALOGV("Supported feature set acquired at initialization : %x", *set);
   1186     } else {
   1187         info->supported_feature_set = *set;
   1188         ALOGV("Supported feature set acquired : %x", *set);
   1189     }
   1190     return WIFI_SUCCESS;
   1191 }
   1192 
   1193 wifi_error wifi_get_concurrency_matrix(wifi_interface_handle handle,
   1194                                        int set_size_max,
   1195                                        feature_set set[], int *set_size)
   1196 {
   1197     wifi_error ret;
   1198     struct nlattr *nlData;
   1199     WifihalGeneric *vCommand = NULL;
   1200     interface_info *ifaceInfo = getIfaceInfo(handle);
   1201     wifi_handle wifiHandle = getWifiHandle(handle);
   1202 
   1203     if (set == NULL) {
   1204         ALOGE("%s: NULL set pointer provided. Exit.",
   1205             __func__);
   1206         return WIFI_ERROR_INVALID_ARGS;
   1207     }
   1208 
   1209     vCommand = new WifihalGeneric(wifiHandle, 0,
   1210             OUI_QCA,
   1211             QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX);
   1212     if (vCommand == NULL) {
   1213         ALOGE("%s: Error vCommand NULL", __func__);
   1214         return WIFI_ERROR_OUT_OF_MEMORY;
   1215     }
   1216 
   1217     /* Create the message */
   1218     ret = vCommand->create();
   1219     if (ret != WIFI_SUCCESS)
   1220         goto cleanup;
   1221 
   1222     ret = vCommand->set_iface_id(ifaceInfo->name);
   1223     if (ret != WIFI_SUCCESS)
   1224         goto cleanup;
   1225 
   1226     /* Add the vendor specific attributes for the NL command. */
   1227     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1228     if (!nlData)
   1229         goto cleanup;
   1230 
   1231     ret = vCommand->put_u32(
   1232           QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_CONFIG_PARAM_SET_SIZE_MAX,
   1233           set_size_max);
   1234     if (ret != WIFI_SUCCESS)
   1235         goto cleanup;
   1236 
   1237     vCommand->attr_end(nlData);
   1238 
   1239     /* Populate the input received from caller/framework. */
   1240     vCommand->setMaxSetSize(set_size_max);
   1241     vCommand->setSizePtr(set_size);
   1242     vCommand->setConcurrencySet(set);
   1243 
   1244     ret = vCommand->requestResponse();
   1245     if (ret != WIFI_SUCCESS)
   1246         ALOGE("%s: requestResponse() error: %d", __func__, ret);
   1247 
   1248 cleanup:
   1249     delete vCommand;
   1250     if (ret)
   1251         *set_size = 0;
   1252     return ret;
   1253 }
   1254 
   1255 
   1256 wifi_error wifi_set_nodfs_flag(wifi_interface_handle handle, u32 nodfs)
   1257 {
   1258     wifi_error ret;
   1259     struct nlattr *nlData;
   1260     WifiVendorCommand *vCommand = NULL;
   1261     interface_info *ifaceInfo = getIfaceInfo(handle);
   1262     wifi_handle wifiHandle = getWifiHandle(handle);
   1263 
   1264     vCommand = new WifiVendorCommand(wifiHandle, 0,
   1265             OUI_QCA,
   1266             QCA_NL80211_VENDOR_SUBCMD_NO_DFS_FLAG);
   1267     if (vCommand == NULL) {
   1268         ALOGE("%s: Error vCommand NULL", __func__);
   1269         return WIFI_ERROR_OUT_OF_MEMORY;
   1270     }
   1271 
   1272     /* Create the message */
   1273     ret = vCommand->create();
   1274     if (ret != WIFI_SUCCESS)
   1275         goto cleanup;
   1276 
   1277     ret = vCommand->set_iface_id(ifaceInfo->name);
   1278     if (ret != WIFI_SUCCESS)
   1279         goto cleanup;
   1280 
   1281     /* Add the vendor specific attributes for the NL command. */
   1282     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1283     if (!nlData)
   1284         goto cleanup;
   1285 
   1286     /* Add the fixed part of the mac_oui to the nl command */
   1287     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_SET_NO_DFS_FLAG, nodfs);
   1288     if (ret != WIFI_SUCCESS)
   1289         goto cleanup;
   1290 
   1291     vCommand->attr_end(nlData);
   1292 
   1293     ret = vCommand->requestResponse();
   1294     /* Don't check response since we aren't expecting one */
   1295 
   1296 cleanup:
   1297     delete vCommand;
   1298     return ret;
   1299 }
   1300 
   1301 wifi_error wifi_start_sending_offloaded_packet(wifi_request_id id,
   1302                                                wifi_interface_handle iface,
   1303                                                u8 *ip_packet,
   1304                                                u16 ip_packet_len,
   1305                                                u8 *src_mac_addr,
   1306                                                u8 *dst_mac_addr,
   1307                                                u32 period_msec)
   1308 {
   1309     wifi_error ret;
   1310     struct nlattr *nlData;
   1311     WifiVendorCommand *vCommand = NULL;
   1312 
   1313     ret = initialize_vendor_cmd(iface, id,
   1314                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
   1315                                 &vCommand);
   1316     if (ret != WIFI_SUCCESS) {
   1317         ALOGE("%s: Initialization failed", __func__);
   1318         return ret;
   1319     }
   1320 
   1321     ALOGV("ip packet length : %u\nIP Packet:", ip_packet_len);
   1322     hexdump(ip_packet, ip_packet_len);
   1323     ALOGV("Src Mac Address: " MAC_ADDR_STR "\nDst Mac Address: " MAC_ADDR_STR
   1324           "\nPeriod in msec : %u", MAC_ADDR_ARRAY(src_mac_addr),
   1325           MAC_ADDR_ARRAY(dst_mac_addr), period_msec);
   1326 
   1327     /* Add the vendor specific attributes for the NL command. */
   1328     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1329     if (!nlData)
   1330         goto cleanup;
   1331 
   1332     ret = vCommand->put_u32(
   1333             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
   1334             QCA_WLAN_OFFLOADED_PACKETS_SENDING_START);
   1335     if (ret != WIFI_SUCCESS)
   1336         goto cleanup;
   1337 
   1338     ret = vCommand->put_u32(
   1339             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
   1340             id);
   1341     if (ret != WIFI_SUCCESS)
   1342         goto cleanup;
   1343 
   1344     ret = vCommand->put_bytes(
   1345             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_IP_PACKET,
   1346             (const char *)ip_packet, ip_packet_len);
   1347     if (ret != WIFI_SUCCESS)
   1348         goto cleanup;
   1349 
   1350     ret = vCommand->put_addr(
   1351             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SRC_MAC_ADDR,
   1352             src_mac_addr);
   1353     if (ret != WIFI_SUCCESS)
   1354         goto cleanup;
   1355 
   1356     ret = vCommand->put_addr(
   1357             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_DST_MAC_ADDR,
   1358             dst_mac_addr);
   1359     if (ret != WIFI_SUCCESS)
   1360         goto cleanup;
   1361 
   1362     ret = vCommand->put_u32(
   1363             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_PERIOD,
   1364             period_msec);
   1365     if (ret != WIFI_SUCCESS)
   1366         goto cleanup;
   1367 
   1368     vCommand->attr_end(nlData);
   1369 
   1370     ret = vCommand->requestResponse();
   1371     if (ret != WIFI_SUCCESS)
   1372         goto cleanup;
   1373 
   1374 cleanup:
   1375     delete vCommand;
   1376     return ret;
   1377 }
   1378 
   1379 wifi_error wifi_stop_sending_offloaded_packet(wifi_request_id id,
   1380                                               wifi_interface_handle iface)
   1381 {
   1382     wifi_error ret;
   1383     struct nlattr *nlData;
   1384     WifiVendorCommand *vCommand = NULL;
   1385 
   1386     ret = initialize_vendor_cmd(iface, id,
   1387                                 QCA_NL80211_VENDOR_SUBCMD_OFFLOADED_PACKETS,
   1388                                 &vCommand);
   1389     if (ret != WIFI_SUCCESS) {
   1390         ALOGE("%s: Initialization failed", __func__);
   1391         return ret;
   1392     }
   1393 
   1394     /* Add the vendor specific attributes for the NL command. */
   1395     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1396     if (!nlData)
   1397         goto cleanup;
   1398 
   1399     ret = vCommand->put_u32(
   1400             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_SENDING_CONTROL,
   1401             QCA_WLAN_OFFLOADED_PACKETS_SENDING_STOP);
   1402     if (ret != WIFI_SUCCESS)
   1403         goto cleanup;
   1404 
   1405     ret = vCommand->put_u32(
   1406             QCA_WLAN_VENDOR_ATTR_OFFLOADED_PACKETS_REQUEST_ID,
   1407             id);
   1408     if (ret != WIFI_SUCCESS)
   1409         goto cleanup;
   1410 
   1411     vCommand->attr_end(nlData);
   1412 
   1413     ret = vCommand->requestResponse();
   1414     if (ret != WIFI_SUCCESS)
   1415         goto cleanup;
   1416 
   1417 cleanup:
   1418     delete vCommand;
   1419     return ret;
   1420 }
   1421 
   1422 static wifi_error wifi_set_packet_filter(wifi_interface_handle iface,
   1423                                          const u8 *program, u32 len)
   1424 {
   1425     wifi_error ret;
   1426     struct nlattr *nlData;
   1427     WifiVendorCommand *vCommand = NULL;
   1428     u32 current_offset = 0;
   1429     wifi_handle wifiHandle = getWifiHandle(iface);
   1430     hal_info *info = getHalInfo(wifiHandle);
   1431 
   1432     /* len=0 clears the filters in driver/firmware */
   1433     if (len != 0 && program == NULL) {
   1434         ALOGE("%s: No valid program provided. Exit.",
   1435             __func__);
   1436         return WIFI_ERROR_INVALID_ARGS;
   1437     }
   1438 
   1439     do {
   1440         ret = initialize_vendor_cmd(iface, get_requestid(),
   1441                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
   1442                                     &vCommand);
   1443         if (ret != WIFI_SUCCESS) {
   1444             ALOGE("%s: Initialization failed", __FUNCTION__);
   1445             return ret;
   1446         }
   1447 
   1448         /* Add the vendor specific attributes for the NL command. */
   1449         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1450         if (!nlData)
   1451             goto cleanup;
   1452 
   1453         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
   1454                                 QCA_WLAN_SET_PACKET_FILTER);
   1455         if (ret != WIFI_SUCCESS)
   1456             goto cleanup;
   1457         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
   1458                                 PACKET_FILTER_ID);
   1459         if (ret != WIFI_SUCCESS)
   1460             goto cleanup;
   1461         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
   1462                                 len);
   1463         if (ret != WIFI_SUCCESS)
   1464             goto cleanup;
   1465         ret = vCommand->put_u32(
   1466                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
   1467                             current_offset);
   1468         if (ret != WIFI_SUCCESS)
   1469             goto cleanup;
   1470 
   1471         if (len) {
   1472             ret = vCommand->put_bytes(
   1473                                      QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
   1474                                      (char *)&program[current_offset],
   1475                                      min(info->firmware_bus_max_size,
   1476                                      len-current_offset));
   1477             if (ret!= WIFI_SUCCESS) {
   1478                 ALOGE("%s: failed to put program", __FUNCTION__);
   1479                 goto cleanup;
   1480             }
   1481         }
   1482 
   1483         vCommand->attr_end(nlData);
   1484 
   1485         ret = vCommand->requestResponse();
   1486         if (ret != WIFI_SUCCESS) {
   1487             ALOGE("%s: requestResponse Error:%d",__func__, ret);
   1488             goto cleanup;
   1489         }
   1490 
   1491         /* destroy the object after sending each fragment to driver */
   1492         delete vCommand;
   1493         vCommand = NULL;
   1494 
   1495         current_offset += min(info->firmware_bus_max_size, len);
   1496     } while (current_offset < len);
   1497 
   1498     info->apf_enabled = !!len;
   1499 
   1500 cleanup:
   1501     if (vCommand)
   1502         delete vCommand;
   1503     return ret;
   1504 }
   1505 
   1506 static wifi_error wifi_get_packet_filter_capabilities(
   1507                 wifi_interface_handle handle, u32 *version, u32 *max_len)
   1508 {
   1509     wifi_error ret;
   1510     struct nlattr *nlData;
   1511     WifihalGeneric *vCommand = NULL;
   1512     interface_info *ifaceInfo = getIfaceInfo(handle);
   1513     wifi_handle wifiHandle = getWifiHandle(handle);
   1514 
   1515     if (version == NULL || max_len == NULL) {
   1516         ALOGE("%s: NULL version/max_len pointer provided. Exit.",
   1517             __FUNCTION__);
   1518         return WIFI_ERROR_INVALID_ARGS;
   1519     }
   1520 
   1521     vCommand = new WifihalGeneric(wifiHandle, 0,
   1522             OUI_QCA,
   1523             QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
   1524     if (vCommand == NULL) {
   1525         ALOGE("%s: Error vCommand NULL", __FUNCTION__);
   1526         return WIFI_ERROR_OUT_OF_MEMORY;
   1527     }
   1528 
   1529     /* Create the message */
   1530     ret = vCommand->create();
   1531     if (ret != WIFI_SUCCESS)
   1532         goto cleanup;
   1533 
   1534     ret = vCommand->set_iface_id(ifaceInfo->name);
   1535     if (ret != WIFI_SUCCESS)
   1536         goto cleanup;
   1537 
   1538     /* Add the vendor specific attributes for the NL command. */
   1539     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1540     if (!nlData)
   1541         goto cleanup;
   1542 
   1543     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
   1544                             QCA_WLAN_GET_PACKET_FILTER_SIZE);
   1545     if (ret != WIFI_SUCCESS)
   1546         goto cleanup;
   1547 
   1548     vCommand->attr_end(nlData);
   1549 
   1550     ret = vCommand->requestResponse();
   1551     if (ret != WIFI_SUCCESS) {
   1552         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
   1553         if (ret == WIFI_ERROR_NOT_SUPPORTED) {
   1554             /* Packet filtering is not supported currently, so return version
   1555              * and length as 0
   1556              */
   1557             ALOGI("Packet filtering is not supprted");
   1558             *version = 0;
   1559             *max_len = 0;
   1560             ret = WIFI_SUCCESS;
   1561         }
   1562         goto cleanup;
   1563     }
   1564 
   1565     *version = vCommand->getFilterVersion();
   1566     *max_len = vCommand->getFilterLength();
   1567 cleanup:
   1568     delete vCommand;
   1569     return ret;
   1570 }
   1571 
   1572 
   1573 static wifi_error wifi_configure_nd_offload(wifi_interface_handle iface,
   1574                                             u8 enable)
   1575 {
   1576     wifi_error ret;
   1577     struct nlattr *nlData;
   1578     WifiVendorCommand *vCommand = NULL;
   1579 
   1580     ret = initialize_vendor_cmd(iface, get_requestid(),
   1581                                 QCA_NL80211_VENDOR_SUBCMD_ND_OFFLOAD,
   1582                                 &vCommand);
   1583     if (ret != WIFI_SUCCESS) {
   1584         ALOGE("%s: Initialization failed", __func__);
   1585         return ret;
   1586     }
   1587 
   1588     ALOGV("ND offload : %s", enable?"Enable":"Disable");
   1589 
   1590     /* Add the vendor specific attributes for the NL command. */
   1591     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1592     if (!nlData)
   1593         goto cleanup;
   1594 
   1595     ret = vCommand->put_u8(QCA_WLAN_VENDOR_ATTR_ND_OFFLOAD_FLAG, enable);
   1596     if (ret != WIFI_SUCCESS)
   1597         goto cleanup;
   1598 
   1599     vCommand->attr_end(nlData);
   1600 
   1601     ret = vCommand->requestResponse();
   1602 
   1603 cleanup:
   1604     delete vCommand;
   1605     return ret;
   1606 }
   1607 
   1608 /**
   1609  * Copy 'len' bytes of raw data from host memory at source address 'program'
   1610  * to APF (Android Packet Filter) working memory starting at offset 'dst_offset'.
   1611  * The size of the program lenght passed to the interpreter is set to
   1612  * 'progaram_lenght'
   1613  *
   1614  * The implementation is allowed to tranlate this wrtie into a series of smaller
   1615  * writes,but this function is not allowed to return untill all write operations
   1616  * have been completed
   1617  * additionally visible memory not targeted by this function must remain
   1618  * unchanged
   1619 
   1620  * @param dst_offset write offset in bytes relative to the beginning of the APF
   1621  * working memory with logical address 0X000. Must be a multiple of 4
   1622  *
   1623  * @param program host memory to copy bytes from. Must be 4B aligned
   1624  *
   1625  * @param len the number of bytes to copy from the bost into the APF working
   1626  * memory
   1627  *
   1628  * @param program_length new length of the program instructions in bytes to pass
   1629  * to the interpreter
   1630  */
   1631 
   1632 wifi_error wifi_write_packet_filter(wifi_interface_handle iface,
   1633                                          u32 dst_offset, const u8 *program,
   1634                                          u32 len, u32 program_length)
   1635 {
   1636     wifi_error ret;
   1637     struct nlattr *nlData;
   1638     WifiVendorCommand *vCommand = NULL;
   1639     u32 current_offset = 0;
   1640     wifi_handle wifiHandle = getWifiHandle(iface);
   1641     hal_info *info = getHalInfo(wifiHandle);
   1642 
   1643     /* len=0 clears the filters in driver/firmware */
   1644     if (len != 0 && program == NULL) {
   1645         ALOGE("%s: No valid program provided. Exit.",
   1646             __func__);
   1647         return WIFI_ERROR_INVALID_ARGS;
   1648     }
   1649 
   1650     do {
   1651         ret = initialize_vendor_cmd(iface, get_requestid(),
   1652                                     QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
   1653                                     &vCommand);
   1654         if (ret != WIFI_SUCCESS) {
   1655             ALOGE("%s: Initialization failed", __FUNCTION__);
   1656             return ret;
   1657         }
   1658 
   1659         /* Add the vendor specific attributes for the NL command. */
   1660         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1661         if (!nlData)
   1662              goto cleanup;
   1663 
   1664         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
   1665                                  QCA_WLAN_WRITE_PACKET_FILTER);
   1666         if (ret != WIFI_SUCCESS)
   1667             goto cleanup;
   1668         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_ID,
   1669                                 PACKET_FILTER_ID);
   1670         if (ret != WIFI_SUCCESS)
   1671             goto cleanup;
   1672         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
   1673                                 len);
   1674         if (ret != WIFI_SUCCESS)
   1675             goto cleanup;
   1676         ret = vCommand->put_u32(
   1677                             QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
   1678                             dst_offset + current_offset);
   1679         if (ret != WIFI_SUCCESS)
   1680             goto cleanup;
   1681         ret = vCommand->put_u32(
   1682                            QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROG_LENGTH,
   1683                             program_length);
   1684         if (ret != WIFI_SUCCESS)
   1685             goto cleanup;
   1686 
   1687         ret = vCommand->put_bytes(
   1688                                  QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM,
   1689                                  (char *)&program[current_offset],
   1690                                  min(info->firmware_bus_max_size,
   1691                                  len - current_offset));
   1692         if (ret!= WIFI_SUCCESS) {
   1693             ALOGE("%s: failed to put program", __FUNCTION__);
   1694             goto cleanup;
   1695         }
   1696 
   1697         vCommand->attr_end(nlData);
   1698 
   1699         ret = vCommand->requestResponse();
   1700        if (ret != WIFI_SUCCESS) {
   1701             ALOGE("%s: requestResponse Error:%d",__func__, ret);
   1702             goto cleanup;
   1703         }
   1704 
   1705         /* destroy the object after sending each fragment to driver */
   1706         delete vCommand;
   1707         vCommand = NULL;
   1708 
   1709         current_offset += min(info->firmware_bus_max_size,
   1710                                          len - current_offset);
   1711     } while (current_offset < len);
   1712 
   1713 cleanup:
   1714     if (vCommand)
   1715         delete vCommand;
   1716     return ret;
   1717 }
   1718 
   1719 wifi_error wifi_enable_packet_filter(wifi_interface_handle handle,
   1720                                         u32 enable)
   1721 {
   1722     wifi_error ret;
   1723     struct nlattr *nlData;
   1724     WifiVendorCommand *vCommand = NULL;
   1725     u32 subcmd;
   1726     wifi_handle wifiHandle = getWifiHandle(handle);
   1727     hal_info *info = getHalInfo(wifiHandle);
   1728 
   1729     ret = initialize_vendor_cmd(handle, get_requestid(),
   1730                                 QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER,
   1731                                 &vCommand);
   1732 
   1733     if (ret != WIFI_SUCCESS) {
   1734         ALOGE("%s: Initialization failed", __func__);
   1735         return ret;
   1736     }
   1737     /* Add the vendor specific attributes for the NL command. */
   1738     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1739     if (!nlData)
   1740         goto cleanup;
   1741 
   1742     subcmd = enable ? QCA_WLAN_ENABLE_PACKET_FILTER :
   1743                       QCA_WLAN_DISABLE_PACKET_FILTER;
   1744     ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
   1745                             subcmd);
   1746     if (ret != WIFI_SUCCESS)
   1747             goto cleanup;
   1748 
   1749     vCommand->attr_end(nlData);
   1750     ret = vCommand->requestResponse();
   1751 
   1752     if (ret != WIFI_SUCCESS) {
   1753         ALOGE("%s: requestResponse() error: %d", __FUNCTION__, ret);
   1754         goto cleanup;
   1755     }
   1756 
   1757     info->apf_enabled = !!enable;
   1758 
   1759 cleanup:
   1760     if (vCommand)
   1761         delete vCommand;
   1762     return ret;
   1763 
   1764 }
   1765 
   1766 /**
   1767  * Copy 'length' bytes of raw data from APF (Android Packet Filter) working
   1768  * memory  to host memory starting at offset src_offset into host memory
   1769  * pointed to by host_dst.
   1770  * Memory can be text, data or some combination of the two. The implementiion is
   1771  * allowed to translate this read into a series of smaller reads, but this
   1772  * function is not allowed to return untill all the reads operations
   1773  * into host_dst have been completed.
   1774  *
   1775  * @param src_offset offset in bytes of destination memory within APF working
   1776  * memory
   1777  *
   1778  * @param host_dst host memory to copy into. Must be 4B aligned.
   1779  *
   1780  * @param length the number of bytes to copy from the APF working memory to the
   1781  * host.
   1782  */
   1783 
   1784 static wifi_error wifi_read_packet_filter(wifi_interface_handle handle,
   1785                                           u32 src_offset, u8 *host_dst, u32 length)
   1786 {
   1787     wifi_error ret;
   1788     struct nlattr *nlData;
   1789     WifihalGeneric *vCommand = NULL;
   1790     interface_info *ifaceInfo = getIfaceInfo(handle);
   1791     wifi_handle wifiHandle = getWifiHandle(handle);
   1792     hal_info *info = getHalInfo(wifiHandle);
   1793 
   1794     /*Temporary varibles to support the read complete length in chunks */
   1795     u8 *temp_host_dst;
   1796     u32 remainingLengthToBeRead, currentLength;
   1797     u8 apf_locally_disabled = 0;
   1798 
   1799     /*Initializing the temporary variables*/
   1800     temp_host_dst = host_dst;
   1801     remainingLengthToBeRead = length;
   1802 
   1803     if (info->apf_enabled) {
   1804         /* Disable APF only when not disabled by framework before calling
   1805          * wifi_read_packet_filter()
   1806          */
   1807         ret = wifi_enable_packet_filter(handle, 0);
   1808         if (ret != WIFI_SUCCESS) {
   1809             ALOGE("%s: Failed to disable APF", __FUNCTION__);
   1810             return ret;
   1811         }
   1812         apf_locally_disabled = 1;
   1813     }
   1814     /**
   1815      * Read the complete length in chunks of size less or equal to firmware bus
   1816      * max size
   1817      */
   1818     while (remainingLengthToBeRead)
   1819     {
   1820         vCommand = new WifihalGeneric(wifiHandle, 0, OUI_QCA,
   1821                                       QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER);
   1822 
   1823         if (vCommand == NULL) {
   1824             ALOGE("%s: Error vCommand NULL", __FUNCTION__);
   1825             ret = WIFI_ERROR_OUT_OF_MEMORY;
   1826             break;
   1827         }
   1828 
   1829         /* Create the message */
   1830         ret = vCommand->create();
   1831         if (ret != WIFI_SUCCESS)
   1832             break;
   1833         ret = vCommand->set_iface_id(ifaceInfo->name);
   1834         if (ret != WIFI_SUCCESS)
   1835             break;
   1836         /* Add the vendor specific attributes for the NL command. */
   1837         nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
   1838         if (!nlData)
   1839             break;
   1840         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD,
   1841                                 QCA_WLAN_READ_PACKET_FILTER);
   1842         if (ret != WIFI_SUCCESS)
   1843             break;
   1844 
   1845         currentLength = min(remainingLengthToBeRead, info->firmware_bus_max_size);
   1846 
   1847         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH,
   1848                                 currentLength);
   1849         if (ret != WIFI_SUCCESS)
   1850             break;
   1851         ret = vCommand->put_u32(QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_CURRENT_OFFSET,
   1852                                 src_offset);
   1853         if (ret != WIFI_SUCCESS)
   1854             break;
   1855 
   1856         vCommand->setPacketBufferParams(temp_host_dst, currentLength);
   1857         vCommand->attr_end(nlData);
   1858         ret = vCommand->requestResponse();
   1859 
   1860         if (ret != WIFI_SUCCESS) {
   1861             ALOGE("%s: requestResponse() error: %d current_len = %u, src_offset = %u",
   1862                   __FUNCTION__, ret, currentLength, src_offset);
   1863             break;
   1864         }
   1865 
   1866         remainingLengthToBeRead -= currentLength;
   1867         temp_host_dst += currentLength;
   1868         src_offset += currentLength;
   1869         delete vCommand;
   1870         vCommand = NULL;
   1871     }
   1872 
   1873     /* Re enable APF only when disabled above within this API */
   1874     if (apf_locally_disabled) {
   1875         wifi_error status;
   1876         status = wifi_enable_packet_filter(handle, 1);
   1877         if (status != WIFI_SUCCESS)
   1878             ALOGE("%s: Failed to enable APF", __FUNCTION__);
   1879         /* Prefer to return read status if read fails */
   1880         if (ret == WIFI_SUCCESS)
   1881             ret = status;
   1882     }
   1883 
   1884     delete vCommand;
   1885     return ret;
   1886 }
   1887