blob: f1d023b2632137603cefad7e284d190b3538d324 [file] [log] [blame]
/**
*
* Copyright (c) 2021 Project CHIP Authors
*
* 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 <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
#include <app/CommandHandler.h>
#include <app/ConcreteCommandPath.h>
#include <app/util/af.h>
#include <app/util/attribute-storage.h>
#include <lib/core/Optional.h>
#include <platform/DiagnosticDataProvider.h>
using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::EthernetNetworkDiagnostics;
using namespace chip::app::Clusters::EthernetNetworkDiagnostics::Attributes;
using chip::DeviceLayer::DiagnosticDataProvider;
namespace {
class EthernetDiagosticsAttrAccess : public AttributeAccessInterface
{
public:
// Register for the EthernetNetworkDiagnostics cluster on all endpoints.
EthernetDiagosticsAttrAccess() : AttributeAccessInterface(Optional<EndpointId>::Missing(), EthernetNetworkDiagnostics::Id) {}
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
private:
template <typename T>
CHIP_ERROR ReadIfSupported(CHIP_ERROR (DiagnosticDataProvider::*getter)(T &), AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadPHYRate(AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadFullDuplex(AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadCarrierDetect(AttributeValueEncoder & aEncoder);
};
template <typename T>
CHIP_ERROR EthernetDiagosticsAttrAccess::ReadIfSupported(CHIP_ERROR (DiagnosticDataProvider::*getter)(T &),
AttributeValueEncoder & aEncoder)
{
T data;
CHIP_ERROR err = (DeviceLayer::GetDiagnosticDataProvider().*getter)(data);
if (err == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE)
{
data = 0;
}
else if (err != CHIP_NO_ERROR)
{
return err;
}
return aEncoder.Encode(data);
}
CHIP_ERROR EthernetDiagosticsAttrAccess::ReadPHYRate(AttributeValueEncoder & aEncoder)
{
Attributes::PHYRate::TypeInfo::Type pHYRate;
PHYRateType value = EmberAfPHYRateType::EMBER_ZCL_PHY_RATE_TYPE_10_M;
if (DeviceLayer::GetDiagnosticDataProvider().GetEthPHYRate(value) == CHIP_NO_ERROR)
{
pHYRate.SetNonNull(value);
ChipLogProgress(Zcl, "The current nominal, usable speed at the top of the physical layer of the Node: %d", value);
}
else
{
ChipLogProgress(Zcl, "The Ethernet interface is not currently configured or operational");
}
return aEncoder.Encode(pHYRate);
}
CHIP_ERROR EthernetDiagosticsAttrAccess::ReadFullDuplex(AttributeValueEncoder & aEncoder)
{
Attributes::FullDuplex::TypeInfo::Type fullDuplex;
bool value = false;
if (DeviceLayer::GetDiagnosticDataProvider().GetEthFullDuplex(value) == CHIP_NO_ERROR)
{
fullDuplex.SetNonNull(value);
ChipLogProgress(Zcl, "The full-duplex operating status of Node: %d", value);
}
else
{
ChipLogProgress(Zcl, "The Ethernet interface is not currently configured or operational");
}
return aEncoder.Encode(fullDuplex);
}
CHIP_ERROR EthernetDiagosticsAttrAccess::ReadCarrierDetect(AttributeValueEncoder & aEncoder)
{
Attributes::CarrierDetect::TypeInfo::Type carrierDetect;
bool value = false;
if (DeviceLayer::GetDiagnosticDataProvider().GetEthCarrierDetect(value) == CHIP_NO_ERROR)
{
carrierDetect.SetNonNull(value);
ChipLogProgress(Zcl, "The status of the Carrier Detect control signal present on the ethernet network interface: %d",
value);
}
else
{
ChipLogProgress(Zcl, "The Ethernet interface is not currently configured or operational");
}
return aEncoder.Encode(carrierDetect);
}
EthernetDiagosticsAttrAccess gAttrAccess;
CHIP_ERROR EthernetDiagosticsAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
if (aPath.mClusterId != EthernetNetworkDiagnostics::Id)
{
// We shouldn't have been called at all.
return CHIP_ERROR_INVALID_ARGUMENT;
}
switch (aPath.mAttributeId)
{
case PHYRate::Id: {
return ReadPHYRate(aEncoder);
}
case FullDuplex::Id: {
return ReadFullDuplex(aEncoder);
}
case CarrierDetect::Id: {
return ReadCarrierDetect(aEncoder);
}
case TimeSinceReset::Id: {
return ReadIfSupported(&DiagnosticDataProvider::GetEthTimeSinceReset, aEncoder);
}
case PacketRxCount::Id: {
return ReadIfSupported(&DiagnosticDataProvider::GetEthPacketRxCount, aEncoder);
}
case PacketTxCount::Id: {
return ReadIfSupported(&DiagnosticDataProvider::GetEthPacketTxCount, aEncoder);
}
case TxErrCount::Id: {
return ReadIfSupported(&DiagnosticDataProvider::GetEthTxErrCount, aEncoder);
}
case CollisionCount::Id: {
return ReadIfSupported(&DiagnosticDataProvider::GetEthCollisionCount, aEncoder);
}
case OverrunCount::Id: {
return ReadIfSupported(&DiagnosticDataProvider::GetEthOverrunCount, aEncoder);
}
default: {
break;
}
}
return CHIP_NO_ERROR;
}
} // anonymous namespace
bool emberAfEthernetNetworkDiagnosticsClusterResetCountsCallback(app::CommandHandler * commandObj,
const app::ConcreteCommandPath & commandPath,
const Commands::ResetCounts::DecodableType & commandData)
{
DeviceLayer::GetDiagnosticDataProvider().ResetEthNetworkDiagnosticsCounts();
commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::Success);
return true;
}
void MatterEthernetNetworkDiagnosticsPluginServerInitCallback()
{
registerAttributeAccessOverride(&gAttrAccess);
}