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