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*/ 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*/ 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 */ 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 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 144 IfaceEventHandlerCommand::~IfaceEventHandlerCommand() 145 { 146 ALOGV("IfaceEventHandlerCommand %p destructor", this); 147 unregisterHandler(mSubcmd); 148 } 149 150 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler) 151 { 152 mHandler = nHandler; 153 } 154 155 int wifiEventHandler::get_request_id() 156 { 157 return mRequestId; 158 } 159 160 int IfaceEventHandlerCommand::get_request_id() 161 { 162 return wifiEventHandler::get_request_id(); 163 } 164 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 174 wifiEventHandler::~wifiEventHandler() 175 { 176 ALOGV("wifiEventHandler %p destructor", this); 177 unregisterHandler(mSubcmd); 178 } 179 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 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 210 WifihalGeneric::~WifihalGeneric() 211 { 212 mCapa = NULL; 213 } 214 215 wifi_error 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 -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. */ 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 541 void WifihalGeneric::getResponseparams(feature_set *pset) 542 { 543 *pset = mSet; 544 } 545 546 void WifihalGeneric::setMaxSetSize(int set_size_max) { 547 mSetSizeMax = set_size_max; 548 } 549 550 void WifihalGeneric::setConcurrencySet(feature_set set[]) { 551 mConcurrencySet = set; 552 } 553 554 void WifihalGeneric::setSizePtr(int *set_size) { 555 mSetSizePtr = set_size; 556 } 557 558 int WifihalGeneric::getFilterVersion() { 559 return filterVersion; 560 } 561 562 int WifihalGeneric::getFilterLength() { 563 return filterLength; 564 } 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 570 int WifihalGeneric::getBusSize() { 571 return firmware_bus_max_size; 572 } 573 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