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