blob: 9c1bc2b819809c9bffb9bc4cf3c5a557697d963f [file] [log] [blame]
/*
*
* Copyright (c) 2020 Project CHIP Authors
* All rights reserved.
*
* 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.
*/
/**
* @file
* This file contains implementations for the CallbacksMgr class. The object of this
* class will be used by Controller applications to interact with ZCL messages.
* This class provide mechanism to store callbacks for global message dispatching
* across the ZCL stack.
*/
#include "CHIPDeviceCallbacksMgr.h"
#include <core/CHIPCore.h>
#include <inttypes.h>
#include <support/ReturnMacros.h>
namespace {
struct ResponseCallbackInfo
{
chip::NodeId nodeId;
uint8_t sequenceNumber;
bool operator==(ResponseCallbackInfo const & other) { return nodeId == other.nodeId && sequenceNumber == other.sequenceNumber; }
};
struct ReportCallbackInfo
{
chip::NodeId nodeId;
chip::EndpointId endpointId;
chip::ClusterId clusterId;
chip::AttributeId attributeId;
bool operator==(ReportCallbackInfo const & other)
{
return nodeId == other.nodeId && endpointId == other.endpointId && clusterId == other.clusterId &&
attributeId == other.attributeId;
}
};
} // namespace
namespace chip {
namespace app {
CHIP_ERROR CHIPDeviceCallbacksMgr::AddResponseCallback(NodeId nodeId, uint8_t sequenceNumber,
Callback::Cancelable * onSuccessCallback,
Callback::Cancelable * onFailureCallback)
{
VerifyOrReturnError(onSuccessCallback != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(onFailureCallback != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
ResponseCallbackInfo info = { nodeId, sequenceNumber };
memcpy(&onSuccessCallback->mInfoPtr, &info, sizeof(info));
memcpy(&onFailureCallback->mInfoPtr, &info, sizeof(info));
// If some callbacks have already been registered for the same ResponseCallbackInfo, it usually means that the response
// has not been received for a previous command with the same sequenceNumber. Cancel the previously registered callbacks.
CancelCallback(info, mResponsesSuccess);
CancelCallback(info, mResponsesFailure);
mResponsesSuccess.Enqueue(onSuccessCallback);
mResponsesFailure.Enqueue(onFailureCallback);
return CHIP_NO_ERROR;
}
CHIP_ERROR CHIPDeviceCallbacksMgr::GetResponseCallback(NodeId nodeId, uint8_t sequenceNumber,
Callback::Cancelable ** onSuccessCallback,
Callback::Cancelable ** onFailureCallback)
{
ResponseCallbackInfo info = { nodeId, sequenceNumber };
ReturnErrorOnFailure(GetCallback(info, mResponsesSuccess, onSuccessCallback));
(*onSuccessCallback)->Cancel();
ReturnErrorOnFailure(GetCallback(info, mResponsesFailure, onFailureCallback));
(*onFailureCallback)->Cancel();
return CHIP_NO_ERROR;
}
CHIP_ERROR CHIPDeviceCallbacksMgr::AddReportCallback(NodeId nodeId, EndpointId endpointId, ClusterId clusterId,
AttributeId attributeId, Callback::Cancelable * onReportCallback)
{
VerifyOrReturnError(onReportCallback != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
ReportCallbackInfo info = { nodeId, endpointId, clusterId, attributeId };
memmove(&onReportCallback->mInfoPtr, &info, sizeof(info));
// If a callback has already been registered for the same ReportCallbackInfo, let's cancel it.
CancelCallback(info, mReports);
mReports.Enqueue(onReportCallback);
return CHIP_NO_ERROR;
}
CHIP_ERROR CHIPDeviceCallbacksMgr::GetReportCallback(NodeId nodeId, EndpointId endpointId, ClusterId clusterId,
AttributeId attributeId, Callback::Cancelable ** onReportCallback)
{
ReportCallbackInfo info = { nodeId, endpointId, clusterId, attributeId };
ReturnErrorOnFailure(GetCallback(info, mReports, onReportCallback));
return CHIP_NO_ERROR;
}
} // namespace app
} // namespace chip