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_SUB_COMMAND;
39
40 typedef enum {
41 RTT_ATTRIBUTE_TARGET_CNT = 0,
42 RTT_ATTRIBUTE_TARGET_INFO,
43 RTT_ATTRIBUTE_TARGET_MAC,
44 RTT_ATTRIBUTE_TARGET_TYPE,
45 RTT_ATTRIBUTE_TARGET_PEER,
46 RTT_ATTRIBUTE_TARGET_CHAN,
47 RTT_ATTRIBUTE_TARGET_PERIOD,
48 RTT_ATTRIBUTE_TARGET_NUM_BURST,
49 RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
50 RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
51 RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
52 RTT_ATTRIBUTE_TARGET_LCI,
53 RTT_ATTRIBUTE_TARGET_LCR,
54 RTT_ATTRIBUTE_TARGET_BURST_DURATION,
55 RTT_ATTRIBUTE_TARGET_PREAMBLE,
56 RTT_ATTRIBUTE_TARGET_BW,
57 RTT_ATTRIBUTE_RESULTS_COMPLETE = 30,
58 RTT_ATTRIBUTE_RESULTS_PER_TARGET,
59 RTT_ATTRIBUTE_RESULT_CNT,
60 RTT_ATTRIBUTE_RESULT
61 } RTT_ATTRIBUTE;
62 typedef struct strmap_entry {
63 int id;
64 String8 text;
65 } strmap_entry_t;
66 struct dot11_rm_ie {
67 u8 id;
68 u8 len;
69 u8 token;
70 u8 mode;
71 u8 type;
72 } __attribute__ ((packed));
73 typedef struct dot11_rm_ie dot11_rm_ie_t;
74 #define DOT11_HDR_LEN 2
75 #define DOT11_RM_IE_LEN 5
76 #define DOT11_MNG_MEASURE_REQUEST_ID 38 /* 11H MeasurementRequest */
77 #define DOT11_MEASURE_TYPE_LCI 8 /* d11 measurement LCI type */
78 #define DOT11_MEASURE_TYPE_CIVICLOC 11 /* d11 measurement location civic */
79
80 static const strmap_entry_t err_info[] = {
81 {RTT_STATUS_SUCCESS, String8("Success")},
82 {RTT_STATUS_FAILURE, String8("Failure")},
83 {RTT_STATUS_FAIL_NO_RSP, String8("No reponse")},
84 {RTT_STATUS_FAIL_INVALID_TS, String8("Invalid Timestamp")},
85 {RTT_STATUS_FAIL_PROTOCOL, String8("Protocol error")},
86 {RTT_STATUS_FAIL_REJECTED, String8("Rejected")},
87 {RTT_STATUS_FAIL_NOT_SCHEDULED_YET, String8("not scheduled")},
88 {RTT_STATUS_FAIL_SCHEDULE, String8("schedule failed")},
89 {RTT_STATUS_FAIL_TM_TIMEOUT, String8("timeout")},
90 {RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, String8("AP is on difference channel")},
91 {RTT_STATUS_FAIL_NO_CAPABILITY, String8("no capability")},
92 {RTT_STATUS_FAIL_BUSY_TRY_LATER, String8("busy and try later")},
93 {RTT_STATUS_ABORTED, String8("aborted")}
94 };
95
96 static const char*
get_err_info(int status)97 get_err_info(int status)
98 {
99 int i;
100 const strmap_entry_t *p_entry;
101 int num_entries = sizeof(err_info)/ sizeof(err_info[0]);
102 /* scan thru the table till end */
103 p_entry = err_info;
104 for (i = 0; i < (int) num_entries; i++)
105 {
106 if (p_entry->id == status)
107 return p_entry->text;
108 p_entry++; /* next entry */
109 }
110 return "unknown error"; /* not found */
111 }
112
113 class GetRttCapabilitiesCommand : public WifiCommand
114 {
115 wifi_rtt_capabilities *mCapabilities;
116 public:
GetRttCapabilitiesCommand(wifi_interface_handle iface,wifi_rtt_capabilities * capabitlites)117 GetRttCapabilitiesCommand(wifi_interface_handle iface, wifi_rtt_capabilities *capabitlites)
118 : WifiCommand("GetRttCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
119 {
120 memset(mCapabilities, 0, sizeof(*mCapabilities));
121 }
122
create()123 virtual int create() {
124 ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
125
126 int ret = mMsg.create(GOOGLE_OUI, RTT_SUBCMD_GETCAPABILITY);
127 if (ret < 0) {
128 return ret;
129 }
130
131 return ret;
132 }
133
134 protected:
handleResponse(WifiEvent & reply)135 virtual int handleResponse(WifiEvent& reply) {
136
137 ALOGD("In GetRttCapabilitiesCommand::handleResponse");
138
139 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
140 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
141 return NL_SKIP;
142 }
143
144 int id = reply.get_vendor_id();
145 int subcmd = reply.get_vendor_subcmd();
146
147 void *data = reply.get_vendor_data();
148 int len = reply.get_vendor_data_len();
149
150 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
151 sizeof(*mCapabilities));
152
153 memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
154
155 return NL_OK;
156 }
157 };
158
159
160 class RttCommand : public WifiCommand
161 {
162 unsigned numRttParams;
163 int mCompleted;
164 int currentIdx;
165 int totalCnt;
166 static const int MAX_RESULTS = 1024;
167 wifi_rtt_result *rttResults[MAX_RESULTS];
168 wifi_rtt_config *rttParams;
169 wifi_rtt_event_handler rttHandler;
170 public:
RttCommand(wifi_interface_handle iface,int id,unsigned num_rtt_config,wifi_rtt_config rtt_config[],wifi_rtt_event_handler handler)171 RttCommand(wifi_interface_handle iface, int id, unsigned num_rtt_config,
172 wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
173 : WifiCommand("RttCommand", iface, id), numRttParams(num_rtt_config), rttParams(rtt_config),
174 rttHandler(handler)
175 {
176 memset(rttResults, 0, sizeof(rttResults));
177 currentIdx = 0;
178 mCompleted = 0;
179 totalCnt = 0;
180 }
181
RttCommand(wifi_interface_handle iface,int id)182 RttCommand(wifi_interface_handle iface, int id)
183 : WifiCommand("RttCommand", iface, id)
184 {
185 currentIdx = 0;
186 mCompleted = 0;
187 totalCnt = 0;
188 numRttParams = 0;
189 }
190
createSetupRequest(WifiRequest & request)191 int createSetupRequest(WifiRequest& request) {
192 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_SET_CONFIG);
193 if (result < 0) {
194 return result;
195 }
196
197 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
198 result = request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, numRttParams);
199 if (result < 0) {
200 return result;
201 }
202 nlattr *rtt_config = request.attr_start(RTT_ATTRIBUTE_TARGET_INFO);
203 for (unsigned i = 0; i < numRttParams; i++) {
204 nlattr *attr2 = request.attr_start(i);
205 if (attr2 == NULL) {
206 return WIFI_ERROR_OUT_OF_MEMORY;
207 }
208
209 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, rttParams[i].addr);
210 if (result < 0) {
211 return result;
212 }
213
214 result = request.put_u8(RTT_ATTRIBUTE_TARGET_TYPE, rttParams[i].type);
215 if (result < 0) {
216 return result;
217 }
218
219 result = request.put_u8(RTT_ATTRIBUTE_TARGET_PEER, rttParams[i].peer);
220 if (result < 0) {
221 return result;
222 }
223
224 result = request.put(RTT_ATTRIBUTE_TARGET_CHAN, &rttParams[i].channel,
225 sizeof(wifi_channel_info));
226 if (result < 0) {
227 return result;
228 }
229
230 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_BURST, rttParams[i].num_burst);
231 if (result < 0) {
232 return result;
233 }
234
235 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST,
236 rttParams[i].num_frames_per_burst);
237 if (result < 0) {
238 return result;
239 }
240
241 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM,
242 rttParams[i].num_retries_per_rtt_frame);
243 if (result < 0) {
244 return result;
245 }
246
247 result = request.put_u32(RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR,
248 rttParams[i].num_retries_per_ftmr);
249 if (result < 0) {
250 return result;
251 }
252
253 result = request.put_u32(RTT_ATTRIBUTE_TARGET_PERIOD,
254 rttParams[i].burst_period);
255 if (result < 0) {
256 return result;
257 }
258
259 result = request.put_u32(RTT_ATTRIBUTE_TARGET_BURST_DURATION,
260 rttParams[i].burst_duration);
261 if (result < 0) {
262 return result;
263 }
264
265 result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCI,
266 rttParams[i].LCI_request);
267 if (result < 0) {
268 return result;
269 }
270
271 result = request.put_u8(RTT_ATTRIBUTE_TARGET_LCR,
272 rttParams[i].LCR_request);
273 if (result < 0) {
274 return result;
275 }
276
277 result = request.put_u8(RTT_ATTRIBUTE_TARGET_BW,
278 rttParams[i].bw);
279 if (result < 0) {
280 return result;
281 }
282
283 result = request.put_u8(RTT_ATTRIBUTE_TARGET_PREAMBLE,
284 rttParams[i].preamble);
285 if (result < 0) {
286 return result;
287 }
288 request.attr_end(attr2);
289 }
290
291 request.attr_end(rtt_config);
292 request.attr_end(data);
293 return WIFI_SUCCESS;
294 }
295
createTeardownRequest(WifiRequest & request,unsigned num_devices,mac_addr addr[])296 int createTeardownRequest(WifiRequest& request, unsigned num_devices, mac_addr addr[]) {
297 int result = request.create(GOOGLE_OUI, RTT_SUBCMD_CANCEL_CONFIG);
298 if (result < 0) {
299 return result;
300 }
301
302 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
303 request.put_u8(RTT_ATTRIBUTE_TARGET_CNT, num_devices);
304 for(unsigned i = 0; i < num_devices; i++) {
305 result = request.put_addr(RTT_ATTRIBUTE_TARGET_MAC, addr[i]);
306 if (result < 0) {
307 return result;
308 }
309 }
310 request.attr_end(data);
311 return result;
312 }
start()313 int start() {
314 ALOGD("Setting RTT configuration");
315 WifiRequest request(familyId(), ifaceId());
316 int result = createSetupRequest(request);
317 if (result != WIFI_SUCCESS) {
318 ALOGE("failed to create setup request; result = %d", result);
319 return result;
320 }
321
322 result = requestResponse(request);
323 if (result != WIFI_SUCCESS) {
324 ALOGE("failed to configure RTT setup; result = %d", result);
325 return result;
326 }
327
328 registerVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
329 ALOGI("Successfully started RTT operation");
330 return result;
331 }
332
cancel()333 virtual int cancel() {
334 ALOGD("Stopping RTT");
335
336 WifiRequest request(familyId(), ifaceId());
337 int result = createTeardownRequest(request, 0, NULL);
338 if (result != WIFI_SUCCESS) {
339 ALOGE("failed to create stop request; result = %d", result);
340 } else {
341 result = requestResponse(request);
342 if (result != WIFI_SUCCESS) {
343 ALOGE("failed to stop scan; result = %d", result);
344 }
345 }
346
347 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
348 return WIFI_SUCCESS;
349 }
350
cancel_specific(unsigned num_devices,mac_addr addr[])351 int cancel_specific(unsigned num_devices, mac_addr addr[]) {
352 ALOGE("Stopping RTT");
353
354 WifiRequest request(familyId(), ifaceId());
355 int result = createTeardownRequest(request, num_devices, addr);
356 if (result != WIFI_SUCCESS) {
357 ALOGE("failed to create stop request; result = %d", result);
358 } else {
359 result = requestResponse(request);
360 if (result != WIFI_SUCCESS) {
361 ALOGE("failed to stop RTT; result = %d", result);
362 }
363 }
364
365 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
366 return WIFI_SUCCESS;
367 }
368
handleResponse(WifiEvent & reply)369 virtual int handleResponse(WifiEvent& reply) {
370 /* Nothing to do on response! */
371 return NL_SKIP;
372 }
373
handleEvent(WifiEvent & event)374 virtual int handleEvent(WifiEvent& event) {
375 ALOGI("Got an RTT event");
376 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
377 int len = event.get_vendor_data_len();
378 if (vendor_data == NULL || len == 0) {
379 ALOGI("No rtt results found");
380 }
381 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
382 if (it.get_type() == RTT_ATTRIBUTE_RESULTS_COMPLETE) {
383 mCompleted = it.get_u32();
384 ALOGI("retrieved completed flag : %d\n", mCompleted);
385 } else if (it.get_type() == RTT_ATTRIBUTE_RESULTS_PER_TARGET) {
386 int result_cnt = 0;
387 mac_addr bssid;
388 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
389 if (it2.get_type() == RTT_ATTRIBUTE_TARGET_MAC) {
390 memcpy(bssid, it2.get_data(), sizeof(mac_addr));
391 ALOGI("retrived target mac : %02x:%02x:%02x:%02x:%02x:%02x\n",
392 bssid[0],
393 bssid[1],
394 bssid[2],
395 bssid[3],
396 bssid[4],
397 bssid[5]);
398 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT_CNT) {
399 result_cnt = it2.get_u32();
400 ALOGI("retrieved result_cnt : %d\n", result_cnt);
401 } else if (it2.get_type() == RTT_ATTRIBUTE_RESULT) {
402 int result_len = it2.get_len();
403 rttResults[currentIdx] = (wifi_rtt_result *)malloc(it2.get_len());
404 wifi_rtt_result *rtt_result = rttResults[currentIdx];
405 if (rtt_result == NULL) {
406 mCompleted = 1;
407 ALOGE("failed to allocate the wifi_rtt_result\n");
408 break;
409 }
410 memcpy(rtt_result, it2.get_data(), it2.get_len());
411 result_len -= sizeof(wifi_rtt_result);
412 if (result_len > 0) {
413 result_len -= sizeof(wifi_rtt_result);
414 dot11_rm_ie_t *ele_1;
415 dot11_rm_ie_t *ele_2;
416 /* The result has LCI or LCR element */
417 ele_1 = (dot11_rm_ie_t *)(rtt_result + 1);
418 if (ele_1->id == DOT11_MNG_MEASURE_REQUEST_ID) {
419 if (ele_1->type == DOT11_MEASURE_TYPE_LCI) {
420 rtt_result->LCI = (wifi_information_element *)ele_1;
421 result_len -= (ele_1->len + DOT11_HDR_LEN);
422 /* get a next rm ie */
423 if (result_len > 0) {
424 ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
425 if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
426 (ele_2->type == DOT11_MEASURE_TYPE_CIVICLOC)) {
427 rtt_result->LCR = (wifi_information_element *)ele_2;
428 }
429 }
430 } else if (ele_1->type == DOT11_MEASURE_TYPE_CIVICLOC){
431 rtt_result->LCR = (wifi_information_element *)ele_1;
432 result_len -= (ele_1->len + DOT11_HDR_LEN);
433 /* get a next rm ie */
434 if (result_len > 0) {
435 ele_2 = (dot11_rm_ie_t *)((char *)ele_1 + (ele_1->len + DOT11_HDR_LEN));
436 if ((ele_2->id == DOT11_MNG_MEASURE_REQUEST_ID) &&
437 (ele_2->type == DOT11_MEASURE_TYPE_LCI)) {
438 rtt_result->LCI = (wifi_information_element *)ele_2;
439 }
440 }
441 }
442 }
443 }
444 totalCnt++;
445 ALOGI("retrived rtt_result : \n\tburst_num :%d, measurement_number : %d, success_number : %d\n"
446 "\tnumber_per_burst_peer : %d, status : %s, retry_after_duration : %d s\n"
447 "\trssi : %d dbm, rx_rate : %d Kbps, rtt : %llu ns, rtt_sd : %llu\n"
448 "\tdistance : %d, burst_duration : %d ms, negotiated_burst_num : %d\n",
449 rtt_result->burst_num, rtt_result->measurement_number,
450 rtt_result->success_number, rtt_result->number_per_burst_peer,
451 get_err_info(rtt_result->status), rtt_result->retry_after_duration,
452 rtt_result->rssi, rtt_result->rx_rate.bitrate * 100,
453 rtt_result->rtt/10, rtt_result->rtt_sd, rtt_result->distance,
454 rtt_result->burst_duration, rtt_result->negotiated_burst_num);
455 currentIdx++;
456 }
457 }
458 }
459
460 }
461 if (mCompleted) {
462 unregisterVendorHandler(GOOGLE_OUI, RTT_EVENT_COMPLETE);
463 (*rttHandler.on_rtt_results)(id(), totalCnt, rttResults);
464 for (int i = 0; i < currentIdx; i++) {
465 free(rttResults[i]);
466 rttResults[i] = NULL;
467 }
468 totalCnt = currentIdx = 0;
469 WifiCommand *cmd = wifi_unregister_cmd(wifiHandle(), id());
470 if (cmd)
471 cmd->releaseRef();
472 }
473 return NL_SKIP;
474 }
475 };
476
477
478 /* 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)479 wifi_error wifi_rtt_range_request(wifi_request_id id, wifi_interface_handle iface,
480 unsigned num_rtt_config, wifi_rtt_config rtt_config[], wifi_rtt_event_handler handler)
481 {
482 wifi_handle handle = getWifiHandle(iface);
483
484 RttCommand *cmd = new RttCommand(iface, id, num_rtt_config, rtt_config, handler);
485 wifi_register_cmd(handle, id, cmd);
486 return (wifi_error)cmd->start();
487 }
488
489 /* API to cancel RTT measurements */
wifi_rtt_range_cancel(wifi_request_id id,wifi_interface_handle iface,unsigned num_devices,mac_addr addr[])490 wifi_error wifi_rtt_range_cancel(wifi_request_id id, wifi_interface_handle iface,
491 unsigned num_devices, mac_addr addr[])
492 {
493 wifi_handle handle = getWifiHandle(iface);
494 RttCommand *cmd = new RttCommand(iface, id);
495 if (cmd) {
496 cmd->cancel_specific(num_devices, addr);
497 cmd->releaseRef();
498 return WIFI_SUCCESS;
499 }
500 return WIFI_ERROR_INVALID_ARGS;
501 }
502
503 /* API to get RTT capability */
wifi_get_rtt_capabilities(wifi_interface_handle iface,wifi_rtt_capabilities * capabilities)504 wifi_error wifi_get_rtt_capabilities(wifi_interface_handle iface,
505 wifi_rtt_capabilities *capabilities)
506 {
507 GetRttCapabilitiesCommand command(iface, capabilities);
508 return (wifi_error) command.requestResponse();
509 }
510