1 /* Copyright (c) 2014, 2018 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 <hardware_legacy/rtt.h>
39 #include <hardware_legacy/wifi_hal.h>
40 #include "wifihal_internal.h"
41
42 /* Implementation of the API functions exposed in rtt.h */
wifi_get_rtt_capabilities(wifi_interface_handle iface,wifi_rtt_capabilities * capabilities)43 wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
44 wifi_rtt_capabilities *capabilities)
45 {
46 wifi_error ret;
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 return WIFI_ERROR_NOT_SUPPORTED;
72 }
73
74 ret = (wifi_error)lowiWifiHalApi->get_rtt_capabilities(iface, capabilities);
75 if (ret != WIFI_SUCCESS)
76 ALOGE("wifi_get_rtt_capabilities: lowi_wifihal_get_rtt_capabilities "
77 "returned error:%d. Exit.", ret);
78
79 return ret;
80 }
81
82 /* API to request RTT measurement */
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)83 wifi_error wifi_rtt_range_request(wifi_request_id id,
84 wifi_interface_handle iface,
85 unsigned num_rtt_config,
86 wifi_rtt_config rtt_config[],
87 wifi_rtt_event_handler handler)
88 {
89 wifi_error ret;
90 lowi_cb_table_t *lowiWifiHalApi = NULL;
91 hal_info *info = NULL;
92
93 if (iface == NULL) {
94 ALOGE("wifi_rtt_range_request: NULL iface pointer provided."
95 " Exit.");
96 return WIFI_ERROR_INVALID_ARGS;
97 }
98
99 wifi_handle wifiHandle = getWifiHandle(iface);
100 info = getHalInfo(wifiHandle);
101 if (!info)
102 {
103 ALOGE("%s: hal_info is null ", __FUNCTION__);
104 return WIFI_ERROR_INVALID_ARGS;
105 }
106
107 if (!(info->supported_feature_set & WIFI_FEATURE_D2AP_RTT)) {
108 ALOGE("%s: RTT is not supported by driver", __FUNCTION__);
109 return WIFI_ERROR_NOT_SUPPORTED;
110 }
111
112 if (rtt_config == NULL) {
113 ALOGE("wifi_rtt_range_request: NULL rtt_config pointer provided."
114 " Exit.");
115 return WIFI_ERROR_INVALID_ARGS;
116 }
117
118 if (num_rtt_config <= 0) {
119 ALOGE("wifi_rtt_range_request: number of destination BSSIDs to "
120 "measure RTT on = 0. Exit.");
121 return WIFI_ERROR_INVALID_ARGS;
122 }
123
124 if (handler.on_rtt_results == NULL && handler.on_rtt_results_v2 == NULL ) {
125 ALOGE("wifi_rtt_range_request: NULL capabilities pointer provided."
126 " Exit.");
127 return WIFI_ERROR_INVALID_ARGS;
128 }
129
130 /* RTT commands are diverted through LOWI interface. */
131 /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
132 * LOWI if it isn't up yet.
133 */
134 lowiWifiHalApi = getLowiCallbackTable(
135 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
136 if (lowiWifiHalApi == NULL ||
137 lowiWifiHalApi->rtt_range_request == NULL) {
138 ALOGE("wifi_rtt_range_request: getLowiCallbackTable returned NULL or "
139 "the function pointer is NULL. Exit.");
140 return WIFI_ERROR_NOT_SUPPORTED;
141 }
142
143 ret = (wifi_error)lowiWifiHalApi->rtt_range_request(id, iface,
144 num_rtt_config,
145 rtt_config, handler);
146 if (ret != WIFI_SUCCESS)
147 ALOGE("wifi_rtt_range_request: lowi_wifihal_rtt_range_request "
148 "returned error:%d. Exit.", ret);
149
150 return ret;
151 }
152
153 /* API to cancel RTT measurements */
wifi_rtt_range_cancel(wifi_request_id id,wifi_interface_handle iface,unsigned num_devices,mac_addr addr[])154 wifi_error wifi_rtt_range_cancel(wifi_request_id id,
155 wifi_interface_handle iface,
156 unsigned num_devices,
157 mac_addr addr[])
158 {
159 wifi_error ret;
160 lowi_cb_table_t *lowiWifiHalApi = NULL;
161
162 if (iface == NULL) {
163 ALOGE("wifi_rtt_range_cancel: NULL iface pointer provided."
164 " Exit.");
165 return WIFI_ERROR_INVALID_ARGS;
166 }
167
168 if (addr == NULL) {
169 ALOGE("wifi_rtt_range_cancel: NULL addr pointer provided."
170 " Exit.");
171 return WIFI_ERROR_INVALID_ARGS;
172 }
173
174 if (num_devices <= 0) {
175 ALOGE("wifi_rtt_range_cancel: number of destination BSSIDs to "
176 "measure RTT on = 0. Exit.");
177 return WIFI_ERROR_INVALID_ARGS;
178 }
179
180 /* RTT commands are diverted through LOWI interface. */
181 /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
182 * LOWI if it isn't up yet.
183 */
184 lowiWifiHalApi = getLowiCallbackTable(
185 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
186 if (lowiWifiHalApi == NULL ||
187 lowiWifiHalApi->rtt_range_cancel == NULL) {
188 ALOGE("wifi_rtt_range_cancel: getLowiCallbackTable returned NULL or "
189 "the function pointer is NULL. Exit.");
190 return WIFI_ERROR_NOT_SUPPORTED;
191 }
192
193 ret = (wifi_error)lowiWifiHalApi->rtt_range_cancel(id, num_devices, addr);
194 if (ret != WIFI_SUCCESS)
195 ALOGE("wifi_rtt_range_cancel: lowi_wifihal_rtt_range_cancel "
196 "returned error:%d. Exit.", ret);
197
198 return ret;
199 }
200
201 // API to configure the LCI. Used in RTT Responder mode only
wifi_set_lci(wifi_request_id id,wifi_interface_handle iface,wifi_lci_information * lci)202 wifi_error wifi_set_lci(wifi_request_id id, wifi_interface_handle iface,
203 wifi_lci_information *lci)
204 {
205 wifi_error ret;
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 return WIFI_ERROR_NOT_SUPPORTED;
231 }
232
233 ret = lowiWifiHalApi->rtt_set_lci(id, iface, lci);
234 if (ret != WIFI_SUCCESS)
235 ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
236
237 return ret;
238 }
239
240 // API to configure the LCR. Used in RTT Responder mode only.
wifi_set_lcr(wifi_request_id id,wifi_interface_handle iface,wifi_lcr_information * lcr)241 wifi_error wifi_set_lcr(wifi_request_id id, wifi_interface_handle iface,
242 wifi_lcr_information *lcr)
243 {
244 wifi_error ret;
245 lowi_cb_table_t *lowiWifiHalApi = NULL;
246
247 if (iface == NULL) {
248 ALOGE("%s: NULL iface pointer provided."
249 " Exit.", __FUNCTION__);
250 return WIFI_ERROR_INVALID_ARGS;
251 }
252
253 if (lcr == NULL) {
254 ALOGE("%s: NULL lcr pointer provided."
255 " Exit.", __FUNCTION__);
256 return WIFI_ERROR_INVALID_ARGS;
257 }
258
259 /* RTT commands are diverted through LOWI interface. */
260 /* Open LOWI dynamic library, retrieve handler to LOWI APIs and initialize
261 * LOWI if it isn't up yet.
262 */
263 lowiWifiHalApi = getLowiCallbackTable(
264 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
265 if (lowiWifiHalApi == NULL ||
266 lowiWifiHalApi->rtt_set_lcr == NULL) {
267 ALOGE("%s: getLowiCallbackTable returned NULL or "
268 "the function pointer is NULL. Exit.", __FUNCTION__);
269 return WIFI_ERROR_NOT_SUPPORTED;
270 }
271
272 ret = lowiWifiHalApi->rtt_set_lcr(id, iface, lcr);
273 if (ret != WIFI_SUCCESS)
274 ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
275
276 return ret;
277 }
278
279 /*
280 * Get RTT responder information e.g. WiFi channel to enable responder on.
281 */
wifi_rtt_get_responder_info(wifi_interface_handle iface,wifi_rtt_responder * responder_info)282 wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface,
283 wifi_rtt_responder *responder_info)
284 {
285 wifi_error ret;
286 lowi_cb_table_t *lowiWifiHalApi = NULL;
287
288 if (iface == NULL || responder_info == NULL) {
289 ALOGE("%s: iface : %p responder_info : %p", __FUNCTION__, iface,
290 responder_info);
291 return WIFI_ERROR_INVALID_ARGS;
292 }
293
294 /* Open LOWI dynamic library, retrieve handler to LOWI APIs */
295 lowiWifiHalApi = getLowiCallbackTable(
296 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
297 if (lowiWifiHalApi == NULL ||
298 lowiWifiHalApi->rtt_get_responder_info == NULL) {
299 ALOGE("%s: getLowiCallbackTable returned NULL or "
300 "the function pointer is NULL. Exit.", __FUNCTION__);
301 return WIFI_ERROR_NOT_SUPPORTED;
302 }
303
304 ret = lowiWifiHalApi->rtt_get_responder_info(iface, responder_info);
305 if (ret != WIFI_SUCCESS)
306 ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
307
308 return ret;
309 }
310
311 /**
312 * Enable RTT responder mode.
313 * channel_hint - hint of the channel information where RTT responder should
314 * be enabled on.
315 * max_duration_seconds - timeout of responder mode.
316 * responder_info - responder information e.g. channel used for RTT responder,
317 * NULL if responder is not enabled.
318 */
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)319 wifi_error wifi_enable_responder(wifi_request_id id,
320 wifi_interface_handle iface,
321 wifi_channel_info channel_hint,
322 unsigned max_duration_seconds,
323 wifi_rtt_responder *responder_info)
324 {
325 wifi_error ret;
326 lowi_cb_table_t *lowiWifiHalApi = NULL;
327
328 if (iface == NULL || responder_info == NULL) {
329 ALOGE("%s: iface : %p responder_info : %p", __FUNCTION__, iface, responder_info);
330 return WIFI_ERROR_INVALID_ARGS;
331 }
332
333 /* Open LOWI dynamic library, retrieve handler to LOWI APIs */
334 lowiWifiHalApi = getLowiCallbackTable(
335 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
336 if (lowiWifiHalApi == NULL ||
337 lowiWifiHalApi->enable_responder == NULL) {
338 ALOGE("%s: getLowiCallbackTable returned NULL or "
339 "the function pointer is NULL. Exit.", __FUNCTION__);
340 return WIFI_ERROR_NOT_SUPPORTED;
341 }
342
343 ret = lowiWifiHalApi->enable_responder(id, iface, channel_hint,
344 max_duration_seconds,
345 responder_info);
346 if (ret != WIFI_SUCCESS)
347 ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
348
349 return ret;
350 }
351
352
353 /**
354 * Disable RTT responder mode.
355 */
wifi_disable_responder(wifi_request_id id,wifi_interface_handle iface)356 wifi_error wifi_disable_responder(wifi_request_id id,
357 wifi_interface_handle iface)
358
359 {
360 wifi_error ret;
361 lowi_cb_table_t *lowiWifiHalApi = NULL;
362
363 if (iface == NULL) {
364 ALOGE("%s: iface : %p", __FUNCTION__, iface);
365 return WIFI_ERROR_INVALID_ARGS;
366 }
367
368 /* Open LOWI dynamic library, retrieve handler to LOWI APIs */
369 lowiWifiHalApi = getLowiCallbackTable(
370 ONE_SIDED_RANGING_SUPPORTED|DUAL_SIDED_RANGING_SUPPORED);
371 if (lowiWifiHalApi == NULL ||
372 lowiWifiHalApi->disable_responder == NULL) {
373 ALOGE("%s: getLowiCallbackTable returned NULL or "
374 "the function pointer is NULL. Exit.", __FUNCTION__);
375 return WIFI_ERROR_NOT_SUPPORTED;
376 }
377
378 ret = lowiWifiHalApi->disable_responder(id, iface);
379 if (ret != WIFI_SUCCESS)
380 ALOGE("%s: returned error:%d. Exit.", __FUNCTION__, ret);
381
382 return ret;
383 }
384