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