• 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 }
209 
~WifihalGeneric()210 WifihalGeneric::~WifihalGeneric()
211 {
212     mCapa = NULL;
213 }
214 
requestResponse()215 wifi_error 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 -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. */
wifiParseCapabilities(struct nlattr ** tbVendor)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 
getResponseparams(feature_set * pset)541 void WifihalGeneric::getResponseparams(feature_set *pset)
542 {
543     *pset = mSet;
544 }
545 
setMaxSetSize(int set_size_max)546 void WifihalGeneric::setMaxSetSize(int set_size_max) {
547     mSetSizeMax = set_size_max;
548 }
549 
setConcurrencySet(feature_set set[])550 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
551     mConcurrencySet = set;
552 }
553 
setSizePtr(int * set_size)554 void WifihalGeneric::setSizePtr(int *set_size) {
555     mSetSizePtr = set_size;
556 }
557 
getFilterVersion()558 int WifihalGeneric::getFilterVersion() {
559     return filterVersion;
560 }
561 
getFilterLength()562 int WifihalGeneric::getFilterLength() {
563     return filterLength;
564 }
setPacketBufferParams(u8 * host_packet_buffer,int packet_length)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 
getBusSize()570 int WifihalGeneric::getBusSize() {
571     return firmware_bus_max_size;
572 }
573 
wifiGetCapabilities(wifi_interface_handle handle)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