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