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