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 RTT_SUBCMD_CANCEL_CONFIG,
34 RTT_SUBCMD_GETCAPABILITY,
35 } RTT_SUB_COMMAND;
36
37 typedef enum {
38 RTT_ATTRIBUTE_TARGET_CNT,
39 RTT_ATTRIBUTE_TARGET_INFO,
40 RTT_ATTRIBUTE_TARGET_MAC,
41 RTT_ATTRIBUTE_TARGET_TYPE,
42 RTT_ATTRIBUTE_TARGET_PEER,
43 RTT_ATTRIBUTE_TARGET_CHAN,
44 RTT_ATTRIBUTE_TARGET_MODE,
45 RTT_ATTRIBUTE_TARGET_INTERVAL,
46 RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT,
47 RTT_ATTRIBUTE_TARGET_NUM_PKT,
48 RTT_ATTRIBUTE_TARGET_NUM_RETRY,
49
50 } GSCAN_ATTRIBUTE;
51 class GetRttCapabilitiesCommand : public WifiCommand
52 {
53 wifi_rtt_capabilities *mCapabilities;
54 public:
GetRttCapabilitiesCommand(wifi_interface_handle iface,wifi_rtt_capabilities * capabitlites)55 GetRttCapabilitiesCommand(wifi_interface_handle iface, wifi_rtt_capabilities *capabitlites)
56 : WifiCommand(iface, 0), mCapabilities(capabitlites)
57 {
58 memset(mCapabilities, 0, sizeof(*mCapabilities));
59 }
60
create()61 virtual int create() {
62 ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
63
64 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETCAPABILITY);
65 if (ret < 0) {
66 return ret;
67 }
68
69 return ret;
70 }
71
72 protected:
handleResponse(WifiEvent & reply)73 virtual int handleResponse(WifiEvent& reply) {
74
75 ALOGD("In GetRttCapabilitiesCommand::handleResponse");
76
77 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
78 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
79 return NL_SKIP;
80 }
81
82 int id = reply.get_vendor_id();
83 int subcmd = reply.get_vendor_subcmd();
84
85 void *data = reply.get_vendor_data();
86 int len = reply.get_vendor_data_len();
87
88 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
89 sizeof(*mCapabilities));
90
91 memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
92
93 return NL_OK;
94 }
95 };
96
97
98 class RttCommand : public WifiCommand
99 {
100 unsigned numRttParams;
101 static const int MAX_RESULTS = 64;
102 wifi_rtt_result rttResults[MAX_RESULTS];
103 wifi_rtt_config *rttParams;
104 wifi_rtt_event_handler rttHandler;
105 public:
RttCommand(wifi_interface_handle iface,int id,unsigned num_rtt_config,wifi_rtt_config rtt_config[],wifi_rtt_event_handler handler)106 RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config,
107 wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
108 : WifiCommand(iface, id), numRttParams(num_rtt_config), rttParams(rtt_config),
109 rttHandler(handler)
110 { }
111
112
createSetupRequest(WifiRequest & request)113 int createSetupRequest(WifiRequest& request) {
114 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG);
115 if (result < 0) {
116 return result;
117 }
118
119 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
120 result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams);
121 if (result < 0) {
122 return result;
123 }
124 nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO);
125 for (unsigned i = 0; i < numRttParams; i++) {
126
127 nlattr *attr2 = request.attr_start(i);
128 if (attr2 == NULL) {
129 return WIFI_ERROR_OUT_OF_MEMORY;
130 }
131
132 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].addr);
133 if (result < 0) {
134 return result;
135 }
136 result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].type);
137 if (result < 0) {
138 return result;
139 }
140 result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].peer);
141 if (result < 0) {
142 return result;
143 }
144 result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].channel,
145 sizeof(wifi_channel_info));
146 if (result < 0) {
147 return result;
148 }
149 result = request.put_u8(RTT_ATTRIBUTE_TARGET_MODE, rttParams[i].continuous);
150 if (result < 0) {
151 return result;
152 }
153 result = request.put_u32(RTT_ATTRIBUTE_TARGET_INTERVAL, rttParams[i].interval);
154 if (result < 0) {
155 return result;
156 }
157 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_MEASUREMENT,
158 rttParams[i].num_measurements);
159 if (result < 0) {
160 return result;
161 }
162 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_PKT,
163 rttParams[i].num_samples_per_measurement);
164 if (result < 0) {
165 return result;
166 }
167 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY,
168 rttParams[i].num_retries_per_measurement);
169 if (result < 0) {
170 return result;
171 }
172 request.attr_end(attr2);
173 }
174
175 request.attr_end(rtt_config);
176 request.attr_end(data);
177 return WIFI_SUCCESS;
178 }
179
createTeardownRequest(WifiRequest & request,unsigned num_devices,mac_addr addr[])180 int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) {
181 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_CONFIG);
182 if (result < 0) {
183 return result;
184 }
185
186 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
187 request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
188 for(unsigned i = 0; i < num_devices; i++) {
189 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
190 if (result < 0) {
191 return result;
192 }
193 }
194 request.attr_end(data);
195 return result;
196 }
start()197 int start() {
198 ALOGD("Setting RTT configuration");
199 WifiRequest request(familyId(), ifaceId());
200 int result = createSetupRequest(request);
201 if (result != WIFI_SUCCESS) {
202 ALOGE("failed to create setup request; result = %d", result);
203 return result;
204 }
205
206 result = requestResponse(request);
207 if (result != WIFI_SUCCESS) {
208 ALOGE("failed to configure RTT setup; result = %d", result);
209 return result;
210 }
211
212 registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
213 ALOGI("Successfully started RTT operation");
214 return result;
215 }
216
cancel()217 virtual int cancel() {
218 ALOGD("Stopping RTT");
219
220 WifiRequest request(familyId(), ifaceId());
221 int result = createTeardownRequest(request, 0, NULL);
222 if (result != WIFI_SUCCESS) {
223 ALOGE("failed to create stop request; result = %d", result);
224 } else {
225 result = requestResponse(request);
226 if (result != WIFI_SUCCESS) {
227 ALOGE("failed to stop scan; result = %d", result);
228 }
229 }
230
231 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
232 return WIFI_SUCCESS;
233 }
234
cancel_specific(unsigned num_devices,mac_addr addr[])235 int cancel_specific(unsigned num_devices, mac_addr addr[]) {
236 ALOGD("Stopping scan");
237
238 WifiRequest request(familyId(), ifaceId());
239 int result = createTeardownRequest(request, num_devices, addr);
240 if (result != WIFI_SUCCESS) {
241 ALOGE("failed to create stop request; result = %d", result);
242 } else {
243 result = requestResponse(request);
244 if (result != WIFI_SUCCESS) {
245 ALOGE("failed to stop RTT; result = %d", result);
246 }
247 }
248
249 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
250 return WIFI_SUCCESS;
251 }
252
handleResponse(WifiEvent & reply)253 virtual int handleResponse(WifiEvent& reply) {
254 /* Nothing to do on response! */
255 return NL_SKIP;
256 }
257
handleEvent(WifiEvent & event)258 virtual int handleEvent(WifiEvent& event) {
259 ALOGI("Got an RTT event");
260
261 // event.log();
262
263 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
264 int len = event.get_vendor_data_len();
265
266 if (vendor_data == NULL || len == 0) {
267 ALOGI("No rtt results found");
268 }
269
270 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
271 wifi_unregister_cmd(wifiHandle(), id());
272
273 memset(rttResults, 0, sizeof(wifi_rtt_result) * MAX_RESULTS);
274
275 int num = len / sizeof(wifi_rtt_result);
276 num = min(MAX_RESULTS, num);
277 memcpy(rttResults, event.get_vendor_data(), num * sizeof(wifi_rtt_result));
278 ALOGI("Retrieved %d rtt results", num);
279
280 (*rttHandler.on_rtt_results)(id(), num, rttResults);
281 return NL_SKIP;
282 }
283 };
284
285
286 /* API to request RTT measurement */
wifi_rtt_range_request(wifi_request_id id,wifi_interface_handle iface,unsigned num_rtt_config,wifi_rtt_config rtt_config[],wifi_rtt_event_handler handler)287 wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
288 unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
289 {
290 wifi_handle handle = getWifiHandle(iface);
291
292 RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
293 wifi_register_cmd(handle, id, cmd);
294 return (wifi_error)cmd->start();
295 }
296
297 /* API to cancel RTT measurements */
wifi_rtt_range_cancel(wifi_request_id id,wifi_interface_handle iface,unsigned num_devices,mac_addr addr[])298 wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface,
299 unsigned num_devices, mac_addr addr[])
300 {
301 wifi_handle handle = getWifiHandle(iface);
302 RttCommand *cmd = (RttCommand *)wifi_unregister_cmd(handle, id);
303 if (cmd) {
304 cmd->cancel_specific(num_devices, addr);
305 cmd->releaseRef();
306 return WIFI_SUCCESS;
307 }
308
309 return WIFI_ERROR_INVALID_ARGS;
310 }
311
312 /* API to get RTT capability */
wifi_get_rtt_capabilities(wifi_interface_handle iface,wifi_rtt_capabilities * capabilities)313 wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
314 wifi_rtt_capabilities *capabilities)
315 {
316 GetRttCapabilitiesCommand command(iface, capabilities);
317 return (wifi_error) command.requestResponse();
318 }
319
320
321