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