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