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