/*
* 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 <utils/Log.h>
#include "gscan_event_handler.h"
#include "vendor_definitions.h"
/* This function implements creation of Vendor command event handler. */
int GScanCommandEventHandler::create() {
int ret = mMsg.create(NL80211_CMD_VENDOR, 0, 0);
if (ret < 0) {
return ret;
}
/* Insert the oui in the msg */
ret = mMsg.put_u32(NL80211_ATTR_VENDOR_ID, mVendor_id);
if (ret < 0)
goto out;
/* Insert the subcmd in the msg */
ret = mMsg.put_u32(NL80211_ATTR_VENDOR_SUBCMD, mSubcmd);
if (ret < 0)
goto out;
out:
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;
ALOGD("GScanCommandEventHandler %p constructed", this);
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. */
ALOGD("%s: wait for GSCAN_RESULTS_AVAILABLE, "
"FULL_SCAN_RESULT, and SCAN EVENT events. \n", __FUNCTION__);
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)
ALOGD("%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)
ALOGD("%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)
ALOGD("%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)
ALOGD("%s: Error in registering handler for"
" GSCAN_HOTLIST_AP_LOST. \n", __FUNCTION__);
}
break;
case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SSID_HOTLIST:
{
ret = registerVendorHandler(mVendor_id,
QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_FOUND);
if (ret)
ALOGD("%s: Error in registering handler for"
" GSCAN_HOTLIST_SSID_FOUND. \n", __FUNCTION__);
ret = registerVendorHandler(mVendor_id,
QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_LOST);
if (ret)
ALOGD("%s: Error in registering handler for"
" GSCAN_HOTLIST_SSID_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)
ALOGD("%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)
ALOGD("%s: Error in registering handler for"
" PNO_PASSPOINT_NETWORK_FOUND. \n", __FUNCTION__);
}
break;
}
}
GScanCommandEventHandler::~GScanCommandEventHandler()
{
ALOGD("GScanCommandEventHandler %p destructor", this);
switch(mSubCommandId)
{
case QCA_NL80211_VENDOR_SUBCMD_GSCAN_START:
{
/* Unregister event handlers. */
ALOGD("%s: Unregister handlers for GSCAN_RESULTS_AVAILABLE, "
"FULL_SCAN_RESULT, and SCAN EVENT events. \n", __FUNCTION__);
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_GSCAN_SET_SSID_HOTLIST:
{
unregisterVendorHandler(mVendor_id,
QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_FOUND);
unregisterVendorHandler(mVendor_id,
QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_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;
ALOGE("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]);
ALOGE("gscan_parse_hotlist_ap_results: ts %lld ", results[i].ts);
ALOGE("gscan_parse_hotlist_ap_results: SSID %s ",
results[i].ssid) ;
ALOGE("gscan_parse_hotlist_ap_results: "
"BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
results[i].bssid[0], results[i].bssid[1], results[i].bssid[2],
results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]);
ALOGE("gscan_parse_hotlist_ap_results: channel %d ",
results[i].channel);
ALOGE("gscan_parse_hotlist_ap_results: rssi %d ", results[i].rssi);
ALOGE("gscan_parse_hotlist_ap_results: rtt %lld ", results[i].rtt);
ALOGE("gscan_parse_hotlist_ap_results: rtt_sd %lld ",
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;
struct nlattr *scanResultsInfo;
ALOGI("gscan_get_significant_change_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_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);
ALOGI("\nsignificant_change_result:%d, BSSID:"
"%02x:%02x:%02x:%02x:%02x:%02x \n", 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]);
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]);
ALOGI("significant_change_result:%d, channel:%d.\n",
i, results[i]->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]);
ALOGI("gscan_get_significant_change_results: "
"significant_change_result:%d, num_rssi:%d.\n",
i, results[i]->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;
}
ALOGI("gscan_get_significant_change_results: before reading the RSSI "
"list: num_rssi:%d, size_of_rssi:%d, total size:%d, ",
results[i]->num_rssi,
sizeof(wifi_rssi), results[i]->num_rssi * sizeof(wifi_rssi));
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));
for (j = 0; j < results[i]->num_rssi; j++)
ALOGI(" significant_change_result: %d, rssi[%d]:%d, ",
i, j, results[i]->rssi[j]);
/* 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;
ALOGI("gscan_parse_hotlist_ssid_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_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]);
ALOGD("gscan_parse_hotlist_ssid_results: ts %lld ", results[i].ts);
ALOGD("gscan_parse_hotlist_ssid_results: SSID %s ",
results[i].ssid) ;
ALOGD("gscan_parse_hotlist_ssid_results: "
"BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
results[i].bssid[0], results[i].bssid[1], results[i].bssid[2],
results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]);
ALOGD("gscan_parse_hotlist_ssid_results: channel %d ",
results[i].channel);
ALOGD("gscan_parse_hotlist_ssid_results: rssi %d ", results[i].rssi);
ALOGD("gscan_parse_hotlist_ssid_results: rtt %lld ", results[i].rtt);
ALOGD("gscan_parse_hotlist_ssid_results: rtt_sd %lld ",
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;
ALOGI("%s: Entering", __FUNCTION__);
for (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
]);
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_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);
ALOGD("%s: ts %lld ", __FUNCTION__,
mPasspointNetworkFoundResult->ts);
ALOGD("%s: SSID %s ", __FUNCTION__,
mPasspointNetworkFoundResult->ssid);
ALOGD("%s: BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
__FUNCTION__,
mPasspointNetworkFoundResult->bssid[0],
mPasspointNetworkFoundResult->bssid[1],
mPasspointNetworkFoundResult->bssid[2],
mPasspointNetworkFoundResult->bssid[3],
mPasspointNetworkFoundResult->bssid[4],
mPasspointNetworkFoundResult->bssid[5]);
ALOGD("%s: channel %d ", __FUNCTION__,
mPasspointNetworkFoundResult->channel);
ALOGD("%s: rssi %d ", __FUNCTION__,
mPasspointNetworkFoundResult->rssi);
ALOGD("%s: rtt %lld ", __FUNCTION__,
mPasspointNetworkFoundResult->rtt);
ALOGD("%s: rtt_sd %lld ", __FUNCTION__,
mPasspointNetworkFoundResult->rtt_sd);
ALOGD("%s: ie_length %lld ", __FUNCTION__,
mPasspointNetworkFoundResult->ie_length);
ALOGD("%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]);
ALOGI("%s: PNO_RESULTS_PASSPOINT_MATCH_ANQP_LEN = %d",
__FUNCTION__, mPasspointAnqpLen);
if (!mPasspointAnqpLen)
{
break;
}
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);
ALOGD("%s: ANQP LEN:%d, ANQP IE:", __FUNCTION__, mPasspointAnqpLen);
hexdump((char*)mPasspointAnqp, mPasspointAnqpLen);
/* expecting only one result break out after the first loop */
break;
}
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;
ALOGD("gscan_parse_pno_network_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_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",
__FUNCTION__);
return WIFI_ERROR_INVALID_ARGS;
break;
}
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", __FUNCTION__);
return WIFI_ERROR_INVALID_ARGS;
break;
}
results[i].capability =
nla_get_u16(
tb2[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_CAPABILITY]);
ALOGD("gscan_parse_pno_network_results: ts %lld ", results[i].ts);
ALOGD("gscan_parse_pno_network_results: SSID %s ",
results[i].ssid) ;
ALOGD("gscan_parse_pno_network_results: "
"BSSID: %02x:%02x:%02x:%02x:%02x:%02x \n",
results[i].bssid[0], results[i].bssid[1], results[i].bssid[2],
results[i].bssid[3], results[i].bssid[4], results[i].bssid[5]);
ALOGD("gscan_parse_pno_network_results: channel %d ",
results[i].channel);
ALOGD("gscan_parse_pno_network_results: rssi %d ", results[i].rssi);
ALOGD("gscan_parse_pno_network_results: rtt %lld ", results[i].rtt);
ALOGD("gscan_parse_pno_network_results: rtt_sd %lld ",
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;
u32 status;
wifi_scan_result *result = NULL;
struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
if (mEventHandlingEnabled == false)
{
ALOGD("%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;
#ifdef QC_HAL_DEBUG
ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_FULL_SCAN_RESULT "
"received.");
#endif
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]);
ALOGD("%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);
#ifdef QC_HAL_DEBUG
ALOGD("handleEvent:FULL_SCAN_RESULTS: ts %lld ", 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 %lld ", result->rtt);
ALOGD("handleEvent:FULL_SCAN_RESULTS: rtt_sd %lld ",
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);
/* Reset flag and num counter. */
free(result);
result = NULL;
}
}
break;
case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE:
{
wifi_request_id id;
u32 numResults = 0;
ALOGD("Event "
"QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_RESULTS_AVAILABLE "
"received.");
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;
}
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]);
ALOGD("%s: number of results:%d", __FUNCTION__, numResults);
/* Invoke the callback func to report the number of results. */
ALOGD("%s: Calling on_scan_results_available handler",
__FUNCTION__);
if (!mHandler.on_scan_results_available) {
break;
}
(*mHandler.on_scan_results_available)(id, numResults);
}
break;
case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND:
{
wifi_request_id id;
u32 resultsBufSize = 0;
u32 numResults = 0;
u32 startingIndex, sizeOfObtainedResults;
ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND "
"received.");
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]);
ALOGD("%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);
ALOGD("%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);
}
ALOGD("%s: Extract hotlist_ap_found results.\n", __FUNCTION__);
startingIndex = mHotlistApFoundNumResults - numResults;
ALOGD("%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;
ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_LOST "
"received.");
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]);
ALOGD("%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);
ALOGD("%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]);
ALOGE("%s: More data = %d. \n",
__FUNCTION__, mHotlistApLostMoreData);
}
ALOGD("%s: Extract hotlist_ap_Lost results.\n", __FUNCTION__);
startingIndex = mHotlistApLostNumResults - numResults;
ALOGD("%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;
ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE "
"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 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);
ALOGD("%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);
ALOGD("%s: For Significant Change results[%d], num_rssi:%d\n",
__FUNCTION__, index, num_rssi);
index++;
}
ALOGD("%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]);
ALOGD("%s: More data = %d. \n",
__FUNCTION__, mSignificantChangeMoreData);
/* Send the results if no more result fragments are expected */
if (!mSignificantChangeMoreData) {
ALOGD("%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;
u32 scanEventStatus = 0;
wifi_request_id reqId;
ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_SCAN_EVENT "
"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 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]);
if (!tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS]) {
ALOGE("%s: GSCAN_RESULTS_SCAN_EVENT_STATUS not"
" found. Stop parsing and exit.", __FUNCTION__);
break;
}
scanEventStatus = nla_get_u32(tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS]);
ALOGI("%s: Scan event type: %d, status = %d. \n", __FUNCTION__,
scanEvent, scanEventStatus);
/* Send the results if no more result fragments are expected. */
(*mHandler.on_scan_event)(scanEvent, scanEventStatus);
}
break;
case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_FOUND:
{
wifi_request_id id;
u32 resultsBufSize = 0;
u32 numResults = 0;
u32 startingIndex, sizeOfObtainedResults;
ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_FOUND "
"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;
}
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]);
ALOGD("%s: number of results:%d", __FUNCTION__, numResults);
/* Get the memory size of previous fragments, if any. */
sizeOfObtainedResults = mHotlistSsidFoundNumResults *
sizeof(wifi_scan_result);
mHotlistSsidFoundNumResults += numResults;
resultsBufSize += mHotlistSsidFoundNumResults *
sizeof(wifi_scan_result);
/* Check if this chunck of scan results is a continuation of
* a previous one.
*/
if (mHotlistSsidFoundMoreData) {
mHotlistSsidFoundResults = (wifi_scan_result *)
realloc (mHotlistSsidFoundResults, resultsBufSize);
} else {
mHotlistSsidFoundResults = (wifi_scan_result *)
malloc (resultsBufSize);
}
if (!mHotlistSsidFoundResults) {
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 *)mHotlistSsidFoundResults + sizeOfObtainedResults, 0,
resultsBufSize - sizeOfObtainedResults);
ALOGD("%s: Num of SSID FOUND results = %d. \n", __FUNCTION__,
mHotlistSsidFoundNumResults);
/* 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 {
mHotlistSsidFoundMoreData = nla_get_u8(
tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
ALOGE("%s: More data = %d. \n",
__FUNCTION__, mHotlistSsidFoundMoreData);
}
ALOGD("%s: Extract hotlist_ssid_found results.\n", __FUNCTION__);
startingIndex = mHotlistSsidFoundNumResults - numResults;
ALOGD("%s: starting_index:%d",
__FUNCTION__, startingIndex);
ret = gscan_parse_hotlist_ssid_results(numResults,
mHotlistSsidFoundResults,
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 (!mHotlistSsidFoundMoreData) {
(*mHandler.on_hotlist_ssid_found)(id,
mHotlistSsidFoundNumResults,
mHotlistSsidFoundResults);
/* Reset flag and num counter. */
free(mHotlistSsidFoundResults);
mHotlistSsidFoundResults = NULL;
mHotlistSsidFoundMoreData = false;
mHotlistSsidFoundNumResults = 0;
}
}
break;
case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_LOST:
{
wifi_request_id id;
u32 resultsBufSize = 0;
u32 numResults = 0;
u32 startingIndex, sizeOfObtainedResults;
ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_LOST "
"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;
}
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]);
ALOGD("%s: number of results:%d", __FUNCTION__, numResults);
/* Get the memory size of previous fragments, if any. */
sizeOfObtainedResults = mHotlistSsidLostNumResults *
sizeof(wifi_scan_result);
mHotlistSsidLostNumResults += numResults;
resultsBufSize += mHotlistSsidLostNumResults *
sizeof(wifi_scan_result);
/* Check if this chunck of scan results is a continuation of
* a previous one.
*/
if (mHotlistSsidLostMoreData) {
mHotlistSsidLostResults = (wifi_scan_result *)
realloc (mHotlistSsidLostResults, resultsBufSize);
} else {
mHotlistSsidLostResults = (wifi_scan_result *)
malloc (resultsBufSize);
}
if (!mHotlistSsidLostResults) {
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 *)mHotlistSsidLostResults + sizeOfObtainedResults, 0,
resultsBufSize - sizeOfObtainedResults);
ALOGD("%s: Num of SSID Lost results = %d. \n", __FUNCTION__,
mHotlistSsidLostNumResults);
/* 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 {
mHotlistSsidLostMoreData = nla_get_u8(
tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
ALOGE("%s: More data = %d. \n",
__FUNCTION__, mHotlistSsidLostMoreData);
}
ALOGD("%s: Extract hotlist_ssid_Lost results.\n", __FUNCTION__);
startingIndex = mHotlistSsidLostNumResults - numResults;
ALOGD("%s: starting_index:%d",
__FUNCTION__, startingIndex);
ret = gscan_parse_hotlist_ssid_results(numResults,
mHotlistSsidLostResults,
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 (!mHotlistSsidLostMoreData) {
(*mHandler.on_hotlist_ssid_lost)(id,
mHotlistSsidLostNumResults,
mHotlistSsidLostResults);
/* Reset flag and num counter. */
free(mHotlistSsidLostResults);
mHotlistSsidLostResults = NULL;
mHotlistSsidLostMoreData = false;
mHotlistSsidLostNumResults = 0;
}
}
break;
case QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND:
{
wifi_request_id id;
u32 resultsBufSize = 0;
u32 numResults = 0;
u32 startingIndex, sizeOfObtainedResults;
ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_PNO_NETWORK_FOUND "
"received.");
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]);
ALOGI("%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);
ALOGI("%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]);
ALOGD("%s: More data = %d. \n",
__FUNCTION__, mPnoNetworkFoundMoreData);
}
ALOGD("%s: Extract PNO_NETWORK_FOUND results.\n", __FUNCTION__);
startingIndex = mPnoNetworkFoundNumResults - numResults;
ALOGD("%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;
ALOGD("Event QCA_NL80211_VENDOR_SUBCMD_PNO_PASSPOINT_"
"NETWORK_FOUND received.");
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_GSCAN_HOTLIST_SSID_FOUND:
{
/* Reset flag and num counter. */
free(mHotlistSsidFoundResults);
mHotlistSsidFoundResults = NULL;
mHotlistSsidFoundMoreData = false;
mHotlistSsidFoundNumResults = 0;
}
break;
case QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_SSID_LOST:
{
/* Reset flag and num counter. */
free(mHotlistSsidLostResults);
mHotlistSsidLostResults = NULL;
mHotlistSsidLostMoreData = false;
mHotlistSsidLostNumResults = 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;
}