/* Copyright (c) 2014, 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)
{
int ret = WIFI_SUCCESS;
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.");
ret = WIFI_ERROR_NOT_SUPPORTED;
goto cleanup;
}
ret = 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);
goto cleanup;
}
cleanup:
return (wifi_error)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)
{
int ret = WIFI_SUCCESS;
lowi_cb_table_t *lowiWifiHalApi = NULL;
if (iface == NULL) {
ALOGE("wifi_rtt_range_request: NULL iface pointer provided."
" Exit.");
return WIFI_ERROR_INVALID_ARGS;
}
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.");
ret = WIFI_ERROR_NOT_SUPPORTED;
goto cleanup;
}
ret = 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);
goto cleanup;
}
cleanup:
return (wifi_error)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[])
{
int ret = WIFI_SUCCESS;
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.");
ret = WIFI_ERROR_NOT_SUPPORTED;
goto cleanup;
}
ret = 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);
goto cleanup;
}
cleanup:
return (wifi_error)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)
{
int ret = WIFI_SUCCESS;
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__);
ret = WIFI_ERROR_NOT_SUPPORTED;
goto cleanup;
}
ret = lowiWifiHalApi->rtt_set_lci(id, iface, lci);
if (ret != WIFI_SUCCESS) {
ALOGE("%s: returned error:%d. Exit.",
__FUNCTION__, ret);
goto cleanup;
}
cleanup:
return (wifi_error)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)
{
int ret = WIFI_SUCCESS;
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__);
ret = WIFI_ERROR_NOT_SUPPORTED;
goto cleanup;
}
ret = lowiWifiHalApi->rtt_set_lcr(id, iface, lcr);
if (ret != WIFI_SUCCESS) {
ALOGE("%s: returned error:%d. Exit.",
__FUNCTION__, ret);
goto cleanup;
}
cleanup:
return (wifi_error)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)
{
int ret = WIFI_SUCCESS;
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__);
ret = WIFI_ERROR_NOT_SUPPORTED;
goto cleanup;
}
ret = lowiWifiHalApi->rtt_get_responder_info(iface, responder_info);
if (ret != WIFI_SUCCESS) {
ALOGE("%s: returned error:%d. Exit.",
__FUNCTION__, ret);
goto cleanup;
}
cleanup:
return (wifi_error)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)
{
int ret = WIFI_SUCCESS;
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__);
ret = WIFI_ERROR_NOT_SUPPORTED;
goto cleanup;
}
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);
goto cleanup;
}
cleanup:
return (wifi_error)ret;
}
/**
* Disable RTT responder mode.
*/
wifi_error wifi_disable_responder(wifi_request_id id,
wifi_interface_handle iface)
{
int ret = WIFI_SUCCESS;
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__);
ret = WIFI_ERROR_NOT_SUPPORTED;
goto cleanup;
}
ret = lowiWifiHalApi->disable_responder(id, iface);
if (ret != WIFI_SUCCESS) {
ALOGE("%s: returned error:%d. Exit.",
__FUNCTION__, ret);
goto cleanup;
}
cleanup:
return (wifi_error)ret;
}