Added support for channel list
[android/platform/hardware/broadcom/wlan.git] / bcmdhd / wifi_hal / rtt.cpp
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
26 #include "wifi_hal.h"
27 #include "common.h"
28 #include "cpp_bindings.h"
29
30 typedef enum {
31
32     RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START
33
34 } RTT_SUB_COMMAND;
35
36 typedef enum {
37     RTT_ATTRIBUTE_TARGET_CNT,
38     RTT_ATTRIBUTE_TARGET_INFO,
39     RTT_ATTRIBUTE_TARGET_MAC,
40     RTT_ATTRIBUTE_TARGET_TYPE,
41     RTT_ATTRIBUTE_TARGET_PEER,
42     RTT_ATTRIBUTE_TARGET_CHAN,
43     RTT_ATTRIBUTE_TARGET_MODE,
44     RTT_ATTRIBUTE_TARGET_INTERVAL,
45     RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT,
46     RTT_ATTRIBUTE_TARGET_NUM_PKT,
47     RTT_ATTRIBUTE_TARGET_NUM_RETRY,
48     RTT_ATTRIBUTE_FLUSH_CFG
49 } GSCAN_ATTRIBUTE;
50
51
52 class RttCommand : public WifiCommand
53 {
54     unsigned numRttParams;
55     static const int MAX_RESULTS = 64;
56     wifi_rtt_result rttResults[MAX_RESULTS];
57     wifi_rtt_config *rttParams;
58     wifi_rtt_event_handler rttHandler;
59 public:
60     RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config,
61                 wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
62         : WifiCommand(iface, id), numRttParams(num_rtt_config), rttParams(rtt_config),
63          rttHandler(handler)
64     { }
65
66
67     int createSetupRequest(WifiRequest& request) {
68         int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG);
69         if (result < 0) {
70             return result;
71         }
72
73         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
74         result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams);
75         if (result < 0) {
76             return result;
77         }
78         nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO);
79         for (unsigned i = 0; i < numRttParams; i++) {
80
81             nlattr *attr2 = request.attr_start(i);
82             if (attr2 == NULL) {
83                 return WIFI_ERROR_OUT_OF_MEMORY;
84             }
85
86             result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].addr);
87             if (result < 0) {
88                 return result;
89             }
90             result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].type);
91             if (result < 0) {
92                 return result;
93             }
94             result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].peer);
95             if (result < 0) {
96                 return result;
97             }
98             result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].channel,
99                      sizeof(wifi_channel_info));
100             if (result < 0) {
101                 return result;
102             }
103             result = request.put_u8(RTT_ATTRIBUTE_TARGET_MODE, rttParams[i].continuous);
104             if (result < 0) {
105                 return result;
106             }
107             result = request.put_u32(RTT_ATTRIBUTE_TARGET_INTERVAL, rttParams[i].interval);
108             if (result < 0) {
109                 return result;
110             }
111             result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT,
112                      rttParams[i].num_measurements);
113             if (result < 0) {
114                 return result;
115             }
116             result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_PKT,
117                      rttParams[i].num_samples_per_measurement);
118             if (result < 0) {
119                 return result;
120             }
121             result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY,
122                      rttParams[i].num_retries_per_measurement);
123             if (result < 0) {
124                 return result;
125             }
126             request.attr_end(attr2);
127         }
128
129         request.attr_end(rtt_config);
130         request.attr_end(data);
131         return WIFI_SUCCESS;
132     }
133
134     int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) {
135         int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG);
136         if (result < 0) {
137             return result;
138         }
139
140         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
141         struct nlattr * attr = request.attr_start(RTT_ATTRIBUTE_FLUSH_CFG);
142         for(unsigned i = 0; i < num_devices; i++) {
143             result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
144             if (result < 0) {
145                 return result;
146             }
147         }
148
149         request.attr_end(attr);
150         request.attr_end(data);
151         return result;
152     }
153     int start() {
154         ALOGD("Setting configuration");
155         WifiRequest request(familyId(), ifaceId());
156         int result = createSetupRequest(request);
157         if (result != WIFI_SUCCESS) {
158             ALOGE("failed to create setup request; result = %d", result);
159             return result;
160         }
161
162         result = requestResponse(request);
163         if (result != WIFI_SUCCESS) {
164             ALOGE("failed to configure setup; result = %d", result);
165             return result;
166         }
167
168         registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
169
170         result = requestResponse(request);
171         if (result < 0) {
172             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS);
173             return result;
174         }
175
176         ALOGI("successfully restarted the scan");
177         return result;
178     }
179
180     virtual int cancel() {
181         ALOGD("Stopping scan");
182
183         WifiRequest request(familyId(), ifaceId());
184         int result = createTeardownRequest(request, 0, NULL);
185         if (result != WIFI_SUCCESS) {
186             ALOGE("failed to create stop request; result = %d", result);
187         } else {
188             result = requestResponse(request);
189             if (result != WIFI_SUCCESS) {
190                 ALOGE("failed to stop scan; result = %d", result);
191             }
192         }
193
194         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
195         return WIFI_SUCCESS;
196     }
197
198     int cancel_specific(unsigned num_devices, mac_addr addr[]) {
199         ALOGD("Stopping scan");
200
201         WifiRequest request(familyId(), ifaceId());
202         int result = createTeardownRequest(request, num_devices, addr);
203         if (result != WIFI_SUCCESS) {
204             ALOGE("failed to create stop request; result = %d", result);
205         } else {
206             result = requestResponse(request);
207             if (result != WIFI_SUCCESS) {
208                 ALOGE("failed to stop scan; result = %d", result);
209             }
210         }
211
212         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
213         return WIFI_SUCCESS;
214     }
215
216     virtual int handleResponse(WifiEvent& reply) {
217         /* Nothing to do on response! */
218         return NL_SKIP;
219     }
220
221     virtual int handleEvent(WifiEvent& event) {
222         ALOGI("Got a scan results event");
223
224         // event.log();
225
226         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
227         int len = event.get_vendor_data_len();
228
229         if (vendor_data == NULL || len == 0) {
230             ALOGI("No rtt results found");
231             return NL_SKIP;
232         }
233
234         memset(rttResults, 0, sizeof(wifi_rtt_result) * MAX_RESULTS);
235
236         int num = len / sizeof(wifi_rtt_result);
237         num = min(MAX_RESULTS, num);
238         memcpy(rttResults, event.get_vendor_data(), num * sizeof(wifi_rtt_result));
239         ALOGI("Retrieved %d rtt results", num);
240
241         (*rttHandler.on_rtt_results)(id(), num, rttResults);
242         return NL_SKIP;
243     }
244 };
245
246
247 /* API to request RTT measurement */
248 wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
249         unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
250 {
251     wifi_handle handle = getWifiHandle(iface);
252
253     RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
254     wifi_register_cmd(handle, id, cmd);
255     return (wifi_error)cmd->start();
256 }
257
258 /* API to cancel RTT measurements */
259 wifi_error wifi_rtt_range_cancel(wifi_request_id id,  wifi_interface_handle iface,
260         unsigned num_devices, mac_addr addr[])
261 {
262     wifi_handle handle = getWifiHandle(iface);
263
264     RttCommand *cmd = (RttCommand *)wifi_get_cmd(handle, id);
265     if (cmd) {
266         cmd->cancel_specific(num_devices, addr);
267         return WIFI_SUCCESS;
268     }
269
270     return WIFI_ERROR_INVALID_ARGS;
271 }
272
273
274