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 if (epno_params.num_networks > MAX_EPNO_NETWORKS) { 1201 ALOGE("wrong epno num_networks:%d", epno_params.num_networks); 1202 return WIFI_ERROR_INVALID_ARGS; 1203 } 1204 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID); 1205 if (result < 0) { 1206 return result; 1207 } 1208 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1209 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1); 1210 if (result < 0) { 1211 return result; 1212 } 1213 1214 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_5G_RSSI_THR, 1215 (u8)epno_params.min5GHz_rssi); 1216 if (result < 0) { 1217 return result; 1218 } 1219 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_2G_RSSI_THR, 1220 (u8)epno_params.min24GHz_rssi); 1221 if (result < 0) { 1222 return result; 1223 } 1224 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_INIT_SCORE_MAX, 1225 epno_params.initial_score_max); 1226 if (result < 0) { 1227 return result; 1228 } 1229 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_CUR_CONN_BONUS, 1230 epno_params.current_connection_bonus); 1231 if (result < 0) { 1232 return result; 1233 } 1234 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SAME_NETWORK_BONUS, 1235 epno_params.same_network_bonus); 1236 if (result < 0) { 1237 return result; 1238 } 1239 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_SECURE_BONUS, 1240 epno_params.secure_bonus); 1241 if (result < 0) { 1242 return result; 1243 } 1244 result = request.put_u16(GSCAN_ATTRIBUTE_EPNO_5G_BONUS, 1245 epno_params.band5GHz_bonus); 1246 if (result < 0) { 1247 return result; 1248 } 1249 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_SSID_NUM, 1250 epno_params.num_networks); 1251 if (result < 0) { 1252 return result; 1253 } 1254 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_EPNO_SSID_LIST); 1255 wifi_epno_network *ssid_list = epno_params.networks; 1256 for (int i = 0; i < epno_params.num_networks; i++) { 1257 nlattr *attr2 = request.attr_start(i); 1258 if (attr2 == NULL) { 1259 return WIFI_ERROR_OUT_OF_MEMORY; 1260 } 1261 result = request.put(GSCAN_ATTRIBUTE_EPNO_SSID, ssid_list[i].ssid, DOT11_MAX_SSID_LEN); 1262 ALOGI("PNO network: SSID %s flags %x auth %x", ssid_list[i].ssid, 1263 ssid_list[i].flags, 1264 ssid_list[i].auth_bit_field); 1265 if (result < 0) { 1266 return result; 1267 } 1268 result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_SSID_LEN, strlen(ssid_list[i].ssid)); 1269 if (result < 0) { 1270 return result; 1271 } 1272 result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_FLAGS, ssid_list[i].flags); 1273 if (result < 0) { 1274 return result; 1275 } 1276 result = request.put_u32(GSCAN_ATTRIBUTE_EPNO_AUTH, ssid_list[i].auth_bit_field); 1277 if (result < 0) { 1278 return result; 1279 } 1280 request.attr_end(attr2); 1281 } 1282 request.attr_end(attr); 1283 request.attr_end(data); 1284 return result; 1285 } 1286 1287 int createTeardownRequest(WifiRequest& request) { 1288 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_EPNO_SSID); 1289 if (result < 0) { 1290 return result; 1291 } 1292 1293 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1294 result = request.put_u8(GSCAN_ATTRIBUTE_EPNO_FLUSH, 1); 1295 if (result < 0) { 1296 return result; 1297 } 1298 request.attr_end(data); 1299 return result; 1300 } 1301 1302 int start() { 1303 ALOGI("Executing ePNO setup request, num = %d", epno_params.num_networks); 1304 WifiRequest request(familyId(), ifaceId()); 1305 int result = createSetupRequest(request); 1306 if (result < 0) { 1307 return result; 1308 } 1309 1310 result = requestResponse(request); 1311 if (result < 0) { 1312 ALOGI("Failed to execute ePNO setup request, result = %d", result); 1313 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); 1314 return result; 1315 } 1316 1317 ALOGI("Successfully set %d SSIDs for ePNO", epno_params.num_networks); 1318 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); 1319 ALOGI("successfully restarted the scan"); 1320 return result; 1321 } 1322 1323 virtual int cancel() { 1324 /* unregister event handler */ 1325 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_EPNO_EVENT); 1326 /* create set hotlist message with empty hotlist */ 1327 WifiRequest request(familyId(), ifaceId()); 1328 int result = createTeardownRequest(request); 1329 if (result < 0) { 1330 return result; 1331 } 1332 1333 result = requestResponse(request); 1334 if (result < 0) { 1335 return result; 1336 } 1337 1338 ALOGI("Successfully reset APs in current hotlist"); 1339 return result; 1340 } 1341 1342 virtual int handleResponse(WifiEvent& reply) { 1343 /* Nothing to do on response! */ 1344 return NL_SKIP; 1345 } 1346 1347 virtual int handleEvent(WifiEvent& event) { 1348 ALOGI("ePNO event"); 1349 int event_id = event.get_vendor_subcmd(); 1350 // event.log(); 1351 1352 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 1353 int len = event.get_vendor_data_len(); 1354 1355 if (vendor_data == NULL || len == 0) { 1356 ALOGI("No scan results found"); 1357 return NL_SKIP; 1358 } 1359 1360 memset(mResults, 0, sizeof(wifi_scan_result) * MAX_EPNO_NETWORKS); 1361 1362 unsigned int num = len / sizeof(wifi_pno_result_t); 1363 unsigned int i; 1364 num = min(MAX_EPNO_NETWORKS, num); 1365 wifi_pno_result_t *res = (wifi_pno_result_t *) event.get_vendor_data(); 1366 for (i = 0; i < num; i++) { 1367 if (res[i].flags == PNO_SSID_FOUND) { 1368 memcpy(mResults[i].ssid, res[i].ssid, res[i].ssid_len); 1369 memcpy(mResults[i].bssid, res[i].bssid, sizeof(mac_addr)); 1370 1371 mResults[i].ssid[res[i].ssid_len] = '\0'; 1372 mResults[i].channel = res[i].channel; 1373 mResults[i].rssi = res[i].rssi; 1374 } 1375 } 1376 if (*mHandler.on_network_found) 1377 (*mHandler.on_network_found)(id(), num, mResults); 1378 return NL_SKIP; 1379 } 1380 }; 1381 1382 wifi_error wifi_set_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface, 1383 wifi_bssid_hotlist_params params, wifi_hotlist_ap_found_handler handler) 1384 { 1385 wifi_handle handle = getWifiHandle(iface); 1386 1387 BssidHotlistCommand *cmd = new BssidHotlistCommand(iface, id, params, handler); 1388 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1389 wifi_error result = wifi_register_cmd(handle, id, cmd); 1390 if (result != WIFI_SUCCESS) { 1391 cmd->releaseRef(); 1392 return result; 1393 } 1394 result = (wifi_error)cmd->start(); 1395 if (result != WIFI_SUCCESS) { 1396 wifi_unregister_cmd(handle, id); 1397 cmd->releaseRef(); 1398 return result; 1399 } 1400 return result; 1401 } 1402 1403 wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, wifi_interface_handle iface) 1404 { 1405 return wifi_cancel_cmd(id, iface); 1406 } 1407 1408 1409 ///////////////////////////////////////////////////////////////////////////// 1410 1411 class SignificantWifiChangeCommand : public WifiCommand 1412 { 1413 typedef struct { 1414 mac_addr bssid; // BSSID 1415 wifi_channel channel; // channel frequency in MHz 1416 int num_rssi; // number of rssi samples 1417 wifi_rssi rssi[8]; // RSSI history in db 1418 } wifi_significant_change_result_internal; 1419 1420 private: 1421 wifi_significant_change_params mParams; 1422 wifi_significant_change_handler mHandler; 1423 static const int MAX_RESULTS = 64; 1424 wifi_significant_change_result_internal mResultsBuffer[MAX_RESULTS]; 1425 wifi_significant_change_result *mResults[MAX_RESULTS]; 1426 public: 1427 SignificantWifiChangeCommand(wifi_interface_handle handle, int id, 1428 wifi_significant_change_params params, wifi_significant_change_handler handler) 1429 : WifiCommand("SignificantWifiChangeCommand", handle, id), mParams(params), 1430 mHandler(handler) 1431 { } 1432 1433 int createSetupRequest(WifiRequest& request) { 1434 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 1435 if (result < 0) { 1436 return result; 1437 } 1438 1439 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1440 result = request.put_u8(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 1441 if (result < 0) { 1442 return result; 1443 } 1444 result = request.put_u16(GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE, mParams.rssi_sample_size); 1445 if (result < 0) { 1446 return result; 1447 } 1448 result = request.put_u16(GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, mParams.lost_ap_sample_size); 1449 if (result < 0) { 1450 return result; 1451 } 1452 result = request.put_u16(GSCAN_ATTRIBUTE_MIN_BREACHING, mParams.min_breaching); 1453 if (result < 0) { 1454 return result; 1455 } 1456 result = request.put_u16(GSCAN_ATTRIBUTE_NUM_BSSID, mParams.num_bssid); 1457 if (result < 0) { 1458 return result; 1459 } 1460 if (mParams.num_bssid != 0) { 1461 nlattr* attr = request.attr_start(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS); 1462 if (attr == NULL) { 1463 return WIFI_ERROR_OUT_OF_MEMORY; 1464 } 1465 1466 for (int i = 0; i < mParams.num_bssid; i++) { 1467 nlattr* attr2 = request.attr_start(i); 1468 if (attr2 == NULL) { 1469 return WIFI_ERROR_OUT_OF_MEMORY; 1470 } 1471 result = request.put_addr(GSCAN_ATTRIBUTE_BSSID, mParams.ap[i].bssid); 1472 if (result < 0) { 1473 return result; 1474 } 1475 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_HIGH, mParams.ap[i].high); 1476 if (result < 0) { 1477 return result; 1478 } 1479 result = request.put_u8(GSCAN_ATTRIBUTE_RSSI_LOW, mParams.ap[i].low); 1480 if (result < 0) { 1481 return result; 1482 } 1483 request.attr_end(attr2); 1484 } 1485 1486 request.attr_end(attr); 1487 } 1488 request.attr_end(data); 1489 1490 return result; 1491 } 1492 1493 int createTeardownRequest(WifiRequest& request) { 1494 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG); 1495 if (result < 0) { 1496 return result; 1497 } 1498 1499 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1500 result = request.put_u16(GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, 1); 1501 if (result < 0) { 1502 return result; 1503 } 1504 1505 request.attr_end(data); 1506 return result; 1507 } 1508 1509 int start() { 1510 ALOGI("Set significant wifi change config"); 1511 WifiRequest request(familyId(), ifaceId()); 1512 1513 int result = createSetupRequest(request); 1514 if (result < 0) { 1515 return result; 1516 } 1517 1518 result = requestResponse(request); 1519 if (result < 0) { 1520 ALOGI("failed to set significant wifi change config %d", result); 1521 return result; 1522 } 1523 1524 ALOGI("successfully set significant wifi change config"); 1525 1526 result = createFeatureRequest(request, GSCAN_SUBCMD_ENABLE_GSCAN, 1); 1527 if (result < 0) { 1528 return result; 1529 } 1530 1531 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 1532 1533 result = requestResponse(request); 1534 if (result < 0) { 1535 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 1536 return result; 1537 } 1538 1539 ALOGI("successfully restarted the scan"); 1540 return result; 1541 } 1542 1543 virtual int cancel() { 1544 /* unregister event handler */ 1545 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS); 1546 1547 /* create set significant change monitor message with empty hotlist */ 1548 WifiRequest request(familyId(), ifaceId()); 1549 1550 int result = createTeardownRequest(request); 1551 if (result < 0) { 1552 return result; 1553 } 1554 1555 result = requestResponse(request); 1556 if (result < 0) { 1557 return result; 1558 } 1559 1560 ALOGI("successfully reset significant wifi change config"); 1561 return result; 1562 } 1563 1564 virtual int handleResponse(WifiEvent& reply) { 1565 /* Nothing to do on response! */ 1566 return NL_SKIP; 1567 } 1568 1569 virtual int handleEvent(WifiEvent& event) { 1570 ALOGV("Got a significant wifi change event"); 1571 1572 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 1573 int len = event.get_vendor_data_len(); 1574 1575 if (vendor_data == NULL || len == 0) { 1576 ALOGI("No scan results found"); 1577 return NL_SKIP; 1578 } 1579 1580 typedef struct { 1581 uint16_t flags; 1582 uint16_t channel; 1583 mac_addr bssid; 1584 s8 rssi_history[8]; 1585 } ChangeInfo; 1586 1587 int num = min(len / sizeof(ChangeInfo), MAX_RESULTS); 1588 ChangeInfo *ci = (ChangeInfo *)event.get_vendor_data(); 1589 1590 for (int i = 0; i < num; i++) { 1591 memcpy(mResultsBuffer[i].bssid, ci[i].bssid, sizeof(mac_addr)); 1592 mResultsBuffer[i].channel = ci[i].channel; 1593 mResultsBuffer[i].num_rssi = 8; 1594 for (int j = 0; j < mResultsBuffer[i].num_rssi; j++) 1595 mResultsBuffer[i].rssi[j] = (int) ci[i].rssi_history[j]; 1596 mResults[i] = reinterpret_cast<wifi_significant_change_result *>(&(mResultsBuffer[i])); 1597 } 1598 1599 ALOGV("Retrieved %d scan results", num); 1600 1601 if (num != 0) { 1602 (*mHandler.on_significant_change)(id(), num, mResults); 1603 } else { 1604 ALOGW("No significant change reported"); 1605 } 1606 1607 return NL_SKIP; 1608 } 1609 }; 1610 1611 wifi_error wifi_set_significant_change_handler(wifi_request_id id, wifi_interface_handle iface, 1612 wifi_significant_change_params params, wifi_significant_change_handler handler) 1613 { 1614 wifi_handle handle = getWifiHandle(iface); 1615 1616 SignificantWifiChangeCommand *cmd = new SignificantWifiChangeCommand( 1617 iface, id, params, handler); 1618 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1619 wifi_error result = wifi_register_cmd(handle, id, cmd); 1620 if (result != WIFI_SUCCESS) { 1621 cmd->releaseRef(); 1622 return result; 1623 } 1624 result = (wifi_error)cmd->start(); 1625 if (result != WIFI_SUCCESS) { 1626 wifi_unregister_cmd(handle, id); 1627 cmd->releaseRef(); 1628 return result; 1629 } 1630 return result; 1631 } 1632 1633 wifi_error wifi_reset_significant_change_handler(wifi_request_id id, wifi_interface_handle iface) 1634 { 1635 return wifi_cancel_cmd(id, iface); 1636 } 1637 1638 wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface) 1639 { 1640 if (id == -1) { 1641 wifi_epno_handler handler; 1642 wifi_handle handle = getWifiHandle(iface); 1643 1644 memset(&handler, 0, sizeof(handler)); 1645 ePNOCommand *cmd = new ePNOCommand(iface, id, NULL, handler); 1646 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1647 cmd->cancel(); 1648 cmd->releaseRef(); 1649 return WIFI_SUCCESS; 1650 } 1651 return wifi_cancel_cmd(id, iface); 1652 } 1653 1654 wifi_error wifi_set_epno_list(wifi_request_id id, wifi_interface_handle iface, 1655 const wifi_epno_params *params, wifi_epno_handler handler) 1656 { 1657 wifi_handle handle = getWifiHandle(iface); 1658 1659 ePNOCommand *cmd = new ePNOCommand(iface, id, params, handler); 1660 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1661 wifi_error result = wifi_register_cmd(handle, id, cmd); 1662 if (result != WIFI_SUCCESS) { 1663 cmd->releaseRef(); 1664 return result; 1665 } 1666 result = (wifi_error)cmd->start(); 1667 if (result != WIFI_SUCCESS) { 1668 wifi_unregister_cmd(handle, id); 1669 cmd->releaseRef(); 1670 return result; 1671 } 1672 return result; 1673 } 1674 1675 1676 //////////////////////////////////////////////////////////////////////////////// 1677 1678 class AnqpoConfigureCommand : public WifiCommand 1679 { 1680 int num_hs; 1681 wifi_passpoint_network *mNetworks; 1682 wifi_passpoint_event_handler mHandler; 1683 wifi_scan_result *mResult; 1684 public: 1685 AnqpoConfigureCommand(wifi_request_id id, wifi_interface_handle iface, 1686 int num, wifi_passpoint_network *hs_list, wifi_passpoint_event_handler handler) 1687 : WifiCommand("AnqpoConfigureCommand", iface, id), num_hs(num), mNetworks(hs_list), 1688 mHandler(handler) 1689 { 1690 mResult = NULL; 1691 } 1692 1693 int createRequest(WifiRequest& request, int val) { 1694 1695 int result = request.create(GOOGLE_OUI, GSCAN_SUBCMD_ANQPO_CONFIG); 1696 result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE, num_hs); 1697 if (result < 0) { 1698 return result; 1699 } 1700 1701 nlattr *data = request.attr_start(NL80211_ATTR_VENDOR_DATA); 1702 1703 struct nlattr * attr = request.attr_start(GSCAN_ATTRIBUTE_ANQPO_HS_LIST); 1704 for (int i = 0; i < num_hs; i++) { 1705 nlattr *attr2 = request.attr_start(i); 1706 if (attr2 == NULL) { 1707 return WIFI_ERROR_OUT_OF_MEMORY; 1708 } 1709 result = request.put_u32(GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID, mNetworks[i].id); 1710 if (result < 0) { 1711 return result; 1712 } 1713 result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM, mNetworks[i].realm, 256); 1714 if (result < 0) { 1715 return result; 1716 } 1717 result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID, 1718 mNetworks[i].roamingConsortiumIds, 128); 1719 if (result < 0) { 1720 return result; 1721 } 1722 result = request.put(GSCAN_ATTRIBUTE_ANQPO_HS_PLMN, mNetworks[i].plmn, 3); 1723 if (result < 0) { 1724 return result; 1725 } 1726 1727 request.attr_end(attr2); 1728 } 1729 1730 request.attr_end(attr); 1731 request.attr_end(data); 1732 1733 return WIFI_SUCCESS; 1734 } 1735 1736 int start() { 1737 1738 WifiRequest request(familyId(), ifaceId()); 1739 int result = createRequest(request, num_hs); 1740 if (result != WIFI_SUCCESS) { 1741 ALOGE("failed to create request; result = %d", result); 1742 return result; 1743 } 1744 1745 registerVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH); 1746 1747 result = requestResponse(request); 1748 if (result != WIFI_SUCCESS) { 1749 ALOGE("failed to set ANQPO networks; result = %d", result); 1750 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH); 1751 return result; 1752 } 1753 1754 return result; 1755 } 1756 1757 virtual int cancel() { 1758 1759 WifiRequest request(familyId(), ifaceId()); 1760 int result = createRequest(request, 0); 1761 if (result != WIFI_SUCCESS) { 1762 ALOGE("failed to create request; result = %d", result); 1763 } else { 1764 result = requestResponse(request); 1765 if (result != WIFI_SUCCESS) { 1766 ALOGE("failed to reset ANQPO networks;result = %d", result); 1767 } 1768 } 1769 1770 unregisterVendorHandler(GOOGLE_OUI, GSCAN_EVENT_ANQPO_HOTSPOT_MATCH); 1771 return WIFI_SUCCESS; 1772 } 1773 1774 virtual int handleResponse(WifiEvent& reply) { 1775 ALOGD("Request complete!"); 1776 /* Nothing to do on response! */ 1777 return NL_SKIP; 1778 } 1779 1780 virtual int handleEvent(WifiEvent& event) { 1781 typedef struct { 1782 u16 channel; /* channel of GAS protocol */ 1783 u8 dialog_token; /* GAS dialog token */ 1784 u8 fragment_id; /* fragment id */ 1785 u16 status_code; /* status code on GAS completion */ 1786 u16 data_len; /* length of data to follow */ 1787 u8 data[1]; /* variable length specified by data_len */ 1788 } wifi_anqp_gas_resp; 1789 1790 ALOGI("ANQPO hotspot matched event!"); 1791 1792 nlattr *vendor_data = event.get_attribute(NL80211_ATTR_VENDOR_DATA); 1793 unsigned int len = event.get_vendor_data_len(); 1794 1795 if (vendor_data == NULL || len < sizeof(wifi_scan_result)) { 1796 ALOGI("No scan results found"); 1797 return NL_SKIP; 1798 } 1799 mResult = (wifi_scan_result *)malloc(sizeof(wifi_scan_result)); 1800 if (!mResult) { 1801 return NL_SKIP; 1802 } 1803 wifi_gscan_full_result_t *drv_res = (wifi_gscan_full_result_t *)event.get_vendor_data(); 1804 wifi_gscan_result_t *fixed = &drv_res->fixed; 1805 convert_to_hal_result(mResult, fixed); 1806 1807 byte *anqp = (byte *)drv_res + offsetof(wifi_gscan_full_result_t, ie_data) + drv_res->ie_length; 1808 wifi_anqp_gas_resp *gas = (wifi_anqp_gas_resp *)anqp; 1809 int anqp_len = offsetof(wifi_anqp_gas_resp, data) + gas->data_len; 1810 int networkId = *(int *)((byte *)anqp + anqp_len); 1811 1812 ALOGI("%-32s\t", mResult->ssid); 1813 1814 ALOGI("%02x:%02x:%02x:%02x:%02x:%02x ", mResult->bssid[0], mResult->bssid[1], 1815 mResult->bssid[2], mResult->bssid[3], mResult->bssid[4], mResult->bssid[5]); 1816 1817 ALOGI("%d\t", mResult->rssi); 1818 ALOGI("%d\t", mResult->channel); 1819 ALOGI("%lld\t", mResult->ts); 1820 ALOGI("%lld\t", mResult->rtt); 1821 ALOGI("%lld\n", mResult->rtt_sd); 1822 1823 if(*mHandler.on_passpoint_network_found) 1824 (*mHandler.on_passpoint_network_found)(id(), networkId, mResult, anqp_len, anqp); 1825 free(mResult); 1826 return NL_SKIP; 1827 } 1828 }; 1829 1830 wifi_error wifi_set_passpoint_list(wifi_request_id id, wifi_interface_handle iface, int num, 1831 wifi_passpoint_network *networks, wifi_passpoint_event_handler handler) 1832 { 1833 wifi_handle handle = getWifiHandle(iface); 1834 1835 AnqpoConfigureCommand *cmd = new AnqpoConfigureCommand(id, iface, num, networks, handler); 1836 NULL_CHECK_RETURN(cmd, "memory allocation failure", WIFI_ERROR_OUT_OF_MEMORY); 1837 wifi_error result = wifi_register_cmd(handle, id, cmd); 1838 if (result != WIFI_SUCCESS) { 1839 cmd->releaseRef(); 1840 return result; 1841 } 1842 result = (wifi_error)cmd->start(); 1843 if (result != WIFI_SUCCESS) { 1844 wifi_unregister_cmd(handle, id); 1845 cmd->releaseRef(); 1846 return result; 1847 } 1848 return result; 1849 } 1850 1851 wifi_error wifi_reset_passpoint_list(wifi_request_id id, wifi_interface_handle iface) 1852 { 1853 return wifi_cancel_cmd(id, iface); 1854 } 1855