1115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <stdint.h>
2115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <fcntl.h>
3115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <sys/socket.h>
4115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <netlink/genl/genl.h>
5115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <netlink/genl/family.h>
6115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <netlink/genl/ctrl.h>
7115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <linux/rtnetlink.h>
8115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <netpacket/packet.h>
9115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <linux/filter.h>
10115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <linux/errqueue.h>
11115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
12115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <linux/pkt_sched.h>
13115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <netlink/object-api.h>
14115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <netlink/netlink.h>
15115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <netlink/socket.h>
16115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <netlink-types.h>
17115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
18115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include "nl80211_copy.h"
19115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
20115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include "sync.h"
21115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
22115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#define LOG_TAG  "WifiHAL"
23115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
24115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include <utils/Log.h>
25115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
26115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include "wifi_hal.h"
27115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include "common.h"
28115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin#include "cpp_bindings.h"
29115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
30115bcffc16c53e9552c09a6792666c52a633b4f2Ashwintypedef enum {
31115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
323acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START,
333acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    RTT_SUBCMD_CANCEL_CONFIG,
343acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    RTT_SUBCMD_GETCAPABILITY,
35115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin} RTT_SUB_COMMAND;
36115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
37115bcffc16c53e9552c09a6792666c52a633b4f2Ashwintypedef enum {
38115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_CNT,
39115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_INFO,
40115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_MAC,
41115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_TYPE,
42115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_PEER,
43115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_CHAN,
44115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_MODE,
45115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_INTERVAL,
46115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT,
47115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_NUM_PKT,
48115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RTT_ATTRIBUTE_TARGET_NUM_RETRY,
493acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
50115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin} GSCAN_ATTRIBUTE;
513acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco parkclass GetRttCapabilitiesCommand : public WifiCommand
523acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park{
533acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    wifi_rtt_capabilities *mCapabilities;
543acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco parkpublic:
553acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    GetRttCapabilitiesCommand(wifi_interface_handle iface, wifi_rtt_capabilities *capabitlites)
563acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        : WifiCommand(iface, 0), mCapabilities(capabitlites)
573acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    {
583acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        memset(mCapabilities, 0, sizeof(*mCapabilities));
593acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    }
603acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
613acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    virtual int create() {
623acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
633acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
643acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETCAPABILITY);
653acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        if (ret < 0) {
663acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park            return ret;
673acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        }
683acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
693acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        return ret;
703acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    }
713acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
723acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco parkprotected:
733acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    virtual int handleResponse(WifiEvent& reply) {
743acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
753acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        ALOGD("In GetRttCapabilitiesCommand::handleResponse");
763acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
773acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        if (reply.get_cmd() != NL80211_CMD_VENDOR) {
783acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park            ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
793acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park            return NL_SKIP;
803acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        }
813acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
823acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        int id = reply.get_vendor_id();
833acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        int subcmd = reply.get_vendor_subcmd();
843acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
853acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        void *data = reply.get_vendor_data();
863acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        int len = reply.get_vendor_data_len();
873acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
883acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
893acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park                    sizeof(*mCapabilities));
903acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
913acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
923acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park
933acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        return NL_OK;
943acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    }
953acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park};
96115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
97115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
98115bcffc16c53e9552c09a6792666c52a633b4f2Ashwinclass RttCommand : public WifiCommand
99115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin{
100115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    unsigned numRttParams;
101115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    static const int MAX_RESULTS = 64;
102115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    wifi_rtt_result rttResults[MAX_RESULTS];
103115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    wifi_rtt_config *rttParams;
104115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    wifi_rtt_event_handler rttHandler;
105115bcffc16c53e9552c09a6792666c52a633b4f2Ashwinpublic:
106115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config,
107115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
108115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        : WifiCommand(iface, id), numRttParams(num_rtt_config), rttParams(rtt_config),
109115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin         rttHandler(handler)
110115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    { }
111115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
112115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
113115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    int createSetupRequest(WifiRequest& request) {
114115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG);
115115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        if (result < 0) {
116115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            return result;
117115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
118115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
119115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
120115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams);
121115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        if (result < 0) {
122115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            return result;
123115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
124115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO);
125115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        for (unsigned i = 0; i < numRttParams; i++) {
126115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
127115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            nlattr *attr2 = request.attr_start(i);
128115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (attr2 == NULL) {
129115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return WIFI_ERROR_OUT_OF_MEMORY;
130115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
131115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
132115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].addr);
133115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
134115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
135115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
136115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].type);
137115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
138115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
139115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
140115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].peer);
141115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
142115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
143115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
144115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].channel,
145115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                     sizeof(wifi_channel_info));
146115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
147115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
148115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
149115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put_u8(RTT_ATTRIBUTE_TARGET_MODE, rttParams[i].continuous);
150115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
151115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
152115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
153115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put_u32(RTT_ATTRIBUTE_TARGET_INTERVAL, rttParams[i].interval);
154115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
155115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
156115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
157115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT,
158115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                     rttParams[i].num_measurements);
159115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
160115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
161115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
162115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_PKT,
163115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                     rttParams[i].num_samples_per_measurement);
164115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
165115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
166115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
167115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY,
168115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                     rttParams[i].num_retries_per_measurement);
169115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
170115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
171115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
172115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            request.attr_end(attr2);
173115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
174115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
175115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        request.attr_end(rtt_config);
176115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        request.attr_end(data);
177115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        return WIFI_SUCCESS;
178115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    }
179115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
180115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) {
1813acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        int result = request.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_CONFIG);
182115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        if (result < 0) {
183115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            return result;
184115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
185115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
186115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1873acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
188115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        for(unsigned i = 0; i < num_devices; i++) {
189115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
190115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result < 0) {
191115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                return result;
192115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
193115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
194115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        request.attr_end(data);
195115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        return result;
196115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    }
197115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    int start() {
19868d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande        ALOGD("Setting RTT configuration");
199115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        WifiRequest request(familyId(), ifaceId());
200115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        int result = createSetupRequest(request);
201115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        if (result != WIFI_SUCCESS) {
202115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            ALOGE("failed to create setup request; result = %d", result);
203115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            return result;
204115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
205115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
206115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        result = requestResponse(request);
207115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        if (result != WIFI_SUCCESS) {
20868d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande            ALOGE("failed to configure RTT setup; result = %d", result);
209115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            return result;
210115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
211115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
212115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
21368d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande        ALOGI("Successfully started RTT operation");
214115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        return result;
215115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    }
216115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
217115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    virtual int cancel() {
21868d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande        ALOGD("Stopping RTT");
219115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
220115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        WifiRequest request(familyId(), ifaceId());
221115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        int result = createTeardownRequest(request, 0, NULL);
222115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        if (result != WIFI_SUCCESS) {
223115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            ALOGE("failed to create stop request; result = %d", result);
224115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        } else {
225115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = requestResponse(request);
226115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result != WIFI_SUCCESS) {
227115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin                ALOGE("failed to stop scan; result = %d", result);
228115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
229115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
230115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
23168d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande        unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
232115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        return WIFI_SUCCESS;
233115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    }
234115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
235115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    int cancel_specific(unsigned num_devices, mac_addr addr[]) {
236115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        ALOGD("Stopping scan");
237115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
238115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        WifiRequest request(familyId(), ifaceId());
239115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        int result = createTeardownRequest(request, num_devices, addr);
240115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        if (result != WIFI_SUCCESS) {
241115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            ALOGE("failed to create stop request; result = %d", result);
242115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        } else {
243115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            result = requestResponse(request);
244115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            if (result != WIFI_SUCCESS) {
24568d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande                ALOGE("failed to stop RTT; result = %d", result);
246115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            }
247115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
248115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
24968d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande        unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
250115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        return WIFI_SUCCESS;
251115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    }
252115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
253115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    virtual int handleResponse(WifiEvent& reply) {
254115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        /* Nothing to do on response! */
255115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        return NL_SKIP;
256115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    }
257115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
258115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    virtual int handleEvent(WifiEvent& event) {
259732e4dd91aebbfb225feaed05893e2ec76842a10Vinit Deshpande        ALOGI("Got an RTT event");
260115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
261115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        // event.log();
262115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
263115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
264115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        int len = event.get_vendor_data_len();
265115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
266115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        if (vendor_data == NULL || len == 0) {
267115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin            ALOGI("No rtt results found");
268115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        }
269115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
27068d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande        unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
27168d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande        wifi_unregister_cmd(wifiHandle(), id());
27268d1fb64d52132a52bcad3450d6783939d8d9726Vinit Deshpande
273115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        memset(rttResults, 0, sizeof(wifi_rtt_result) * MAX_RESULTS);
274115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
275115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        int num = len / sizeof(wifi_rtt_result);
276115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        num = min(MAX_RESULTS, num);
277115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        memcpy(rttResults, event.get_vendor_data(), num * sizeof(wifi_rtt_result));
278115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        ALOGI("Retrieved %d rtt results", num);
279115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
280115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        (*rttHandler.on_rtt_results)(id(), num, rttResults);
281115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        return NL_SKIP;
282115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    }
283115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin};
284115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
285115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
286115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin/* API to request RTT measurement */
287115bcffc16c53e9552c09a6792666c52a633b4f2Ashwinwifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
288115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
289115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin{
290115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    wifi_handle handle = getWifiHandle(iface);
291115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
292115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
293115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    wifi_register_cmd(handle, id, cmd);
294115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    return (wifi_error)cmd->start();
295115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin}
296115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
297115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin/* API to cancel RTT measurements */
298115bcffc16c53e9552c09a6792666c52a633b4f2Ashwinwifi_error wifi_rtt_range_cancel(wifi_request_id id,  wifi_interface_handle iface,
299115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        unsigned num_devices, mac_addr addr[])
300115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin{
301115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    wifi_handle handle = getWifiHandle(iface);
3023acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    RttCommand *cmd = (RttCommand *)wifi_unregister_cmd(handle, id);
303115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    if (cmd) {
304115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        cmd->cancel_specific(num_devices, addr);
30528237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande        cmd->releaseRef();
306115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin        return WIFI_SUCCESS;
307115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    }
308115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
309115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin    return WIFI_ERROR_INVALID_ARGS;
310115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin}
31128237f92de2634ec1d529c63b2d61d80e7485c83Vinit Deshpande
3123acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park/* API to get RTT capability */
3133acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco parkwifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
3143acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park        wifi_rtt_capabilities *capabilities)
3153acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park{
3163acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    GetRttCapabilitiesCommand command(iface, capabilities);
3173acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park    return (wifi_error) command.requestResponse();
3183acd5f599fa32a9a66a1f5bda8f17b4837140924Ecco park}
319115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
320115bcffc16c53e9552c09a6792666c52a633b4f2Ashwin
321