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*/ 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*/ 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 */ 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 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 146 IfaceEventHandlerCommand::~IfaceEventHandlerCommand() 147 { 148 ALOGV("IfaceEventHandlerCommand %p destructor", this); 149 unregisterHandler(mSubcmd); 150 } 151 152 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler) 153 { 154 mHandler = nHandler; 155 } 156 157 int wifiEventHandler::get_request_id() 158 { 159 return mRequestId; 160 } 161 162 int IfaceEventHandlerCommand::get_request_id() 163 { 164 return wifiEventHandler::get_request_id(); 165 } 166 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 176 wifiEventHandler::~wifiEventHandler() 177 { 178 ALOGV("wifiEventHandler %p destructor", this); 179 unregisterHandler(mSubcmd); 180 } 181 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 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 210 WifihalGeneric::~WifihalGeneric() 211 { 212 mCapa = NULL; 213 } 214 215 int WifihalGeneric::requestResponse() 216 { 217 return WifiCommand::requestResponse(mMsg); 218 } 219 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. */ 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 503 void WifihalGeneric::getResponseparams(feature_set *pset) 504 { 505 *pset = mSet; 506 } 507 508 void WifihalGeneric::setMaxSetSize(int set_size_max) { 509 mSetSizeMax = set_size_max; 510 } 511 512 void WifihalGeneric::setConcurrencySet(feature_set set[]) { 513 mConcurrencySet = set; 514 } 515 516 void WifihalGeneric::setSizePtr(int *set_size) { 517 mSetSizePtr = set_size; 518 } 519 520 int WifihalGeneric::getFilterVersion() { 521 return filterVersion; 522 } 523 524 int WifihalGeneric::getFilterLength() { 525 return filterLength; 526 } 527 528 int WifihalGeneric::getBusSize() { 529 return firmware_bus_max_size; 530 } 531 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