• 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     res_size = 0;
209     channel_buff = NULL;
210     memset(&mDriverFeatures, 0, sizeof(mDriverFeatures));
211 }
212 
~WifihalGeneric()213 WifihalGeneric::~WifihalGeneric()
214 {
215     mCapa = NULL;
216     if (mDriverFeatures.flags != NULL) {
217         free(mDriverFeatures.flags);
218         mDriverFeatures.flags = NULL;
219     }
220 }
221 
requestResponse()222 wifi_error WifihalGeneric::requestResponse()
223 {
224     return WifiCommand::requestResponse(mMsg);
225 }
226 
get_wifi_iftype_masks(u32 in_mask)227 static u32 get_wifi_iftype_masks(u32 in_mask)
228 {
229     u32 op_mask = 0;
230 
231     if (in_mask & BIT(NL80211_IFTYPE_STATION)) {
232         op_mask |= BIT(WIFI_INTERFACE_STA);
233         op_mask |= BIT(WIFI_INTERFACE_TDLS);
234     }
235     if (in_mask & BIT(NL80211_IFTYPE_AP))
236         op_mask |= BIT(WIFI_INTERFACE_SOFTAP);
237     if (in_mask & BIT(NL80211_IFTYPE_P2P_CLIENT))
238         op_mask |= BIT(WIFI_INTERFACE_P2P_CLIENT);
239     if (in_mask & BIT(NL80211_IFTYPE_P2P_GO))
240         op_mask |= BIT(WIFI_INTERFACE_P2P_GO);
241     if (in_mask & BIT(NL80211_IFTYPE_NAN))
242         op_mask |= BIT(WIFI_INTERFACE_NAN);
243 
244     return op_mask;
245 }
246 
get_channel_width(u32 nl_width)247 static wifi_channel_width get_channel_width(u32 nl_width)
248 {
249     switch(nl_width) {
250     case NL80211_CHAN_WIDTH_20:
251          return WIFI_CHAN_WIDTH_20;
252     case NL80211_CHAN_WIDTH_40:
253          return WIFI_CHAN_WIDTH_40;
254     case NL80211_CHAN_WIDTH_80:
255          return WIFI_CHAN_WIDTH_80;
256     case NL80211_CHAN_WIDTH_160:
257          return WIFI_CHAN_WIDTH_160;
258     case NL80211_CHAN_WIDTH_80P80:
259          return WIFI_CHAN_WIDTH_80P80;
260     case NL80211_CHAN_WIDTH_5:
261          return WIFI_CHAN_WIDTH_5;
262     case NL80211_CHAN_WIDTH_10:
263          return WIFI_CHAN_WIDTH_10;
264     default:
265          return WIFI_CHAN_WIDTH_INVALID;
266     }
267 }
268 
handle_response_usable_channels(struct nlattr * VendorData,u32 mDataLen)269 int WifihalGeneric::handle_response_usable_channels(struct nlattr *VendorData,
270                                                     u32 mDataLen)
271 {
272     struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX + 1];
273     struct nlattr *curr_attr;
274     wifi_usable_channel *chan_info = NULL;
275     int rem;
276     u32 currSize = 0;
277 
278     if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_MAX,
279                   (struct nlattr *)mVendorData, mDataLen, NULL)) {
280          ALOGE("Failed to parse NL channels list");
281          return WIFI_ERROR_INVALID_ARGS;
282     }
283 
284     if (!tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO]) {
285          ALOGE("%s: USABLE_CHANNELS_CHAN_INFO not found", __FUNCTION__);
286          return WIFI_ERROR_INVALID_ARGS;
287     }
288 
289     for_each_nested_attribute(curr_attr,
290                      tb[QCA_WLAN_VENDOR_ATTR_USABLE_CHANNELS_CHAN_INFO], rem) {
291          struct nlattr *ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX + 1];
292 
293          if (currSize >= mSetSizeMax) {
294               ALOGE("Got max channels %d completed", mSetSizeMax);
295               break;
296          }
297 
298          if (nla_parse_nested(ch_info, QCA_WLAN_VENDOR_ATTR_CHAN_INFO_MAX,
299                               curr_attr, NULL)) {
300               ALOGE("Failed to get usable channel info");
301               return NL_SKIP;
302          }
303 
304          chan_info = &channel_buff[currSize];
305          if (!ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ]) {
306               ALOGE("%s: CHAN_INFO_PRIMARY_FREQ not found",
307                     __FUNCTION__);
308               return NL_SKIP;
309          }
310 
311          chan_info->freq = nla_get_u32(ch_info[
312                                   QCA_WLAN_VENDOR_ATTR_CHAN_INFO_PRIMARY_FREQ]);
313          if (!ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH]) {
314               ALOGE("%s: CHAN_INFO_BANDWIDTH not found",
315                     __FUNCTION__);
316               return NL_SKIP;
317          }
318 
319          chan_info->width = get_channel_width(nla_get_u32(
320                             ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_BANDWIDTH]));
321          if (!ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK]) {
322               ALOGE("%s: CHAN_INFO_IFACE_MODE_MASK not found",
323                     __FUNCTION__);
324               return NL_SKIP;
325          }
326 
327          chan_info->iface_mode_mask = get_wifi_iftype_masks(nla_get_u32(
328                       ch_info[QCA_WLAN_VENDOR_ATTR_CHAN_INFO_IFACE_MODE_MASK]));
329          ALOGV("Primary freq %d BW %d iface mask %d", chan_info->freq,
330                chan_info->width, chan_info->iface_mode_mask);
331          currSize++;
332     }
333 
334     res_size = currSize;
335     ALOGV("%s: Result size %d", __FUNCTION__, res_size);
336 
337     return NL_SKIP;
338 }
339 
handleResponse(WifiEvent & reply)340 int WifihalGeneric::handleResponse(WifiEvent &reply)
341 {
342     ALOGV("Got a Wi-Fi HAL module message from Driver");
343     int i = 0;
344     WifiVendorCommand::handleResponse(reply);
345 
346     // Parse the vendordata and get the attribute
347     switch(mSubcmd)
348     {
349         case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES:
350             {
351                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
352                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
353                         (struct nlattr *)mVendorData,
354                         mDataLen, NULL);
355 
356                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET])
357                 {
358                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_FEATURE_SET not found", __func__);
359                     return -EINVAL;
360                 }
361                 mSet = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
362                 ALOGV("Supported feature set : 0x%" PRIx64, mSet);
363 
364                 break;
365             }
366         case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES:
367             {
368                 struct nlattr *attr;
369                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_MAX + 1];
370                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_MAX,
371                           (struct nlattr *)mVendorData, mDataLen, NULL);
372                 attr = tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_FLAGS];
373                 if (attr) {
374                     int len = nla_len(attr);
375                     mDriverFeatures.flags = (u8 *)malloc(len);
376                     if (mDriverFeatures.flags != NULL) {
377                         memcpy(mDriverFeatures.flags, nla_data(attr), len);
378                         mDriverFeatures.flags_len = len;
379                     }
380                  }
381                  break;
382             }
383         case QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX:
384             {
385                 struct nlattr *tb_vendor[
386                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
387                 nla_parse(tb_vendor,
388                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
389                     (struct nlattr *)mVendorData,mDataLen, NULL);
390 
391                 if (tb_vendor[
392                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]) {
393                     u32 val;
394                     val = nla_get_u32(
395                         tb_vendor[
396                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]);
397 
398                     ALOGV("%s: Num of concurrency combinations: %d",
399                         __func__, val);
400                     val = val > (unsigned int)mSetSizeMax ?
401                           (unsigned int)mSetSizeMax : val;
402                     *mSetSizePtr = val;
403 
404                     /* Extract the list of channels. */
405                     if (*mSetSizePtr > 0 &&
406                         tb_vendor[
407                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET]) {
408                         nla_memcpy(mConcurrencySet,
409                             tb_vendor[
410                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET],
411                             sizeof(feature_set) * (*mSetSizePtr));
412                     }
413 
414                     ALOGV("%s: Get concurrency matrix response received.",
415                         __func__);
416                     ALOGV("%s: Num of concurrency combinations : %d",
417                         __func__, *mSetSizePtr);
418                     ALOGV("%s: List of valid concurrency combinations is: ",
419                         __func__);
420                     for(i = 0; i < *mSetSizePtr; i++)
421                     {
422                         ALOGV("0x%" PRIx64, *(mConcurrencySet + i));
423                     }
424                 }
425             }
426             break;
427         case QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER:
428             {
429                 int subCmd;
430                 struct nlattr *tb_vendor[
431                         QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
432                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
433                         (struct nlattr *)mVendorData,
434                         mDataLen, NULL);
435 
436                 if (tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD])
437                 {
438                     subCmd = nla_get_u32(
439                            tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SUB_CMD]);
440                 } else {
441                     /*
442                      * The older drivers may not send PACKET_FILTER_SUB_CMD as
443                      * they support QCA_WLAN_GET_PACKET_FILTER only.
444                      */
445                     subCmd = QCA_WLAN_GET_PACKET_FILTER;
446                 }
447                 if (subCmd == QCA_WLAN_GET_PACKET_FILTER) {
448                     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION])
449                     {
450                         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION"
451                               " not found", __FUNCTION__);
452                         return -EINVAL;
453                     }
454                     filterVersion = nla_get_u32(
455                            tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]);
456                     ALOGV("Current version : %u", filterVersion);
457 
458                     if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE])
459                     {
460                         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE"
461                               " not found", __FUNCTION__);
462                         return -EINVAL;
463                     }
464                     filterLength = nla_get_u32(
465                         tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_SIZE]);
466                     ALOGV("Max filter length Supported : %u", filterLength);
467                 } else if (subCmd == QCA_WLAN_READ_PACKET_FILTER) {
468 
469                    if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM])
470                    {
471                        ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM"
472                              " not found", __FUNCTION__);
473                        return -EINVAL;
474                    }
475                    if (nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM])
476                            < mfilter_packet_length)
477                    {
478                        ALOGE("%s: Expected packet filter length :%d but received only: %d bytes",
479                              __FUNCTION__, mfilter_packet_length,
480                              nla_len(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM]));
481                        return -EINVAL;
482                    }
483                    memcpy(mfilter_packet_read_buffer,
484                       nla_data(tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_PROGRAM]),
485                       mfilter_packet_length);
486                    ALOGV("Filter Program length : %u", mfilter_packet_length);
487                 } else {
488                        ALOGE("%s: Unknown APF sub command received",
489                              __FUNCTION__);
490                        return -EINVAL;
491                 }
492 
493             }
494             break;
495         case QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE:
496             {
497                 struct nlattr *tb_vendor[
498                         QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX + 1];
499                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX,
500                           (struct nlattr *)mVendorData, mDataLen, NULL);
501 
502                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE])
503                 {
504                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE"
505                           " not found", __FUNCTION__);
506                     return -EINVAL;
507                 }
508                 firmware_bus_max_size = nla_get_u32(
509                        tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE]);
510                 ALOGV("Max BUS size Supported: %d", firmware_bus_max_size);
511             }
512             break;
513         case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES:
514             {
515                 struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
516                 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
517                           (struct nlattr *)mVendorData,mDataLen, NULL);
518 
519                 if (wifiParseCapabilities(tbVendor) == WIFI_SUCCESS) {
520                     ALOGV("%s: GSCAN Capabilities:\n"
521                           "     max_ap_cache_per_scan:%d\n"
522                           "     max_bssid_history_entries:%d\n"
523                           "     max_hotlist_bssids:%d\n"
524                           "     max_hotlist_ssids:%d\n"
525                           "     max_rssi_sample_size:%d\n"
526                           "     max_scan_buckets:%d\n"
527                           "     max_scan_cache_size:%d\n"
528                           "     max_scan_reporting_threshold:%d\n"
529                           "     max_significant_wifi_change_aps:%d\n"
530                           "     max_number_epno_networks:%d\n"
531                           "     max_number_epno_networks_by_ssid:%d\n"
532                           "     max_number_of_white_listed_ssid:%d.",
533                           __FUNCTION__, mCapa->gscan_capa.max_ap_cache_per_scan,
534                           mCapa->gscan_capa.max_bssid_history_entries,
535                           mCapa->gscan_capa.max_hotlist_bssids,
536                           mCapa->gscan_capa.max_hotlist_ssids,
537                           mCapa->gscan_capa.max_rssi_sample_size,
538                           mCapa->gscan_capa.max_scan_buckets,
539                           mCapa->gscan_capa.max_scan_cache_size,
540                           mCapa->gscan_capa.max_scan_reporting_threshold,
541                           mCapa->gscan_capa.max_significant_wifi_change_aps,
542                           mCapa->gscan_capa.max_number_epno_networks,
543                           mCapa->gscan_capa.max_number_epno_networks_by_ssid,
544                           mCapa->gscan_capa.max_number_of_white_listed_ssid);
545 
546                     ALOGV("%s: Roaming Capabilities:\n"
547                           "    max_blacklist_size: %d\n"
548                           "    max_whitelist_size: %d\n",
549                           __FUNCTION__, mCapa->roaming_capa.max_blacklist_size,
550                           mCapa->roaming_capa.max_whitelist_size);
551                 }
552             }
553             break;
554         case QCA_NL80211_VENDOR_SUBCMD_USABLE_CHANNELS:
555             return handle_response_usable_channels((struct nlattr *)mVendorData,
556                                                    mDataLen);
557         default :
558             ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
559     }
560     return NL_SKIP;
561 }
562 
563 /* Parses and extract capabilities results. */
wifiParseCapabilities(struct nlattr ** tbVendor)564 wifi_error WifihalGeneric::wifiParseCapabilities(struct nlattr **tbVendor)
565 {
566     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]) {
567         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE not found",
568               __FUNCTION__);
569         return WIFI_ERROR_INVALID_ARGS;
570     }
571     mCapa->gscan_capa.max_scan_cache_size = nla_get_u32(tbVendor[
572                               QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]);
573 
574     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]) {
575         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS not found",
576               __FUNCTION__);
577         return WIFI_ERROR_INVALID_ARGS;
578     }
579     mCapa->gscan_capa.max_scan_buckets = nla_get_u32(tbVendor[
580                                  QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]);
581 
582     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]) {
583         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN not found",
584               __FUNCTION__);
585         return WIFI_ERROR_INVALID_ARGS;
586     }
587     mCapa->gscan_capa.max_ap_cache_per_scan = nla_get_u32(tbVendor[
588                             QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]);
589 
590     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]) {
591         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE not found",
592               __FUNCTION__);
593         return WIFI_ERROR_INVALID_ARGS;
594     }
595     mCapa->gscan_capa.max_rssi_sample_size = nla_get_u32(tbVendor[
596                              QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]);
597 
598     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]) {
599         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD not"
600               " found", __FUNCTION__);
601         return WIFI_ERROR_INVALID_ARGS;
602     }
603     mCapa->gscan_capa.max_scan_reporting_threshold = nla_get_u32(tbVendor[
604                      QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]);
605 
606     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]) {
607         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS not found",
608               __FUNCTION__);
609         return WIFI_ERROR_INVALID_ARGS;
610     }
611     mCapa->gscan_capa.max_hotlist_bssids = nla_get_u32(tbVendor[
612                                QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]);
613 
614     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]
615        ) {
616         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS "
617               "not found", __FUNCTION__);
618         return WIFI_ERROR_INVALID_ARGS;
619     }
620     mCapa->gscan_capa.max_significant_wifi_change_aps = nla_get_u32(tbVendor[
621                   QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]);
622 
623     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]) {
624         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES not "
625               "found", __FUNCTION__);
626         return WIFI_ERROR_INVALID_ARGS;
627     }
628     mCapa->gscan_capa.max_bssid_history_entries = nla_get_u32(tbVendor[
629                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]);
630 
631     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]) {
632         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS not found. Set"
633               " to 0.", __FUNCTION__);
634         mCapa->gscan_capa.max_hotlist_ssids = 0;
635     } else {
636         mCapa->gscan_capa.max_hotlist_ssids = nla_get_u32(tbVendor[
637                                 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]);
638     }
639 
640     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS]) {
641         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS not found. Set"
642               " to 0.", __FUNCTION__);
643         mCapa->gscan_capa.max_number_epno_networks = 0;
644     } else {
645         mCapa->gscan_capa.max_number_epno_networks
646             = nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
647                                   ]);
648     }
649 
650     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]) {
651         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID not "
652               "found. Set to 0.", __FUNCTION__);
653         mCapa->gscan_capa.max_number_epno_networks_by_ssid = 0;
654     } else {
655         mCapa->gscan_capa.max_number_epno_networks_by_ssid = nla_get_u32(tbVendor[
656                         QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]);
657     }
658 
659     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]) {
660         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID not "
661               "found. Set to 0.", __FUNCTION__);
662         mCapa->gscan_capa.max_number_of_white_listed_ssid = 0;
663         mCapa->roaming_capa.max_whitelist_size = 0;
664     } else {
665         mCapa->gscan_capa.max_number_of_white_listed_ssid = nla_get_u32(tbVendor[
666                          QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]);
667         mCapa->roaming_capa.max_whitelist_size = mCapa->gscan_capa.max_number_of_white_listed_ssid;
668     }
669 
670     if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID]) {
671         ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID not found. Set to 0.",
672               __FUNCTION__);
673         mCapa->roaming_capa.max_blacklist_size = 0;
674     } else {
675         mCapa->roaming_capa.max_blacklist_size = nla_get_u32(tbVendor[
676                                       QCA_WLAN_VENDOR_ATTR_GSCAN_MAX_NUM_BLACKLISTED_BSSID]);
677     }
678     return WIFI_SUCCESS;
679 }
680 
getResponseparams(feature_set * pset)681 void WifihalGeneric::getResponseparams(feature_set *pset)
682 {
683     *pset = mSet;
684 }
685 
getDriverFeatures(features_info * pfeatures)686 void WifihalGeneric::getDriverFeatures(features_info *pfeatures)
687 {
688     if (!pfeatures)
689         return;
690 
691     if (mDriverFeatures.flags != NULL) {
692         pfeatures->flags = (u8 *)malloc(mDriverFeatures.flags_len);
693         if (pfeatures->flags) {
694             memcpy(pfeatures->flags, mDriverFeatures.flags,
695                    mDriverFeatures.flags_len);
696             pfeatures->flags_len = mDriverFeatures.flags_len;
697             return;
698         }
699     }
700 
701     pfeatures->flags_len = 0;
702     pfeatures->flags = NULL;
703 }
704 
setMaxSetSize(int set_size_max)705 void WifihalGeneric::setMaxSetSize(int set_size_max) {
706     mSetSizeMax = set_size_max;
707 }
708 
setConcurrencySet(feature_set set[])709 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
710     mConcurrencySet = set;
711 }
712 
setSizePtr(int * set_size)713 void WifihalGeneric::setSizePtr(int *set_size) {
714     mSetSizePtr = set_size;
715 }
716 
getFilterVersion()717 int WifihalGeneric::getFilterVersion() {
718     return filterVersion;
719 }
720 
getFilterLength()721 int WifihalGeneric::getFilterLength() {
722     return filterLength;
723 }
setPacketBufferParams(u8 * host_packet_buffer,int packet_length)724 void WifihalGeneric::setPacketBufferParams(u8 *host_packet_buffer, int packet_length) {
725     mfilter_packet_read_buffer = host_packet_buffer;
726     mfilter_packet_length = packet_length;
727 }
728 
getBusSize()729 int WifihalGeneric::getBusSize() {
730     return firmware_bus_max_size;
731 }
732 
set_channels_buff(wifi_usable_channel * channels)733 void WifihalGeneric::set_channels_buff(wifi_usable_channel* channels)
734 {
735     channel_buff = channels;
736     memset(channel_buff, 0, sizeof(wifi_usable_channel) * mSetSizeMax);
737 }
738 
get_results_size(void)739 u32 WifihalGeneric::get_results_size(void)
740 {
741     return res_size;
742 }
743 
wifiGetCapabilities(wifi_interface_handle handle)744 wifi_error WifihalGeneric::wifiGetCapabilities(wifi_interface_handle handle)
745 {
746     wifi_error ret;
747     struct nlattr *nlData;
748     interface_info *ifaceInfo = getIfaceInfo(handle);
749 
750     /* Create the NL message. */
751     ret = create();
752     if (ret != WIFI_SUCCESS) {
753         ALOGE("%s: Failed to create NL message,  Error:%d", __FUNCTION__, ret);
754         return ret;
755     }
756 
757     /* Set the interface Id of the message. */
758     ret = set_iface_id(ifaceInfo->name);
759     if (ret != WIFI_SUCCESS) {
760         ALOGE("%s: Failed to set interface Id of message, Error:%d", __FUNCTION__, ret);
761         return ret;
762     }
763 
764     /* Add the vendor specific attributes for the NL command. */
765     nlData = attr_start(NL80211_ATTR_VENDOR_DATA);
766     if (!nlData)
767         return WIFI_ERROR_OUT_OF_MEMORY;
768 
769     ret = put_u32(QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, mId);
770     if (ret != WIFI_SUCCESS) {
771         ALOGE("%s: Failed to add request_ID to NL command, Error:%d", __FUNCTION__, ret);
772         return ret;
773     }
774 
775     attr_end(nlData);
776 
777     ret = requestResponse();
778     if (ret != WIFI_SUCCESS)
779         ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
780 
781     return ret;
782 }
783