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