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