1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Portions copyright (C) 2023 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_V3_SIZE (sizeof(wifi_rtt_result_v3))
50 #define RTT_RESULT_V2_SIZE (sizeof(wifi_rtt_result_v2))
51 #define RTT_RESULT_V1_SIZE (sizeof(wifi_rtt_result))
52 #define UNSPECIFIED -1 // wifi HAL common definition for unspecified value
53 typedef enum {
54
55 RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
56 RTT_SUBCMD_CANCEL_CONFIG,
57 RTT_SUBCMD_GETCAPABILITY,
58 RTT_SUBCMD_GETAVAILCHANNEL,
59 RTT_SUBCMD_SET_RESPONDER,
60 RTT_SUBCMD_CANCEL_RESPONDER,
61 } RTT_SUB_COMMAND;
62
63 typedef enum {
64 RTT_ATTRIBUTE_TARGET_INVALID = 0,
65 RTT_ATTRIBUTE_TARGET_CNT = 1,
66 RTT_ATTRIBUTE_TARGET_INFO = 2,
67 RTT_ATTRIBUTE_TARGET_MAC = 3,
68 RTT_ATTRIBUTE_TARGET_TYPE = 4,
69 RTT_ATTRIBUTE_TARGET_PEER = 5,
70 RTT_ATTRIBUTE_TARGET_CHAN = 6,
71 RTT_ATTRIBUTE_TARGET_PERIOD = 7,
72 RTT_ATTRIBUTE_TARGET_NUM_BURST = 8,
73 RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST = 9,
74 RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM = 10,
75 RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR = 11,
76 RTT_ATTRIBUTE_TARGET_LCI = 12,
77 RTT_ATTRIBUTE_TARGET_LCR = 13,
78 RTT_ATTRIBUTE_TARGET_BURST_DURATION = 14,
79 RTT_ATTRIBUTE_TARGET_PREAMBLE = 15,
80 RTT_ATTRIBUTE_TARGET_BW = 16,
81 RTT_ATTRIBUTE_TARGET_NTB_MIN_MEAS_TIME = 17,
82 RTT_ATTRIBUTE_TARGET_NTB_MAX_MEAS_TIME = 18,
83 /* Add Attributes related to the event */
84 RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
85 RTT_ATTRIBUTE_RESULTS_PER_TARGET = 31,
86 RTT_ATTRIBUTE_RESULT_CNT = 32,
87 RTT_ATTRIBUTE_RESULT = 33,
88 RTT_ATTRIBUTE_RESUTL_DETAIL = 34,
89 RTT_ATTRIBUTE_RESULT_FREQ = 35,
90 RTT_ATTRIBUTE_RESULT_BW = 36,
91 RTT_ATTRIBUTE_RESULT_I2R_TX_LTF_RPT_CNT = 37,
92 RTT_ATTRIBUTE_RESULT_R2I_TX_LTF_RPT_CNT = 38,
93 RTT_ATTRIBUTE_RESULT_NTB_MIN_MEAS_TIME = 39,
94 RTT_ATTRIBUTE_RESULT_NTB_MAX_MEAS_TIME = 40,
95 /* Add any new RTT_ATTRIBUTE prior to RTT_ATTRIBUTE_MAX */
96 RTT_ATTRIBUTE_MAX
97 } RTT_ATTRIBUTE;
98 typedef struct strmap_entry {
99 int id;
100 String8 text;
101 } strmap_entry_t;
102 struct dot11_rm_ie {
103 u8 id;
104 u8 len;
105 u8 token;
106 u8 mode;
107 u8 type;
108 } __attribute__ ((packed));
109 typedef struct dot11_rm_ie dot11_rm_ie_t;
110 #define DOT11_HDR_LEN 2
111 #define DOT11_RM_IE_LEN 5
112 #define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
113 #define DOT11_MNG_MEASURE_REPORT_ID 39 /* 11H MeasurementResponse */
114 #define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */
115 #define DOT11_MEASURE_TYPE_CIVICLOC 11 /* d11 measurement location civic */
116
117 static const strmap_entry_t err_info[] = {
118 {RTT_STATUS_SUCCESS, String8("Success")},
119 {RTT_STATUS_FAILURE, String8("Failure")},
120 {RTT_STATUS_FAIL_NO_RSP, String8("No reponse")},
121 {RTT_STATUS_FAIL_INVALID_TS, String8("Invalid Timestamp")},
122 {RTT_STATUS_FAIL_PROTOCOL, String8("Protocol error")},
123 {RTT_STATUS_FAIL_REJECTED, String8("Rejected")},
124 {RTT_STATUS_FAIL_NOT_SCHEDULED_YET, String8("not scheduled")},
125 {RTT_STATUS_FAIL_SCHEDULE, String8("schedule failed")},
126 {RTT_STATUS_FAIL_TM_TIMEOUT, String8("timeout")},
127 {RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, String8("AP is on difference channel")},
128 {RTT_STATUS_FAIL_NO_CAPABILITY, String8("no capability")},
129 {RTT_STATUS_FAIL_BUSY_TRY_LATER, String8("busy and try later")},
130 {RTT_STATUS_ABORTED, String8("aborted")}
131 };
132
133 static const char*
get_err_info(int status)134 get_err_info(int status)
135 {
136 int i;
137 const strmap_entry_t *p_entry;
138 int num_entries = sizeof(err_info)/ sizeof(err_info[0]);
139 /* scan thru the table till end */
140 p_entry = err_info;
141 for (i = 0; i < (int) num_entries; i++)
142 {
143 if (p_entry->id == status)
144 return p_entry->text.c_str();
145 p_entry++; /* next entry */
146 }
147 return "unknown error"; /* not found */
148 }
149
150 class GetRttCapabilitiesCommand : public WifiCommand
151 {
152 wifi_rtt_capabilities_v3 *mCapabilities;
153 public:
GetRttCapabilitiesCommand(wifi_interface_handle iface,wifi_rtt_capabilities_v3 * capabitlites)154 GetRttCapabilitiesCommand(wifi_interface_handle iface, wifi_rtt_capabilities_v3 *capabitlites)
155 : WifiCommand("GetRttCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
156 {
157 memset(mCapabilities, 0, sizeof(*mCapabilities));
158 }
159
create()160 virtual int create() {
161 ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
162
163 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETCAPABILITY);
164 if (ret < 0) {
165 return ret;
166 }
167
168 return ret;
169 }
170
171 protected:
handleResponse(WifiEvent & reply)172 virtual int handleResponse(WifiEvent& reply) {
173
174 ALOGD("In GetRttCapabilitiesCommand::handleResponse");
175
176 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
177 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
178 return NL_SKIP;
179 }
180
181 int id = reply.get_vendor_id();
182 int subcmd = reply.get_vendor_subcmd();
183
184 void *data = reply.get_vendor_data();
185 int len = reply.get_vendor_data_len();
186
187 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
188 sizeof(*mCapabilities));
189
190 memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
191
192 return NL_OK;
193 }
194 };
195
196
197 class GetRttResponderInfoCommand : public WifiCommand
198 {
199 wifi_rtt_responder* mResponderInfo;
200 public:
GetRttResponderInfoCommand(wifi_interface_handle iface,wifi_rtt_responder * responderInfo)201 GetRttResponderInfoCommand(wifi_interface_handle iface, wifi_rtt_responder *responderInfo)
202 : WifiCommand("GetRttResponderInfoCommand", iface, 0), mResponderInfo(responderInfo)
203 {
204 memset(mResponderInfo, 0 , sizeof(*mResponderInfo));
205
206 }
207
create()208 virtual int create() {
209 ALOGD("Creating message to get responder info ; iface = %d", mIfaceInfo->id);
210
211 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETAVAILCHANNEL);
212 if (ret < 0) {
213 return ret;
214 }
215
216 return ret;
217 }
218
219 protected:
handleResponse(WifiEvent & reply)220 virtual int handleResponse(WifiEvent& reply) {
221
222 ALOGD("In GetRttResponderInfoCommand::handleResponse");
223
224 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
225 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
226 return NL_SKIP;
227 }
228
229 int id = reply.get_vendor_id();
230 int subcmd = reply.get_vendor_subcmd();
231
232 void *data = reply.get_vendor_data();
233 int len = reply.get_vendor_data_len();
234
235 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
236 sizeof(*mResponderInfo));
237
238 memcpy(mResponderInfo, data, min(len, (int) sizeof(*mResponderInfo)));
239
240 return NL_OK;
241 }
242 };
243
244
245 class EnableResponderCommand : public WifiCommand
246 {
247 wifi_channel_info mChannelInfo;
248 wifi_rtt_responder* mResponderInfo;
249 unsigned int m_max_duration_sec;
250 public:
EnableResponderCommand(wifi_interface_handle iface,int id,wifi_channel_info channel_hint,unsigned max_duration_seconds,wifi_rtt_responder * responderInfo)251 EnableResponderCommand(wifi_interface_handle iface, int id, wifi_channel_info channel_hint,
252 unsigned max_duration_seconds, wifi_rtt_responder *responderInfo)
253 : WifiCommand("EnableResponderCommand", iface, 0), mChannelInfo(channel_hint),
254 mResponderInfo(responderInfo), m_max_duration_sec(max_duration_seconds)
255 {
256 memset(mResponderInfo, 0, sizeof(*mResponderInfo));
257 memset(&mChannelInfo, 0, sizeof(mChannelInfo));
258 m_max_duration_sec = 0;
259 }
260
create()261 virtual int create() {
262 ALOGD("Creating message to set responder ; iface = %d", mIfaceInfo->id);
263
264 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_SET_RESPONDER);
265 if (ret < 0) {
266 return ret;
267 }
268
269 return ret;
270 }
271
272 protected:
handleResponse(WifiEvent & reply)273 virtual int handleResponse(WifiEvent& reply) {
274
275 ALOGD("In EnableResponderCommand::handleResponse");
276
277 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
278 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
279 return NL_SKIP;
280 }
281
282 int id = reply.get_vendor_id();
283 int subcmd = reply.get_vendor_subcmd();
284
285 void *data = reply.get_vendor_data();
286 int len = reply.get_vendor_data_len();
287
288 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
289 sizeof(*mResponderInfo));
290
291 memcpy(mResponderInfo, data, min(len, (int) sizeof(*mResponderInfo)));
292
293 return NL_OK;
294 }
295 };
296
297
298 class CancelResponderCommand : public WifiCommand
299 {
300
301 public:
CancelResponderCommand(wifi_interface_handle iface,int id)302 CancelResponderCommand(wifi_interface_handle iface, int id)
303 : WifiCommand("CancelResponderCommand", iface, 0)/*, mChannelInfo(channel)*/
304 {
305
306 }
307
create()308 virtual int create() {
309 ALOGD("Creating message to cancel responder ; iface = %d", mIfaceInfo->id);
310
311 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_RESPONDER);
312 if (ret < 0) {
313 return ret;
314 }
315
316 return ret;
317 }
318
319 protected:
handleResponse(WifiEvent & reply)320 virtual int handleResponse(WifiEvent& reply) {
321 /* Nothing to do on response! */
322 return NL_SKIP;
323 }
324
325 };
326
327
328 class RttCommand : public WifiCommand
329 {
330 unsigned numRttParams;
331 int mCompleted;
332 int currentIdx = 0;
333 int totalCnt = 0;
334 static const int MAX_RESULTS = 1024;
335 wifi_rtt_result *rttResultsV1[MAX_RESULTS];
336 wifi_rtt_result_v2 *rttResultsV2[MAX_RESULTS];
337 wifi_rtt_result_v3 *rttResultsV3[MAX_RESULTS];
338 wifi_rtt_config_v3 *rttParams;
339 wifi_rtt_event_handler_v3 rttHandler;
340 int nextidx = 0;
341 wifi_channel channel = 0;
342 wifi_rtt_bw bw;
343 int result_size = 0;
344 int opt_result_size = 0;
345 u8 i2r_tx_ltf_repetition_count = 0;
346 u8 r2i_tx_ltf_repetition_count = 0;
347 u32 ntb_min_measurement_time = 0;
348 u32 ntb_max_measurement_time = 0;
349
350 public:
RttCommand(wifi_interface_handle iface,int id,unsigned num_rtt_config,wifi_rtt_config_v3 rtt_config[],wifi_rtt_event_handler_v3 handler)351 RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config,
352 wifi_rtt_config_v3 rtt_config[], wifi_rtt_event_handler_v3 handler)
353 : WifiCommand("RttCommand", iface, id), numRttParams(num_rtt_config), rttParams(rtt_config),
354 rttHandler(handler)
355 {
356 memset(rttResultsV1, 0, sizeof(rttResultsV1));
357 memset(rttResultsV2, 0, sizeof(rttResultsV2));
358 memset(rttResultsV3, 0, sizeof(rttResultsV3));
359 currentIdx = 0;
360 mCompleted = 0;
361 totalCnt = 0;
362 channel = 0;
363 result_size = 0;
364 opt_result_size = 0;
365 channel = 0;
366 result_size = 0;
367 opt_result_size = 0;
368 }
369
RttCommand(wifi_interface_handle iface,int id)370 RttCommand(wifi_interface_handle iface, int id)
371 : WifiCommand("RttCommand", iface, id)
372 {
373 currentIdx = 0;
374 mCompleted = 0;
375 totalCnt = 0;
376 numRttParams = 0;
377 memset(rttResultsV1, 0, sizeof(rttResultsV1));
378 memset(rttResultsV2, 0, sizeof(rttResultsV2));
379 memset(rttResultsV3, 0, sizeof(rttResultsV3));
380 rttParams = NULL;
381 rttHandler.on_rtt_results_v3 = NULL;
382 channel = 0;
383 result_size = 0;
384 opt_result_size = 0;
385 }
386
createSetupRequest(WifiRequest & request)387 int createSetupRequest(WifiRequest& request) {
388 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG);
389 if (result < 0) {
390 return result;
391 }
392
393 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
394 result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams);
395 if (result < 0) {
396 return result;
397 }
398 nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO);
399 for (unsigned i = 0; i < numRttParams; i++) {
400 nlattr *attr2 = request.attr_start(i);
401 if (attr2 == NULL) {
402 return WIFI_ERROR_OUT_OF_MEMORY;
403 }
404
405 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].rtt_config.addr);
406 if (result < 0) {
407 return result;
408 }
409
410 result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].rtt_config.type);
411 if (result < 0) {
412 return result;
413 }
414
415 result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].rtt_config.peer);
416 if (result < 0) {
417 return result;
418 }
419
420 result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].rtt_config.channel,
421 sizeof(wifi_channel_info));
422 if (result < 0) {
423 return result;
424 }
425
426 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_BURST,
427 rttParams[i].rtt_config.num_burst);
428 if (result < 0) {
429 return result;
430 }
431
432 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
433 rttParams[i].rtt_config.num_frames_per_burst);
434 if (result < 0) {
435 return result;
436 }
437
438 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
439 rttParams[i].rtt_config.num_retries_per_rtt_frame);
440 if (result < 0) {
441 return result;
442 }
443
444 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
445 rttParams[i].rtt_config.num_retries_per_ftmr);
446 if (result < 0) {
447 return result;
448 }
449
450 result = request.put_u32(RTT_ATTRIBUTE_TARGET_PERIOD,
451 rttParams[i].rtt_config.burst_period);
452 if (result < 0) {
453 return result;
454 }
455
456 result = request.put_u32(RTT_ATTRIBUTE_TARGET_BURST_DURATION,
457 rttParams[i].rtt_config.burst_duration);
458 if (result < 0) {
459 return result;
460 }
461
462 result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCI,
463 rttParams[i].rtt_config.LCI_request);
464 if (result < 0) {
465 return result;
466 }
467
468 result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCR,
469 rttParams[i].rtt_config.LCR_request);
470 if (result < 0) {
471 return result;
472 }
473
474 result = request.put_u8(RTT_ATTRIBUTE_TARGET_BW,
475 rttParams[i].rtt_config.bw);
476 if (result < 0) {
477 return result;
478 }
479
480 result = request.put_u8(RTT_ATTRIBUTE_TARGET_PREAMBLE,
481 rttParams[i].rtt_config.preamble);
482 if (result < 0) {
483 return result;
484 }
485
486 /* Below params are applicable for only 11az ranging */
487 if (rttParams[i].rtt_config.type == RTT_TYPE_2_SIDED_11AZ_NTB) {
488 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NTB_MIN_MEAS_TIME,
489 rttParams[i].ntb_min_measurement_time);
490 if (result < 0) {
491 return result;
492 }
493
494 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NTB_MAX_MEAS_TIME,
495 rttParams[i].ntb_max_measurement_time);
496 if (result < 0) {
497 return result;
498 }
499 }
500
501 request.attr_end(attr2);
502 }
503
504 request.attr_end(rtt_config);
505 request.attr_end(data);
506 return WIFI_SUCCESS;
507 }
508
createTeardownRequest(WifiRequest & request,unsigned num_devices,mac_addr addr[])509 int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) {
510 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_CONFIG);
511 if (result < 0) {
512 return result;
513 }
514
515 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
516 result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
517
518 if (result < 0) {
519 return result;
520 }
521 for(unsigned i = 0; i < num_devices; i++) {
522 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
523 if (result < 0) {
524 return result;
525 }
526 }
527 request.attr_end(data);
528 return result;
529 }
530
start()531 int start() {
532 ALOGD("Setting RTT configuration");
533 WifiRequest request(familyId(), ifaceId());
534 int result = createSetupRequest(request);
535 if (result != WIFI_SUCCESS) {
536 ALOGE("failed to create setup request; result = %d", result);
537 return result;
538 }
539
540 registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
541
542 result = requestResponse(request);
543 if (result != WIFI_SUCCESS) {
544 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
545 ALOGE("failed to configure RTT setup; result = %d", result);
546 return result;
547 }
548
549 ALOGI("Successfully started RTT operation");
550 return result;
551 }
552
cancel()553 virtual int cancel() {
554 ALOGD("Stopping RTT");
555
556 WifiRequest request(familyId(), ifaceId());
557 int result = createTeardownRequest(request, 0, NULL);
558 if (result != WIFI_SUCCESS) {
559 ALOGE("failed to create stop request; result = %d", result);
560 } else {
561 result = requestResponse(request);
562 if (result != WIFI_SUCCESS) {
563 ALOGE("failed to stop scan; result = %d", result);
564 }
565 }
566
567 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
568 ALOGD("Stopped RTT");
569 return WIFI_SUCCESS;
570 }
571
cancel_specific(unsigned num_devices,mac_addr addr[])572 int cancel_specific(unsigned num_devices, mac_addr addr[]) {
573 ALOGE("Stopping RTT");
574
575 WifiRequest request(familyId(), ifaceId());
576 int result = createTeardownRequest(request, num_devices, addr);
577 if (result != WIFI_SUCCESS) {
578 ALOGE("failed to create stop request; result = %d", result);
579 } else {
580 result = requestResponse(request);
581 if (result != WIFI_SUCCESS) {
582 ALOGE("failed to stop RTT; result = %d", result);
583 }
584 }
585
586 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
587 return WIFI_SUCCESS;
588 }
589
handleResponse(WifiEvent & reply)590 virtual int handleResponse(WifiEvent& reply) {
591 /* Nothing to do on response! */
592 return NL_SKIP;
593 }
594
handleEvent(WifiEvent & event)595 virtual int handleEvent(WifiEvent& event) {
596 ALOGI("Got an RTT event");
597 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
598 int len = event.get_vendor_data_len();
599 if (vendor_data == NULL || len == 0) {
600 ALOGI("No rtt results found");
601 return NL_STOP;
602 }
603
604 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
605 if (it.get_type() == RTT_ATTRIBUTE_RESULTS_COMPLETE) {
606 mCompleted = it.get_u32();
607 ALOGI("Completed flag : %d\n", mCompleted);
608 } else if (it.get_type() == RTT_ATTRIBUTE_RESULTS_PER_TARGET) {
609 int result_cnt = 0;
610 mac_addr bssid;
611 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
612 if (it2.get_type() == RTT_ATTRIBUTE_TARGET_MAC) {
613 memcpy(bssid, it2.get_data(), sizeof(mac_addr));
614 ALOGI("target mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
615 bssid[0], bssid[1], bssid[2], bssid[3],
616 bssid[4], bssid[5]);
617 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_FREQ) {
618 channel = it2.get_u32();
619 if (rttResultsV3[currentIdx] == NULL) {
620 ALOGE("Not allocated, currentIdx %d\n", currentIdx);
621 break;
622 }
623 if (!channel) {
624 rttResultsV3[currentIdx]->rtt_result.frequency =
625 UNSPECIFIED;
626 } else {
627 rttResultsV3[currentIdx]->rtt_result.frequency =
628 channel;
629 }
630
631 ALOGI("rtt_resultV3 : \n\tchannel :%d",
632 rttResultsV3[currentIdx]->rtt_result.frequency);
633 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_BW) {
634 bw = (wifi_rtt_bw)it2.get_u32();
635 if (rttResultsV3[currentIdx] == NULL) {
636 ALOGE("Not allocated, currentIdx %d\n", currentIdx);
637 break;
638 }
639 rttResultsV3[currentIdx]->rtt_result.packet_bw =
640 bw;
641
642 ALOGI("rtt_resultV3 : \n\tpacket_bw :%d",
643 rttResultsV3[currentIdx]->rtt_result.packet_bw);
644 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_CNT) {
645 result_cnt = it2.get_u32();
646 ALOGI("result_cnt : %d\n", result_cnt);
647 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_I2R_TX_LTF_RPT_CNT) {
648 i2r_tx_ltf_repetition_count = it2.get_u8();
649 if (rttResultsV3[currentIdx] == NULL) {
650 ALOGE("Not allocated, currentIdx %d\n", currentIdx);
651 break;
652 }
653 rttResultsV3[currentIdx]->i2r_tx_ltf_repetition_count =
654 i2r_tx_ltf_repetition_count;
655 ALOGI("rtt_resultv3 : \n\ti2r_tx_ltf_repetition_count :%d",
656 rttResultsV3[currentIdx]->i2r_tx_ltf_repetition_count);
657 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_R2I_TX_LTF_RPT_CNT) {
658 r2i_tx_ltf_repetition_count = it2.get_u8();
659 if (rttResultsV3[currentIdx] == NULL) {
660 ALOGE("Not allocated, currentIdx %d\n", currentIdx);
661 break;
662 }
663 rttResultsV3[currentIdx]->r2i_tx_ltf_repetition_count =
664 r2i_tx_ltf_repetition_count;
665 ALOGI("rtt_resultv3 : \n\tr2i_tx_ltf_repetition_count :%d",
666 rttResultsV3[currentIdx]->r2i_tx_ltf_repetition_count);
667 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_NTB_MIN_MEAS_TIME) {
668 ntb_min_measurement_time = it2.get_u32();
669 if (rttResultsV3[currentIdx] == NULL) {
670 ALOGE("Not allocated, currentIdx %d\n", currentIdx);
671 break;
672 }
673 rttResultsV3[currentIdx]->ntb_min_measurement_time =
674 ntb_min_measurement_time;
675 ALOGI("rtt_resultv3 : \n\t ntb_min_measurement_time :%lu units of 100 us",
676 rttResultsV3[currentIdx]->ntb_min_measurement_time);
677 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_NTB_MAX_MEAS_TIME) {
678 ntb_max_measurement_time = it2.get_u32();
679 if (rttResultsV3[currentIdx] == NULL) {
680 ALOGE("Not allocated, currentIdx %d\n", currentIdx);
681 break;
682 }
683 rttResultsV3[currentIdx]->ntb_max_measurement_time =
684 ntb_max_measurement_time;
685 ALOGI("rtt_resultv3 : \n\t ntb_max_measurement_time:%lu units of 10ms",
686 rttResultsV3[currentIdx]->ntb_max_measurement_time);
687 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT) {
688 currentIdx = nextidx;
689 int result_len = it2.get_len();
690 rttResultsV1[currentIdx] =
691 (wifi_rtt_result *)malloc(it2.get_len());
692 wifi_rtt_result *rtt_results_v1 = rttResultsV1[currentIdx];
693 if (rtt_results_v1 == NULL) {
694 mCompleted = 1;
695 ALOGE("failed to allocate the wifi_result_v1\n");
696 break;
697 }
698
699 /* Populate to the rtt_results_v1 struct */
700 memcpy(rtt_results_v1, it2.get_data(), it2.get_len());
701
702 /* handle the optional data */
703 result_len -= RTT_RESULT_V1_SIZE;
704 if (result_len > 0) {
705 dot11_rm_ie_t *ele_1;
706 dot11_rm_ie_t *ele_2;
707 /* The result has LCI or LCR element */
708 ele_1 = (dot11_rm_ie_t *)(rtt_results_v1 + 1);
709 if (ele_1->id == DOT11_MNG_MEASURE_REPORT_ID) {
710 if (ele_1->type == DOT11_MEASURE_TYPE_LCI) {
711 rtt_results_v1->LCI = (wifi_information_element *)ele_1;
712 result_len -= (ele_1->len + DOT11_HDR_LEN);
713 opt_result_size += (ele_1->len + DOT11_HDR_LEN);
714 /* get a next rm ie */
715 if (result_len > 0) {
716 ele_2 = (dot11_rm_ie_t *)((char *)ele_1 +
717 (ele_1->len + DOT11_HDR_LEN));
718 if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
719 (ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) {
720 rtt_results_v1->LCR = (wifi_information_element *)ele_2;
721 }
722 }
723 } else if (ele_1->type == DOT11_MEASURE_TYPE_CIVICLOC) {
724 rtt_results_v1->LCR = (wifi_information_element *)ele_1;
725 result_len -= (ele_1->len + DOT11_HDR_LEN);
726 opt_result_size += (ele_1->len + DOT11_HDR_LEN);
727 /* get a next rm ie */
728 if (result_len > 0) {
729 ele_2 = (dot11_rm_ie_t *)((char *)ele_1 +
730 (ele_1->len + DOT11_HDR_LEN));
731 if ((ele_2->id == DOT11_MNG_MEASURE_REPORT_ID) &&
732 (ele_2->type == DOT11_MEASURE_TYPE_LCI)) {
733 rtt_results_v1->LCI = (wifi_information_element *)ele_2;
734 }
735 }
736 }
737 }
738 }
739
740 /* Alloc struct v2 including new elements of ver2 */
741 rttResultsV2[currentIdx] =
742 (wifi_rtt_result_v2 *)malloc(RTT_RESULT_V2_SIZE + opt_result_size);
743 wifi_rtt_result_v2 *rtt_result_v2 = rttResultsV2[currentIdx];
744 if (rtt_result_v2 == NULL) {
745 ALOGE("failed to allocate the rtt_result\n");
746 break;
747 }
748
749 /* Populate the v2 result struct as per the v1 result struct elements */
750 memcpy(&rtt_result_v2->rtt_result,
751 (wifi_rtt_result *)rtt_results_v1, RTT_RESULT_V1_SIZE);
752 if (!channel) {
753 rtt_result_v2->frequency = UNSPECIFIED;
754 }
755
756 /* Copy the optional v1 data to v2 struct */
757 if (opt_result_size &&
758 (opt_result_size == (it2.get_len() - RTT_RESULT_V1_SIZE))) {
759
760 wifi_rtt_result_v2 *opt_rtt_result_v2 = NULL;
761 /* Intersect the optional data from v1 rtt result struct */
762 wifi_rtt_result *opt_rtt_result_v1 =
763 (wifi_rtt_result *)(rtt_results_v1 + 1);
764
765 /* Move to v2 ptr to the start of the optional params */
766 opt_rtt_result_v2 =
767 (wifi_rtt_result_v2 *)(rtt_result_v2 + 1);
768
769 /* Append optional rtt_result_v1 data to optional rtt_result_v2 */
770 memcpy(opt_rtt_result_v2, opt_rtt_result_v1,
771 (it2.get_len() - RTT_RESULT_V1_SIZE));
772 } else {
773 ALOGI("Optional rtt result elements missing, skip processing\n");
774 }
775
776 /* Alloc struct v3 including new elements, reserve for new elements */
777 rttResultsV3[currentIdx] =
778 (wifi_rtt_result_v3 *)malloc(RTT_RESULT_V3_SIZE + opt_result_size);
779 wifi_rtt_result_v3 *rtt_result_v3 = rttResultsV3[currentIdx];
780 if (rtt_result_v3 == NULL) {
781 ALOGE("failed to allocate the rtt_result ver3\n");
782 break;
783 }
784
785 /* Populate the v3 struct with v1 struct, v1 struct opt + v2 struct + v2 struct opt */
786 memcpy(&rtt_result_v3->rtt_result,
787 (wifi_rtt_result_v2 *)rtt_result_v2,
788 RTT_RESULT_V2_SIZE + opt_result_size);
789
790 totalCnt++;
791 nextidx = currentIdx;
792 nextidx++;
793 }
794 }
795 ALOGI("Current Id: %d: retrieved rtt_resultv3 :\n"
796 " burst_num : %d, measurement_number : %d,\n"
797 " success_number : %d, number_per_burst_peer : %d, status : %s,\n"
798 " retry_after_duration : %d rssi : %d dbm,\n"
799 " rx_rate : %d Kbps, rtt : %lu pss, rtt_sd : %lu ps,\n"
800 " distance : %d mm, burst_duration : %d ms, freq : %d,\n"
801 " packet_bw : %d, negotiated_burst_num : %d\n",
802 currentIdx,
803 rttResultsV3[currentIdx]->rtt_result.rtt_result.burst_num,
804 rttResultsV3[currentIdx]->rtt_result.rtt_result.measurement_number,
805 rttResultsV3[currentIdx]->rtt_result.rtt_result.success_number,
806 rttResultsV3[currentIdx]->rtt_result.rtt_result.number_per_burst_peer,
807 get_err_info(rttResultsV3[currentIdx]->rtt_result.rtt_result.status),
808 rttResultsV3[currentIdx]->rtt_result.rtt_result.retry_after_duration,
809 rttResultsV3[currentIdx]->rtt_result.rtt_result.rssi,
810 rttResultsV3[currentIdx]->rtt_result.rtt_result.rx_rate.bitrate * 100,
811 (unsigned long)rttResultsV3[currentIdx]->rtt_result.rtt_result.rtt,
812 (unsigned long)rttResultsV3[currentIdx]->rtt_result.rtt_result.rtt_sd,
813 rttResultsV3[currentIdx]->rtt_result.rtt_result.distance_mm,
814 rttResultsV3[currentIdx]->rtt_result.rtt_result.burst_duration,
815 rttResultsV3[currentIdx]->rtt_result.frequency,
816 rttResultsV3[currentIdx]->rtt_result.packet_bw,
817 rttResultsV3[currentIdx]->rtt_result.rtt_result.negotiated_burst_num);
818
819 }
820 }
821
822 if (mCompleted) {
823 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
824 {
825 if (*rttHandler.on_rtt_results_v3) {
826 (*rttHandler.on_rtt_results_v3)(id(), totalCnt, rttResultsV3);
827 }
828 }
829
830 for (int i = 0; i < currentIdx; i++) {
831 free(rttResultsV1[i]);
832 rttResultsV1[i] = NULL;
833
834 free(rttResultsV2[i]);
835 rttResultsV2[i] = NULL;
836
837 free(rttResultsV3[i]);
838 rttResultsV3[i] = NULL;
839 }
840 totalCnt = currentIdx = nextidx = 0;
841 WifiCommand *cmd = wifi_unregister_cmd(wifiHandle(), id());
842 if (cmd)
843 cmd->releaseRef();
844 }
845 return NL_SKIP;
846 }
847 };
848
849
850 /* API to request RTT measurement */
wifi_rtt_range_request_v3(wifi_request_id id,wifi_interface_handle iface,unsigned num_rtt_config,wifi_rtt_config_v3 rtt_config[],wifi_rtt_event_handler_v3 handler)851 wifi_error wifi_rtt_range_request_v3(wifi_request_id id, wifi_interface_handle iface,
852 unsigned num_rtt_config, wifi_rtt_config_v3 rtt_config[],
853 wifi_rtt_event_handler_v3 handler)
854 {
855 if (iface == NULL) {
856 ALOGE("wifi_rtt_range_request_v3: NULL iface pointer provided."
857 " Exit.");
858 return WIFI_ERROR_INVALID_ARGS;
859 }
860
861 wifi_handle handle = getWifiHandle(iface);
862 if (handle == NULL) {
863 ALOGE("wifi_rtt_range_request_v3: NULL handle pointer provided."
864 " Exit.");
865 return WIFI_ERROR_INVALID_ARGS;
866 }
867
868 ALOGI("Rtt range_request; id = %d", id);
869 RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
870 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
871 wifi_error result = wifi_register_cmd(handle, id, cmd);
872 if (result != WIFI_SUCCESS) {
873 cmd->releaseRef();
874 return result;
875 }
876 result = (wifi_error)cmd->start();
877 if (result != WIFI_SUCCESS) {
878 wifi_unregister_cmd(handle, id);
879 cmd->releaseRef();
880 return result;
881 }
882 return result;
883 }
884
885 /* API to cancel RTT measurements */
wifi_rtt_range_cancel(wifi_request_id id,wifi_interface_handle iface,unsigned num_devices,mac_addr addr[])886 wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface,
887 unsigned num_devices, mac_addr addr[])
888 {
889 if (iface == NULL) {
890 ALOGE("wifi_rtt_range_cancel: NULL iface pointer provided."
891 " Exit.");
892 return WIFI_ERROR_INVALID_ARGS;
893 }
894
895 wifi_handle handle = getWifiHandle(iface);
896 if (handle == NULL) {
897 ALOGE("wifi_rtt_range_cancel: NULL handle pointer provided."
898 " Exit.");
899 return WIFI_ERROR_INVALID_ARGS;
900 }
901
902 ALOGI("Rtt range_cancel_request; id = %d", id);
903 RttCommand *cmd = new RttCommand(iface, id);
904 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
905 cmd->cancel_specific(num_devices, addr);
906 wifi_unregister_cmd(handle, id);
907 cmd->releaseRef();
908 return WIFI_SUCCESS;
909 }
910
911 /* API to get RTT capability */
wifi_get_rtt_capabilities_v3(wifi_interface_handle iface,wifi_rtt_capabilities_v3 * capabilities)912 wifi_error wifi_get_rtt_capabilities_v3(wifi_interface_handle iface,
913 wifi_rtt_capabilities_v3 *capabilities)
914 {
915 if (iface == NULL) {
916 ALOGE("wifi_get_rtt_capabilities_v3: NULL iface pointer provided."
917 " Exit.");
918 return WIFI_ERROR_INVALID_ARGS;
919 }
920
921 if (capabilities == NULL) {
922 ALOGE("wifi_get_rtt_capabilities_v3: NULL capabilities pointer provided."
923 " Exit.");
924 return WIFI_ERROR_INVALID_ARGS;
925 }
926
927 GetRttCapabilitiesCommand command(iface, capabilities);
928 return (wifi_error) command.requestResponse();
929 }
930
931 /* API to get the responder information */
wifi_rtt_get_responder_info(wifi_interface_handle iface,wifi_rtt_responder * responderInfo)932 wifi_error wifi_rtt_get_responder_info(wifi_interface_handle iface,
933 wifi_rtt_responder* responderInfo)
934 {
935 if (iface == NULL) {
936 ALOGE("wifi_rtt_get_responder_info: NULL iface pointer provided."
937 " Exit.");
938 return WIFI_ERROR_INVALID_ARGS;
939 }
940
941 GetRttResponderInfoCommand command(iface, responderInfo);
942 return (wifi_error) command.requestResponse();
943
944 }
945
946 /**
947 * Enable RTT responder mode.
948 * channel_hint - hint of the channel information where RTT responder should be enabled on.
949 * max_duration_seconds - timeout of responder mode.
950 * wifi_rtt_responder - information for RTT responder e.g. channel used and preamble supported.
951 */
wifi_enable_responder(wifi_request_id id,wifi_interface_handle iface,wifi_channel_info channel_hint,unsigned max_duration_seconds,wifi_rtt_responder * responderInfo)952 wifi_error wifi_enable_responder(wifi_request_id id, wifi_interface_handle iface,
953 wifi_channel_info channel_hint, unsigned max_duration_seconds,
954 wifi_rtt_responder* responderInfo)
955 {
956 EnableResponderCommand command(iface, id, channel_hint, max_duration_seconds, responderInfo);
957 return (wifi_error) command.requestResponse();
958 }
959
960 /**
961 * Disable RTT responder mode.
962 */
wifi_disable_responder(wifi_request_id id,wifi_interface_handle iface)963 wifi_error wifi_disable_responder(wifi_request_id id, wifi_interface_handle iface)
964 {
965 CancelResponderCommand command(iface, id);
966 return (wifi_error) command.requestResponse();
967 }
968
969