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