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