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