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