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