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