/*
* 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.
*/
#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;
}
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;
mSignificantChangeResults = NULL;
mSignificantChangeNumResults = 0;
mSignificantChangeMoreData = 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", __func__);
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 < 0)
ALOGD("%s: Error in registering handler for "
"GSCAN_START. \n", __func__);
}
break;
case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_SIGNIFICANT_CHANGE:
{
ret = registerVendorHandler(mVendor_id,
QCA_NL80211_VENDOR_SUBCMD_GSCAN_SIGNIFICANT_CHANGE);
if (ret < 0)
ALOGD("%s: Error in registering handler for "
"GSCAN_SIGNIFICANT_CHANGE. \n", __func__);
}
break;
case QCA_NL80211_VENDOR_SUBCMD_GSCAN_SET_BSSID_HOTLIST:
{
ret = registerVendorHandler(mVendor_id,
QCA_NL80211_VENDOR_SUBCMD_GSCAN_HOTLIST_AP_FOUND);
if (ret < 0)
ALOGD("%s: Error in registering handler for"
" GSCAN_HOTLIST_AP_FOUND. \n", __func__);
}
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", __func__);
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);
}
break;
}
}
static wifi_error gscan_get_hotlist_ap_found_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_get_hotlist_ap_found_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_get_hotlist_ap_found_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_get_hotlist_ap_found_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_get_hotlist_ap_found_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_get_hotlist_ap_found_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_get_hotlist_ap_found_results: "
"RESULTS_SCAN_RESULT_RSSI not found");
return WIFI_ERROR_INVALID_ARGS;
}
results[i].rssi =
nla_get_u32(
tb2[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RSSI]);
if (!
tb2[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_RTT
])
{
ALOGE("gscan_get_hotlist_ap_found_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_get_hotlist_ap_found_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_get_hotlist_ap_found_results: ts %lld ", results[i].ts);
ALOGE("gscan_get_hotlist_ap_found_results: SSID %s ",
results[i].ssid) ;
ALOGE("gscan_get_hotlist_ap_found_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_get_hotlist_ap_found_results: channel %d ",
results[i].channel);
ALOGE("gscan_get_hotlist_ap_found_results: rssi %d ", results[i].rssi);
ALOGE("gscan_get_hotlist_ap_found_results: rtt %lld ", results[i].rtt);
ALOGE("gscan_get_hotlist_ap_found_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;
ALOGE("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;
}
/* This function will be the main handler for incoming (from driver) GSscan_SUBCMD.
* Calls the appropriate callback handler after parsing the vendor data.
*/
int GScanCommandEventHandler::handleEvent(WifiEvent &event)
{
ALOGI("GScanCommandEventHandler::handleEvent: Got a GSCAN Event"
" message from the Driver.");
unsigned i=0;
int ret = WIFI_SUCCESS;
u32 status;
wifi_scan_result *result;
struct nlattr *tbVendor[QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_MAX + 1];
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;
ALOGD("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.",
__func__);
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, ignore it.",
__func__, reqId, mRequestId);
break;
}
/* 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", __func__);
ret = WIFI_ERROR_INVALID_ARGS;
break;
}
lengthOfInfoElements =
nla_get_u32(
tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_IE_LENGTH]);
ALOGI("%s: RESULTS_SCAN_RESULT_IE_LENGTH =%d",
__func__, 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",
__func__);
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",
__func__);
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", __func__);
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", __func__);
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", __func__);
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", __func__);
ret = WIFI_ERROR_INVALID_ARGS;
break;
}
result->rssi =
nla_get_u32(
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", __func__);
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", __func__);
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",
__func__);
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", __func__);
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", __func__);
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);
ALOGE("handleEvent:FULL_SCAN_RESULTS: ts %lld ", result->ts);
ALOGE("handleEvent:FULL_SCAN_RESULTS: SSID %s ", result->ssid) ;
ALOGE("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]);
ALOGE("handleEvent:FULL_SCAN_RESULTS: channel %d ",
result->channel);
ALOGE("handleEvent:FULL_SCAN_RESULTS: rssi %d ", result->rssi);
ALOGE("handleEvent:FULL_SCAN_RESULTS: rtt %lld ", result->rtt);
ALOGE("handleEvent:FULL_SCAN_RESULTS: rtt_sd %lld ",
result->rtt_sd);
ALOGE("handleEvent:FULL_SCAN_RESULTS: beacon period %d ",
result->beacon_period);
ALOGE("handleEvent:FULL_SCAN_RESULTS: capability %d ",
result->capability);
ALOGE("handleEvent:FULL_SCAN_RESULTS: IE length %d ",
result->ie_length);
ALOGE("%s: Invoking the callback. \n", __func__);
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", __func__);
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",
__func__, id, mRequestId);
break;
}
if (!tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found",
__func__);
ret = WIFI_ERROR_INVALID_ARGS;
break;
}
numResults = nla_get_u32(tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
ALOGE("%s: number of results:%d", __func__, numResults);
/* Invoke the callback func to report the number of results. */
ALOGE("%s: Calling on_scan_results_available handler",
__func__);
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",
__func__, id, mRequestId);
break;
}
if (!tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]) {
ALOGE("%s: GSCAN_RESULTS_NUM_RESULTS_AVAILABLE not found",
__func__);
ret = WIFI_ERROR_INVALID_ARGS;
break;
}
numResults = nla_get_u32(tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_NUM_RESULTS_AVAILABLE]);
ALOGE("%s: number of results:%d", __func__, 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",
__func__);
ret = WIFI_ERROR_OUT_OF_MEMORY;
break;
}
/* Initialize the newly allocated memory area with 0. */
memset((u8 *)mHotlistApFoundResults + sizeOfObtainedResults, 0,
resultsBufSize - sizeOfObtainedResults);
ALOGE("%s: Num of AP FOUND results = %d. \n", __func__,
mHotlistApFoundNumResults);
/* To support fragmentation from firmware, monitor the
* MORE_DTATA 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", __func__);
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",
__func__, mHotlistApFoundMoreData);
}
ALOGE("%s: Extract hotlist_ap_found results.\n", __func__);
startingIndex = mHotlistApFoundNumResults - numResults;
ALOGE("%s: starting_index:%d",
__func__, startingIndex);
ret = gscan_get_hotlist_ap_found_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_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.",
__func__);
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",
__func__, 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.", __func__);
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",
__func__);
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",
__func__, 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.", __func__);
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.\n",
__func__);
ret = WIFI_ERROR_OUT_OF_MEMORY;
break;
}
/* Initialize the newly allocated memory area with 0. */
memset((u8 *)mSignificantChangeResults[index],
0, resultsBufSize);
ALOGE("%s: For Significant Change results[%d], num_rssi:%d\n",
__func__, index, num_rssi);
index++;
}
ALOGE("%s: Extract significant change results.\n", __func__);
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_DTATA 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.", __func__);
break;
}
mSignificantChangeMoreData = nla_get_u8(
tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_RESULT_MORE_DATA]);
ALOGE("%s: More data = %d. \n",
__func__, mSignificantChangeMoreData);
/* Send the results if no more result fragments are expected */
if (!mSignificantChangeMoreData) {
ALOGE("%s: Invoking the callback. \n", __func__);
(*mHandler.on_significant_change)(reqId,
mSignificantChangeNumResults,
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.",
__func__);
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",
__func__, 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.", __func__);
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.", __func__);
break;
}
scanEventStatus = nla_get_u32(tbVendor[
QCA_WLAN_VENDOR_ATTR_GSCAN_RESULTS_SCAN_EVENT_STATUS]);
ALOGE("%s: Scan event type: %d, status = %d. \n", __func__,
scanEvent, scanEventStatus);
/* Send the results if no more result fragments are expected. */
(*mHandler.on_scan_event)(scanEvent, scanEventStatus);
}
break;
default:
/* Error case should not happen print log */
ALOGE("%s: Wrong GScan subcmd received %d", __func__, 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:
{
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;
default:
ALOGE("%s: Parsing err handler: wrong GScan subcmd "
"received %d", __func__, mSubcmd);
}
}
return NL_SKIP;
}