1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Portions copyright (C) 2017 Broadcom Limited 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #include <stdint.h> 20 #include <fcntl.h> 21 #include <sys/socket.h> 22 #include <netlink/genl/genl.h> 23 #include <netlink/genl/family.h> 24 #include <netlink/genl/ctrl.h> 25 #include <linux/rtnetlink.h> 26 #include <netpacket/packet.h> 27 #include <linux/filter.h> 28 #include <linux/errqueue.h> 29 30 #include <linux/pkt_sched.h> 31 #include <netlink/object-api.h> 32 #include <netlink/netlink.h> 33 #include <netlink/socket.h> 34 #include <netlink/handlers.h> 35 36 #include "sync.h" 37 38 #define LOG_TAG "WifiHAL" 39 //#define LOG_NDEBUG 0 //uncomment to enable verbose logging 40 41 #include <log/log.h> 42 43 #include "wifi_hal.h" 44 #include "common.h" 45 #include "cpp_bindings.h" 46 47 typedef enum { 48 49 GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, 50 GSCAN_ATTRIBUTE_BASE_PERIOD, 51 GSCAN_ATTRIBUTE_BUCKETS_BAND, 52 GSCAN_ATTRIBUTE_BUCKET_ID, 53 GSCAN_ATTRIBUTE_BUCKET_PERIOD, 54 GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, 55 GSCAN_ATTRIBUTE_BUCKET_CHANNELS, 56 GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, 57 GSCAN_ATTRIBUTE_REPORT_THRESHOLD, 58 GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, 59 GSCAN_ATTRIBUTE_BAND = GSCAN_ATTRIBUTE_BUCKETS_BAND, 60 61 GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, 62 GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ 63 GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ 64 GSCAN_ENABLE_FULL_SCAN_RESULTS, 65 GSCAN_ATTRIBUTE_REPORT_EVENTS, 66 67 /* remaining reserved for additional attributes */ 68 GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, 69 GSCAN_ATTRIBUTE_FLUSH_RESULTS, 70 GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ 71 GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ 72 GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ 73 GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ 74 GSCAN_ATTRIBUTE_NUM_CHANNELS, 75 GSCAN_ATTRIBUTE_CHANNEL_LIST, 76 GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK, 77 /* remaining reserved for additional attributes */ 78 79 GSCAN_ATTRIBUTE_SSID = 40, 80 GSCAN_ATTRIBUTE_BSSID, 81 GSCAN_ATTRIBUTE_CHANNEL, 82 GSCAN_ATTRIBUTE_RSSI, 83 GSCAN_ATTRIBUTE_TIMESTAMP, 84 GSCAN_ATTRIBUTE_RTT, 85 GSCAN_ATTRIBUTE_RTTSD, 86 87 /* remaining reserved for additional attributes */ 88 89 GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, 90 GSCAN_ATTRIBUTE_RSSI_LOW, 91 GSCAN_ATTRIBUTE_RSSI_HIGH, 92 GSCAN_ATTRIBUTE_HOTLIST_ELEM, 93 GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 94 GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT, 95 96 /* remaining reserved for additional attributes */ 97 GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, 98 GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, 99 GSCAN_ATTRIBUTE_MIN_BREACHING, 100 GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, 101 GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 102 103 /* EPNO */ 104 GSCAN_ATTRIBUTE_EPNO_SSID_LIST = 70, 105 GSCAN_ATTRIBUTE_EPNO_SSID, 106 GSCAN_ATTRIBUTE_EPNO_SSID_LEN, 107 GSCAN_ATTRIBUTE_EPNO_RSSI, 108 GSCAN_ATTRIBUTE_EPNO_FLAGS, 109 GSCAN_ATTRIBUTE_EPNO_AUTH, 110 GSCAN_ATTRIBUTE_EPNO_SSID_NUM, 111 GSCAN_ATTRIBUTE_EPNO_FLUSH, 112 113 /* remaining reserved for additional attributes */ 114 115 GSCAN_ATTRIBUTE_WHITELIST_SSID = 80, 116 GSCAN_ATTRIBUTE_NUM_WL_SSID, 117 GSCAN_ATTRIBUTE_WL_SSID_LEN, 118 GSCAN_ATTRIBUTE_WL_SSID_FLUSH, 119 GSCAN_ATTRIBUTE_WHITELIST_SSID_ELEM, 120 GSCAN_ATTRIBUTE_NUM_BSSID, 121 GSCAN_ATTRIBUTE_BSSID_PREF_LIST, 122 GSCAN_ATTRIBUTE_BSSID_PREF_FLUSH, 123 GSCAN_ATTRIBUTE_BSSID_PREF, 124 GSCAN_ATTRIBUTE_RSSI_MODIFIER, 125 126 /* remaining reserved for additional attributes */ 127 128 GSCAN_ATTRIBUTE_A_BAND_BOOST_THRESHOLD = 90, 129 GSCAN_ATTRIBUTE_A_BAND_PENALTY_THRESHOLD, 130 GSCAN_ATTRIBUTE_A_BAND_BOOST_FACTOR, 131 GSCAN_ATTRIBUTE_A_BAND_PENALTY_FACTOR, 132 GSCAN_ATTRIBUTE_A_BAND_MAX_BOOST, 133 GSCAN_ATTRIBUTE_LAZY_ROAM_HYSTERESIS, 134 GSCAN_ATTRIBUTE_ALERT_ROAM_RSSI_TRIGGER, 135 GSCAN_ATTRIBUTE_LAZY_ROAM_ENABLE, 136 137 /* BSSID blacklist */ 138 GSCAN_ATTRIBUTE_BSSID_BLACKLIST_FLUSH = 100, 139 GSCAN_ATTRIBUTE_BLACKLIST_BSSID, 140 141 /* ANQPO */ 142 GSCAN_ATTRIBUTE_ANQPO_HS_LIST = 110, 143 GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, 144 GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, 145 GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, 146 GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID, 147 GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, 148 149 /* Adaptive scan attributes */ 150 GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT = 120, 151 GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, 152 153 /* ePNO cfg */ 154 GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR = 130, 155 GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR, 156 GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX, 157 GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS, 158 GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS, 159 GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS, 160 GSCAN_ATTRIBUTE_EPNO_5G_BONUS, 161 162 GSCAN_ATTRIBUTE_MAX 163 164 } GSCAN_ATTRIBUTE; 165 166 167 // helper methods 168 wifi_error wifi_enable_full_scan_results(wifi_request_id id, wifi_interface_handle iface, 169 wifi_scan_result_handler handler); 170 wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface); 171 int wifi_handle_full_scan_event(wifi_request_id id, WifiEvent& event, 172 wifi_scan_result_handler handler); 173 void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from); 174 175 176 void convert_to_hal_result(wifi_scan_result *to, wifi_gscan_result_t *from) 177 { 178 to->ts = from->ts; 179 to->channel = from->channel; 180 to->rssi = from->rssi; 181 to->rtt = from->rtt; 182 to->rtt_sd = from->rtt_sd; 183 to->beacon_period = from->beacon_period; 184 to->capability = from->capability; 185 memcpy(to->ssid, from->ssid, (DOT11_MAX_SSID_LEN+1)); 186 memcpy(&to->bssid, &from->bssid, sizeof(mac_addr)); 187 } 188 189 ///////////////////////////////////////////////////////////////////////////// 190 191 class GetCapabilitiesCommand : public WifiCommand 192 { 193 wifi_gscan_capabilities *mCapabilities; 194 public: 195 GetCapabilitiesCommand(wifi_interface_handle iface, wifi_gscan_capabilities *capabitlites) 196 : WifiCommand("GetGscanCapabilitiesCommand", iface, 0), mCapabilities(capabitlites) 197 { 198 memset(mCapabilities, 0, sizeof(*mCapabilities)); 199 } 200 201 virtual int create() { 202 ALOGV("Creating message to get scan capablities; iface = %d", mIfaceInfo->id); 203 204 int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CAPABILITIES); 205 if (ret < 0) { 206 return ret; 207 } 208 209 return ret; 210 } 211 212 protected: 213 virtual int handleResponse(WifiEvent& reply) { 214 215 ALOGV("In GetCapabilities::handleResponse"); 216 217 if (reply.get_cmd() != NL80211_CMD_VENDOR) { 218 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 219 return NL_SKIP; 220 } 221 222 int id = reply.get_vendor_id(); 223 int subcmd = reply.get_vendor_subcmd(); 224 225 void *data = reply.get_vendor_data(); 226 int len = reply.get_vendor_data_len(); 227 228 ALOGV("Id = %0x, subcmd = %d, len = %d, expected len = %d", id, subcmd, len, 229 sizeof(*mCapabilities)); 230 231 memcpy(mCapabilities, data, min(len, (int) sizeof(*mCapabilities))); 232 233 return NL_OK; 234 } 235 }; 236 237 238 wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, 239 wifi_gscan_capabilities *capabilities) 240 { 241 GetCapabilitiesCommand command(handle, capabilities); 242 return (wifi_error) command.requestResponse(); 243 } 244 245 class GetChannelListCommand : public WifiCommand 246 { 247 wifi_channel *channels; 248 int max_channels; 249 int *num_channels; 250 int band; 251 public: 252 GetChannelListCommand(wifi_interface_handle iface, wifi_channel *channel_buf, int *ch_num, 253 int num_max_ch, int band) 254 : WifiCommand("GetChannelListCommand", iface, 0), channels(channel_buf), 255 max_channels(num_max_ch), num_channels(ch_num), band(band) 256 { 257 memset(channels, 0, sizeof(wifi_channel) * max_channels); 258 } 259 virtual int create() { 260 ALOGV("Creating message to get channel list; iface = %d", mIfaceInfo->id); 261 262 int ret = mMsg.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_CHANNEL_LIST); 263 if (ret < 0) { 264 return ret; 265 } 266 267 nlattr *data = mMsg.attr_start(NL80211_ATTR_VENDOR_DATA); 268 ret = mMsg.put_u32(GSCAN_ATTRIBUTE_BAND, band); 269 if (ret < 0) { 270 return ret; 271 } 272 273 mMsg.attr_end(data); 274 275 return ret; 276 } 277 278 protected: 279 virtual int handleResponse(WifiEvent& reply) { 280 281 ALOGV("In GetChannelList::handleResponse"); 282 283 if (reply.get_cmd() != NL80211_CMD_VENDOR) { 284 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 285 return NL_SKIP; 286 } 287 288 int id = reply.get_vendor_id(); 289 int subcmd = reply.get_vendor_subcmd(); 290 int num_channels_to_copy = 0; 291 292 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 293 int len = reply.get_vendor_data_len(); 294 295 ALOGV("Id = %0x, subcmd = %d, len = %d", id, subcmd, len); 296 if (vendor_data == NULL || len == 0) { 297 ALOGE("no vendor data in GetChannelList response; ignoring it"); 298 return NL_SKIP; 299 } 300 301 for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 302 if (it.get_type() == GSCAN_ATTRIBUTE_NUM_CHANNELS) { 303 num_channels_to_copy = it.get_u32(); 304 ALOGI("Got channel list with %d channels", num_channels_to_copy); 305 if(num_channels_to_copy > max_channels) 306 num_channels_to_copy = max_channels; 307 *num_channels = num_channels_to_copy; 308 } else if (it.get_type() == GSCAN_ATTRIBUTE_CHANNEL_LIST && num_channels_to_copy) { 309 memcpy(channels, it.get_data(), sizeof(int) * num_channels_to_copy); 310 } else { 311 ALOGW("Ignoring invalid attribute type = %d, size = %d", 312 it.get_type(), it.get_len()); 313 } 314 } 315 316 return NL_OK; 317 } 318 }; 319 320 wifi_error wifi_get_valid_channels(wifi_interface_handle handle, 321 int band, int max_channels, wifi_channel *channels, int *num_channels) 322 { 323 GetChannelListCommand command(handle, channels, num_channels, 324 max_channels, band); 325 return (wifi_error) command.requestResponse(); 326 } 327 ///////////////////////////////////////////////////////////////////////////// 328 329 /* helper functions */ 330 331 static int parseScanResults(wifi_scan_result *results, int num, nlattr *attr) 332 { 333 memset(results, 0, sizeof(wifi_scan_result) * num); 334 335 int i = 0; 336 for (nl_iterator it(attr); it.has_next() && i < num; it.next(), i++) { 337 338 int index = it.get_type(); 339 ALOGI("retrieved scan result %d", index); 340 nlattr *sc_data = (nlattr *) it.get_data(); 341 wifi_scan_result *result = results + i; 342 343 for (nl_iterator it2(sc_data); it2.has_next(); it2.next()) { 344 int type = it2.get_type(); 345 if (type == GSCAN_ATTRIBUTE_SSID) { 346 strncpy(result->ssid, (char *) it2.get_data(), it2.get_len()); 347 result->ssid[it2.get_len()] = 0; 348 } else if (type == GSCAN_ATTRIBUTE_BSSID) { 349 memcpy(result->bssid, (byte *) it2.get_data(), sizeof(mac_addr)); 350 } else if (type == GSCAN_ATTRIBUTE_TIMESTAMP) { 351 result->ts = it2.get_u64(); 352 } else if (type == GSCAN_ATTRIBUTE_CHANNEL) { 353 result->ts = it2.get_u16(); 354 } else if (type == GSCAN_ATTRIBUTE_RSSI) { 355 result->rssi = it2.get_u8(); 356 } else if (type == GSCAN_ATTRIBUTE_RTT) { 357 result->rtt = it2.get_u64(); 358 } else if (type == GSCAN_ATTRIBUTE_RTTSD) { 359 result->rtt_sd = it2.get_u64(); 360 } 361 } 362 363 } 364 365 if (i >= num) { 366 ALOGE("Got too many results; skipping some"); 367 } 368 369 return i; 370 } 371 372 int createFeatureRequest(WifiRequest& request, int subcmd, int enable) { 373 374 int result = request.create(GOOGLE_OUI, subcmd); 375 if (result < 0) { 376 return result; 377 } 378 379 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 380 result = request.put_u32(GSCAN_ATTRIBUTE_ENABLE_FEATURE, enable); 381 if (result < 0) { 382 return result; 383 } 384 385 request.attr_end(data); 386 return WIFI_SUCCESS; 387 } 388 389 ///////////////////////////////////////////////////////////////////////////// 390 class FullScanResultsCommand : public WifiCommand 391 { 392 int *mParams; 393 wifi_scan_result_handler mHandler; 394 public: 395 FullScanResultsCommand(wifi_interface_handle iface, int id, int *params, 396 wifi_scan_result_handler handler) 397 : WifiCommand("FullScanResultsCommand", iface, id), mParams(params), mHandler(handler) 398 { } 399 400 int createRequest(WifiRequest& request, int subcmd, int enable) { 401 int result = request.create(GOOGLE_OUI, subcmd); 402 if (result < 0) { 403 return result; 404 } 405 406 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 407 result = request.put_u32(GSCAN_ENABLE_FULL_SCAN_RESULTS, enable); 408 if (result < 0) { 409 return result; 410 } 411 412 request.attr_end(data); 413 return WIFI_SUCCESS; 414 415 } 416 417 int start() { 418 ALOGV("Enabling Full scan results"); 419 WifiRequest request(familyId(), ifaceId()); 420 int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 1); 421 if (result != WIFI_SUCCESS) { 422 ALOGE("failed to create request; result = %d", result); 423 return result; 424 } 425 426 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 427 428 result = requestResponse(request); 429 if (result != WIFI_SUCCESS) { 430 ALOGE("failed to enable full scan results; result = %d", result); 431 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 432 return result; 433 } 434 435 return result; 436 } 437 438 virtual int cancel() { 439 ALOGV("Disabling Full scan results"); 440 441 WifiRequest request(familyId(), ifaceId()); 442 int result = createRequest(request, GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, 0); 443 if (result != WIFI_SUCCESS) { 444 ALOGE("failed to create request; result = %d", result); 445 } else { 446 result = requestResponse(request); 447 if (result != WIFI_SUCCESS) { 448 ALOGE("failed to disable full scan results;result = %d", result); 449 } 450 } 451 452 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 453 return WIFI_SUCCESS; 454 } 455 456 virtual int handleResponse(WifiEvent& reply) { 457 ALOGD("Request complete!"); 458 /* Nothing to do on response! */ 459 return NL_SKIP; 460 } 461 462 virtual int handleEvent(WifiEvent& event) { 463 ALOGV("Full scan results: Got an event"); 464 return wifi_handle_full_scan_event(id(), event, mHandler); 465 } 466 467 }; 468 ///////////////////////////////////////////////////////////////////////////// 469 470 class ScanCommand : public WifiCommand 471 { 472 wifi_scan_cmd_params *mParams; 473 wifi_scan_result_handler mHandler; 474 public: 475 ScanCommand(wifi_interface_handle iface, int id, wifi_scan_cmd_params *params, 476 wifi_scan_result_handler handler) 477 : WifiCommand("ScanCommand", iface, id), mParams(params), mHandler(handler) 478 { } 479 480 int createSetupRequest(WifiRequest& request) { 481 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_CONFIG); 482 if (result < 0) { 483 return result; 484 } 485 486 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 487 result = request.put_u32(GSCAN_ATTRIBUTE_BASE_PERIOD, mParams->base_period); 488 if (result < 0) { 489 return result; 490 } 491 492 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_BUCKETS, mParams->num_buckets); 493 if (result < 0) { 494 return result; 495 } 496 497 for (int i = 0; i < mParams->num_buckets; i++) { 498 nlattr * bucket = request.attr_start(i); // next bucket 499 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_ID, mParams->buckets[i].bucket); 500 if (result < 0) { 501 return result; 502 } 503 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_PERIOD, mParams->buckets[i].period); 504 if (result < 0) { 505 return result; 506 } 507 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKETS_BAND, 508 mParams->buckets[i].band); 509 if (result < 0) { 510 return result; 511 } 512 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT, 513 mParams->buckets[i].step_count); 514 if (result < 0) { 515 return result; 516 } 517 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD, 518 mParams->buckets[i].max_period); 519 if (result < 0) { 520 return result; 521 } 522 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_EVENTS, 523 mParams->buckets[i].report_events); 524 if (result < 0) { 525 return result; 526 } 527 528 result = request.put_u32(GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, 529 mParams->buckets[i].num_channels); 530 if (result < 0) { 531 return result; 532 } 533 534 if (mParams->buckets[i].num_channels) { 535 nlattr *channels = request.attr_start(GSCAN_ATTRIBUTE_BUCKET_CHANNELS); 536 ALOGV(" channels: "); 537 for (int j = 0; j < mParams->buckets[i].num_channels; j++) { 538 result = request.put_u32(j, mParams->buckets[i].channels[j].channel); 539 ALOGV(" %u", mParams->buckets[i].channels[j].channel); 540 541 if (result < 0) { 542 return result; 543 } 544 } 545 request.attr_end(channels); 546 } 547 548 request.attr_end(bucket); 549 } 550 551 request.attr_end(data); 552 return WIFI_SUCCESS; 553 } 554 555 int createScanConfigRequest(WifiRequest& request) { 556 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SCAN_CONFIG); 557 if (result < 0) { 558 return result; 559 } 560 561 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 562 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, mParams->max_ap_per_scan); 563 if (result < 0) { 564 return result; 565 } 566 567 result = request.put_u32(GSCAN_ATTRIBUTE_REPORT_THRESHOLD, 568 mParams->report_threshold_percent); 569 if (result < 0) { 570 return result; 571 } 572 573 int num_scans = mParams->report_threshold_num_scans; 574 575 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, num_scans); 576 if (result < 0) { 577 return result; 578 } 579 580 request.attr_end(data); 581 return WIFI_SUCCESS; 582 } 583 584 int createStartRequest(WifiRequest& request) { 585 return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 586 } 587 588 int createStopRequest(WifiRequest& request) { 589 return createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 0); 590 } 591 592 int start() { 593 ALOGV("GSCAN start"); 594 WifiRequest request(familyId(), ifaceId()); 595 int result = createSetupRequest(request); 596 if (result != WIFI_SUCCESS) { 597 ALOGE("failed to create setup request; result = %d", result); 598 return result; 599 } 600 601 result = requestResponse(request); 602 if (result != WIFI_SUCCESS) { 603 ALOGE("failed to configure setup; result = %d", result); 604 return result; 605 } 606 607 request.destroy(); 608 609 result = createScanConfigRequest(request); 610 if (result != WIFI_SUCCESS) { 611 ALOGE("failed to create scan config request; result = %d", result); 612 return result; 613 } 614 615 result = requestResponse(request); 616 if (result != WIFI_SUCCESS) { 617 ALOGE("failed to configure scan; result = %d", result); 618 return result; 619 } 620 621 ALOGV(" ....starting scan"); 622 623 result = createStartRequest(request); 624 if (result != WIFI_SUCCESS) { 625 ALOGE("failed to create start request; result = %d", result); 626 return result; 627 } 628 629 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 630 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); 631 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 632 633 result = requestResponse(request); 634 if (result != WIFI_SUCCESS) { 635 ALOGE("failed to start scan; result = %d", result); 636 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); 637 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 638 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 639 return result; 640 } 641 return result; 642 } 643 644 virtual int cancel() { 645 ALOGV("Stopping scan"); 646 647 WifiRequest request(familyId(), ifaceId()); 648 int result = createStopRequest(request); 649 if (result != WIFI_SUCCESS) { 650 ALOGE("failed to create stop request; result = %d", result); 651 } else { 652 result = requestResponse(request); 653 if (result != WIFI_SUCCESS) { 654 ALOGE("failed to stop scan; result = %d", result); 655 } 656 } 657 658 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_COMPLETE_SCAN); 659 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE); 660 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_FULL_SCAN_RESULTS); 661 return WIFI_SUCCESS; 662 } 663 664 virtual int handleResponse(WifiEvent& reply) { 665 /* Nothing to do on response! */ 666 return NL_SKIP; 667 } 668 669 virtual int handleEvent(WifiEvent& event) { 670 ALOGV("Got a scan results event"); 671 //event.log(); 672 673 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 674 int len = event.get_vendor_data_len(); 675 int event_id = event.get_vendor_subcmd(); 676 677 if ((event_id == GSCAN_EVENT_COMPLETE_SCAN) || 678 (event_id == GSCAN_EVENT_SCAN_RESULTS_AVAILABLE)) { 679 if (vendor_data == NULL || len != 4) { 680 ALOGI("Bad event data!"); 681 return NL_SKIP; 682 } 683 wifi_scan_event evt_type; 684 evt_type = (wifi_scan_event) event.get_u32(NL80211_ATTR_VENDOR_DATA); 685 ALOGV("Received event type %d", evt_type); 686 if(*mHandler.on_scan_event) 687 (*mHandler.on_scan_event)(id(), evt_type); 688 } else if (event_id == GSCAN_EVENT_FULL_SCAN_RESULTS) { 689 wifi_handle_full_scan_event(id(), event, mHandler); 690 } 691 return NL_SKIP; 692 } 693 }; 694 695 wifi_error wifi_start_gscan( 696 wifi_request_id id, 697 wifi_interface_handle iface, 698 wifi_scan_cmd_params params, 699 wifi_scan_result_handler handler) 700 { 701 wifi_handle handle = getWifiHandle(iface); 702 703 ALOGV("Starting GScan, halHandle = %p", handle); 704 705 ScanCommand *cmd = new ScanCommand(iface, id, ¶ms, handler); 706 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 707 wifi_error result = wifi_register_cmd(handle, id, cmd); 708 if (result != WIFI_SUCCESS) { 709 cmd->releaseRef(); 710 return result; 711 } 712 result = (wifi_error)cmd->start(); 713 if (result != WIFI_SUCCESS) { 714 wifi_unregister_cmd(handle, id); 715 cmd->releaseRef(); 716 return result; 717 } 718 return result; 719 } 720 721 wifi_error wifi_stop_gscan(wifi_request_id id, wifi_interface_handle iface) 722 { 723 wifi_handle handle = getWifiHandle(iface); 724 ALOGV("Stopping GScan, wifi_request_id = %d, halHandle = %p", id, handle); 725 726 if (id == -1) { 727 wifi_scan_result_handler handler; 728 wifi_scan_cmd_params dummy_params; 729 wifi_handle handle = getWifiHandle(iface); 730 memset(&handler, 0, sizeof(handler)); 731 732 ScanCommand *cmd = new ScanCommand(iface, id, &dummy_params, handler); 733 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 734 cmd->cancel(); 735 cmd->releaseRef(); 736 return WIFI_SUCCESS; 737 } 738 739 return wifi_cancel_cmd(id, iface); 740 } 741 742 wifi_error wifi_enable_full_scan_results( 743 wifi_request_id id, 744 wifi_interface_handle iface, 745 wifi_scan_result_handler handler) 746 { 747 wifi_handle handle = getWifiHandle(iface); 748 int params_dummy; 749 750 ALOGV("Enabling full scan results, halHandle = %p", handle); 751 752 FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, id, ¶ms_dummy, handler); 753 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 754 wifi_error result = wifi_register_cmd(handle, id, cmd); 755 if (result != WIFI_SUCCESS) { 756 cmd->releaseRef(); 757 return result; 758 } 759 result = (wifi_error)cmd->start(); 760 if (result != WIFI_SUCCESS) { 761 wifi_unregister_cmd(handle, id); 762 cmd->releaseRef(); 763 return result; 764 } 765 return result; 766 } 767 768 int wifi_handle_full_scan_event( 769 wifi_request_id id, 770 WifiEvent& event, 771 wifi_scan_result_handler handler) 772 { 773 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 774 unsigned int len = event.get_vendor_data_len(); 775 776 if (vendor_data == NULL || len < sizeof(wifi_gscan_full_result_t)) { 777 ALOGI("Full scan results: No scan results found"); 778 return NL_SKIP; 779 } 780 781 wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data(); 782 /* To protect against corrupted data, put a ceiling */ 783 int ie_len = min(MAX_PROBE_RESP_IE_LEN, drv_res->ie_length); 784 wifi_scan_result *full_scan_result; 785 wifi_gscan_result_t *fixed = &drv_res->fixed; 786 787 if ((ie_len + offsetof(wifi_gscan_full_result_t, ie_data)) > len) { 788 ALOGE("BAD event data, len %d ie_len %d fixed length %d!\n", len, 789 ie_len, offsetof(wifi_gscan_full_result_t, ie_data)); 790 return NL_SKIP; 791 } 792 full_scan_result = (wifi_scan_result *) malloc((ie_len + offsetof(wifi_scan_result, ie_data))); 793 if (!full_scan_result) { 794 ALOGE("Full scan results: Can't malloc!\n"); 795 return NL_SKIP; 796 } 797 convert_to_hal_result(full_scan_result, fixed); 798 full_scan_result->ie_length = ie_len; 799 memcpy(full_scan_result->ie_data, drv_res->ie_data, ie_len); 800 if(handler.on_full_scan_result) 801 handler.on_full_scan_result(id, full_scan_result, drv_res->scan_ch_bucket); 802 803 ALOGV("Full scan result: %-32s %02x:%02x:%02x:%02x:%02x:%02x %d %d %lld %lld %lld %x %d\n", 804 fixed->ssid, fixed->bssid[0], fixed->bssid[1], fixed->bssid[2], fixed->bssid[3], 805 fixed->bssid[4], fixed->bssid[5], fixed->rssi, fixed->channel, fixed->ts, 806 fixed->rtt, fixed->rtt_sd, drv_res->scan_ch_bucket, drv_res->ie_length); 807 free(full_scan_result); 808 return NL_SKIP; 809 } 810 811 812 wifi_error wifi_disable_full_scan_results(wifi_request_id id, wifi_interface_handle iface) 813 { 814 ALOGV("Disabling full scan results"); 815 wifi_handle handle = getWifiHandle(iface); 816 817 if(id == -1) { 818 wifi_scan_result_handler handler; 819 wifi_handle handle = getWifiHandle(iface); 820 int params_dummy; 821 822 memset(&handler, 0, sizeof(handler)); 823 FullScanResultsCommand *cmd = new FullScanResultsCommand(iface, 0, ¶ms_dummy, handler); 824 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 825 cmd->cancel(); 826 cmd->releaseRef(); 827 return WIFI_SUCCESS; 828 } 829 830 return wifi_cancel_cmd(id, iface); 831 } 832 833 834 ///////////////////////////////////////////////////////////////////////////// 835 836 class GetScanResultsCommand : public WifiCommand { 837 wifi_cached_scan_results *mScans; 838 int mMax; 839 int *mNum; 840 int mRetrieved; 841 byte mFlush; 842 int mCompleted; 843 public: 844 GetScanResultsCommand(wifi_interface_handle iface, byte flush, 845 wifi_cached_scan_results *results, int max, int *num) 846 : WifiCommand("GetScanResultsCommand", iface, -1), mScans(results), mMax(max), mNum(num), 847 mRetrieved(0), mFlush(flush), mCompleted(0) 848 { } 849 850 int createRequest(WifiRequest& request, int num, byte flush) { 851 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_GET_SCAN_RESULTS); 852 if (result < 0) { 853 return result; 854 } 855 856 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 857 result = request.put_u32(GSCAN_ATTRIBUTE_NUM_OF_RESULTS, num); 858 if (result < 0) { 859 return result; 860 } 861 862 result = request.put_u8(GSCAN_ATTRIBUTE_FLUSH_RESULTS, flush); 863 if (result < 0) { 864 return result; 865 } 866 867 request.attr_end(data); 868 return WIFI_SUCCESS; 869 } 870 871 int execute() { 872 WifiRequest request(familyId(), ifaceId()); 873 ALOGV("retrieving %d scan results", mMax); 874 875 for (int i = 0; i < 10 && mRetrieved < mMax; i++) { 876 int num_to_retrieve = mMax - mRetrieved; 877 // ALOGI("retrieving %d scan results in one shot", num_to_retrieve); 878 int result = createRequest(request, num_to_retrieve, mFlush); 879 if (result < 0) { 880 ALOGE("failed to create request"); 881 return result; 882 } 883 884 int prev_retrieved = mRetrieved; 885 886 result = requestResponse(request); 887 888 if (result != WIFI_SUCCESS) { 889 ALOGE("failed to retrieve scan results; result = %d", result); 890 return result; 891 } 892 893 if (mRetrieved == prev_retrieved || mCompleted) { 894 /* no more items left to retrieve */ 895 break; 896 } 897 898 request.destroy(); 899 } 900 901 ALOGV("GetScanResults read %d results", mRetrieved); 902 *mNum = mRetrieved; 903 return WIFI_SUCCESS; 904 } 905 906 virtual int handleResponse(WifiEvent& reply) { 907 ALOGV("In GetScanResultsCommand::handleResponse"); 908 909 if (reply.get_cmd() != NL80211_CMD_VENDOR) { 910 ALOGD("Ignoring reply with cmd = %d", reply.get_cmd()); 911 return NL_SKIP; 912 } 913 914 int id = reply.get_vendor_id(); 915 int subcmd = reply.get_vendor_subcmd(); 916 917 ALOGV("Id = %0x, subcmd = %d", id, subcmd); 918 919 /* 920 if (subcmd != GSCAN_SUBCMD_SCAN_RESULTS) { 921 ALOGE("Invalid response to GetScanResultsCommand; ignoring it"); 922 return NL_SKIP; 923 } 924 */ 925 926 nlattr *vendor_data = reply.get_attribute(NL80211_ATTR_VENDOR_DATA); 927 int len = reply.get_vendor_data_len(); 928 929 if (vendor_data == NULL || len == 0) { 930 ALOGE("no vendor data in GetScanResults response; ignoring it"); 931 return NL_SKIP; 932 } 933 934 for (nl_iterator it(vendor_data); it.has_next(); it.next()) { 935 if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE) { 936 mCompleted = it.get_u8(); 937 ALOGV("retrieved mCompleted flag : %d", mCompleted); 938 } else if (it.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS || it.get_type() == 0) { 939 int scan_id = 0, flags = 0, num = 0, scan_ch_bucket_mask = 0; 940 for (nl_iterator it2(it.get()); it2.has_next(); it2.next()) { 941 if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_ID) { 942 scan_id = it2.get_u32(); 943 ALOGV("retrieved scan_id : 0x%0x", scan_id); 944 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_FLAGS) { 945 flags = it2.get_u8(); 946 ALOGV("retrieved scan_flags : 0x%0x", flags); 947 } else if (it2.get_type() == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { 948 num = it2.get_u32(); 949 ALOGV("retrieved num_results: %d", num); 950 } else if (it2.get_type() == GSCAN_ATTRIBUTE_CH_BUCKET_BITMASK) { 951 scan_ch_bucket_mask = it2.get_u32(); 952 ALOGD("retrieved scan_ch_bucket_mask: %x", scan_ch_bucket_mask); 953 } else if (it2.get_type() == GSCAN_ATTRIBUTE_SCAN_RESULTS && num) { 954 if (mRetrieved >= mMax) { 955 ALOGW("Stored %d scans, ignoring excess results", mRetrieved); 956 break; 957 } 958 num = min(num, (int)(it2.get_len()/sizeof(wifi_gscan_result))); 959 num = min(num, (int)MAX_AP_CACHE_PER_SCAN); 960 ALOGV("Copying %d scan results", num); 961 wifi_gscan_result_t *results = (wifi_gscan_result_t *)it2.get_data(); 962 wifi_scan_result *mScanResults = mScans[mRetrieved].results; 963 964 for (int i = 0; i < num; i++) { 965 wifi_gscan_result_t *result = &results[i]; 966 convert_to_hal_result(&mScanResults[i], result); 967 mScanResults[i].ie_length = 0; 968 ALOGV("%02d %-32s %02x:%02x:%02x:%02x:%02x:%02x %04d", i, 969 result->ssid, result->bssid[0], result->bssid[1], result->bssid[2], 970 result->bssid[3], result->bssid[4], result->bssid[5], 971 result->rssi); 972 } 973 mScans[mRetrieved].scan_id = scan_id; 974 mScans[mRetrieved].flags = flags; 975 mScans[mRetrieved].num_results = num; 976 mScans[mRetrieved].buckets_scanned = scan_ch_bucket_mask; 977 ALOGV("Setting result of scan_id : 0x%0x", mScans[mRetrieved].scan_id); 978 mRetrieved++; 979 } else { 980 ALOGW("Ignoring invalid attribute type = %d, size = %d", 981 it.get_type(), it.get_len()); 982 } 983 } 984 } else { 985 ALOGW("Ignoring invalid attribute type = %d, size = %d", 986 it.get_type(), it.get_len()); 987 } 988 } 989 ALOGV("GetScanResults read %d results", mRetrieved); 990 return NL_OK; 991 } 992 }; 993 994 wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, byte flush, 995 int max, wifi_cached_scan_results *results, int *num) { 996 ALOGV("Getting cached scan results, iface handle = %p, num = %d", iface, *num); 997 998 GetScanResultsCommand *cmd = new GetScanResultsCommand(iface, flush, results, max, num); 999 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1000 wifi_error err = (wifi_error)cmd->execute(); 1001 cmd->releaseRef(); 1002 return err; 1003 } 1004 1005 ///////////////////////////////////////////////////////////////////////////// 1006 1007 class BssidHotlistCommand : public WifiCommand 1008 { 1009 private: 1010 wifi_bssid_hotlist_params mParams; 1011 wifi_hotlist_ap_found_handler mHandler; 1012 static const int MAX_RESULTS = 64; 1013 wifi_scan_result mResults[MAX_RESULTS]; 1014 public: 1015 BssidHotlistCommand(wifi_interface_handle handle, int id, 1016 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) 1017 : WifiCommand("BssidHotlistCommand", handle, id), mParams(params), mHandler(handler) 1018 { } 1019 1020 int createSetupRequest(WifiRequest& request) { 1021 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); 1022 if (result < 0) { 1023 return result; 1024 } 1025 1026 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1027 result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); 1028 if (result < 0) { 1029 return result; 1030 } 1031 1032 result = request.put_u32(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); 1033 if (result < 0) { 1034 return result; 1035 } 1036 1037 result = request.put_u32(GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT, mParams.num_bssid); 1038 if (result < 0) { 1039 return result; 1040 } 1041 1042 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); 1043 for (int i = 0; i < mParams.num_bssid; i++) { 1044 nlattr *attr2 = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_ELEM); 1045 if (attr2 == NULL) { 1046 return WIFI_ERROR_OUT_OF_MEMORY; 1047 } 1048 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); 1049 if (result < 0) { 1050 return result; 1051 } 1052 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); 1053 if (result < 0) { 1054 return result; 1055 } 1056 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); 1057 if (result < 0) { 1058 return result; 1059 } 1060 request.attr_end(attr2); 1061 } 1062 1063 request.attr_end(attr); 1064 request.attr_end(data); 1065 return result; 1066 } 1067 1068 int createTeardownRequest(WifiRequest& request) { 1069 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_HOTLIST); 1070 if (result < 0) { 1071 return result; 1072 } 1073 1074 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1075 result = request.put_u8(GSCAN_ATTRIBUTE_HOTLIST_FLUSH, 1); 1076 if (result < 0) { 1077 return result; 1078 } 1079 1080 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_HOTLIST_BSSIDS); 1081 request.attr_end(attr); 1082 request.attr_end(data); 1083 return result; 1084 } 1085 1086 int start() { 1087 ALOGI("Executing hotlist setup request, num = %d", mParams.num_bssid); 1088 WifiRequest request(familyId(), ifaceId()); 1089 int result = createSetupRequest(request); 1090 if (result < 0) { 1091 return result; 1092 } 1093 1094 result = requestResponse(request); 1095 if (result < 0) { 1096 ALOGI("Failed to execute hotlist setup request, result = %d", result); 1097 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); 1098 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); 1099 return result; 1100 } 1101 1102 ALOGI("Successfully set %d APs in the hotlist ", mParams.num_bssid); 1103 result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 1104 if (result < 0) { 1105 return result; 1106 } 1107 1108 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); 1109 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); 1110 1111 result = requestResponse(request); 1112 if (result < 0) { 1113 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); 1114 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); 1115 return result; 1116 } 1117 1118 ALOGI("successfully restarted the scan"); 1119 return result; 1120 } 1121 1122 virtual int cancel() { 1123 /* unregister event handler */ 1124 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_FOUND); 1125 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_HOTLIST_RESULTS_LOST); 1126 /* create set hotlist message with empty hotlist */ 1127 WifiRequest request(familyId(), ifaceId()); 1128 int result = createTeardownRequest(request); 1129 if (result < 0) { 1130 return result; 1131 } 1132 1133 result = requestResponse(request); 1134 if (result < 0) { 1135 return result; 1136 } 1137 1138 ALOGI("Successfully reset APs in current hotlist"); 1139 return result; 1140 } 1141 1142 virtual int handleResponse(WifiEvent& reply) { 1143 /* Nothing to do on response! */ 1144 return NL_SKIP; 1145 } 1146 1147 virtual int handleEvent(WifiEvent& event) { 1148 ALOGI("Hotlist AP event"); 1149 int event_id = event.get_vendor_subcmd(); 1150 // event.log(); 1151 1152 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 1153 int len = event.get_vendor_data_len(); 1154 1155 if (vendor_data == NULL || len == 0) { 1156 ALOGI("No scan results found"); 1157 return NL_SKIP; 1158 } 1159 1160 memset(mResults, 0, sizeof(wifi_scan_result) * MAX_RESULTS); 1161 1162 int num = len / sizeof(wifi_gscan_result_t); 1163 wifi_gscan_result_t *inp = (wifi_gscan_result_t *)event.get_vendor_data(); 1164 num = min(MAX_RESULTS, num); 1165 for (int i = 0; i < num; i++, inp++) { 1166 convert_to_hal_result(&(mResults[i]), inp); 1167 } 1168 1169 if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_FOUND) { 1170 ALOGI("FOUND %d hotlist APs", num); 1171 if (*mHandler.on_hotlist_ap_found) 1172 (*mHandler.on_hotlist_ap_found)(id(), num, mResults); 1173 } else if (event_id == GSCAN_EVENT_HOTLIST_RESULTS_LOST) { 1174 ALOGI("LOST %d hotlist APs", num); 1175 if (*mHandler.on_hotlist_ap_lost) 1176 (*mHandler.on_hotlist_ap_lost)(id(), num, mResults); 1177 } 1178 return NL_SKIP; 1179 } 1180 }; 1181 1182 class ePNOCommand : public WifiCommand 1183 { 1184 private: 1185 wifi_epno_params epno_params; 1186 wifi_epno_handler mHandler; 1187 wifi_scan_result mResults[MAX_EPNO_NETWORKS]; 1188 public: 1189 ePNOCommand(wifi_interface_handle handle, int id, 1190 const wifi_epno_params *params, wifi_epno_handler handler) 1191 : WifiCommand("ePNOCommand", handle, id), mHandler(handler) 1192 { 1193 if (params != NULL) { 1194 memcpy(&epno_params, params, sizeof(wifi_epno_params)); 1195 } else { 1196 memset(&epno_params, 0, sizeof(wifi_epno_params)); 1197 } 1198 } 1199 int createSetupRequest(WifiRequest& request) { 1200 char tmp_buf[DOT11_MAX_SSID_LEN + 1]; 1201 if (epno_params.num_networks > MAX_EPNO_NETWORKS) { 1202 ALOGE("wrong epno num_networks:%d", epno_params.num_networks); 1203 return WIFI_ERROR_INVALID_ARGS; 1204 } 1205 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID); 1206 if (result < 0) { 1207 return result; 1208 } 1209 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1210 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1); 1211 if (result < 0) { 1212 return result; 1213 } 1214 1215 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR, 1216 (u8)epno_params.min5GHz_rssi); 1217 if (result < 0) { 1218 return result; 1219 } 1220 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR, 1221 (u8)epno_params.min24GHz_rssi); 1222 if (result < 0) { 1223 return result; 1224 } 1225 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX, 1226 epno_params.initial_score_max); 1227 if (result < 0) { 1228 return result; 1229 } 1230 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS, 1231 epno_params.current_connection_bonus); 1232 if (result < 0) { 1233 return result; 1234 } 1235 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS, 1236 epno_params.same_network_bonus); 1237 if (result < 0) { 1238 return result; 1239 } 1240 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS, 1241 epno_params.secure_bonus); 1242 if (result < 0) { 1243 return result; 1244 } 1245 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_5G_BONUS, 1246 epno_params.band5GHz_bonus); 1247 if (result < 0) { 1248 return result; 1249 } 1250 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM, 1251 epno_params.num_networks); 1252 if (result < 0) { 1253 return result; 1254 } 1255 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST); 1256 wifi_epno_network *ssid_list = epno_params.networks; 1257 for (int i = 0; i < epno_params.num_networks; i++) { 1258 nlattr *attr2 = request.attr_start(i); 1259 if (attr2 == NULL) { 1260 return WIFI_ERROR_OUT_OF_MEMORY; 1261 } 1262 strlcpy(tmp_buf, ssid_list[i].ssid, sizeof(tmp_buf)); 1263 result = request.put(GSCAN_ATTRIBUTE_EPNO_SSID, tmp_buf, 1264 strlen(tmp_buf)); 1265 ALOGI("PNO network: SSID %s flags %x auth %x", tmp_buf, 1266 ssid_list[i].flags, 1267 ssid_list[i].auth_bit_field); 1268 if (result < 0) { 1269 return result; 1270 } 1271 result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_SSID_LEN, 1272 strlen(tmp_buf)); 1273 if (result < 0) { 1274 return result; 1275 } 1276 result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_FLAGS, ssid_list[i].flags); 1277 if (result < 0) { 1278 return result; 1279 } 1280 result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_AUTH, ssid_list[i].auth_bit_field); 1281 if (result < 0) { 1282 return result; 1283 } 1284 request.attr_end(attr2); 1285 } 1286 request.attr_end(attr); 1287 request.attr_end(data); 1288 return result; 1289 } 1290 1291 int createTeardownRequest(WifiRequest& request) { 1292 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID); 1293 if (result < 0) { 1294 return result; 1295 } 1296 1297 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1298 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1); 1299 if (result < 0) { 1300 return result; 1301 } 1302 request.attr_end(data); 1303 return result; 1304 } 1305 1306 int start() { 1307 ALOGI("Executing ePNO setup request, num = %d", epno_params.num_networks); 1308 WifiRequest request(familyId(), ifaceId()); 1309 int result = createSetupRequest(request); 1310 if (result < 0) { 1311 return result; 1312 } 1313 1314 result = requestResponse(request); 1315 if (result < 0) { 1316 ALOGI("Failed to execute ePNO setup request, result = %d", result); 1317 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); 1318 return result; 1319 } 1320 1321 ALOGI("Successfully set %d SSIDs for ePNO", epno_params.num_networks); 1322 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); 1323 ALOGI("successfully restarted the scan"); 1324 return result; 1325 } 1326 1327 virtual int cancel() { 1328 /* unregister event handler */ 1329 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); 1330 /* create set hotlist message with empty hotlist */ 1331 WifiRequest request(familyId(), ifaceId()); 1332 int result = createTeardownRequest(request); 1333 if (result < 0) { 1334 return result; 1335 } 1336 1337 result = requestResponse(request); 1338 if (result < 0) { 1339 return result; 1340 } 1341 1342 ALOGI("Successfully reset APs in current hotlist"); 1343 return result; 1344 } 1345 1346 virtual int handleResponse(WifiEvent& reply) { 1347 /* Nothing to do on response! */ 1348 return NL_SKIP; 1349 } 1350 1351 virtual int handleEvent(WifiEvent& event) { 1352 ALOGI("ePNO event"); 1353 int event_id = event.get_vendor_subcmd(); 1354 // event.log(); 1355 1356 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 1357 int len = event.get_vendor_data_len(); 1358 1359 if (vendor_data == NULL || len == 0) { 1360 ALOGI("No scan results found"); 1361 return NL_SKIP; 1362 } 1363 1364 memset(mResults, 0, sizeof(wifi_scan_result) * MAX_EPNO_NETWORKS); 1365 1366 unsigned int num = len / sizeof(wifi_pno_result_t); 1367 unsigned int i; 1368 num = min(MAX_EPNO_NETWORKS, num); 1369 wifi_pno_result_t *res = (wifi_pno_result_t *) event.get_vendor_data(); 1370 for (i = 0; i < num; i++) { 1371 if (res[i].flags == PNO_SSID_FOUND) { 1372 memcpy(mResults[i].ssid, res[i].ssid, res[i].ssid_len); 1373 memcpy(mResults[i].bssid, res[i].bssid, sizeof(mac_addr)); 1374 1375 mResults[i].ssid[res[i].ssid_len] = '\0'; 1376 mResults[i].channel = res[i].channel; 1377 mResults[i].rssi = res[i].rssi; 1378 } 1379 } 1380 if (*mHandler.on_network_found) 1381 (*mHandler.on_network_found)(id(), num, mResults); 1382 return NL_SKIP; 1383 } 1384 }; 1385 1386 wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, 1387 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) 1388 { 1389 wifi_handle handle = getWifiHandle(iface); 1390 1391 BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler); 1392 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1393 wifi_error result = wifi_register_cmd(handle, id, cmd); 1394 if (result != WIFI_SUCCESS) { 1395 cmd->releaseRef(); 1396 return result; 1397 } 1398 result = (wifi_error)cmd->start(); 1399 if (result != WIFI_SUCCESS) { 1400 wifi_unregister_cmd(handle, id); 1401 cmd->releaseRef(); 1402 return result; 1403 } 1404 return result; 1405 } 1406 1407 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface) 1408 { 1409 return wifi_cancel_cmd(id, iface); 1410 } 1411 1412 1413 ///////////////////////////////////////////////////////////////////////////// 1414 1415 class SignificantWifiChangeCommand : public WifiCommand 1416 { 1417 typedef struct { 1418 mac_addr bssid; // BSSID 1419 wifi_channel channel; // channel frequency in MHz 1420 int num_rssi; // number of rssi samples 1421 wifi_rssi rssi[8]; // RSSI history in db 1422 } wifi_significant_change_result_internal; 1423 1424 private: 1425 wifi_significant_change_params mParams; 1426 wifi_significant_change_handler mHandler; 1427 static const int MAX_RESULTS = 64; 1428 wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS]; 1429 wifi_significant_change_result *mResults[MAX_RESULTS]; 1430 public: 1431 SignificantWifiChangeCommand(wifi_interface_handle handle, int id, 1432 wifi_significant_change_params params, wifi_significant_change_handler handler) 1433 : WifiCommand("SignificantWifiChangeCommand", handle, id), mParams(params), 1434 mHandler(handler) 1435 { } 1436 1437 int createSetupRequest(WifiRequest& request) { 1438 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 1439 if (result < 0) { 1440 return result; 1441 } 1442 1443 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1444 result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 1445 if (result < 0) { 1446 return result; 1447 } 1448 result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size); 1449 if (result < 0) { 1450 return result; 1451 } 1452 result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); 1453 if (result < 0) { 1454 return result; 1455 } 1456 result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching); 1457 if (result < 0) { 1458 return result; 1459 } 1460 result = request.put_u16(GSCAN_ATTRIBUTE_NUM_BSSID, mParams.num_bssid); 1461 if (result < 0) { 1462 return result; 1463 } 1464 if (mParams.num_bssid != 0) { 1465 nlattr* attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS); 1466 if (attr == NULL) { 1467 return WIFI_ERROR_OUT_OF_MEMORY; 1468 } 1469 1470 for (int i = 0; i < mParams.num_bssid; i++) { 1471 nlattr* attr2 = request.attr_start(i); 1472 if (attr2 == NULL) { 1473 return WIFI_ERROR_OUT_OF_MEMORY; 1474 } 1475 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); 1476 if (result < 0) { 1477 return result; 1478 } 1479 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); 1480 if (result < 0) { 1481 return result; 1482 } 1483 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); 1484 if (result < 0) { 1485 return result; 1486 } 1487 request.attr_end(attr2); 1488 } 1489 1490 request.attr_end(attr); 1491 } 1492 request.attr_end(data); 1493 1494 return result; 1495 } 1496 1497 int createTeardownRequest(WifiRequest& request) { 1498 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 1499 if (result < 0) { 1500 return result; 1501 } 1502 1503 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1504 result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 1505 if (result < 0) { 1506 return result; 1507 } 1508 1509 request.attr_end(data); 1510 return result; 1511 } 1512 1513 int start() { 1514 ALOGI("Set significant wifi change config"); 1515 WifiRequest request(familyId(), ifaceId()); 1516 1517 int result = createSetupRequest(request); 1518 if (result < 0) { 1519 return result; 1520 } 1521 1522 result = requestResponse(request); 1523 if (result < 0) { 1524 ALOGI("failed to set significant wifi change config %d", result); 1525 return result; 1526 } 1527 1528 ALOGI("successfully set significant wifi change config"); 1529 1530 result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 1531 if (result < 0) { 1532 return result; 1533 } 1534 1535 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 1536 1537 result = requestResponse(request); 1538 if (result < 0) { 1539 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 1540 return result; 1541 } 1542 1543 ALOGI("successfully restarted the scan"); 1544 return result; 1545 } 1546 1547 virtual int cancel() { 1548 /* unregister event handler */ 1549 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 1550 1551 /* create set significant change monitor message with empty hotlist */ 1552 WifiRequest request(familyId(), ifaceId()); 1553 1554 int result = createTeardownRequest(request); 1555 if (result < 0) { 1556 return result; 1557 } 1558 1559 result = requestResponse(request); 1560 if (result < 0) { 1561 return result; 1562 } 1563 1564 ALOGI("successfully reset significant wifi change config"); 1565 return result; 1566 } 1567 1568 virtual int handleResponse(WifiEvent& reply) { 1569 /* Nothing to do on response! */ 1570 return NL_SKIP; 1571 } 1572 1573 virtual int handleEvent(WifiEvent& event) { 1574 ALOGV("Got a significant wifi change event"); 1575 1576 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 1577 int len = event.get_vendor_data_len(); 1578 1579 if (vendor_data == NULL || len == 0) { 1580 ALOGI("No scan results found"); 1581 return NL_SKIP; 1582 } 1583 1584 typedef struct { 1585 uint16_t flags; 1586 uint16_t channel; 1587 mac_addr bssid; 1588 s8 rssi_history[8]; 1589 } ChangeInfo; 1590 1591 int num = min(len / sizeof(ChangeInfo), MAX_RESULTS); 1592 ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data(); 1593 1594 for (int i = 0; i < num; i++) { 1595 memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr)); 1596 mResultsBuffer[i].channel = ci[i].channel; 1597 mResultsBuffer[i].num_rssi = 8; 1598 for (int j = 0; j < mResultsBuffer[i].num_rssi; j++) 1599 mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j]; 1600 mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i])); 1601 } 1602 1603 ALOGV("Retrieved %d scan results", num); 1604 1605 if (num != 0) { 1606 (*mHandler.on_significant_change)(id(), num, mResults); 1607 } else { 1608 ALOGW("No significant change reported"); 1609 } 1610 1611 return NL_SKIP; 1612 } 1613 }; 1614 1615 wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, 1616 wifi_significant_change_params params, wifi_significant_change_handler handler) 1617 { 1618 wifi_handle handle = getWifiHandle(iface); 1619 1620 SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand( 1621 iface, id, params, handler); 1622 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1623 wifi_error result = wifi_register_cmd(handle, id, cmd); 1624 if (result != WIFI_SUCCESS) { 1625 cmd->releaseRef(); 1626 return result; 1627 } 1628 result = (wifi_error)cmd->start(); 1629 if (result != WIFI_SUCCESS) { 1630 wifi_unregister_cmd(handle, id); 1631 cmd->releaseRef(); 1632 return result; 1633 } 1634 return result; 1635 } 1636 1637 wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface) 1638 { 1639 return wifi_cancel_cmd(id, iface); 1640 } 1641 1642 wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface) 1643 { 1644 if (id == -1) { 1645 wifi_epno_handler handler; 1646 wifi_handle handle = getWifiHandle(iface); 1647 1648 memset(&handler, 0, sizeof(handler)); 1649 ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler); 1650 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1651 cmd->cancel(); 1652 cmd->releaseRef(); 1653 return WIFI_SUCCESS; 1654 } 1655 return wifi_cancel_cmd(id, iface); 1656 } 1657 1658 wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface, 1659 const wifi_epno_params *params, wifi_epno_handler handler) 1660 { 1661 wifi_handle handle = getWifiHandle(iface); 1662 1663 ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler); 1664 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1665 wifi_error result = wifi_register_cmd(handle, id, cmd); 1666 if (result != WIFI_SUCCESS) { 1667 cmd->releaseRef(); 1668 return result; 1669 } 1670 result = (wifi_error)cmd->start(); 1671 if (result != WIFI_SUCCESS) { 1672 wifi_unregister_cmd(handle, id); 1673 cmd->releaseRef(); 1674 return result; 1675 } 1676 return result; 1677 } 1678 1679 1680 //////////////////////////////////////////////////////////////////////////////// 1681 1682 class AnqpoConfigureCommand : public WifiCommand 1683 { 1684 int num_hs; 1685 wifi_passpoint_network *mNetworks; 1686 wifi_passpoint_event_handler mHandler; 1687 wifi_scan_result *mResult; 1688 public: 1689 AnqpoConfigureCommand(wifi_request_id id, wifi_interface_handle iface, 1690 int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler) 1691 : WifiCommand("AnqpoConfigureCommand", iface, id), num_hs(num), mNetworks(hs_list), 1692 mHandler(handler) 1693 { 1694 mResult = NULL; 1695 } 1696 1697 int createRequest(WifiRequest& request, int val) { 1698 1699 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_ANQPO_CONFIG); 1700 result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, num_hs); 1701 if (result < 0) { 1702 return result; 1703 } 1704 1705 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1706 1707 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST); 1708 for (int i = 0; i < num_hs; i++) { 1709 nlattr *attr2 = request.attr_start(i); 1710 if (attr2 == NULL) { 1711 return WIFI_ERROR_OUT_OF_MEMORY; 1712 } 1713 result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, mNetworks[i].id); 1714 if (result < 0) { 1715 return result; 1716 } 1717 result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, mNetworks[i].realm, 256); 1718 if (result < 0) { 1719 return result; 1720 } 1721 result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID, 1722 mNetworks[i].roamingConsortiumIds, 128); 1723 if (result < 0) { 1724 return result; 1725 } 1726 result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, mNetworks[i].plmn, 3); 1727 if (result < 0) { 1728 return result; 1729 } 1730 1731 request.attr_end(attr2); 1732 } 1733 1734 request.attr_end(attr); 1735 request.attr_end(data); 1736 1737 return WIFI_SUCCESS; 1738 } 1739 1740 int start() { 1741 1742 WifiRequest request(familyId(), ifaceId()); 1743 int result = createRequest(request, num_hs); 1744 if (result != WIFI_SUCCESS) { 1745 ALOGE("failed to create request; result = %d", result); 1746 return result; 1747 } 1748 1749 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH); 1750 1751 result = requestResponse(request); 1752 if (result != WIFI_SUCCESS) { 1753 ALOGE("failed to set ANQPO networks; result = %d", result); 1754 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH); 1755 return result; 1756 } 1757 1758 return result; 1759 } 1760 1761 virtual int cancel() { 1762 1763 WifiRequest request(familyId(), ifaceId()); 1764 int result = createRequest(request, 0); 1765 if (result != WIFI_SUCCESS) { 1766 ALOGE("failed to create request; result = %d", result); 1767 } else { 1768 result = requestResponse(request); 1769 if (result != WIFI_SUCCESS) { 1770 ALOGE("failed to reset ANQPO networks;result = %d", result); 1771 } 1772 } 1773 1774 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH); 1775 return WIFI_SUCCESS; 1776 } 1777 1778 virtual int handleResponse(WifiEvent& reply) { 1779 ALOGD("Request complete!"); 1780 /* Nothing to do on response! */ 1781 return NL_SKIP; 1782 } 1783 1784 virtual int handleEvent(WifiEvent& event) { 1785 typedef struct { 1786 u16 channel; /* channel of GAS protocol */ 1787 u8 dialog_token; /* GAS dialog token */ 1788 u8 fragment_id; /* fragment id */ 1789 u16 status_code; /* status code on GAS completion */ 1790 u16 data_len; /* length of data to follow */ 1791 u8 data[1]; /* variable length specified by data_len */ 1792 } wifi_anqp_gas_resp; 1793 1794 ALOGI("ANQPO hotspot matched event!"); 1795 1796 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 1797 unsigned int len = event.get_vendor_data_len(); 1798 1799 if (vendor_data == NULL || len < sizeof(wifi_scan_result)) { 1800 ALOGI("No scan results found"); 1801 return NL_SKIP; 1802 } 1803 mResult = (wifi_scan_result *)malloc(sizeof(wifi_scan_result)); 1804 if (!mResult) { 1805 return NL_SKIP; 1806 } 1807 wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data(); 1808 wifi_gscan_result_t *fixed = &drv_res->fixed; 1809 convert_to_hal_result(mResult, fixed); 1810 1811 byte *anqp = (byte *)drv_res + offsetof(wifi_gscan_full_result_t, ie_data) + drv_res->ie_length; 1812 wifi_anqp_gas_resp *gas = (wifi_anqp_gas_resp *)anqp; 1813 int anqp_len = offsetof(wifi_anqp_gas_resp, data) + gas->data_len; 1814 int networkId = *(int *)((byte *)anqp + anqp_len); 1815 1816 ALOGI("%-32s\t", mResult->ssid); 1817 1818 ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1], 1819 mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]); 1820 1821 ALOGI("%d\t", mResult->rssi); 1822 ALOGI("%d\t", mResult->channel); 1823 ALOGI("%lld\t", mResult->ts); 1824 ALOGI("%lld\t", mResult->rtt); 1825 ALOGI("%lld\n", mResult->rtt_sd); 1826 1827 if(*mHandler.on_passpoint_network_found) 1828 (*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp); 1829 free(mResult); 1830 return NL_SKIP; 1831 } 1832 }; 1833 1834 wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num, 1835 wifi_passpoint_network *networks, wifi_passpoint_event_handler handler) 1836 { 1837 wifi_handle handle = getWifiHandle(iface); 1838 1839 AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler); 1840 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1841 wifi_error result = wifi_register_cmd(handle, id, cmd); 1842 if (result != WIFI_SUCCESS) { 1843 cmd->releaseRef(); 1844 return result; 1845 } 1846 result = (wifi_error)cmd->start(); 1847 if (result != WIFI_SUCCESS) { 1848 wifi_unregister_cmd(handle, id); 1849 cmd->releaseRef(); 1850 return result; 1851 } 1852 return result; 1853 } 1854 1855 wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface) 1856 { 1857 return wifi_cancel_cmd(id, iface); 1858 } 1859