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