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