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