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