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