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