[9610][7872][7570][7885] wlbt: Reduce gscan logGing
[GitHub/MotorolaMobilityLLC/hardware-samsung_slsi-scsc_wifibt-wifi_hal.git] / gscan.cpp
1
2 #include <stdint.h>
3 #include <stddef.h>
4 #include <fcntl.h>
5 #include <sys/socket.h>
6 #include <netlink/genl/genl.h>
7 #include <netlink/genl/family.h>
8 #include <netlink/genl/ctrl.h>
9 #include <linux/rtnetlink.h>
10 #include <netpacket/packet.h>
11 #include <linux/filter.h>
12 #include <linux/errqueue.h>
13
14 #include <linux/pkt_sched.h>
15 #include <netlink/object-api.h>
16 #include <netlink/netlink.h>
17 #include <netlink/socket.h>
18 #include <netlink/handlers.h>
19
20 #include "sync.h"
21
22 #define LOG_TAG "WifiHAL"
23
24 #include <utils/Log.h>
25
26 #include "wifi_hal.h"
27 #include "common.h"
28 #include "cpp_bindings.h"
29
30 typedef enum {
31
32 GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
33 GSCAN_ATTRIBUTE_BASE_PERIOD,
34 GSCAN_ATTRIBUTE_BUCKETS_BAND,
35 GSCAN_ATTRIBUTE_BUCKET_ID,
36 GSCAN_ATTRIBUTE_BUCKET_PERIOD,
37 GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
38 GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
39 GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
40 GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
41 GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
42 GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS,
43 GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
44
45 GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
46 GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */
47 GSCAN_ATTRIBUTE_REPORT_EVENTS,
48
49 /* remaining reserved for additional attributes */
50 GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
51 GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */
52 GSCAN_ATTRIBUTE_NUM_CHANNELS,
53 GSCAN_ATTRIBUTE_CHANNEL_LIST,
54 GSCAN_ATTRIBUTE_SCAN_ID,
55 GSCAN_ATTRIBUTE_SCAN_FLAGS,
56 GSCAN_ATTRIBUTE_SCAN_BUCKET_BIT,
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
83 GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 70,
84 GSCAN_ATTRIBUTE_BUCKET_EXPONENT,
85 GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
86
87 GSCAN_ATTRIBUTE_NUM_BSSID,
88 GSCAN_ATTRIBUTE_BLACKLIST_BSSID,
89
90 GSCAN_ATTRIBUTE_MAX
91
92 } GSCAN_ATTRIBUTE;
93
94 typedef enum {
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,
102 EPNO_ATTRIBUTE_SSID_NUM,
103 EPNO_ATTRIBUTE_SSID_LIST,
104 EPNO_ATTRIBUTE_SSID,
105 EPNO_ATTRIBUTE_SSID_LEN,
106 EPNO_ATTRIBUTE_FLAGS,
107 EPNO_ATTRIBUTE_AUTH,
108 EPNO_ATTRIBUTE_MAX
109 } EPNO_ATTRIBUTE;
110
111 typedef 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
121
122 class GetCapabilitiesCommand : public WifiCommand
123 {
124 wifi_gscan_capabilities *mCapabilities;
125 public:
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() {
133 int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES);
134 if (ret < 0) {
135 ALOGE("NL message creation failed");
136 return ret;
137 }
138
139 return ret;
140 }
141
142 protected:
143 virtual int handleResponse(WifiEvent& reply) {
144
145 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
146 ALOGE("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
156 memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
157
158 return NL_OK;
159 }
160 };
161
162
163 wifi_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
170 class GetChannelListCommand : public WifiCommand
171 {
172 wifi_channel *channels;
173 int max_channels;
174 int *num_channels;
175 int band;
176 public:
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() {
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
201 protected:
202 virtual int handleResponse(WifiEvent& reply) {
203
204 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
205 ALOGE("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
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();
224 /*ALOGD("Got channel list with %d channels", num_channels_to_copy);*/
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
240 wifi_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
251 static 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();
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
291 int 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
301 class ScanCommand : public WifiCommand
302 {
303 wifi_scan_cmd_params *mParams;
304 wifi_scan_result_handler mHandler;
305 static unsigned mGlobalFullScanBuckets;
306 bool mLocalFullScanBuckets;
307 public:
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
326 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan);
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
374 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_EXPONENT,
375 mParams->buckets[i].base);
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
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() {
419 ALOGD("starting Gscan");
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 }
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
449
450 return result;
451 }
452
453 virtual int cancel() {
454 ALOGD("Stopping Gscan");
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) {
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();
485
486 if(event_id == GSCAN_EVENT_COMPLETE_SCAN) {
487 if (vendor_data == NULL || len != 4) {
488 ALOGE("Scan complete type not mentioned!");
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);
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) {
497 uint32_t bucket_scanned = 0;
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);
519 */
520 }
521 }
522 return NL_SKIP;
523 }
524 };
525
526 unsigned ScanCommand::mGlobalFullScanBuckets = 0;
527
528 wifi_error wifi_start_gscan(
529 wifi_request_id id,
530 wifi_interface_handle iface,
531 wifi_scan_cmd_params params,
532 wifi_scan_result_handler handler)
533 {
534 wifi_handle handle = getWifiHandle(iface);
535
536 ScanCommand *cmd = new ScanCommand(iface, id, &params, handler);
537 wifi_register_cmd(handle, id, cmd);
538 return (wifi_error)cmd->start();
539 }
540
541 wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
542 {
543 wifi_handle handle = getWifiHandle(iface);
544
545 if(id == -1) {
546 wifi_scan_result_handler handler;
547 wifi_scan_cmd_params dummy_params;
548 wifi_handle handle = getWifiHandle(iface);
549 memset(&handler, 0, sizeof(handler));
550
551 ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
552 cmd->cancel();
553 cmd->releaseRef();
554 return WIFI_SUCCESS;
555 }
556
557
558 WifiCommand *cmd = wifi_unregister_cmd(handle, id);
559 if (cmd) {
560 cmd->cancel();
561 cmd->releaseRef();
562 return WIFI_SUCCESS;
563 }
564
565 return WIFI_ERROR_INVALID_ARGS;
566 }
567
568 class GetScanResultsCommand : public WifiCommand {
569 wifi_cached_scan_results *mScans;
570 int mMax;
571 int *mNum;
572 int mRetrieved;
573 byte mFlush;
574 int mCompleted;
575 static const int MAX_RESULTS = 320;
576 wifi_scan_result mScanResults[MAX_RESULTS];
577 int mNextScanResult;
578 public:
579 GetScanResultsCommand(wifi_interface_handle iface, byte flush,
580 wifi_cached_scan_results *results, int max, int *num)
581 : WifiCommand(iface, -1), mScans(results), mMax(max), mNum(num),
582 mRetrieved(0), mFlush(flush), mCompleted(0)
583 {
584 memset(mScanResults,0,sizeof(mScanResults));
585 mNextScanResult = 0;
586 }
587
588 int createRequest(WifiRequest& request, int num, byte flush) {
589 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS);
590 if (result < 0) {
591 return result;
592 }
593
594 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
595 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num);
596 if (result < 0) {
597 return result;
598 }
599
600 request.attr_end(data);
601 return WIFI_SUCCESS;
602 }
603
604 int execute() {
605 WifiRequest request(familyId(), ifaceId());
606
607 for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
608 int result = createRequest(request, (mMax - mRetrieved), mFlush);
609 if (result < 0) {
610 ALOGE("failed to create request");
611 return result;
612 }
613
614 int prev_retrieved = mRetrieved;
615
616 result = requestResponse(request);
617
618 if (result != WIFI_SUCCESS) {
619 ALOGE("failed to retrieve scan results; result = %d", result);
620 return result;
621 }
622
623 if (mRetrieved == prev_retrieved || mCompleted) {
624 /* no more items left to retrieve */
625 break;
626 }
627
628 request.destroy();
629 }
630
631 ALOGE("GetScanResults read %d results", mRetrieved);
632 *mNum = mRetrieved;
633 return WIFI_SUCCESS;
634 }
635
636 virtual int handleResponse(WifiEvent& reply) {
637
638 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
639 ALOGE("Ignoring reply with cmd = %d", reply.get_cmd());
640 return NL_SKIP;
641 }
642
643 int id = reply.get_vendor_id();
644 int subcmd = reply.get_vendor_subcmd();
645
646 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
647 int len = reply.get_vendor_data_len();
648
649 if (vendor_data == NULL || len == 0) {
650 ALOGE("no vendor data in GetScanResults response; ignoring it");
651 return NL_SKIP;
652 }
653
654 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
655 if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) {
656 mCompleted = it.get_u8();
657 //ALOGD("retrieved mCompleted flag : %d", mCompleted);
658 } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) {
659 int scan_id = 0, flags = 0, num = 0;
660 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
661 if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) {
662 scan_id = it2.get_u32();
663 //ALOGD("retrieved scan_id : 0x%0x", scan_id);
664 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) {
665 flags = it2.get_u8();
666 //ALOGD("retrieved scan_flags : 0x%0x", flags);
667 } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) {
668 num = it2.get_u32();
669 //ALOGD("retrieved num_results: %d", num);
670 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) {
671 if (mRetrieved >= mMax) {
672 ALOGW("Stored %d scans, ignoring excess results", mRetrieved);
673 break;
674 }
675 num = it2.get_len() / sizeof(wifi_scan_result);
676 num = min(MAX_RESULTS - mNextScanResult, num);
677 num = min((int)MAX_AP_CACHE_PER_SCAN, num);
678 memcpy(mScanResults + mNextScanResult, it2.get_data(),
679 sizeof(wifi_scan_result) * num);
680 wifi_scan_result *results = (wifi_scan_result *)it2.get_data();
681 /*
682 for (int i = 0; i < num; i++) {
683 wifi_scan_result *result = results + i;
684 ALOGD("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i,
685 result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
686 result->bssid[3], result->bssid[4], result->bssid[5],
687 result->rssi);
688 }*/
689 mScans[mRetrieved].scan_id = scan_id;
690 mScans[mRetrieved].flags = flags;
691 mScans[mRetrieved].num_results = num;
692 //ALOGD("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
693 memcpy(mScans[mRetrieved].results,
694 &(mScanResults[mNextScanResult]), num * sizeof(wifi_scan_result));
695 mNextScanResult += num;
696 mRetrieved++;
697 } else {
698 ALOGW("Ignoring invalid attribute type = %d, size = %d",
699 it.get_type(), it.get_len());
700 }
701 }
702 } else {
703 ALOGW("Ignoring invalid attribute type = %d, size = %d",
704 it.get_type(), it.get_len());
705 }
706 }
707
708 return NL_OK;
709 }
710 };
711
712 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
713 int max, wifi_cached_scan_results *results, int *num) {
714 GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
715 return (wifi_error)cmd->execute();
716 }
717
718 /////////////////////////////////////////////////////////////////////////////
719
720 class BssidHotlistCommand : public WifiCommand
721 {
722 private:
723 wifi_bssid_hotlist_params mParams;
724 wifi_hotlist_ap_found_handler mHandler;
725 static const int MAX_RESULTS = 64;
726 wifi_scan_result mResults[MAX_RESULTS];
727 public:
728 BssidHotlistCommand(wifi_interface_handle handle, int id,
729 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
730 : WifiCommand(handle, id), mParams(params), mHandler(handler)
731 {
732 memset(mResults, 0, sizeof(mResults));
733 }
734
735 int createSetupRequest(WifiRequest& request) {
736 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST);
737 if (result < 0) {
738 return result;
739 }
740
741 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
742
743 result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
744 if (result < 0) {
745 return result;
746 }
747
748 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
749 for (int i = 0; i < mParams.num_bssid; i++) {
750 nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM);
751 if (attr2 == NULL) {
752 return WIFI_ERROR_OUT_OF_MEMORY;
753 }
754 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
755 if (result < 0) {
756 return result;
757 }
758 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
759 if (result < 0) {
760 return result;
761 }
762 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
763 if (result < 0) {
764 return result;
765 }
766 request.attr_end(attr2);
767 }
768
769 request.attr_end(attr);
770 request.attr_end(data);
771 return result;
772 }
773
774 int createTeardownRequest(WifiRequest& request) {
775 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST);
776 if (result < 0) {
777 return result;
778 }
779
780 return result;
781 }
782
783 int start() {
784 WifiRequest request(familyId(), ifaceId());
785 int result = createSetupRequest(request);
786 if (result < 0) {
787 return result;
788 }
789
790 result = requestResponse(request);
791 if (result < 0) {
792 ALOGE("Failed to execute hotlist setup request, result = %d", result);
793 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
794 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
795 return result;
796 }
797
798 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
799 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
800
801 return result;
802 }
803
804 virtual int cancel() {
805 /* unregister event handler */
806 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
807 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
808 /* create set hotlist message with empty hotlist */
809 WifiRequest request(familyId(), ifaceId());
810 int result = createTeardownRequest(request);
811 if (result < 0) {
812 return result;
813 }
814
815 result = requestResponse(request);
816 if (result < 0) {
817 return result;
818 }
819
820 return result;
821 }
822
823 virtual int handleResponse(WifiEvent& reply) {
824 /* Nothing to do on response! */
825 return NL_SKIP;
826 }
827
828 virtual int handleEvent(WifiEvent& event) {
829 int event_id = event.get_vendor_subcmd();
830 //event.log();
831
832 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
833 int len = event.get_vendor_data_len();
834
835 if (vendor_data == NULL || len == 0) {
836 ALOGE("No scan results found");
837 return NL_SKIP;
838 }
839
840
841 int num = len / sizeof(wifi_scan_result);
842 num = min(MAX_RESULTS, num);
843 memcpy(mResults, event.get_vendor_data(), num * sizeof(wifi_scan_result));
844
845 if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) {
846 ALOGD("FOUND %d hotlist APs", num);
847 if (*mHandler.on_hotlist_ap_found)
848 (*mHandler.on_hotlist_ap_found)(id(), num, mResults);
849 } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) {
850 ALOGD("LOST %d hotlist APs", num);
851 if (*mHandler.on_hotlist_ap_lost)
852 (*mHandler.on_hotlist_ap_lost)(id(), num, mResults);
853 }
854 return NL_SKIP;
855 }
856 };
857
858 wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
859 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
860 {
861 wifi_handle handle = getWifiHandle(iface);
862
863 BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
864 wifi_register_cmd(handle, id, cmd);
865 return (wifi_error)cmd->start();
866 }
867
868 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
869 {
870 wifi_handle handle = getWifiHandle(iface);
871
872 WifiCommand *cmd = wifi_unregister_cmd(handle, id);
873 if (cmd) {
874 cmd->cancel();
875 cmd->releaseRef();
876 return WIFI_SUCCESS;
877 }
878
879 return WIFI_ERROR_INVALID_ARGS;
880 }
881
882
883 /////////////////////////////////////////////////////////////////////////////
884
885 class SignificantWifiChangeCommand : public WifiCommand
886 {
887 typedef struct {
888 mac_addr bssid; // BSSID
889 wifi_channel channel; // channel frequency in MHz
890 int num_rssi; // number of rssi samples
891 wifi_rssi rssi[8]; // RSSI history in db
892 } wifi_significant_change_result_internal;
893
894 private:
895 wifi_significant_change_params mParams;
896 wifi_significant_change_handler mHandler;
897 static const int MAX_RESULTS = 64;
898 wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS];
899 wifi_significant_change_result *mResults[MAX_RESULTS];
900 public:
901 SignificantWifiChangeCommand(wifi_interface_handle handle, int id,
902 wifi_significant_change_params params, wifi_significant_change_handler handler)
903 : WifiCommand(handle, id), mParams(params), mHandler(handler)
904 {
905 memset(mResultsBuffer,0,sizeof(mResultsBuffer));
906 memset(mResults,0,sizeof(mResults));
907 }
908
909 int createSetupRequest(WifiRequest& request) {
910 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE);
911 if (result < 0) {
912 return result;
913 }
914
915 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
916
917 result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size);
918 if (result < 0) {
919 return result;
920 }
921 result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
922 if (result < 0) {
923 return result;
924 }
925 result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching);
926 if (result < 0) {
927 return result;
928 }
929
930 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS);
931
932 for (int i = 0; i < mParams.num_bssid; i++) {
933
934 nlattr *attr2 = request.attr_start(i);
935 if (attr2 == NULL) {
936 return WIFI_ERROR_OUT_OF_MEMORY;
937 }
938 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
939 if (result < 0) {
940 return result;
941 }
942 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
943 if (result < 0) {
944 return result;
945 }
946 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
947 if (result < 0) {
948 return result;
949 }
950 request.attr_end(attr2);
951 }
952
953 request.attr_end(attr);
954 request.attr_end(data);
955
956 return result;
957 }
958
959 int createTeardownRequest(WifiRequest& request) {
960 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE);
961 if (result < 0) {
962 return result;
963 }
964
965 return result;
966 }
967
968 int start() {
969 WifiRequest request(familyId(), ifaceId());
970
971 int result = createSetupRequest(request);
972 if (result < 0) {
973 return result;
974 }
975
976 result = requestResponse(request);
977 if (result < 0) {
978 ALOGE("failed to set significant wifi change %d", result);
979 return result;
980 }
981 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
982
983 return result;
984 }
985
986 virtual int cancel() {
987 /* unregister event handler */
988 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
989
990 /* create set significant change monitor message with empty hotlist */
991 WifiRequest request(familyId(), ifaceId());
992
993 int result = createTeardownRequest(request);
994 if (result < 0) {
995 return result;
996 }
997
998 result = requestResponse(request);
999 if (result < 0) {
1000 return result;
1001 }
1002
1003 return result;
1004 }
1005
1006 virtual int handleResponse(WifiEvent& reply) {
1007 /* Nothing to do on response! */
1008 return NL_SKIP;
1009 }
1010
1011 virtual int handleEvent(WifiEvent& event) {
1012 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1013 int len = event.get_vendor_data_len();
1014
1015 if (vendor_data == NULL || len == 0) {
1016 ALOGE("No scan results found");
1017 return NL_SKIP;
1018 }
1019
1020 typedef struct {
1021 uint16_t channel;
1022 mac_addr bssid;
1023 int16_t rssi_history[8];
1024 } ChangeInfo;
1025
1026 int num = min(len / sizeof(ChangeInfo), MAX_RESULTS);
1027 ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data();
1028
1029 for (int i = 0; i < num; i++) {
1030 memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr));
1031 mResultsBuffer[i].channel = ci[i].channel;
1032 /* Driver sends N samples and the rest 8-N are filled 0x7FFF
1033 * N = no of rssi samples to average sent in significant change request. */
1034 int num_rssi = 0;
1035 for (int j = 0; j < 8; j++) {
1036 if (ci[i].rssi_history[j] == 0x7FFF) {
1037 num_rssi = j;
1038 break;
1039 }
1040 mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j];
1041 }
1042 mResultsBuffer[i].num_rssi = num_rssi;
1043 mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
1044 }
1045
1046 if (num != 0) {
1047 (*mHandler.on_significant_change)(id(), num, mResults);
1048 } else {
1049 ALOGW("No significant change reported");
1050 }
1051
1052 return NL_SKIP;
1053 }
1054 };
1055
1056 wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface,
1057 wifi_significant_change_params params, wifi_significant_change_handler handler)
1058 {
1059 wifi_handle handle = getWifiHandle(iface);
1060
1061 SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
1062 iface, id, params, handler);
1063 wifi_register_cmd(handle, id, cmd);
1064 return (wifi_error)cmd->start();
1065 }
1066
1067 wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
1068 {
1069 wifi_handle handle = getWifiHandle(iface);
1070
1071 WifiCommand *cmd = wifi_unregister_cmd(handle, id);
1072 if (cmd) {
1073 cmd->cancel();
1074 cmd->releaseRef();
1075 return WIFI_SUCCESS;
1076 }
1077
1078 return WIFI_ERROR_INVALID_ARGS;
1079 }
1080
1081 class ePNOCommand : public WifiCommand
1082 {
1083 private:
1084 wifi_epno_params *epno_params;
1085 wifi_epno_handler mHandler;
1086 wifi_scan_result mResults;
1087 public:
1088 ePNOCommand(wifi_interface_handle handle, int id,
1089 wifi_epno_params *params, wifi_epno_handler handler)
1090 : WifiCommand(handle, id), mHandler(handler)
1091 {
1092 epno_params = params;
1093 memset(&mResults,0,sizeof(wifi_scan_result));
1094 }
1095
1096 int createSetupRequest(WifiRequest& request) {
1097 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_EPNO_LIST);
1098 if (result < 0) {
1099 return result;
1100 }
1101
1102 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1103 if (epno_params == NULL) {
1104 result = request.put_u8(EPNO_ATTRIBUTE_SSID_NUM, 0);
1105 if (result < 0) {
1106 return result;
1107 }
1108 request.attr_end(data);
1109 return result;
1110 }
1111 result = request.put_u16(EPNO_ATTRIBUTE_MINIMUM_5G_RSSI, epno_params->min5GHz_rssi);
1112 if (result < 0) {
1113 return result;
1114 }
1115 result = request.put_u16(EPNO_ATTRIBUTE_MINIMUM_2G_RSSI, epno_params->min24GHz_rssi);
1116 if (result < 0) {
1117 return result;
1118 }
1119 result = request.put_u16(EPNO_ATTRIBUTE_INITIAL_SCORE_MAX, epno_params->initial_score_max);
1120 if (result < 0) {
1121 return result;
1122 }
1123 result = request.put_u8(EPNO_ATTRIBUTE_CUR_CONN_BONUS, epno_params->current_connection_bonus);
1124 if (result < 0) {
1125 return result;
1126 }
1127 result = request.put_u8(EPNO_ATTRIBUTE_SAME_NETWORK_BONUS, epno_params->same_network_bonus);
1128 if (result < 0) {
1129 return result;
1130 }
1131 result = request.put_u8(EPNO_ATTRIBUTE_SECURE_BONUS, epno_params->secure_bonus);
1132 if (result < 0) {
1133 return result;
1134 }
1135 result = request.put_u8(EPNO_ATTRIBUTE_5G_BONUS, epno_params->band5GHz_bonus);
1136 if (result < 0) {
1137 return result;
1138 }
1139 result = request.put_u8(EPNO_ATTRIBUTE_SSID_NUM, epno_params->num_networks);
1140 if (result < 0) {
1141 return result;
1142 }
1143
1144 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]",
1145 epno_params->min5GHz_rssi,
1146 epno_params->min24GHz_rssi,
1147 epno_params->initial_score_max,
1148 epno_params->current_connection_bonus,
1149 epno_params->same_network_bonus,
1150 epno_params->secure_bonus,
1151 epno_params->band5GHz_bonus,
1152 epno_params->num_networks);
1153
1154 struct nlattr * attr = request.attr_start(EPNO_ATTRIBUTE_SSID_LIST);
1155 for (int i = 0; i < epno_params->num_networks; i++) {
1156 nlattr *attr2 = request.attr_start(i);
1157 if (attr2 == NULL) {
1158 return WIFI_ERROR_OUT_OF_MEMORY;
1159 }
1160 result = request.put_u16(EPNO_ATTRIBUTE_FLAGS, epno_params->networks[i].flags);
1161 if (result < 0) {
1162 return result;
1163 }
1164 result = request.put_u8(EPNO_ATTRIBUTE_AUTH, epno_params->networks[i].auth_bit_field);
1165 if (result < 0) {
1166 return result;
1167 }
1168 result = request.put_u8(EPNO_ATTRIBUTE_SSID_LEN, strlen(epno_params->networks[i].ssid));
1169 if (result < 0) {
1170 return result;
1171 }
1172 result = request.put(EPNO_ATTRIBUTE_SSID, epno_params->networks[i].ssid, strlen(epno_params->networks[i].ssid));
1173 if (result < 0) {
1174 return result;
1175 }
1176 request.attr_end(attr2);
1177 }
1178
1179 request.attr_end(attr);
1180 request.attr_end(data);
1181 return result;
1182 }
1183
1184 int start() {
1185 ALOGI("ePNO num_network=%d", epno_params ? epno_params->num_networks : 0);
1186 WifiRequest request(familyId(), ifaceId());
1187 int result = createSetupRequest(request);
1188 if (result < 0) {
1189 return result;
1190 }
1191
1192 result = requestResponse(request);
1193 if (result < 0) {
1194 ALOGI("Failed: ePNO setup request, result = %d", result);
1195 unregisterVendorHandler(GOOGLE_OUI, WIFI_EPNO_EVENT);
1196 return result;
1197 }
1198
1199 if (epno_params) {
1200 registerVendorHandler(GOOGLE_OUI, WIFI_EPNO_EVENT);
1201 }
1202 return result;
1203 }
1204
1205 virtual int cancel() {
1206 /* unregister event handler */
1207 unregisterVendorHandler(GOOGLE_OUI, WIFI_EPNO_EVENT);
1208 return 0;
1209 }
1210
1211 virtual int handleResponse(WifiEvent& reply) {
1212 /* Nothing to do on response! */
1213 return NL_SKIP;
1214 }
1215
1216 virtual int handleEvent(WifiEvent& 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
1229 mResults = *(wifi_scan_result *) event.get_vendor_data();
1230 if (*mHandler.on_network_found)
1231 (*mHandler.on_network_found)(id(), 1, &mResults);
1232 return NL_SKIP;
1233 }
1234 };
1235
1236 wifi_error wifi_set_epno_list(wifi_request_id id,
1237 wifi_interface_handle iface,
1238 const wifi_epno_params *epno_params,
1239 wifi_epno_handler handler)
1240 {
1241 wifi_handle handle = getWifiHandle(iface);
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
1251 wifi_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;
1264 }
1265
1266 class HsListCommand : public WifiCommand
1267 {
1268 int num_hs;
1269 wifi_passpoint_network *mNetworks;
1270 wifi_passpoint_event_handler mHandler;
1271 public:
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 mHandler.on_passpoint_network_found = NULL;
1284 }
1285
1286 int createRequest(WifiRequest& request, int val) {
1287 int result;
1288
1289 if (val) {
1290 result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_HS_LIST);
1291 result = request.put_u32(EPNO_ATTRIBUTE_HS_NUM, num_hs);
1292 if (result < 0) {
1293 return result;
1294 }
1295 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1296
1297 struct nlattr * attr = request.attr_start(EPNO_ATTRIBUTE_HS_PARAM_LIST);
1298 for (int i = 0; i < num_hs; i++) {
1299 nlattr *attr2 = request.attr_start(i);
1300 if (attr2 == NULL) {
1301 return WIFI_ERROR_OUT_OF_MEMORY;
1302 }
1303 result = request.put_u32(EPNO_ATTRIBUTE_HS_ID, mNetworks[i].id);
1304 if (result < 0) {
1305 return result;
1306 }
1307 result = request.put(EPNO_ATTRIBUTE_HS_REALM, mNetworks[i].realm, 256);
1308 if (result < 0) {
1309 return result;
1310 }
1311 result = request.put(EPNO_ATTRIBUTE_HS_CONSORTIUM_IDS, mNetworks[i].roamingConsortiumIds, 128);
1312 if (result < 0) {
1313 return result;
1314 }
1315 result = request.put(EPNO_ATTRIBUTE_HS_PLMN, mNetworks[i].plmn, 3);
1316 if (result < 0) {
1317 return result;
1318 }
1319 request.attr_end(attr2);
1320 }
1321 request.attr_end(attr);
1322 request.attr_end(data);
1323 }else {
1324 result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_HS_LIST);
1325 if (result < 0) {
1326 return result;
1327 }
1328 }
1329
1330 return WIFI_SUCCESS;
1331 }
1332
1333 int start() {
1334
1335 WifiRequest request(familyId(), ifaceId());
1336 int result = createRequest(request, num_hs);
1337 if (result != WIFI_SUCCESS) {
1338 ALOGE("failed to create request; result = %d", result);
1339 return result;
1340 }
1341
1342 registerVendorHandler(GOOGLE_OUI, WIFI_HOTSPOT_MATCH);
1343
1344 result = requestResponse(request);
1345 if (result != WIFI_SUCCESS) {
1346 ALOGE("failed to set ANQPO networks; result = %d", result);
1347 unregisterVendorHandler(GOOGLE_OUI, WIFI_HOTSPOT_MATCH);
1348 return result;
1349 }
1350
1351 return result;
1352 }
1353
1354 virtual int cancel() {
1355
1356 WifiRequest request(familyId(), ifaceId());
1357 int result = createRequest(request, 0);
1358 if (result != WIFI_SUCCESS) {
1359 ALOGE("failed to create request; result = %d", result);
1360 } else {
1361 result = requestResponse(request);
1362 if (result != WIFI_SUCCESS) {
1363 ALOGE("failed to reset ANQPO networks;result = %d", result);
1364 }
1365 }
1366
1367 unregisterVendorHandler(GOOGLE_OUI, WIFI_HOTSPOT_MATCH);
1368 return WIFI_SUCCESS;
1369 }
1370
1371 virtual int handleResponse(WifiEvent& reply) {
1372 /* Nothing to do on response! */
1373 return NL_SKIP;
1374 }
1375
1376 virtual int handleEvent(WifiEvent& event) {
1377 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1378 unsigned int len = event.get_vendor_data_len();
1379 if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
1380 ALOGE("ERROR: No scan results found");
1381 return NL_SKIP;
1382 }
1383
1384 wifi_scan_result *result = (wifi_scan_result *)event.get_vendor_data();
1385 byte *anqp = (byte *)result + offsetof(wifi_scan_result, ie_data) + result->ie_length;
1386 int networkId = *(int *)anqp;
1387 anqp += sizeof(int);
1388 int anqp_len = *(u16 *)anqp;
1389 anqp += sizeof(u16);
1390
1391 if(*mHandler.on_passpoint_network_found)
1392 (*mHandler.on_passpoint_network_found)(id(), networkId, result, anqp_len, anqp);
1393
1394 return NL_SKIP;
1395 }
1396 };
1397
1398 wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num,
1399 wifi_passpoint_network *networks, wifi_passpoint_event_handler handler)
1400 {
1401 wifi_handle handle = getWifiHandle(iface);
1402 HsListCommand *cmd = new HsListCommand(id, iface, num, networks, handler);
1403
1404 wifi_register_cmd(handle, id, cmd);
1405 wifi_error result = (wifi_error)cmd->start();
1406 if (result != WIFI_SUCCESS) {
1407 wifi_unregister_cmd(handle, id);
1408 }
1409 return result;
1410 }
1411
1412 wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface)
1413 {
1414 wifi_handle handle = getWifiHandle(iface);
1415 wifi_error result;
1416 HsListCommand *cmd = (HsListCommand *)(wifi_get_cmd(handle, id));
1417
1418 if (cmd == NULL) {
1419 cmd = new HsListCommand(id, iface, 0);
1420 wifi_register_cmd(handle, id, cmd);
1421 }
1422 result = (wifi_error)cmd->cancel();
1423 wifi_unregister_cmd(handle, id);
1424 return result;
1425 }
1426
1427 #if 0 // TODO: (IP) removed to make it build
1428
1429 class BssidBlacklistCommand : public WifiCommand
1430 {
1431 private:
1432 wifi_bssid_params *mParams;
1433 public:
1434 BssidBlacklistCommand(wifi_interface_handle handle, int id,
1435 wifi_bssid_params *params)
1436 : WifiCommand(handle, id), mParams(params)
1437 { }
1438 int createRequest(WifiRequest& request) {
1439 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_BLACKLIST);
1440 if (result < 0) {
1441 return result;
1442 }
1443
1444 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1445 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BSSID, mParams->num_bssid);
1446 if (result < 0) {
1447 return result;
1448 }
1449
1450 for (int i = 0; i < mParams->num_bssid; i++) {
1451 result = request.put_addr(GSCAN_ATTRIBUTE_BLACKLIST_BSSID, mParams->bssids[i]);
1452 if (result < 0) {
1453 return result;
1454 }
1455 }
1456 request.attr_end(data);
1457 return result;
1458 }
1459
1460 int start() {
1461 WifiRequest request(familyId(), ifaceId());
1462 int result = createRequest(request);
1463 if (result < 0) {
1464 return result;
1465 }
1466
1467 result = requestResponse(request);
1468 if (result < 0) {
1469 ALOGE("Failed to execute bssid blacklist request, result = %d", result);
1470 return result;
1471 }
1472
1473 return result;
1474 }
1475
1476
1477 virtual int handleResponse(WifiEvent& reply) {
1478 /* Nothing to do on response! */
1479 return NL_SKIP;
1480 }
1481 };
1482
1483 wifi_error wifi_set_bssid_blacklist(wifi_request_id id, wifi_interface_handle iface,
1484 wifi_bssid_params params)
1485 {
1486 wifi_handle handle = getWifiHandle(iface);
1487
1488 BssidBlacklistCommand *cmd = new BssidBlacklistCommand(iface, id, &params);
1489 wifi_error result = (wifi_error)cmd->start();
1490 //release the reference of command as well
1491 cmd->releaseRef();
1492 return result;
1493 }
1494 #endif