1 /* Copyright (c) 2014, 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 
34 #include "ifaceeventhandler.h"
35 
36 /* Used to handle NL command events from driver/firmware. */
37 IfaceEventHandlerCommand *mwifiEventHandler = NULL;
38 
39 /* Set the interface event monitor handler*/
wifi_set_iface_event_handler(wifi_request_id id,wifi_interface_handle iface,wifi_event_handler eh)40 wifi_error wifi_set_iface_event_handler(wifi_request_id id,
41                                         wifi_interface_handle iface,
42                                         wifi_event_handler eh)
43 {
44     int ret = 0;
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_error)ret;
76 }
77 
78 /* Reset monitoring for the NL event*/
wifi_reset_iface_event_handler(wifi_request_id id,wifi_interface_handle iface)79 wifi_error wifi_reset_iface_event_handler(wifi_request_id id,
80                                           wifi_interface_handle iface)
81 {
82     int ret = 0;
83 
84     if (mwifiEventHandler)
85     {
86         if (id == mwifiEventHandler->get_request_id()) {
87             ALOGV("Delete Object mwifiEventHandler for id = %d", id);
88             delete mwifiEventHandler;
89             mwifiEventHandler = NULL;
90         } else {
91             ALOGE("%s: Iface Event Handler Set for a different Request "
92                 "Id:%d is requested. Not supported. Exit", __func__, id);
93             return WIFI_ERROR_NOT_SUPPORTED;
94         }
95     } else {
96         ALOGV("Object mwifiEventHandler for id = %d already Deleted", id);
97     }
98 
99     return (wifi_error)ret;
100 }
101 
102 /* This function will be the main handler for the registered incoming
103  * (from driver) Commads. Calls the appropriate callback handler after
104  * parsing the vendor data.
105  */
handleEvent(WifiEvent & event)106 int IfaceEventHandlerCommand::handleEvent(WifiEvent &event)
107 {
108     wifiEventHandler::handleEvent(event);
109 
110     switch(mSubcmd)
111     {
112         case NL80211_CMD_REG_CHANGE:
113         {
114             char code[2];
115             memset(&code[0], 0, 2);
116             if(tb[NL80211_ATTR_REG_ALPHA2])
117             {
118                 memcpy(&code[0], (char *) nla_data(tb[NL80211_ATTR_REG_ALPHA2]), 2);
119             } else {
120                 ALOGE("%s: NL80211_ATTR_REG_ALPHA2 not found", __func__);
121             }
122             ALOGV("Country : %c%c", code[0], code[1]);
123             if(mHandler.on_country_code_changed)
124             {
125                 mHandler.on_country_code_changed(code);
126             }
127         }
128         break;
129         default:
130             ALOGV("NL Event : %d Not supported", mSubcmd);
131     }
132 
133     return NL_SKIP;
134 }
135 
IfaceEventHandlerCommand(wifi_handle handle,int id,u32 subcmd)136 IfaceEventHandlerCommand::IfaceEventHandlerCommand(wifi_handle handle, int id, u32 subcmd)
137         : wifiEventHandler(handle, id, subcmd)
138 {
139     ALOGV("wifiEventHandler %p constructed", this);
140     registerHandler(mSubcmd);
141     memset(&mHandler, 0, sizeof(wifi_event_handler));
142     mEventData = NULL;
143     mDataLen = 0;
144 }
145 
~IfaceEventHandlerCommand()146 IfaceEventHandlerCommand::~IfaceEventHandlerCommand()
147 {
148     ALOGV("IfaceEventHandlerCommand %p destructor", this);
149     unregisterHandler(mSubcmd);
150 }
151 
setCallbackHandler(wifi_event_handler nHandler)152 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler)
153 {
154     mHandler = nHandler;
155 }
156 
get_request_id()157 int wifiEventHandler::get_request_id()
158 {
159     return mRequestId;
160 }
161 
get_request_id()162 int IfaceEventHandlerCommand::get_request_id()
163 {
164     return wifiEventHandler::get_request_id();
165 }
166 
wifiEventHandler(wifi_handle handle,int id,u32 subcmd)167 wifiEventHandler::wifiEventHandler(wifi_handle handle, int id, u32 subcmd)
168         : WifiCommand(handle, id)
169 {
170     mRequestId = id;
171     mSubcmd = subcmd;
172     registerHandler(mSubcmd);
173     ALOGV("wifiEventHandler %p constructed", this);
174 }
175 
~wifiEventHandler()176 wifiEventHandler::~wifiEventHandler()
177 {
178     ALOGV("wifiEventHandler %p destructor", this);
179     unregisterHandler(mSubcmd);
180 }
181 
handleEvent(WifiEvent & event)182 int wifiEventHandler::handleEvent(WifiEvent &event)
183 {
184     struct genlmsghdr *gnlh = event.header();
185     mSubcmd = gnlh->cmd;
186     nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
187             genlmsg_attrlen(gnlh, 0), NULL);
188     ALOGV("Got NL Event : %d from the Driver.", gnlh->cmd);
189 
190     return NL_SKIP;
191 }
192 
WifihalGeneric(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)193 WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id,
194                                   u32 subcmd)
195         : WifiVendorCommand(handle, id, vendor_id, subcmd)
196 {
197     hal_info *info = getHalInfo(handle);
198 
199     /* Initialize the member data variables here */
200     mSet = 0;
201     mSetSizeMax = 0;
202     mSetSizePtr = NULL;
203     mConcurrencySet = 0;
204     filterVersion = 0;
205     filterLength = 0;
206     firmware_bus_max_size = 0;
207     mCapa = &(info->capa);
208 }
209 
~WifihalGeneric()210 WifihalGeneric::~WifihalGeneric()
211 {
212     mCapa = NULL;
213 }
214 
requestResponse()215 int WifihalGeneric::requestResponse()
216 {
217     return WifiCommand::requestResponse(mMsg);
218 }
219 
handleResponse(WifiEvent & reply)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 WIFI_ERROR_INVALID_ARGS;
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                 struct nlattr *tb_vendor[
293                         QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
294                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
295                         (struct nlattr *)mVendorData,
296                         mDataLen, NULL);
297 
298                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION])
299                 {
300                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION"
301                           " not found", __FUNCTION__);
302                     return WIFI_ERROR_INVALID_ARGS;
303                 }
304                 filterVersion = nla_get_u32(
305                        tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]);
306                 ALOGV("Current version : %u", filterVersion);
307 
308                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH])
309                 {
310                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH"
311                           " not found", __FUNCTION__);
312                     return WIFI_ERROR_INVALID_ARGS;
313                 }
314                 filterLength = nla_get_u32(
315                     tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]);
316                 ALOGV("Max filter length Supported : %u", filterLength);
317 
318             }
319             break;
320         case QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE:
321             {
322                 struct nlattr *tb_vendor[
323                         QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX + 1];
324                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX,
325                           (struct nlattr *)mVendorData, mDataLen, NULL);
326 
327                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE])
328                 {
329                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE"
330                           " not found", __FUNCTION__);
331                     return WIFI_ERROR_INVALID_ARGS;
332                 }
333                 firmware_bus_max_size = nla_get_u32(
334                        tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE]);
335                 ALOGV("Max BUS size Supported: %d", firmware_bus_max_size);
336             }
337             break;
338         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES:
339             {
340                 struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
341                 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
342                           (struct nlattr *)mVendorData,mDataLen, NULL);
343 
344                 if (wifiParseCapabilities(tbVendor) == WIFI_SUCCESS) {
345                     ALOGV("%s: GSCAN Capabilities:\n"
346                           "     max_ap_cache_per_scan:%d\n"
347                           "     max_bssid_history_entries:%d\n"
348                           "     max_hotlist_bssids:%d\n"
349                           "     max_hotlist_ssids:%d\n"
350                           "     max_rssi_sample_size:%d\n"
351                           "     max_scan_buckets:%d\n"
352                           "     max_scan_cache_size:%d\n"
353                           "     max_scan_reporting_threshold:%d\n"
354                           "     max_significant_wifi_change_aps:%d\n"
355                           "     max_number_epno_networks:%d\n"
356                           "     max_number_epno_networks_by_ssid:%d\n"
357                           "     max_number_of_white_listed_ssid:%d.",
358                           __FUNCTION__, mCapa->gscan_capa.max_ap_cache_per_scan,
359                           mCapa->gscan_capa.max_bssid_history_entries,
360                           mCapa->gscan_capa.max_hotlist_bssids,
361                           mCapa->gscan_capa.max_hotlist_ssids,
362                           mCapa->gscan_capa.max_rssi_sample_size,
363                           mCapa->gscan_capa.max_scan_buckets,
364                           mCapa->gscan_capa.max_scan_cache_size,
365                           mCapa->gscan_capa.max_scan_reporting_threshold,
366                           mCapa->gscan_capa.max_significant_wifi_change_aps,
367                           mCapa->gscan_capa.max_number_epno_networks,
368                           mCapa->gscan_capa.max_number_epno_networks_by_ssid,
369                           mCapa->gscan_capa.max_number_of_white_listed_ssid);
370 
371                     ALOGV("%s: Roaming Capabilities:\n"
372                           "    max_blacklist_size: %d\n"
373                           "    max_whitelist_size: %d\n",
374                           __FUNCTION__, mCapa->roaming_capa.max_blacklist_size,
375                           mCapa->roaming_capa.max_whitelist_size);
376                 }
377             }
378             break;
379         default :
380             ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
381     }
382     return NL_SKIP;
383 }
384 
385 /* Parses and extract capabilities results. */
wifiParseCapabilities(struct nlattr ** tbVendor)386 wifi_error WifihalGeneric::wifiParseCapabilities(struct nlattr **tbVendor)
387 {
388     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]) {
389         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE not found",
390               __FUNCTION__);
391         return WIFI_ERROR_INVALID_ARGS;
392     }
393     mCapa->gscan_capa.max_scan_cache_size = nla_get_u32(tbVendor[
394                               QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]);
395 
396     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]) {
397         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS not found",
398               __FUNCTION__);
399         return WIFI_ERROR_INVALID_ARGS;
400     }
401     mCapa->gscan_capa.max_scan_buckets = nla_get_u32(tbVendor[
402                                  QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]);
403 
404     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]) {
405         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN not found",
406               __FUNCTION__);
407         return WIFI_ERROR_INVALID_ARGS;
408     }
409     mCapa->gscan_capa.max_ap_cache_per_scan = nla_get_u32(tbVendor[
410                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]);
411 
412     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]) {
413         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE not found",
414               __FUNCTION__);
415         return WIFI_ERROR_INVALID_ARGS;
416     }
417     mCapa->gscan_capa.max_rssi_sample_size = nla_get_u32(tbVendor[
418                              QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]);
419 
420     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]) {
421         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD not"
422               " found", __FUNCTION__);
423         return WIFI_ERROR_INVALID_ARGS;
424     }
425     mCapa->gscan_capa.max_scan_reporting_threshold = nla_get_u32(tbVendor[
426                      QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]);
427 
428     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]) {
429         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS not found",
430               __FUNCTION__);
431         return WIFI_ERROR_INVALID_ARGS;
432     }
433     mCapa->gscan_capa.max_hotlist_bssids = nla_get_u32(tbVendor[
434                                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]);
435 
436     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]
437        ) {
438         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS "
439               "not found", __FUNCTION__);
440         return WIFI_ERROR_INVALID_ARGS;
441     }
442     mCapa->gscan_capa.max_significant_wifi_change_aps = nla_get_u32(tbVendor[
443                   QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]);
444 
445     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]) {
446         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES not "
447               "found", __FUNCTION__);
448         return WIFI_ERROR_INVALID_ARGS;
449     }
450     mCapa->gscan_capa.max_bssid_history_entries = nla_get_u32(tbVendor[
451                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]);
452 
453     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]) {
454         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS not found. Set"
455               " to 0.", __FUNCTION__);
456         mCapa->gscan_capa.max_hotlist_ssids = 0;
457     } else {
458         mCapa->gscan_capa.max_hotlist_ssids = nla_get_u32(tbVendor[
459                                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]);
460     }
461 
462     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS]) {
463         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS not found. Set"
464               " to 0.", __FUNCTION__);
465         mCapa->gscan_capa.max_number_epno_networks = 0;
466     } else {
467         mCapa->gscan_capa.max_number_epno_networks
468             = nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
469                                   ]);
470     }
471 
472     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]) {
473         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID not "
474               "found. Set to 0.", __FUNCTION__);
475         mCapa->gscan_capa.max_number_epno_networks_by_ssid = 0;
476     } else {
477         mCapa->gscan_capa.max_number_epno_networks_by_ssid = nla_get_u32(tbVendor[
478                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]);
479     }
480 
481     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]) {
482         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID not "
483               "found. Set to 0.", __FUNCTION__);
484         mCapa->gscan_capa.max_number_of_white_listed_ssid = 0;
485         mCapa->roaming_capa.max_whitelist_size = 0;
486     } else {
487         mCapa->gscan_capa.max_number_of_white_listed_ssid = nla_get_u32(tbVendor[
488                          QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]);
489         mCapa->roaming_capa.max_whitelist_size = mCapa->gscan_capa.max_number_of_white_listed_ssid;
490     }
491 
492     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_CAPABILITIES_MAX_NUM_BLACKLISTED_BSSID]) {
493         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
494             "_NUM_BLACKLIST_BSSID not found. Set to 0.", __FUNCTION__);
495         mCapa->roaming_capa.max_blacklist_size = 0;
496     } else {
497         mCapa->roaming_capa.max_blacklist_size = nla_get_u32(tbVendor[
498                                       QCA_WLAN_VENDOR_ATTR_CAPABILITIES_MAX_NUM_BLACKLISTED_BSSID]);
499     }
500     return WIFI_SUCCESS;
501 }
502 
getResponseparams(feature_set * pset)503 void WifihalGeneric::getResponseparams(feature_set *pset)
504 {
505     *pset = mSet;
506 }
507 
setMaxSetSize(int set_size_max)508 void WifihalGeneric::setMaxSetSize(int set_size_max) {
509     mSetSizeMax = set_size_max;
510 }
511 
setConcurrencySet(feature_set set[])512 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
513     mConcurrencySet = set;
514 }
515 
setSizePtr(int * set_size)516 void WifihalGeneric::setSizePtr(int *set_size) {
517     mSetSizePtr = set_size;
518 }
519 
getFilterVersion()520 int WifihalGeneric::getFilterVersion() {
521     return filterVersion;
522 }
523 
getFilterLength()524 int WifihalGeneric::getFilterLength() {
525     return filterLength;
526 }
527 
getBusSize()528 int WifihalGeneric::getBusSize() {
529     return firmware_bus_max_size;
530 }
531 
wifiGetCapabilities(wifi_interface_handle handle)532 wifi_error WifihalGeneric::wifiGetCapabilities(wifi_interface_handle handle)
533 {
534     int ret;
535     struct nlattr *nlData;
536     interface_info *ifaceInfo = getIfaceInfo(handle);
537 
538     /* Create the NL message. */
539     ret = create();
540     if (ret < 0) {
541         ALOGE("%s: Failed to create NL message,  Error:%d", __FUNCTION__, ret);
542         return WIFI_ERROR_UNKNOWN;
543     }
544 
545     /* Set the interface Id of the message. */
546     ret = set_iface_id(ifaceInfo->name);
547     if (ret < 0) {
548         ALOGE("%s: Failed to set interface Id of message, Error:%d", __FUNCTION__, ret);
549         return WIFI_ERROR_UNKNOWN;
550     }
551 
552     /* Add the vendor specific attributes for the NL command. */
553     nlData = attr_start(NL80211_ATTR_VENDOR_DATA);
554     if (!nlData)
555         return WIFI_ERROR_UNKNOWN;
556 
557     ret = put_u32(QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, mId);
558     if (ret < 0) {
559         ALOGE("%s: Failed to add request_ID to NL command, Error:%d", __FUNCTION__, ret);
560         return WIFI_ERROR_UNKNOWN;
561     }
562 
563     attr_end(nlData);
564 
565     ret = requestResponse();
566     if (ret != 0) {
567         ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
568         return WIFI_ERROR_UNKNOWN;
569     }
570 
571     return WIFI_SUCCESS;
572 }
573