063ac557d54d9ac791289c34bf1e812d6074d757
[GitHub/LineageOS/android_hardware_samsung_slsi_scsc_wifibt_wifi_hal.git] / gscan.cpp
1
2 #include <stdint.h>
3 #include <stddef.h>
4 #include <fcntl.h>
5 #include <sys/socket.h>
6 #include <netlink/genl/genl.h>
7 #include <netlink/genl/family.h>
8 #include <netlink/genl/ctrl.h>
9 #include <linux/rtnetlink.h>
10 #include <netpacket/packet.h>
11 #include <linux/filter.h>
12 #include <linux/errqueue.h>
13
14 #include <linux/pkt_sched.h>
15 #include <netlink/object-api.h>
16 #include <netlink/netlink.h>
17 #include <netlink/socket.h>
18 #include <netlink/handlers.h>
19
20 #include "sync.h"
21
22 #include <utils/Log.h>
23
24 #include "wifi_hal.h"
25 #include "common.h"
26 #include "cpp_bindings.h"
27
28 typedef enum {
29 EPNO_ATTRIBUTE_MINIMUM_5G_RSSI,
30 EPNO_ATTRIBUTE_MINIMUM_2G_RSSI,
31 EPNO_ATTRIBUTE_INITIAL_SCORE_MAX,
32 EPNO_ATTRIBUTE_CUR_CONN_BONUS,
33 EPNO_ATTRIBUTE_SAME_NETWORK_BONUS,
34 EPNO_ATTRIBUTE_SECURE_BONUS,
35 EPNO_ATTRIBUTE_5G_BONUS,
36 EPNO_ATTRIBUTE_SSID_NUM,
37 EPNO_ATTRIBUTE_SSID_LIST,
38 EPNO_ATTRIBUTE_SSID,
39 EPNO_ATTRIBUTE_SSID_LEN,
40 EPNO_ATTRIBUTE_FLAGS,
41 EPNO_ATTRIBUTE_AUTH,
42 EPNO_ATTRIBUTE_MAX
43 } EPNO_ATTRIBUTE;
44
45 typedef enum {
46 EPNO_ATTRIBUTE_HS_PARAM_LIST,
47 EPNO_ATTRIBUTE_HS_NUM,
48 EPNO_ATTRIBUTE_HS_ID,
49 EPNO_ATTRIBUTE_HS_REALM,
50 EPNO_ATTRIBUTE_HS_CONSORTIUM_IDS,
51 EPNO_ATTRIBUTE_HS_PLMN,
52 EPNO_ATTRIBUTE_HS_MAX
53 } EPNO_HS_ATTRIBUTE;
54
55
56 class GetCapabilitiesCommand : public WifiCommand
57 {
58 wifi_gscan_capabilities *mCapabilities;
59 public:
60 GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites)
61 : WifiCommand(iface, 0), mCapabilities(capabitlites)
62 {
63 memset(mCapabilities, 0, sizeof(*mCapabilities));
64 }
65
66 virtual int create() {
67 int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES);
68 if (ret < 0) {
69 ALOGE("NL message creation failed");
70 return ret;
71 }
72
73 return ret;
74 }
75
76 protected:
77 virtual int handleResponse(WifiEvent& reply) {
78
79 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
80 ALOGE("Ignoring reply with cmd = %d", reply.get_cmd());
81 return NL_SKIP;
82 }
83
84 int id = reply.get_vendor_id();
85 int subcmd = reply.get_vendor_subcmd();
86
87 void *data = reply.get_vendor_data();
88 int len = reply.get_vendor_data_len();
89
90 memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
91
92 return NL_OK;
93 }
94 };
95
96
97 wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
98 wifi_gscan_capabilities *capabilities)
99 {
100 GetCapabilitiesCommand command(handle, capabilities);
101 return (wifi_error) command.requestResponse();
102 }
103
104 class GetChannelListCommand : public WifiCommand
105 {
106 wifi_channel *channels;
107 int max_channels;
108 int *num_channels;
109 int band;
110 public:
111 GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num,
112 int num_max_ch, int band)
113 : WifiCommand(iface, 0), channels(channel_buf), max_channels(num_max_ch), num_channels(ch_num),
114 band(band)
115 {
116 memset(channels, 0, sizeof(wifi_channel) * max_channels);
117 }
118 virtual int create() {
119 int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS);
120 if (ret < 0) {
121 return ret;
122 }
123
124 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
125 ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band);
126 if (ret < 0) {
127 return ret;
128 }
129
130 mMsg.attr_end(data);
131
132 return ret;
133 }
134
135 protected:
136 virtual int handleResponse(WifiEvent& reply) {
137
138 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
139 ALOGE("Ignoring reply with cmd = %d", reply.get_cmd());
140 return NL_SKIP;
141 }
142
143 int id = reply.get_vendor_id();
144 int subcmd = reply.get_vendor_subcmd();
145 int num_channels_to_copy = 0;
146
147 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
148 int len = reply.get_vendor_data_len();
149
150 if (vendor_data == NULL || len == 0) {
151 ALOGE("no vendor data in GetChannelList response; ignoring it");
152 return NL_SKIP;
153 }
154
155 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
156 if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) {
157 num_channels_to_copy = it.get_u32();
158 /*ALOGD("Got channel list with %d channels", num_channels_to_copy);*/
159 if(num_channels_to_copy > max_channels)
160 num_channels_to_copy = max_channels;
161 *num_channels = num_channels_to_copy;
162 } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) {
163 memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy);
164 } else {
165 ALOGW("Ignoring invalid attribute type = %d, size = %d",
166 it.get_type(), it.get_len());
167 }
168 }
169
170 return NL_OK;
171 }
172 };
173
174 wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
175 int band, int max_channels, wifi_channel *channels, int *num_channels)
176 {
177 GetChannelListCommand command(handle, channels, num_channels,
178 max_channels, band);
179 return (wifi_error) command.requestResponse();
180 }
181 /////////////////////////////////////////////////////////////////////////////
182
183 /* helper functions */
184
185 static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr)
186 {
187 memset(results, 0, sizeof(wifi_scan_result) * num);
188
189 int i = 0;
190 for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) {
191
192 int index = it.get_type();
193 nlattr *sc_data = (nlattr *) it.get_data();
194 wifi_scan_result *result = results + i;
195
196 for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) {
197 int type = it2.get_type();
198 if (type == GSCAN_ATTRIBUTE_SSID) {
199 strncpy(result->ssid, (char *) it2.get_data(), it2.get_len());
200 result->ssid[it2.get_len()] = 0;
201 } else if (type == GSCAN_ATTRIBUTE_BSSID) {
202 memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr));
203 } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) {
204 result->ts = it2.get_u64();
205 } else if (type == GSCAN_ATTRIBUTE_CHANNEL) {
206 result->ts = it2.get_u16();
207 } else if (type == GSCAN_ATTRIBUTE_RSSI) {
208 result->rssi = it2.get_u8();
209 } else if (type == GSCAN_ATTRIBUTE_RTT) {
210 result->rtt = it2.get_u64();
211 } else if (type == GSCAN_ATTRIBUTE_RTTSD) {
212 result->rtt_sd = it2.get_u64();
213 }
214 }
215
216 }
217
218 if (i >= num) {
219 ALOGE("Got too many results; skipping some");
220 }
221
222 return i;
223 }
224
225 int createFeatureRequest(WifiRequest& request, int subcmd) {
226
227 int result = request.create(GOOGLE_OUI, subcmd);
228 if (result < 0) {
229 return result;
230 }
231
232 return WIFI_SUCCESS;
233 }
234
235 class ScanCommand : public WifiCommand
236 {
237 wifi_scan_cmd_params *mParams;
238 wifi_scan_result_handler mHandler;
239 static unsigned mGlobalFullScanBuckets;
240 bool mLocalFullScanBuckets;
241 public:
242 ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params,
243 wifi_scan_result_handler handler)
244 : WifiCommand(iface, id), mParams(params), mHandler(handler),
245 mLocalFullScanBuckets(0)
246 { }
247
248 int createSetupRequest(WifiRequest& request) {
249 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN);
250 if (result < 0) {
251 return result;
252 }
253
254 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
255 result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period);
256 if (result < 0) {
257 return result;
258 }
259
260 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan);
261 if (result < 0) {
262 return result;
263 }
264
265 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD, mParams->report_threshold_percent);
266 if (result < 0) {
267 return result;
268 }
269
270 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS, mParams->report_threshold_num_scans);
271 if (result < 0) {
272 return result;
273 }
274
275 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets);
276 if (result < 0) {
277 return result;
278 }
279
280 for (int i = 0; i < mParams->num_buckets; i++) {
281 nlattr * bucket = request.attr_start(i); // next bucket
282 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket);
283 if (result < 0) {
284 return result;
285 }
286 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period);
287 if (result < 0) {
288 return result;
289 }
290 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND,
291 mParams->buckets[i].band);
292 if (result < 0) {
293 return result;
294 }
295
296 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS,
297 mParams->buckets[i].report_events);
298 if (result < 0) {
299 return result;
300 }
301
302 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
303 mParams->buckets[i].num_channels);
304 if (result < 0) {
305 return result;
306 }
307
308 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_EXPONENT,
309 mParams->buckets[i].base);
310 if (result < 0) {
311 return result;
312 }
313
314 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
315 mParams->buckets[i].max_period);
316 if (result < 0) {
317 return result;
318 }
319
320 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT,
321 mParams->buckets[i].step_count);
322 if (result < 0) {
323 return result;
324 }
325
326 if (mParams->buckets[i].num_channels) {
327 nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS);
328 for (int j = 0; j < mParams->buckets[i].num_channels; j++) {
329 result = request.put_u32(j, mParams->buckets[i].channels[j].channel);
330 if (result < 0) {
331 return result;
332 }
333 }
334 request.attr_end(channels);
335 }
336
337 request.attr_end(bucket);
338 }
339
340 request.attr_end(data);
341 return WIFI_SUCCESS;
342 }
343
344 int createStartRequest(WifiRequest& request) {
345 return createFeatureRequest(request, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN);
346 }
347
348 int createStopRequest(WifiRequest& request) {
349 return createFeatureRequest(request, SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN);
350 }
351
352 int start() {
353 ALOGD("starting Gscan");
354 WifiRequest request(familyId(), ifaceId());
355 int result = createSetupRequest(request);
356 if (result != WIFI_SUCCESS) {
357 ALOGE("failed to create setup request; result = %d", result);
358 return result;
359 }
360
361 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
362 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
363
364 int nBuckets = 0;
365 for (int i = 0; i < mParams->num_buckets; i++) {
366 if (mParams->buckets[i].report_events == 2) {
367 nBuckets++;
368 }
369 }
370
371 if (nBuckets != 0) {
372 ALOGI("Full scan requested with nBuckets = %d", nBuckets);
373 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
374 }
375 result = requestResponse(request);
376 if (result != WIFI_SUCCESS) {
377 ALOGE("failed to start scan; result = %d", result);
378 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
379 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
380 return result;
381 }
382
383
384 return result;
385 }
386
387 virtual int cancel() {
388 ALOGD("Stopping Gscan");
389
390 WifiRequest request(familyId(), ifaceId());
391 int result = createStopRequest(request);
392 if (result != WIFI_SUCCESS) {
393 ALOGE("failed to create stop request; result = %d", result);
394 } else {
395 result = requestResponse(request);
396 if (result != WIFI_SUCCESS) {
397 ALOGE("failed to stop scan; result = %d", result);
398 }
399 }
400
401 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
402 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
403 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
404
405 return WIFI_SUCCESS;
406 }
407
408 virtual int handleResponse(WifiEvent& reply) {
409 /* Nothing to do on response! */
410 return NL_SKIP;
411 }
412
413 virtual int handleEvent(WifiEvent& event) {
414 //event.log();
415
416 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
417 unsigned int len = event.get_vendor_data_len();
418 int event_id = event.get_vendor_subcmd();
419
420 if(event_id == GSCAN_EVENT_COMPLETE_SCAN) {
421 if (vendor_data == NULL || len != 4) {
422 ALOGE("Scan complete type not mentioned!");
423 return NL_SKIP;
424 }
425 wifi_scan_event evt_type;
426
427 evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA);
428 if(*mHandler.on_scan_event)
429 (*mHandler.on_scan_event)(evt_type, evt_type);
430 } else if(event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) {
431 uint32_t bucket_scanned = 0;
432 wifi_scan_result *scan_result = NULL;
433 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
434 if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_BUCKET_BIT) {
435 bucket_scanned = it.get_u32();
436 } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) {
437 if (it.get_len() >= (int)sizeof(*scan_result))
438 scan_result = (wifi_scan_result *)it.get_data();
439 }
440 }
441 if (scan_result) {
442 if(*mHandler.on_full_scan_result)
443 (*mHandler.on_full_scan_result)(id(), scan_result, bucket_scanned);
444 /*
445 ALOGD("%-32s\t", scan_result->ssid);
446 ALOGD("%02x:%02x:%02x:%02x:%02x:%02x ", scan_result->bssid[0], scan_result->bssid[1],
447 scan_result->bssid[2], scan_result->bssid[3], scan_result->bssid[4], scan_result->bssid[5]);
448 ALOGD("%d\t", scan_result->rssi);
449 ALOGD("%d\t", scan_result->channel);
450 ALOGD("%lld\t", scan_result->ts);
451 ALOGD("%lld\t", scan_result->rtt);
452 ALOGD("%lld\n", scan_result->rtt_sd);
453 */
454 }
455 }
456 return NL_SKIP;
457 }
458 };
459
460 unsigned ScanCommand::mGlobalFullScanBuckets = 0;
461
462 wifi_error wifi_start_gscan(
463 wifi_request_id id,
464 wifi_interface_handle iface,
465 wifi_scan_cmd_params params,
466 wifi_scan_result_handler handler)
467 {
468 wifi_handle handle = getWifiHandle(iface);
469
470 ScanCommand *cmd = new ScanCommand(iface, id, &params, handler);
471 wifi_register_cmd(handle, id, cmd);
472 return (wifi_error)cmd->start();
473 }
474
475 wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
476 {
477 wifi_handle handle = getWifiHandle(iface);
478
479 if(id == -1) {
480 wifi_scan_result_handler handler;
481 wifi_scan_cmd_params dummy_params;
482 wifi_handle handle = getWifiHandle(iface);
483 memset(&handler, 0, sizeof(handler));
484
485 ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
486 cmd->cancel();
487 cmd->releaseRef();
488 return WIFI_SUCCESS;
489 }
490
491
492 WifiCommand *cmd = wifi_unregister_cmd(handle, id);
493 if (cmd) {
494 cmd->cancel();
495 cmd->releaseRef();
496 return WIFI_SUCCESS;
497 }
498
499 return WIFI_ERROR_INVALID_ARGS;
500 }
501
502 class GetScanResultsCommand : public WifiCommand {
503 wifi_cached_scan_results *mScans;
504 int mMax;
505 int *mNum;
506 int mRetrieved;
507 byte mFlush;
508 int mCompleted;
509 static const int MAX_RESULTS = 320;
510 wifi_scan_result mScanResults[MAX_RESULTS];
511 int mNextScanResult;
512 public:
513 GetScanResultsCommand(wifi_interface_handle iface, byte flush,
514 wifi_cached_scan_results *results, int max, int *num)
515 : WifiCommand(iface, -1), mScans(results), mMax(max), mNum(num),
516 mRetrieved(0), mFlush(flush), mCompleted(0)
517 {
518 memset(mScanResults,0,sizeof(mScanResults));
519 mNextScanResult = 0;
520 }
521
522 int createRequest(WifiRequest& request, int num, byte flush) {
523 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS);
524 if (result < 0) {
525 return result;
526 }
527
528 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
529 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num);
530 if (result < 0) {
531 return result;
532 }
533
534 request.attr_end(data);
535 return WIFI_SUCCESS;
536 }
537
538 int execute() {
539 WifiRequest request(familyId(), ifaceId());
540
541 for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
542 int result = createRequest(request, (mMax - mRetrieved), mFlush);
543 if (result < 0) {
544 ALOGE("failed to create request");
545 return result;
546 }
547
548 int prev_retrieved = mRetrieved;
549
550 result = requestResponse(request);
551
552 if (result != WIFI_SUCCESS) {
553 ALOGE("failed to retrieve scan results; result = %d", result);
554 return result;
555 }
556
557 if (mRetrieved == prev_retrieved || mCompleted) {
558 /* no more items left to retrieve */
559 break;
560 }
561
562 request.destroy();
563 }
564
565 ALOGE("GetScanResults read %d results", mRetrieved);
566 *mNum = mRetrieved;
567 return WIFI_SUCCESS;
568 }
569
570 virtual int handleResponse(WifiEvent& reply) {
571
572 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
573 ALOGE("Ignoring reply with cmd = %d", reply.get_cmd());
574 return NL_SKIP;
575 }
576
577 int id = reply.get_vendor_id();
578 int subcmd = reply.get_vendor_subcmd();
579
580 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
581 int len = reply.get_vendor_data_len();
582
583 if (vendor_data == NULL || len == 0) {
584 ALOGE("no vendor data in GetScanResults response; ignoring it");
585 return NL_SKIP;
586 }
587
588 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
589 if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) {
590 mCompleted = it.get_u8();
591 //ALOGD("retrieved mCompleted flag : %d", mCompleted);
592 } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) {
593 int scan_id = 0, flags = 0, num = 0;
594 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
595 if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) {
596 scan_id = it2.get_u32();
597 //ALOGD("retrieved scan_id : 0x%0x", scan_id);
598 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) {
599 flags = it2.get_u8();
600 //ALOGD("retrieved scan_flags : 0x%0x", flags);
601 } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) {
602 num = it2.get_u32();
603 //ALOGD("retrieved num_results: %d", num);
604 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) {
605 if (mRetrieved >= mMax) {
606 ALOGW("Stored %d scans, ignoring excess results", mRetrieved);
607 break;
608 }
609 num = it2.get_len() / sizeof(wifi_scan_result);
610 num = min(MAX_RESULTS - mNextScanResult, num);
611 num = min((int)MAX_AP_CACHE_PER_SCAN, num);
612 memcpy(mScanResults + mNextScanResult, it2.get_data(),
613 sizeof(wifi_scan_result) * num);
614 wifi_scan_result *results = (wifi_scan_result *)it2.get_data();
615 /*
616 for (int i = 0; i < num; i++) {
617 wifi_scan_result *result = results + i;
618 ALOGD("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i,
619 result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
620 result->bssid[3], result->bssid[4], result->bssid[5],
621 result->rssi);
622 }*/
623 mScans[mRetrieved].scan_id = scan_id;
624 mScans[mRetrieved].flags = flags;
625 mScans[mRetrieved].num_results = num;
626 //ALOGD("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
627 memcpy(mScans[mRetrieved].results,
628 &(mScanResults[mNextScanResult]), num * sizeof(wifi_scan_result));
629 mNextScanResult += num;
630 mRetrieved++;
631 } else {
632 ALOGW("Ignoring invalid attribute type = %d, size = %d",
633 it.get_type(), it.get_len());
634 }
635 }
636 } else {
637 ALOGW("Ignoring invalid attribute type = %d, size = %d",
638 it.get_type(), it.get_len());
639 }
640 }
641
642 return NL_OK;
643 }
644 };
645
646 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
647 int max, wifi_cached_scan_results *results, int *num) {
648 GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
649 return (wifi_error)cmd->execute();
650 }
651
652 /////////////////////////////////////////////////////////////////////////////
653
654 class BssidHotlistCommand : public WifiCommand
655 {
656 private:
657 wifi_bssid_hotlist_params mParams;
658 wifi_hotlist_ap_found_handler mHandler;
659 static const int MAX_RESULTS = 64;
660 wifi_scan_result mResults[MAX_RESULTS];
661 public:
662 BssidHotlistCommand(wifi_interface_handle handle, int id,
663 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
664 : WifiCommand(handle, id), mParams(params), mHandler(handler)
665 {
666 memset(mResults, 0, sizeof(mResults));
667 }
668
669 int createSetupRequest(WifiRequest& request) {
670 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST);
671 if (result < 0) {
672 return result;
673 }
674
675 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
676
677 result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
678 if (result < 0) {
679 return result;
680 }
681
682 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
683 for (int i = 0; i < mParams.num_bssid; i++) {
684 nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM);
685 if (attr2 == NULL) {
686 return WIFI_ERROR_OUT_OF_MEMORY;
687 }
688 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
689 if (result < 0) {
690 return result;
691 }
692 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
693 if (result < 0) {
694 return result;
695 }
696 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
697 if (result < 0) {
698 return result;
699 }
700 request.attr_end(attr2);
701 }
702
703 request.attr_end(attr);
704 request.attr_end(data);
705 return result;
706 }
707
708 int createTeardownRequest(WifiRequest& request) {
709 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST);
710 if (result < 0) {
711 return result;
712 }
713
714 return result;
715 }
716
717 int start() {
718 WifiRequest request(familyId(), ifaceId());
719 int result = createSetupRequest(request);
720 if (result < 0) {
721 return result;
722 }
723
724 result = requestResponse(request);
725 if (result < 0) {
726 ALOGE("Failed to execute hotlist setup request, result = %d", result);
727 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
728 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
729 return result;
730 }
731
732 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
733 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
734
735 return result;
736 }
737
738 virtual int cancel() {
739 /* unregister event handler */
740 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
741 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
742 /* create set hotlist message with empty hotlist */
743 WifiRequest request(familyId(), ifaceId());
744 int result = createTeardownRequest(request);
745 if (result < 0) {
746 return result;
747 }
748
749 result = requestResponse(request);
750 if (result < 0) {
751 return result;
752 }
753
754 return result;
755 }
756
757 virtual int handleResponse(WifiEvent& reply) {
758 /* Nothing to do on response! */
759 return NL_SKIP;
760 }
761
762 virtual int handleEvent(WifiEvent& event) {
763 int event_id = event.get_vendor_subcmd();
764 //event.log();
765
766 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
767 int len = event.get_vendor_data_len();
768
769 if (vendor_data == NULL || len == 0) {
770 ALOGE("No scan results found");
771 return NL_SKIP;
772 }
773
774
775 int num = len / sizeof(wifi_scan_result);
776 num = min(MAX_RESULTS, num);
777 memcpy(mResults, event.get_vendor_data(), num * sizeof(wifi_scan_result));
778
779 if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) {
780 ALOGD("FOUND %d hotlist APs", num);
781 if (*mHandler.on_hotlist_ap_found)
782 (*mHandler.on_hotlist_ap_found)(id(), num, mResults);
783 } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) {
784 ALOGD("LOST %d hotlist APs", num);
785 if (*mHandler.on_hotlist_ap_lost)
786 (*mHandler.on_hotlist_ap_lost)(id(), num, mResults);
787 }
788 return NL_SKIP;
789 }
790 };
791
792 wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
793 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
794 {
795 wifi_handle handle = getWifiHandle(iface);
796
797 BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
798 wifi_register_cmd(handle, id, cmd);
799 return (wifi_error)cmd->start();
800 }
801
802 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
803 {
804 wifi_handle handle = getWifiHandle(iface);
805
806 WifiCommand *cmd = wifi_unregister_cmd(handle, id);
807 if (cmd) {
808 cmd->cancel();
809 cmd->releaseRef();
810 return WIFI_SUCCESS;
811 }
812
813 return WIFI_ERROR_INVALID_ARGS;
814 }
815
816
817 /////////////////////////////////////////////////////////////////////////////
818
819 class SignificantWifiChangeCommand : public WifiCommand
820 {
821 typedef struct {
822 mac_addr bssid; // BSSID
823 wifi_channel channel; // channel frequency in MHz
824 int num_rssi; // number of rssi samples
825 wifi_rssi rssi[8]; // RSSI history in db
826 } wifi_significant_change_result_internal;
827
828 private:
829 wifi_significant_change_params mParams;
830 wifi_significant_change_handler mHandler;
831 static const int MAX_RESULTS = 64;
832 wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS];
833 wifi_significant_change_result *mResults[MAX_RESULTS];
834 public:
835 SignificantWifiChangeCommand(wifi_interface_handle handle, int id,
836 wifi_significant_change_params params, wifi_significant_change_handler handler)
837 : WifiCommand(handle, id), mParams(params), mHandler(handler)
838 {
839 memset(mResultsBuffer,0,sizeof(mResultsBuffer));
840 memset(mResults,0,sizeof(mResults));
841 }
842
843 int createSetupRequest(WifiRequest& request) {
844 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE);
845 if (result < 0) {
846 return result;
847 }
848
849 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
850
851 result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size);
852 if (result < 0) {
853 return result;
854 }
855 result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
856 if (result < 0) {
857 return result;
858 }
859 result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching);
860 if (result < 0) {
861 return result;
862 }
863
864 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS);
865
866 for (int i = 0; i < mParams.num_bssid; i++) {
867
868 nlattr *attr2 = request.attr_start(i);
869 if (attr2 == NULL) {
870 return WIFI_ERROR_OUT_OF_MEMORY;
871 }
872 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
873 if (result < 0) {
874 return result;
875 }
876 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
877 if (result < 0) {
878 return result;
879 }
880 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
881 if (result < 0) {
882 return result;
883 }
884 request.attr_end(attr2);
885 }
886
887 request.attr_end(attr);
888 request.attr_end(data);
889
890 return result;
891 }
892
893 int createTeardownRequest(WifiRequest& request) {
894 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE);
895 if (result < 0) {
896 return result;
897 }
898
899 return result;
900 }
901
902 int start() {
903 WifiRequest request(familyId(), ifaceId());
904
905 int result = createSetupRequest(request);
906 if (result < 0) {
907 return result;
908 }
909
910 result = requestResponse(request);
911 if (result < 0) {
912 ALOGE("failed to set significant wifi change %d", result);
913 return result;
914 }
915 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
916
917 return result;
918 }
919
920 virtual int cancel() {
921 /* unregister event handler */
922 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
923
924 /* create set significant change monitor message with empty hotlist */
925 WifiRequest request(familyId(), ifaceId());
926
927 int result = createTeardownRequest(request);
928 if (result < 0) {
929 return result;
930 }
931
932 result = requestResponse(request);
933 if (result < 0) {
934 return result;
935 }
936
937 return result;
938 }
939
940 virtual int handleResponse(WifiEvent& reply) {
941 /* Nothing to do on response! */
942 return NL_SKIP;
943 }
944
945 virtual int handleEvent(WifiEvent& event) {
946 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
947 int len = event.get_vendor_data_len();
948
949 if (vendor_data == NULL || len == 0) {
950 ALOGE("No scan results found");
951 return NL_SKIP;
952 }
953
954 typedef struct {
955 uint16_t channel;
956 mac_addr bssid;
957 int16_t rssi_history[8];
958 } ChangeInfo;
959
960 int num = min(len / sizeof(ChangeInfo), MAX_RESULTS);
961 ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data();
962
963 for (int i = 0; i < num; i++) {
964 memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr));
965 mResultsBuffer[i].channel = ci[i].channel;
966 /* Driver sends N samples and the rest 8-N are filled 0x7FFF
967 * N = no of rssi samples to average sent in significant change request. */
968 int num_rssi = 0;
969 for (int j = 0; j < 8; j++) {
970 if (ci[i].rssi_history[j] == 0x7FFF) {
971 num_rssi = j;
972 break;
973 }
974 mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j];
975 }
976 mResultsBuffer[i].num_rssi = num_rssi;
977 mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
978 }
979
980 if (num != 0) {
981 (*mHandler.on_significant_change)(id(), num, mResults);
982 } else {
983 ALOGW("No significant change reported");
984 }
985
986 return NL_SKIP;
987 }
988 };
989
990 wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface,
991 wifi_significant_change_params params, wifi_significant_change_handler handler)
992 {
993 wifi_handle handle = getWifiHandle(iface);
994
995 SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
996 iface, id, params, handler);
997 wifi_register_cmd(handle, id, cmd);
998 return (wifi_error)cmd->start();
999 }
1000
1001 wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
1002 {
1003 wifi_handle handle = getWifiHandle(iface);
1004
1005 WifiCommand *cmd = wifi_unregister_cmd(handle, id);
1006 if (cmd) {
1007 cmd->cancel();
1008 cmd->releaseRef();
1009 return WIFI_SUCCESS;
1010 }
1011
1012 return WIFI_ERROR_INVALID_ARGS;
1013 }
1014
1015 class ePNOCommand : public WifiCommand
1016 {
1017 private:
1018 wifi_epno_params *epno_params;
1019 wifi_epno_handler mHandler;
1020 wifi_scan_result mResults;
1021 public:
1022 ePNOCommand(wifi_interface_handle handle, int id,
1023 wifi_epno_params *params, wifi_epno_handler handler)
1024 : WifiCommand(handle, id), mHandler(handler)
1025 {
1026 epno_params = params;
1027 memset(&mResults,0,sizeof(wifi_scan_result));
1028 }
1029
1030 int createSetupRequest(WifiRequest& request) {
1031 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_EPNO_LIST);
1032 if (result < 0) {
1033 return result;
1034 }
1035
1036 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1037 if (epno_params == NULL) {
1038 result = request.put_u8(EPNO_ATTRIBUTE_SSID_NUM, 0);
1039 if (result < 0) {
1040 return result;
1041 }
1042 request.attr_end(data);
1043 return result;
1044 }
1045 result = request.put_u16(EPNO_ATTRIBUTE_MINIMUM_5G_RSSI, epno_params->min5GHz_rssi);
1046 if (result < 0) {
1047 return result;
1048 }
1049 result = request.put_u16(EPNO_ATTRIBUTE_MINIMUM_2G_RSSI, epno_params->min24GHz_rssi);
1050 if (result < 0) {
1051 return result;
1052 }
1053 result = request.put_u16(EPNO_ATTRIBUTE_INITIAL_SCORE_MAX, epno_params->initial_score_max);
1054 if (result < 0) {
1055 return result;
1056 }
1057 result = request.put_u8(EPNO_ATTRIBUTE_CUR_CONN_BONUS, epno_params->current_connection_bonus);
1058 if (result < 0) {
1059 return result;
1060 }
1061 result = request.put_u8(EPNO_ATTRIBUTE_SAME_NETWORK_BONUS, epno_params->same_network_bonus);
1062 if (result < 0) {
1063 return result;
1064 }
1065 result = request.put_u8(EPNO_ATTRIBUTE_SECURE_BONUS, epno_params->secure_bonus);
1066 if (result < 0) {
1067 return result;
1068 }
1069 result = request.put_u8(EPNO_ATTRIBUTE_5G_BONUS, epno_params->band5GHz_bonus);
1070 if (result < 0) {
1071 return result;
1072 }
1073 result = request.put_u8(EPNO_ATTRIBUTE_SSID_NUM, epno_params->num_networks);
1074 if (result < 0) {
1075 return result;
1076 }
1077
1078 ALOGI("ePNO [min5GHz_rssi:%d min24GHz_rssi:%d initial_score_max:%d current_connection_bonus:%d same_network_bonus:%d secure_bonus:%d band5GHz_bonus:%d num_networks:%d]",
1079 epno_params->min5GHz_rssi,
1080 epno_params->min24GHz_rssi,
1081 epno_params->initial_score_max,
1082 epno_params->current_connection_bonus,
1083 epno_params->same_network_bonus,
1084 epno_params->secure_bonus,
1085 epno_params->band5GHz_bonus,
1086 epno_params->num_networks);
1087
1088 struct nlattr * attr = request.attr_start(EPNO_ATTRIBUTE_SSID_LIST);
1089 for (int i = 0; i < epno_params->num_networks; i++) {
1090 nlattr *attr2 = request.attr_start(i);
1091 if (attr2 == NULL) {
1092 return WIFI_ERROR_OUT_OF_MEMORY;
1093 }
1094 result = request.put_u16(EPNO_ATTRIBUTE_FLAGS, epno_params->networks[i].flags);
1095 if (result < 0) {
1096 return result;
1097 }
1098 result = request.put_u8(EPNO_ATTRIBUTE_AUTH, epno_params->networks[i].auth_bit_field);
1099 if (result < 0) {
1100 return result;
1101 }
1102 result = request.put_u8(EPNO_ATTRIBUTE_SSID_LEN, strlen(epno_params->networks[i].ssid));
1103 if (result < 0) {
1104 return result;
1105 }
1106 result = request.put(EPNO_ATTRIBUTE_SSID, epno_params->networks[i].ssid, strlen(epno_params->networks[i].ssid));
1107 if (result < 0) {
1108 return result;
1109 }
1110 request.attr_end(attr2);
1111 }
1112
1113 request.attr_end(attr);
1114 request.attr_end(data);
1115 return result;
1116 }
1117
1118 int start() {
1119 ALOGI("ePNO num_network=%d", epno_params ? epno_params->num_networks : 0);
1120 WifiRequest request(familyId(), ifaceId());
1121 int result = createSetupRequest(request);
1122 if (result < 0) {
1123 return result;
1124 }
1125
1126 result = requestResponse(request);
1127 if (result < 0) {
1128 ALOGI("Failed: ePNO setup request, result = %d", result);
1129 unregisterVendorHandler(GOOGLE_OUI, WIFI_EPNO_EVENT);
1130 return result;
1131 }
1132
1133 if (epno_params) {
1134 registerVendorHandler(GOOGLE_OUI, WIFI_EPNO_EVENT);
1135 }
1136 return result;
1137 }
1138
1139 virtual int cancel() {
1140 /* unregister event handler */
1141 unregisterVendorHandler(GOOGLE_OUI, WIFI_EPNO_EVENT);
1142 return 0;
1143 }
1144
1145 virtual int handleResponse(WifiEvent& reply) {
1146 /* Nothing to do on response! */
1147 return NL_SKIP;
1148 }
1149
1150 virtual int handleEvent(WifiEvent& event) {
1151 int event_id = event.get_vendor_subcmd();
1152 // event.log();
1153
1154 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1155 int len = event.get_vendor_data_len();
1156
1157 if (vendor_data == NULL || len == 0) {
1158 ALOGI("No scan results found");
1159 return NL_SKIP;
1160 }
1161
1162
1163 mResults = *(wifi_scan_result *) event.get_vendor_data();
1164 if (*mHandler.on_network_found)
1165 (*mHandler.on_network_found)(id(), 1, &mResults);
1166 return NL_SKIP;
1167 }
1168 };
1169
1170 wifi_error wifi_set_epno_list(wifi_request_id id,
1171 wifi_interface_handle iface,
1172 const wifi_epno_params *epno_params,
1173 wifi_epno_handler handler)
1174 {
1175 wifi_handle handle = getWifiHandle(iface);
1176 ePNOCommand *cmd = new ePNOCommand(iface, id, (wifi_epno_params *)epno_params, handler);
1177 wifi_register_cmd(handle, id, cmd);
1178 wifi_error result = (wifi_error)cmd->start();
1179 if (result != WIFI_SUCCESS) {
1180 wifi_unregister_cmd(handle, id);
1181 }
1182 return result;
1183 }
1184
1185 wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface)
1186 {
1187 wifi_handle handle = getWifiHandle(iface);
1188 wifi_epno_handler handler;
1189
1190 handler.on_network_found = NULL;
1191 ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler);
1192 wifi_register_cmd(handle, id, cmd);
1193 wifi_error result = (wifi_error)cmd->start();
1194 if (result != WIFI_SUCCESS) {
1195 wifi_unregister_cmd(handle, id);
1196 }
1197 return result;
1198 }
1199
1200 class HsListCommand : public WifiCommand
1201 {
1202 int num_hs;
1203 wifi_passpoint_network *mNetworks;
1204 wifi_passpoint_event_handler mHandler;
1205 public:
1206 HsListCommand(wifi_request_id id, wifi_interface_handle iface,
1207 int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler)
1208 : WifiCommand(iface, id), num_hs(num), mNetworks(hs_list),
1209 mHandler(handler)
1210 {
1211 }
1212
1213 HsListCommand(wifi_request_id id, wifi_interface_handle iface,
1214 int num)
1215 : WifiCommand(iface, id), num_hs(num), mNetworks(NULL)
1216 {
1217 mHandler.on_passpoint_network_found = NULL;
1218 }
1219
1220 int createRequest(WifiRequest& request, int val) {
1221 int result;
1222
1223 if (val) {
1224 result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_HS_LIST);
1225 result = request.put_u32(EPNO_ATTRIBUTE_HS_NUM, num_hs);
1226 if (result < 0) {
1227 return result;
1228 }
1229 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1230
1231 struct nlattr * attr = request.attr_start(EPNO_ATTRIBUTE_HS_PARAM_LIST);
1232 for (int i = 0; i < num_hs; i++) {
1233 nlattr *attr2 = request.attr_start(i);
1234 if (attr2 == NULL) {
1235 return WIFI_ERROR_OUT_OF_MEMORY;
1236 }
1237 result = request.put_u32(EPNO_ATTRIBUTE_HS_ID, mNetworks[i].id);
1238 if (result < 0) {
1239 return result;
1240 }
1241 result = request.put(EPNO_ATTRIBUTE_HS_REALM, mNetworks[i].realm, 256);
1242 if (result < 0) {
1243 return result;
1244 }
1245 result = request.put(EPNO_ATTRIBUTE_HS_CONSORTIUM_IDS, mNetworks[i].roamingConsortiumIds, 128);
1246 if (result < 0) {
1247 return result;
1248 }
1249 result = request.put(EPNO_ATTRIBUTE_HS_PLMN, mNetworks[i].plmn, 3);
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 }else {
1258 result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_HS_LIST);
1259 if (result < 0) {
1260 return result;
1261 }
1262 }
1263
1264 return WIFI_SUCCESS;
1265 }
1266
1267 int start() {
1268
1269 WifiRequest request(familyId(), ifaceId());
1270 int result = createRequest(request, num_hs);
1271 if (result != WIFI_SUCCESS) {
1272 ALOGE("failed to create request; result = %d", result);
1273 return result;
1274 }
1275
1276 registerVendorHandler(GOOGLE_OUI, WIFI_HOTSPOT_MATCH);
1277
1278 result = requestResponse(request);
1279 if (result != WIFI_SUCCESS) {
1280 ALOGE("failed to set ANQPO networks; result = %d", result);
1281 unregisterVendorHandler(GOOGLE_OUI, WIFI_HOTSPOT_MATCH);
1282 return result;
1283 }
1284
1285 return result;
1286 }
1287
1288 virtual int cancel() {
1289
1290 WifiRequest request(familyId(), ifaceId());
1291 int result = createRequest(request, 0);
1292 if (result != WIFI_SUCCESS) {
1293 ALOGE("failed to create request; result = %d", result);
1294 } else {
1295 result = requestResponse(request);
1296 if (result != WIFI_SUCCESS) {
1297 ALOGE("failed to reset ANQPO networks;result = %d", result);
1298 }
1299 }
1300
1301 unregisterVendorHandler(GOOGLE_OUI, WIFI_HOTSPOT_MATCH);
1302 return WIFI_SUCCESS;
1303 }
1304
1305 virtual int handleResponse(WifiEvent& reply) {
1306 /* Nothing to do on response! */
1307 return NL_SKIP;
1308 }
1309
1310 virtual int handleEvent(WifiEvent& event) {
1311 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1312 unsigned int len = event.get_vendor_data_len();
1313 if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
1314 ALOGE("ERROR: No scan results found");
1315 return NL_SKIP;
1316 }
1317
1318 wifi_scan_result *result = (wifi_scan_result *)event.get_vendor_data();
1319 byte *anqp = (byte *)result + offsetof(wifi_scan_result, ie_data) + result->ie_length;
1320 int networkId = *(int *)anqp;
1321 anqp += sizeof(int);
1322 int anqp_len = *(u16 *)anqp;
1323 anqp += sizeof(u16);
1324
1325 if(*mHandler.on_passpoint_network_found)
1326 (*mHandler.on_passpoint_network_found)(id(), networkId, result, anqp_len, anqp);
1327
1328 return NL_SKIP;
1329 }
1330 };
1331
1332 wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num,
1333 wifi_passpoint_network *networks, wifi_passpoint_event_handler handler)
1334 {
1335 wifi_handle handle = getWifiHandle(iface);
1336 HsListCommand *cmd = new HsListCommand(id, iface, num, networks, handler);
1337
1338 wifi_register_cmd(handle, id, cmd);
1339 wifi_error result = (wifi_error)cmd->start();
1340 if (result != WIFI_SUCCESS) {
1341 wifi_unregister_cmd(handle, id);
1342 }
1343 return result;
1344 }
1345
1346 wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
1347 {
1348 wifi_handle handle = getWifiHandle(iface);
1349 wifi_error result;
1350 HsListCommand *cmd = (HsListCommand *)(wifi_get_cmd(handle, id));
1351
1352 if (cmd == NULL) {
1353 cmd = new HsListCommand(id, iface, 0);
1354 wifi_register_cmd(handle, id, cmd);
1355 }
1356 result = (wifi_error)cmd->cancel();
1357 wifi_unregister_cmd(handle, id);
1358 return result;
1359 }