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