1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "sync.h" 18#define LOG_TAG "WifiHAL" 19#include <utils/Log.h> 20#include <time.h> 21#include <errno.h> 22#include <stdlib.h> 23 24#include "common.h" 25#include "cpp_bindings.h" 26#include "gscancommand.h" 27#include "gscan_event_handler.h" 28 29#define GSCAN_EVENT_WAIT_TIME_SECONDS 4 30 31/* BSSID blacklist */ 32typedef struct { 33 int num_bssid; // number of blacklisted BSSIDs 34 mac_addr bssids[MAX_BLACKLIST_BSSID]; // blacklisted BSSIDs 35} wifi_bssid_params; 36 37/* Used to handle gscan command events from driver/firmware.*/ 38typedef struct gscan_event_handlers_s { 39 GScanCommandEventHandler *gscanStartCmdEventHandler; 40 GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler; 41 GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler; 42 GScanCommandEventHandler *gScanSetSsidHotlistCmdEventHandler; 43 GScanCommandEventHandler *gScanSetPnoListCmdEventHandler; 44 GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler; 45} gscan_event_handlers; 46 47wifi_error initializeGscanHandlers(hal_info *info) 48{ 49 info->gscan_handlers = (gscan_event_handlers *)malloc(sizeof(gscan_event_handlers)); 50 if (info->gscan_handlers) { 51 memset(info->gscan_handlers, 0, sizeof(gscan_event_handlers)); 52 } 53 else { 54 ALOGE("%s: Allocation of gscan event handlers failed", 55 __FUNCTION__); 56 return WIFI_ERROR_OUT_OF_MEMORY; 57 } 58 return WIFI_SUCCESS; 59} 60 61wifi_error cleanupGscanHandlers(hal_info *info) 62{ 63 gscan_event_handlers* event_handlers; 64 if (info && info->gscan_handlers) { 65 event_handlers = (gscan_event_handlers*) info->gscan_handlers; 66 if (event_handlers->gscanStartCmdEventHandler) { 67 delete event_handlers->gscanStartCmdEventHandler; 68 } 69 if (event_handlers->gScanSetBssidHotlistCmdEventHandler) { 70 delete event_handlers->gScanSetBssidHotlistCmdEventHandler; 71 } 72 if (event_handlers->gScanSetSignificantChangeCmdEventHandler) { 73 delete event_handlers->gScanSetSignificantChangeCmdEventHandler; 74 } 75 if (event_handlers->gScanSetSsidHotlistCmdEventHandler) { 76 delete event_handlers->gScanSetSsidHotlistCmdEventHandler; 77 } 78 if (event_handlers->gScanSetPnoListCmdEventHandler) { 79 delete event_handlers->gScanSetPnoListCmdEventHandler; 80 } 81 if (event_handlers->gScanPnoSetPasspointListCmdEventHandler) { 82 delete event_handlers->gScanPnoSetPasspointListCmdEventHandler; 83 } 84 memset(event_handlers, 0, sizeof(gscan_event_handlers)); 85 return WIFI_SUCCESS; 86 } 87 ALOGE ("%s: info or info->gscan_handlers NULL", __FUNCTION__); 88 return WIFI_ERROR_UNKNOWN; 89} 90 91/* Implementation of the API functions exposed in gscan.h */ 92wifi_error wifi_get_valid_channels(wifi_interface_handle handle, 93 int band, int max_channels, wifi_channel *channels, int *num_channels) 94{ 95 int requestId, ret = 0; 96 GScanCommand *gScanCommand; 97 struct nlattr *nlData; 98 interface_info *ifaceInfo = getIfaceInfo(handle); 99 wifi_handle wifiHandle = getWifiHandle(handle); 100 lowi_cb_table_t *lowiWifiHalApi = NULL; 101 102 /* Route GSCAN request through LOWI if supported */ 103 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED); 104 if (lowiWifiHalApi == NULL || 105 lowiWifiHalApi->get_valid_channels == NULL) { 106 ALOGV("%s: Sending cmd directly to host", __FUNCTION__); 107 } else { 108 ret = lowiWifiHalApi->get_valid_channels(handle, band, max_channels, 109 channels, num_channels); 110 ALOGV("%s: lowi get_valid_channels " 111 "returned: %d. Exit.", __FUNCTION__, ret); 112 return (wifi_error)ret; 113 } 114 115 /* No request id from caller, so generate one and pass it on to the driver. 116 * Generate one randomly. 117 */ 118 requestId = get_requestid(); 119 ALOGV("%s: RequestId:%d band:%d max_channels:%d", __FUNCTION__, 120 requestId, band, max_channels); 121 122 if (channels == NULL) { 123 ALOGE("%s: NULL channels pointer provided. Exit.", 124 __FUNCTION__); 125 return WIFI_ERROR_INVALID_ARGS; 126 } 127 128 gScanCommand = new GScanCommand( 129 wifiHandle, 130 requestId, 131 OUI_QCA, 132 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS); 133 if (gScanCommand == NULL) { 134 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 135 return WIFI_ERROR_UNKNOWN; 136 } 137 /* Create the NL message. */ 138 ret = gScanCommand->create(); 139 if (ret < 0) 140 goto cleanup; 141 142 /* Set the interface Id of the message. */ 143 ret = gScanCommand->set_iface_id(ifaceInfo->name); 144 if (ret < 0) 145 goto cleanup; 146 147 /* Add the vendor specific attributes for the NL command. */ 148 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 149 if (!nlData) 150 goto cleanup; 151 152 if (gScanCommand->put_u32( 153 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 154 requestId) || 155 gScanCommand->put_u32( 156 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_WIFI_BAND, 157 band) || 158 gScanCommand->put_u32( 159 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_VALID_CHANNELS_CONFIG_PARAM_MAX_CHANNELS, 160 max_channels) ) 161 { 162 goto cleanup; 163 } 164 gScanCommand->attr_end(nlData); 165 /* Populate the input received from caller/framework. */ 166 gScanCommand->setMaxChannels(max_channels); 167 gScanCommand->setChannels(channels); 168 gScanCommand->setNumChannelsPtr(num_channels); 169 170 /* Send the msg and wait for a response. */ 171 ret = gScanCommand->requestResponse(); 172 if (ret) { 173 ALOGE("%s: Error %d happened. ", __FUNCTION__, ret); 174 } 175 176cleanup: 177 delete gScanCommand; 178 return (wifi_error)ret; 179} 180 181wifi_error wifi_get_gscan_capabilities(wifi_interface_handle handle, 182 wifi_gscan_capabilities *capabilities) 183{ 184 wifi_error ret = WIFI_SUCCESS; 185 wifi_handle wifiHandle = getWifiHandle(handle); 186 hal_info *info = getHalInfo(wifiHandle); 187 lowi_cb_table_t *lowiWifiHalApi = NULL; 188 189 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) { 190 ALOGE("%s: GSCAN is not supported by driver", __FUNCTION__); 191 return WIFI_ERROR_NOT_SUPPORTED; 192 } 193 194 if (capabilities == NULL) { 195 ALOGE("%s: NULL capabilities pointer provided. Exit.", __FUNCTION__); 196 return WIFI_ERROR_INVALID_ARGS; 197 } 198 199 /* Route GSCAN request through LOWI if supported */ 200 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED); 201 if (lowiWifiHalApi == NULL || 202 lowiWifiHalApi->get_gscan_capabilities == NULL) { 203 ALOGV("%s: Sending cmd directly to host", __FUNCTION__); 204 } else { 205 ret = lowiWifiHalApi->get_gscan_capabilities(handle, capabilities); 206 ALOGV("%s: lowi get_gscan_capabilities returned: %d. Exit.", __FUNCTION__, ret); 207 return ret; 208 } 209 210 memcpy(capabilities, &info->capa.gscan_capa, sizeof(wifi_gscan_capabilities)); 211 212 return ret; 213} 214 215wifi_error wifi_start_gscan(wifi_request_id id, 216 wifi_interface_handle iface, 217 wifi_scan_cmd_params params, 218 wifi_scan_result_handler handler) 219{ 220 int ret = 0; 221 u32 i, j; 222 GScanCommand *gScanCommand; 223 struct nlattr *nlData; 224 interface_info *ifaceInfo = getIfaceInfo(iface); 225 wifi_handle wifiHandle = getWifiHandle(iface); 226 u32 num_scan_buckets, numChannelSpecs; 227 wifi_scan_bucket_spec bucketSpec; 228 struct nlattr *nlBuckectSpecList; 229 hal_info *info = getHalInfo(wifiHandle); 230 lowi_cb_table_t *lowiWifiHalApi = NULL; 231 gscan_event_handlers* event_handlers; 232 GScanCommandEventHandler *gScanStartCmdEventHandler; 233 234 event_handlers = (gscan_event_handlers*)info->gscan_handlers; 235 gScanStartCmdEventHandler = event_handlers->gscanStartCmdEventHandler; 236 237 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) { 238 ALOGE("%s: GSCAN is not supported by driver", 239 __FUNCTION__); 240 return WIFI_ERROR_NOT_SUPPORTED; 241 } 242 243 /* Route GSCAN request through LOWI if supported */ 244 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED); 245 if (lowiWifiHalApi == NULL || 246 lowiWifiHalApi->start_gscan == NULL) { 247 ALOGV("%s: Sending cmd directly to host", __FUNCTION__); 248 } else { 249 ret = lowiWifiHalApi->start_gscan(id, iface, params, handler); 250 ALOGV("%s: lowi start_gscan " 251 "returned: %d. Exit.", __FUNCTION__, ret); 252 return (wifi_error)ret; 253 } 254 255 ALOGV("%s: RequestId:%d ", __FUNCTION__, id); 256 /* Wi-Fi HAL doesn't need to check if a similar request to start gscan was 257 * made earlier. If start_gscan() is called while another gscan is already 258 * running, the request will be sent down to driver and firmware. If new 259 * request is successfully honored, then Wi-Fi HAL will use the new request 260 * id for the gScanStartCmdEventHandler object. 261 */ 262 gScanCommand = new GScanCommand( 263 wifiHandle, 264 id, 265 OUI_QCA, 266 QCA_NL80211_VENDOR_SUBCMD_GSCAN_START); 267 if (gScanCommand == NULL) { 268 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 269 return WIFI_ERROR_UNKNOWN; 270 } 271 272 /* Create the NL message. */ 273 ret = gScanCommand->create(); 274 if (ret < 0) 275 goto cleanup; 276 277 /* Set the interface Id of the message. */ 278 ret = gScanCommand->set_iface_id(ifaceInfo->name); 279 if (ret < 0) 280 goto cleanup; 281 282 /* Add the vendor specific attributes for the NL command. */ 283 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 284 if (!nlData) 285 goto cleanup; 286 287 num_scan_buckets = (unsigned int)params.num_buckets > MAX_BUCKETS ? 288 MAX_BUCKETS : params.num_buckets; 289 290 ALOGV("%s: Base Period:%d Max_ap_per_scan:%d " 291 "Threshold_percent:%d Threshold_num_scans:%d " 292 "num_buckets:%d", __FUNCTION__, params.base_period, 293 params.max_ap_per_scan, params.report_threshold_percent, 294 params.report_threshold_num_scans, num_scan_buckets); 295 if (gScanCommand->put_u32( 296 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 297 id) || 298 gScanCommand->put_u32( 299 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_BASE_PERIOD, 300 params.base_period) || 301 gScanCommand->put_u32( 302 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_MAX_AP_PER_SCAN, 303 params.max_ap_per_scan) || 304 gScanCommand->put_u8( 305 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_PERCENT, 306 params.report_threshold_percent) || 307 gScanCommand->put_u8( 308 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_REPORT_THRESHOLD_NUM_SCANS, 309 params.report_threshold_num_scans) || 310 gScanCommand->put_u8( 311 QCA_WLAN_VENDOR_ATTR_GSCAN_SCAN_CMD_PARAMS_NUM_BUCKETS, 312 num_scan_buckets)) 313 { 314 goto cleanup; 315 } 316 317 nlBuckectSpecList = 318 gScanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC); 319 /* Add NL attributes for scan bucket specs . */ 320 for (i = 0; i < num_scan_buckets; i++) { 321 bucketSpec = params.buckets[i]; 322 numChannelSpecs = (unsigned int)bucketSpec.num_channels > MAX_CHANNELS ? 323 MAX_CHANNELS : bucketSpec.num_channels; 324 325 ALOGV("%s: Index: %d Bucket Id:%d Band:%d Period:%d ReportEvent:%d " 326 "numChannelSpecs:%d max_period:%d base:%d step_count:%d", 327 __FUNCTION__, i, bucketSpec.bucket, bucketSpec.band, 328 bucketSpec.period, bucketSpec.report_events, 329 numChannelSpecs, bucketSpec.max_period, 330 bucketSpec.base, bucketSpec.step_count); 331 332 struct nlattr *nlBucketSpec = gScanCommand->attr_start(i); 333 if (gScanCommand->put_u8( 334 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_INDEX, 335 bucketSpec.bucket) || 336 gScanCommand->put_u8( 337 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BAND, 338 bucketSpec.band) || 339 gScanCommand->put_u32( 340 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_PERIOD, 341 bucketSpec.period) || 342 gScanCommand->put_u8( 343 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_REPORT_EVENTS, 344 bucketSpec.report_events) || 345 gScanCommand->put_u32( 346 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_NUM_CHANNEL_SPECS, 347 numChannelSpecs) || 348 gScanCommand->put_u32( 349 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_MAX_PERIOD, 350 bucketSpec.max_period) || 351 gScanCommand->put_u32( 352 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_BASE, 353 bucketSpec.base) || 354 gScanCommand->put_u32( 355 QCA_WLAN_VENDOR_ATTR_GSCAN_BUCKET_SPEC_STEP_COUNT, 356 bucketSpec.step_count)) 357 { 358 goto cleanup; 359 } 360 361 struct nlattr *nl_channelSpecList = 362 gScanCommand->attr_start(QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC); 363 364 /* Add NL attributes for scan channel specs . */ 365 for (j = 0; j < numChannelSpecs; j++) { 366 struct nlattr *nl_channelSpec = gScanCommand->attr_start(j); 367 wifi_scan_channel_spec channel_spec = bucketSpec.channels[j]; 368 369 ALOGV("%s: Channel Spec Index:%d Channel:%d Dwell Time:%d " 370 "passive:%d", __FUNCTION__, j, channel_spec.channel, 371 channel_spec.dwellTimeMs, channel_spec.passive); 372 373 if ( gScanCommand->put_u32( 374 QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_CHANNEL, 375 channel_spec.channel) || 376 gScanCommand->put_u32( 377 QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_DWELL_TIME, 378 channel_spec.dwellTimeMs) || 379 gScanCommand->put_u8( 380 QCA_WLAN_VENDOR_ATTR_GSCAN_CHANNEL_SPEC_PASSIVE, 381 channel_spec.passive) ) 382 { 383 goto cleanup; 384 } 385 386 gScanCommand->attr_end(nl_channelSpec); 387 } 388 gScanCommand->attr_end(nl_channelSpecList); 389 gScanCommand->attr_end(nlBucketSpec); 390 } 391 gScanCommand->attr_end(nlBuckectSpecList); 392 393 gScanCommand->attr_end(nlData); 394 395 /* Set the callback handler functions for related events. */ 396 GScanCallbackHandler callbackHandler; 397 memset(&callbackHandler, 0, sizeof(callbackHandler)); 398 callbackHandler.on_full_scan_result = handler.on_full_scan_result; 399 callbackHandler.on_scan_event = handler.on_scan_event; 400 401 /* Create an object to handle the related events from firmware/driver. */ 402 if (gScanStartCmdEventHandler == NULL) { 403 gScanStartCmdEventHandler = new GScanCommandEventHandler( 404 wifiHandle, 405 id, 406 OUI_QCA, 407 QCA_NL80211_VENDOR_SUBCMD_GSCAN_START, 408 callbackHandler); 409 if (gScanStartCmdEventHandler == NULL) { 410 ALOGE("%s: Error gScanStartCmdEventHandler NULL", __FUNCTION__); 411 ret = WIFI_ERROR_UNKNOWN; 412 goto cleanup; 413 } 414 event_handlers->gscanStartCmdEventHandler = gScanStartCmdEventHandler; 415 } else { 416 gScanStartCmdEventHandler->setCallbackHandler(callbackHandler); 417 } 418 419 ret = gScanCommand->requestResponse(); 420 if (ret != 0) { 421 ALOGE("%s : requestResponse Error:%d", __FUNCTION__, ret); 422 goto cleanup; 423 } 424 425 if (gScanStartCmdEventHandler != NULL) { 426 gScanStartCmdEventHandler->set_request_id(id); 427 gScanStartCmdEventHandler->enableEventHandling(); 428 } 429 430cleanup: 431 delete gScanCommand; 432 /* Disable Event Handling if ret != 0 */ 433 if (ret && gScanStartCmdEventHandler) { 434 ALOGI("%s: Error ret:%d, disable event handling", 435 __FUNCTION__, ret); 436 gScanStartCmdEventHandler->disableEventHandling(); 437 } 438 return (wifi_error)ret; 439 440} 441 442wifi_error wifi_stop_gscan(wifi_request_id id, 443 wifi_interface_handle iface) 444{ 445 int ret = 0; 446 GScanCommand *gScanCommand; 447 struct nlattr *nlData; 448 lowi_cb_table_t *lowiWifiHalApi = NULL; 449 450 interface_info *ifaceInfo = getIfaceInfo(iface); 451 wifi_handle wifiHandle = getWifiHandle(iface); 452 hal_info *info = getHalInfo(wifiHandle); 453 gscan_event_handlers* event_handlers; 454 GScanCommandEventHandler *gScanStartCmdEventHandler; 455 456 event_handlers = (gscan_event_handlers*)info->gscan_handlers; 457 gScanStartCmdEventHandler = event_handlers->gscanStartCmdEventHandler; 458 459 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) { 460 ALOGE("%s: GSCAN is not supported by driver", 461 __FUNCTION__); 462 return WIFI_ERROR_NOT_SUPPORTED; 463 } 464 465 /* Route GSCAN request through LOWI if supported */ 466 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED); 467 if (lowiWifiHalApi == NULL || 468 lowiWifiHalApi->stop_gscan == NULL) { 469 ALOGV("%s: Sending cmd directly to host", __FUNCTION__); 470 } else { 471 ret = lowiWifiHalApi->stop_gscan(id, iface); 472 ALOGV("%s: lowi stop_gscan " 473 "returned: %d. Exit.", __FUNCTION__, ret); 474 return (wifi_error)ret; 475 } 476 477 if (gScanStartCmdEventHandler == NULL || 478 gScanStartCmdEventHandler->isEventHandlingEnabled() == false) { 479 ALOGE("%s: GSCAN isn't running or already stopped. " 480 "Nothing to do. Exit", __FUNCTION__); 481 return WIFI_ERROR_NOT_AVAILABLE; 482 } 483 484 gScanCommand = new GScanCommand( 485 wifiHandle, 486 id, 487 OUI_QCA, 488 QCA_NL80211_VENDOR_SUBCMD_GSCAN_STOP); 489 if (gScanCommand == NULL) { 490 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 491 return WIFI_ERROR_UNKNOWN; 492 } 493 494 /* Create the NL message. */ 495 ret = gScanCommand->create(); 496 if (ret < 0) 497 goto cleanup; 498 499 /* Set the interface Id of the message. */ 500 ret = gScanCommand->set_iface_id(ifaceInfo->name); 501 if (ret < 0) 502 goto cleanup; 503 504 /* Add the vendor specific attributes for the NL command. */ 505 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 506 if (!nlData) 507 goto cleanup; 508 509 ret = gScanCommand->put_u32( 510 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 511 id); 512 if (ret < 0) 513 goto cleanup; 514 515 gScanCommand->attr_end(nlData); 516 517 ret = gScanCommand->requestResponse(); 518 if (ret != 0) { 519 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 520 } 521 522 /* Disable Event Handling. */ 523 if (gScanStartCmdEventHandler) { 524 gScanStartCmdEventHandler->disableEventHandling(); 525 } 526 527cleanup: 528 delete gScanCommand; 529 return (wifi_error)ret; 530} 531 532/* Set the GSCAN BSSID Hotlist. */ 533wifi_error wifi_set_bssid_hotlist(wifi_request_id id, 534 wifi_interface_handle iface, 535 wifi_bssid_hotlist_params params, 536 wifi_hotlist_ap_found_handler handler) 537{ 538 int i, numAp, ret = 0; 539 GScanCommand *gScanCommand; 540 struct nlattr *nlData, *nlApThresholdParamList; 541 interface_info *ifaceInfo = getIfaceInfo(iface); 542 wifi_handle wifiHandle = getWifiHandle(iface); 543 hal_info *info = getHalInfo(wifiHandle); 544 lowi_cb_table_t *lowiWifiHalApi = NULL; 545 gscan_event_handlers* event_handlers; 546 GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler; 547 548 event_handlers = (gscan_event_handlers*)info->gscan_handlers; 549 gScanSetBssidHotlistCmdEventHandler = 550 event_handlers->gScanSetBssidHotlistCmdEventHandler; 551 552 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) { 553 ALOGE("%s: GSCAN is not supported by driver", 554 __FUNCTION__); 555 return WIFI_ERROR_NOT_SUPPORTED; 556 } 557 558 /* Route request through LOWI if supported*/ 559 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED); 560 if (lowiWifiHalApi == NULL || 561 lowiWifiHalApi->set_bssid_hotlist == NULL) { 562 ALOGV("%s: Sending cmd directly to host", __FUNCTION__); 563 } else { 564 ret = lowiWifiHalApi->set_bssid_hotlist(id, iface, params,handler); 565 ALOGV("%s: lowi set_bssid_hotlist " 566 "returned: %d. Exit.", __FUNCTION__, ret); 567 return (wifi_error)ret; 568 } 569 570 /* Wi-Fi HAL doesn't need to check if a similar request to set bssid 571 * hotlist was made earlier. If set_bssid_hotlist() is called while 572 * another one is running, the request will be sent down to driver and 573 * firmware. If the new request is successfully honored, then Wi-Fi HAL 574 * will use the new request id for the gScanSetBssidHotlistCmdEventHandler 575 * object. 576 */ 577 578 gScanCommand = 579 new GScanCommand( 580 wifiHandle, 581 id, 582 OUI_QCA, 583 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST); 584 if (gScanCommand == NULL) { 585 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 586 return WIFI_ERROR_UNKNOWN; 587 } 588 589 /* Create the NL message. */ 590 ret = gScanCommand->create(); 591 if (ret < 0) 592 goto cleanup; 593 594 /* Set the interface Id of the message. */ 595 ret = gScanCommand->set_iface_id(ifaceInfo->name); 596 if (ret < 0) 597 goto cleanup; 598 599 /* Add the vendor specific attributes for the NL command. */ 600 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 601 if (!nlData) 602 goto cleanup; 603 604 numAp = (unsigned int)params.num_bssid > MAX_HOTLIST_APS ? 605 MAX_HOTLIST_APS : params.num_bssid; 606 if (gScanCommand->put_u32( 607 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 608 id) || 609 gScanCommand->put_u32( 610 QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_LOST_AP_SAMPLE_SIZE, 611 params.lost_ap_sample_size) || 612 gScanCommand->put_u32( 613 QCA_WLAN_VENDOR_ATTR_GSCAN_BSSID_HOTLIST_PARAMS_NUM_AP, 614 numAp)) 615 { 616 goto cleanup; 617 } 618 619 ALOGV("%s: lost_ap_sample_size:%d numAp:%d", __FUNCTION__, 620 params.lost_ap_sample_size, numAp); 621 /* Add the vendor specific attributes for the NL command. */ 622 nlApThresholdParamList = 623 gScanCommand->attr_start( 624 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM); 625 if (!nlApThresholdParamList) 626 goto cleanup; 627 628 /* Add nested NL attributes for AP Threshold Param. */ 629 for (i = 0; i < numAp; i++) { 630 ap_threshold_param apThreshold = params.ap[i]; 631 struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i); 632 if (!nlApThresholdParam) 633 goto cleanup; 634 if (gScanCommand->put_addr( 635 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID, 636 apThreshold.bssid) || 637 gScanCommand->put_s32( 638 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW, 639 apThreshold.low) || 640 gScanCommand->put_s32( 641 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH, 642 apThreshold.high)) 643 { 644 goto cleanup; 645 } 646 ALOGV("%s: Index:%d BssId: %hhx:%hhx:%hhx:%hhx:%hhx:%hhx " 647 "Threshold low:%d high:%d", __FUNCTION__, i, 648 apThreshold.bssid[0], apThreshold.bssid[1], 649 apThreshold.bssid[2], apThreshold.bssid[3], 650 apThreshold.bssid[4], apThreshold.bssid[5], 651 apThreshold.low, apThreshold.high); 652 gScanCommand->attr_end(nlApThresholdParam); 653 } 654 655 gScanCommand->attr_end(nlApThresholdParamList); 656 657 gScanCommand->attr_end(nlData); 658 659 GScanCallbackHandler callbackHandler; 660 memset(&callbackHandler, 0, sizeof(callbackHandler)); 661 callbackHandler.on_hotlist_ap_found = handler.on_hotlist_ap_found; 662 callbackHandler.on_hotlist_ap_lost = handler.on_hotlist_ap_lost; 663 664 /* Create an object of the event handler class to take care of the 665 * asychronous events on the north-bound. 666 */ 667 if (gScanSetBssidHotlistCmdEventHandler == NULL) { 668 gScanSetBssidHotlistCmdEventHandler = new GScanCommandEventHandler( 669 wifiHandle, 670 id, 671 OUI_QCA, 672 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST, 673 callbackHandler); 674 if (gScanSetBssidHotlistCmdEventHandler == NULL) { 675 ALOGE("%s: Error instantiating " 676 "gScanSetBssidHotlistCmdEventHandler.", __FUNCTION__); 677 ret = WIFI_ERROR_UNKNOWN; 678 goto cleanup; 679 } 680 event_handlers->gScanSetBssidHotlistCmdEventHandler = 681 gScanSetBssidHotlistCmdEventHandler; 682 } else { 683 gScanSetBssidHotlistCmdEventHandler->setCallbackHandler(callbackHandler); 684 } 685 686 ret = gScanCommand->requestResponse(); 687 if (ret != 0) { 688 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 689 goto cleanup; 690 } 691 692 if (gScanSetBssidHotlistCmdEventHandler != NULL) { 693 gScanSetBssidHotlistCmdEventHandler->set_request_id(id); 694 gScanSetBssidHotlistCmdEventHandler->enableEventHandling(); 695 } 696 697cleanup: 698 delete gScanCommand; 699 /* Disable Event Handling if ret != 0 */ 700 if (ret && gScanSetBssidHotlistCmdEventHandler) { 701 ALOGI("%s: Error ret:%d, disable event handling", 702 __FUNCTION__, ret); 703 gScanSetBssidHotlistCmdEventHandler->disableEventHandling(); 704 } 705 return (wifi_error)ret; 706} 707 708wifi_error wifi_reset_bssid_hotlist(wifi_request_id id, 709 wifi_interface_handle iface) 710{ 711 int ret = 0; 712 GScanCommand *gScanCommand; 713 struct nlattr *nlData; 714 interface_info *ifaceInfo = getIfaceInfo(iface); 715 wifi_handle wifiHandle = getWifiHandle(iface); 716 hal_info *info = getHalInfo(wifiHandle); 717 lowi_cb_table_t *lowiWifiHalApi = NULL; 718 gscan_event_handlers* event_handlers; 719 GScanCommandEventHandler *gScanSetBssidHotlistCmdEventHandler; 720 721 event_handlers = (gscan_event_handlers*)info->gscan_handlers; 722 gScanSetBssidHotlistCmdEventHandler = 723 event_handlers->gScanSetBssidHotlistCmdEventHandler; 724 725 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) { 726 ALOGE("%s: GSCAN is not supported by driver", 727 __FUNCTION__); 728 return WIFI_ERROR_NOT_SUPPORTED; 729 } 730 731 /* Route request through LOWI if supported*/ 732 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED); 733 if (lowiWifiHalApi == NULL || 734 lowiWifiHalApi->reset_bssid_hotlist == NULL) { 735 ALOGV("%s: Sending cmd directly to host", __FUNCTION__); 736 } else { 737 ret = lowiWifiHalApi->reset_bssid_hotlist(id, iface); 738 ALOGV("%s: lowi reset_bssid_hotlist " 739 "returned: %d. Exit.", __FUNCTION__, ret); 740 return (wifi_error)ret; 741 } 742 743 744 if (gScanSetBssidHotlistCmdEventHandler == NULL || 745 (gScanSetBssidHotlistCmdEventHandler->isEventHandlingEnabled() == 746 false)) { 747 ALOGE("wifi_reset_bssid_hotlist: GSCAN bssid_hotlist isn't set. " 748 "Nothing to do. Exit"); 749 return WIFI_ERROR_NOT_AVAILABLE; 750 } 751 752 gScanCommand = new GScanCommand( 753 wifiHandle, 754 id, 755 OUI_QCA, 756 QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_BSSID_HOTLIST); 757 758 if (gScanCommand == NULL) { 759 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 760 return WIFI_ERROR_UNKNOWN; 761 } 762 763 /* Create the NL message. */ 764 ret = gScanCommand->create(); 765 if (ret < 0) 766 goto cleanup; 767 768 /* Set the interface Id of the message. */ 769 ret = gScanCommand->set_iface_id(ifaceInfo->name); 770 if (ret < 0) 771 goto cleanup; 772 773 /* Add the vendor specific attributes for the NL command. */ 774 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 775 if (!nlData) 776 goto cleanup; 777 778 ret = gScanCommand->put_u32( 779 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id); 780 if (ret < 0) 781 goto cleanup; 782 783 gScanCommand->attr_end(nlData); 784 785 ret = gScanCommand->requestResponse(); 786 if (ret != 0) { 787 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 788 } 789 790 /* Disable Event Handling. */ 791 if (gScanSetBssidHotlistCmdEventHandler) { 792 gScanSetBssidHotlistCmdEventHandler->disableEventHandling(); 793 } 794 795cleanup: 796 delete gScanCommand; 797 return (wifi_error)ret; 798} 799 800/* Set the GSCAN Significant AP Change list. */ 801wifi_error wifi_set_significant_change_handler(wifi_request_id id, 802 wifi_interface_handle iface, 803 wifi_significant_change_params params, 804 wifi_significant_change_handler handler) 805{ 806 int i, numAp, ret = 0; 807 GScanCommand *gScanCommand; 808 struct nlattr *nlData, *nlApThresholdParamList; 809 interface_info *ifaceInfo = getIfaceInfo(iface); 810 wifi_handle wifiHandle = getWifiHandle(iface); 811 hal_info *info = getHalInfo(wifiHandle); 812 lowi_cb_table_t *lowiWifiHalApi = NULL; 813 gscan_event_handlers* event_handlers; 814 GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler; 815 816 event_handlers = (gscan_event_handlers*)info->gscan_handlers; 817 gScanSetSignificantChangeCmdEventHandler = 818 event_handlers->gScanSetSignificantChangeCmdEventHandler; 819 820 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) { 821 ALOGE("%s: GSCAN is not supported by driver", 822 __FUNCTION__); 823 return WIFI_ERROR_NOT_SUPPORTED; 824 } 825 826 /* Route request through LOWI if supported*/ 827 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED); 828 if (lowiWifiHalApi == NULL || 829 lowiWifiHalApi->set_significant_change_handler == NULL) { 830 ALOGV("%s: Sending cmd directly to host", __FUNCTION__); 831 } else { 832 ret = lowiWifiHalApi->set_significant_change_handler(id, 833 iface, 834 params, 835 handler); 836 ALOGV("%s: lowi set_significant_change_handler " 837 "returned: %d. Exit.", __FUNCTION__, ret); 838 return (wifi_error)ret; 839 } 840 841 /* Wi-Fi HAL doesn't need to check if a similar request to set significant 842 * change list was made earlier. If set_significant_change() is called while 843 * another one is running, the request will be sent down to driver and 844 * firmware. If the new request is successfully honored, then Wi-Fi HAL 845 * will use the new request id for the gScanSetSignificantChangeCmdEventHandler 846 * object. 847 */ 848 849 gScanCommand = new GScanCommand( 850 wifiHandle, 851 id, 852 OUI_QCA, 853 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE); 854 if (gScanCommand == NULL) { 855 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 856 return WIFI_ERROR_UNKNOWN; 857 } 858 859 /* Create the NL message. */ 860 ret = gScanCommand->create(); 861 if (ret < 0) 862 goto cleanup; 863 864 /* Set the interface Id of the message. */ 865 ret = gScanCommand->set_iface_id(ifaceInfo->name); 866 if (ret < 0) 867 goto cleanup; 868 869 /* Add the vendor specific attributes for the NL command. */ 870 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 871 if (!nlData) 872 goto cleanup; 873 874 numAp = (unsigned int)params.num_bssid > MAX_SIGNIFICANT_CHANGE_APS ? 875 MAX_SIGNIFICANT_CHANGE_APS : params.num_bssid; 876 877 if (gScanCommand->put_u32( 878 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 879 id) || 880 gScanCommand->put_u32( 881 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_RSSI_SAMPLE_SIZE, 882 params.rssi_sample_size) || 883 gScanCommand->put_u32( 884 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_LOST_AP_SAMPLE_SIZE, 885 params.lost_ap_sample_size) || 886 gScanCommand->put_u32( 887 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_MIN_BREACHING, 888 params.min_breaching) || 889 gScanCommand->put_u32( 890 QCA_WLAN_VENDOR_ATTR_GSCAN_SIGNIFICANT_CHANGE_PARAMS_NUM_AP, 891 numAp)) 892 { 893 goto cleanup; 894 } 895 896 ALOGV("%s: Number of AP params:%d Rssi_sample_size:%d " 897 "lost_ap_sample_size:%d min_breaching:%d", __FUNCTION__, 898 numAp, params.rssi_sample_size, params.lost_ap_sample_size, 899 params.min_breaching); 900 901 /* Add the vendor specific attributes for the NL command. */ 902 nlApThresholdParamList = 903 gScanCommand->attr_start( 904 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM); 905 if (!nlApThresholdParamList) 906 goto cleanup; 907 908 /* Add nested NL attributes for AP Threshold Param list. */ 909 for (i = 0; i < numAp; i++) { 910 ap_threshold_param apThreshold = params.ap[i]; 911 struct nlattr *nlApThresholdParam = gScanCommand->attr_start(i); 912 if (!nlApThresholdParam) 913 goto cleanup; 914 if ( gScanCommand->put_addr( 915 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_BSSID, 916 apThreshold.bssid) || 917 gScanCommand->put_s32( 918 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_LOW, 919 apThreshold.low) || 920 gScanCommand->put_s32( 921 QCA_WLAN_VENDOR_ATTR_GSCAN_AP_THRESHOLD_PARAM_RSSI_HIGH, 922 apThreshold.high)) 923 { 924 goto cleanup; 925 } 926 ALOGV("%s: ap[%d].bssid:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx " 927 "ap[%d].low:%d ap[%d].high:%d", __FUNCTION__, 928 i, 929 apThreshold.bssid[0], apThreshold.bssid[1], 930 apThreshold.bssid[2], apThreshold.bssid[3], 931 apThreshold.bssid[4], apThreshold.bssid[5], 932 i, apThreshold.low, i, apThreshold.high); 933 gScanCommand->attr_end(nlApThresholdParam); 934 } 935 936 gScanCommand->attr_end(nlApThresholdParamList); 937 938 gScanCommand->attr_end(nlData); 939 940 GScanCallbackHandler callbackHandler; 941 memset(&callbackHandler, 0, sizeof(callbackHandler)); 942 callbackHandler.on_significant_change = handler.on_significant_change; 943 944 /* Create an object of the event handler class to take care of the 945 * asychronous events on the north-bound. 946 */ 947 if (gScanSetSignificantChangeCmdEventHandler == NULL) { 948 gScanSetSignificantChangeCmdEventHandler = 949 new GScanCommandEventHandler( 950 wifiHandle, 951 id, 952 OUI_QCA, 953 QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE, 954 callbackHandler); 955 if (gScanSetSignificantChangeCmdEventHandler == NULL) { 956 ALOGE("%s: Error in instantiating, " 957 "gScanSetSignificantChangeCmdEventHandler.", 958 __FUNCTION__); 959 ret = WIFI_ERROR_UNKNOWN; 960 goto cleanup; 961 } 962 event_handlers->gScanSetSignificantChangeCmdEventHandler = 963 gScanSetSignificantChangeCmdEventHandler; 964 } else { 965 gScanSetSignificantChangeCmdEventHandler->setCallbackHandler(callbackHandler); 966 } 967 968 ret = gScanCommand->requestResponse(); 969 if (ret != 0) { 970 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 971 goto cleanup; 972 } 973 974 if (gScanSetSignificantChangeCmdEventHandler != NULL) { 975 gScanSetSignificantChangeCmdEventHandler->set_request_id(id); 976 gScanSetSignificantChangeCmdEventHandler->enableEventHandling(); 977 } 978 979cleanup: 980 /* Disable Event Handling if ret != 0 */ 981 if (ret && gScanSetSignificantChangeCmdEventHandler) { 982 ALOGI("%s: Error ret:%d, disable event handling", 983 __FUNCTION__, ret); 984 gScanSetSignificantChangeCmdEventHandler->disableEventHandling(); 985 } 986 delete gScanCommand; 987 return (wifi_error)ret; 988} 989 990/* Clear the GSCAN Significant AP change list. */ 991wifi_error wifi_reset_significant_change_handler(wifi_request_id id, 992 wifi_interface_handle iface) 993{ 994 int ret = 0; 995 GScanCommand *gScanCommand; 996 struct nlattr *nlData; 997 interface_info *ifaceInfo = getIfaceInfo(iface); 998 wifi_handle wifiHandle = getWifiHandle(iface); 999 hal_info *info = getHalInfo(wifiHandle); 1000 lowi_cb_table_t *lowiWifiHalApi = NULL; 1001 gscan_event_handlers* event_handlers; 1002 GScanCommandEventHandler *gScanSetSignificantChangeCmdEventHandler; 1003 1004 event_handlers = (gscan_event_handlers*)info->gscan_handlers; 1005 gScanSetSignificantChangeCmdEventHandler = 1006 event_handlers->gScanSetSignificantChangeCmdEventHandler; 1007 1008 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) { 1009 ALOGE("%s: GSCAN is not supported by driver", 1010 __FUNCTION__); 1011 return WIFI_ERROR_NOT_SUPPORTED; 1012 } 1013 1014 /* Route request through LOWI if supported*/ 1015 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED); 1016 if (lowiWifiHalApi == NULL || 1017 lowiWifiHalApi->reset_significant_change_handler == NULL) { 1018 ALOGV("%s: Sending cmd directly to host", __FUNCTION__); 1019 } else { 1020 ret = lowiWifiHalApi->reset_significant_change_handler(id, iface); 1021 ALOGV("%s: lowi reset_significant_change_handler " 1022 "returned: %d. Exit.", __FUNCTION__, ret); 1023 return (wifi_error)ret; 1024 } 1025 1026 if (gScanSetSignificantChangeCmdEventHandler == NULL || 1027 (gScanSetSignificantChangeCmdEventHandler->isEventHandlingEnabled() == 1028 false)) { 1029 ALOGE("wifi_reset_significant_change_handler: GSCAN significant_change" 1030 " isn't set. Nothing to do. Exit"); 1031 return WIFI_ERROR_NOT_AVAILABLE; 1032 } 1033 1034 gScanCommand = 1035 new GScanCommand 1036 ( 1037 wifiHandle, 1038 id, 1039 OUI_QCA, 1040 QCA_NL80211_VENDOR_SUBCMD_GSCAN_RESET_SIGNIFICANT_CHANGE); 1041 if (gScanCommand == NULL) { 1042 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 1043 return WIFI_ERROR_UNKNOWN; 1044 } 1045 1046 /* Create the NL message. */ 1047 ret = gScanCommand->create(); 1048 if (ret < 0) 1049 goto cleanup; 1050 1051 /* Set the interface Id of the message. */ 1052 ret = gScanCommand->set_iface_id(ifaceInfo->name); 1053 if (ret < 0) 1054 goto cleanup; 1055 1056 /* Add the vendor specific attributes for the NL command. */ 1057 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1058 if (!nlData) 1059 goto cleanup; 1060 1061 ret = gScanCommand->put_u32( 1062 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 1063 id); 1064 if (ret < 0) 1065 goto cleanup; 1066 1067 gScanCommand->attr_end(nlData); 1068 1069 ret = gScanCommand->requestResponse(); 1070 if (ret != 0) { 1071 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 1072 } 1073 1074 /* Disable Event Handling. */ 1075 if (gScanSetSignificantChangeCmdEventHandler) { 1076 gScanSetSignificantChangeCmdEventHandler->disableEventHandling(); 1077 } 1078 1079cleanup: 1080 delete gScanCommand; 1081 return (wifi_error)ret; 1082} 1083 1084/* Get the GSCAN cached scan results. */ 1085wifi_error wifi_get_cached_gscan_results(wifi_interface_handle iface, 1086 byte flush, int max, 1087 wifi_cached_scan_results *results, 1088 int *num) 1089{ 1090 int requestId, ret = 0, retRequestRsp = 0; 1091 GScanCommand *gScanCommand; 1092 struct nlattr *nlData; 1093 lowi_cb_table_t *lowiWifiHalApi = NULL; 1094 1095 interface_info *ifaceInfo = getIfaceInfo(iface); 1096 wifi_handle wifiHandle = getWifiHandle(iface); 1097 hal_info *info = getHalInfo(wifiHandle); 1098 1099 if (!(info->supported_feature_set & WIFI_FEATURE_GSCAN)) { 1100 ALOGE("%s: GSCAN is not supported by driver", 1101 __FUNCTION__); 1102 return WIFI_ERROR_NOT_SUPPORTED; 1103 } 1104 1105 /* Route GSCAN request through LOWI if supported */ 1106 lowiWifiHalApi = getLowiCallbackTable(GSCAN_SUPPORTED); 1107 if (lowiWifiHalApi == NULL || 1108 lowiWifiHalApi->get_cached_gscan_results == NULL) { 1109 ALOGV("%s: Sending cmd directly to host", __FUNCTION__); 1110 } else { 1111 ret = lowiWifiHalApi->get_cached_gscan_results(iface, 1112 flush, 1113 max, 1114 results, 1115 num); 1116 ALOGV("%s: lowi get_cached_gscan_results" 1117 "returned: %d. Exit.", __FUNCTION__, ret); 1118 return (wifi_error)ret; 1119 } 1120 1121 /* No request id from caller, so generate one and pass it on to the driver. */ 1122 /* Generate it randomly */ 1123 requestId = get_requestid(); 1124 1125 if (results == NULL || num == NULL) { 1126 ALOGE("%s: NULL pointer provided. Exit.", 1127 __FUNCTION__); 1128 return WIFI_ERROR_INVALID_ARGS; 1129 } 1130 1131 gScanCommand = new GScanCommand( 1132 wifiHandle, 1133 requestId, 1134 OUI_QCA, 1135 QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS); 1136 if (gScanCommand == NULL) { 1137 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 1138 return WIFI_ERROR_UNKNOWN; 1139 } 1140 1141 ret = gScanCommand->allocRspParams(eGScanGetCachedResultsRspParams); 1142 if (ret != 0) { 1143 ALOGE("%s: Failed to allocate memory for response struct. Error:%d", 1144 __FUNCTION__, ret); 1145 goto cleanup; 1146 } 1147 1148 ret = gScanCommand->allocCachedResultsTemp(max, results); 1149 if (ret != 0) { 1150 ALOGE("%s: Failed to allocate memory for temp gscan cached list. " 1151 "Error:%d", __FUNCTION__, ret); 1152 goto cleanup; 1153 } 1154 1155 /* Clear the destination cached results list before copying results. */ 1156 memset(results, 0, max * sizeof(wifi_cached_scan_results)); 1157 1158 /* Create the NL message. */ 1159 ret = gScanCommand->create(); 1160 if (ret < 0) 1161 goto cleanup; 1162 1163 /* Set the interface Id of the message. */ 1164 ret = gScanCommand->set_iface_id(ifaceInfo->name); 1165 if (ret < 0) 1166 goto cleanup; 1167 1168 /* Add the vendor specific attributes for the NL command. */ 1169 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1170 if (!nlData) 1171 goto cleanup; 1172 1173 if (ret < 0) 1174 goto cleanup; 1175 1176 if (gScanCommand->put_u32( 1177 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 1178 requestId) || 1179 gScanCommand->put_u8( 1180 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_FLUSH, 1181 flush) || 1182 gScanCommand->put_u32( 1183 QCA_WLAN_VENDOR_ATTR_GSCAN_GET_CACHED_SCAN_RESULTS_CONFIG_PARAM_MAX, 1184 max)) 1185 { 1186 goto cleanup; 1187 } 1188 1189 ALOGV("%s: flush:%d max:%d", __FUNCTION__, flush, max); 1190 gScanCommand->attr_end(nlData); 1191 1192 retRequestRsp = gScanCommand->requestResponse(); 1193 if (retRequestRsp != 0) { 1194 ALOGE("%s: requestResponse Error:%d", 1195 __FUNCTION__, retRequestRsp); 1196 if (retRequestRsp != -ETIMEDOUT) { 1197 /* Proceed to cleanup & return no results */ 1198 goto cleanup; 1199 } 1200 } 1201 1202 /* No more data, copy the parsed results into the caller's results array */ 1203 ret = gScanCommand->copyCachedScanResults(num, results); 1204 ALOGV("%s: max: %d, num:%d", __FUNCTION__, max, *num); 1205 1206 if (!ret) { 1207 /* If requestResponse returned a TIMEOUT */ 1208 if (retRequestRsp == -ETIMEDOUT) { 1209 if (*num > 0) { 1210 /* Mark scan results as incomplete for the last scan_id */ 1211 results[(*num)-1].flags = WIFI_SCAN_FLAG_INTERRUPTED; 1212 ALOGV("%s: Timeout happened. Mark scan results as incomplete " 1213 "for scan_id:%d", __FUNCTION__, results[(*num)-1].scan_id); 1214 ret = WIFI_SUCCESS; 1215 } else 1216 ret = WIFI_ERROR_TIMED_OUT; 1217 } 1218 } 1219cleanup: 1220 gScanCommand->freeRspParams(eGScanGetCachedResultsRspParams); 1221 delete gScanCommand; 1222 return (wifi_error)ret; 1223} 1224 1225/* Random MAC OUI for PNO */ 1226wifi_error wifi_set_scanning_mac_oui(wifi_interface_handle handle, oui scan_oui) 1227{ 1228 int ret = 0; 1229 struct nlattr *nlData; 1230 WifiVendorCommand *vCommand = NULL; 1231 interface_info *iinfo = getIfaceInfo(handle); 1232 wifi_handle wifiHandle = getWifiHandle(handle); 1233 1234 vCommand = new WifiVendorCommand(wifiHandle, 0, 1235 OUI_QCA, 1236 QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI); 1237 if (vCommand == NULL) { 1238 ALOGE("%s: Error vCommand NULL", __FUNCTION__); 1239 return WIFI_ERROR_OUT_OF_MEMORY; 1240 } 1241 1242 /* create the message */ 1243 ret = vCommand->create(); 1244 if (ret < 0) 1245 goto cleanup; 1246 1247 ret = vCommand->set_iface_id(iinfo->name); 1248 if (ret < 0) 1249 goto cleanup; 1250 1251 /* Add the vendor specific attributes for the NL command. */ 1252 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1253 if (!nlData) 1254 goto cleanup; 1255 1256 ALOGV("%s: MAC_OUI - %02x:%02x:%02x", __FUNCTION__, 1257 scan_oui[0], scan_oui[1], scan_oui[2]); 1258 1259 /* Add the fixed part of the mac_oui to the nl command */ 1260 ret = vCommand->put_bytes( 1261 QCA_WLAN_VENDOR_ATTR_SET_SCANNING_MAC_OUI, 1262 (char *)scan_oui, 1263 WIFI_SCANNING_MAC_OUI_LENGTH); 1264 if (ret < 0) 1265 goto cleanup; 1266 1267 vCommand->attr_end(nlData); 1268 1269 ret = vCommand->requestResponse(); 1270 if (ret != 0) { 1271 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 1272 goto cleanup; 1273 } 1274 1275cleanup: 1276 delete vCommand; 1277 return (wifi_error)ret; 1278} 1279 1280 1281GScanCommand::GScanCommand(wifi_handle handle, int id, u32 vendor_id, 1282 u32 subcmd) 1283 : WifiVendorCommand(handle, id, vendor_id, subcmd) 1284{ 1285 /* Initialize the member data variables here */ 1286 mGetCachedResultsRspParams = NULL; 1287 mChannels = NULL; 1288 mMaxChannels = 0; 1289 mNumChannelsPtr = NULL; 1290 1291 mRequestId = id; 1292 memset(&mHandler, 0,sizeof(mHandler)); 1293} 1294 1295GScanCommand::~GScanCommand() 1296{ 1297 unregisterVendorHandler(mVendor_id, mSubcmd); 1298} 1299 1300 1301/* This function implements creation of Vendor command */ 1302int GScanCommand::create() { 1303 int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0); 1304 if (ret < 0) { 1305 return ret; 1306 } 1307 1308 /* Insert the oui in the msg */ 1309 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id); 1310 if (ret < 0) 1311 goto out; 1312 /* Insert the subcmd in the msg */ 1313 ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd); 1314 if (ret < 0) 1315 goto out; 1316 1317 ALOGV("%s: mVendor_id = %d, Subcmd = %d.", 1318 __FUNCTION__, mVendor_id, mSubcmd); 1319out: 1320 return ret; 1321} 1322 1323int GScanCommand::requestResponse() 1324{ 1325 return WifiCommand::requestResponse(mMsg); 1326} 1327 1328int GScanCommand::handleResponse(WifiEvent &reply) { 1329 int i = 0; 1330 int ret = WIFI_SUCCESS; 1331 u32 val; 1332 1333 WifiVendorCommand::handleResponse(reply); 1334 1335 struct nlattr *tbVendor[ 1336 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; 1337 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, 1338 (struct nlattr *)mVendorData,mDataLen, NULL); 1339 1340 switch(mSubcmd) 1341 { 1342 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_VALID_CHANNELS: 1343 { 1344 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]) { 1345 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS" 1346 " not found", __FUNCTION__); 1347 ret = WIFI_ERROR_INVALID_ARGS; 1348 break; 1349 } 1350 val = nla_get_u32(tbVendor[ 1351 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_CHANNELS]); 1352 1353 val = val > (unsigned int)mMaxChannels ? 1354 (unsigned int)mMaxChannels : val; 1355 *mNumChannelsPtr = val; 1356 1357 /* Extract the list of channels. */ 1358 if (*mNumChannelsPtr > 0 ) { 1359 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS]) { 1360 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS" 1361 " not found", __FUNCTION__); 1362 ret = WIFI_ERROR_INVALID_ARGS; 1363 break; 1364 } 1365 nla_memcpy(mChannels, 1366 tbVendor[ 1367 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CHANNELS], 1368 sizeof(wifi_channel) * (*mNumChannelsPtr)); 1369 } 1370 char buf[256]; 1371 size_t len = 0; 1372 for (i = 0; i < *mNumChannelsPtr && len < sizeof(buf); i++) { 1373 len += snprintf(buf + len, sizeof(buf) - len, "%u ", 1374 *(mChannels + i)); 1375 } 1376 ALOGV("%s: Num Channels %d: List of valid channels are: %s", 1377 __FUNCTION__, *mNumChannelsPtr, buf); 1378 1379 } 1380 break; 1381 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS: 1382 { 1383 wifi_request_id id; 1384 u32 numResults = 0; 1385 int firstScanIdInPatch = -1; 1386 1387 if (!tbVendor[ 1388 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { 1389 ALOGE("%s: GSCAN_RESULTS_REQUEST_ID not" 1390 "found", __FUNCTION__); 1391 ret = WIFI_ERROR_INVALID_ARGS; 1392 break; 1393 } 1394 id = nla_get_u32( 1395 tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] 1396 ); 1397 /* If this is not for us, just ignore it. */ 1398 if (id != mRequestId) { 1399 ALOGV("%s: Event has Req. ID:%d <> ours:%d", 1400 __FUNCTION__, id, mRequestId); 1401 break; 1402 } 1403 if (!tbVendor[ 1404 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) { 1405 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not" 1406 "found", __FUNCTION__); 1407 ret = WIFI_ERROR_INVALID_ARGS; 1408 break; 1409 } 1410 /* Read num of cached scan results in this data chunk. Note that 1411 * this value doesn't represent the number of unique gscan scan Ids 1412 * since the first scan id in this new chunk could be similar to 1413 * the last scan id in the previous chunk. 1414 */ 1415 numResults = nla_get_u32(tbVendor[ 1416 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]); 1417 ALOGV("%s: num Cached results in this fragment:%d", 1418 __FUNCTION__, numResults); 1419 1420 if (!mGetCachedResultsRspParams) { 1421 ALOGE("%s: mGetCachedResultsRspParams is NULL, exit.", 1422 __FUNCTION__); 1423 ret = WIFI_ERROR_INVALID_ARGS; 1424 break; 1425 } 1426 1427 /* To support fragmentation from firmware, monitor the 1428 * MORE_DATA flag and cache results until MORE_DATA = 0. 1429 */ 1430 if (!tbVendor[ 1431 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) { 1432 ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA " 1433 "not found", __FUNCTION__); 1434 ret = WIFI_ERROR_INVALID_ARGS; 1435 break; 1436 } else { 1437 mGetCachedResultsRspParams->more_data = nla_get_u8( 1438 tbVendor[ 1439 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]); 1440 } 1441 1442 /* No data in this chunk so skip this chunk */ 1443 if (numResults == 0) { 1444 return NL_SKIP; 1445 } 1446 1447 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]) { 1448 ALOGE("GSCAN_CACHED_RESULTS_SCAN_ID not found"); 1449 ret = WIFI_ERROR_INVALID_ARGS; 1450 break; 1451 } 1452 1453 /* Get the first Scan-Id in this chuck of cached results. */ 1454 firstScanIdInPatch = nla_get_u32(tbVendor[ 1455 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID]); 1456 1457 ALOGV("More data: %d, firstScanIdInPatch: %d, lastProcessedScanId: %d", 1458 mGetCachedResultsRspParams->more_data, firstScanIdInPatch, 1459 mGetCachedResultsRspParams->lastProcessedScanId); 1460 1461 if (numResults) { 1462 if (firstScanIdInPatch != 1463 mGetCachedResultsRspParams->lastProcessedScanId) { 1464 /* New result scan Id block, update the starting index. */ 1465 mGetCachedResultsRspParams->cachedResultsStartingIndex++; 1466 } 1467 1468 ret = gscan_get_cached_results( 1469 mGetCachedResultsRspParams->cached_results, 1470 tbVendor); 1471 /* If a parsing error occurred, exit and proceed for cleanup. */ 1472 if (ret) 1473 break; 1474 } 1475 } 1476 break; 1477 default: 1478 /* Error case should not happen print log */ 1479 ALOGE("%s: Wrong GScan subcmd response received %d", 1480 __FUNCTION__, mSubcmd); 1481 } 1482 1483 /* A parsing error occurred, do the cleanup of gscan result lists. */ 1484 if (ret) { 1485 switch(mSubcmd) 1486 { 1487 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CACHED_RESULTS: 1488 { 1489 ALOGE("%s: Parsing error, free CachedResultsRspParams", 1490 __FUNCTION__); 1491 freeRspParams(eGScanGetCachedResultsRspParams); 1492 } 1493 break; 1494 default: 1495 ALOGE("%s: Wrong GScan subcmd received %d", __FUNCTION__, mSubcmd); 1496 } 1497 } 1498 return NL_SKIP; 1499} 1500 1501/* Called to parse and extract cached results. */ 1502int GScanCommand:: gscan_get_cached_results( 1503 wifi_cached_scan_results *cached_results, 1504 struct nlattr **tb_vendor) 1505{ 1506 u32 j = 0; 1507 struct nlattr *scanResultsInfo, *wifiScanResultsInfo; 1508 int rem = 0, remResults = 0; 1509 u32 len = 0, numScanResults = 0; 1510 u32 i = mGetCachedResultsRspParams->cachedResultsStartingIndex; 1511 ALOGV("%s: starting counter: %d", __FUNCTION__, i); 1512 1513 for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[ 1514 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]), 1515 rem = nla_len(tb_vendor[ 1516 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_LIST]); 1517 nla_ok(scanResultsInfo, rem) && i < mGetCachedResultsRspParams->max; 1518 scanResultsInfo = nla_next(scanResultsInfo, &(rem))) 1519 { 1520 struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; 1521 nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, 1522 (struct nlattr *) nla_data(scanResultsInfo), 1523 nla_len(scanResultsInfo), NULL); 1524 1525 if (! 1526 tb2[ 1527 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID 1528 ]) 1529 { 1530 ALOGE("%s: GSCAN_CACHED_RESULTS_SCAN_ID" 1531 " not found", __FUNCTION__); 1532 return WIFI_ERROR_INVALID_ARGS; 1533 } 1534 cached_results[i].scan_id = 1535 nla_get_u32( 1536 tb2[ 1537 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_SCAN_ID 1538 ]); 1539 1540 if (! 1541 tb2[ 1542 QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS 1543 ]) 1544 { 1545 ALOGE("%s: GSCAN_CACHED_RESULTS_FLAGS " 1546 "not found", __FUNCTION__); 1547 return WIFI_ERROR_INVALID_ARGS; 1548 } 1549 cached_results[i].flags = 1550 nla_get_u32( 1551 tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_CACHED_RESULTS_FLAGS]); 1552 1553 if (!tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED]) 1554 { 1555 ALOGI("%s: GSCAN_RESULTS_BUCKETS_SCANNED" 1556 "not found", __FUNCTION__); 1557 } else { 1558 cached_results[i].buckets_scanned = nla_get_u32( 1559 tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED]); 1560 } 1561 1562 if (! 1563 tb2[ 1564 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE 1565 ]) 1566 { 1567 ALOGE("%s: RESULTS_NUM_RESULTS_AVAILABLE " 1568 "not found", __FUNCTION__); 1569 return WIFI_ERROR_INVALID_ARGS; 1570 } 1571 numScanResults = 1572 nla_get_u32( 1573 tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]); 1574 1575 if (mGetCachedResultsRspParams->lastProcessedScanId != 1576 cached_results[i].scan_id) { 1577 j = 0; /* reset wifi_scan_result counter */ 1578 cached_results[i].num_results = 0; 1579 ALOGV("parsing: *lastProcessedScanId [%d] !=" 1580 " cached_results[%d].scan_id:%d, j:%d " 1581 "numScanResults: %d", 1582 mGetCachedResultsRspParams->lastProcessedScanId, i, 1583 cached_results[i].scan_id, j, numScanResults); 1584 mGetCachedResultsRspParams->lastProcessedScanId = 1585 cached_results[i].scan_id; 1586 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = 0; 1587 /* Increment the number of cached scan results received */ 1588 mGetCachedResultsRspParams->num_cached_results++; 1589 } else { 1590 j = mGetCachedResultsRspParams->wifiScanResultsStartingIndex; 1591 ALOGV("parsing: *lastProcessedScanId [%d] == " 1592 "cached_results[%d].scan_id:%d, j:%d " 1593 "numScanResults:%d", 1594 mGetCachedResultsRspParams->lastProcessedScanId, i, 1595 cached_results[i].scan_id, j, numScanResults); 1596 } 1597 1598 ALOGV("%s: scan_id %d ", __FUNCTION__, 1599 cached_results[i].scan_id); 1600 ALOGV("%s: flags %u ", __FUNCTION__, 1601 cached_results[i].flags); 1602 1603 for (wifiScanResultsInfo = (struct nlattr *) nla_data(tb2[ 1604 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), 1605 remResults = nla_len(tb2[ 1606 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]); 1607 nla_ok(wifiScanResultsInfo, remResults); 1608 wifiScanResultsInfo = nla_next(wifiScanResultsInfo, &(remResults))) 1609 { 1610 struct nlattr *tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; 1611 nla_parse(tb3, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, 1612 (struct nlattr *) nla_data(wifiScanResultsInfo), 1613 nla_len(wifiScanResultsInfo), NULL); 1614 if (j < MAX_AP_CACHE_PER_SCAN) { 1615 if (! 1616 tb3[ 1617 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP 1618 ]) 1619 { 1620 ALOGE("%s: " 1621 "RESULTS_SCAN_RESULT_TIME_STAMP not found", 1622 __FUNCTION__); 1623 return WIFI_ERROR_INVALID_ARGS; 1624 } 1625 cached_results[i].results[j].ts = 1626 nla_get_u64( 1627 tb3[ 1628 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP 1629 ]); 1630 if (! 1631 tb3[ 1632 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID 1633 ]) 1634 { 1635 ALOGE("%s: " 1636 "RESULTS_SCAN_RESULT_SSID not found", 1637 __FUNCTION__); 1638 return WIFI_ERROR_INVALID_ARGS; 1639 } 1640 len = nla_len(tb3[ 1641 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]); 1642 len = 1643 sizeof(cached_results[i].results[j].ssid) <= len ? 1644 sizeof(cached_results[i].results[j].ssid) : len; 1645 memcpy((void *)&cached_results[i].results[j].ssid, 1646 nla_data( 1647 tb3[ 1648 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), 1649 len); 1650 if (! 1651 tb3[ 1652 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID 1653 ]) 1654 { 1655 ALOGE("%s: " 1656 "RESULTS_SCAN_RESULT_BSSID not found", 1657 __FUNCTION__); 1658 return WIFI_ERROR_INVALID_ARGS; 1659 } 1660 len = nla_len( 1661 tb3[ 1662 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]); 1663 len = 1664 sizeof(cached_results[i].results[j].bssid) <= len ? 1665 sizeof(cached_results[i].results[j].bssid) : len; 1666 memcpy(&cached_results[i].results[j].bssid, 1667 nla_data( 1668 tb3[ 1669 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), 1670 len); 1671 if (! 1672 tb3[ 1673 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL 1674 ]) 1675 { 1676 ALOGE("%s: " 1677 "RESULTS_SCAN_RESULT_CHANNEL not found", 1678 __FUNCTION__); 1679 return WIFI_ERROR_INVALID_ARGS; 1680 } 1681 cached_results[i].results[j].channel = 1682 nla_get_u32( 1683 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]); 1684 if (! 1685 tb3[ 1686 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI 1687 ]) 1688 { 1689 ALOGE("%s: " 1690 "RESULTS_SCAN_RESULT_RSSI not found", 1691 __FUNCTION__); 1692 return WIFI_ERROR_INVALID_ARGS; 1693 } 1694 cached_results[i].results[j].rssi = 1695 get_s32( 1696 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]); 1697 if (! 1698 tb3[ 1699 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT 1700 ]) 1701 { 1702 ALOGE("%s: " 1703 "RESULTS_SCAN_RESULT_RTT not found", 1704 __FUNCTION__); 1705 return WIFI_ERROR_INVALID_ARGS; 1706 } 1707 cached_results[i].results[j].rtt = 1708 nla_get_u32( 1709 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]); 1710 if (! 1711 tb3[ 1712 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD 1713 ]) 1714 { 1715 ALOGE("%s: " 1716 "RESULTS_SCAN_RESULT_RTT_SD not found", 1717 __FUNCTION__); 1718 return WIFI_ERROR_INVALID_ARGS; 1719 } 1720 cached_results[i].results[j].rtt_sd = 1721 nla_get_u32( 1722 tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]); 1723#ifdef QC_HAL_DEBUG 1724 /* Enable these prints for debugging if needed. */ 1725 ALOGD("%s: ts %" PRId64, __FUNCTION__, 1726 cached_results[i].results[j].ts); 1727 ALOGD("%s: SSID %s ", __FUNCTION__, 1728 cached_results[i].results[j].ssid); 1729 ALOGD("%s: BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n", 1730 __FUNCTION__, cached_results[i].results[j].bssid[0], 1731 cached_results[i].results[j].bssid[1], 1732 cached_results[i].results[j].bssid[2], 1733 cached_results[i].results[j].bssid[3], 1734 cached_results[i].results[j].bssid[4], 1735 cached_results[i].results[j].bssid[5]); 1736 ALOGD("%s: channel %d ", __FUNCTION__, 1737 cached_results[i].results[j].channel); 1738 ALOGD("%s: rssi %d ", __FUNCTION__, 1739 cached_results[i].results[j].rssi); 1740 ALOGD("%s: rtt %" PRId64, __FUNCTION__, 1741 cached_results[i].results[j].rtt); 1742 ALOGD("%s: rtt_sd %" PRId64, __FUNCTION__, 1743 cached_results[i].results[j].rtt_sd); 1744#endif 1745 /* Increment loop index for next record */ 1746 j++; 1747 /* For this scan id, update the wifiScanResultsStartingIndex 1748 * and number of cached results parsed so far. 1749 */ 1750 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = j; 1751 cached_results[i].num_results++; 1752 } else { 1753 /* We already parsed and stored up to max wifi_scan_results 1754 * specified by the caller. Now, continue to loop over NL 1755 * entries in order to properly update NL parsing pointer 1756 * so it points to the next scan_id results. 1757 */ 1758 ALOGD("%s: loop index:%d > max num" 1759 " of wifi_scan_results:%d for gscan cached results" 1760 " bucket:%d. Dummy loop", __FUNCTION__, 1761 j, MAX_AP_CACHE_PER_SCAN, i); 1762 } 1763 } 1764 ALOGV("%s: cached_results[%d].num_results: %d ", __FUNCTION__, 1765 i, cached_results[i].num_results); 1766 /* Increment loop index for next cached scan result record */ 1767 i++; 1768 } 1769 /* Increment starting index of filling cached results received */ 1770 if (mGetCachedResultsRspParams->num_cached_results) 1771 mGetCachedResultsRspParams->cachedResultsStartingIndex = 1772 mGetCachedResultsRspParams->num_cached_results - 1; 1773 return WIFI_SUCCESS; 1774} 1775 1776/* Set the GSCAN BSSID Hotlist. */ 1777wifi_error wifi_set_epno_list(wifi_request_id id, 1778 wifi_interface_handle iface, 1779 const wifi_epno_params *epno_params, 1780 wifi_epno_handler handler) 1781{ 1782 int i, ret = 0, num_networks; 1783 GScanCommand *gScanCommand; 1784 struct nlattr *nlData, *nlPnoParamList; 1785 interface_info *ifaceInfo = getIfaceInfo(iface); 1786 wifi_handle wifiHandle = getWifiHandle(iface); 1787 hal_info *info = getHalInfo(wifiHandle); 1788 gscan_event_handlers* event_handlers; 1789 GScanCommandEventHandler *gScanSetPnoListCmdEventHandler; 1790 1791 event_handlers = (gscan_event_handlers*)info->gscan_handlers; 1792 gScanSetPnoListCmdEventHandler = 1793 event_handlers->gScanSetPnoListCmdEventHandler; 1794 1795 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) { 1796 ALOGE("%s: Enhanced PNO is not supported by the driver", 1797 __FUNCTION__); 1798 return WIFI_ERROR_NOT_SUPPORTED; 1799 } 1800 1801 /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO 1802 * list was made earlier. If wifi_set_epno_list() is called while 1803 * another one is running, the request will be sent down to driver and 1804 * firmware. If the new request is successfully honored, then Wi-Fi HAL 1805 * will use the new request id for the gScanSetPnoListCmdEventHandler 1806 * object. 1807 */ 1808 1809 gScanCommand = 1810 new GScanCommand( 1811 wifiHandle, 1812 id, 1813 OUI_QCA, 1814 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST); 1815 if (gScanCommand == NULL) { 1816 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 1817 return WIFI_ERROR_UNKNOWN; 1818 } 1819 1820 /* Create the NL message. */ 1821 ret = gScanCommand->create(); 1822 if (ret < 0) { 1823 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret); 1824 goto cleanup; 1825 } 1826 1827 /* Set the interface Id of the message. */ 1828 ret = gScanCommand->set_iface_id(ifaceInfo->name); 1829 if (ret < 0) { 1830 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret); 1831 goto cleanup; 1832 } 1833 1834 /* Add the vendor specific attributes for the NL command. */ 1835 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 1836 if (!nlData) { 1837 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d", 1838 __FUNCTION__, ret); 1839 goto cleanup; 1840 } 1841 1842 num_networks = (unsigned int)epno_params->num_networks > MAX_EPNO_NETWORKS ? 1843 MAX_EPNO_NETWORKS : epno_params->num_networks; 1844 if (gScanCommand->put_u32( 1845 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 1846 id) || 1847 gScanCommand->put_u32( 1848 QCA_WLAN_VENDOR_ATTR_EPNO_MIN5GHZ_RSSI, 1849 epno_params->min5GHz_rssi) || 1850 gScanCommand->put_u32( 1851 QCA_WLAN_VENDOR_ATTR_EPNO_MIN24GHZ_RSSI, 1852 epno_params->min24GHz_rssi) || 1853 gScanCommand->put_u32( 1854 QCA_WLAN_VENDOR_ATTR_EPNO_INITIAL_SCORE_MAX, 1855 epno_params->initial_score_max) || 1856 gScanCommand->put_u32( 1857 QCA_WLAN_VENDOR_ATTR_EPNO_CURRENT_CONNECTION_BONUS, 1858 epno_params->current_connection_bonus) || 1859 gScanCommand->put_u32( 1860 QCA_WLAN_VENDOR_ATTR_EPNO_SAME_NETWORK_BONUS, 1861 epno_params->same_network_bonus) || 1862 gScanCommand->put_u32( 1863 QCA_WLAN_VENDOR_ATTR_EPNO_SECURE_BONUS, 1864 epno_params->secure_bonus) || 1865 gScanCommand->put_u32( 1866 QCA_WLAN_VENDOR_ATTR_EPNO_BAND5GHZ_BONUS, 1867 epno_params->band5GHz_bonus) || 1868 gScanCommand->put_u32( 1869 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS, 1870 num_networks)) 1871 { 1872 ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret); 1873 goto cleanup; 1874 } 1875 1876 /* Add the vendor specific attributes for the NL command. */ 1877 nlPnoParamList = 1878 gScanCommand->attr_start( 1879 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST); 1880 if (!nlPnoParamList) { 1881 ALOGE("%s: Failed to add attr. PNO_SET_LIST_PARAM_EPNO_NETWORKS_LIST. " 1882 "Error:%d", __FUNCTION__, ret); 1883 goto cleanup; 1884 } 1885 1886 /* Add nested NL attributes for ePno List. */ 1887 for (i = 0; i < num_networks; i++) { 1888 wifi_epno_network pnoNetwork = epno_params->networks[i]; 1889 struct nlattr *nlPnoNetwork = gScanCommand->attr_start(i); 1890 if (!nlPnoNetwork) { 1891 ALOGE("%s: Failed attr_start for nlPnoNetwork. Error:%d", 1892 __FUNCTION__, ret); 1893 goto cleanup; 1894 } 1895 if (gScanCommand->put_string( 1896 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_SSID, 1897 pnoNetwork.ssid) || 1898 gScanCommand->put_u8( 1899 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_FLAGS, 1900 pnoNetwork.flags) || 1901 gScanCommand->put_u8( 1902 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_EPNO_NETWORK_AUTH_BIT, 1903 pnoNetwork.auth_bit_field)) 1904 { 1905 ALOGE("%s: Failed to add PNO_SET_LIST_PARAM_EPNO_NETWORK_*. " 1906 "Error:%d", __FUNCTION__, ret); 1907 goto cleanup; 1908 } 1909 gScanCommand->attr_end(nlPnoNetwork); 1910 } 1911 1912 gScanCommand->attr_end(nlPnoParamList); 1913 1914 gScanCommand->attr_end(nlData); 1915 1916 GScanCallbackHandler callbackHandler; 1917 memset(&callbackHandler, 0, sizeof(callbackHandler)); 1918 callbackHandler.on_pno_network_found = handler.on_network_found; 1919 1920 /* Create an object of the event handler class to take care of the 1921 * asychronous events on the north-bound. 1922 */ 1923 if (gScanSetPnoListCmdEventHandler == NULL) { 1924 gScanSetPnoListCmdEventHandler = new GScanCommandEventHandler( 1925 wifiHandle, 1926 id, 1927 OUI_QCA, 1928 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST, 1929 callbackHandler); 1930 if (gScanSetPnoListCmdEventHandler == NULL) { 1931 ALOGE("%s: Error instantiating " 1932 "gScanSetPnoListCmdEventHandler.", __FUNCTION__); 1933 ret = WIFI_ERROR_UNKNOWN; 1934 goto cleanup; 1935 } 1936 event_handlers->gScanSetPnoListCmdEventHandler = 1937 gScanSetPnoListCmdEventHandler; 1938 } else { 1939 gScanSetPnoListCmdEventHandler->setCallbackHandler(callbackHandler); 1940 } 1941 1942 ret = gScanCommand->requestResponse(); 1943 if (ret != 0) { 1944 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 1945 goto cleanup; 1946 } 1947 1948 if (gScanSetPnoListCmdEventHandler != NULL) { 1949 gScanSetPnoListCmdEventHandler->set_request_id(id); 1950 gScanSetPnoListCmdEventHandler->enableEventHandling(); 1951 } 1952 1953cleanup: 1954 delete gScanCommand; 1955 /* Disable Event Handling if ret != 0 */ 1956 if (ret && gScanSetPnoListCmdEventHandler) { 1957 ALOGI("%s: Error ret:%d, disable event handling", 1958 __FUNCTION__, ret); 1959 gScanSetPnoListCmdEventHandler->disableEventHandling(); 1960 } 1961 return (wifi_error)ret; 1962} 1963 1964/* Reset the ePNO list - no ePNO networks should be matched after this */ 1965wifi_error wifi_reset_epno_list(wifi_request_id id, wifi_interface_handle iface) 1966{ 1967 int ret = 0; 1968 GScanCommand *gScanCommand; 1969 struct nlattr *nlData; 1970 interface_info *ifaceInfo = getIfaceInfo(iface); 1971 wifi_handle wifiHandle = getWifiHandle(iface); 1972 hal_info *info = getHalInfo(wifiHandle); 1973 1974 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) { 1975 ALOGE("%s: Enhanced PNO is not supported by the driver", 1976 __FUNCTION__); 1977 return WIFI_ERROR_NOT_SUPPORTED; 1978 } 1979 1980 gScanCommand = new GScanCommand(wifiHandle, 1981 id, 1982 OUI_QCA, 1983 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST); 1984 if (gScanCommand == NULL) { 1985 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 1986 return WIFI_ERROR_UNKNOWN; 1987 } 1988 1989 /* Create the NL message. */ 1990 ret = gScanCommand->create(); 1991 if (ret < 0) { 1992 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret); 1993 goto cleanup; 1994 } 1995 1996 /* Set the interface Id of the message. */ 1997 ret = gScanCommand->set_iface_id(ifaceInfo->name); 1998 if (ret < 0) { 1999 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret); 2000 goto cleanup; 2001 } 2002 2003 /* Add the vendor specific attributes for the NL command. */ 2004 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 2005 if (!nlData) { 2006 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d", 2007 __FUNCTION__, ret); 2008 goto cleanup; 2009 } 2010 2011 if (gScanCommand->put_u32( 2012 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 2013 id) || 2014 gScanCommand->put_u32( 2015 QCA_WLAN_VENDOR_ATTR_PNO_SET_LIST_PARAM_NUM_NETWORKS, 2016 EPNO_NO_NETWORKS)) 2017 { 2018 ALOGE("%s: Failed to add vendor atributes Error:%d", __FUNCTION__, ret); 2019 goto cleanup; 2020 } 2021 2022 gScanCommand->attr_end(nlData); 2023 2024 ret = gScanCommand->requestResponse(); 2025 if (ret != 0) { 2026 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 2027 } 2028 2029cleanup: 2030 delete gScanCommand; 2031 return (wifi_error)ret; 2032} 2033 2034/* Set the ePNO Passpoint List. */ 2035wifi_error wifi_set_passpoint_list(wifi_request_id id, 2036 wifi_interface_handle iface, int num, 2037 wifi_passpoint_network *networks, 2038 wifi_passpoint_event_handler handler) 2039{ 2040 int i, ret = 0; 2041 GScanCommand *gScanCommand; 2042 struct nlattr *nlData, *nlPasspointNetworksParamList; 2043 interface_info *ifaceInfo = getIfaceInfo(iface); 2044 wifi_handle wifiHandle = getWifiHandle(iface); 2045 hal_info *info = getHalInfo(wifiHandle); 2046 gscan_event_handlers* event_handlers; 2047 GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler; 2048 2049 event_handlers = (gscan_event_handlers*)info->gscan_handlers; 2050 gScanPnoSetPasspointListCmdEventHandler = 2051 event_handlers->gScanPnoSetPasspointListCmdEventHandler; 2052 2053 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) { 2054 ALOGE("%s: Enhanced PNO is not supported by the driver", 2055 __FUNCTION__); 2056 return WIFI_ERROR_NOT_SUPPORTED; 2057 } 2058 2059 /* Wi-Fi HAL doesn't need to check if a similar request to set ePNO 2060 * passpoint list was made earlier. If wifi_set_passpoint_list() is called 2061 * while another one is running, the request will be sent down to driver and 2062 * firmware. If the new request is successfully honored, then Wi-Fi HAL 2063 * will use the new request id for the 2064 * gScanPnoSetPasspointListCmdEventHandler object. 2065 */ 2066 gScanCommand = 2067 new GScanCommand( 2068 wifiHandle, 2069 id, 2070 OUI_QCA, 2071 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST); 2072 if (gScanCommand == NULL) { 2073 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 2074 return WIFI_ERROR_UNKNOWN; 2075 } 2076 2077 /* Create the NL message. */ 2078 ret = gScanCommand->create(); 2079 if (ret < 0) { 2080 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret); 2081 goto cleanup; 2082 } 2083 2084 /* Set the interface Id of the message. */ 2085 ret = gScanCommand->set_iface_id(ifaceInfo->name); 2086 if (ret < 0) { 2087 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret); 2088 goto cleanup; 2089 } 2090 2091 /* Add the vendor specific attributes for the NL command. */ 2092 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 2093 if (!nlData) { 2094 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d", 2095 __FUNCTION__, ret); 2096 goto cleanup; 2097 } 2098 2099 if (gScanCommand->put_u32( 2100 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, 2101 id) || 2102 gScanCommand->put_u32( 2103 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NUM, 2104 num)) 2105 { 2106 ALOGE("%s: Failed to add vendor atributes. Error:%d", __FUNCTION__, ret); 2107 goto cleanup; 2108 } 2109 2110 /* Add the vendor specific attributes for the NL command. */ 2111 nlPasspointNetworksParamList = 2112 gScanCommand->attr_start( 2113 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_LIST_PARAM_NETWORK_ARRAY); 2114 if (!nlPasspointNetworksParamList) { 2115 ALOGE("%s: Failed attr_start for PASSPOINT_LIST_PARAM_NETWORK_ARRAY. " 2116 "Error:%d", __FUNCTION__, ret); 2117 goto cleanup; 2118 } 2119 2120 /* Add nested NL attributes for Passpoint List param. */ 2121 for (i = 0; i < num; i++) { 2122 wifi_passpoint_network passpointNetwork = networks[i]; 2123 struct nlattr *nlPasspointNetworkParam = gScanCommand->attr_start(i); 2124 if (!nlPasspointNetworkParam) { 2125 ALOGE("%s: Failed attr_start for nlPasspointNetworkParam. " 2126 "Error:%d", __FUNCTION__, ret); 2127 goto cleanup; 2128 } 2129 if (gScanCommand->put_u32( 2130 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ID, 2131 passpointNetwork.id) || 2132 gScanCommand->put_string( 2133 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_REALM, 2134 passpointNetwork.realm) || 2135 gScanCommand->put_bytes( 2136 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_CNSRTM_ID, 2137 (char*)passpointNetwork.roamingConsortiumIds, 2138 16 * sizeof(int64_t)) || 2139 gScanCommand->put_bytes( 2140 QCA_WLAN_VENDOR_ATTR_PNO_PASSPOINT_NETWORK_PARAM_ROAM_PLMN, 2141 (char*)passpointNetwork.plmn, 3 * sizeof(u8))) 2142 { 2143 ALOGE("%s: Failed to add PNO_PASSPOINT_NETWORK_PARAM_ROAM_* attr. " 2144 "Error:%d", __FUNCTION__, ret); 2145 goto cleanup; 2146 } 2147 gScanCommand->attr_end(nlPasspointNetworkParam); 2148 } 2149 2150 gScanCommand->attr_end(nlPasspointNetworksParamList); 2151 2152 gScanCommand->attr_end(nlData); 2153 2154 GScanCallbackHandler callbackHandler; 2155 memset(&callbackHandler, 0, sizeof(callbackHandler)); 2156 callbackHandler.on_passpoint_network_found = 2157 handler.on_passpoint_network_found; 2158 2159 /* Create an object of the event handler class to take care of the 2160 * asychronous events on the north-bound. 2161 */ 2162 if (gScanPnoSetPasspointListCmdEventHandler == NULL) { 2163 gScanPnoSetPasspointListCmdEventHandler = new GScanCommandEventHandler( 2164 wifiHandle, 2165 id, 2166 OUI_QCA, 2167 QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST, 2168 callbackHandler); 2169 if (gScanPnoSetPasspointListCmdEventHandler == NULL) { 2170 ALOGE("%s: Error instantiating " 2171 "gScanPnoSetPasspointListCmdEventHandler.", __FUNCTION__); 2172 ret = WIFI_ERROR_UNKNOWN; 2173 goto cleanup; 2174 } 2175 event_handlers->gScanPnoSetPasspointListCmdEventHandler = 2176 gScanPnoSetPasspointListCmdEventHandler; 2177 } else { 2178 gScanPnoSetPasspointListCmdEventHandler->setCallbackHandler(callbackHandler); 2179 } 2180 2181 ret = gScanCommand->requestResponse(); 2182 if (ret != 0) { 2183 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 2184 goto cleanup; 2185 } 2186 2187 if (gScanPnoSetPasspointListCmdEventHandler != NULL) { 2188 gScanPnoSetPasspointListCmdEventHandler->set_request_id(id); 2189 gScanPnoSetPasspointListCmdEventHandler->enableEventHandling(); 2190 } 2191 2192cleanup: 2193 delete gScanCommand; 2194 /* Disable Event Handling if ret != 0 */ 2195 if (ret && gScanPnoSetPasspointListCmdEventHandler) { 2196 ALOGI("%s: Error ret:%d, disable event handling", 2197 __FUNCTION__, ret); 2198 gScanPnoSetPasspointListCmdEventHandler->disableEventHandling(); 2199 } 2200 return (wifi_error)ret; 2201} 2202 2203wifi_error wifi_reset_passpoint_list(wifi_request_id id, 2204 wifi_interface_handle iface) 2205{ 2206 int ret = 0; 2207 GScanCommand *gScanCommand; 2208 struct nlattr *nlData; 2209 interface_info *ifaceInfo = getIfaceInfo(iface); 2210 wifi_handle wifiHandle = getWifiHandle(iface); 2211 hal_info *info = getHalInfo(wifiHandle); 2212 gscan_event_handlers* event_handlers; 2213 GScanCommandEventHandler *gScanPnoSetPasspointListCmdEventHandler; 2214 2215 event_handlers = (gscan_event_handlers*)info->gscan_handlers; 2216 gScanPnoSetPasspointListCmdEventHandler = 2217 event_handlers->gScanPnoSetPasspointListCmdEventHandler; 2218 2219 if (!(info->supported_feature_set & WIFI_FEATURE_HAL_EPNO)) { 2220 ALOGE("%s: Enhanced PNO is not supported by the driver", 2221 __FUNCTION__); 2222 return WIFI_ERROR_NOT_SUPPORTED; 2223 } 2224 2225 if (gScanPnoSetPasspointListCmdEventHandler == NULL || 2226 (gScanPnoSetPasspointListCmdEventHandler->isEventHandlingEnabled() == 2227 false)) { 2228 ALOGE("wifi_reset_passpoint_list: ePNO passpoint_list isn't set. " 2229 "Nothing to do. Exit."); 2230 return WIFI_ERROR_NOT_AVAILABLE; 2231 } 2232 2233 gScanCommand = new GScanCommand( 2234 wifiHandle, 2235 id, 2236 OUI_QCA, 2237 QCA_NL80211_VENDOR_SUBCMD_PNO_RESET_PASSPOINT_LIST); 2238 2239 if (gScanCommand == NULL) { 2240 ALOGE("%s: Error GScanCommand NULL", __FUNCTION__); 2241 return WIFI_ERROR_UNKNOWN; 2242 } 2243 2244 /* Create the NL message. */ 2245 ret = gScanCommand->create(); 2246 if (ret < 0) { 2247 ALOGE("%s: Failed to create the NL msg. Error:%d", __FUNCTION__, ret); 2248 goto cleanup; 2249 } 2250 2251 /* Set the interface Id of the message. */ 2252 ret = gScanCommand->set_iface_id(ifaceInfo->name); 2253 if (ret < 0) { 2254 ALOGE("%s: Failed to set iface id. Error:%d", __FUNCTION__, ret); 2255 goto cleanup; 2256 } 2257 2258 /* Add the vendor specific attributes for the NL command. */ 2259 nlData = gScanCommand->attr_start(NL80211_ATTR_VENDOR_DATA); 2260 if (!nlData) { 2261 ALOGE("%s: Failed to add attribute NL80211_ATTR_VENDOR_DATA. Error:%d", 2262 __FUNCTION__, ret); 2263 goto cleanup; 2264 } 2265 2266 ret = gScanCommand->put_u32( 2267 QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, id); 2268 if (ret < 0) { 2269 ALOGE("%s: Failed to add vendor data attributes. Error:%d", 2270 __FUNCTION__, ret); 2271 goto cleanup; 2272 } 2273 2274 gScanCommand->attr_end(nlData); 2275 2276 ret = gScanCommand->requestResponse(); 2277 if (ret != 0) { 2278 ALOGE("%s: requestResponse Error:%d",__FUNCTION__, ret); 2279 } 2280 2281 /* Disable Event Handling. */ 2282 if (gScanPnoSetPasspointListCmdEventHandler) { 2283 gScanPnoSetPasspointListCmdEventHandler->disableEventHandling(); 2284 } 2285 2286cleanup: 2287 delete gScanCommand; 2288 return (wifi_error)ret; 2289} 2290 2291int GScanCommand::allocCachedResultsTemp(int max, 2292 wifi_cached_scan_results *cached_results) 2293{ 2294 /* Alloc memory for "max" number of cached results. */ 2295 mGetCachedResultsRspParams->cached_results = 2296 (wifi_cached_scan_results*) 2297 malloc(max * sizeof(wifi_cached_scan_results)); 2298 if (!mGetCachedResultsRspParams->cached_results) { 2299 ALOGE("%s: Failed to allocate memory for " 2300 "mGetCachedResultsRspParams->cached_results.", 2301 __FUNCTION__); 2302 return WIFI_ERROR_OUT_OF_MEMORY; 2303 } 2304 memset(mGetCachedResultsRspParams->cached_results, 0, 2305 max * sizeof(wifi_cached_scan_results)); 2306 2307 mGetCachedResultsRspParams->max = max; 2308 2309 return WIFI_SUCCESS; 2310} 2311 2312/* 2313 * Allocates memory for the subCmd response struct and initializes status = -1 2314 */ 2315int GScanCommand::allocRspParams(eGScanRspRarams cmd) 2316{ 2317 int ret = 0; 2318 switch(cmd) 2319 { 2320 case eGScanGetCachedResultsRspParams: 2321 mGetCachedResultsRspParams = (GScanGetCachedResultsRspParams *) 2322 malloc(sizeof(GScanGetCachedResultsRspParams)); 2323 if (!mGetCachedResultsRspParams) 2324 ret = -1; 2325 else { 2326 mGetCachedResultsRspParams->num_cached_results = 0; 2327 mGetCachedResultsRspParams->more_data = false; 2328 mGetCachedResultsRspParams->cachedResultsStartingIndex = -1; 2329 mGetCachedResultsRspParams->lastProcessedScanId = -1; 2330 mGetCachedResultsRspParams->wifiScanResultsStartingIndex = -1; 2331 mGetCachedResultsRspParams->max = 0; 2332 mGetCachedResultsRspParams->cached_results = NULL; 2333 } 2334 break; 2335 default: 2336 ALOGD("%s: Wrong request for alloc.", __FUNCTION__); 2337 ret = -1; 2338 } 2339 return ret; 2340} 2341 2342void GScanCommand::freeRspParams(eGScanRspRarams cmd) 2343{ 2344 switch(cmd) 2345 { 2346 case eGScanGetCachedResultsRspParams: 2347 if (mGetCachedResultsRspParams) { 2348 if (mGetCachedResultsRspParams->cached_results) { 2349 free(mGetCachedResultsRspParams->cached_results); 2350 mGetCachedResultsRspParams->cached_results = NULL; 2351 } 2352 free(mGetCachedResultsRspParams); 2353 mGetCachedResultsRspParams = NULL; 2354 } 2355 break; 2356 default: 2357 ALOGD("%s: Wrong request for free.", __FUNCTION__); 2358 } 2359} 2360 2361wifi_error GScanCommand::copyCachedScanResults( 2362 int *numResults, 2363 wifi_cached_scan_results *cached_results) 2364{ 2365 wifi_error ret = WIFI_SUCCESS; 2366 int i; 2367 wifi_cached_scan_results *cachedResultRsp; 2368 2369 if (mGetCachedResultsRspParams && cached_results) 2370 { 2371 /* Populate the number of parsed cached results. */ 2372 *numResults = mGetCachedResultsRspParams->num_cached_results; 2373 2374 for (i = 0; i < *numResults; i++) { 2375 cachedResultRsp = &mGetCachedResultsRspParams->cached_results[i]; 2376 cached_results[i].scan_id = cachedResultRsp->scan_id; 2377 cached_results[i].flags = cachedResultRsp->flags; 2378 cached_results[i].num_results = cachedResultRsp->num_results; 2379 cached_results[i].buckets_scanned = cachedResultRsp->buckets_scanned; 2380 2381 if (!cached_results[i].num_results) { 2382 ALOGI("Error: cached_results[%d].num_results=0", i); 2383 continue; 2384 } 2385 2386 ALOGV("copyCachedScanResults: " 2387 "cached_results[%d].num_results : %d", 2388 i, cached_results[i].num_results); 2389 2390 memcpy(cached_results[i].results, 2391 cachedResultRsp->results, 2392 cached_results[i].num_results * sizeof(wifi_scan_result)); 2393 } 2394 } else { 2395 ALOGE("%s: mGetCachedResultsRspParams is NULL", __FUNCTION__); 2396 *numResults = 0; 2397 ret = WIFI_ERROR_INVALID_ARGS; 2398 } 2399 return ret; 2400} 2401 2402void GScanCommand::setMaxChannels(int max_channels) { 2403 mMaxChannels = max_channels; 2404} 2405 2406void GScanCommand::setChannels(int *channels) { 2407 mChannels = channels; 2408} 2409 2410void GScanCommand::setNumChannelsPtr(int *num_channels) { 2411 mNumChannelsPtr = num_channels; 2412} 2413