net: wireless: bcmdhd: update bcm4358 FW (7.112.201.3) am: 38cfc377c2 am: 0c97e9a22b
[android/platform/hardware/broadcom/wlan.git] / bcmdhd / wifi_hal / gscan.cpp
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
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:
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
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:
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
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:
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     }
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:
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
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
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
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:
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
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
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
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
438     virtual int handleResponse(WifiEvent& reply) {
439          ALOGD("Request complete!");
440         /* Nothing to do on response! */
441         return NL_SKIP;
442     }
443
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:
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
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
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
566     int createStartRequest(WifiRequest& request) {
567         return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1);
568     }
569
570     int createStopRequest(WifiRequest& request) {
571         return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0);
572     }
573
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
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
646     virtual int handleResponse(WifiEvent& reply) {
647         /* Nothing to do on response! */
648         return NL_SKIP;
649     }
650
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
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
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
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
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
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:
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
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
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
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_gscan_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
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:
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
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
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
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
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
1119     virtual int handleResponse(WifiEvent& reply) {
1120         /* Nothing to do on response! */
1121         return NL_SKIP;
1122     }
1123
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:
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     }
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
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
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
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
1315     virtual int handleResponse(WifiEvent& reply) {
1316         /* Nothing to do on response! */
1317         return NL_SKIP;
1318     }
1319
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
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
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:
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
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
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
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
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
1529     virtual int handleResponse(WifiEvent& reply) {
1530         /* Nothing to do on response! */
1531         return NL_SKIP;
1532     }
1533
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
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
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
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
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
1641 ////////////////////////////////////////////////////////////////////////////////
1642
1643 class AnqpoConfigureCommand : public WifiCommand
1644 {
1645     int num_hs;
1646     wifi_passpoint_network *mNetworks;
1647     wifi_passpoint_event_handler mHandler;
1648     wifi_scan_result *mResult;
1649 public:
1650     AnqpoConfigureCommand(wifi_request_id id, wifi_interface_handle iface,
1651         int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler)
1652         : WifiCommand("AnqpoConfigureCommand", iface, id), num_hs(num), mNetworks(hs_list),
1653             mHandler(handler)
1654     {
1655         mResult = NULL;
1656     }
1657
1658     int createRequest(WifiRequest& request, int val) {
1659
1660         int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_ANQPO_CONFIG);
1661         result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, num_hs);
1662         if (result < 0) {
1663             return result;
1664         }
1665
1666         nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1667
1668         struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST);
1669         for (int i = 0; i < num_hs; i++) {
1670             nlattr *attr2 = request.attr_start(i);
1671             if (attr2 == NULL) {
1672                 return WIFI_ERROR_OUT_OF_MEMORY;
1673             }
1674             result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, mNetworks[i].id);
1675             if (result < 0) {
1676                 return result;
1677             }
1678             result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, mNetworks[i].realm, 256);
1679             if (result < 0) {
1680                 return result;
1681             }
1682             result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID,
1683                          mNetworks[i].roamingConsortiumIds, 128);
1684             if (result < 0) {
1685                 return result;
1686             }
1687             result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, mNetworks[i].plmn, 3);
1688             if (result < 0) {
1689                 return result;
1690             }
1691
1692             request.attr_end(attr2);
1693         }
1694
1695         request.attr_end(attr);
1696         request.attr_end(data);
1697
1698         return WIFI_SUCCESS;
1699     }
1700
1701     int start() {
1702
1703         WifiRequest request(familyId(), ifaceId());
1704         int result = createRequest(request, num_hs);
1705         if (result != WIFI_SUCCESS) {
1706             ALOGE("failed to create request; result = %d", result);
1707             return result;
1708         }
1709
1710         registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1711
1712         result = requestResponse(request);
1713         if (result != WIFI_SUCCESS) {
1714             ALOGE("failed to set ANQPO networks; result = %d", result);
1715             unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1716             return result;
1717         }
1718
1719         return result;
1720     }
1721
1722     virtual int cancel() {
1723
1724         WifiRequest request(familyId(), ifaceId());
1725         int result = createRequest(request, 0);
1726         if (result != WIFI_SUCCESS) {
1727             ALOGE("failed to create request; result = %d", result);
1728         } else {
1729             result = requestResponse(request);
1730             if (result != WIFI_SUCCESS) {
1731                 ALOGE("failed to reset ANQPO networks;result = %d", result);
1732             }
1733         }
1734
1735         unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH);
1736         return WIFI_SUCCESS;
1737     }
1738
1739     virtual int handleResponse(WifiEvent& reply) {
1740          ALOGD("Request complete!");
1741         /* Nothing to do on response! */
1742         return NL_SKIP;
1743     }
1744
1745     virtual int handleEvent(WifiEvent& event) {
1746         typedef struct {
1747             u16 channel;        /* channel of GAS protocol */
1748             u8  dialog_token;   /* GAS dialog token */
1749             u8  fragment_id;    /* fragment id */
1750             u16 status_code;    /* status code on GAS completion */
1751             u16 data_len;       /* length of data to follow */
1752             u8  data[1];        /* variable length specified by data_len */
1753         } wifi_anqp_gas_resp;
1754
1755         ALOGI("ANQPO hotspot matched event!");
1756
1757         nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1758         unsigned int len = event.get_vendor_data_len();
1759
1760         if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
1761             ALOGI("No scan results found");
1762             return NL_SKIP;
1763         }
1764         mResult = (wifi_scan_result *)malloc(sizeof(wifi_scan_result));
1765         if (!mResult) {
1766             return NL_SKIP;
1767         }
1768         wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data();
1769         wifi_gscan_result_t *fixed = &drv_res->fixed;
1770         convert_to_hal_result(mResult, fixed);
1771
1772         byte *anqp = (byte *)drv_res + offsetof(wifi_gscan_full_result_t, ie_data) + drv_res->ie_length;
1773         wifi_anqp_gas_resp *gas = (wifi_anqp_gas_resp *)anqp;
1774         int anqp_len = offsetof(wifi_anqp_gas_resp, data) + gas->data_len;
1775         int networkId = *(int *)((byte *)anqp + anqp_len);
1776
1777         ALOGI("%-32s\t", mResult->ssid);
1778
1779         ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1],
1780                 mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]);
1781
1782         ALOGI("%d\t", mResult->rssi);
1783         ALOGI("%d\t", mResult->channel);
1784         ALOGI("%lld\t", mResult->ts);
1785         ALOGI("%lld\t", mResult->rtt);
1786         ALOGI("%lld\n", mResult->rtt_sd);
1787
1788         if(*mHandler.on_passpoint_network_found)
1789             (*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp);
1790         free(mResult);
1791         return NL_SKIP;
1792     }
1793 };
1794
1795 wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num,
1796         wifi_passpoint_network *networks, wifi_passpoint_event_handler handler)
1797 {
1798     wifi_handle handle = getWifiHandle(iface);
1799
1800     AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler);
1801     NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY);
1802     wifi_error result = wifi_register_cmd(handle, id, cmd);
1803     if (result != WIFI_SUCCESS) {
1804         cmd->releaseRef();
1805         return result;
1806     }
1807     result = (wifi_error)cmd->start();
1808     if (result != WIFI_SUCCESS) {
1809         wifi_unregister_cmd(handle, id);
1810         cmd->releaseRef();
1811         return result;
1812     }
1813     return result;
1814 }
1815
1816 wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
1817 {
1818     return wifi_cancel_cmd(id, iface);
1819 }