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