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