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