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 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
492 ALOGE("failed to configure RTT setup; result = %d", result);
493 return result;
494 }
495
496 ALOGI("Successfully started RTT operation");
497 return result;
498 }
499
cancel()500 virtual int cancel() {
501 ALOGD("Stopping RTT");
502
503 WifiRequest request(familyId(), ifaceId());
504 int result = createTeardownRequest(request, 0, NULL);
505 if (result != WIFI_SUCCESS) {
506 ALOGE("failed to create stop request; result = %d", result);
507 } else {
508 result = requestResponse(request);
509 if (result != WIFI_SUCCESS) {
510 ALOGE("failed to stop scan; result = %d", result);
511 }
512 }
513
514 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
515 return WIFI_SUCCESS;
516 }
517
cancel_specific(unsigned num_devices,mac_addr addr[])518 int cancel_specific(unsigned num_devices, mac_addr addr[]) {
519 ALOGE("Stopping RTT");
520
521 WifiRequest request(familyId(), ifaceId());
522 int result = createTeardownRequest(request, num_devices, addr);
523 if (result != WIFI_SUCCESS) {
524 ALOGE("failed to create stop request; result = %d", result);
525 } else {
526 result = requestResponse(request);
527 if (result != WIFI_SUCCESS) {
528 ALOGE("failed to stop RTT; result = %d", result);
529 }
530 }
531
532 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
533 return WIFI_SUCCESS;
534 }
535
handleResponse(WifiEvent & reply)536 virtual int handleResponse(WifiEvent& reply) {
537 /* Nothing to do on response! */
538 return NL_SKIP;
539 }
540
handleEvent(WifiEvent & event)541 virtual int handleEvent(WifiEvent& event) {
542 ALOGI("Got an RTT event");
543 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
544 int len = event.get_vendor_data_len();
545 if (vendor_data == NULL || len == 0) {
546 ALOGI("No rtt results found");
547 return NL_STOP;
548 }
549 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
550 if (it.get_type() == RTT_ATTRIBUTE_RESULTS_COMPLETE) {
551 mCompleted = it.get_u32();
552 ALOGI("retrieved completed flag : %d\n", mCompleted);
553 } else if (it.get_type() == RTT_ATTRIBUTE_RESULTS_PER_TARGET) {
554 int result_cnt = 0;
555 mac_addr bssid;
556 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
557 if (it2.get_type() == RTT_ATTRIBUTE_TARGET_MAC) {
558 memcpy(bssid, it2.get_data(), sizeof(mac_addr));
559 ALOGI("retrived target mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
560 bssid[0],
561 bssid[1],
562 bssid[2],
563 bssid[3],
564 bssid[4],
565 bssid[5]);
566 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_CNT) {
567 result_cnt = it2.get_u32();
568 ALOGI("retrieved result_cnt : %d\n", result_cnt);
569 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT) {
570 int result_len = it2.get_len();
571 rttResults[currentIdx] = (wifi_rtt_result *)malloc(it2.get_len());
572 wifi_rtt_result *rtt_result = rttResults[currentIdx];
573 if (rtt_result == NULL) {
574 mCompleted = 1;
575 ALOGE("failed to allocate the wifi_rtt_result\n");
576 break;
577 }
578 memcpy(rtt_result, it2.get_data(), it2.get_len());
579 result_len -= sizeof(wifi_rtt_result);
580 if (result_len > 0) {
581 dot11_rm_ie_t *ele_1;
582 dot11_rm_ie_t *ele_2;
583 /* The result has LCI or LCR element */
584 ele_1 = (dot11_rm_ie_t *)(rtt_result + 1);
585 if (ele_1->id == DOT11_MNG_MEASURE_REPORT_ID) {
586 if (ele_1->type == DOT11_MEASURE_TYPE_LCI) {
587 rtt_result->LCI = (wifi_information_element *)ele_1;
588 result_len -= (ele_1->len + DOT11_HDR_LEN);
589 /* get a next rm ie */
590 if (result_len > 0) {
591 ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
592 if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
593 (ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) {
594 rtt_result->LCR = (wifi_information_element *)ele_2;
595 }
596 }
597 } else if (ele_1->type == DOT11_MEASURE_TYPE_CIVICLOC){
598 rtt_result->LCR = (wifi_information_element *)ele_1;
599 result_len -= (ele_1->len + DOT11_HDR_LEN);
600 /* get a next rm ie */
601 if (result_len > 0) {
602 ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
603 if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
604 (ele_2->type == DOT11_MEASURE_TYPE_LCI)) {
605 rtt_result->LCI = (wifi_information_element *)ele_2;
606 }
607 }
608 }
609 }
610 }
611 totalCnt++;
612 ALOGI("retrived rtt_result : \n\tburst_num :%d, measurement_number : %d, success_number : %d\n"
613 "\tnumber_per_burst_peer : %d, status : %s, retry_after_duration : %d s\n"
614 "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %lu ns, rtt_sd : %lu\n"
615 "\tdistance : %d cm, burst_duration : %d ms, negotiated_burst_num : %d\n",
616 rtt_result->burst_num, rtt_result->measurement_number,
617 rtt_result->success_number, rtt_result->number_per_burst_peer,
618 get_err_info(rtt_result->status), rtt_result->retry_after_duration,
619 rtt_result->rssi, rtt_result->rx_rate.bitrate * 100,
620 (unsigned long)rtt_result->rtt/1000, (unsigned long)rtt_result->rtt_sd,
621 rtt_result->distance_mm / 10,
622 rtt_result->burst_duration, rtt_result->negotiated_burst_num);
623 currentIdx++;
624 }
625 }
626 }
627
628 }
629 if (mCompleted) {
630 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
631 if (*rttHandler.on_rtt_results) {
632 (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
633 }
634 for (int i = 0; i < currentIdx; i++) {
635 free(rttResults[i]);
636 rttResults[i] = NULL;
637 }
638 totalCnt = currentIdx = 0;
639 WifiCommand *cmd = wifi_unregister_cmd(wifiHandle(), id());
640 if (cmd)
641 cmd->releaseRef();
642 }
643 return NL_SKIP;
644 }
645 };
646
647
648 /* 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)649 wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
650 unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
651 {
652 if (iface == NULL) {
653 ALOGE("wifi_rtt_range_request: NULL iface pointer provided."
654 " Exit.");
655 return WIFI_ERROR_INVALID_ARGS;
656 }
657
658 wifi_handle handle = getWifiHandle(iface);
659 if (handle == NULL) {
660 ALOGE("wifi_rtt_range_request: NULL handle pointer provided."
661 " Exit.");
662 return WIFI_ERROR_INVALID_ARGS;
663 }
664
665 RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
666 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
667 wifi_error result = wifi_register_cmd(handle, id, cmd);
668 if (result != WIFI_SUCCESS) {
669 cmd->releaseRef();
670 return result;
671 }
672 result = (wifi_error)cmd->start();
673 if (result != WIFI_SUCCESS) {
674 wifi_unregister_cmd(handle, id);
675 cmd->releaseRef();
676 return result;
677 }
678 return result;
679 }
680
681 /* API to cancel RTT measurements */
wifi_rtt_range_cancel(wifi_request_id id,wifi_interface_handle iface,unsigned num_devices,mac_addr addr[])682 wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface,
683 unsigned num_devices, mac_addr addr[])
684 {
685 if (iface == NULL) {
686 ALOGE("wifi_rtt_range_cancel: NULL iface pointer provided."
687 " Exit.");
688 return WIFI_ERROR_INVALID_ARGS;
689 }
690
691 wifi_handle handle = getWifiHandle(iface);
692 if (handle == NULL) {
693 ALOGE("wifi_rtt_range_cancel: NULL handle pointer provided."
694 " Exit.");
695 return WIFI_ERROR_INVALID_ARGS;
696 }
697
698 RttCommand *cmd = new RttCommand(iface, id);
699 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
700 cmd->cancel_specific(num_devices, addr);
701 cmd->releaseRef();
702 return WIFI_SUCCESS;
703 }
704
705 /* API to get RTT capability */
wifi_get_rtt_capabilities(wifi_interface_handle iface,wifi_rtt_capabilities * capabilities)706 wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
707 wifi_rtt_capabilities *capabilities)
708 {
709 if (iface == NULL) {
710 ALOGE("wifi_get_rtt_capabilities: NULL iface pointer provided."
711 " Exit.");
712 return WIFI_ERROR_INVALID_ARGS;
713 }
714
715 if (capabilities == NULL) {
716 ALOGE("wifi_get_rtt_capabilities: NULL capabilities pointer provided."
717 " Exit.");
718 return WIFI_ERROR_INVALID_ARGS;
719 }
720
721 GetRttCapabilitiesCommand command(iface, capabilities);
722 return (wifi_error) command.requestResponse();
723 }
724
725 /* API to get the responder information */
wifi_rtt_get_responder_info(wifi_interface_handle iface,wifi_rtt_responder * responderInfo)726 wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface,
727 wifi_rtt_responder* responderInfo)
728 {
729 if (iface == NULL) {
730 ALOGE("wifi_rtt_get_responder_info: NULL iface pointer provided."
731 " Exit.");
732 return WIFI_ERROR_INVALID_ARGS;
733 }
734
735 GetRttResponderInfoCommand command(iface, responderInfo);
736 return (wifi_error) command.requestResponse();
737
738 }
739
740 /**
741 * Enable RTT responder mode.
742 * channel_hint - hint of the channel information where RTT responder should be enabled on.
743 * max_duration_seconds - timeout of responder mode.
744 * wifi_rtt_responder - information for RTT responder e.g. channel used and preamble supported.
745 */
wifi_enable_responder(wifi_request_id id,wifi_interface_handle iface,wifi_channel_info channel_hint,unsigned max_duration_seconds,wifi_rtt_responder * responderInfo)746 wifi_error wifi_enable_responder(wifi_request_id id, wifi_interface_handle iface,
747 wifi_channel_info channel_hint, unsigned max_duration_seconds,
748 wifi_rtt_responder* responderInfo)
749 {
750 EnableResponderCommand command(iface, id, channel_hint, max_duration_seconds, responderInfo);
751 return (wifi_error) command.requestResponse();
752 }
753
754 /**
755 * Disable RTT responder mode.
756 */
wifi_disable_responder(wifi_request_id id,wifi_interface_handle iface)757 wifi_error wifi_disable_responder(wifi_request_id id, wifi_interface_handle iface)
758 {
759 CancelResponderCommand command(iface, id);
760 return (wifi_error) command.requestResponse();
761 }
762
763