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