text: /**
   *
   *    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.
   */
  /****************************************************************************
   * @file
   * @brief Routines for the Content Launch plugin, the
   *server implementation of the Content Launch cluster.
   *******************************************************************************
   ******************************************************************************/
  
  #include <app-common/zap-generated/attributes/Accessors.h>
  #include <app-common/zap-generated/cluster-objects.h>
  #include <app/CommandHandler.h>
  #include <app/ConcreteCommandPath.h>
  #include <app/util/af.h>
  #include <app/util/attribute-storage.h>
  #include <lib/support/Span.h>
  #include <lib/support/logging/CHIPLogging.h>
  #include <platform/CHIPDeviceConfig.h>
  #include <platform/ConfigurationManager.h>
  #include <platform/DeviceControlServer.h>
  
  using namespace chip;
  using namespace chip::app;
  using namespace chip::app::Clusters;
  using namespace chip::app::Clusters::GeneralCommissioning;
  using namespace chip::app::Clusters::GeneralCommissioning::Attributes;
  using namespace chip::DeviceLayer;
  
  namespace {
  
  class GeneralCommissioningAttrAccess : public AttributeAccessInterface
  {
  public:
      // Register for the GeneralCommissioning cluster on all endpoints.
      GeneralCommissioningAttrAccess() : AttributeAccessInterface(Optional<EndpointId>::Missing(), GeneralCommissioning::Id) {}
  
      CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
  
  private:
      CHIP_ERROR ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(uint8_t &), AttributeValueEncoder & aEncoder);
  };
  
  GeneralCommissioningAttrAccess gAttrAccess;
  
  CHIP_ERROR GeneralCommissioningAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
  {
      if (aPath.mClusterId != GeneralCommissioning::Id)
      {
          // We shouldn't have been called at all.
          return CHIP_ERROR_INVALID_ARGUMENT;
      }
  
      switch (aPath.mAttributeId)
      {
      case RegulatoryConfig::Id: {
          return ReadIfSupported(&ConfigurationManager::GetRegulatoryLocation, aEncoder);
      }
      case LocationCapability::Id: {
          return ReadIfSupported(&ConfigurationManager::GetLocationCapability, aEncoder);
      }
      default: {
          break;
      }
      }
      return CHIP_NO_ERROR;
  }
  
  CHIP_ERROR GeneralCommissioningAttrAccess::ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(uint8_t &),
                                                             AttributeValueEncoder & aEncoder)
  {
      uint8_t data;
      CHIP_ERROR err = (DeviceLayer::ConfigurationMgr().*getter)(data);
      if (err == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE)
      {
          data = 0;
      }
      else if (err != CHIP_NO_ERROR)
      {
          return err;
      }
  
      return aEncoder.Encode(data);
  }
  
  } // anonymous namespace
  
  bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler * commandObj,
                                                             const app::ConcreteCommandPath & commandPath,
                                                             const Commands::ArmFailSafe::DecodableType & commandData)
  {
      auto expiryLengthSeconds = System::Clock::Seconds16(commandData.expiryLengthSeconds);
  
      CHIP_ERROR err = DeviceLayer::DeviceControlServer::DeviceControlSvr().ArmFailSafe(expiryLengthSeconds);
      emberAfSendImmediateDefaultResponse(err == CHIP_NO_ERROR ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE);
  
      return true;
  }
  
  bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback(
      app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath,
      const Commands::CommissioningComplete::DecodableType & commandData)
  {
      CHIP_ERROR err = DeviceLayer::DeviceControlServer::DeviceControlSvr().CommissioningComplete();
      emberAfSendImmediateDefaultResponse(err == CHIP_NO_ERROR ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE);
  
      return true;
  }
  
  bool emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(app::CommandHandler * commandObj,
                                                                     const app::ConcreteCommandPath & commandPath,
                                                                     const Commands::SetRegulatoryConfig::DecodableType & commandData)
  {
      auto & location    = commandData.location;
      auto & countryCode = commandData.countryCode;
      auto & breadcrumb  = commandData.breadcrumb;
  
      CHIP_ERROR err = DeviceLayer::DeviceControlServer::DeviceControlSvr().SetRegulatoryConfig(location, countryCode, breadcrumb);
  
      emberAfSendImmediateDefaultResponse(err == CHIP_NO_ERROR ? EMBER_ZCL_STATUS_SUCCESS : EMBER_ZCL_STATUS_FAILURE);
  
      return true;
  }
  
  void MatterGeneralCommissioningPluginServerInitCallback()
  {
      registerAttributeAccessOverride(&gAttrAccess);
  }
  