1/* Copyright (c) 2014, The Linux Foundation. All rights reserved. 2 * 3 * Redistribution and use in source and binary forms, with or without 4 * modification, are permitted provided that the following conditions 5 * are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above 9 * copyright notice, this list of conditions and the following 10 * disclaimer in the documentation and/or other materials provided 11 * with the distribution. 12 * * Neither the name of The Linux Foundation nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#define LOG_TAG "WifiHAL" 30#include <cutils/sched_policy.h> 31#include <unistd.h> 32 33#include <utils/Log.h> 34#include <time.h> 35 36#include "common.h" 37#include "cpp_bindings.h" 38#include "rtt.h" 39#include "wifi_hal.h" 40#include "wifihal_internal.h" 41 42/* Implementation of the API functions exposed in rtt.h */ 43wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface, 44 wifi_rtt_capabilities *capabilities) 45{ 46 int ret = WIFI_SUCCESS; 47 lowi_cb_table_t *lowiWifiHalApi = NULL; 48 49 if (iface == NULL) { 50 ALOGE("wifi_get_rtt_capabilities: NULL iface pointer provided." 51 " Exit."); 52 return WIFI_ERROR_INVALID_ARGS; 53 } 54 55 if (capabilities == NULL) { 56 ALOGE("wifi_get_rtt_capabilities: NULL capabilities pointer provided." 57 " Exit."); 58 return WIFI_ERROR_INVALID_ARGS; 59 } 60 61 /* RTT commands are diverted through LOWI interface. */ 62 /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize 63 * LOWI if it isn't up yet. 64 */ 65 lowiWifiHalApi = getLowiCallbackTable( 66 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED); 67 if (lowiWifiHalApi == NULL || 68 lowiWifiHalApi->get_rtt_capabilities == NULL) { 69 ALOGE("wifi_get_rtt_capabilities: getLowiCallbackTable returned NULL or " 70 "the function pointer is NULL. Exit."); 71 ret = WIFI_ERROR_NOT_SUPPORTED; 72 goto cleanup; 73 } 74 75 ret = lowiWifiHalApi->get_rtt_capabilities(iface, capabilities); 76 if (ret != WIFI_SUCCESS) { 77 ALOGE("wifi_get_rtt_capabilities: lowi_wifihal_get_rtt_capabilities " 78 "returned error:%d. Exit.", ret); 79 goto cleanup; 80 } 81 82cleanup: 83 return (wifi_error)ret; 84} 85 86/* API to request RTT measurement */ 87wifi_error wifi_rtt_range_request(wifi_request_id id, 88 wifi_interface_handle iface, 89 unsigned num_rtt_config, 90 wifi_rtt_config rtt_config[], 91 wifi_rtt_event_handler handler) 92{ 93 int ret = WIFI_SUCCESS; 94 lowi_cb_table_t *lowiWifiHalApi = NULL; 95 96 if (iface == NULL) { 97 ALOGE("wifi_rtt_range_request: NULL iface pointer provided." 98 " Exit."); 99 return WIFI_ERROR_INVALID_ARGS; 100 } 101 102 if (rtt_config == NULL) { 103 ALOGE("wifi_rtt_range_request: NULL rtt_config pointer provided." 104 " Exit."); 105 return WIFI_ERROR_INVALID_ARGS; 106 } 107 108 if (num_rtt_config <= 0) { 109 ALOGE("wifi_rtt_range_request: number of destination BSSIDs to " 110 "measure RTT on = 0. Exit."); 111 return WIFI_ERROR_INVALID_ARGS; 112 } 113 114 if (handler.on_rtt_results == NULL) { 115 ALOGE("wifi_rtt_range_request: NULL capabilities pointer provided." 116 " Exit."); 117 return WIFI_ERROR_INVALID_ARGS; 118 } 119 120 /* RTT commands are diverted through LOWI interface. */ 121 /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize 122 * LOWI if it isn't up yet. 123 */ 124 lowiWifiHalApi = getLowiCallbackTable( 125 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED); 126 if (lowiWifiHalApi == NULL || 127 lowiWifiHalApi->rtt_range_request == NULL) { 128 ALOGE("wifi_rtt_range_request: getLowiCallbackTable returned NULL or " 129 "the function pointer is NULL. Exit."); 130 ret = WIFI_ERROR_NOT_SUPPORTED; 131 goto cleanup; 132 } 133 134 ret = lowiWifiHalApi->rtt_range_request(id, 135 iface, 136 num_rtt_config, 137 rtt_config, 138 handler); 139 if (ret != WIFI_SUCCESS) { 140 ALOGE("wifi_rtt_range_request: lowi_wifihal_rtt_range_request " 141 "returned error:%d. Exit.", ret); 142 goto cleanup; 143 } 144 145cleanup: 146 return (wifi_error)ret; 147} 148 149/* API to cancel RTT measurements */ 150wifi_error wifi_rtt_range_cancel(wifi_request_id id, 151 wifi_interface_handle iface, 152 unsigned num_devices, 153 mac_addr addr[]) 154{ 155 int ret = WIFI_SUCCESS; 156 lowi_cb_table_t *lowiWifiHalApi = NULL; 157 158 if (iface == NULL) { 159 ALOGE("wifi_rtt_range_cancel: NULL iface pointer provided." 160 " Exit."); 161 return WIFI_ERROR_INVALID_ARGS; 162 } 163 164 if (addr == NULL) { 165 ALOGE("wifi_rtt_range_cancel: NULL addr pointer provided." 166 " Exit."); 167 return WIFI_ERROR_INVALID_ARGS; 168 } 169 170 if (num_devices <= 0) { 171 ALOGE("wifi_rtt_range_cancel: number of destination BSSIDs to " 172 "measure RTT on = 0. Exit."); 173 return WIFI_ERROR_INVALID_ARGS; 174 } 175 176 /* RTT commands are diverted through LOWI interface. */ 177 /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize 178 * LOWI if it isn't up yet. 179 */ 180 lowiWifiHalApi = getLowiCallbackTable( 181 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED); 182 if (lowiWifiHalApi == NULL || 183 lowiWifiHalApi->rtt_range_cancel == NULL) { 184 ALOGE("wifi_rtt_range_cancel: getLowiCallbackTable returned NULL or " 185 "the function pointer is NULL. Exit."); 186 ret = WIFI_ERROR_NOT_SUPPORTED; 187 goto cleanup; 188 } 189 190 ret = lowiWifiHalApi->rtt_range_cancel(id, num_devices, addr); 191 if (ret != WIFI_SUCCESS) { 192 ALOGE("wifi_rtt_range_cancel: lowi_wifihal_rtt_range_cancel " 193 "returned error:%d. Exit.", ret); 194 goto cleanup; 195 } 196 197cleanup: 198 return (wifi_error)ret; 199} 200 201// API to configure the LCI. Used in RTT Responder mode only 202wifi_error wifi_set_lci(wifi_request_id id, wifi_interface_handle iface, 203 wifi_lci_information *lci) 204{ 205 int ret = WIFI_SUCCESS; 206 lowi_cb_table_t *lowiWifiHalApi = NULL; 207 208 if (iface == NULL) { 209 ALOGE("%s: NULL iface pointer provided." 210 " Exit.", __FUNCTION__); 211 return WIFI_ERROR_INVALID_ARGS; 212 } 213 214 if (lci == NULL) { 215 ALOGE("%s: NULL lci pointer provided." 216 " Exit.", __FUNCTION__); 217 return WIFI_ERROR_INVALID_ARGS; 218 } 219 220 /* RTT commands are diverted through LOWI interface. */ 221 /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize 222 * LOWI if it isn't up yet. 223 */ 224 lowiWifiHalApi = getLowiCallbackTable( 225 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED); 226 if (lowiWifiHalApi == NULL || 227 lowiWifiHalApi->rtt_set_lci == NULL) { 228 ALOGE("%s: getLowiCallbackTable returned NULL or " 229 "the function pointer is NULL. Exit.", __FUNCTION__); 230 ret = WIFI_ERROR_NOT_SUPPORTED; 231 goto cleanup; 232 } 233 234 ret = lowiWifiHalApi->rtt_set_lci(id, iface, lci); 235 if (ret != WIFI_SUCCESS) { 236 ALOGE("%s: returned error:%d. Exit.", 237 __FUNCTION__, ret); 238 goto cleanup; 239 } 240 241cleanup: 242 return (wifi_error)ret; 243} 244 245// API to configure the LCR. Used in RTT Responder mode only. 246wifi_error wifi_set_lcr(wifi_request_id id, wifi_interface_handle iface, 247 wifi_lcr_information *lcr) 248{ 249 int ret = WIFI_SUCCESS; 250 lowi_cb_table_t *lowiWifiHalApi = NULL; 251 252 if (iface == NULL) { 253 ALOGE("%s: NULL iface pointer provided." 254 " Exit.", __FUNCTION__); 255 return WIFI_ERROR_INVALID_ARGS; 256 } 257 258 if (lcr == NULL) { 259 ALOGE("%s: NULL lcr pointer provided." 260 " Exit.", __FUNCTION__); 261 return WIFI_ERROR_INVALID_ARGS; 262 } 263 264 /* RTT commands are diverted through LOWI interface. */ 265 /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize 266 * LOWI if it isn't up yet. 267 */ 268 lowiWifiHalApi = getLowiCallbackTable( 269 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED); 270 if (lowiWifiHalApi == NULL || 271 lowiWifiHalApi->rtt_set_lcr == NULL) { 272 ALOGE("%s: getLowiCallbackTable returned NULL or " 273 "the function pointer is NULL. Exit.", __FUNCTION__); 274 ret = WIFI_ERROR_NOT_SUPPORTED; 275 goto cleanup; 276 } 277 278 ret = lowiWifiHalApi->rtt_set_lcr(id, iface, lcr); 279 if (ret != WIFI_SUCCESS) { 280 ALOGE("%s: returned error:%d. Exit.", 281 __FUNCTION__, ret); 282 goto cleanup; 283 } 284 285cleanup: 286 return (wifi_error)ret; 287} 288 289/* 290 * Get RTT responder information e.g. WiFi channel to enable responder on. 291 */ 292wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface, 293 wifi_rtt_responder *responder_info) 294{ 295 int ret = WIFI_SUCCESS; 296 lowi_cb_table_t *lowiWifiHalApi = NULL; 297 298 if (iface == NULL || responder_info == NULL) { 299 ALOGE("%s: iface : %p responder_info : %p", __FUNCTION__, iface, 300 responder_info); 301 return WIFI_ERROR_INVALID_ARGS; 302 } 303 304 /* Open LOWI dynamic library, retrieve handler to LOWI APIs */ 305 lowiWifiHalApi = getLowiCallbackTable( 306 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED); 307 if (lowiWifiHalApi == NULL || 308 lowiWifiHalApi->rtt_get_responder_info == NULL) { 309 ALOGE("%s: getLowiCallbackTable returned NULL or " 310 "the function pointer is NULL. Exit.", __FUNCTION__); 311 ret = WIFI_ERROR_NOT_SUPPORTED; 312 goto cleanup; 313 } 314 315 ret = lowiWifiHalApi->rtt_get_responder_info(iface, responder_info); 316 if (ret != WIFI_SUCCESS) { 317 ALOGE("%s: returned error:%d. Exit.", 318 __FUNCTION__, ret); 319 goto cleanup; 320 } 321 322cleanup: 323 return (wifi_error)ret; 324} 325 326/** 327 * Enable RTT responder mode. 328 * channel_hint - hint of the channel information where RTT responder should 329 * be enabled on. 330 * max_duration_seconds - timeout of responder mode. 331 * responder_info - responder information e.g. channel used for RTT responder, 332 * NULL if responder is not enabled. 333 */ 334wifi_error wifi_enable_responder(wifi_request_id id, 335 wifi_interface_handle iface, 336 wifi_channel_info channel_hint, 337 unsigned max_duration_seconds, 338 wifi_rtt_responder *responder_info) 339{ 340 int ret = WIFI_SUCCESS; 341 lowi_cb_table_t *lowiWifiHalApi = NULL; 342 343 if (iface == NULL || responder_info == NULL) { 344 ALOGE("%s: iface : %p responder_info : %p", __FUNCTION__, iface, responder_info); 345 return WIFI_ERROR_INVALID_ARGS; 346 } 347 348 /* Open LOWI dynamic library, retrieve handler to LOWI APIs */ 349 lowiWifiHalApi = getLowiCallbackTable( 350 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED); 351 if (lowiWifiHalApi == NULL || 352 lowiWifiHalApi->enable_responder == NULL) { 353 ALOGE("%s: getLowiCallbackTable returned NULL or " 354 "the function pointer is NULL. Exit.", __FUNCTION__); 355 ret = WIFI_ERROR_NOT_SUPPORTED; 356 goto cleanup; 357 } 358 359 ret = lowiWifiHalApi->enable_responder(id, iface, channel_hint, 360 max_duration_seconds, 361 responder_info); 362 if (ret != WIFI_SUCCESS) { 363 ALOGE("%s: returned error:%d. Exit.", 364 __FUNCTION__, ret); 365 goto cleanup; 366 } 367 368cleanup: 369 return (wifi_error)ret; 370} 371 372 373/** 374 * Disable RTT responder mode. 375 */ 376wifi_error wifi_disable_responder(wifi_request_id id, 377 wifi_interface_handle iface) 378 379{ 380 int ret = WIFI_SUCCESS; 381 lowi_cb_table_t *lowiWifiHalApi = NULL; 382 383 if (iface == NULL) { 384 ALOGE("%s: iface : %p", __FUNCTION__, iface); 385 return WIFI_ERROR_INVALID_ARGS; 386 } 387 388 /* Open LOWI dynamic library, retrieve handler to LOWI APIs */ 389 lowiWifiHalApi = getLowiCallbackTable( 390 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED); 391 if (lowiWifiHalApi == NULL || 392 lowiWifiHalApi->disable_responder == NULL) { 393 ALOGE("%s: getLowiCallbackTable returned NULL or " 394 "the function pointer is NULL. Exit.", __FUNCTION__); 395 ret = WIFI_ERROR_NOT_SUPPORTED; 396 goto cleanup; 397 } 398 399 ret = lowiWifiHalApi->disable_responder(id, iface); 400 if (ret != WIFI_SUCCESS) { 401 ALOGE("%s: returned error:%d. Exit.", 402 __FUNCTION__, ret); 403 goto cleanup; 404 } 405 406cleanup: 407 return (wifi_error)ret; 408} 409