Home | History | Annotate | Download | only in wifi_hal
      1 /* Copyright (c) 2014, 2018 The Linux Foundation. All rights reserved.
      2  *
      3  * Redistribution and use in source and binary forms, with or without
      4  * modification, are permitted provided that the following conditions
      5  * are met:
      6  *  * Redistributions of source code must retain the above copyright
      7  *    notice, this list of conditions and the following disclaimer.
      8  *  * Redistributions in binary form must reproduce the above copyright
      9  *    notice, this list of conditions and the following disclaimer in
     10  *    the documentation and/or other materials provided with the
     11  *    distribution.
     12  *  * Neither the name of The Linux Foundation nor the names of its
     13  *    contributors may be used to endorse or promote products derived
     14  *    from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     26  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include "sync.h"
     30 #define LOG_TAG  "WifiHAL"
     31 #include <utils/Log.h>
     32 #include <time.h>
     33 #include <errno.h>
     34 
     35 #include "ifaceeventhandler.h"
     36 
     37 /* Used to handle NL command events from driver/firmware. */
     38 IfaceEventHandlerCommand *mwifiEventHandler = NULL;
     39 
     40 /* Set the interface event monitor handler*/
     41 wifi_error wifi_set_iface_event_handler(wifi_request_id id,
     42                                         wifi_interface_handle iface,
     43                                         wifi_event_handler eh)
     44 {
     45     wifi_handle wifiHandle = getWifiHandle(iface);
     46 
     47     /* Check if a similar request to set iface event handler was made earlier.
     48      * Right now we don't differentiate between the case where (i) the new
     49      * Request Id is different from the current one vs (ii) both new and
     50      * Request Ids are the same.
     51      */
     52     if (mwifiEventHandler)
     53     {
     54         if (id == mwifiEventHandler->get_request_id()) {
     55             ALOGE("%s: Iface Event Handler Set for request Id %d is still"
     56                 "running. Exit", __func__, id);
     57             return WIFI_ERROR_TOO_MANY_REQUESTS;
     58         } else {
     59             ALOGE("%s: Iface Event Handler Set for a different Request "
     60                 "Id:%d is requested. Not supported. Exit", __func__, id);
     61             return WIFI_ERROR_NOT_SUPPORTED;
     62         }
     63     }
     64 
     65     mwifiEventHandler = new IfaceEventHandlerCommand(
     66                     wifiHandle,
     67                     id,
     68                     NL80211_CMD_REG_CHANGE);
     69     if (mwifiEventHandler == NULL) {
     70         ALOGE("%s: Error mwifiEventHandler NULL", __func__);
     71         return WIFI_ERROR_UNKNOWN;
     72     }
     73     mwifiEventHandler->setCallbackHandler(eh);
     74 
     75     return WIFI_SUCCESS;
     76 }
     77 
     78 /* Reset monitoring for the NL event*/
     79 wifi_error wifi_reset_iface_event_handler(wifi_request_id id,
     80                                           wifi_interface_handle iface)
     81 {
     82     if (mwifiEventHandler)
     83     {
     84         if (id == mwifiEventHandler->get_request_id()) {
     85             ALOGV("Delete Object mwifiEventHandler for id = %d", id);
     86             delete mwifiEventHandler;
     87             mwifiEventHandler = NULL;
     88         } else {
     89             ALOGE("%s: Iface Event Handler Set for a different Request "
     90                 "Id:%d is requested. Not supported. Exit", __func__, id);
     91             return WIFI_ERROR_NOT_SUPPORTED;
     92         }
     93     } else {
     94         ALOGV("Object mwifiEventHandler for id = %d already Deleted", id);
     95     }
     96 
     97     return WIFI_SUCCESS;
     98 }
     99 
    100 /* This function will be the main handler for the registered incoming
    101  * (from driver) Commads. Calls the appropriate callback handler after
    102  * parsing the vendor data.
    103  */
    104 int IfaceEventHandlerCommand::handleEvent(WifiEvent &event)
    105 {
    106     wifiEventHandler::handleEvent(event);
    107 
    108     switch(mSubcmd)
    109     {
    110         case NL80211_CMD_REG_CHANGE:
    111         {
    112             char code[2];
    113             memset(&code[0], 0, 2);
    114             if(tb[NL80211_ATTR_REG_ALPHA2])
    115             {
    116                 memcpy(&code[0], (char *) nla_data(tb[NL80211_ATTR_REG_ALPHA2]), 2);
    117             } else {
    118                 ALOGE("%s: NL80211_ATTR_REG_ALPHA2 not found", __func__);
    119             }
    120             ALOGV("Country : %c%c", code[0], code[1]);
    121             if(mHandler.on_country_code_changed)
    122             {
    123                 mHandler.on_country_code_changed(code);
    124             }
    125         }
    126         break;
    127         default:
    128             ALOGV("NL Event : %d Not supported", mSubcmd);
    129     }
    130 
    131     return NL_SKIP;
    132 }
    133 
    134 IfaceEventHandlerCommand::IfaceEventHandlerCommand(wifi_handle handle, int id, u32 subcmd)
    135         : wifiEventHandler(handle, id, subcmd)
    136 {
    137     ALOGV("wifiEventHandler %p constructed", this);
    138     registerHandler(mSubcmd);
    139     memset(&mHandler, 0, sizeof(wifi_event_handler));
    140     mEventData = NULL;
    141     mDataLen = 0;
    142 }
    143 
    144 IfaceEventHandlerCommand::~IfaceEventHandlerCommand()
    145 {
    146     ALOGV("IfaceEventHandlerCommand %p destructor", this);
    147     unregisterHandler(mSubcmd);
    148 }
    149 
    150 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler)
    151 {
    152     mHandler = nHandler;
    153 }
    154 
    155 int wifiEventHandler::get_request_id()
    156 {
    157     return mRequestId;
    158 }
    159 
    160 int IfaceEventHandlerCommand::get_request_id()
    161 {
    162     return wifiEventHandler::get_request_id();
    163 }
    164 
    165 wifiEventHandler::wifiEventHandler(wifi_handle handle, int id, u32 subcmd)
    166         : WifiCommand(handle, id)
    167 {
    168     mRequestId = id;
    169     mSubcmd = subcmd;
    170     registerHandler(mSubcmd);
    171     ALOGV("wifiEventHandler %p constructed", this);
    172 }
    173 
    174 wifiEventHandler::~wifiEventHandler()
    175 {
    176     ALOGV("wifiEventHandler %p destructor", this);
    177     unregisterHandler(mSubcmd);
    178 }
    179 
    180 int wifiEventHandler::handleEvent(WifiEvent &event)
    181 {
    182     struct genlmsghdr *gnlh = event.header();
    183     mSubcmd = gnlh->cmd;
    184     nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
    185             genlmsg_attrlen(gnlh, 0), NULL);
    186     ALOGV("Got NL Event : %d from the Driver.", gnlh->cmd);
    187 
    188     return NL_SKIP;
    189 }
    190 
    191 WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id,
    192                                   u32 subcmd)
    193         : WifiVendorCommand(handle, id, vendor_id, subcmd)
    194 {
    195     hal_info *info = getHalInfo(handle);
    196 
    197     /* Initialize the member data variables here */
    198     mSet = 0;
    199     mSetSizeMax = 0;
    200     mSetSizePtr = NULL;
    201     mConcurrencySet = 0;
    202     filterVersion = 0;
    203     filterLength = 0;
    204     firmware_bus_max_size = 0;
    205     mCapa = &(info->capa);
    206     mfilter_packet_read_buffer = NULL;
    207     mfilter_packet_length = 0;
    208 }
    209 
    210 WifihalGeneric::~WifihalGeneric()
    211 {
    212     mCapa = NULL;
    213 }
    214 
    215 wifi_error WifihalGeneric::requestResponse()
    216 {
    217     return WifiCommand::requestResponse(mMsg);
    218 }
    219 
    220 int WifihalGeneric::handleResponse(WifiEvent &reply)
    221 {
    222     ALOGV("Got a Wi-Fi HAL module message from Driver");
    223     int i = 0;
    224     WifiVendorCommand::handleResponse(reply);
    225 
    226     // Parse the vendordata and get the attribute
    227     switch(mSubcmd)
    228     {
    229         case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES:
    230             {
    231                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
    232                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
    233                         (struct nlattr *)mVendorData,
    234                         mDataLen, NULL);
    235 
    236                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET])
    237                 {
    238                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_FEATURE_SET not found", __func__);
    239                     return -EINVAL;
    240                 }
    241                 mSet = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
    242                 ALOGV("Supported feature set : %x", mSet);
    243 
    244                 break;
    245             }
    246         case QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX:
    247             {
    248                 struct nlattr *tb_vendor[
    249                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
    250                 nla_parse(tb_vendor,
    251                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
    252                     (struct nlattr *)mVendorData,mDataLen, NULL);
    253 
    254                 if (tb_vendor[
    255                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]) {
    256                     u32 val;
    257                     val = nla_get_u32(
    258                         tb_vendor[
    259                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]);
    260 
    261                     ALOGV("%s: Num of concurrency combinations: %d",
    262                         __func__, val);
    263                     val = val > (unsigned int)mSetSizeMax ?
    264                           (unsigned int)mSetSizeMax : val;
    265                     *mSetSizePtr = val;
    266 
    267                     /* Extract the list of channels. */
    268                     if (*mSetSizePtr > 0 &&
    269                         tb_vendor[
    270                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET]) {
    271                         nla_memcpy(mConcurrencySet,
    272                             tb_vendor[
    273                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET],
    274                             sizeof(feature_set) * (*mSetSizePtr));
    275                     }
    276 
    277                     ALOGV("%s: Get concurrency matrix response received.",
    278                         __func__);
    279                     ALOGV("%s: Num of concurrency combinations : %d",
    280                         __func__, *mSetSizePtr);
    281                     ALOGV("%s: List of valid concurrency combinations is: ",
    282                         __func__);
    283                     for(i = 0; i < *mSetSizePtr; i++)
    284                     {
    285                         ALOGV("%x", *(mConcurrencySet + i));
    286                     }
    287                 }
    288             }
    289             break;
    290         case QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER:
    291             {
    292                 int subCmd;
    293                 struct nlattr *tb_vendor[
    294                         QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
    295                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
    296                         (struct nlattr *)mVendorData,
    297                         mDataLen, NULL);
    298 
    299                 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD])
    300                 {
    301                     subCmd = nla_get_u32(
    302                            tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD]);
    303                 } else {
    304                     /*
    305                      * The older drivers may not send PACKET_FILTER_SUB_CMD as
    306                      * they support QCA_WLAN_GET_PACKET_FILTER_SIZE only.
    307                      */
    308                     subCmd = QCA_WLAN_GET_PACKET_FILTER_SIZE;
    309                 }
    310                 if (subCmd == QCA_WLAN_GET_PACKET_FILTER_SIZE) {
    311                     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION])
    312                     {
    313                         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION"
    314                               " not found", __FUNCTION__);
    315                         return -EINVAL;
    316                     }
    317                     filterVersion = nla_get_u32(
    318                            tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]);
    319                     ALOGV("Current version : %u", filterVersion);
    320 
    321                     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH])
    322                     {
    323                         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH"
    324                               " not found", __FUNCTION__);
    325                         return -EINVAL;
    326                     }
    327                     filterLength = nla_get_u32(
    328                         tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]);
    329                     ALOGV("Max filter length Supported : %u", filterLength);
    330                 } else if (subCmd == QCA_WLAN_READ_PACKET_FILTER) {
    331 
    332                    if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM])
    333                    {
    334                        ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM"
    335                              " not found", __FUNCTION__);
    336                        return -EINVAL;
    337                    }
    338                    if (nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM])
    339                            < mfilter_packet_length)
    340                    {
    341                        ALOGE("%s: Expected packet filter length :%d but received only: %d bytes",
    342                              __FUNCTION__, mfilter_packet_length,
    343                              nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM]));
    344                        return -EINVAL;
    345                    }
    346                    memcpy(mfilter_packet_read_buffer,
    347                       nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM]),
    348                       mfilter_packet_length);
    349                    ALOGV("Filter Program length : %u", mfilter_packet_length);
    350                 } else {
    351                        ALOGE("%s: Unknown APF sub command received",
    352                              __FUNCTION__);
    353                        return -EINVAL;
    354                 }
    355 
    356             }
    357             break;
    358         case QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE:
    359             {
    360                 struct nlattr *tb_vendor[
    361                         QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX + 1];
    362                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX,
    363                           (struct nlattr *)mVendorData, mDataLen, NULL);
    364 
    365                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE])
    366                 {
    367                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE"
    368                           " not found", __FUNCTION__);
    369                     return -EINVAL;
    370                 }
    371                 firmware_bus_max_size = nla_get_u32(
    372                        tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE]);
    373                 ALOGV("Max BUS size Supported: %d", firmware_bus_max_size);
    374             }
    375             break;
    376         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES:
    377             {
    378                 struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
    379                 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
    380                           (struct nlattr *)mVendorData,mDataLen, NULL);
    381 
    382                 if (wifiParseCapabilities(tbVendor) == WIFI_SUCCESS) {
    383                     ALOGV("%s: GSCAN Capabilities:\n"
    384                           "     max_ap_cache_per_scan:%d\n"
    385                           "     max_bssid_history_entries:%d\n"
    386                           "     max_hotlist_bssids:%d\n"
    387                           "     max_hotlist_ssids:%d\n"
    388                           "     max_rssi_sample_size:%d\n"
    389                           "     max_scan_buckets:%d\n"
    390                           "     max_scan_cache_size:%d\n"
    391                           "     max_scan_reporting_threshold:%d\n"
    392                           "     max_significant_wifi_change_aps:%d\n"
    393                           "     max_number_epno_networks:%d\n"
    394                           "     max_number_epno_networks_by_ssid:%d\n"
    395                           "     max_number_of_white_listed_ssid:%d.",
    396                           __FUNCTION__, mCapa->gscan_capa.max_ap_cache_per_scan,
    397                           mCapa->gscan_capa.max_bssid_history_entries,
    398                           mCapa->gscan_capa.max_hotlist_bssids,
    399                           mCapa->gscan_capa.max_hotlist_ssids,
    400                           mCapa->gscan_capa.max_rssi_sample_size,
    401                           mCapa->gscan_capa.max_scan_buckets,
    402                           mCapa->gscan_capa.max_scan_cache_size,
    403                           mCapa->gscan_capa.max_scan_reporting_threshold,
    404                           mCapa->gscan_capa.max_significant_wifi_change_aps,
    405                           mCapa->gscan_capa.max_number_epno_networks,
    406                           mCapa->gscan_capa.max_number_epno_networks_by_ssid,
    407                           mCapa->gscan_capa.max_number_of_white_listed_ssid);
    408 
    409                     ALOGV("%s: Roaming Capabilities:\n"
    410                           "    max_blacklist_size: %d\n"
    411                           "    max_whitelist_size: %d\n",
    412                           __FUNCTION__, mCapa->roaming_capa.max_blacklist_size,
    413                           mCapa->roaming_capa.max_whitelist_size);
    414                 }
    415             }
    416             break;
    417         default :
    418             ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
    419     }
    420     return NL_SKIP;
    421 }
    422 
    423 /* Parses and extract capabilities results. */
    424 wifi_error WifihalGeneric::wifiParseCapabilities(struct nlattr **tbVendor)
    425 {
    426     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]) {
    427         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE not found",
    428               __FUNCTION__);
    429         return WIFI_ERROR_INVALID_ARGS;
    430     }
    431     mCapa->gscan_capa.max_scan_cache_size = nla_get_u32(tbVendor[
    432                               QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]);
    433 
    434     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]) {
    435         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS not found",
    436               __FUNCTION__);
    437         return WIFI_ERROR_INVALID_ARGS;
    438     }
    439     mCapa->gscan_capa.max_scan_buckets = nla_get_u32(tbVendor[
    440                                  QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]);
    441 
    442     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]) {
    443         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN not found",
    444               __FUNCTION__);
    445         return WIFI_ERROR_INVALID_ARGS;
    446     }
    447     mCapa->gscan_capa.max_ap_cache_per_scan = nla_get_u32(tbVendor[
    448                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]);
    449 
    450     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]) {
    451         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE not found",
    452               __FUNCTION__);
    453         return WIFI_ERROR_INVALID_ARGS;
    454     }
    455     mCapa->gscan_capa.max_rssi_sample_size = nla_get_u32(tbVendor[
    456                              QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]);
    457 
    458     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]) {
    459         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD not"
    460               " found", __FUNCTION__);
    461         return WIFI_ERROR_INVALID_ARGS;
    462     }
    463     mCapa->gscan_capa.max_scan_reporting_threshold = nla_get_u32(tbVendor[
    464                      QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]);
    465 
    466     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]) {
    467         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS not found",
    468               __FUNCTION__);
    469         return WIFI_ERROR_INVALID_ARGS;
    470     }
    471     mCapa->gscan_capa.max_hotlist_bssids = nla_get_u32(tbVendor[
    472                                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]);
    473 
    474     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]
    475        ) {
    476         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS "
    477               "not found", __FUNCTION__);
    478         return WIFI_ERROR_INVALID_ARGS;
    479     }
    480     mCapa->gscan_capa.max_significant_wifi_change_aps = nla_get_u32(tbVendor[
    481                   QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]);
    482 
    483     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]) {
    484         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES not "
    485               "found", __FUNCTION__);
    486         return WIFI_ERROR_INVALID_ARGS;
    487     }
    488     mCapa->gscan_capa.max_bssid_history_entries = nla_get_u32(tbVendor[
    489                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]);
    490 
    491     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]) {
    492         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS not found. Set"
    493               " to 0.", __FUNCTION__);
    494         mCapa->gscan_capa.max_hotlist_ssids = 0;
    495     } else {
    496         mCapa->gscan_capa.max_hotlist_ssids = nla_get_u32(tbVendor[
    497                                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]);
    498     }
    499 
    500     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS]) {
    501         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS not found. Set"
    502               " to 0.", __FUNCTION__);
    503         mCapa->gscan_capa.max_number_epno_networks = 0;
    504     } else {
    505         mCapa->gscan_capa.max_number_epno_networks
    506             = nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
    507                                   ]);
    508     }
    509 
    510     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]) {
    511         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID not "
    512               "found. Set to 0.", __FUNCTION__);
    513         mCapa->gscan_capa.max_number_epno_networks_by_ssid = 0;
    514     } else {
    515         mCapa->gscan_capa.max_number_epno_networks_by_ssid = nla_get_u32(tbVendor[
    516                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]);
    517     }
    518 
    519     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]) {
    520         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID not "
    521               "found. Set to 0.", __FUNCTION__);
    522         mCapa->gscan_capa.max_number_of_white_listed_ssid = 0;
    523         mCapa->roaming_capa.max_whitelist_size = 0;
    524     } else {
    525         mCapa->gscan_capa.max_number_of_white_listed_ssid = nla_get_u32(tbVendor[
    526                          QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]);
    527         mCapa->roaming_capa.max_whitelist_size = mCapa->gscan_capa.max_number_of_white_listed_ssid;
    528     }
    529 
    530     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_CAPABILITIES_MAX_NUM_BLACKLISTED_BSSID]) {
    531         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
    532             "_NUM_BLACKLIST_BSSID not found. Set to 0.", __FUNCTION__);
    533         mCapa->roaming_capa.max_blacklist_size = 0;
    534     } else {
    535         mCapa->roaming_capa.max_blacklist_size = nla_get_u32(tbVendor[
    536                                       QCA_WLAN_VENDOR_ATTR_CAPABILITIES_MAX_NUM_BLACKLISTED_BSSID]);
    537     }
    538     return WIFI_SUCCESS;
    539 }
    540 
    541 void WifihalGeneric::getResponseparams(feature_set *pset)
    542 {
    543     *pset = mSet;
    544 }
    545 
    546 void WifihalGeneric::setMaxSetSize(int set_size_max) {
    547     mSetSizeMax = set_size_max;
    548 }
    549 
    550 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
    551     mConcurrencySet = set;
    552 }
    553 
    554 void WifihalGeneric::setSizePtr(int *set_size) {
    555     mSetSizePtr = set_size;
    556 }
    557 
    558 int WifihalGeneric::getFilterVersion() {
    559     return filterVersion;
    560 }
    561 
    562 int WifihalGeneric::getFilterLength() {
    563     return filterLength;
    564 }
    565 void WifihalGeneric::setPacketBufferParams(u8 *host_packet_buffer, int packet_length) {
    566     mfilter_packet_read_buffer = host_packet_buffer;
    567     mfilter_packet_length = packet_length;
    568 }
    569 
    570 int WifihalGeneric::getBusSize() {
    571     return firmware_bus_max_size;
    572 }
    573 
    574 wifi_error WifihalGeneric::wifiGetCapabilities(wifi_interface_handle handle)
    575 {
    576     wifi_error ret;
    577     struct nlattr *nlData;
    578     interface_info *ifaceInfo = getIfaceInfo(handle);
    579 
    580     /* Create the NL message. */
    581     ret = create();
    582     if (ret != WIFI_SUCCESS) {
    583         ALOGE("%s: Failed to create NL message,  Error:%d", __FUNCTION__, ret);
    584         return ret;
    585     }
    586 
    587     /* Set the interface Id of the message. */
    588     ret = set_iface_id(ifaceInfo->name);
    589     if (ret != WIFI_SUCCESS) {
    590         ALOGE("%s: Failed to set interface Id of message, Error:%d", __FUNCTION__, ret);
    591         return ret;
    592     }
    593 
    594     /* Add the vendor specific attributes for the NL command. */
    595     nlData = attr_start(NL80211_ATTR_VENDOR_DATA);
    596     if (!nlData)
    597         return WIFI_ERROR_OUT_OF_MEMORY;
    598 
    599     ret = put_u32(QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, mId);
    600     if (ret != WIFI_SUCCESS) {
    601         ALOGE("%s: Failed to add request_ID to NL command, Error:%d", __FUNCTION__, ret);
    602         return ret;
    603     }
    604 
    605     attr_end(nlData);
    606 
    607     ret = requestResponse();
    608     if (ret != WIFI_SUCCESS)
    609         ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
    610 
    611     return ret;
    612 }
    613