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