• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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*/
wifi_set_iface_event_handler(wifi_request_id id,wifi_interface_handle iface,wifi_event_handler eh)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*/
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     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  */
handleEvent(WifiEvent & event)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 
IfaceEventHandlerCommand(wifi_handle handle,int id,u32 subcmd)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 
~IfaceEventHandlerCommand()144 IfaceEventHandlerCommand::~IfaceEventHandlerCommand()
145 {
146     ALOGV("IfaceEventHandlerCommand %p destructor", this);
147     unregisterHandler(mSubcmd);
148 }
149 
setCallbackHandler(wifi_event_handler nHandler)150 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler)
151 {
152     mHandler = nHandler;
153 }
154 
get_request_id()155 int wifiEventHandler::get_request_id()
156 {
157     return mRequestId;
158 }
159 
get_request_id()160 int IfaceEventHandlerCommand::get_request_id()
161 {
162     return wifiEventHandler::get_request_id();
163 }
164 
wifiEventHandler(wifi_handle handle,int id,u32 subcmd)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 
~wifiEventHandler()174 wifiEventHandler::~wifiEventHandler()
175 {
176     ALOGV("wifiEventHandler %p destructor", this);
177     unregisterHandler(mSubcmd);
178 }
179 
handleEvent(WifiEvent & event)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 
WifihalGeneric(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)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     memset(&mDriverFeatures, 0, sizeof(mDriverFeatures));
209 }
210 
~WifihalGeneric()211 WifihalGeneric::~WifihalGeneric()
212 {
213     mCapa = NULL;
214     if (mDriverFeatures.flags != NULL) {
215         free(mDriverFeatures.flags);
216         mDriverFeatures.flags = NULL;
217     }
218 }
219 
requestResponse()220 wifi_error WifihalGeneric::requestResponse()
221 {
222     return WifiCommand::requestResponse(mMsg);
223 }
224 
handleResponse(WifiEvent & reply)225 int WifihalGeneric::handleResponse(WifiEvent &reply)
226 {
227     ALOGV("Got a Wi-Fi HAL module message from Driver");
228     int i = 0;
229     WifiVendorCommand::handleResponse(reply);
230 
231     // Parse the vendordata and get the attribute
232     switch(mSubcmd)
233     {
234         case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES:
235             {
236                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
237                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
238                         (struct nlattr *)mVendorData,
239                         mDataLen, NULL);
240 
241                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET])
242                 {
243                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_FEATURE_SET not found", __func__);
244                     return -EINVAL;
245                 }
246                 mSet = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
247                 ALOGV("Supported feature set : %x", mSet);
248 
249                 break;
250             }
251         case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
252             {
253                 struct nlattr *attr;
254                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
255                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
256                           (struct nlattr *)mVendorData, mDataLen, NULL);
257                 attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS];
258                 if (attr) {
259                     int len = nla_len(attr);
260                     mDriverFeatures.flags = (u8 *)malloc(len);
261                     if (mDriverFeatures.flags != NULL) {
262                         memcpy(mDriverFeatures.flags, nla_data(attr), len);
263                         mDriverFeatures.flags_len = len;
264                     }
265                  }
266                  break;
267             }
268         case QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX:
269             {
270                 struct nlattr *tb_vendor[
271                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
272                 nla_parse(tb_vendor,
273                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
274                     (struct nlattr *)mVendorData,mDataLen, NULL);
275 
276                 if (tb_vendor[
277                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]) {
278                     u32 val;
279                     val = nla_get_u32(
280                         tb_vendor[
281                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]);
282 
283                     ALOGV("%s: Num of concurrency combinations: %d",
284                         __func__, val);
285                     val = val > (unsigned int)mSetSizeMax ?
286                           (unsigned int)mSetSizeMax : val;
287                     *mSetSizePtr = val;
288 
289                     /* Extract the list of channels. */
290                     if (*mSetSizePtr > 0 &&
291                         tb_vendor[
292                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET]) {
293                         nla_memcpy(mConcurrencySet,
294                             tb_vendor[
295                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET],
296                             sizeof(feature_set) * (*mSetSizePtr));
297                     }
298 
299                     ALOGV("%s: Get concurrency matrix response received.",
300                         __func__);
301                     ALOGV("%s: Num of concurrency combinations : %d",
302                         __func__, *mSetSizePtr);
303                     ALOGV("%s: List of valid concurrency combinations is: ",
304                         __func__);
305                     for(i = 0; i < *mSetSizePtr; i++)
306                     {
307                         ALOGV("%x", *(mConcurrencySet + i));
308                     }
309                 }
310             }
311             break;
312         case QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER:
313             {
314                 int subCmd;
315                 struct nlattr *tb_vendor[
316                         QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
317                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
318                         (struct nlattr *)mVendorData,
319                         mDataLen, NULL);
320 
321                 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD])
322                 {
323                     subCmd = nla_get_u32(
324                            tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD]);
325                 } else {
326                     /*
327                      * The older drivers may not send PACKET_FILTER_SUB_CMD as
328                      * they support QCA_WLAN_GET_PACKET_FILTER only.
329                      */
330                     subCmd = QCA_WLAN_GET_PACKET_FILTER;
331                 }
332                 if (subCmd == QCA_WLAN_GET_PACKET_FILTER) {
333                     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION])
334                     {
335                         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION"
336                               " not found", __FUNCTION__);
337                         return -EINVAL;
338                     }
339                     filterVersion = nla_get_u32(
340                            tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]);
341                     ALOGV("Current version : %u", filterVersion);
342 
343                     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE])
344                     {
345                         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE"
346                               " not found", __FUNCTION__);
347                         return -EINVAL;
348                     }
349                     filterLength = nla_get_u32(
350                         tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE]);
351                     ALOGV("Max filter length Supported : %u", filterLength);
352                 } else if (subCmd == QCA_WLAN_READ_PACKET_FILTER) {
353 
354                    if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM])
355                    {
356                        ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM"
357                              " not found", __FUNCTION__);
358                        return -EINVAL;
359                    }
360                    if (nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM])
361                            < mfilter_packet_length)
362                    {
363                        ALOGE("%s: Expected packet filter length :%d but received only: %d bytes",
364                              __FUNCTION__, mfilter_packet_length,
365                              nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM]));
366                        return -EINVAL;
367                    }
368                    memcpy(mfilter_packet_read_buffer,
369                       nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM]),
370                       mfilter_packet_length);
371                    ALOGV("Filter Program length : %u", mfilter_packet_length);
372                 } else {
373                        ALOGE("%s: Unknown APF sub command received",
374                              __FUNCTION__);
375                        return -EINVAL;
376                 }
377 
378             }
379             break;
380         case QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE:
381             {
382                 struct nlattr *tb_vendor[
383                         QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX + 1];
384                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX,
385                           (struct nlattr *)mVendorData, mDataLen, NULL);
386 
387                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE])
388                 {
389                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE"
390                           " not found", __FUNCTION__);
391                     return -EINVAL;
392                 }
393                 firmware_bus_max_size = nla_get_u32(
394                        tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE]);
395                 ALOGV("Max BUS size Supported: %d", firmware_bus_max_size);
396             }
397             break;
398         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES:
399             {
400                 struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
401                 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
402                           (struct nlattr *)mVendorData,mDataLen, NULL);
403 
404                 if (wifiParseCapabilities(tbVendor) == WIFI_SUCCESS) {
405                     ALOGV("%s: GSCAN Capabilities:\n"
406                           "     max_ap_cache_per_scan:%d\n"
407                           "     max_bssid_history_entries:%d\n"
408                           "     max_hotlist_bssids:%d\n"
409                           "     max_hotlist_ssids:%d\n"
410                           "     max_rssi_sample_size:%d\n"
411                           "     max_scan_buckets:%d\n"
412                           "     max_scan_cache_size:%d\n"
413                           "     max_scan_reporting_threshold:%d\n"
414                           "     max_significant_wifi_change_aps:%d\n"
415                           "     max_number_epno_networks:%d\n"
416                           "     max_number_epno_networks_by_ssid:%d\n"
417                           "     max_number_of_white_listed_ssid:%d.",
418                           __FUNCTION__, mCapa->gscan_capa.max_ap_cache_per_scan,
419                           mCapa->gscan_capa.max_bssid_history_entries,
420                           mCapa->gscan_capa.max_hotlist_bssids,
421                           mCapa->gscan_capa.max_hotlist_ssids,
422                           mCapa->gscan_capa.max_rssi_sample_size,
423                           mCapa->gscan_capa.max_scan_buckets,
424                           mCapa->gscan_capa.max_scan_cache_size,
425                           mCapa->gscan_capa.max_scan_reporting_threshold,
426                           mCapa->gscan_capa.max_significant_wifi_change_aps,
427                           mCapa->gscan_capa.max_number_epno_networks,
428                           mCapa->gscan_capa.max_number_epno_networks_by_ssid,
429                           mCapa->gscan_capa.max_number_of_white_listed_ssid);
430 
431                     ALOGV("%s: Roaming Capabilities:\n"
432                           "    max_blacklist_size: %d\n"
433                           "    max_whitelist_size: %d\n",
434                           __FUNCTION__, mCapa->roaming_capa.max_blacklist_size,
435                           mCapa->roaming_capa.max_whitelist_size);
436                 }
437             }
438             break;
439         default :
440             ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
441     }
442     return NL_SKIP;
443 }
444 
445 /* Parses and extract capabilities results. */
wifiParseCapabilities(struct nlattr ** tbVendor)446 wifi_error WifihalGeneric::wifiParseCapabilities(struct nlattr **tbVendor)
447 {
448     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]) {
449         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE not found",
450               __FUNCTION__);
451         return WIFI_ERROR_INVALID_ARGS;
452     }
453     mCapa->gscan_capa.max_scan_cache_size = nla_get_u32(tbVendor[
454                               QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]);
455 
456     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]) {
457         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS not found",
458               __FUNCTION__);
459         return WIFI_ERROR_INVALID_ARGS;
460     }
461     mCapa->gscan_capa.max_scan_buckets = nla_get_u32(tbVendor[
462                                  QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]);
463 
464     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]) {
465         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN not found",
466               __FUNCTION__);
467         return WIFI_ERROR_INVALID_ARGS;
468     }
469     mCapa->gscan_capa.max_ap_cache_per_scan = nla_get_u32(tbVendor[
470                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]);
471 
472     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]) {
473         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE not found",
474               __FUNCTION__);
475         return WIFI_ERROR_INVALID_ARGS;
476     }
477     mCapa->gscan_capa.max_rssi_sample_size = nla_get_u32(tbVendor[
478                              QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]);
479 
480     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]) {
481         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD not"
482               " found", __FUNCTION__);
483         return WIFI_ERROR_INVALID_ARGS;
484     }
485     mCapa->gscan_capa.max_scan_reporting_threshold = nla_get_u32(tbVendor[
486                      QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]);
487 
488     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]) {
489         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS not found",
490               __FUNCTION__);
491         return WIFI_ERROR_INVALID_ARGS;
492     }
493     mCapa->gscan_capa.max_hotlist_bssids = nla_get_u32(tbVendor[
494                                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]);
495 
496     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]
497        ) {
498         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS "
499               "not found", __FUNCTION__);
500         return WIFI_ERROR_INVALID_ARGS;
501     }
502     mCapa->gscan_capa.max_significant_wifi_change_aps = nla_get_u32(tbVendor[
503                   QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]);
504 
505     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]) {
506         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES not "
507               "found", __FUNCTION__);
508         return WIFI_ERROR_INVALID_ARGS;
509     }
510     mCapa->gscan_capa.max_bssid_history_entries = nla_get_u32(tbVendor[
511                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]);
512 
513     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]) {
514         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS not found. Set"
515               " to 0.", __FUNCTION__);
516         mCapa->gscan_capa.max_hotlist_ssids = 0;
517     } else {
518         mCapa->gscan_capa.max_hotlist_ssids = nla_get_u32(tbVendor[
519                                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]);
520     }
521 
522     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS]) {
523         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS not found. Set"
524               " to 0.", __FUNCTION__);
525         mCapa->gscan_capa.max_number_epno_networks = 0;
526     } else {
527         mCapa->gscan_capa.max_number_epno_networks
528             = nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
529                                   ]);
530     }
531 
532     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]) {
533         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID not "
534               "found. Set to 0.", __FUNCTION__);
535         mCapa->gscan_capa.max_number_epno_networks_by_ssid = 0;
536     } else {
537         mCapa->gscan_capa.max_number_epno_networks_by_ssid = nla_get_u32(tbVendor[
538                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]);
539     }
540 
541     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]) {
542         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID not "
543               "found. Set to 0.", __FUNCTION__);
544         mCapa->gscan_capa.max_number_of_white_listed_ssid = 0;
545         mCapa->roaming_capa.max_whitelist_size = 0;
546     } else {
547         mCapa->gscan_capa.max_number_of_white_listed_ssid = nla_get_u32(tbVendor[
548                          QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]);
549         mCapa->roaming_capa.max_whitelist_size = mCapa->gscan_capa.max_number_of_white_listed_ssid;
550     }
551 
552     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_CAPABILITIES_MAX_NUM_BLACKLISTED_BSSID]) {
553         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
554             "_NUM_BLACKLIST_BSSID not found. Set to 0.", __FUNCTION__);
555         mCapa->roaming_capa.max_blacklist_size = 0;
556     } else {
557         mCapa->roaming_capa.max_blacklist_size = nla_get_u32(tbVendor[
558                                       QCA_WLAN_VENDOR_ATTR_CAPABILITIES_MAX_NUM_BLACKLISTED_BSSID]);
559     }
560     return WIFI_SUCCESS;
561 }
562 
getResponseparams(feature_set * pset)563 void WifihalGeneric::getResponseparams(feature_set *pset)
564 {
565     *pset = mSet;
566 }
567 
getDriverFeatures(features_info * pfeatures)568 void WifihalGeneric::getDriverFeatures(features_info *pfeatures)
569 {
570     if (!pfeatures)
571         return;
572 
573     if (mDriverFeatures.flags != NULL) {
574         pfeatures->flags = (u8 *)malloc(mDriverFeatures.flags_len);
575         if (pfeatures->flags) {
576             memcpy(pfeatures->flags, mDriverFeatures.flags,
577                    mDriverFeatures.flags_len);
578             pfeatures->flags_len = mDriverFeatures.flags_len;
579             return;
580         }
581     }
582 
583     pfeatures->flags_len = 0;
584     pfeatures->flags = NULL;
585 }
586 
setMaxSetSize(int set_size_max)587 void WifihalGeneric::setMaxSetSize(int set_size_max) {
588     mSetSizeMax = set_size_max;
589 }
590 
setConcurrencySet(feature_set set[])591 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
592     mConcurrencySet = set;
593 }
594 
setSizePtr(int * set_size)595 void WifihalGeneric::setSizePtr(int *set_size) {
596     mSetSizePtr = set_size;
597 }
598 
getFilterVersion()599 int WifihalGeneric::getFilterVersion() {
600     return filterVersion;
601 }
602 
getFilterLength()603 int WifihalGeneric::getFilterLength() {
604     return filterLength;
605 }
setPacketBufferParams(u8 * host_packet_buffer,int packet_length)606 void WifihalGeneric::setPacketBufferParams(u8 *host_packet_buffer, int packet_length) {
607     mfilter_packet_read_buffer = host_packet_buffer;
608     mfilter_packet_length = packet_length;
609 }
610 
getBusSize()611 int WifihalGeneric::getBusSize() {
612     return firmware_bus_max_size;
613 }
614 
wifiGetCapabilities(wifi_interface_handle handle)615 wifi_error WifihalGeneric::wifiGetCapabilities(wifi_interface_handle handle)
616 {
617     wifi_error ret;
618     struct nlattr *nlData;
619     interface_info *ifaceInfo = getIfaceInfo(handle);
620 
621     /* Create the NL message. */
622     ret = create();
623     if (ret != WIFI_SUCCESS) {
624         ALOGE("%s: Failed to create NL message,  Error:%d", __FUNCTION__, ret);
625         return ret;
626     }
627 
628     /* Set the interface Id of the message. */
629     ret = set_iface_id(ifaceInfo->name);
630     if (ret != WIFI_SUCCESS) {
631         ALOGE("%s: Failed to set interface Id of message, Error:%d", __FUNCTION__, ret);
632         return ret;
633     }
634 
635     /* Add the vendor specific attributes for the NL command. */
636     nlData = attr_start(NL80211_ATTR_VENDOR_DATA);
637     if (!nlData)
638         return WIFI_ERROR_OUT_OF_MEMORY;
639 
640     ret = put_u32(QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, mId);
641     if (ret != WIFI_SUCCESS) {
642         ALOGE("%s: Failed to add request_ID to NL command, Error:%d", __FUNCTION__, ret);
643         return ret;
644     }
645 
646     attr_end(nlData);
647 
648     ret = requestResponse();
649     if (ret != WIFI_SUCCESS)
650         ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
651 
652     return ret;
653 }
654