/* Copyright (c) 2014, 2018 The Linux Foundation. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *  * Neither the name of The Linux Foundation nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#define LOG_TAG  "WifiHAL"
#include <cutils/sched_policy.h>
#include <unistd.h>

#include <utils/Log.h>
#include <time.h>

#include "common.h"
#include "cpp_bindings.h"
#include "rtt.h"
#include "wifi_hal.h"
#include "wifihal_internal.h"

/* Implementation of the API functions exposed in rtt.h */
wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
                                     wifi_rtt_capabilities *capabilities)
{
    wifi_error ret;
    lowi_cb_table_t *lowiWifiHalApi = NULL;

    if (iface == NULL) {
        ALOGE("wifi_get_rtt_capabilities: NULL iface pointer provided."
            " Exit.");
        return WIFI_ERROR_INVALID_ARGS;
    }

    if (capabilities == NULL) {
        ALOGE("wifi_get_rtt_capabilities: NULL capabilities pointer provided."
            " Exit.");
        return WIFI_ERROR_INVALID_ARGS;
    }

    /* RTT commands are diverted through LOWI interface. */
    /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
     * LOWI if it isn't up yet.
     */
    lowiWifiHalApi = getLowiCallbackTable(
                ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
    if (lowiWifiHalApi == NULL ||
        lowiWifiHalApi->get_rtt_capabilities == NULL) {
        ALOGE("wifi_get_rtt_capabilities: getLowiCallbackTable returned NULL or "
            "the function pointer is NULL. Exit.");
        return WIFI_ERROR_NOT_SUPPORTED;
    }

    ret = (wifi_error)lowiWifiHalApi->get_rtt_capabilities(iface, capabilities);
    if (ret != WIFI_SUCCESS)
        ALOGE("wifi_get_rtt_capabilities: lowi_wifihal_get_rtt_capabilities "
            "returned error:%d. Exit.", ret);

    return ret;
}

/* API to request RTT measurement */
wifi_error wifi_rtt_range_request(wifi_request_id id,
                                    wifi_interface_handle iface,
                                    unsigned num_rtt_config,
                                    wifi_rtt_config rtt_config[],
                                    wifi_rtt_event_handler handler)
{
    wifi_error ret;
    lowi_cb_table_t *lowiWifiHalApi = NULL;
    hal_info *info = NULL;

    if (iface == NULL) {
        ALOGE("wifi_rtt_range_request: NULL iface pointer provided."
            " Exit.");
        return WIFI_ERROR_INVALID_ARGS;
    }

    wifi_handle wifiHandle = getWifiHandle(iface);
    info = getHalInfo(wifiHandle);
    if (!info)
    {
        ALOGE("%s: hal_info is null ", __FUNCTION__);
        return WIFI_ERROR_INVALID_ARGS;
    }

    if (!(info->supported_feature_set & WIFI_FEATURE_D2AP_RTT)) {
        ALOGE("%s: RTT is not supported by driver", __FUNCTION__);
        return WIFI_ERROR_NOT_SUPPORTED;
    }

    if (rtt_config == NULL) {
        ALOGE("wifi_rtt_range_request: NULL rtt_config pointer provided."
            " Exit.");
        return WIFI_ERROR_INVALID_ARGS;
    }

    if (num_rtt_config <= 0) {
        ALOGE("wifi_rtt_range_request: number of destination BSSIDs to "
            "measure RTT on = 0. Exit.");
        return WIFI_ERROR_INVALID_ARGS;
    }

    if (handler.on_rtt_results == NULL) {
        ALOGE("wifi_rtt_range_request: NULL capabilities pointer provided."
            " Exit.");
        return WIFI_ERROR_INVALID_ARGS;
    }

    /* RTT commands are diverted through LOWI interface. */
    /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
     * LOWI if it isn't up yet.
     */
    lowiWifiHalApi = getLowiCallbackTable(
                    ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
    if (lowiWifiHalApi == NULL ||
        lowiWifiHalApi->rtt_range_request == NULL) {
        ALOGE("wifi_rtt_range_request: getLowiCallbackTable returned NULL or "
            "the function pointer is NULL. Exit.");
        return WIFI_ERROR_NOT_SUPPORTED;
    }

    ret = (wifi_error)lowiWifiHalApi->rtt_range_request(id, iface,
                                                        num_rtt_config,
                                                        rtt_config, handler);
    if (ret != WIFI_SUCCESS)
        ALOGE("wifi_rtt_range_request: lowi_wifihal_rtt_range_request "
            "returned error:%d. Exit.", ret);

    return ret;
}

/* API to cancel RTT measurements */
wifi_error wifi_rtt_range_cancel(wifi_request_id id,
                                   wifi_interface_handle iface,
                                   unsigned num_devices,
                                   mac_addr addr[])
{
    wifi_error ret;
    lowi_cb_table_t *lowiWifiHalApi = NULL;

    if (iface == NULL) {
        ALOGE("wifi_rtt_range_cancel: NULL iface pointer provided."
            " Exit.");
        return WIFI_ERROR_INVALID_ARGS;
    }

    if (addr == NULL) {
        ALOGE("wifi_rtt_range_cancel: NULL addr pointer provided."
            " Exit.");
        return WIFI_ERROR_INVALID_ARGS;
    }

    if (num_devices <= 0) {
        ALOGE("wifi_rtt_range_cancel: number of destination BSSIDs to "
            "measure RTT on = 0. Exit.");
        return WIFI_ERROR_INVALID_ARGS;
    }

    /* RTT commands are diverted through LOWI interface. */
    /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
     * LOWI if it isn't up yet.
     */
    lowiWifiHalApi = getLowiCallbackTable(
                    ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
    if (lowiWifiHalApi == NULL ||
        lowiWifiHalApi->rtt_range_cancel == NULL) {
        ALOGE("wifi_rtt_range_cancel: getLowiCallbackTable returned NULL or "
            "the function pointer is NULL. Exit.");
        return WIFI_ERROR_NOT_SUPPORTED;
    }

    ret = (wifi_error)lowiWifiHalApi->rtt_range_cancel(id, num_devices, addr);
    if (ret != WIFI_SUCCESS)
        ALOGE("wifi_rtt_range_cancel: lowi_wifihal_rtt_range_cancel "
            "returned error:%d. Exit.", ret);

    return ret;
}

// API to configure the LCI. Used in RTT Responder mode only
wifi_error wifi_set_lci(wifi_request_id id, wifi_interface_handle iface,
                        wifi_lci_information *lci)
{
    wifi_error ret;
    lowi_cb_table_t *lowiWifiHalApi = NULL;

    if (iface == NULL) {
        ALOGE("%s: NULL iface pointer provided."
            " Exit.", __FUNCTION__);
        return WIFI_ERROR_INVALID_ARGS;
    }

    if (lci == NULL) {
        ALOGE("%s: NULL lci pointer provided."
            " Exit.", __FUNCTION__);
        return WIFI_ERROR_INVALID_ARGS;
    }

    /* RTT commands are diverted through LOWI interface. */
    /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
     * LOWI if it isn't up yet.
     */
    lowiWifiHalApi = getLowiCallbackTable(
                    ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
    if (lowiWifiHalApi == NULL ||
        lowiWifiHalApi->rtt_set_lci == NULL) {
        ALOGE("%s: getLowiCallbackTable returned NULL or "
            "the function pointer is NULL. Exit.", __FUNCTION__);
        return WIFI_ERROR_NOT_SUPPORTED;
    }

    ret = lowiWifiHalApi->rtt_set_lci(id, iface, lci);
    if (ret != WIFI_SUCCESS)
        ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);

    return ret;
}

// API to configure the LCR. Used in RTT Responder mode only.
wifi_error wifi_set_lcr(wifi_request_id id, wifi_interface_handle iface,
                        wifi_lcr_information *lcr)
{
    wifi_error ret;
    lowi_cb_table_t *lowiWifiHalApi = NULL;

    if (iface == NULL) {
        ALOGE("%s: NULL iface pointer provided."
            " Exit.", __FUNCTION__);
        return WIFI_ERROR_INVALID_ARGS;
    }

    if (lcr == NULL) {
        ALOGE("%s: NULL lcr pointer provided."
            " Exit.", __FUNCTION__);
        return WIFI_ERROR_INVALID_ARGS;
    }

    /* RTT commands are diverted through LOWI interface. */
    /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
     * LOWI if it isn't up yet.
     */
    lowiWifiHalApi = getLowiCallbackTable(
                    ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
    if (lowiWifiHalApi == NULL ||
        lowiWifiHalApi->rtt_set_lcr == NULL) {
        ALOGE("%s: getLowiCallbackTable returned NULL or "
            "the function pointer is NULL. Exit.", __FUNCTION__);
        return WIFI_ERROR_NOT_SUPPORTED;
    }

    ret = lowiWifiHalApi->rtt_set_lcr(id, iface, lcr);
    if (ret != WIFI_SUCCESS)
        ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);

    return ret;
}

/*
 * Get RTT responder information e.g. WiFi channel to enable responder on.
 */
wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface,
                                      wifi_rtt_responder *responder_info)
{
    wifi_error ret;
    lowi_cb_table_t *lowiWifiHalApi = NULL;

    if (iface == NULL || responder_info == NULL) {
        ALOGE("%s: iface : %p responder_info : %p", __FUNCTION__, iface,
               responder_info);
        return WIFI_ERROR_INVALID_ARGS;
    }

    /* Open LOWI dynamic library, retrieve handler to LOWI APIs */
    lowiWifiHalApi = getLowiCallbackTable(
                    ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
    if (lowiWifiHalApi == NULL ||
        lowiWifiHalApi->rtt_get_responder_info == NULL) {
        ALOGE("%s: getLowiCallbackTable returned NULL or "
            "the function pointer is NULL. Exit.", __FUNCTION__);
        return WIFI_ERROR_NOT_SUPPORTED;
    }

    ret = lowiWifiHalApi->rtt_get_responder_info(iface, responder_info);
    if (ret != WIFI_SUCCESS)
        ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);

    return ret;
}

/**
 * Enable RTT responder mode.
 * channel_hint - hint of the channel information where RTT responder should
 *                be enabled on.
 * max_duration_seconds - timeout of responder mode.
 * responder_info - responder information e.g. channel used for RTT responder,
 *                  NULL if responder is not enabled.
 */
wifi_error wifi_enable_responder(wifi_request_id id,
                                 wifi_interface_handle iface,
                                 wifi_channel_info channel_hint,
                                 unsigned max_duration_seconds,
                                 wifi_rtt_responder *responder_info)
{
    wifi_error ret;
    lowi_cb_table_t *lowiWifiHalApi = NULL;

    if (iface == NULL || responder_info == NULL) {
        ALOGE("%s: iface : %p responder_info : %p", __FUNCTION__, iface, responder_info);
        return WIFI_ERROR_INVALID_ARGS;
    }

    /* Open LOWI dynamic library, retrieve handler to LOWI APIs */
    lowiWifiHalApi = getLowiCallbackTable(
                    ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
    if (lowiWifiHalApi == NULL ||
        lowiWifiHalApi->enable_responder == NULL) {
        ALOGE("%s: getLowiCallbackTable returned NULL or "
            "the function pointer is NULL. Exit.", __FUNCTION__);
        return WIFI_ERROR_NOT_SUPPORTED;
    }

    ret = lowiWifiHalApi->enable_responder(id, iface, channel_hint,
                                           max_duration_seconds,
                                           responder_info);
    if (ret != WIFI_SUCCESS)
        ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);

    return ret;
}


/**
 * Disable RTT responder mode.
 */
wifi_error wifi_disable_responder(wifi_request_id id,
                                  wifi_interface_handle iface)

{
    wifi_error ret;
    lowi_cb_table_t *lowiWifiHalApi = NULL;

    if (iface == NULL) {
        ALOGE("%s: iface : %p", __FUNCTION__, iface);
        return WIFI_ERROR_INVALID_ARGS;
    }

    /* Open LOWI dynamic library, retrieve handler to LOWI APIs */
    lowiWifiHalApi = getLowiCallbackTable(
                    ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
    if (lowiWifiHalApi == NULL ||
        lowiWifiHalApi->disable_responder == NULL) {
        ALOGE("%s: getLowiCallbackTable returned NULL or "
            "the function pointer is NULL. Exit.", __FUNCTION__);
        return WIFI_ERROR_NOT_SUPPORTED;
    }

    ret = lowiWifiHalApi->disable_responder(id, iface);
    if (ret != WIFI_SUCCESS)
        ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);

    return ret;
}
