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