1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Portions copyright (C) 2017 Broadcom Limited
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 #include <stdint.h>
20 #include <fcntl.h>
21 #include <sys/socket.h>
22 #include <netlink/genl/genl.h>
23 #include <netlink/genl/family.h>
24 #include <netlink/genl/ctrl.h>
25 #include <linux/rtnetlink.h>
26 #include <netpacket/packet.h>
27 #include <linux/filter.h>
28 #include <linux/errqueue.h>
29
30 #include <linux/pkt_sched.h>
31 #include <netlink/object-api.h>
32 #include <netlink/netlink.h>
33 #include <netlink/socket.h>
34 #include <netlink-private/object-api.h>
35 #include <netlink-private/types.h>
36
37 #include "nl80211_copy.h"
38
39 #include "sync.h"
40
41 #define LOG_TAG "WifiHAL"
42
43 #include <log/log.h>
44 #include <utils/String8.h>
45
46 #include "wifi_hal.h"
47 #include "common.h"
48 #include "cpp_bindings.h"
49
50 using namespace android;
51 #define RTT_RESULT_SIZE (sizeof(wifi_rtt_result));
52 typedef enum {
53
54 RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
55 RTT_SUBCMD_CANCEL_CONFIG,
56 RTT_SUBCMD_GETCAPABILITY,
57 RTT_SUBCMD_GETAVAILCHANNEL,
58 RTT_SUBCMD_SET_RESPONDER,
59 RTT_SUBCMD_CANCEL_RESPONDER,
60 } RTT_SUB_COMMAND;
61
62 typedef enum {
63 RTT_ATTRIBUTE_TARGET_CNT = 0,
64 RTT_ATTRIBUTE_TARGET_INFO,
65 RTT_ATTRIBUTE_TARGET_MAC,
66 RTT_ATTRIBUTE_TARGET_TYPE,
67 RTT_ATTRIBUTE_TARGET_PEER,
68 RTT_ATTRIBUTE_TARGET_CHAN,
69 RTT_ATTRIBUTE_TARGET_PERIOD,
70 RTT_ATTRIBUTE_TARGET_NUM_BURST,
71 RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
72 RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
73 RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
74 RTT_ATTRIBUTE_TARGET_LCI,
75 RTT_ATTRIBUTE_TARGET_LCR,
76 RTT_ATTRIBUTE_TARGET_BURST_DURATION,
77 RTT_ATTRIBUTE_TARGET_PREAMBLE,
78 RTT_ATTRIBUTE_TARGET_BW,
79 RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
80 RTT_ATTRIBUTE_RESULTS_PER_TARGET,
81 RTT_ATTRIBUTE_RESULT_CNT,
82 RTT_ATTRIBUTE_RESULT
83 } RTT_ATTRIBUTE;
84 typedef struct strmap_entry {
85 int id;
86 String8 text;
87 } strmap_entry_t;
88 struct dot11_rm_ie {
89 u8 id;
90 u8 len;
91 u8 token;
92 u8 mode;
93 u8 type;
94 } __attribute__ ((packed));
95 typedef struct dot11_rm_ie dot11_rm_ie_t;
96 #define DOT11_HDR_LEN 2
97 #define DOT11_RM_IE_LEN 5
98 #define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
99 #define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */
100 #define DOT11_MEASURE_TYPE_CIVICLOC 11 /* d11 measurement location civic */
101
102 static const strmap_entry_t err_info[] = {
103 {RTT_STATUS_SUCCESS, String8("Success")},
104 {RTT_STATUS_FAILURE, String8("Failure")},
105 {RTT_STATUS_FAIL_NO_RSP, String8("No reponse")},
106 {RTT_STATUS_FAIL_INVALID_TS, String8("Invalid Timestamp")},
107 {RTT_STATUS_FAIL_PROTOCOL, String8("Protocol error")},
108 {RTT_STATUS_FAIL_REJECTED, String8("Rejected")},
109 {RTT_STATUS_FAIL_NOT_SCHEDULED_YET, String8("not scheduled")},
110 {RTT_STATUS_FAIL_SCHEDULE, String8("schedule failed")},
111 {RTT_STATUS_FAIL_TM_TIMEOUT, String8("timeout")},
112 {RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, String8("AP is on difference channel")},
113 {RTT_STATUS_FAIL_NO_CAPABILITY, String8("no capability")},
114 {RTT_STATUS_FAIL_BUSY_TRY_LATER, String8("busy and try later")},
115 {RTT_STATUS_ABORTED, String8("aborted")}
116 };
117
118 static const char*
get_err_info(int status)119 get_err_info(int status)
120 {
121 int i;
122 const strmap_entry_t *p_entry;
123 int num_entries = sizeof(err_info)/ sizeof(err_info[0]);
124 /* scan thru the table till end */
125 p_entry = err_info;
126 for (i = 0; i < (int) num_entries; i++)
127 {
128 if (p_entry->id == status)
129 return p_entry->text;
130 p_entry++; /* next entry */
131 }
132 return "unknown error"; /* not found */
133 }
134
135 class GetRttCapabilitiesCommand : public WifiCommand
136 {
137 wifi_rtt_capabilities *mCapabilities;
138 public:
GetRttCapabilitiesCommand(wifi_interface_handle iface,wifi_rtt_capabilities * capabitlites)139 GetRttCapabilitiesCommand(wifi_interface_handle iface, wifi_rtt_capabilities *capabitlites)
140 : WifiCommand("GetRttCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
141 {
142 memset(mCapabilities, 0, sizeof(*mCapabilities));
143 }
144
create()145 virtual int create() {
146 ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
147
148 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETCAPABILITY);
149 if (ret < 0) {
150 return ret;
151 }
152
153 return ret;
154 }
155
156 protected:
handleResponse(WifiEvent & reply)157 virtual int handleResponse(WifiEvent& reply) {
158
159 ALOGD("In GetRttCapabilitiesCommand::handleResponse");
160
161 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
162 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
163 return NL_SKIP;
164 }
165
166 int id = reply.get_vendor_id();
167 int subcmd = reply.get_vendor_subcmd();
168
169 void *data = reply.get_vendor_data();
170 int len = reply.get_vendor_data_len();
171
172 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
173 sizeof(*mCapabilities));
174
175 memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
176
177 return NL_OK;
178 }
179 };
180
181
182 class GetRttResponderInfoCommand : public WifiCommand
183 {
184 wifi_rtt_responder* mResponderInfo;
185 public:
GetRttResponderInfoCommand(wifi_interface_handle iface,wifi_rtt_responder * responderInfo)186 GetRttResponderInfoCommand(wifi_interface_handle iface, wifi_rtt_responder *responderInfo)
187 : WifiCommand("GetRttResponderInfoCommand", iface, 0), mResponderInfo(responderInfo)
188 {
189 memset(mResponderInfo, 0 , sizeof(*mResponderInfo));
190
191 }
192
create()193 virtual int create() {
194 ALOGD("Creating message to get responder info ; iface = %d", mIfaceInfo->id);
195
196 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETAVAILCHANNEL);
197 if (ret < 0) {
198 return ret;
199 }
200
201 return ret;
202 }
203
204 protected:
handleResponse(WifiEvent & reply)205 virtual int handleResponse(WifiEvent& reply) {
206
207 ALOGD("In GetRttResponderInfoCommand::handleResponse");
208
209 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
210 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
211 return NL_SKIP;
212 }
213
214 int id = reply.get_vendor_id();
215 int subcmd = reply.get_vendor_subcmd();
216
217 void *data = reply.get_vendor_data();
218 int len = reply.get_vendor_data_len();
219
220 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
221 sizeof(*mResponderInfo));
222
223 memcpy(mResponderInfo, data, min(len, (int) sizeof(*mResponderInfo)));
224
225 return NL_OK;
226 }
227 };
228
229
230 class EnableResponderCommand : public WifiCommand
231 {
232 wifi_channel_info mChannelInfo;
233 wifi_rtt_responder* mResponderInfo;
234 unsigned m_max_duration_sec;
235 public:
EnableResponderCommand(wifi_interface_handle iface,int id,wifi_channel_info channel_hint,unsigned max_duration_seconds,wifi_rtt_responder * responderInfo)236 EnableResponderCommand(wifi_interface_handle iface, int id, wifi_channel_info channel_hint,
237 unsigned max_duration_seconds, wifi_rtt_responder *responderInfo)
238 : WifiCommand("EnableResponderCommand", iface, 0), mChannelInfo(channel_hint),
239 m_max_duration_sec(max_duration_seconds), mResponderInfo(responderInfo)
240 {
241 memset(mResponderInfo, 0, sizeof(*mResponderInfo));
242 }
243
create()244 virtual int create() {
245 ALOGD("Creating message to set responder ; iface = %d", mIfaceInfo->id);
246
247 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_SET_RESPONDER);
248 if (ret < 0) {
249 return ret;
250 }
251
252 return ret;
253 }
254
255 protected:
handleResponse(WifiEvent & reply)256 virtual int handleResponse(WifiEvent& reply) {
257
258 ALOGD("In EnableResponderCommand::handleResponse");
259
260 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
261 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
262 return NL_SKIP;
263 }
264
265 int id = reply.get_vendor_id();
266 int subcmd = reply.get_vendor_subcmd();
267
268 void *data = reply.get_vendor_data();
269 int len = reply.get_vendor_data_len();
270
271 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
272 sizeof(*mResponderInfo));
273
274 memcpy(mResponderInfo, data, min(len, (int) sizeof(*mResponderInfo)));
275
276 return NL_OK;
277 }
278 };
279
280
281 class CancelResponderCommand : public WifiCommand
282 {
283
284 public:
CancelResponderCommand(wifi_interface_handle iface,int id)285 CancelResponderCommand(wifi_interface_handle iface, int id)
286 : WifiCommand("CancelResponderCommand", iface, 0)/*, mChannelInfo(channel)*/
287 {
288
289 }
290
create()291 virtual int create() {
292 ALOGD("Creating message to cancel responder ; iface = %d", mIfaceInfo->id);
293
294 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_RESPONDER);
295 if (ret < 0) {
296 return ret;
297 }
298
299 return ret;
300 }
301
302 protected:
handleResponse(WifiEvent & reply)303 virtual int handleResponse(WifiEvent& reply) {
304 /* Nothing to do on response! */
305 return NL_SKIP;
306 }
307
308 };
309
310
311 class RttCommand : public WifiCommand
312 {
313 unsigned numRttParams;
314 int mCompleted;
315 int currentIdx;
316 int totalCnt;
317 static const int MAX_RESULTS = 1024;
318 wifi_rtt_result *rttResults[MAX_RESULTS];
319 wifi_rtt_config *rttParams;
320 wifi_rtt_event_handler rttHandler;
321 public:
RttCommand(wifi_interface_handle iface,int id,unsigned num_rtt_config,wifi_rtt_config rtt_config[],wifi_rtt_event_handler handler)322 RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config,
323 wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
324 : WifiCommand("RttCommand", iface, id), numRttParams(num_rtt_config), rttParams(rtt_config),
325 rttHandler(handler)
326 {
327 memset(rttResults, 0, sizeof(rttResults));
328 currentIdx = 0;
329 mCompleted = 0;
330 totalCnt = 0;
331 }
332
RttCommand(wifi_interface_handle iface,int id)333 RttCommand(wifi_interface_handle iface, int id)
334 : WifiCommand("RttCommand", iface, id)
335 {
336 currentIdx = 0;
337 mCompleted = 0;
338 totalCnt = 0;
339 numRttParams = 0;
340 }
341
createSetupRequest(WifiRequest & request)342 int createSetupRequest(WifiRequest& request) {
343 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG);
344 if (result < 0) {
345 return result;
346 }
347
348 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
349 result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams);
350 if (result < 0) {
351 return result;
352 }
353 nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO);
354 for (unsigned i = 0; i < numRttParams; i++) {
355 nlattr *attr2 = request.attr_start(i);
356 if (attr2 == NULL) {
357 return WIFI_ERROR_OUT_OF_MEMORY;
358 }
359
360 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].addr);
361 if (result < 0) {
362 return result;
363 }
364
365 result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].type);
366 if (result < 0) {
367 return result;
368 }
369
370 result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].peer);
371 if (result < 0) {
372 return result;
373 }
374
375 result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].channel,
376 sizeof(wifi_channel_info));
377 if (result < 0) {
378 return result;
379 }
380
381 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_BURST, rttParams[i].num_burst);
382 if (result < 0) {
383 return result;
384 }
385
386 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
387 rttParams[i].num_frames_per_burst);
388 if (result < 0) {
389 return result;
390 }
391
392 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
393 rttParams[i].num_retries_per_rtt_frame);
394 if (result < 0) {
395 return result;
396 }
397
398 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
399 rttParams[i].num_retries_per_ftmr);
400 if (result < 0) {
401 return result;
402 }
403
404 result = request.put_u32(RTT_ATTRIBUTE_TARGET_PERIOD,
405 rttParams[i].burst_period);
406 if (result < 0) {
407 return result;
408 }
409
410 result = request.put_u32(RTT_ATTRIBUTE_TARGET_BURST_DURATION,
411 rttParams[i].burst_duration);
412 if (result < 0) {
413 return result;
414 }
415
416 result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCI,
417 rttParams[i].LCI_request);
418 if (result < 0) {
419 return result;
420 }
421
422 result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCR,
423 rttParams[i].LCR_request);
424 if (result < 0) {
425 return result;
426 }
427
428 result = request.put_u8(RTT_ATTRIBUTE_TARGET_BW,
429 rttParams[i].bw);
430 if (result < 0) {
431 return result;
432 }
433
434 result = request.put_u8(RTT_ATTRIBUTE_TARGET_PREAMBLE,
435 rttParams[i].preamble);
436 if (result < 0) {
437 return result;
438 }
439 request.attr_end(attr2);
440 }
441
442 request.attr_end(rtt_config);
443 request.attr_end(data);
444 return WIFI_SUCCESS;
445 }
446
createTeardownRequest(WifiRequest & request,unsigned num_devices,mac_addr addr[])447 int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) {
448 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_CONFIG);
449 if (result < 0) {
450 return result;
451 }
452
453 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
454 request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
455 for(unsigned i = 0; i < num_devices; i++) {
456 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
457 if (result < 0) {
458 return result;
459 }
460 }
461 request.attr_end(data);
462 return result;
463 }
start()464 int start() {
465 ALOGD("Setting RTT configuration");
466 WifiRequest request(familyId(), ifaceId());
467 int result = createSetupRequest(request);
468 if (result != WIFI_SUCCESS) {
469 ALOGE("failed to create setup request; result = %d", result);
470 return result;
471 }
472
473 result = requestResponse(request);
474 if (result != WIFI_SUCCESS) {
475 ALOGE("failed to configure RTT setup; result = %d", result);
476 return result;
477 }
478
479 registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
480 ALOGI("Successfully started RTT operation");
481 return result;
482 }
483
cancel()484 virtual int cancel() {
485 ALOGD("Stopping RTT");
486
487 WifiRequest request(familyId(), ifaceId());
488 int result = createTeardownRequest(request, 0, NULL);
489 if (result != WIFI_SUCCESS) {
490 ALOGE("failed to create stop request; result = %d", result);
491 } else {
492 result = requestResponse(request);
493 if (result != WIFI_SUCCESS) {
494 ALOGE("failed to stop scan; result = %d", result);
495 }
496 }
497
498 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
499 return WIFI_SUCCESS;
500 }
501
cancel_specific(unsigned num_devices,mac_addr addr[])502 int cancel_specific(unsigned num_devices, mac_addr addr[]) {
503 ALOGE("Stopping RTT");
504
505 WifiRequest request(familyId(), ifaceId());
506 int result = createTeardownRequest(request, num_devices, addr);
507 if (result != WIFI_SUCCESS) {
508 ALOGE("failed to create stop request; result = %d", result);
509 } else {
510 result = requestResponse(request);
511 if (result != WIFI_SUCCESS) {
512 ALOGE("failed to stop RTT; result = %d", result);
513 }
514 }
515
516 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
517 return WIFI_SUCCESS;
518 }
519
handleResponse(WifiEvent & reply)520 virtual int handleResponse(WifiEvent& reply) {
521 /* Nothing to do on response! */
522 return NL_SKIP;
523 }
524
handleEvent(WifiEvent & event)525 virtual int handleEvent(WifiEvent& event) {
526 ALOGI("Got an RTT event");
527 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
528 int len = event.get_vendor_data_len();
529 if (vendor_data == NULL || len == 0) {
530 ALOGI("No rtt results found");
531 }
532 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
533 if (it.get_type() == RTT_ATTRIBUTE_RESULTS_COMPLETE) {
534 mCompleted = it.get_u32();
535 ALOGI("retrieved completed flag : %d\n", mCompleted);
536 } else if (it.get_type() == RTT_ATTRIBUTE_RESULTS_PER_TARGET) {
537 int result_cnt = 0;
538 mac_addr bssid;
539 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
540 if (it2.get_type() == RTT_ATTRIBUTE_TARGET_MAC) {
541 memcpy(bssid, it2.get_data(), sizeof(mac_addr));
542 ALOGI("retrived target mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
543 bssid[0],
544 bssid[1],
545 bssid[2],
546 bssid[3],
547 bssid[4],
548 bssid[5]);
549 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_CNT) {
550 result_cnt = it2.get_u32();
551 ALOGI("retrieved result_cnt : %d\n", result_cnt);
552 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT) {
553 int result_len = it2.get_len();
554 rttResults[currentIdx] = (wifi_rtt_result *)malloc(it2.get_len());
555 wifi_rtt_result *rtt_result = rttResults[currentIdx];
556 if (rtt_result == NULL) {
557 mCompleted = 1;
558 ALOGE("failed to allocate the wifi_rtt_result\n");
559 break;
560 }
561 memcpy(rtt_result, it2.get_data(), it2.get_len());
562 result_len -= sizeof(wifi_rtt_result);
563 if (result_len > 0) {
564 result_len -= sizeof(wifi_rtt_result);
565 dot11_rm_ie_t *ele_1;
566 dot11_rm_ie_t *ele_2;
567 /* The result has LCI or LCR element */
568 ele_1 = (dot11_rm_ie_t *)(rtt_result + 1);
569 if (ele_1->id == DOT11_MNG_MEASURE_REQUEST_ID) {
570 if (ele_1->type == DOT11_MEASURE_TYPE_LCI) {
571 rtt_result->LCI = (wifi_information_element *)ele_1;
572 result_len -= (ele_1->len + DOT11_HDR_LEN);
573 /* get a next rm ie */
574 if (result_len > 0) {
575 ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
576 if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
577 (ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) {
578 rtt_result->LCR = (wifi_information_element *)ele_2;
579 }
580 }
581 } else if (ele_1->type == DOT11_MEASURE_TYPE_CIVICLOC){
582 rtt_result->LCR = (wifi_information_element *)ele_1;
583 result_len -= (ele_1->len + DOT11_HDR_LEN);
584 /* get a next rm ie */
585 if (result_len > 0) {
586 ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
587 if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
588 (ele_2->type == DOT11_MEASURE_TYPE_LCI)) {
589 rtt_result->LCI = (wifi_information_element *)ele_2;
590 }
591 }
592 }
593 }
594 }
595 totalCnt++;
596 ALOGI("retrived rtt_result : \n\tburst_num :%d, measurement_number : %d, success_number : %d\n"
597 "\tnumber_per_burst_peer : %d, status : %s, retry_after_duration : %d s\n"
598 "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %llu ns, rtt_sd : %llu\n"
599 "\tdistance : %d, burst_duration : %d ms, negotiated_burst_num : %d\n",
600 rtt_result->burst_num, rtt_result->measurement_number,
601 rtt_result->success_number, rtt_result->number_per_burst_peer,
602 get_err_info(rtt_result->status), rtt_result->retry_after_duration,
603 rtt_result->rssi, rtt_result->rx_rate.bitrate * 100,
604 rtt_result->rtt/10, rtt_result->rtt_sd, rtt_result->distance_mm / 10,
605 rtt_result->burst_duration, rtt_result->negotiated_burst_num);
606 currentIdx++;
607 }
608 }
609 }
610
611 }
612 if (mCompleted) {
613 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
614 (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
615 for (int i = 0; i < currentIdx; i++) {
616 free(rttResults[i]);
617 rttResults[i] = NULL;
618 }
619 totalCnt = currentIdx = 0;
620 WifiCommand *cmd = wifi_unregister_cmd(wifiHandle(), id());
621 if (cmd)
622 cmd->releaseRef();
623 }
624 return NL_SKIP;
625 }
626 };
627
628
629 /* 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)630 wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
631 unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
632 {
633 wifi_handle handle = getWifiHandle(iface);
634 RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
635 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
636 wifi_error result = wifi_register_cmd(handle, id, cmd);
637 if (result != WIFI_SUCCESS) {
638 cmd->releaseRef();
639 return result;
640 }
641 result = (wifi_error)cmd->start();
642 if (result != WIFI_SUCCESS) {
643 wifi_unregister_cmd(handle, id);
644 cmd->releaseRef();
645 return result;
646 }
647 return result;
648 }
649
650 /* API to cancel RTT measurements */
wifi_rtt_range_cancel(wifi_request_id id,wifi_interface_handle iface,unsigned num_devices,mac_addr addr[])651 wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface,
652 unsigned num_devices, mac_addr addr[])
653 {
654 wifi_handle handle = getWifiHandle(iface);
655 RttCommand *cmd = new RttCommand(iface, id);
656 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
657 cmd->cancel_specific(num_devices, addr);
658 cmd->releaseRef();
659 return WIFI_SUCCESS;
660 }
661
662 /* API to get RTT capability */
wifi_get_rtt_capabilities(wifi_interface_handle iface,wifi_rtt_capabilities * capabilities)663 wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
664 wifi_rtt_capabilities *capabilities)
665 {
666 GetRttCapabilitiesCommand command(iface, capabilities);
667 return (wifi_error) command.requestResponse();
668 }
669
670 /* API to get the responder information */
wifi_rtt_get_responder_info(wifi_interface_handle iface,wifi_rtt_responder * responderInfo)671 wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface,
672 wifi_rtt_responder* responderInfo)
673 {
674 GetRttResponderInfoCommand command(iface, responderInfo);
675 return (wifi_error) command.requestResponse();
676
677 }
678
679 /**
680 * Enable RTT responder mode.
681 * channel_hint - hint of the channel information where RTT responder should be enabled on.
682 * max_duration_seconds - timeout of responder mode.
683 * wifi_rtt_responder - information for RTT responder e.g. channel used and preamble supported.
684 */
wifi_enable_responder(wifi_request_id id,wifi_interface_handle iface,wifi_channel_info channel_hint,unsigned max_duration_seconds,wifi_rtt_responder * responderInfo)685 wifi_error wifi_enable_responder(wifi_request_id id, wifi_interface_handle iface,
686 wifi_channel_info channel_hint, unsigned max_duration_seconds,
687 wifi_rtt_responder* responderInfo)
688 {
689 EnableResponderCommand command(iface, id, channel_hint, max_duration_seconds, responderInfo);
690 return (wifi_error) command.requestResponse();
691 }
692
693 /**
694 * Disable RTT responder mode.
695 */
wifi_disable_responder(wifi_request_id id,wifi_interface_handle iface)696 wifi_error wifi_disable_responder(wifi_request_id id, wifi_interface_handle iface)
697 {
698 CancelResponderCommand command(iface, id);
699 return (wifi_error) command.requestResponse();
700 }
701
702