Home | History | Annotate | Download | only in wifi_hal
      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