• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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