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