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