• 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 
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