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