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