/*
* 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 "sync.h"
#include <utils/Log.h>
#include "nan.h"
#include "wifi_hal.h"
#include "nan_i.h"
#include "nancommand.h"
int NanCommand::isNanResponse()
{
if (mNanVendorEvent == NULL) {
ALOGE("NULL check failed");
return WIFI_ERROR_INVALID_ARGS;
}
NanMsgHeader *pHeader = (NanMsgHeader *)mNanVendorEvent;
switch (pHeader->msgId) {
case NAN_MSG_ID_ERROR_RSP:
case NAN_MSG_ID_CONFIGURATION_RSP:
case NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_RSP:
case NAN_MSG_ID_PUBLISH_SERVICE_RSP:
case NAN_MSG_ID_SUBSCRIBE_SERVICE_RSP:
case NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_RSP:
case NAN_MSG_ID_TRANSMIT_FOLLOWUP_RSP:
case NAN_MSG_ID_STATS_RSP:
case NAN_MSG_ID_ENABLE_RSP:
case NAN_MSG_ID_DISABLE_RSP:
case NAN_MSG_ID_TCA_RSP:
#ifdef NAN_2_0
case NAN_MSG_ID_BEACON_SDF_RSP:
#endif /* NAN_2_0 */
return 1;
default:
return 0;
}
}
int NanCommand::getNanResponse(NanResponseMsg *pRsp)
{
if (mNanVendorEvent == NULL || pRsp == NULL) {
ALOGE("NULL check failed");
return WIFI_ERROR_INVALID_ARGS;
}
NanMsgHeader *pHeader = (NanMsgHeader *)mNanVendorEvent;
switch (pHeader->msgId) {
case NAN_MSG_ID_ERROR_RSP:
{
pNanErrorRspMsg pFwRsp = \
(pNanErrorRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = pFwRsp->value;
pRsp->response_type = NAN_RESPONSE_ERROR;
break;
}
case NAN_MSG_ID_CONFIGURATION_RSP:
{
pNanConfigurationRspMsg pFwRsp = \
(pNanConfigurationRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = pFwRsp->value;
pRsp->response_type = NAN_RESPONSE_CONFIG;
}
break;
case NAN_MSG_ID_PUBLISH_SERVICE_CANCEL_RSP:
{
pNanPublishServiceCancelRspMsg pFwRsp = \
(pNanPublishServiceCancelRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = pFwRsp->value;
pRsp->response_type = NAN_RESPONSE_PUBLISH_CANCEL;
break;
}
case NAN_MSG_ID_PUBLISH_SERVICE_RSP:
{
pNanPublishServiceRspMsg pFwRsp = \
(pNanPublishServiceRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = pFwRsp->value;
pRsp->response_type = NAN_RESPONSE_PUBLISH;
break;
}
case NAN_MSG_ID_SUBSCRIBE_SERVICE_RSP:
{
pNanSubscribeServiceRspMsg pFwRsp = \
(pNanSubscribeServiceRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = pFwRsp->value;
pRsp->response_type = NAN_RESPONSE_SUBSCRIBE;
}
break;
case NAN_MSG_ID_SUBSCRIBE_SERVICE_CANCEL_RSP:
{
pNanSubscribeServiceCancelRspMsg pFwRsp = \
(pNanSubscribeServiceCancelRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = pFwRsp->value;
pRsp->response_type = NAN_RESPONSE_SUBSCRIBE_CANCEL;
break;
}
case NAN_MSG_ID_TRANSMIT_FOLLOWUP_RSP:
{
pNanTransmitFollowupRspMsg pFwRsp = \
(pNanTransmitFollowupRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = pFwRsp->value;
pRsp->response_type = NAN_RESPONSE_TRANSMIT_FOLLOWUP;
break;
}
case NAN_MSG_ID_STATS_RSP:
{
pNanStatsRspMsg pFwRsp = \
(pNanStatsRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->statsRspParams.status;
pRsp->value = pFwRsp->statsRspParams.value;
pRsp->response_type = NAN_RESPONSE_STATS;
pRsp->body.stats_response.stats_id = \
(NanStatsId)pFwRsp->statsRspParams.statsId;
ALOGI("%s: stats_id:%d",__func__,
pRsp->body.stats_response.stats_id);
u8 *pInputTlv = pFwRsp->ptlv;
NanTlv outputTlv;
memset(&outputTlv, 0, sizeof(outputTlv));
u16 readLen = 0;
int remainingLen = (mNanDataLen - \
(sizeof(NanMsgHeader) + sizeof(NanStatsRspParams)));
if (remainingLen > 0) {
readLen = NANTLV_ReadTlv(pInputTlv, &outputTlv);
ALOGI("%s: Remaining Len:%d readLen:%d type:%d length:%d",
__func__, remainingLen, readLen, outputTlv.type,
outputTlv.length);
if (outputTlv.length <= \
sizeof(pRsp->body.stats_response.data)) {
memcpy(&pRsp->body.stats_response.data, outputTlv.value,
outputTlv.length);
hexdump((char*)&pRsp->body.stats_response.data, outputTlv.length);
}
else {
ALOGE("%s:copying only sizeof(pRsp->body.stats_response.data):%d",
__func__, sizeof(pRsp->body.stats_response.data));
memcpy(&pRsp->body.stats_response.data, outputTlv.value,
sizeof(pRsp->body.stats_response.data));
hexdump((char*)&pRsp->body.stats_response.data,
sizeof(pRsp->body.stats_response.data));
}
}
else
ALOGI("%s: No TLV's present",__func__);
break;
}
case NAN_MSG_ID_ENABLE_RSP:
{
pNanEnableRspMsg pFwRsp = \
(pNanEnableRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = pFwRsp->value;
pRsp->response_type = NAN_RESPONSE_ENABLED;
break;
}
case NAN_MSG_ID_DISABLE_RSP:
{
pNanDisableRspMsg pFwRsp = \
(pNanDisableRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = 0;
pRsp->response_type = NAN_RESPONSE_DISABLED;
break;
}
case NAN_MSG_ID_TCA_RSP:
{
pNanTcaRspMsg pFwRsp = \
(pNanTcaRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = pFwRsp->value;
pRsp->response_type = NAN_RESPONSE_TCA;
break;
}
#ifdef NAN_2_0
case NAN_MSG_ID_BEACON_SDF_RSP:
{
pNanBeaconSdfPayloadRspMsg pFwRsp = \
(pNanBeaconSdfPayloadRspMsg)mNanVendorEvent;
pRsp->header.handle = pFwRsp->fwHeader.handle;
pRsp->header.transaction_id = pFwRsp->fwHeader.transactionId;
pRsp->status = pFwRsp->status;
pRsp->value = 0;
pRsp->response_type = NAN_RESPONSE_BEACON_SDF_PAYLOAD;
break;
}
#endif /* NAN_2_0 */
default:
return -1;
}
return 0;
}
int NanCommand::handleNanResponse()
{
//parse the data and call
//the response callback handler with the populated
//NanResponseMsg
NanResponseMsg rsp_data;
int ret;
ALOGV("handleNanResponse called %p", this);
memset(&rsp_data, 0, sizeof(rsp_data));
//get the rsp_data
ret = getNanResponse(&rsp_data);
ALOGI("handleNanResponse ret:%d status:%u value:%u response_type:%u",
ret, rsp_data.status, rsp_data.value, rsp_data.response_type);
if (ret == 0 && (rsp_data.response_type == NAN_RESPONSE_STATS) &&
(mStaParam != NULL) &&
(rsp_data.body.stats_response.stats_id == NAN_STATS_ID_DE_TIMING_SYNC)) {
/*
Fill the staParam with appropriate values and return from here.
No need to call NotifyResponse as the request is for getting the
STA response
*/
NanSyncStats *pSyncStats = &rsp_data.body.stats_response.data.sync_stats;
mStaParam->master_rank = pSyncStats->myRank;
mStaParam->master_pref = (pSyncStats->myRank & 0xFF00000000000000) >> 56;
mStaParam->random_factor = (pSyncStats->myRank & 0x00FF000000000000) >> 48;
mStaParam->hop_count = pSyncStats->currAmHopCount;
mStaParam->beacon_transmit_time = pSyncStats->currAmBTT;
return ret;
}
//Call the NotifyResponse Handler
if (ret == 0 && mHandler.NotifyResponse) {
(*mHandler.NotifyResponse)(&rsp_data, mUserData);
}
return ret;
}