1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Portions copyright (C) 2017 Broadcom Limited
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #include <stdint.h>
20 #include <fcntl.h>
21 #include <sys/socket.h>
22 #include <netlink/genl/genl.h>
23 #include <netlink/genl/family.h>
24 #include <netlink/genl/ctrl.h>
25 #include <linux/rtnetlink.h>
26 #include <netpacket/packet.h>
27 #include <linux/filter.h>
28 #include <linux/errqueue.h>
29 
30 #include <linux/pkt_sched.h>
31 #include <netlink/object-api.h>
32 #include <netlink/netlink.h>
33 #include <netlink/socket.h>
34 #include <netlink/handlers.h>
35 
36 #include "sync.h"
37 
38 #define LOG_TAG  "WifiHAL"
39 //#define LOG_NDEBUG 0         //uncomment to enable verbose logging
40 
41 #include <log/log.h>
42 
43 #include "wifi_hal.h"
44 #include "common.h"
45 #include "cpp_bindings.h"
46 
47 typedef enum {
48 
49     GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
50     GSCAN_ATTRIBUTE_BASE_PERIOD,
51     GSCAN_ATTRIBUTE_BUCKETS_BAND,
52     GSCAN_ATTRIBUTE_BUCKET_ID,
53     GSCAN_ATTRIBUTE_BUCKET_PERIOD,
54     GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
55     GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
56     GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
57     GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
58     GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
59     GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
60 
61     GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
62     GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE,              /* indicates no more results */
63     GSCAN_ATTRIBUTE_FLUSH_FEATURE,                      /* Flush all the configs */
64     GSCAN_ENABLE_FULL_SCAN_RESULTS,
65     GSCAN_ATTRIBUTE_REPORT_EVENTS,
66 
67     /* remaining reserved for additional attributes */
68     GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
69     GSCAN_ATTRIBUTE_FLUSH_RESULTS,
70     GSCAN_ATTRIBUTE_SCAN_RESULTS,                       /* flat array of wifi_scan_result */
71     GSCAN_ATTRIBUTE_SCAN_ID,                            /* indicates scan number */
72     GSCAN_ATTRIBUTE_SCAN_FLAGS,                         /* indicates if scan was aborted */
73     GSCAN_ATTRIBUTE_AP_FLAGS,                           /* flags on significant change event */
74     GSCAN_ATTRIBUTE_NUM_CHANNELS,
75     GSCAN_ATTRIBUTE_CHANNEL_LIST,
76     GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK,
77     /* remaining reserved for additional attributes */
78 
79     GSCAN_ATTRIBUTE_SSID = 40,
80     GSCAN_ATTRIBUTE_BSSID,
81     GSCAN_ATTRIBUTE_CHANNEL,
82     GSCAN_ATTRIBUTE_RSSI,
83     GSCAN_ATTRIBUTE_TIMESTAMP,
84     GSCAN_ATTRIBUTE_RTT,
85     GSCAN_ATTRIBUTE_RTTSD,
86 
87     /* remaining reserved for additional attributes */
88 
89     GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50,
90     GSCAN_ATTRIBUTE_RSSI_LOW,
91     GSCAN_ATTRIBUTE_RSSI_HIGH,
92     GSCAN_ATTRIBUTE_HOTLIST_ELEM,
93     GSCAN_ATTRIBUTE_HOTLIST_FLUSH,
94     GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT,
95 
96     /* remaining reserved for additional attributes */
97     GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60,
98     GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE,
99     GSCAN_ATTRIBUTE_MIN_BREACHING,
100     GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS,
101     GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH,
102 
103     /* EPNO */
104     GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70,
105     GSCAN_ATTRIBUTE_EPNO_SSID,
106     GSCAN_ATTRIBUTE_EPNO_SSID_LEN,
107     GSCAN_ATTRIBUTE_EPNO_RSSI,
108     GSCAN_ATTRIBUTE_EPNO_FLAGS,
109     GSCAN_ATTRIBUTE_EPNO_AUTH,
110     GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
111     GSCAN_ATTRIBUTE_EPNO_FLUSH,
112 
113     /* remaining reserved for additional attributes */
114 
115     GSCAN_ATTRIBUTE_WHITELIST_SSID = 80,
116     GSCAN_ATTRIBUTE_NUM_WL_SSID,
117     GSCAN_ATTRIBUTE_WL_SSID_LEN,
118     GSCAN_ATTRIBUTE_WL_SSID_FLUSH,
119     GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM,
120     GSCAN_ATTRIBUTE_NUM_BSSID,
121     GSCAN_ATTRIBUTE_BSSID_PREF_LIST,
122     GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH,
123     GSCAN_ATTRIBUTE_BSSID_PREF,
124     GSCAN_ATTRIBUTE_RSSI_MODIFIER,
125 
126     /* remaining reserved for additional attributes */
127 
128     GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD = 90,
129     GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD,
130     GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR,
131     GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR,
132     GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST,
133     GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS,
134     GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER,
135     GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE,
136 
137     /* BSSID blacklist */
138     GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH = 100,
139     GSCAN_ATTRIBUTE_BLACKLIST_BSSID,
140 
141     /* ANQPO */
142     GSCAN_ATTRIBUTE_ANQPO_HS_LIST = 110,
143     GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE,
144     GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID,
145     GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM,
146     GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
147     GSCAN_ATTRIBUTE_ANQPO_HS_PLMN,
148 
149     /* Adaptive scan attributes */
150     GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 120,
151     GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
152 
153     /* ePNO cfg */
154     GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR = 130,
155     GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
156     GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
157     GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
158     GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
159     GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
160     GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
161 
162     GSCAN_ATTRIBUTE_MAX
163 
164 } GSCAN_ATTRIBUTE;
165 
166 
167 // helper methods
168 wifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface,
169          wifi_scan_result_handler handler);
170 wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface);
171 int wifi_handle_full_scan_event(wifi_request_id id, WifiEvent& event,
172          wifi_scan_result_handler handler);
173 void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from);
174 
175 
convert_to_hal_result(wifi_scan_result * to,wifi_gscan_result_t * from)176 void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from)
177 {
178     to->ts = from->ts;
179     to->channel = from->channel;
180     to->rssi = from->rssi;
181     to->rtt = from->rtt;
182     to->rtt_sd = from->rtt_sd;
183     to->beacon_period = from->beacon_period;
184     to->capability = from->capability;
185     memcpy(to->ssid, from->ssid, (DOT11_MAX_SSID_LEN+1));
186     memcpy(&to->bssid, &from->bssid, sizeof(mac_addr));
187 }
188 
189 /////////////////////////////////////////////////////////////////////////////
190 
191 class GetCapabilitiesCommand : public WifiCommand
192 {
193     wifi_gscan_capabilities *mCapabilities;
194 public:
GetCapabilitiesCommand(wifi_interface_handle iface,wifi_gscan_capabilities * capabitlites)195     GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites)
196         : WifiCommand("GetGscanCapabilitiesCommand", iface, 0), mCapabilities(capabitlites)
197     {
198         memset(mCapabilities, 0, sizeof(*mCapabilities));
199     }
200 
create()201     virtual int create() {
202         ALOGV("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
203 
204         int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES);
205         if (ret < 0) {
206             return ret;
207         }
208 
209         return ret;
210     }
211 
212 protected:
handleResponse(WifiEvent & reply)213     virtual int handleResponse(WifiEvent& reply) {
214 
215         ALOGV("In GetCapabilities::handleResponse");
216 
217         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
218             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
219             return NL_SKIP;
220         }
221 
222         int id = reply.get_vendor_id();
223         int subcmd = reply.get_vendor_subcmd();
224 
225         void *data = reply.get_vendor_data();
226         int len = reply.get_vendor_data_len();
227 
228         ALOGV("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
229                     sizeof(*mCapabilities));
230 
231         memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
232 
233         return NL_OK;
234     }
235 };
236 
237 
wifi_get_gscan_capabilities(wifi_interface_handle handle,wifi_gscan_capabilities * capabilities)238 wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
239         wifi_gscan_capabilities *capabilities)
240 {
241     GetCapabilitiesCommand command(handle, capabilities);
242     return (wifi_error) command.requestResponse();
243 }
244 
245 class GetChannelListCommand : public WifiCommand
246 {
247     wifi_channel *channels;
248     int max_channels;
249     int *num_channels;
250     int band;
251 public:
GetChannelListCommand(wifi_interface_handle iface,wifi_channel * channel_buf,int * ch_num,int num_max_ch,int band)252     GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num,
253         int num_max_ch, int band)
254         : WifiCommand("GetChannelListCommand", iface, 0), channels(channel_buf),
255             max_channels(num_max_ch), num_channels(ch_num), band(band)
256     {
257         memset(channels, 0, sizeof(wifi_channel) * max_channels);
258     }
create()259     virtual int create() {
260         ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id);
261 
262         int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CHANNEL_LIST);
263         if (ret < 0) {
264             return ret;
265         }
266 
267         nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
268         ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band);
269         if (ret < 0) {
270             return ret;
271         }
272 
273         mMsg.attr_end(data);
274 
275         return ret;
276     }
277 
278 protected:
handleResponse(WifiEvent & reply)279     virtual int handleResponse(WifiEvent& reply) {
280 
281         ALOGV("In GetChannelList::handleResponse");
282 
283         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
284             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
285             return NL_SKIP;
286         }
287 
288         int id = reply.get_vendor_id();
289         int subcmd = reply.get_vendor_subcmd();
290         int num_channels_to_copy = 0;
291 
292         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
293         int len = reply.get_vendor_data_len();
294 
295         ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
296         if (vendor_data == NULL || len == 0) {
297             ALOGE("no vendor data in GetChannelList response; ignoring it");
298             return NL_SKIP;
299         }
300 
301         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
302             if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) {
303                 num_channels_to_copy = it.get_u32();
304                 ALOGI("Got channel list with %d channels", num_channels_to_copy);
305                 if(num_channels_to_copy > max_channels)
306                     num_channels_to_copy = max_channels;
307                 *num_channels = num_channels_to_copy;
308             } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) {
309                 memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy);
310             } else {
311                 ALOGW("Ignoring invalid attribute type = %d, size = %d",
312                         it.get_type(), it.get_len());
313             }
314         }
315 
316         return NL_OK;
317     }
318 };
319 
wifi_get_valid_channels(wifi_interface_handle handle,int band,int max_channels,wifi_channel * channels,int * num_channels)320 wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
321         int band, int max_channels, wifi_channel *channels, int *num_channels)
322 {
323     *num_channels = 12;
324     return WIFI_SUCCESS;
325 }
326 /////////////////////////////////////////////////////////////////////////////
327 
328 /* helper functions */
329 
parseScanResults(wifi_scan_result * results,int num,nlattr * attr)330 static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr)
331 {
332     memset(results, 0, sizeof(wifi_scan_result) * num);
333 
334     int i = 0;
335     for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) {
336 
337         int index = it.get_type();
338         ALOGI("retrieved scan result %d", index);
339         nlattr *sc_data = (nlattr *) it.get_data();
340         wifi_scan_result *result = results + i;
341 
342         for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) {
343             int type = it2.get_type();
344             if (type == GSCAN_ATTRIBUTE_SSID) {
345                 strncpy(result->ssid, (char *) it2.get_data(), it2.get_len());
346                 result->ssid[it2.get_len()] = 0;
347             } else if (type == GSCAN_ATTRIBUTE_BSSID) {
348                 memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr));
349             } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) {
350                 result->ts = it2.get_u64();
351             } else if (type == GSCAN_ATTRIBUTE_CHANNEL) {
352                 result->ts = it2.get_u16();
353             } else if (type == GSCAN_ATTRIBUTE_RSSI) {
354                 result->rssi = it2.get_u8();
355             } else if (type == GSCAN_ATTRIBUTE_RTT) {
356                 result->rtt = it2.get_u64();
357             } else if (type == GSCAN_ATTRIBUTE_RTTSD) {
358                 result->rtt_sd = it2.get_u64();
359             }
360         }
361 
362     }
363 
364     if (i >= num) {
365         ALOGE("Got too many results; skipping some");
366     }
367 
368     return i;
369 }
370 
createFeatureRequest(WifiRequest & request,int subcmd,int enable)371 int createFeatureRequest(WifiRequest& request, int subcmd, int enable) {
372 
373     int result = request.create(GOOGLE_OUI, subcmd);
374     if (result < 0) {
375         return result;
376     }
377 
378     nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
379     result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable);
380     if (result < 0) {
381         return result;
382     }
383 
384     request.attr_end(data);
385     return WIFI_SUCCESS;
386 }
387 
388 /////////////////////////////////////////////////////////////////////////////
389 class FullScanResultsCommand : public WifiCommand
390 {
391     int *mParams;
392     wifi_scan_result_handler mHandler;
393 public:
FullScanResultsCommand(wifi_interface_handle iface,int id,int * params,wifi_scan_result_handler handler)394     FullScanResultsCommand(wifi_interface_handle iface, int id, int *params,
395                 wifi_scan_result_handler handler)
396         : WifiCommand("FullScanResultsCommand", iface, id), mParams(params), mHandler(handler)
397     { }
398 
createRequest(WifiRequest & request,int subcmd,int enable)399     int createRequest(WifiRequest& request, int subcmd, int enable) {
400         int result = request.create(GOOGLE_OUI, subcmd);
401         if (result < 0) {
402             return result;
403         }
404 
405         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
406         result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable);
407         if (result < 0) {
408             return result;
409         }
410 
411         request.attr_end(data);
412         return WIFI_SUCCESS;
413 
414     }
415 
start()416     int start() {
417         ALOGV("Enabling Full scan results");
418         WifiRequest request(familyId(), ifaceId());
419         int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1);
420         if (result != WIFI_SUCCESS) {
421             ALOGE("failed to create request; result = %d", result);
422             return result;
423         }
424 
425         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
426 
427         result = requestResponse(request);
428         if (result != WIFI_SUCCESS) {
429             ALOGE("failed to enable full scan results; result = %d", result);
430             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
431             return result;
432         }
433 
434         return result;
435     }
436 
cancel()437     virtual int cancel() {
438         ALOGV("Disabling Full scan results");
439 
440         WifiRequest request(familyId(), ifaceId());
441         int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0);
442         if (result != WIFI_SUCCESS) {
443             ALOGE("failed to create request; result = %d", result);
444         } else {
445             result = requestResponse(request);
446             if (result != WIFI_SUCCESS) {
447                 ALOGE("failed to disable full scan results;result = %d", result);
448             }
449         }
450 
451         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
452         return WIFI_SUCCESS;
453     }
454 
handleResponse(WifiEvent & reply)455     virtual int handleResponse(WifiEvent& reply) {
456          ALOGD("Request complete!");
457         /* Nothing to do on response! */
458         return NL_SKIP;
459     }
460 
handleEvent(WifiEvent & event)461     virtual int handleEvent(WifiEvent& event) {
462         ALOGV("Full scan results:  Got an event");
463         return wifi_handle_full_scan_event(id(), event, mHandler);
464     }
465 
466 };
467 /////////////////////////////////////////////////////////////////////////////
468 
469 class ScanCommand : public WifiCommand
470 {
471     wifi_scan_cmd_params *mParams;
472     wifi_scan_result_handler mHandler;
473 public:
ScanCommand(wifi_interface_handle iface,int id,wifi_scan_cmd_params * params,wifi_scan_result_handler handler)474     ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params,
475                 wifi_scan_result_handler handler)
476         : WifiCommand("ScanCommand", iface, id), mParams(params), mHandler(handler)
477     { }
478 
createSetupRequest(WifiRequest & request)479     int createSetupRequest(WifiRequest& request) {
480         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_CONFIG);
481         if (result < 0) {
482             return result;
483         }
484 
485         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
486         result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period);
487         if (result < 0) {
488             return result;
489         }
490 
491         result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets);
492         if (result < 0) {
493             return result;
494         }
495 
496         for (int i = 0; i < mParams->num_buckets; i++) {
497             nlattr * bucket = request.attr_start(i);    // next bucket
498             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket);
499             if (result < 0) {
500                 return result;
501             }
502             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period);
503             if (result < 0) {
504                 return result;
505             }
506             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND,
507                     mParams->buckets[i].band);
508             if (result < 0) {
509                 return result;
510             }
511             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT,
512                     mParams->buckets[i].step_count);
513             if (result < 0) {
514                 return result;
515             }
516             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
517                     mParams->buckets[i].max_period);
518             if (result < 0) {
519                 return result;
520             }
521             result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS,
522                     mParams->buckets[i].report_events);
523             if (result < 0) {
524                 return result;
525             }
526 
527             result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
528                     mParams->buckets[i].num_channels);
529             if (result < 0) {
530                 return result;
531             }
532 
533             if (mParams->buckets[i].num_channels) {
534                 nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS);
535                 ALOGV(" channels: ");
536                 for (int j = 0; j < mParams->buckets[i].num_channels; j++) {
537                     result = request.put_u32(j, mParams->buckets[i].channels[j].channel);
538                     ALOGV(" %u", mParams->buckets[i].channels[j].channel);
539 
540                     if (result < 0) {
541                         return result;
542                     }
543                 }
544                 request.attr_end(channels);
545             }
546 
547             request.attr_end(bucket);
548         }
549 
550         request.attr_end(data);
551         return WIFI_SUCCESS;
552     }
553 
createScanConfigRequest(WifiRequest & request)554     int createScanConfigRequest(WifiRequest& request) {
555         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG);
556         if (result < 0) {
557             return result;
558         }
559 
560         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
561         result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan);
562         if (result < 0) {
563             return result;
564         }
565 
566         result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
567                 mParams->report_threshold_percent);
568         if (result < 0) {
569             return result;
570         }
571 
572         int num_scans = mParams->report_threshold_num_scans;
573 
574         result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans);
575         if (result < 0) {
576             return result;
577         }
578 
579         request.attr_end(data);
580         return WIFI_SUCCESS;
581     }
582 
createStartRequest(WifiRequest & request)583     int createStartRequest(WifiRequest& request) {
584         return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
585     }
586 
createStopRequest(WifiRequest & request)587     int createStopRequest(WifiRequest& request) {
588         return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0);
589     }
590 
start()591     int start() {
592         ALOGV("GSCAN start");
593         WifiRequest request(familyId(), ifaceId());
594         int result = createSetupRequest(request);
595         if (result != WIFI_SUCCESS) {
596             ALOGE("failed to create setup request; result = %d", result);
597             return result;
598         }
599 
600         result = requestResponse(request);
601         if (result != WIFI_SUCCESS) {
602             ALOGE("failed to configure setup; result = %d", result);
603             return result;
604         }
605 
606         request.destroy();
607 
608         result = createScanConfigRequest(request);
609         if (result != WIFI_SUCCESS) {
610             ALOGE("failed to create scan config request; result = %d", result);
611             return result;
612         }
613 
614         result = requestResponse(request);
615         if (result != WIFI_SUCCESS) {
616             ALOGE("failed to configure scan; result = %d", result);
617             return result;
618         }
619 
620         ALOGV(" ....starting scan");
621 
622         result = createStartRequest(request);
623         if (result != WIFI_SUCCESS) {
624             ALOGE("failed to create start request; result = %d", result);
625             return result;
626         }
627 
628         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
629         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
630         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
631 
632         result = requestResponse(request);
633         if (result != WIFI_SUCCESS) {
634             ALOGE("failed to start scan; result = %d", result);
635             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
636             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
637             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
638             return result;
639         }
640         return result;
641     }
642 
cancel()643     virtual int cancel() {
644         ALOGV("Stopping scan");
645 
646         WifiRequest request(familyId(), ifaceId());
647         int result = createStopRequest(request);
648         if (result != WIFI_SUCCESS) {
649             ALOGE("failed to create stop request; result = %d", result);
650         } else {
651             result = requestResponse(request);
652             if (result != WIFI_SUCCESS) {
653                 ALOGE("failed to stop scan; result = %d", result);
654             }
655         }
656 
657         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
658         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
659         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
660         return WIFI_SUCCESS;
661     }
662 
handleResponse(WifiEvent & reply)663     virtual int handleResponse(WifiEvent& reply) {
664         /* Nothing to do on response! */
665         return NL_SKIP;
666     }
667 
handleEvent(WifiEvent & event)668     virtual int handleEvent(WifiEvent& event) {
669         ALOGV("Got a scan results event");
670         //event.log();
671 
672         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
673         int len = event.get_vendor_data_len();
674         int event_id = event.get_vendor_subcmd();
675 
676         if ((event_id == GSCAN_EVENT_COMPLETE_SCAN) ||
677             (event_id == GSCAN_EVENT_SCAN_RESULTS_AVAILABLE)) {
678             if (vendor_data == NULL || len != 4) {
679                 ALOGI("Bad event data!");
680                 return NL_SKIP;
681             }
682             wifi_scan_event evt_type;
683             evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA);
684             ALOGV("Received event type %d", evt_type);
685             if(*mHandler.on_scan_event)
686                 (*mHandler.on_scan_event)(id(), evt_type);
687         } else if (event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) {
688             wifi_handle_full_scan_event(id(), event, mHandler);
689         }
690         return NL_SKIP;
691     }
692 };
693 
wifi_start_gscan(wifi_request_id id,wifi_interface_handle iface,wifi_scan_cmd_params params,wifi_scan_result_handler handler)694 wifi_error wifi_start_gscan(
695         wifi_request_id id,
696         wifi_interface_handle iface,
697         wifi_scan_cmd_params params,
698         wifi_scan_result_handler handler)
699 {
700     wifi_handle handle = getWifiHandle(iface);
701 
702     ALOGV("Starting GScan, halHandle = %p", handle);
703 
704     ScanCommand *cmd = new ScanCommand(iface, id, &params, handler);
705     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
706     wifi_error result = wifi_register_cmd(handle, id, cmd);
707     if (result != WIFI_SUCCESS) {
708         cmd->releaseRef();
709         return result;
710     }
711     result = (wifi_error)cmd->start();
712     if (result != WIFI_SUCCESS) {
713         wifi_unregister_cmd(handle, id);
714         cmd->releaseRef();
715         return result;
716     }
717     return result;
718 }
719 
wifi_stop_gscan(wifi_request_id id,wifi_interface_handle iface)720 wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
721 {
722     wifi_handle handle = getWifiHandle(iface);
723     ALOGV("Stopping GScan, wifi_request_id = %d, halHandle = %p", id, handle);
724 
725     if (id == -1) {
726         wifi_scan_result_handler handler;
727         wifi_scan_cmd_params dummy_params;
728         wifi_handle handle = getWifiHandle(iface);
729         memset(&handler, 0, sizeof(handler));
730 
731         ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
732         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
733         cmd->cancel();
734         cmd->releaseRef();
735         return WIFI_SUCCESS;
736     }
737 
738     return wifi_cancel_cmd(id, iface);
739 }
740 
wifi_enable_full_scan_results(wifi_request_id id,wifi_interface_handle iface,wifi_scan_result_handler handler)741 wifi_error wifi_enable_full_scan_results(
742         wifi_request_id id,
743         wifi_interface_handle iface,
744         wifi_scan_result_handler handler)
745 {
746     wifi_handle handle = getWifiHandle(iface);
747     int params_dummy;
748 
749     ALOGV("Enabling full scan results, halHandle = %p", handle);
750 
751     FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, &params_dummy, handler);
752     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
753     wifi_error result = wifi_register_cmd(handle, id, cmd);
754     if (result != WIFI_SUCCESS) {
755         cmd->releaseRef();
756         return result;
757     }
758     result = (wifi_error)cmd->start();
759     if (result != WIFI_SUCCESS) {
760         wifi_unregister_cmd(handle, id);
761         cmd->releaseRef();
762         return result;
763     }
764     return result;
765 }
766 
wifi_handle_full_scan_event(wifi_request_id id,WifiEvent & event,wifi_scan_result_handler handler)767 int wifi_handle_full_scan_event(
768         wifi_request_id id,
769         WifiEvent& event,
770         wifi_scan_result_handler handler)
771 {
772     nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
773     unsigned int len = event.get_vendor_data_len();
774 
775     if (vendor_data == NULL || len < sizeof(wifi_gscan_full_result_t)) {
776         ALOGI("Full scan results: No scan results found");
777         return NL_SKIP;
778     }
779 
780     wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data();
781     /* To protect against corrupted data, put a ceiling */
782     int ie_len = min(MAX_PROBE_RESP_IE_LEN, drv_res->ie_length);
783     wifi_scan_result *full_scan_result;
784     wifi_gscan_result_t *fixed = &drv_res->fixed;
785 
786     if ((ie_len + offsetof(wifi_gscan_full_result_t, ie_data)) > len) {
787         ALOGE("BAD event data, len %d ie_len %d fixed length %d!\n", len,
788             ie_len, offsetof(wifi_gscan_full_result_t, ie_data));
789         return NL_SKIP;
790     }
791     full_scan_result = (wifi_scan_result *) malloc((ie_len + offsetof(wifi_scan_result, ie_data)));
792     if (!full_scan_result) {
793         ALOGE("Full scan results: Can't malloc!\n");
794         return NL_SKIP;
795     }
796     convert_to_hal_result(full_scan_result, fixed);
797     full_scan_result->ie_length = ie_len;
798     memcpy(full_scan_result->ie_data, drv_res->ie_data, ie_len);
799     if(handler.on_full_scan_result)
800         handler.on_full_scan_result(id, full_scan_result, drv_res->scan_ch_bucket);
801 
802     ALOGV("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %lld %lld %lld %x %d\n",
803         fixed->ssid, fixed->bssid[0], fixed->bssid[1], fixed->bssid[2], fixed->bssid[3],
804         fixed->bssid[4], fixed->bssid[5], fixed->rssi, fixed->channel, fixed->ts,
805         fixed->rtt, fixed->rtt_sd, drv_res->scan_ch_bucket, drv_res->ie_length);
806     free(full_scan_result);
807     return NL_SKIP;
808 }
809 
810 
wifi_disable_full_scan_results(wifi_request_id id,wifi_interface_handle iface)811 wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface)
812 {
813     ALOGV("Disabling full scan results");
814     wifi_handle handle = getWifiHandle(iface);
815 
816     if(id == -1) {
817         wifi_scan_result_handler handler;
818         wifi_handle handle = getWifiHandle(iface);
819         int params_dummy;
820 
821         memset(&handler, 0, sizeof(handler));
822         FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, &params_dummy, handler);
823         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
824         cmd->cancel();
825         cmd->releaseRef();
826         return WIFI_SUCCESS;
827     }
828 
829     return wifi_cancel_cmd(id, iface);
830 }
831 
832 
833 /////////////////////////////////////////////////////////////////////////////
834 
835 class GetScanResultsCommand : public WifiCommand {
836     wifi_cached_scan_results *mScans;
837     int mMax;
838     int *mNum;
839     int mRetrieved;
840     byte mFlush;
841     int mCompleted;
842 public:
GetScanResultsCommand(wifi_interface_handle iface,byte flush,wifi_cached_scan_results * results,int max,int * num)843     GetScanResultsCommand(wifi_interface_handle iface, byte flush,
844             wifi_cached_scan_results *results, int max, int *num)
845         : WifiCommand("GetScanResultsCommand", iface, -1), mScans(results), mMax(max), mNum(num),
846                 mRetrieved(0), mFlush(flush), mCompleted(0)
847     { }
848 
createRequest(WifiRequest & request,int num,byte flush)849     int createRequest(WifiRequest& request, int num, byte flush) {
850         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS);
851         if (result < 0) {
852             return result;
853         }
854 
855         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
856         result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num);
857         if (result < 0) {
858             return result;
859         }
860 
861         result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush);
862         if (result < 0) {
863             return result;
864         }
865 
866         request.attr_end(data);
867         return WIFI_SUCCESS;
868     }
869 
execute()870     int execute() {
871         WifiRequest request(familyId(), ifaceId());
872         ALOGV("retrieving %d scan results", mMax);
873 
874         for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
875             int num_to_retrieve = mMax - mRetrieved;
876             // ALOGI("retrieving %d scan results in one shot", num_to_retrieve);
877             int result = createRequest(request, num_to_retrieve, mFlush);
878             if (result < 0) {
879                 ALOGE("failed to create request");
880                 return result;
881             }
882 
883             int prev_retrieved = mRetrieved;
884 
885             result = requestResponse(request);
886 
887             if (result != WIFI_SUCCESS) {
888                 ALOGE("failed to retrieve scan results; result = %d", result);
889                 return result;
890             }
891 
892             if (mRetrieved == prev_retrieved || mCompleted) {
893                 /* no more items left to retrieve */
894                 break;
895             }
896 
897             request.destroy();
898         }
899 
900         ALOGV("GetScanResults read %d results", mRetrieved);
901         *mNum = mRetrieved;
902         return WIFI_SUCCESS;
903     }
904 
handleResponse(WifiEvent & reply)905     virtual int handleResponse(WifiEvent& reply) {
906         ALOGV("In GetScanResultsCommand::handleResponse");
907 
908         if (reply.get_cmd() != NL80211_CMD_VENDOR) {
909             ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
910             return NL_SKIP;
911         }
912 
913         int id = reply.get_vendor_id();
914         int subcmd = reply.get_vendor_subcmd();
915 
916         ALOGV("Id = %0x, subcmd = %d", id, subcmd);
917 
918         /*
919         if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) {
920             ALOGE("Invalid response to GetScanResultsCommand; ignoring it");
921             return NL_SKIP;
922         }
923         */
924 
925         nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
926         int len = reply.get_vendor_data_len();
927 
928         if (vendor_data == NULL || len == 0) {
929             ALOGE("no vendor data in GetScanResults response; ignoring it");
930             return NL_SKIP;
931         }
932 
933         for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
934             if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) {
935                 mCompleted = it.get_u8();
936                 ALOGV("retrieved mCompleted flag : %d", mCompleted);
937             } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) {
938                 int scan_id = 0, flags = 0, num = 0, scan_ch_bucket_mask = 0;
939                 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
940                     if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) {
941                         scan_id = it2.get_u32();
942                         ALOGV("retrieved scan_id : 0x%0x", scan_id);
943                     } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) {
944                         flags = it2.get_u8();
945                         ALOGV("retrieved scan_flags : 0x%0x", flags);
946                     } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) {
947                         num = it2.get_u32();
948                         ALOGV("retrieved num_results: %d", num);
949                     } else if (it2.get_type() == GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK) {
950                         scan_ch_bucket_mask = it2.get_u32();
951                         ALOGD("retrieved scan_ch_bucket_mask: %x", scan_ch_bucket_mask);
952                     } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS && num) {
953                         if (mRetrieved >= mMax) {
954                             ALOGW("Stored %d scans, ignoring excess results", mRetrieved);
955                             break;
956                         }
957                         num = min(num, (int)(it2.get_len()/sizeof(wifi_gscan_result)));
958                         num = min(num, (int)MAX_AP_CACHE_PER_SCAN);
959                         ALOGV("Copying %d scan results", num);
960                         wifi_gscan_result_t *results = (wifi_gscan_result_t *)it2.get_data();
961                         wifi_scan_result *mScanResults = mScans[mRetrieved].results;
962 
963                         for (int i = 0; i < num; i++) {
964                             wifi_gscan_result_t *result = &results[i];
965                             convert_to_hal_result(&mScanResults[i], result);
966                             mScanResults[i].ie_length = 0;
967                             ALOGV("%02d  %-32s  %02x:%02x:%02x:%02x:%02x:%02x  %04d", i,
968                                 result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
969                                 result->bssid[3], result->bssid[4], result->bssid[5],
970                                 result->rssi);
971                         }
972                         mScans[mRetrieved].scan_id = scan_id;
973                         mScans[mRetrieved].flags = flags;
974                         mScans[mRetrieved].num_results = num;
975                         mScans[mRetrieved].buckets_scanned = scan_ch_bucket_mask;
976                         ALOGV("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
977                         mRetrieved++;
978                     } else {
979                         ALOGW("Ignoring invalid attribute type = %d, size = %d",
980                                 it.get_type(), it.get_len());
981                     }
982                 }
983             } else {
984                 ALOGW("Ignoring invalid attribute type = %d, size = %d",
985                         it.get_type(), it.get_len());
986             }
987         }
988         ALOGV("GetScanResults read %d results", mRetrieved);
989         return NL_OK;
990     }
991 };
992 
wifi_get_cached_gscan_results(wifi_interface_handle iface,byte flush,int max,wifi_cached_scan_results * results,int * num)993 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
994         int max, wifi_cached_scan_results *results, int *num) {
995     ALOGV("Getting cached scan results, iface handle = %p, num = %d", iface, *num);
996 
997     GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
998     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
999     wifi_error err = (wifi_error)cmd->execute();
1000     cmd->releaseRef();
1001     return err;
1002 }
1003 
1004 /////////////////////////////////////////////////////////////////////////////
1005 
1006 class BssidHotlistCommand : public WifiCommand
1007 {
1008 private:
1009     wifi_bssid_hotlist_params mParams;
1010     wifi_hotlist_ap_found_handler mHandler;
1011     static const int MAX_RESULTS = 64;
1012     wifi_scan_result mResults[MAX_RESULTS];
1013 public:
BssidHotlistCommand(wifi_interface_handle handle,int id,wifi_bssid_hotlist_params params,wifi_hotlist_ap_found_handler handler)1014     BssidHotlistCommand(wifi_interface_handle handle, int id,
1015             wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
1016         : WifiCommand("BssidHotlistCommand", handle, id), mParams(params), mHandler(handler)
1017     { }
1018 
createSetupRequest(WifiRequest & request)1019     int createSetupRequest(WifiRequest& request) {
1020         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
1021         if (result < 0) {
1022             return result;
1023         }
1024 
1025         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1026         result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
1027         if (result < 0) {
1028             return result;
1029         }
1030 
1031         result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
1032         if (result < 0) {
1033             return result;
1034         }
1035 
1036         result = request.put_u32(GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT, mParams.num_bssid);
1037         if (result < 0) {
1038             return result;
1039         }
1040 
1041         struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
1042         for (int i = 0; i < mParams.num_bssid; i++) {
1043             nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM);
1044             if (attr2 == NULL) {
1045                 return WIFI_ERROR_OUT_OF_MEMORY;
1046             }
1047             result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
1048             if (result < 0) {
1049                 return result;
1050             }
1051             result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
1052             if (result < 0) {
1053                 return result;
1054             }
1055             result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
1056             if (result < 0) {
1057                 return result;
1058             }
1059             request.attr_end(attr2);
1060         }
1061 
1062         request.attr_end(attr);
1063         request.attr_end(data);
1064         return result;
1065     }
1066 
createTeardownRequest(WifiRequest & request)1067     int createTeardownRequest(WifiRequest& request) {
1068         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST);
1069         if (result < 0) {
1070             return result;
1071         }
1072 
1073         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1074         result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1);
1075         if (result < 0) {
1076             return result;
1077         }
1078 
1079         struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
1080         request.attr_end(attr);
1081         request.attr_end(data);
1082         return result;
1083     }
1084 
start()1085     int start() {
1086         ALOGI("Executing hotlist setup request, num = %d", mParams.num_bssid);
1087         WifiRequest request(familyId(), ifaceId());
1088         int result = createSetupRequest(request);
1089         if (result < 0) {
1090             return result;
1091         }
1092 
1093         result = requestResponse(request);
1094         if (result < 0) {
1095             ALOGI("Failed to execute hotlist setup request, result = %d", result);
1096             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1097             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
1098             return result;
1099         }
1100 
1101         ALOGI("Successfully set %d APs in the hotlist ", mParams.num_bssid);
1102         result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
1103         if (result < 0) {
1104             return result;
1105         }
1106 
1107         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1108         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
1109 
1110         result = requestResponse(request);
1111         if (result < 0) {
1112             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1113             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
1114             return result;
1115         }
1116 
1117         ALOGI("successfully restarted the scan");
1118         return result;
1119     }
1120 
cancel()1121     virtual int cancel() {
1122         /* unregister event handler */
1123         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
1124         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
1125         /* create set hotlist message with empty hotlist */
1126         WifiRequest request(familyId(), ifaceId());
1127         int result = createTeardownRequest(request);
1128         if (result < 0) {
1129             return result;
1130         }
1131 
1132         result = requestResponse(request);
1133         if (result < 0) {
1134             return result;
1135         }
1136 
1137         ALOGI("Successfully reset APs in current hotlist");
1138         return result;
1139     }
1140 
handleResponse(WifiEvent & reply)1141     virtual int handleResponse(WifiEvent& reply) {
1142         /* Nothing to do on response! */
1143         return NL_SKIP;
1144     }
1145 
handleEvent(WifiEvent & event)1146     virtual int handleEvent(WifiEvent& event) {
1147         ALOGI("Hotlist AP event");
1148         int event_id = event.get_vendor_subcmd();
1149         // event.log();
1150 
1151         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1152         int len = event.get_vendor_data_len();
1153 
1154         if (vendor_data == NULL || len == 0) {
1155             ALOGI("No scan results found");
1156             return NL_SKIP;
1157         }
1158 
1159         memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS);
1160 
1161         int num = len / sizeof(wifi_gscan_result_t);
1162         wifi_gscan_result_t *inp = (wifi_gscan_result_t *)event.get_vendor_data();
1163         num = min(MAX_RESULTS, num);
1164         for (int i = 0; i < num; i++, inp++) {
1165             convert_to_hal_result(&(mResults[i]), inp);
1166         }
1167 
1168         if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) {
1169             ALOGI("FOUND %d hotlist APs", num);
1170             if (*mHandler.on_hotlist_ap_found)
1171                 (*mHandler.on_hotlist_ap_found)(id(), num, mResults);
1172         } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) {
1173             ALOGI("LOST %d hotlist APs", num);
1174             if (*mHandler.on_hotlist_ap_lost)
1175                 (*mHandler.on_hotlist_ap_lost)(id(), num, mResults);
1176         }
1177         return NL_SKIP;
1178     }
1179 };
1180 
1181 class ePNOCommand : public WifiCommand
1182 {
1183 private:
1184     wifi_epno_params epno_params;
1185     wifi_epno_handler mHandler;
1186     wifi_scan_result mResults[MAX_EPNO_NETWORKS];
1187 public:
ePNOCommand(wifi_interface_handle handle,int id,const wifi_epno_params * params,wifi_epno_handler handler)1188     ePNOCommand(wifi_interface_handle handle, int id,
1189             const wifi_epno_params *params, wifi_epno_handler handler)
1190         : WifiCommand("ePNOCommand", handle, id), mHandler(handler)
1191     {
1192         if (params != NULL) {
1193             memcpy(&epno_params, params, sizeof(wifi_epno_params));
1194         } else {
1195             memset(&epno_params, 0, sizeof(wifi_epno_params));
1196         }
1197     }
createSetupRequest(WifiRequest & request)1198     int createSetupRequest(WifiRequest& request) {
1199         if (epno_params.num_networks > MAX_EPNO_NETWORKS) {
1200             ALOGE("wrong epno num_networks:%d", epno_params.num_networks);
1201             return WIFI_ERROR_INVALID_ARGS;
1202         }
1203         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
1204         if (result < 0) {
1205             return result;
1206         }
1207         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1208         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
1209         if (result < 0) {
1210             return result;
1211         }
1212 
1213         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR,
1214                             (u8)epno_params.min5GHz_rssi);
1215         if (result < 0) {
1216             return result;
1217         }
1218         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR,
1219                             (u8)epno_params.min24GHz_rssi);
1220         if (result < 0) {
1221             return result;
1222         }
1223         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX,
1224                             epno_params.initial_score_max);
1225         if (result < 0) {
1226             return result;
1227         }
1228         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS,
1229                             epno_params.current_connection_bonus);
1230         if (result < 0) {
1231             return result;
1232         }
1233         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS,
1234                             epno_params.same_network_bonus);
1235         if (result < 0) {
1236             return result;
1237         }
1238         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS,
1239                             epno_params.secure_bonus);
1240         if (result < 0) {
1241             return result;
1242         }
1243         result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_5G_BONUS,
1244                             epno_params.band5GHz_bonus);
1245         if (result < 0) {
1246             return result;
1247         }
1248         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM,
1249                         epno_params.num_networks);
1250         if (result < 0) {
1251             return result;
1252         }
1253         struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST);
1254         wifi_epno_network *ssid_list = epno_params.networks;
1255         for (int i = 0; i < epno_params.num_networks; i++) {
1256             nlattr *attr2 = request.attr_start(i);
1257             if (attr2 == NULL) {
1258                 return WIFI_ERROR_OUT_OF_MEMORY;
1259             }
1260             result = request.put(GSCAN_ATTRIBUTE_EPNO_SSID, ssid_list[i].ssid, DOT11_MAX_SSID_LEN);
1261             ALOGI("PNO network: SSID %s flags %x auth %x", ssid_list[i].ssid,
1262                 ssid_list[i].flags,
1263                 ssid_list[i].auth_bit_field);
1264             if (result < 0) {
1265                 return result;
1266             }
1267             result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_SSID_LEN, strlen(ssid_list[i].ssid));
1268             if (result < 0) {
1269                 return result;
1270             }
1271             result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_FLAGS, ssid_list[i].flags);
1272             if (result < 0) {
1273                 return result;
1274             }
1275             result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_AUTH, ssid_list[i].auth_bit_field);
1276             if (result < 0) {
1277                 return result;
1278             }
1279             request.attr_end(attr2);
1280         }
1281         request.attr_end(attr);
1282         request.attr_end(data);
1283         return result;
1284     }
1285 
createTeardownRequest(WifiRequest & request)1286     int createTeardownRequest(WifiRequest& request) {
1287         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID);
1288         if (result < 0) {
1289             return result;
1290         }
1291 
1292         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1293         result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1);
1294         if (result < 0) {
1295             return result;
1296         }
1297         request.attr_end(data);
1298         return result;
1299     }
1300 
start()1301     int start() {
1302         ALOGI("Executing ePNO setup request, num = %d", epno_params.num_networks);
1303         WifiRequest request(familyId(), ifaceId());
1304         int result = createSetupRequest(request);
1305         if (result < 0) {
1306             return result;
1307         }
1308 
1309         result = requestResponse(request);
1310         if (result < 0) {
1311             ALOGI("Failed to execute ePNO setup request, result = %d", result);
1312             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
1313             return result;
1314         }
1315 
1316         ALOGI("Successfully set %d SSIDs for ePNO", epno_params.num_networks);
1317         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
1318         ALOGI("successfully restarted the scan");
1319         return result;
1320     }
1321 
cancel()1322     virtual int cancel() {
1323         /* unregister event handler */
1324         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT);
1325         /* create set hotlist message with empty hotlist */
1326         WifiRequest request(familyId(), ifaceId());
1327         int result = createTeardownRequest(request);
1328         if (result < 0) {
1329             return result;
1330         }
1331 
1332         result = requestResponse(request);
1333         if (result < 0) {
1334             return result;
1335         }
1336 
1337         ALOGI("Successfully reset APs in current hotlist");
1338         return result;
1339     }
1340 
handleResponse(WifiEvent & reply)1341     virtual int handleResponse(WifiEvent& reply) {
1342         /* Nothing to do on response! */
1343         return NL_SKIP;
1344     }
1345 
handleEvent(WifiEvent & event)1346     virtual int handleEvent(WifiEvent& event) {
1347         ALOGI("ePNO event");
1348         int event_id = event.get_vendor_subcmd();
1349         // event.log();
1350 
1351         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1352         int len = event.get_vendor_data_len();
1353 
1354         if (vendor_data == NULL || len == 0) {
1355             ALOGI("No scan results found");
1356             return NL_SKIP;
1357         }
1358 
1359         memset(mResults, 0, sizeof(wifi_scan_result) * MAX_EPNO_NETWORKS);
1360 
1361         unsigned int num = len / sizeof(wifi_pno_result_t);
1362         unsigned int i;
1363         num = min(MAX_EPNO_NETWORKS, num);
1364         wifi_pno_result_t *res = (wifi_pno_result_t *) event.get_vendor_data();
1365         for (i = 0; i < num; i++) {
1366             if (res[i].flags == PNO_SSID_FOUND) {
1367                 memcpy(mResults[i].ssid, res[i].ssid, res[i].ssid_len);
1368                 memcpy(mResults[i].bssid, res[i].bssid, sizeof(mac_addr));
1369 
1370                 mResults[i].ssid[res[i].ssid_len] = '\0';
1371                 mResults[i].channel = res[i].channel;
1372                 mResults[i].rssi = res[i].rssi;
1373             }
1374         }
1375         if (*mHandler.on_network_found)
1376             (*mHandler.on_network_found)(id(), num, mResults);
1377         return NL_SKIP;
1378     }
1379 };
1380 
wifi_set_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface,wifi_bssid_hotlist_params params,wifi_hotlist_ap_found_handler handler)1381 wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
1382         wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
1383 {
1384     wifi_handle handle = getWifiHandle(iface);
1385 
1386     BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
1387     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1388     wifi_error result = wifi_register_cmd(handle, id, cmd);
1389     if (result != WIFI_SUCCESS) {
1390         cmd->releaseRef();
1391         return result;
1392     }
1393     result = (wifi_error)cmd->start();
1394     if (result != WIFI_SUCCESS) {
1395         wifi_unregister_cmd(handle, id);
1396         cmd->releaseRef();
1397         return result;
1398     }
1399     return result;
1400 }
1401 
wifi_reset_bssid_hotlist(wifi_request_id id,wifi_interface_handle iface)1402 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
1403 {
1404     return wifi_cancel_cmd(id, iface);
1405 }
1406 
1407 
1408 /////////////////////////////////////////////////////////////////////////////
1409 
1410 class SignificantWifiChangeCommand : public WifiCommand
1411 {
1412     typedef struct {
1413         mac_addr bssid;                     // BSSID
1414         wifi_channel channel;               // channel frequency in MHz
1415         int num_rssi;                       // number of rssi samples
1416         wifi_rssi rssi[8];                   // RSSI history in db
1417     } wifi_significant_change_result_internal;
1418 
1419 private:
1420     wifi_significant_change_params mParams;
1421     wifi_significant_change_handler mHandler;
1422     static const int MAX_RESULTS = 64;
1423     wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS];
1424     wifi_significant_change_result *mResults[MAX_RESULTS];
1425 public:
SignificantWifiChangeCommand(wifi_interface_handle handle,int id,wifi_significant_change_params params,wifi_significant_change_handler handler)1426     SignificantWifiChangeCommand(wifi_interface_handle handle, int id,
1427             wifi_significant_change_params params, wifi_significant_change_handler handler)
1428         : WifiCommand("SignificantWifiChangeCommand", handle, id), mParams(params),
1429             mHandler(handler)
1430     { }
1431 
createSetupRequest(WifiRequest & request)1432     int createSetupRequest(WifiRequest& request) {
1433         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
1434         if (result < 0) {
1435             return result;
1436         }
1437 
1438         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1439         result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
1440         if (result < 0) {
1441             return result;
1442         }
1443         result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size);
1444         if (result < 0) {
1445             return result;
1446         }
1447         result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
1448         if (result < 0) {
1449             return result;
1450         }
1451         result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching);
1452         if (result < 0) {
1453             return result;
1454         }
1455         result = request.put_u16(GSCAN_ATTRIBUTE_NUM_BSSID, mParams.num_bssid);
1456         if (result < 0) {
1457             return result;
1458         }
1459         if (mParams.num_bssid != 0) {
1460             nlattr* attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS);
1461             if (attr == NULL) {
1462                 return WIFI_ERROR_OUT_OF_MEMORY;
1463             }
1464 
1465             for (int i = 0; i < mParams.num_bssid; i++) {
1466                 nlattr* attr2 = request.attr_start(i);
1467                 if (attr2 == NULL) {
1468                     return WIFI_ERROR_OUT_OF_MEMORY;
1469                 }
1470                 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
1471                 if (result < 0) {
1472                     return result;
1473                 }
1474                 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
1475                 if (result < 0) {
1476                     return result;
1477                 }
1478                 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
1479                 if (result < 0) {
1480                     return result;
1481                 }
1482                 request.attr_end(attr2);
1483             }
1484 
1485             request.attr_end(attr);
1486         }
1487         request.attr_end(data);
1488 
1489         return result;
1490     }
1491 
createTeardownRequest(WifiRequest & request)1492     int createTeardownRequest(WifiRequest& request) {
1493         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG);
1494         if (result < 0) {
1495             return result;
1496         }
1497 
1498         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1499         result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1);
1500         if (result < 0) {
1501             return result;
1502         }
1503 
1504         request.attr_end(data);
1505         return result;
1506     }
1507 
start()1508     int start() {
1509         ALOGI("Set significant wifi change config");
1510         WifiRequest request(familyId(), ifaceId());
1511 
1512         int result = createSetupRequest(request);
1513         if (result < 0) {
1514             return result;
1515         }
1516 
1517         result = requestResponse(request);
1518         if (result < 0) {
1519             ALOGI("failed to set significant wifi change config %d", result);
1520             return result;
1521         }
1522 
1523         ALOGI("successfully set significant wifi change config");
1524 
1525         result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
1526         if (result < 0) {
1527             return result;
1528         }
1529 
1530         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
1531 
1532         result = requestResponse(request);
1533         if (result < 0) {
1534             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
1535             return result;
1536         }
1537 
1538         ALOGI("successfully restarted the scan");
1539         return result;
1540     }
1541 
cancel()1542     virtual int cancel() {
1543         /* unregister event handler */
1544         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
1545 
1546         /* create set significant change monitor message with empty hotlist */
1547         WifiRequest request(familyId(), ifaceId());
1548 
1549         int result = createTeardownRequest(request);
1550         if (result < 0) {
1551             return result;
1552         }
1553 
1554         result = requestResponse(request);
1555         if (result < 0) {
1556             return result;
1557         }
1558 
1559         ALOGI("successfully reset significant wifi change config");
1560         return result;
1561     }
1562 
handleResponse(WifiEvent & reply)1563     virtual int handleResponse(WifiEvent& reply) {
1564         /* Nothing to do on response! */
1565         return NL_SKIP;
1566     }
1567 
handleEvent(WifiEvent & event)1568     virtual int handleEvent(WifiEvent& event) {
1569         ALOGV("Got a significant wifi change event");
1570 
1571         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1572         int len = event.get_vendor_data_len();
1573 
1574         if (vendor_data == NULL || len == 0) {
1575             ALOGI("No scan results found");
1576             return NL_SKIP;
1577         }
1578 
1579         typedef struct {
1580             uint16_t flags;
1581             uint16_t channel;
1582             mac_addr bssid;
1583             s8 rssi_history[8];
1584         } ChangeInfo;
1585 
1586         int num = min(len / sizeof(ChangeInfo), MAX_RESULTS);
1587         ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data();
1588 
1589         for (int i = 0; i < num; i++) {
1590             memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr));
1591             mResultsBuffer[i].channel = ci[i].channel;
1592             mResultsBuffer[i].num_rssi = 8;
1593             for (int j = 0; j < mResultsBuffer[i].num_rssi; j++)
1594                 mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j];
1595             mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
1596         }
1597 
1598         ALOGV("Retrieved %d scan results", num);
1599 
1600         if (num != 0) {
1601             (*mHandler.on_significant_change)(id(), num, mResults);
1602         } else {
1603             ALOGW("No significant change reported");
1604         }
1605 
1606         return NL_SKIP;
1607     }
1608 };
1609 
wifi_set_significant_change_handler(wifi_request_id id,wifi_interface_handle iface,wifi_significant_change_params params,wifi_significant_change_handler handler)1610 wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface,
1611         wifi_significant_change_params params, wifi_significant_change_handler handler)
1612 {
1613     wifi_handle handle = getWifiHandle(iface);
1614 
1615     SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
1616             iface, id, params, handler);
1617     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1618     wifi_error result = wifi_register_cmd(handle, id, cmd);
1619     if (result != WIFI_SUCCESS) {
1620         cmd->releaseRef();
1621         return result;
1622     }
1623     result = (wifi_error)cmd->start();
1624     if (result != WIFI_SUCCESS) {
1625         wifi_unregister_cmd(handle, id);
1626         cmd->releaseRef();
1627         return result;
1628     }
1629     return result;
1630 }
1631 
wifi_reset_significant_change_handler(wifi_request_id id,wifi_interface_handle iface)1632 wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
1633 {
1634     return wifi_cancel_cmd(id, iface);
1635 }
1636 
wifi_reset_epno_list(wifi_request_id id,wifi_interface_handle iface)1637 wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
1638 {
1639     if (id == -1) {
1640         wifi_epno_handler handler;
1641         wifi_handle handle = getWifiHandle(iface);
1642 
1643         memset(&handler, 0, sizeof(handler));
1644         ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler);
1645         NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1646         cmd->cancel();
1647         cmd->releaseRef();
1648         return WIFI_SUCCESS;
1649     }
1650     return wifi_cancel_cmd(id, iface);
1651 }
1652 
wifi_set_epno_list(wifi_request_id id,wifi_interface_handle iface,const wifi_epno_params * params,wifi_epno_handler handler)1653 wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface,
1654         const wifi_epno_params *params, wifi_epno_handler handler)
1655 {
1656     wifi_handle handle = getWifiHandle(iface);
1657 
1658     ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler);
1659     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1660     wifi_error result = wifi_register_cmd(handle, id, cmd);
1661     if (result != WIFI_SUCCESS) {
1662         cmd->releaseRef();
1663         return result;
1664     }
1665     result = (wifi_error)cmd->start();
1666     if (result != WIFI_SUCCESS) {
1667         wifi_unregister_cmd(handle, id);
1668         cmd->releaseRef();
1669         return result;
1670     }
1671     return result;
1672 }
1673 
1674 
1675 ////////////////////////////////////////////////////////////////////////////////
1676 
1677 class AnqpoConfigureCommand : public WifiCommand
1678 {
1679     int num_hs;
1680     wifi_passpoint_network *mNetworks;
1681     wifi_passpoint_event_handler mHandler;
1682     wifi_scan_result *mResult;
1683 public:
AnqpoConfigureCommand(wifi_request_id id,wifi_interface_handle iface,int num,wifi_passpoint_network * hs_list,wifi_passpoint_event_handler handler)1684     AnqpoConfigureCommand(wifi_request_id id, wifi_interface_handle iface,
1685         int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler)
1686         : WifiCommand("AnqpoConfigureCommand", iface, id), num_hs(num), mNetworks(hs_list),
1687             mHandler(handler)
1688     {
1689         mResult = NULL;
1690     }
1691 
createRequest(WifiRequest & request,int val)1692     int createRequest(WifiRequest& request, int val) {
1693 
1694         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_ANQPO_CONFIG);
1695         result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, num_hs);
1696         if (result < 0) {
1697             return result;
1698         }
1699 
1700         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1701 
1702         struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST);
1703         for (int i = 0; i < num_hs; i++) {
1704             nlattr *attr2 = request.attr_start(i);
1705             if (attr2 == NULL) {
1706                 return WIFI_ERROR_OUT_OF_MEMORY;
1707             }
1708             result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, mNetworks[i].id);
1709             if (result < 0) {
1710                 return result;
1711             }
1712             result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, mNetworks[i].realm, 256);
1713             if (result < 0) {
1714                 return result;
1715             }
1716             result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
1717                          mNetworks[i].roamingConsortiumIds, 128);
1718             if (result < 0) {
1719                 return result;
1720             }
1721             result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, mNetworks[i].plmn, 3);
1722             if (result < 0) {
1723                 return result;
1724             }
1725 
1726             request.attr_end(attr2);
1727         }
1728 
1729         request.attr_end(attr);
1730         request.attr_end(data);
1731 
1732         return WIFI_SUCCESS;
1733     }
1734 
start()1735     int start() {
1736 
1737         WifiRequest request(familyId(), ifaceId());
1738         int result = createRequest(request, num_hs);
1739         if (result != WIFI_SUCCESS) {
1740             ALOGE("failed to create request; result = %d", result);
1741             return result;
1742         }
1743 
1744         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1745 
1746         result = requestResponse(request);
1747         if (result != WIFI_SUCCESS) {
1748             ALOGE("failed to set ANQPO networks; result = %d", result);
1749             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1750             return result;
1751         }
1752 
1753         return result;
1754     }
1755 
cancel()1756     virtual int cancel() {
1757 
1758         WifiRequest request(familyId(), ifaceId());
1759         int result = createRequest(request, 0);
1760         if (result != WIFI_SUCCESS) {
1761             ALOGE("failed to create request; result = %d", result);
1762         } else {
1763             result = requestResponse(request);
1764             if (result != WIFI_SUCCESS) {
1765                 ALOGE("failed to reset ANQPO networks;result = %d", result);
1766             }
1767         }
1768 
1769         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1770         return WIFI_SUCCESS;
1771     }
1772 
handleResponse(WifiEvent & reply)1773     virtual int handleResponse(WifiEvent& reply) {
1774          ALOGD("Request complete!");
1775         /* Nothing to do on response! */
1776         return NL_SKIP;
1777     }
1778 
handleEvent(WifiEvent & event)1779     virtual int handleEvent(WifiEvent& event) {
1780         typedef struct {
1781             u16 channel;        /* channel of GAS protocol */
1782             u8  dialog_token;   /* GAS dialog token */
1783             u8  fragment_id;    /* fragment id */
1784             u16 status_code;    /* status code on GAS completion */
1785             u16 data_len;       /* length of data to follow */
1786             u8  data[1];        /* variable length specified by data_len */
1787         } wifi_anqp_gas_resp;
1788 
1789         ALOGI("ANQPO hotspot matched event!");
1790 
1791         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1792         unsigned int len = event.get_vendor_data_len();
1793 
1794         if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
1795             ALOGI("No scan results found");
1796             return NL_SKIP;
1797         }
1798         mResult = (wifi_scan_result *)malloc(sizeof(wifi_scan_result));
1799         if (!mResult) {
1800             return NL_SKIP;
1801         }
1802         wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data();
1803         wifi_gscan_result_t *fixed = &drv_res->fixed;
1804         convert_to_hal_result(mResult, fixed);
1805 
1806         byte *anqp = (byte *)drv_res + offsetof(wifi_gscan_full_result_t, ie_data) + drv_res->ie_length;
1807         wifi_anqp_gas_resp *gas = (wifi_anqp_gas_resp *)anqp;
1808         int anqp_len = offsetof(wifi_anqp_gas_resp, data) + gas->data_len;
1809         int networkId = *(int *)((byte *)anqp + anqp_len);
1810 
1811         ALOGI("%-32s\t", mResult->ssid);
1812 
1813         ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1],
1814                 mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]);
1815 
1816         ALOGI("%d\t", mResult->rssi);
1817         ALOGI("%d\t", mResult->channel);
1818         ALOGI("%lld\t", mResult->ts);
1819         ALOGI("%lld\t", mResult->rtt);
1820         ALOGI("%lld\n", mResult->rtt_sd);
1821 
1822         if(*mHandler.on_passpoint_network_found)
1823             (*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp);
1824         free(mResult);
1825         return NL_SKIP;
1826     }
1827 };
1828 
wifi_set_passpoint_list(wifi_request_id id,wifi_interface_handle iface,int num,wifi_passpoint_network * networks,wifi_passpoint_event_handler handler)1829 wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num,
1830         wifi_passpoint_network *networks, wifi_passpoint_event_handler handler)
1831 {
1832     wifi_handle handle = getWifiHandle(iface);
1833 
1834     AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler);
1835     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1836     wifi_error result = wifi_register_cmd(handle, id, cmd);
1837     if (result != WIFI_SUCCESS) {
1838         cmd->releaseRef();
1839         return result;
1840     }
1841     result = (wifi_error)cmd->start();
1842     if (result != WIFI_SUCCESS) {
1843         wifi_unregister_cmd(handle, id);
1844         cmd->releaseRef();
1845         return result;
1846     }
1847     return result;
1848 }
1849 
wifi_reset_passpoint_list(wifi_request_id id,wifi_interface_handle iface)1850 wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
1851 {
1852     return wifi_cancel_cmd(id, iface);
1853 }
1854