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 */
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     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 
82 cleanup:
83     return (wifi_error)ret;
84 }
85 
86 /* 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)87 wifi_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 
145 cleanup:
146     return (wifi_error)ret;
147 }
148 
149 /* API to cancel RTT measurements */
wifi_rtt_range_cancel(wifi_request_id id,wifi_interface_handle iface,unsigned num_devices,mac_addr addr[])150 wifi_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 
197 cleanup:
198     return (wifi_error)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     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 
241 cleanup:
242     return (wifi_error)ret;
243 }
244 
245 // 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)246 wifi_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 
285 cleanup:
286     return (wifi_error)ret;
287 }
288 
289 /*
290  * Get RTT responder information e.g. WiFi channel to enable responder on.
291  */
wifi_rtt_get_responder_info(wifi_interface_handle iface,wifi_rtt_responder * responder_info)292 wifi_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 
322 cleanup:
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  */
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)334 wifi_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 
368 cleanup:
369     return (wifi_error)ret;
370 }
371 
372 
373 /**
374  * Disable RTT responder mode.
375  */
wifi_disable_responder(wifi_request_id id,wifi_interface_handle iface)376 wifi_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 
406 cleanup:
407     return (wifi_error)ret;
408 }
409