1 /* Copyright (c) 2014, 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
34 #include "ifaceeventhandler.h"
35
36 /* Used to handle NL command events from driver/firmware. */
37 IfaceEventHandlerCommand *mwifiEventHandler = NULL;
38
39 /* Set the interface event monitor handler*/
wifi_set_iface_event_handler(wifi_request_id id,wifi_interface_handle iface,wifi_event_handler eh)40 wifi_error wifi_set_iface_event_handler(wifi_request_id id,
41 wifi_interface_handle iface,
42 wifi_event_handler eh)
43 {
44 int ret = 0;
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_error)ret;
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 int ret = 0;
83
84 if (mwifiEventHandler)
85 {
86 if (id == mwifiEventHandler->get_request_id()) {
87 ALOGV("Delete Object mwifiEventHandler for id = %d", id);
88 delete mwifiEventHandler;
89 mwifiEventHandler = NULL;
90 } else {
91 ALOGE("%s: Iface Event Handler Set for a different Request "
92 "Id:%d is requested. Not supported. Exit", __func__, id);
93 return WIFI_ERROR_NOT_SUPPORTED;
94 }
95 } else {
96 ALOGV("Object mwifiEventHandler for id = %d already Deleted", id);
97 }
98
99 return (wifi_error)ret;
100 }
101
102 /* This function will be the main handler for the registered incoming
103 * (from driver) Commads. Calls the appropriate callback handler after
104 * parsing the vendor data.
105 */
handleEvent(WifiEvent & event)106 int IfaceEventHandlerCommand::handleEvent(WifiEvent &event)
107 {
108 wifiEventHandler::handleEvent(event);
109
110 switch(mSubcmd)
111 {
112 case NL80211_CMD_REG_CHANGE:
113 {
114 char code[2];
115 memset(&code[0], 0, 2);
116 if(tb[NL80211_ATTR_REG_ALPHA2])
117 {
118 memcpy(&code[0], (char *) nla_data(tb[NL80211_ATTR_REG_ALPHA2]), 2);
119 } else {
120 ALOGE("%s: NL80211_ATTR_REG_ALPHA2 not found", __func__);
121 }
122 ALOGV("Country : %c%c", code[0], code[1]);
123 if(mHandler.on_country_code_changed)
124 {
125 mHandler.on_country_code_changed(code);
126 }
127 }
128 break;
129 default:
130 ALOGV("NL Event : %d Not supported", mSubcmd);
131 }
132
133 return NL_SKIP;
134 }
135
IfaceEventHandlerCommand(wifi_handle handle,int id,u32 subcmd)136 IfaceEventHandlerCommand::IfaceEventHandlerCommand(wifi_handle handle, int id, u32 subcmd)
137 : wifiEventHandler(handle, id, subcmd)
138 {
139 ALOGV("wifiEventHandler %p constructed", this);
140 registerHandler(mSubcmd);
141 memset(&mHandler, 0, sizeof(wifi_event_handler));
142 mEventData = NULL;
143 mDataLen = 0;
144 }
145
~IfaceEventHandlerCommand()146 IfaceEventHandlerCommand::~IfaceEventHandlerCommand()
147 {
148 ALOGV("IfaceEventHandlerCommand %p destructor", this);
149 unregisterHandler(mSubcmd);
150 }
151
setCallbackHandler(wifi_event_handler nHandler)152 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler)
153 {
154 mHandler = nHandler;
155 }
156
get_request_id()157 int wifiEventHandler::get_request_id()
158 {
159 return mRequestId;
160 }
161
get_request_id()162 int IfaceEventHandlerCommand::get_request_id()
163 {
164 return wifiEventHandler::get_request_id();
165 }
166
wifiEventHandler(wifi_handle handle,int id,u32 subcmd)167 wifiEventHandler::wifiEventHandler(wifi_handle handle, int id, u32 subcmd)
168 : WifiCommand(handle, id)
169 {
170 mRequestId = id;
171 mSubcmd = subcmd;
172 registerHandler(mSubcmd);
173 ALOGV("wifiEventHandler %p constructed", this);
174 }
175
~wifiEventHandler()176 wifiEventHandler::~wifiEventHandler()
177 {
178 ALOGV("wifiEventHandler %p destructor", this);
179 unregisterHandler(mSubcmd);
180 }
181
handleEvent(WifiEvent & event)182 int wifiEventHandler::handleEvent(WifiEvent &event)
183 {
184 struct genlmsghdr *gnlh = event.header();
185 mSubcmd = gnlh->cmd;
186 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
187 genlmsg_attrlen(gnlh, 0), NULL);
188 ALOGV("Got NL Event : %d from the Driver.", gnlh->cmd);
189
190 return NL_SKIP;
191 }
192
WifihalGeneric(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)193 WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id,
194 u32 subcmd)
195 : WifiVendorCommand(handle, id, vendor_id, subcmd)
196 {
197 hal_info *info = getHalInfo(handle);
198
199 /* Initialize the member data variables here */
200 mSet = 0;
201 mSetSizeMax = 0;
202 mSetSizePtr = NULL;
203 mConcurrencySet = 0;
204 filterVersion = 0;
205 filterLength = 0;
206 firmware_bus_max_size = 0;
207 mCapa = &(info->capa);
208 }
209
~WifihalGeneric()210 WifihalGeneric::~WifihalGeneric()
211 {
212 mCapa = NULL;
213 }
214
requestResponse()215 int 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 WIFI_ERROR_INVALID_ARGS;
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 struct nlattr *tb_vendor[
293 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
294 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
295 (struct nlattr *)mVendorData,
296 mDataLen, NULL);
297
298 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION])
299 {
300 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION"
301 " not found", __FUNCTION__);
302 return WIFI_ERROR_INVALID_ARGS;
303 }
304 filterVersion = nla_get_u32(
305 tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]);
306 ALOGV("Current version : %u", filterVersion);
307
308 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH])
309 {
310 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH"
311 " not found", __FUNCTION__);
312 return WIFI_ERROR_INVALID_ARGS;
313 }
314 filterLength = nla_get_u32(
315 tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]);
316 ALOGV("Max filter length Supported : %u", filterLength);
317
318 }
319 break;
320 case QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE:
321 {
322 struct nlattr *tb_vendor[
323 QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX + 1];
324 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX,
325 (struct nlattr *)mVendorData, mDataLen, NULL);
326
327 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE])
328 {
329 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE"
330 " not found", __FUNCTION__);
331 return WIFI_ERROR_INVALID_ARGS;
332 }
333 firmware_bus_max_size = nla_get_u32(
334 tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE]);
335 ALOGV("Max BUS size Supported: %d", firmware_bus_max_size);
336 }
337 break;
338 case QCA_NL80211_VENDOR_SUBCMD_GSCAN_GET_CAPABILITIES:
339 {
340 struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
341 nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX,
342 (struct nlattr *)mVendorData,mDataLen, NULL);
343
344 if (wifiParseCapabilities(tbVendor) == WIFI_SUCCESS) {
345 ALOGV("%s: GSCAN Capabilities:\n"
346 " max_ap_cache_per_scan:%d\n"
347 " max_bssid_history_entries:%d\n"
348 " max_hotlist_bssids:%d\n"
349 " max_hotlist_ssids:%d\n"
350 " max_rssi_sample_size:%d\n"
351 " max_scan_buckets:%d\n"
352 " max_scan_cache_size:%d\n"
353 " max_scan_reporting_threshold:%d\n"
354 " max_significant_wifi_change_aps:%d\n"
355 " max_number_epno_networks:%d\n"
356 " max_number_epno_networks_by_ssid:%d\n"
357 " max_number_of_white_listed_ssid:%d.",
358 __FUNCTION__, mCapa->gscan_capa.max_ap_cache_per_scan,
359 mCapa->gscan_capa.max_bssid_history_entries,
360 mCapa->gscan_capa.max_hotlist_bssids,
361 mCapa->gscan_capa.max_hotlist_ssids,
362 mCapa->gscan_capa.max_rssi_sample_size,
363 mCapa->gscan_capa.max_scan_buckets,
364 mCapa->gscan_capa.max_scan_cache_size,
365 mCapa->gscan_capa.max_scan_reporting_threshold,
366 mCapa->gscan_capa.max_significant_wifi_change_aps,
367 mCapa->gscan_capa.max_number_epno_networks,
368 mCapa->gscan_capa.max_number_epno_networks_by_ssid,
369 mCapa->gscan_capa.max_number_of_white_listed_ssid);
370
371 ALOGV("%s: Roaming Capabilities:\n"
372 " max_blacklist_size: %d\n"
373 " max_whitelist_size: %d\n",
374 __FUNCTION__, mCapa->roaming_capa.max_blacklist_size,
375 mCapa->roaming_capa.max_whitelist_size);
376 }
377 }
378 break;
379 default :
380 ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
381 }
382 return NL_SKIP;
383 }
384
385 /* Parses and extract capabilities results. */
wifiParseCapabilities(struct nlattr ** tbVendor)386 wifi_error WifihalGeneric::wifiParseCapabilities(struct nlattr **tbVendor)
387 {
388 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]) {
389 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE not found",
390 __FUNCTION__);
391 return WIFI_ERROR_INVALID_ARGS;
392 }
393 mCapa->gscan_capa.max_scan_cache_size = nla_get_u32(tbVendor[
394 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_CACHE_SIZE]);
395
396 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]) {
397 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS not found",
398 __FUNCTION__);
399 return WIFI_ERROR_INVALID_ARGS;
400 }
401 mCapa->gscan_capa.max_scan_buckets = nla_get_u32(tbVendor[
402 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_BUCKETS]);
403
404 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]) {
405 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN not found",
406 __FUNCTION__);
407 return WIFI_ERROR_INVALID_ARGS;
408 }
409 mCapa->gscan_capa.max_ap_cache_per_scan = nla_get_u32(tbVendor[
410 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_AP_CACHE_PER_SCAN]);
411
412 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]) {
413 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE not found",
414 __FUNCTION__);
415 return WIFI_ERROR_INVALID_ARGS;
416 }
417 mCapa->gscan_capa.max_rssi_sample_size = nla_get_u32(tbVendor[
418 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_RSSI_SAMPLE_SIZE]);
419
420 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]) {
421 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD not"
422 " found", __FUNCTION__);
423 return WIFI_ERROR_INVALID_ARGS;
424 }
425 mCapa->gscan_capa.max_scan_reporting_threshold = nla_get_u32(tbVendor[
426 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SCAN_REPORTING_THRESHOLD]);
427
428 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]) {
429 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS not found",
430 __FUNCTION__);
431 return WIFI_ERROR_INVALID_ARGS;
432 }
433 mCapa->gscan_capa.max_hotlist_bssids = nla_get_u32(tbVendor[
434 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_BSSIDS]);
435
436 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]
437 ) {
438 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS "
439 "not found", __FUNCTION__);
440 return WIFI_ERROR_INVALID_ARGS;
441 }
442 mCapa->gscan_capa.max_significant_wifi_change_aps = nla_get_u32(tbVendor[
443 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_SIGNIFICANT_WIFI_CHANGE_APS]);
444
445 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]) {
446 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES not "
447 "found", __FUNCTION__);
448 return WIFI_ERROR_INVALID_ARGS;
449 }
450 mCapa->gscan_capa.max_bssid_history_entries = nla_get_u32(tbVendor[
451 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_BSSID_HISTORY_ENTRIES]);
452
453 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]) {
454 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS not found. Set"
455 " to 0.", __FUNCTION__);
456 mCapa->gscan_capa.max_hotlist_ssids = 0;
457 } else {
458 mCapa->gscan_capa.max_hotlist_ssids = nla_get_u32(tbVendor[
459 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_HOTLIST_SSIDS]);
460 }
461
462 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS]) {
463 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS not found. Set"
464 " to 0.", __FUNCTION__);
465 mCapa->gscan_capa.max_number_epno_networks = 0;
466 } else {
467 mCapa->gscan_capa.max_number_epno_networks
468 = nla_get_u32(tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS
469 ]);
470 }
471
472 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]) {
473 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID not "
474 "found. Set to 0.", __FUNCTION__);
475 mCapa->gscan_capa.max_number_epno_networks_by_ssid = 0;
476 } else {
477 mCapa->gscan_capa.max_number_epno_networks_by_ssid = nla_get_u32(tbVendor[
478 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_EPNO_NETS_BY_SSID]);
479 }
480
481 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]) {
482 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID not "
483 "found. Set to 0.", __FUNCTION__);
484 mCapa->gscan_capa.max_number_of_white_listed_ssid = 0;
485 mCapa->roaming_capa.max_whitelist_size = 0;
486 } else {
487 mCapa->gscan_capa.max_number_of_white_listed_ssid = nla_get_u32(tbVendor[
488 QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX_NUM_WHITELISTED_SSID]);
489 mCapa->roaming_capa.max_whitelist_size = mCapa->gscan_capa.max_number_of_white_listed_ssid;
490 }
491
492 if (!tbVendor[QCA_WLAN_VENDOR_ATTR_CAPABILITIES_MAX_NUM_BLACKLISTED_BSSID]) {
493 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_CAPABILITIES_MAX"
494 "_NUM_BLACKLIST_BSSID not found. Set to 0.", __FUNCTION__);
495 mCapa->roaming_capa.max_blacklist_size = 0;
496 } else {
497 mCapa->roaming_capa.max_blacklist_size = nla_get_u32(tbVendor[
498 QCA_WLAN_VENDOR_ATTR_CAPABILITIES_MAX_NUM_BLACKLISTED_BSSID]);
499 }
500 return WIFI_SUCCESS;
501 }
502
getResponseparams(feature_set * pset)503 void WifihalGeneric::getResponseparams(feature_set *pset)
504 {
505 *pset = mSet;
506 }
507
setMaxSetSize(int set_size_max)508 void WifihalGeneric::setMaxSetSize(int set_size_max) {
509 mSetSizeMax = set_size_max;
510 }
511
setConcurrencySet(feature_set set[])512 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
513 mConcurrencySet = set;
514 }
515
setSizePtr(int * set_size)516 void WifihalGeneric::setSizePtr(int *set_size) {
517 mSetSizePtr = set_size;
518 }
519
getFilterVersion()520 int WifihalGeneric::getFilterVersion() {
521 return filterVersion;
522 }
523
getFilterLength()524 int WifihalGeneric::getFilterLength() {
525 return filterLength;
526 }
527
getBusSize()528 int WifihalGeneric::getBusSize() {
529 return firmware_bus_max_size;
530 }
531
wifiGetCapabilities(wifi_interface_handle handle)532 wifi_error WifihalGeneric::wifiGetCapabilities(wifi_interface_handle handle)
533 {
534 int ret;
535 struct nlattr *nlData;
536 interface_info *ifaceInfo = getIfaceInfo(handle);
537
538 /* Create the NL message. */
539 ret = create();
540 if (ret < 0) {
541 ALOGE("%s: Failed to create NL message, Error:%d", __FUNCTION__, ret);
542 return WIFI_ERROR_UNKNOWN;
543 }
544
545 /* Set the interface Id of the message. */
546 ret = set_iface_id(ifaceInfo->name);
547 if (ret < 0) {
548 ALOGE("%s: Failed to set interface Id of message, Error:%d", __FUNCTION__, ret);
549 return WIFI_ERROR_UNKNOWN;
550 }
551
552 /* Add the vendor specific attributes for the NL command. */
553 nlData = attr_start(NL80211_ATTR_VENDOR_DATA);
554 if (!nlData)
555 return WIFI_ERROR_UNKNOWN;
556
557 ret = put_u32(QCA_WLAN_VENDOR_ATTR_GSCAN_SUBCMD_CONFIG_PARAM_REQUEST_ID, mId);
558 if (ret < 0) {
559 ALOGE("%s: Failed to add request_ID to NL command, Error:%d", __FUNCTION__, ret);
560 return WIFI_ERROR_UNKNOWN;
561 }
562
563 attr_end(nlData);
564
565 ret = requestResponse();
566 if (ret != 0) {
567 ALOGE("%s: Failed to send request, Error:%d", __FUNCTION__, ret);
568 return WIFI_ERROR_UNKNOWN;
569 }
570
571 return WIFI_SUCCESS;
572 }
573