/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "WifiHAL" #include #include "gscan_event_handler.h" /* This function implements creation of Vendor command event handler. */ wifi_error GScanCommandEventHandler::create() { wifi_error ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0); if (ret != WIFI_SUCCESS) return ret; /* Insert the oui in the msg */ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id); if (ret != WIFI_SUCCESS) return ret; /* Insert the subcmd in the msg */ ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd); return ret; } int GScanCommandEventHandler::get_request_id() { return mRequestId; } void GScanCommandEventHandler::set_request_id(int request_id) { mRequestId = request_id; } void GScanCommandEventHandler::enableEventHandling() { mEventHandlingEnabled = true; } void GScanCommandEventHandler::disableEventHandling() { mEventHandlingEnabled = false; } bool GScanCommandEventHandler::isEventHandlingEnabled() { return mEventHandlingEnabled; } void GScanCommandEventHandler::setCallbackHandler(GScanCallbackHandler handler) { mHandler = handler; } GScanCommandEventHandler::GScanCommandEventHandler(wifi_handle handle, int id, u32 vendor_id, u32 subcmd, GScanCallbackHandler handler) : WifiVendorCommand(handle, id, vendor_id, subcmd) { int ret = 0; mRequestId = id; mHandler = handler; mSubCommandId = subcmd; mHotlistApFoundResults = NULL; mHotlistApFoundNumResults = 0; mHotlistApFoundMoreData = false; mHotlistApLostResults = NULL; mHotlistApLostNumResults = 0; mHotlistApLostMoreData = false; mSignificantChangeResults = NULL; mSignificantChangeNumResults = 0; mSignificantChangeMoreData = false; mHotlistSsidFoundNumResults = 0; mHotlistSsidFoundMoreData = false; mHotlistSsidLostNumResults = 0; mHotlistSsidLostMoreData = false; mHotlistSsidFoundResults = NULL; mHotlistSsidLostResults = NULL; mPnoNetworkFoundResults = NULL; mPnoNetworkFoundNumResults = 0; mPnoNetworkFoundMoreData = false; mPasspointNetworkFoundResult = NULL; mPasspointAnqp = NULL; mPasspointAnqpLen = 0; mPasspointNetId = -1; mEventHandlingEnabled = false; switch(mSubCommandId) { case QCA_NL80211_VENDOR_SUBCMD_GSCAN_START: { /* Register handlers for northbound asychronous scan events. */ ret = registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE) || registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT) || registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT); if (ret) ALOGE("%s: Error in registering handler for " "GSCAN_START. \n", __FUNCTION__); } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE: { ret = registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE); if (ret) ALOGE("%s: Error in registering handler for " "GSCAN_SIGNIFICANT_CHANGE. \n", __FUNCTION__); } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST: { ret = registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND); if (ret) ALOGE("%s: Error in registering handler for" " GSCAN_HOTLIST_AP_FOUND. \n", __FUNCTION__); ret = registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST); if (ret) ALOGE("%s: Error in registering handler for" " GSCAN_HOTLIST_AP_LOST. \n", __FUNCTION__); } break; case QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST: { ret = registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND); if (ret) ALOGE("%s: Error in registering handler for" " PNO_NETWORK_FOUND. \n", __FUNCTION__); } break; case QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST: { ret = registerVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND); if (ret) ALOGE("%s: Error in registering handler for" " PNO_PASSPOINT_NETWORK_FOUND. \n", __FUNCTION__); } break; } } GScanCommandEventHandler::~GScanCommandEventHandler() { switch(mSubCommandId) { case QCA_NL80211_VENDOR_SUBCMD_GSCAN_START: { /* Unregister event handlers. */ unregisterVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE); unregisterVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT); unregisterVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT); } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE: { unregisterVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE); } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST: { unregisterVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND); unregisterVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST); } break; case QCA_NL80211_VENDOR_SUBCMD_PNO_SET_LIST: { unregisterVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND); } break; case QCA_NL80211_VENDOR_SUBCMD_PNO_SET_PASSPOINT_LIST: { unregisterVendorHandler(mVendor_id, QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND); } break; } } wifi_error GScanCommandEventHandler::gscan_parse_hotlist_ap_results( u32 num_results, wifi_scan_result *results, u32 starting_index, struct nlattr **tb_vendor) { u32 i = starting_index; struct nlattr *scanResultsInfo; int rem = 0; u32 len = 0; ALOGV("gscan_parse_hotlist_ap_results: starting counter: %d", i); for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), rem = nla_len(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST ]); nla_ok(scanResultsInfo, rem); scanResultsInfo = nla_next(scanResultsInfo, &(rem))) { struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *) nla_data(scanResultsInfo), nla_len(scanResultsInfo), NULL); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]) { ALOGE("gscan_parse_hotlist_ap_results: " "RESULTS_SCAN_RESULT_TIME_STAMP not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].ts = nla_get_u64( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID ]) { ALOGE("gscan_parse_hotlist_ap_results: " "RESULTS_SCAN_RESULT_SSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len(tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]); len = sizeof(results->ssid) <= len ? sizeof(results->ssid) : len; memcpy((void *)&results[i].ssid, nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID ]) { ALOGE("gscan_parse_hotlist_ap_results: " "RESULTS_SCAN_RESULT_BSSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]); len = sizeof(results->bssid) <= len ? sizeof(results->bssid) : len; memcpy(&results[i].bssid, nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL ]) { ALOGE("gscan_parse_hotlist_ap_results: " "RESULTS_SCAN_RESULT_CHANNEL not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].channel = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI ]) { ALOGE("gscan_parse_hotlist_ap_results: " "RESULTS_SCAN_RESULT_RSSI not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rssi = get_s32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT ]) { ALOGE("gscan_parse_hotlist_ap_results: " "RESULTS_SCAN_RESULT_RTT not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rtt = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD ]) { ALOGE("gscan_parse_hotlist_ap_results: " "RESULTS_SCAN_RESULT_RTT_SD not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rtt_sd = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]); ALOGV("gscan_parse_hotlist_ap_results: ts %" PRId64 " SSID %s " "BSSID: %02x:%02x:%02x:%02x:%02x:%02x channel %d rssi %d " "rtt %" PRId64" rtt_sd %" PRId64, results[i].ts, results[i].ssid, results[i].bssid[0], results[i].bssid[1], results[i].bssid[2], results[i].bssid[3], results[i].bssid[4], results[i].bssid[5], results[i].channel, results[i].rssi, results[i].rtt, results[i].rtt_sd); /* Increment loop index for next record */ i++; } return WIFI_SUCCESS; } static wifi_error gscan_get_significant_change_results(u32 num_results, wifi_significant_change_result **results, u32 starting_index, struct nlattr **tb_vendor) { u32 i = starting_index; int j; int rem = 0; u32 len = 0; char rssi_buf[1024]; //TODO: sizeof buf int rem_size; struct nlattr *scanResultsInfo; for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), rem = nla_len(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]); nla_ok(scanResultsInfo, rem); scanResultsInfo = nla_next(scanResultsInfo, &(rem))) { struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *) nla_data(scanResultsInfo), nla_len(scanResultsInfo), NULL); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID ]) { ALOGE("gscan_get_significant_change_results: " "SIGNIFICANT_CHANGE_RESULT_BSSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID] ); len = sizeof(results[i]->bssid) <= len ? sizeof(results[i]->bssid) : len; memcpy(&results[i]->bssid[0], nla_data( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_BSSID]), len); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL ]) { ALOGE("gscan_get_significant_change_results: " "SIGNIFICANT_CHANGE_RESULT_CHANNEL not found"); return WIFI_ERROR_INVALID_ARGS; } results[i]->channel = nla_get_u32( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_CHANNEL]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI ]) { ALOGE("gscan_get_significant_change_results: " "SIGNIFICANT_CHANGE_RESULT_NUM_RSSI not found"); return WIFI_ERROR_INVALID_ARGS; } results[i]->num_rssi = nla_get_u32( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST ]) { ALOGE("gscan_get_significant_change_results: " "SIGNIFICANT_CHANGE_RESULT_RSSI_LIST not found"); return WIFI_ERROR_INVALID_ARGS; } memcpy(&(results[i]->rssi[0]), nla_data( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_RSSI_LIST] ), results[i]->num_rssi * sizeof(wifi_rssi)); ALOGV("significant_change_result:%d, BSSID:" "%02x:%02x:%02x:%02x:%02x:%02x channel:%d num_rssi:%d ", i, results[i]->bssid[0], results[i]->bssid[1], results[i]->bssid[2], results[i]->bssid[3], results[i]->bssid[4], results[i]->bssid[5], results[i]->channel, results[i]->num_rssi); rem_size = sizeof(rssi_buf); char *dst = rssi_buf; for (j = 0; j < results[i]->num_rssi && rem_size > 0; j++) { len = snprintf(dst, rem_size, "rssi[%d]:%d, ", j, results[i]->rssi[j]); dst += len; rem_size -= len; } ALOGV("RSSI LIST: %s", rssi_buf); /* Increment loop index to prase next record. */ i++; } return WIFI_SUCCESS; } wifi_error GScanCommandEventHandler::gscan_parse_hotlist_ssid_results( u32 num_results, wifi_scan_result *results, u32 starting_index, struct nlattr **tb_vendor) { u32 i = starting_index; struct nlattr *scanResultsInfo; int rem = 0; u32 len = 0; for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), rem = nla_len(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST ]); nla_ok(scanResultsInfo, rem); scanResultsInfo = nla_next(scanResultsInfo, &(rem))) { struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *) nla_data(scanResultsInfo), nla_len(scanResultsInfo), NULL); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]) { ALOGE("gscan_parse_hotlist_ssid_results: " "RESULTS_SCAN_RESULT_TIME_STAMP not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].ts = nla_get_u64( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID ]) { ALOGE("gscan_parse_hotlist_ssid_results: " "RESULTS_SCAN_RESULT_SSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len(tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]); len = sizeof(results->ssid) <= len ? sizeof(results->ssid) : len; memcpy((void *)&results[i].ssid, nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID ]) { ALOGE("gscan_parse_hotlist_ssid_results: " "RESULTS_SCAN_RESULT_BSSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]); len = sizeof(results->bssid) <= len ? sizeof(results->bssid) : len; memcpy(&results[i].bssid, nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL ]) { ALOGE("gscan_parse_hotlist_ssid_results: " "RESULTS_SCAN_RESULT_CHANNEL not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].channel = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI ]) { ALOGE("gscan_parse_hotlist_ssid_results: " "RESULTS_SCAN_RESULT_RSSI not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rssi = get_s32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT ]) { ALOGE("gscan_parse_hotlist_ssid_results: " "RESULTS_SCAN_RESULT_RTT not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rtt = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD ]) { ALOGE("gscan_parse_hotlist_ssid_results: " "RESULTS_SCAN_RESULT_RTT_SD not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rtt_sd = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]); ALOGV("gscan_parse_hotlist_ssid_results: ts %" PRId64 " SSID %s " "BSSID: %02x:%02x:%02x:%02x:%02x:%02x channel %d rssi %d " "rtt %" PRId64 " rtt_sd %" PRId64, results[i].ts, results[i].ssid, results[i].bssid[0], results[i].bssid[1], results[i].bssid[2], results[i].bssid[3], results[i].bssid[4], results[i].bssid[5], results[i].channel, results[i].rssi, results[i].rtt, results[i].rtt_sd); /* Increment loop index for next record */ i++; } return WIFI_SUCCESS; } wifi_error GScanCommandEventHandler::gscan_parse_passpoint_network_result( struct nlattr **tb_vendor) { struct nlattr *scanResultsInfo, *wifiScanResultsInfo; u32 resultsBufSize = 0; u32 len = 0; int rem = 0; scanResultsInfo = (struct nlattr *)nla_data( tb_vendor [QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST]); rem = nla_len( tb_vendor [QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_RESULT_LIST]); if (!nla_ok(scanResultsInfo, rem)) { return WIFI_SUCCESS; } struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *)nla_data(scanResultsInfo), nla_len(scanResultsInfo), NULL); if (!tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID]) { ALOGE("%s: GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } mPasspointNetId = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ID]); for (wifiScanResultsInfo = (struct nlattr *)nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), rem = nla_len(tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]); nla_ok(wifiScanResultsInfo, rem); wifiScanResultsInfo = nla_next(wifiScanResultsInfo, &(rem))) { struct nlattr *tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb3, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *)nla_data(wifiScanResultsInfo), nla_len(wifiScanResultsInfo), NULL); resultsBufSize = sizeof(wifi_scan_result); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]) { ALOGE("%s: RESULTS_SCAN_RESULT_IE_LENGTH not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } resultsBufSize += nla_get_u32( tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]); /* Allocate the appropriate memory for mPasspointNetworkFoundResult */ mPasspointNetworkFoundResult = (wifi_scan_result *)malloc(resultsBufSize); if (!mPasspointNetworkFoundResult) { ALOGE("%s: Failed to alloc memory for result struct. Exit.\n", __FUNCTION__); return WIFI_ERROR_OUT_OF_MEMORY; } memset(mPasspointNetworkFoundResult, 0, resultsBufSize); mPasspointNetworkFoundResult->ie_length = nla_get_u32( tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP]) { ALOGE("%s: RESULTS_SCAN_RESULT_TIME_STAMP not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } mPasspointNetworkFoundResult->ts = nla_get_u64( tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP]); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]) { ALOGE("%s: RESULTS_SCAN_RESULT_SSID not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } len = nla_len(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]); len = sizeof(mPasspointNetworkFoundResult->ssid) <= len ? sizeof(mPasspointNetworkFoundResult->ssid) : len; memcpy((void *)&(mPasspointNetworkFoundResult->ssid[0]), nla_data(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]) { ALOGE("%s: RESULTS_SCAN_RESULT_BSSID not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } len = nla_len(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]); len = sizeof(mPasspointNetworkFoundResult->bssid) <= len ? sizeof(mPasspointNetworkFoundResult->bssid) : len; memcpy( &(mPasspointNetworkFoundResult->bssid[0]), nla_data(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]) { ALOGE("%s: RESULTS_SCAN_RESULT_CHANNEL not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } mPasspointNetworkFoundResult->channel = nla_get_u32( tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]) { ALOGE("%s: RESULTS_SCAN_RESULT_RSSI not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } mPasspointNetworkFoundResult->rssi = get_s32(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]) { ALOGE("%s: RESULTS_SCAN_RESULT_RTT not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } mPasspointNetworkFoundResult->rtt = nla_get_u32(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]) { ALOGE("%s: RESULTS_SCAN_RESULT_RTT_SD not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } mPasspointNetworkFoundResult->rtt_sd = nla_get_u32( tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]) { ALOGE("%s: RESULTS_SCAN_RESULT_BEACON_PERIOD not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } mPasspointNetworkFoundResult->beacon_period = nla_get_u16( tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]) { ALOGE("%s: RESULTS_SCAN_RESULT_CAPABILITY not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } mPasspointNetworkFoundResult->capability = nla_get_u16( tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]); if (!tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA]) { ALOGE("%s: RESULTS_SCAN_RESULT_IE_DATA not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } memcpy( &(mPasspointNetworkFoundResult->ie_data[0]), nla_data(tb3[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA]), mPasspointNetworkFoundResult->ie_length); ALOGV("%s: ts: %" PRId64 " SSID: %s " "BSSID: %02x:%02x:%02x:%02x:%02x:%02x channel: %d rssi: %d" " rtt: % " PRId64 " rtt_sd %" PRId64 " ie_length %u ", __FUNCTION__, mPasspointNetworkFoundResult->ts, mPasspointNetworkFoundResult->ssid, mPasspointNetworkFoundResult->bssid[0], mPasspointNetworkFoundResult->bssid[1], mPasspointNetworkFoundResult->bssid[2], mPasspointNetworkFoundResult->bssid[3], mPasspointNetworkFoundResult->bssid[4], mPasspointNetworkFoundResult->bssid[5], mPasspointNetworkFoundResult->channel, mPasspointNetworkFoundResult->rssi, mPasspointNetworkFoundResult->rtt, mPasspointNetworkFoundResult->rtt_sd, mPasspointNetworkFoundResult->ie_length); ALOGV("%s: ie_data: ", __FUNCTION__); hexdump(mPasspointNetworkFoundResult->ie_data, mPasspointNetworkFoundResult->ie_length); } if (!tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN]) { ALOGE("%s:PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } mPasspointAnqpLen = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN]); if (!mPasspointAnqpLen) { return WIFI_SUCCESS; } mPasspointAnqp = (u8 *)malloc(mPasspointAnqpLen); if (!mPasspointAnqp) { ALOGE("%s: Failed to alloc memory for result struct. Exit.\n", __FUNCTION__); return WIFI_ERROR_OUT_OF_MEMORY; } memset(mPasspointAnqp, 0, mPasspointAnqpLen); if (!tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP]) { ALOGE("%s: RESULTS_PASSPOINT_MATCH_ANQP not found", __FUNCTION__); return WIFI_ERROR_INVALID_ARGS; } memcpy( &(mPasspointAnqp[0]), nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_PNO_RESULTS_PASSPOINT_MATCH_ANQP]), mPasspointAnqpLen); ALOGV("%s: ANQP LEN:%d, ANQP IE:", __FUNCTION__, mPasspointAnqpLen); hexdump((char *)mPasspointAnqp, mPasspointAnqpLen); return WIFI_SUCCESS; } wifi_error GScanCommandEventHandler::gscan_parse_pno_network_results( u32 num_results, wifi_scan_result *results, u32 starting_index, struct nlattr **tb_vendor) { u32 i = starting_index; struct nlattr *scanResultsInfo; int rem = 0; u32 len = 0; for (scanResultsInfo = (struct nlattr *) nla_data(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), rem = nla_len(tb_vendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST ]); nla_ok(scanResultsInfo, rem); scanResultsInfo = nla_next(scanResultsInfo, &(rem))) { struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *) nla_data(scanResultsInfo), nla_len(scanResultsInfo), NULL); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]) { ALOGE("gscan_parse_pno_network_results: " "RESULTS_SCAN_RESULT_TIME_STAMP not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].ts = nla_get_u64( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID ]) { ALOGE("gscan_parse_pno_network_results: " "RESULTS_SCAN_RESULT_SSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len(tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]); len = sizeof(results->ssid) <= len ? sizeof(results->ssid) : len; memcpy((void *)&results[i].ssid, nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID ]) { ALOGE("gscan_parse_pno_network_results: " "RESULTS_SCAN_RESULT_BSSID not found"); return WIFI_ERROR_INVALID_ARGS; } len = nla_len( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]); len = sizeof(results->bssid) <= len ? sizeof(results->bssid) : len; memcpy(&results[i].bssid, nla_data( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL ]) { ALOGE("gscan_parse_pno_network_results: " "RESULTS_SCAN_RESULT_CHANNEL not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].channel = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI ]) { ALOGE("gscan_parse_pno_network_results: " "RESULTS_SCAN_RESULT_RSSI not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rssi = get_s32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT ]) { ALOGE("gscan_parse_pno_network_results: " "RESULTS_SCAN_RESULT_RTT not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rtt = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD ]) { ALOGE("gscan_parse_pno_network_results: " "RESULTS_SCAN_RESULT_RTT_SD not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].rtt_sd = nla_get_u32( tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]) { ALOGE("gscan_parse_pno_network_results: " "RESULTS_SCAN_RESULT_BEACON_PERIOD not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].beacon_period = nla_get_u16( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]); if (! tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY ]) { ALOGE("gscan_parse_pno_network_results: " "RESULTS_SCAN_RESULT_CAPABILITY not found"); return WIFI_ERROR_INVALID_ARGS; } results[i].capability = nla_get_u16( tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]); ALOGV("gscan_parse_pno_network_results: ts %" PRId64 " SSID %s " "BSSID: %02x:%02x:%02x:%02x:%02x:%02x channel %d rssi %d " "rtt %" PRId64 " rtt_sd %" PRId64, results[i].ts, results[i].ssid, results[i].bssid[0], results[i].bssid[1], results[i].bssid[2], results[i].bssid[3], results[i].bssid[4], results[i].bssid[5], results[i].channel, results[i].rssi, results[i].rtt, results[i].rtt_sd); /* Increment loop index for next record */ i++; } return WIFI_SUCCESS; } /* This function will be the main handler for incoming (from driver) * GScan_SUBCMD. Calls the appropriate callback handler after parsing * the vendor data. */ int GScanCommandEventHandler::handleEvent(WifiEvent &event) { unsigned i=0; int ret = WIFI_SUCCESS; wifi_scan_result *result = NULL; struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; if (mEventHandlingEnabled == false) { ALOGV("%s:Discarding event: %d", __FUNCTION__, mSubcmd); return NL_SKIP; } WifiVendorCommand::handleEvent(event); nla_parse(tbVendor, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *)mVendorData, mDataLen, NULL); switch(mSubcmd) { case QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT: { wifi_request_id reqId; u32 len = 0; u32 resultsBufSize = 0; u32 lengthOfInfoElements = 0; u32 buckets_scanned = 0; ALOGV("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT " "received."); if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } reqId = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If event has a different request_id, ignore that and use the * request_id value which we're maintaining. */ if (reqId != mRequestId) { #ifdef QC_HAL_DEBUG ALOGE("%s: Event has Req. ID:%d <> Ours:%d, continue...", __FUNCTION__, reqId, mRequestId); #endif reqId = mRequestId; } /* Parse and extract the results. */ if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH ]) { ALOGE("%s:RESULTS_SCAN_RESULT_IE_LENGTH not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } lengthOfInfoElements = nla_get_u32( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]); ALOGV("%s: RESULTS_SCAN_RESULT_IE_LENGTH =%d", __FUNCTION__, lengthOfInfoElements); resultsBufSize = lengthOfInfoElements + sizeof(wifi_scan_result); result = (wifi_scan_result *) malloc (resultsBufSize); if (!result) { ALOGE("%s: Failed to alloc memory for result struct. Exit.\n", __FUNCTION__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } memset(result, 0, resultsBufSize); result->ie_length = lengthOfInfoElements; /* Extract and fill out the wifi_scan_result struct. */ if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]) { ALOGE("%s: RESULTS_SCAN_RESULT_TIME_STAMP not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->ts = nla_get_u64( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_TIME_STAMP ]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID ]) { ALOGE("%s: RESULTS_SCAN_RESULT_SSID not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } len = nla_len(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]); len = sizeof(result->ssid) <= len ? sizeof(result->ssid) : len; memcpy((void *)&result->ssid, nla_data( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_SSID]), len); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID ]) { ALOGE("%s: RESULTS_SCAN_RESULT_BSSID not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } len = nla_len( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]); len = sizeof(result->bssid) <= len ? sizeof(result->bssid) : len; memcpy(&result->bssid, nla_data( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BSSID]), len); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL ]) { ALOGE("%s: RESULTS_SCAN_RESULT_CHANNEL not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->channel = nla_get_u32( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CHANNEL]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI ]) { ALOGE("%s: RESULTS_SCAN_RESULT_RSSI not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->rssi = get_s32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI] ); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT ]) { ALOGE("%s: RESULTS_SCAN_RESULT_RTT not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->rtt = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD ]) { ALOGE("%s: RESULTS_SCAN_RESULT_RTT_SD not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->rtt_sd = nla_get_u32( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT_SD]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]) { ALOGE("%s: RESULTS_SCAN_RESULT_BEACON_PERIOD not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->beacon_period = nla_get_u16( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_BEACON_PERIOD]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY ]) { ALOGE("%s: RESULTS_SCAN_RESULT_CAPABILITY not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } result->capability = nla_get_u16( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA ]) { ALOGE("%s: RESULTS_SCAN_RESULT_IE_DATA not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } memcpy(&(result->ie_data[0]), nla_data(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_DATA]), lengthOfInfoElements); if (! tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED ]) { ALOGD("%s: RESULTS_BUCKETS_SCANNED not found", __FUNCTION__); } else { buckets_scanned = get_u32(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_BUCKETS_SCANNED]); } #ifdef QC_HAL_DEBUG ALOGD("handleEvent:FULL_SCAN_RESULTS: ts %" PRId64, result->ts); ALOGD("handleEvent:FULL_SCAN_RESULTS: SSID %s ", result->ssid) ; ALOGD("handleEvent:FULL_SCAN_RESULTS: " "BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n", result->bssid[0], result->bssid[1], result->bssid[2], result->bssid[3], result->bssid[4], result->bssid[5]); ALOGD("handleEvent:FULL_SCAN_RESULTS: channel %d ", result->channel); ALOGD("handleEvent:FULL_SCAN_RESULTS: rssi %d ", result->rssi); ALOGD("handleEvent:FULL_SCAN_RESULTS: rtt %" PRId64, result->rtt); ALOGD("handleEvent:FULL_SCAN_RESULTS: rtt_sd %" PRId64, result->rtt_sd); ALOGD("handleEvent:FULL_SCAN_RESULTS: beacon period %d ", result->beacon_period); ALOGD("handleEvent:FULL_SCAN_RESULTS: capability %d ", result->capability); ALOGD("handleEvent:FULL_SCAN_RESULTS: IE length %d ", result->ie_length); ALOGD("%s: Invoking the callback. \n", __FUNCTION__); #endif if (mHandler.on_full_scan_result) { (*mHandler.on_full_scan_result)(reqId, result, buckets_scanned); /* Reset flag and num counter. */ free(result); result = NULL; } } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE: { wifi_request_id id; #ifdef QC_HAL_DEBUG ALOGV("Event " "QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE " "received."); #endif if (!tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID" "not found. Exit", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } id = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, then ignore it. */ if (id != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __FUNCTION__, id, mRequestId); break; } /* Invoke the callback func to report the number of results. */ ALOGV("%s: Calling on_scan_event handler", __FUNCTION__); (*mHandler.on_scan_event)(id, WIFI_SCAN_THRESHOLD_NUM_SCANS); } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND: { wifi_request_id id; u32 resultsBufSize = 0; u32 numResults = 0; u32 startingIndex, sizeOfObtainedResults; id = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, just ignore it. */ if (id != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __FUNCTION__, id, mRequestId); break; } if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } numResults = nla_get_u32(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]); ALOGV("%s: number of results:%d", __FUNCTION__, numResults); /* Get the memory size of previous fragments, if any. */ sizeOfObtainedResults = mHotlistApFoundNumResults * sizeof(wifi_scan_result); mHotlistApFoundNumResults += numResults; resultsBufSize += mHotlistApFoundNumResults * sizeof(wifi_scan_result); /* Check if this chunck of scan results is a continuation of * a previous one. */ if (mHotlistApFoundMoreData) { mHotlistApFoundResults = (wifi_scan_result *) realloc (mHotlistApFoundResults, resultsBufSize); } else { mHotlistApFoundResults = (wifi_scan_result *) malloc (resultsBufSize); } if (!mHotlistApFoundResults) { ALOGE("%s: Failed to alloc memory for results array. Exit.\n", __FUNCTION__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } /* Initialize the newly allocated memory area with 0. */ memset((u8 *)mHotlistApFoundResults + sizeOfObtainedResults, 0, resultsBufSize - sizeOfObtainedResults); ALOGV("%s: Num of AP FOUND results = %d. \n", __FUNCTION__, mHotlistApFoundNumResults); /* To support fragmentation from firmware, monitor the * MORE_DATA flag and cache results until MORE_DATA = 0. * Only then we can pass on the results to framework through * the callback function. */ if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not" " found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } else { mHotlistApFoundMoreData = nla_get_u8( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]); ALOGE("%s: More data = %d. \n", __FUNCTION__, mHotlistApFoundMoreData); } ALOGV("%s: Extract hotlist_ap_found results.\n", __FUNCTION__); startingIndex = mHotlistApFoundNumResults - numResults; ALOGV("%s: starting_index:%d", __FUNCTION__, startingIndex); ret = gscan_parse_hotlist_ap_results(numResults, mHotlistApFoundResults, startingIndex, tbVendor); /* If a parsing error occurred, exit and proceed for cleanup. */ if (ret) break; /* Send the results if no more result data fragments are expected */ if (!mHotlistApFoundMoreData) { (*mHandler.on_hotlist_ap_found)(id, mHotlistApFoundNumResults, mHotlistApFoundResults); /* Reset flag and num counter. */ free(mHotlistApFoundResults); mHotlistApFoundResults = NULL; mHotlistApFoundMoreData = false; mHotlistApFoundNumResults = 0; } } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST: { wifi_request_id id; u32 resultsBufSize = 0; u32 numResults = 0; u32 startingIndex, sizeOfObtainedResults; id = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, just ignore it. */ if (id != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __FUNCTION__, id, mRequestId); break; } if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } numResults = nla_get_u32(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]); ALOGV("%s: number of results:%d", __FUNCTION__, numResults); /* Get the memory size of previous fragments, if any. */ sizeOfObtainedResults = mHotlistApLostNumResults * sizeof(wifi_scan_result); mHotlistApLostNumResults += numResults; resultsBufSize += mHotlistApLostNumResults * sizeof(wifi_scan_result); /* Check if this chunck of scan results is a continuation of * a previous one. */ if (mHotlistApLostMoreData) { mHotlistApLostResults = (wifi_scan_result *) realloc (mHotlistApLostResults, resultsBufSize); } else { mHotlistApLostResults = (wifi_scan_result *) malloc (resultsBufSize); } if (!mHotlistApLostResults) { ALOGE("%s: Failed to alloc memory for results array. Exit.\n", __FUNCTION__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } /* Initialize the newly allocated memory area with 0. */ memset((u8 *)mHotlistApLostResults + sizeOfObtainedResults, 0, resultsBufSize - sizeOfObtainedResults); ALOGV("%s: Num of AP Lost results = %d. \n", __FUNCTION__, mHotlistApLostNumResults); /* To support fragmentation from firmware, monitor the * MORE_DATA flag and cache results until MORE_DATA = 0. * Only then we can pass on the results to framework through * the callback function. */ if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not" " found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } else { mHotlistApLostMoreData = nla_get_u8( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]); ALOGV("%s: More data = %d. \n", __FUNCTION__, mHotlistApLostMoreData); } ALOGV("%s: Extract hotlist_ap_Lost results.\n", __FUNCTION__); startingIndex = mHotlistApLostNumResults - numResults; ALOGV("%s: starting_index:%d", __FUNCTION__, startingIndex); ret = gscan_parse_hotlist_ap_results(numResults, mHotlistApLostResults, startingIndex, tbVendor); /* If a parsing error occurred, exit and proceed for cleanup. */ if (ret) break; /* Send the results if no more result data fragments are expected */ if (!mHotlistApLostMoreData) { (*mHandler.on_hotlist_ap_lost)(id, mHotlistApLostNumResults, mHotlistApLostResults); /* Reset flag and num counter. */ free(mHotlistApLostResults); mHotlistApLostResults = NULL; mHotlistApLostMoreData = false; mHotlistApLostNumResults = 0; } } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE: { wifi_request_id reqId; u32 numResults = 0, sizeOfObtainedResults; u32 startingIndex, index = 0; struct nlattr *scanResultsInfo; int rem = 0; if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } reqId = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, just ignore it. */ if (reqId != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __FUNCTION__, reqId, mRequestId); break; } if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) { ALOGE("%s: ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found." "Exit.", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } numResults = nla_get_u32(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]); /* Get the memory size of previous fragments, if any. */ sizeOfObtainedResults = sizeof(wifi_significant_change_result *) * mSignificantChangeNumResults; index = mSignificantChangeNumResults; mSignificantChangeNumResults += numResults; /* * Check if this chunck of wifi_significant_change results is a * continuation of a previous one. */ if (mSignificantChangeMoreData) { mSignificantChangeResults = (wifi_significant_change_result **) realloc (mSignificantChangeResults, sizeof(wifi_significant_change_result *) * mSignificantChangeNumResults); } else { mSignificantChangeResults = (wifi_significant_change_result **) malloc (sizeof(wifi_significant_change_result *) * mSignificantChangeNumResults); } if (!mSignificantChangeResults) { ALOGE("%s: Failed to alloc memory for results array. Exit.\n", __FUNCTION__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } /* Initialize the newly allocated memory area with 0. */ memset((u8 *)mSignificantChangeResults + sizeOfObtainedResults, 0, sizeof(wifi_significant_change_result *) * numResults); ALOGV("%s: mSignificantChangeMoreData = %d", __FUNCTION__, mSignificantChangeMoreData); for (scanResultsInfo = (struct nlattr *) nla_data(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]), rem = nla_len(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_LIST]); nla_ok(scanResultsInfo, rem); scanResultsInfo = nla_next(scanResultsInfo, &(rem))) { u32 num_rssi = 0; u32 resultsBufSize = 0; struct nlattr *tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1]; nla_parse(tb2, QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX, (struct nlattr *) nla_data(scanResultsInfo), nla_len(scanResultsInfo), NULL); if (!tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI ]) { ALOGE("%s: QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_" "SIGNIFICANT_CHANGE_RESULT_NUM_RSSI not found. " "Exit.", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } num_rssi = nla_get_u32(tb2[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SIGNIFICANT_CHANGE_RESULT_NUM_RSSI ]); resultsBufSize = sizeof(wifi_significant_change_result) + num_rssi * sizeof(wifi_rssi); mSignificantChangeResults[index] = (wifi_significant_change_result *) malloc (resultsBufSize); if (!mSignificantChangeResults[index]) { ALOGE("%s: Failed to alloc memory for results array Exit", __FUNCTION__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } /* Initialize the newly allocated memory area with 0. */ memset((u8 *)mSignificantChangeResults[index], 0, resultsBufSize); ALOGV("%s: For Significant Change results[%d], num_rssi:%d\n", __FUNCTION__, index, num_rssi); index++; } ALOGV("%s: Extract significant change results.\n", __FUNCTION__); startingIndex = mSignificantChangeNumResults - numResults; ret = gscan_get_significant_change_results(numResults, mSignificantChangeResults, startingIndex, tbVendor); /* If a parsing error occurred, exit and proceed for cleanup. */ if (ret) break; /* To support fragmentation from firmware, monitor the * MORE_DATA flag and cache results until MORE_DATA = 0. * Only then we can pass on the results to framework through * the callback function. */ if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not" " found. Stop parsing and exit.", __FUNCTION__); break; } mSignificantChangeMoreData = nla_get_u8( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]); ALOGV("%s: More data = %d. \n", __FUNCTION__, mSignificantChangeMoreData); /* Send the results if no more result fragments are expected */ if (!mSignificantChangeMoreData) { ALOGV("%s: Invoking the callback. \n", __FUNCTION__); (*mHandler.on_significant_change)(reqId, mSignificantChangeNumResults, mSignificantChangeResults); if (mSignificantChangeResults) { /* Reset flag and num counter. */ for (index = 0; index < mSignificantChangeNumResults; index++) { free(mSignificantChangeResults[index]); mSignificantChangeResults[index] = NULL; } free(mSignificantChangeResults); mSignificantChangeResults = NULL; } mSignificantChangeNumResults = 0; mSignificantChangeMoreData = false; } } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT: { wifi_scan_event scanEvent; wifi_request_id reqId; if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Exit.", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } reqId = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, just ignore it. */ if (reqId != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __FUNCTION__, reqId, mRequestId); break; } if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE]) { ALOGE("%s: GSCAN_RESULTS_SCAN_EVENT_TYPE not" " found. Stop parsing and exit.", __FUNCTION__); break; } scanEvent = (wifi_scan_event) nla_get_u8(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_TYPE]); ALOGV("%s: Scan event type: %d\n", __FUNCTION__, scanEvent); /* Send the results if no more result fragments are expected. */ (*mHandler.on_scan_event)(reqId, scanEvent); } break; case QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND: { wifi_request_id id; u32 resultsBufSize = 0; u32 numResults = 0; u32 startingIndex, sizeOfObtainedResults; if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { /* RequestId is not provided by FW/Driver for this event */ ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Continue.", __FUNCTION__); id = mRequestId; /* Use the saved mRequestId instead. */ } else { id = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, use the saved requestId */ if (id != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __FUNCTION__, id, mRequestId); id = mRequestId; } } if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } numResults = nla_get_u32(tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]); ALOGV("%s: number of results:%d", __FUNCTION__, numResults); /* Get the memory size of previous fragments, if any. */ sizeOfObtainedResults = mPnoNetworkFoundNumResults * sizeof(wifi_scan_result); mPnoNetworkFoundNumResults += numResults; resultsBufSize += mPnoNetworkFoundNumResults * sizeof(wifi_scan_result); /* Check if this chunck of scan results is a continuation of * a previous one. */ if (mPnoNetworkFoundMoreData) { mPnoNetworkFoundResults = (wifi_scan_result *) realloc (mPnoNetworkFoundResults, resultsBufSize); } else { mPnoNetworkFoundResults = (wifi_scan_result *) malloc (resultsBufSize); } if (!mPnoNetworkFoundResults) { ALOGE("%s: Failed to alloc memory for results array. Exit.\n", __FUNCTION__); ret = WIFI_ERROR_OUT_OF_MEMORY; break; } /* Initialize the newly allocated memory area with 0. */ memset((u8 *)mPnoNetworkFoundResults + sizeOfObtainedResults, 0, resultsBufSize - sizeOfObtainedResults); ALOGV("%s: Num of AP FOUND results = %d. \n", __FUNCTION__, mPnoNetworkFoundNumResults); /* To support fragmentation from firmware, monitor the * MORE_DATA flag and cache results until MORE_DATA = 0. * Only then we can pass on the results to framework through * the callback function. */ if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]) { ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_MORE_DATA not" " found", __FUNCTION__); ret = WIFI_ERROR_INVALID_ARGS; break; } else { mPnoNetworkFoundMoreData = nla_get_u8( tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]); ALOGV("%s: More data = %d. \n", __FUNCTION__, mPnoNetworkFoundMoreData); } ALOGV("%s: Extract PNO_NETWORK_FOUND results.\n", __FUNCTION__); startingIndex = mPnoNetworkFoundNumResults - numResults; ALOGV("%s: starting_index:%d", __FUNCTION__, startingIndex); ret = gscan_parse_pno_network_results(numResults, mPnoNetworkFoundResults, startingIndex, tbVendor); /* If a parsing error occurred, exit and proceed for cleanup. */ if (ret) break; /* Send the results if no more result data fragments are expected */ if (!mPnoNetworkFoundMoreData) { (*mHandler.on_pno_network_found)(id, mPnoNetworkFoundNumResults, mPnoNetworkFoundResults); /* Reset flag and num counter. */ if (mPnoNetworkFoundResults) { free(mPnoNetworkFoundResults); mPnoNetworkFoundResults = NULL; } mPnoNetworkFoundMoreData = false; mPnoNetworkFoundNumResults = 0; } } break; case QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND: { wifi_request_id id; if (!tbVendor[ QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID]) { /* RequestId is not provided by FW/Driver for this event */ ALOGE("%s: ATTR_GSCAN_RESULTS_REQUEST_ID not found. Continue.", __FUNCTION__); id = mRequestId; /* Use the saved mRequestId instead. */ } else { id = nla_get_u32( tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_REQUEST_ID] ); /* If this is not for us, use the saved requestId */ if (id != mRequestId) { ALOGE("%s: Event has Req. ID:%d <> ours:%d", __FUNCTION__, id, mRequestId); id = mRequestId; } } ret = gscan_parse_passpoint_network_result(tbVendor); /* If a parsing error occurred, exit and proceed for cleanup. */ if (ret) { ALOGE("%s: gscan_parse_passpoint_network_result" "returned error: %d.\n", __FUNCTION__, ret); break; } (*mHandler.on_passpoint_network_found)(id, mPasspointNetId, mPasspointNetworkFoundResult, mPasspointAnqpLen, mPasspointAnqp); if (mPasspointNetworkFoundResult) { free(mPasspointNetworkFoundResult); mPasspointNetworkFoundResult = NULL; } if (mPasspointAnqp) { free(mPasspointAnqp); mPasspointAnqp = NULL; } mPasspointNetId = -1; mPasspointAnqpLen = 0; } break; default: /* Error case should not happen print log */ ALOGE("%s: Wrong GScan subcmd received %d", __FUNCTION__, mSubcmd); } /* A parsing error occurred, do the cleanup of gscan result lists. */ if (ret) { switch(mSubcmd) { case QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT: { free(result); result = NULL; } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND: { /* Reset flag and num counter. */ free(mHotlistApFoundResults); mHotlistApFoundResults = NULL; mHotlistApFoundMoreData = false; mHotlistApFoundNumResults = 0; } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE: { if (mSignificantChangeResults) { for (i = 0; i < mSignificantChangeNumResults; i++) { if (mSignificantChangeResults[i]) { free(mSignificantChangeResults[i]); mSignificantChangeResults[i] = NULL; } } free(mSignificantChangeResults); mSignificantChangeResults = NULL; } mSignificantChangeNumResults = 0; mSignificantChangeMoreData = false; } break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE: break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT: break; case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST: { /* Reset flag and num counter. */ free(mHotlistApLostResults); mHotlistApLostResults = NULL; mHotlistApLostMoreData = false; mHotlistApLostNumResults = 0; } break; case QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND: { /* Reset flag and num counter. */ if (mPnoNetworkFoundResults) { free(mPnoNetworkFoundResults); mPnoNetworkFoundResults = NULL; } mPnoNetworkFoundMoreData = false; mPnoNetworkFoundNumResults = 0; } break; case QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_NETWORK_FOUND: { if (mPasspointNetworkFoundResult) { free(mPasspointNetworkFoundResult); mPasspointNetworkFoundResult = NULL; } if (mPasspointAnqp) { free(mPasspointAnqp); mPasspointAnqp = NULL; } mPasspointNetId = -1; mPasspointAnqpLen = 0; } break; default: ALOGE("%s: Parsing err handler: wrong GScan subcmd " "received %d", __FUNCTION__, mSubcmd); } } return NL_SKIP; }