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