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