[7570] wlbt: Support for Roam BSSID Blacklist
[GitHub/MotorolaMobilityLLC/hardware-samsung_slsi-scsc_wifibt-wifi_hal.git] / gscan.cpp
1
2 #include <stdint.h>
3 #include <fcntl.h>
4 #include <sys/socket.h>
5 #include <netlink/genl/genl.h>
6 #include <netlink/genl/family.h>
7 #include <netlink/genl/ctrl.h>
8 #include <linux/rtnetlink.h>
9 #include <netpacket/packet.h>
10 #include <linux/filter.h>
11 #include <linux/errqueue.h>
12
13 #include <linux/pkt_sched.h>
14 #include <netlink/object-api.h>
15 #include <netlink/netlink.h>
16 #include <netlink/socket.h>
17 #include <netlink/handlers.h>
18
19 #include "sync.h"
20
21 #define LOG_TAG "WifiHAL"
22
23 #include <utils/Log.h>
24
25 #include "wifi_hal.h"
26 #include "common.h"
27 #include "cpp_bindings.h"
28
29 typedef enum {
30
31 GSCAN_ATTRIBUTE_NUM_BUCKETS = 10,
32 GSCAN_ATTRIBUTE_BASE_PERIOD,
33 GSCAN_ATTRIBUTE_BUCKETS_BAND,
34 GSCAN_ATTRIBUTE_BUCKET_ID,
35 GSCAN_ATTRIBUTE_BUCKET_PERIOD,
36 GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
37 GSCAN_ATTRIBUTE_BUCKET_CHANNELS,
38 GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN,
39 GSCAN_ATTRIBUTE_REPORT_THRESHOLD,
40 GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE,
41 GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS,
42 GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND,
43
44 GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20,
45 GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */
46 GSCAN_ATTRIBUTE_REPORT_EVENTS,
47
48 /* remaining reserved for additional attributes */
49 GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30,
50 GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */
51 GSCAN_ATTRIBUTE_NUM_CHANNELS,
52 GSCAN_ATTRIBUTE_CHANNEL_LIST,
53 GSCAN_ATTRIBUTE_SCAN_ID,
54 GSCAN_ATTRIBUTE_SCAN_FLAGS,
55
56 /* remaining reserved for additional attributes */
57
58 GSCAN_ATTRIBUTE_SSID = 40,
59 GSCAN_ATTRIBUTE_BSSID,
60 GSCAN_ATTRIBUTE_CHANNEL,
61 GSCAN_ATTRIBUTE_RSSI,
62 GSCAN_ATTRIBUTE_TIMESTAMP,
63 GSCAN_ATTRIBUTE_RTT,
64 GSCAN_ATTRIBUTE_RTTSD,
65
66 /* remaining reserved for additional attributes */
67
68 GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50,
69 GSCAN_ATTRIBUTE_RSSI_LOW,
70 GSCAN_ATTRIBUTE_RSSI_HIGH,
71 GSCAN_ATTRIBUTE_HOTLIST_ELEM,
72 GSCAN_ATTRIBUTE_HOTLIST_FLUSH,
73 GSCAN_ATTRIBUTE_CHANNEL_NUMBER,
74
75 /* remaining reserved for additional attributes */
76 GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60,
77 GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE,
78 GSCAN_ATTRIBUTE_MIN_BREACHING,
79 GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS,
80
81 GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 70,
82 GSCAN_ATTRIBUTE_BUCKET_EXPONENT,
83 GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
84
85 GSCAN_ATTRIBUTE_NUM_BSSID,
86 GSCAN_ATTRIBUTE_BLACKLIST_BSSID,
87
88 GSCAN_ATTRIBUTE_MAX
89
90 } GSCAN_ATTRIBUTE;
91
92
93 class GetCapabilitiesCommand : public WifiCommand
94 {
95 wifi_gscan_capabilities *mCapabilities;
96 public:
97 GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites)
98 : WifiCommand(iface, 0), mCapabilities(capabitlites)
99 {
100 memset(mCapabilities, 0, sizeof(*mCapabilities));
101 }
102
103 virtual int create() {
104 ALOGD("Creating message to get scan capablities; iface = %d", mIfaceInfo->id);
105
106 int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_CAPABILITIES);
107 if (ret < 0) {
108 ALOGD("NL message creation failed");
109 return ret;
110 }
111
112 return ret;
113 }
114
115 protected:
116 virtual int handleResponse(WifiEvent& reply) {
117
118 ALOGD("In GetCapabilities::handleResponse");
119
120 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
121 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
122 return NL_SKIP;
123 }
124
125 int id = reply.get_vendor_id();
126 int subcmd = reply.get_vendor_subcmd();
127
128 void *data = reply.get_vendor_data();
129 int len = reply.get_vendor_data_len();
130
131 ALOGD("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len,
132 sizeof(*mCapabilities));
133
134 memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities)));
135
136 return NL_OK;
137 }
138 };
139
140
141 wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle,
142 wifi_gscan_capabilities *capabilities)
143 {
144 GetCapabilitiesCommand command(handle, capabilities);
145 return (wifi_error) command.requestResponse();
146 }
147
148 class GetChannelListCommand : public WifiCommand
149 {
150 wifi_channel *channels;
151 int max_channels;
152 int *num_channels;
153 int band;
154 public:
155 GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num,
156 int num_max_ch, int band)
157 : WifiCommand(iface, 0), channels(channel_buf), max_channels(num_max_ch), num_channels(ch_num),
158 band(band)
159 {
160 memset(channels, 0, sizeof(wifi_channel) * max_channels);
161 }
162 virtual int create() {
163 ALOGD("Creating message to get channel list; iface = %d", mIfaceInfo->id);
164
165 int ret = mMsg.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_VALID_CHANNELS);
166 if (ret < 0) {
167 return ret;
168 }
169
170 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA);
171 ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band);
172 if (ret < 0) {
173 return ret;
174 }
175
176 mMsg.attr_end(data);
177
178 return ret;
179 }
180
181 protected:
182 virtual int handleResponse(WifiEvent& reply) {
183
184 ALOGD("In GetChannelList::handleResponse");
185
186 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
187 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
188 return NL_SKIP;
189 }
190
191 int id = reply.get_vendor_id();
192 int subcmd = reply.get_vendor_subcmd();
193 int num_channels_to_copy = 0;
194
195 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
196 int len = reply.get_vendor_data_len();
197
198 ALOGD("Id = %0x, subcmd = %d, len = %d", id, subcmd, len);
199 if (vendor_data == NULL || len == 0) {
200 ALOGE("no vendor data in GetChannelList response; ignoring it");
201 return NL_SKIP;
202 }
203
204 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
205 if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) {
206 num_channels_to_copy = it.get_u32();
207 ALOGD("Got channel list with %d channels", num_channels_to_copy);
208 if(num_channels_to_copy > max_channels)
209 num_channels_to_copy = max_channels;
210 *num_channels = num_channels_to_copy;
211 } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) {
212 memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy);
213 } else {
214 ALOGW("Ignoring invalid attribute type = %d, size = %d",
215 it.get_type(), it.get_len());
216 }
217 }
218
219 return NL_OK;
220 }
221 };
222
223 wifi_error wifi_get_valid_channels(wifi_interface_handle handle,
224 int band, int max_channels, wifi_channel *channels, int *num_channels)
225 {
226 GetChannelListCommand command(handle, channels, num_channels,
227 max_channels, band);
228 return (wifi_error) command.requestResponse();
229 }
230 /////////////////////////////////////////////////////////////////////////////
231
232 /* helper functions */
233
234 static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr)
235 {
236 memset(results, 0, sizeof(wifi_scan_result) * num);
237
238 int i = 0;
239 for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) {
240
241 int index = it.get_type();
242 ALOGD("retrieved scan result %d", index);
243 nlattr *sc_data = (nlattr *) it.get_data();
244 wifi_scan_result *result = results + i;
245
246 for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) {
247 int type = it2.get_type();
248 if (type == GSCAN_ATTRIBUTE_SSID) {
249 strncpy(result->ssid, (char *) it2.get_data(), it2.get_len());
250 result->ssid[it2.get_len()] = 0;
251 } else if (type == GSCAN_ATTRIBUTE_BSSID) {
252 memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr));
253 } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) {
254 result->ts = it2.get_u64();
255 } else if (type == GSCAN_ATTRIBUTE_CHANNEL) {
256 result->ts = it2.get_u16();
257 } else if (type == GSCAN_ATTRIBUTE_RSSI) {
258 result->rssi = it2.get_u8();
259 } else if (type == GSCAN_ATTRIBUTE_RTT) {
260 result->rtt = it2.get_u64();
261 } else if (type == GSCAN_ATTRIBUTE_RTTSD) {
262 result->rtt_sd = it2.get_u64();
263 }
264 }
265
266 }
267
268 if (i >= num) {
269 ALOGE("Got too many results; skipping some");
270 }
271
272 return i;
273 }
274
275 int createFeatureRequest(WifiRequest& request, int subcmd) {
276
277 int result = request.create(GOOGLE_OUI, subcmd);
278 if (result < 0) {
279 return result;
280 }
281
282 return WIFI_SUCCESS;
283 }
284
285 class ScanCommand : public WifiCommand
286 {
287 wifi_scan_cmd_params *mParams;
288 wifi_scan_result_handler mHandler;
289 static unsigned mGlobalFullScanBuckets;
290 bool mLocalFullScanBuckets;
291 public:
292 ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params,
293 wifi_scan_result_handler handler)
294 : WifiCommand(iface, id), mParams(params), mHandler(handler),
295 mLocalFullScanBuckets(0)
296 { }
297
298 int createSetupRequest(WifiRequest& request) {
299 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN);
300 if (result < 0) {
301 return result;
302 }
303
304 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
305 result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period);
306 if (result < 0) {
307 return result;
308 }
309
310 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan);
311 if (result < 0) {
312 return result;
313 }
314
315 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD, mParams->report_threshold_percent);
316 if (result < 0) {
317 return result;
318 }
319
320 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD_NUM_SCANS, mParams->report_threshold_num_scans);
321 if (result < 0) {
322 return result;
323 }
324
325 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets);
326 if (result < 0) {
327 return result;
328 }
329
330 for (int i = 0; i < mParams->num_buckets; i++) {
331 nlattr * bucket = request.attr_start(i); // next bucket
332 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket);
333 if (result < 0) {
334 return result;
335 }
336 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period);
337 if (result < 0) {
338 return result;
339 }
340 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND,
341 mParams->buckets[i].band);
342 if (result < 0) {
343 return result;
344 }
345
346 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS,
347 mParams->buckets[i].report_events);
348 if (result < 0) {
349 return result;
350 }
351
352 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS,
353 mParams->buckets[i].num_channels);
354 if (result < 0) {
355 return result;
356 }
357
358 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_EXPONENT,
359 mParams->buckets[i].exponent);
360 if (result < 0) {
361 return result;
362 }
363
364 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD,
365 mParams->buckets[i].max_period);
366 if (result < 0) {
367 return result;
368 }
369
370 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT,
371 mParams->buckets[i].step_count);
372 if (result < 0) {
373 return result;
374 }
375
376 if (mParams->buckets[i].num_channels) {
377 nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS);
378 for (int j = 0; j < mParams->buckets[i].num_channels; j++) {
379 result = request.put_u32(j, mParams->buckets[i].channels[j].channel);
380 if (result < 0) {
381 return result;
382 }
383 }
384 request.attr_end(channels);
385 }
386
387 request.attr_end(bucket);
388 }
389
390 request.attr_end(data);
391 return WIFI_SUCCESS;
392 }
393
394 int createStartRequest(WifiRequest& request) {
395 return createFeatureRequest(request, SLSI_NL80211_VENDOR_SUBCMD_ADD_GSCAN);
396 }
397
398 int createStopRequest(WifiRequest& request) {
399 return createFeatureRequest(request, SLSI_NL80211_VENDOR_SUBCMD_DEL_GSCAN);
400 }
401
402 int start() {
403 ALOGD(" sending scan req to driver");
404 WifiRequest request(familyId(), ifaceId());
405 int result = createSetupRequest(request);
406 if (result != WIFI_SUCCESS) {
407 ALOGE("failed to create setup request; result = %d", result);
408 return result;
409 }
410 ALOGD("Starting scan");
411
412 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
413 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
414
415 int nBuckets = 0;
416 for (int i = 0; i < mParams->num_buckets; i++) {
417 if (mParams->buckets[i].report_events == 2) {
418 nBuckets++;
419 }
420 }
421
422 if (nBuckets != 0) {
423 ALOGI("Full scan requested with nBuckets = %d", nBuckets);
424 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
425 }
426 result = requestResponse(request);
427 if (result != WIFI_SUCCESS) {
428 ALOGE("failed to start scan; result = %d", result);
429 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
430 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
431 return result;
432 }
433
434
435 return result;
436 }
437
438 virtual int cancel() {
439 ALOGD("Stopping scan");
440
441 WifiRequest request(familyId(), ifaceId());
442 int result = createStopRequest(request);
443 if (result != WIFI_SUCCESS) {
444 ALOGE("failed to create stop request; result = %d", result);
445 } else {
446 result = requestResponse(request);
447 if (result != WIFI_SUCCESS) {
448 ALOGE("failed to stop scan; result = %d", result);
449 }
450 }
451
452 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN);
453 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE);
454 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS);
455
456 return WIFI_SUCCESS;
457 }
458
459 virtual int handleResponse(WifiEvent& reply) {
460 /* Nothing to do on response! */
461 return NL_SKIP;
462 }
463
464 virtual int handleEvent(WifiEvent& event) {
465 ALOGD("Got a scan results event");
466
467 event.log();
468
469 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
470 unsigned int len = event.get_vendor_data_len();
471 int event_id = event.get_vendor_subcmd();
472 ALOGD("handleEvent, event_id = %d", event_id);
473
474 if(event_id == GSCAN_EVENT_COMPLETE_SCAN) {
475 if (vendor_data == NULL || len != 4) {
476 ALOGD("Scan complete type not mentioned!");
477 return NL_SKIP;
478 }
479 wifi_scan_event evt_type;
480
481 evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA);
482 ALOGD("Scan complete: Received event type %d", evt_type);
483 if(*mHandler.on_scan_event)
484 (*mHandler.on_scan_event)(evt_type, evt_type);
485 } else if(event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) {
486 if (vendor_data == NULL || len < sizeof(wifi_scan_result)) {
487 ALOGD("No scan results found");
488 return NL_SKIP;
489 }
490 wifi_scan_result *result = (wifi_scan_result *)event.get_vendor_data();
491
492 if(*mHandler.on_full_scan_result)
493 (*mHandler.on_full_scan_result)(id(), result);
494
495 ALOGD("%-32s\t", result->ssid);
496
497 ALOGD("%02x:%02x:%02x:%02x:%02x:%02x ", result->bssid[0], result->bssid[1],
498 result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]);
499
500 ALOGD("%d\t", result->rssi);
501 ALOGD("%d\t", result->channel);
502 ALOGD("%lld\t", result->ts);
503 ALOGD("%lld\t", result->rtt);
504 ALOGD("%lld\n", result->rtt_sd);
505 } else {
506
507 if (vendor_data == NULL || len != 4) {
508 ALOGD("No scan results found");
509 return NL_SKIP;
510 }
511
512 int num = event.get_u32(NL80211_ATTR_VENDOR_DATA);
513 ALOGD("Found %d scan results", num);
514 if(*mHandler.on_scan_results_available)
515 (*mHandler.on_scan_results_available)(id(), num);
516 }
517 return NL_SKIP;
518 }
519 };
520
521 unsigned ScanCommand::mGlobalFullScanBuckets = 0;
522
523 wifi_error wifi_start_gscan(
524 wifi_request_id id,
525 wifi_interface_handle iface,
526 wifi_scan_cmd_params params,
527 wifi_scan_result_handler handler)
528 {
529 wifi_handle handle = getWifiHandle(iface);
530
531 ALOGD("Starting GScan, halHandle = %p", handle);
532
533 ScanCommand *cmd = new ScanCommand(iface, id, &params, handler);
534 wifi_register_cmd(handle, id, cmd);
535 return (wifi_error)cmd->start();
536 }
537
538 wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface)
539 {
540 ALOGD("Stopping GScan");
541 wifi_handle handle = getWifiHandle(iface);
542
543 if(id == -1) {
544 wifi_scan_result_handler handler;
545 wifi_scan_cmd_params dummy_params;
546 wifi_handle handle = getWifiHandle(iface);
547 memset(&handler, 0, sizeof(handler));
548
549 ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler);
550 cmd->cancel();
551 cmd->releaseRef();
552 return WIFI_SUCCESS;
553 }
554
555
556 WifiCommand *cmd = wifi_unregister_cmd(handle, id);
557 if (cmd) {
558 cmd->cancel();
559 cmd->releaseRef();
560 return WIFI_SUCCESS;
561 }
562
563 return WIFI_ERROR_INVALID_ARGS;
564 }
565
566 class GetScanResultsCommand : public WifiCommand {
567 wifi_cached_scan_results *mScans;
568 int mMax;
569 int *mNum;
570 int mRetrieved;
571 byte mFlush;
572 int mCompleted;
573 static const int MAX_RESULTS = 320;
574 wifi_scan_result mScanResults[MAX_RESULTS];
575 int mNextScanResult;
576 public:
577 GetScanResultsCommand(wifi_interface_handle iface, byte flush,
578 wifi_cached_scan_results *results, int max, int *num)
579 : WifiCommand(iface, -1), mScans(results), mMax(max), mNum(num),
580 mRetrieved(0), mFlush(flush), mCompleted(0)
581 { }
582
583 int createRequest(WifiRequest& request, int num, byte flush) {
584 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_GET_SCAN_RESULTS);
585 if (result < 0) {
586 return result;
587 }
588
589 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
590 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num);
591 if (result < 0) {
592 return result;
593 }
594
595 request.attr_end(data);
596 return WIFI_SUCCESS;
597 }
598
599 int execute() {
600 WifiRequest request(familyId(), ifaceId());
601 ALOGD("retrieving %d scan results", mMax);
602
603 for (int i = 0; i < 10 && mRetrieved < mMax; i++) {
604 int result = createRequest(request, (mMax - mRetrieved), mFlush);
605 if (result < 0) {
606 ALOGE("failed to create request");
607 return result;
608 }
609
610 int prev_retrieved = mRetrieved;
611
612 result = requestResponse(request);
613
614 if (result != WIFI_SUCCESS) {
615 ALOGE("failed to retrieve scan results; result = %d", result);
616 return result;
617 }
618
619 if (mRetrieved == prev_retrieved || mCompleted) {
620 /* no more items left to retrieve */
621 break;
622 }
623
624 request.destroy();
625 }
626
627 ALOGE("GetScanResults read %d results", mRetrieved);
628 *mNum = mRetrieved;
629 return WIFI_SUCCESS;
630 }
631
632 virtual int handleResponse(WifiEvent& reply) {
633 ALOGD("In GetScanResultsCommand::handleResponse");
634
635 if (reply.get_cmd() != NL80211_CMD_VENDOR) {
636 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd());
637 return NL_SKIP;
638 }
639
640 int id = reply.get_vendor_id();
641 int subcmd = reply.get_vendor_subcmd();
642
643 ALOGD("Id = %0x, subcmd = %d", id, subcmd);
644
645 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA);
646 int len = reply.get_vendor_data_len();
647
648 if (vendor_data == NULL || len == 0) {
649 ALOGE("no vendor data in GetScanResults response; ignoring it");
650 return NL_SKIP;
651 }
652
653 for (nl_iterator it(vendor_data); it.has_next(); it.next()) {
654 if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) {
655 mCompleted = it.get_u8();
656 ALOGD("retrieved mCompleted flag : %d", mCompleted);
657 } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) {
658 int scan_id = 0, flags = 0, num = 0;
659 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) {
660 if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) {
661 scan_id = it2.get_u32();
662 ALOGD("retrieved scan_id : 0x%0x", scan_id);
663 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) {
664 flags = it2.get_u8();
665 ALOGD("retrieved scan_flags : 0x%0x", flags);
666 } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) {
667 num = it2.get_u32();
668 ALOGD("retrieved num_results: %d", num);
669 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS) {
670 if (mRetrieved >= mMax) {
671 ALOGW("Stored %d scans, ignoring excess results", mRetrieved);
672 break;
673 }
674 num = it2.get_len() / sizeof(wifi_scan_result);
675 num = min(MAX_RESULTS - mNextScanResult, num);
676 num = min((int)MAX_AP_CACHE_PER_SCAN, num);
677 memcpy(mScanResults + mNextScanResult, it2.get_data(),
678 sizeof(wifi_scan_result) * num);
679 ALOGD("Retrieved %d scan results", num);
680 wifi_scan_result *results = (wifi_scan_result *)it2.get_data();
681 for (int i = 0; i < num; i++) {
682 wifi_scan_result *result = results + i;
683 ALOGD("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i,
684 result->ssid, result->bssid[0], result->bssid[1], result->bssid[2],
685 result->bssid[3], result->bssid[4], result->bssid[5],
686 result->rssi);
687 }
688 mScans[mRetrieved].scan_id = scan_id;
689 mScans[mRetrieved].flags = flags;
690 mScans[mRetrieved].num_results = num;
691 ALOGD("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id);
692 memcpy(mScans[mRetrieved].results,
693 &(mScanResults[mNextScanResult]), num * sizeof(wifi_scan_result));
694 mNextScanResult += num;
695 mRetrieved++;
696 } else {
697 ALOGW("Ignoring invalid attribute type = %d, size = %d",
698 it.get_type(), it.get_len());
699 }
700 }
701 } else {
702 ALOGW("Ignoring invalid attribute type = %d, size = %d",
703 it.get_type(), it.get_len());
704 }
705 }
706
707 return NL_OK;
708 }
709 };
710
711 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush,
712 int max, wifi_cached_scan_results *results, int *num) {
713 ALOGD("Getting cached scan results, iface handle = %p, num = %d", iface, *num);
714
715 GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num);
716 return (wifi_error)cmd->execute();
717 }
718
719 /////////////////////////////////////////////////////////////////////////////
720
721 class BssidHotlistCommand : public WifiCommand
722 {
723 private:
724 wifi_bssid_hotlist_params mParams;
725 wifi_hotlist_ap_found_handler mHandler;
726 static const int MAX_RESULTS = 64;
727 wifi_scan_result mResults[MAX_RESULTS];
728 public:
729 BssidHotlistCommand(wifi_interface_handle handle, int id,
730 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
731 : WifiCommand(handle, id), mParams(params), mHandler(handler)
732 { }
733
734 int createSetupRequest(WifiRequest& request) {
735 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_HOTLIST);
736 if (result < 0) {
737 return result;
738 }
739
740 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
741
742 result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
743 if (result < 0) {
744 return result;
745 }
746
747 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS);
748 for (int i = 0; i < mParams.num_bssid; i++) {
749 nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM);
750 if (attr2 == NULL) {
751 return WIFI_ERROR_OUT_OF_MEMORY;
752 }
753 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
754 if (result < 0) {
755 return result;
756 }
757 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
758 if (result < 0) {
759 return result;
760 }
761 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
762 if (result < 0) {
763 return result;
764 }
765 request.attr_end(attr2);
766 }
767
768 request.attr_end(attr);
769 request.attr_end(data);
770 return result;
771 }
772
773 int createTeardownRequest(WifiRequest& request) {
774 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_BSSID_HOTLIST);
775 if (result < 0) {
776 return result;
777 }
778
779 return result;
780 }
781
782 int start() {
783 ALOGD("Executing hotlist setup request, num = %d", mParams.num_bssid);
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 ALOGD("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 ALOGD("Successfully set %d APs in the hotlist", mParams.num_bssid);
799
800 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
801 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
802
803 return result;
804 }
805
806 virtual int cancel() {
807 /* unregister event handler */
808 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND);
809 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST);
810 /* create set hotlist message with empty hotlist */
811 WifiRequest request(familyId(), ifaceId());
812 int result = createTeardownRequest(request);
813 if (result < 0) {
814 return result;
815 }
816
817 result = requestResponse(request);
818 if (result < 0) {
819 return result;
820 }
821
822 ALOGD("Successfully reset APs in current hotlist");
823 return result;
824 }
825
826 virtual int handleResponse(WifiEvent& reply) {
827 /* Nothing to do on response! */
828 return NL_SKIP;
829 }
830
831 virtual int handleEvent(WifiEvent& event) {
832 ALOGD("Hotlist AP event");
833 int event_id = event.get_vendor_subcmd();
834 event.log();
835
836 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
837 int len = event.get_vendor_data_len();
838
839 if (vendor_data == NULL || len == 0) {
840 ALOGD("No scan results found");
841 return NL_SKIP;
842 }
843
844 memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS);
845
846 int num = len / sizeof(wifi_scan_result);
847 num = min(MAX_RESULTS, num);
848 memcpy(mResults, event.get_vendor_data(), num * sizeof(wifi_scan_result));
849
850 if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) {
851 ALOGD("FOUND %d hotlist APs", num);
852 if (*mHandler.on_hotlist_ap_found)
853 (*mHandler.on_hotlist_ap_found)(id(), num, mResults);
854 } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) {
855 ALOGD("LOST %d hotlist APs", num);
856 if (*mHandler.on_hotlist_ap_lost)
857 (*mHandler.on_hotlist_ap_lost)(id(), num, mResults);
858 }
859 return NL_SKIP;
860 }
861 };
862
863 wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface,
864 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler)
865 {
866 wifi_handle handle = getWifiHandle(iface);
867
868 BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler);
869 wifi_register_cmd(handle, id, cmd);
870 return (wifi_error)cmd->start();
871 }
872
873 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface)
874 {
875 wifi_handle handle = getWifiHandle(iface);
876
877 WifiCommand *cmd = wifi_unregister_cmd(handle, id);
878 if (cmd) {
879 cmd->cancel();
880 cmd->releaseRef();
881 return WIFI_SUCCESS;
882 }
883
884 return WIFI_ERROR_INVALID_ARGS;
885 }
886
887
888 /////////////////////////////////////////////////////////////////////////////
889
890 class SignificantWifiChangeCommand : public WifiCommand
891 {
892 typedef struct {
893 mac_addr bssid; // BSSID
894 wifi_channel channel; // channel frequency in MHz
895 int num_rssi; // number of rssi samples
896 wifi_rssi rssi[8]; // RSSI history in db
897 } wifi_significant_change_result_internal;
898
899 private:
900 wifi_significant_change_params mParams;
901 wifi_significant_change_handler mHandler;
902 static const int MAX_RESULTS = 64;
903 wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS];
904 wifi_significant_change_result *mResults[MAX_RESULTS];
905 public:
906 SignificantWifiChangeCommand(wifi_interface_handle handle, int id,
907 wifi_significant_change_params params, wifi_significant_change_handler handler)
908 : WifiCommand(handle, id), mParams(params), mHandler(handler)
909 { }
910
911 int createSetupRequest(WifiRequest& request) {
912 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_SIGNIFICANT_CHANGE);
913 if (result < 0) {
914 return result;
915 }
916
917 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
918
919 result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size);
920 if (result < 0) {
921 return result;
922 }
923 result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size);
924 if (result < 0) {
925 return result;
926 }
927 result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching);
928 if (result < 0) {
929 return result;
930 }
931
932 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS);
933
934 for (int i = 0; i < mParams.num_bssid; i++) {
935
936 nlattr *attr2 = request.attr_start(i);
937 if (attr2 == NULL) {
938 return WIFI_ERROR_OUT_OF_MEMORY;
939 }
940 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid);
941 if (result < 0) {
942 return result;
943 }
944 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high);
945 if (result < 0) {
946 return result;
947 }
948 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low);
949 if (result < 0) {
950 return result;
951 }
952 request.attr_end(attr2);
953 }
954
955 request.attr_end(attr);
956 request.attr_end(data);
957
958 return result;
959 }
960
961 int createTeardownRequest(WifiRequest& request) {
962 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_RESET_SIGNIFICANT_CHANGE);
963 if (result < 0) {
964 return result;
965 }
966
967 return result;
968 }
969
970 int start() {
971 ALOGD("Set significant wifi change");
972 WifiRequest request(familyId(), ifaceId());
973
974 int result = createSetupRequest(request);
975 if (result < 0) {
976 return result;
977 }
978
979 result = requestResponse(request);
980 if (result < 0) {
981 ALOGD("failed to set significant wifi change %d", result);
982 return result;
983 }
984 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
985
986 return result;
987 }
988
989 virtual int cancel() {
990 /* unregister event handler */
991 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS);
992
993 /* create set significant change monitor message with empty hotlist */
994 WifiRequest request(familyId(), ifaceId());
995
996 int result = createTeardownRequest(request);
997 if (result < 0) {
998 return result;
999 }
1000
1001 result = requestResponse(request);
1002 if (result < 0) {
1003 return result;
1004 }
1005
1006 ALOGD("successfully reset significant wifi change");
1007 return result;
1008 }
1009
1010 virtual int handleResponse(WifiEvent& reply) {
1011 /* Nothing to do on response! */
1012 return NL_SKIP;
1013 }
1014
1015 virtual int handleEvent(WifiEvent& event) {
1016 ALOGD("Got a significant wifi change event");
1017
1018 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA);
1019 int len = event.get_vendor_data_len();
1020
1021 if (vendor_data == NULL || len == 0) {
1022 ALOGD("No scan results found");
1023 return NL_SKIP;
1024 }
1025
1026 typedef struct {
1027 uint16_t channel;
1028 mac_addr bssid;
1029 int16_t rssi_history[8];
1030 } ChangeInfo;
1031
1032 int num = min(len / sizeof(ChangeInfo), MAX_RESULTS);
1033 ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data();
1034
1035 for (int i = 0; i < num; i++) {
1036 memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr));
1037 mResultsBuffer[i].channel = ci[i].channel;
1038 /* Driver sends N samples and the rest 8-N are filled 0x7FFF
1039 * N = no of rssi samples to average sent in significant change request. */
1040 int num_rssi = 0;
1041 for (int j = 0; j < 8; j++) {
1042 if (ci[i].rssi_history[j] == 0x7FFF) {
1043 num_rssi = j;
1044 break;
1045 }
1046 mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j];
1047 }
1048 mResultsBuffer[i].num_rssi = num_rssi;
1049 mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i]));
1050 }
1051
1052 ALOGD("Retrieved %d scan results", num);
1053
1054 if (num != 0) {
1055 (*mHandler.on_significant_change)(id(), num, mResults);
1056 } else {
1057 ALOGW("No significant change reported");
1058 }
1059
1060 return NL_SKIP;
1061 }
1062 };
1063
1064 wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface,
1065 wifi_significant_change_params params, wifi_significant_change_handler handler)
1066 {
1067 wifi_handle handle = getWifiHandle(iface);
1068
1069 SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand(
1070 iface, id, params, handler);
1071 wifi_register_cmd(handle, id, cmd);
1072 return (wifi_error)cmd->start();
1073 }
1074
1075 wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface)
1076 {
1077 wifi_handle handle = getWifiHandle(iface);
1078
1079 WifiCommand *cmd = wifi_unregister_cmd(handle, id);
1080 if (cmd) {
1081 cmd->cancel();
1082 cmd->releaseRef();
1083 return WIFI_SUCCESS;
1084 }
1085
1086 return WIFI_ERROR_INVALID_ARGS;
1087 }
1088
1089 class BssidBlacklistCommand : public WifiCommand
1090 {
1091 private:
1092 wifi_bssid_params *mParams;
1093 public:
1094 BssidBlacklistCommand(wifi_interface_handle handle, int id,
1095 wifi_bssid_params *params)
1096 : WifiCommand(handle, id), mParams(params)
1097 { }
1098 int createRequest(WifiRequest& request) {
1099 int result = request.create(GOOGLE_OUI, SLSI_NL80211_VENDOR_SUBCMD_SET_BSSID_BLACKLIST);
1100 if (result < 0) {
1101 return result;
1102 }
1103
1104 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA);
1105 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BSSID, mParams->num_bssid);
1106 if (result < 0) {
1107 return result;
1108 }
1109
1110 for (int i = 0; i < mParams->num_bssid; i++) {
1111 result = request.put_addr(GSCAN_ATTRIBUTE_BLACKLIST_BSSID, mParams->bssids[i]);
1112 if (result < 0) {
1113 return result;
1114 }
1115 }
1116 request.attr_end(data);
1117 return result;
1118 }
1119
1120 int start() {
1121 ALOGD("Executing bssid blacklist request, num = %d", mParams->num_bssid);
1122 WifiRequest request(familyId(), ifaceId());
1123 int result = createRequest(request);
1124 if (result < 0) {
1125 return result;
1126 }
1127
1128 result = requestResponse(request);
1129 if (result < 0) {
1130 ALOGE("Failed to execute bssid blacklist request, result = %d", result);
1131 return result;
1132 }
1133
1134 ALOGI("Successfully added %d blacklist bssids", mParams->num_bssid);
1135 return result;
1136 }
1137
1138
1139 virtual int handleResponse(WifiEvent& reply) {
1140 /* Nothing to do on response! */
1141 return NL_SKIP;
1142 }
1143 };
1144
1145 wifi_error wifi_set_bssid_blacklist(wifi_request_id id, wifi_interface_handle iface,
1146 wifi_bssid_params params)
1147 {
1148 wifi_handle handle = getWifiHandle(iface);
1149
1150 BssidBlacklistCommand *cmd = new BssidBlacklistCommand(iface, id, &params);
1151 wifi_error result = (wifi_error)cmd->start();
1152 //release the reference of command as well
1153 cmd->releaseRef();
1154 return result;
1155 }
1156