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