diff --git a/examples/platform/linux/CommissionerMain.cpp b/examples/platform/linux/CommissionerMain.cpp index f30e92269bd251..afa4f800fa1b0e 100644 --- a/examples/platform/linux/CommissionerMain.cpp +++ b/examples/platform/linux/CommissionerMain.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -132,6 +133,10 @@ CHIP_ERROR InitCommissioner(uint16_t commissionerPort, uint16_t udcListenPort) factoryParams.groupDataProvider = &gGroupDataProvider; params.operationalCredentialsDelegate = &gOpCredsIssuer; + uint16_t vendorId; + DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(vendorId); + ChipLogProgress(Support, " ----- Commissioner using vendorId 0x%04X", vendorId); + params.controllerVendorId = static_cast(vendorId); ReturnErrorOnFailure(gOpCredsIssuer.Initialize(gServerStorage)); diff --git a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp index 1d15233ab165f1..6dc80c5b164f5a 100644 --- a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp +++ b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.cpp @@ -100,3 +100,15 @@ uint32_t AppContentLauncherManager::HandleGetSupportedStreamingProtocols() ChipLogProgress(Zcl, "AppContentLauncherManager::HandleGetSupportedStreamingProtocols"); return mSupportedStreamingProtocols; } + +uint32_t AppContentLauncherManager::GetFeatureMap(chip::EndpointId endpoint) +{ + if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT) + { + return mDynamicEndpointFeatureMap; + } + + uint32_t featureMap = 0; + Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} diff --git a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.h b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.h index af0b987fbd9bfd..b5b8f7a533c4e2 100644 --- a/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.h +++ b/examples/tv-app/android/include/content-launcher/AppContentLauncherManager.h @@ -19,6 +19,7 @@ #pragma once #include "../../java/ContentAppCommandDelegate.h" +#include #include using chip::CharSpan; @@ -47,6 +48,8 @@ class AppContentLauncherManager : public ContentLauncherDelegate void SetEndpointId(EndpointId epId) { mEndpointId = epId; }; + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + protected: std::list mAcceptHeaderList; uint32_t mSupportedStreamingProtocols; @@ -54,4 +57,7 @@ class AppContentLauncherManager : public ContentLauncherDelegate private: EndpointId mEndpointId; ContentAppCommandDelegate mCommandDelegate; + + // TODO: set this based upon meta data from app + uint32_t mDynamicEndpointFeatureMap = 3; }; diff --git a/examples/tv-app/android/java/AppImpl.cpp b/examples/tv-app/android/java/AppImpl.cpp index a0564d2efc3832..063a2be2528354 100644 --- a/examples/tv-app/android/java/AppImpl.cpp +++ b/examples/tv-app/android/java/AppImpl.cpp @@ -113,6 +113,12 @@ static const int kDescriptorAttributeArraySize = 254; // CONTENT APP ENDPOINT: contains the following clusters: // - Descriptor // - Application Basic +// - Keypad Input +// - Application Launcher +// - Account Login +// - Content Launcher +// - Target Navigator +// - Channel // Declare Descriptor cluster attributes DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(descriptorAttrs) @@ -123,23 +129,27 @@ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_DEVICE_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttrib DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Application Basic information cluster attributes -// TODO: add missing attributes once schema is updated DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(applicationBasicAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VENDOR_NAME_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* VendorName */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VENDOR_ID_ATTRIBUTE_ID, INT16U, 1, 0), /* VendorID */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_NAME_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* ApplicationName */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_PRODUCT_ID_ATTRIBUTE_ID, INT16U, 1, 0), /* ProductID */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_STATUS_ATTRIBUTE_ID, INT8U, 1, 0), /* ApplicationStatus */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VERSION_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* ApplicationVersion */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_ALLOWED_VENDOR_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, + 0), /* AllowedVendorList */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Keypad Input cluster attributes DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(keypadInputAttrs) -DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); +DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ + DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Application Launcher cluster attributes -// TODO: add missing attributes once schema is updated +// NOTE: Does not make sense for content app to be able to set the AP feature flag DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(applicationLauncherAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_LAUNCHER_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* catalog list */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_LAUNCHER_CURRENT_APP_ATTRIBUTE_ID, STRUCT, 1, 0), /* current app */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Account Login cluster attributes @@ -151,18 +161,20 @@ DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(contentLauncherAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CONTENT_LAUNCHER_ACCEPT_HEADER_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* accept header list */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CONTENT_LAUNCHER_SUPPORTED_STREAMING_PROTOCOLS_ATTRIBUTE_ID, BITMAP32, 1, - 0), /* streaming protocols */ + 0), /* streaming protocols */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Media Playback cluster attributes -// TODO: add missing attributes once schema is updated DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(mediaPlaybackAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_STATE_ATTRIBUTE_ID, ENUM8, 1, 0), /* current state */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_START_TIME_ATTRIBUTE_ID, EPOCH_US, 1, 0), /* start time */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_DURATION_ATTRIBUTE_ID, INT64U, 1, 0), /* duration */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_POSITION_ATTRIBUTE_ID, STRUCT, 1, 0), /* playback speed */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SPEED_ATTRIBUTE_ID, SINGLE, 1, 0), /* playback speed */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SEEK_RANGE_END_ATTRIBUTE_ID, INT64U, 1, 0), /* seek range end */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SEEK_RANGE_START_ATTRIBUTE_ID, INT64U, 1, 0), /* seek range start */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Target Navigator cluster attributes @@ -176,6 +188,7 @@ DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(channelAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* channel list */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_LINEUP_ATTRIBUTE_ID, STRUCT, 1, 0), /* lineup */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_CURRENT_CHANNEL_ATTRIBUTE_ID, STRUCT, 1, 0), /* current channel */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); constexpr CommandId keypadInputIncomingCommands[] = { diff --git a/examples/tv-app/android/java/ChannelManager.cpp b/examples/tv-app/android/java/ChannelManager.cpp index e8231b38db86b0..fb8a4d8d2ab558 100644 --- a/examples/tv-app/android/java/ChannelManager.cpp +++ b/examples/tv-app/android/java/ChannelManager.cpp @@ -17,6 +17,7 @@ #include "ChannelManager.h" #include "TvApp-JNI.h" +#include #include #include #include @@ -407,3 +408,15 @@ void ChannelManager::InitializeWithObjects(jobject managerObject) env->ExceptionClear(); } } + +uint32_t ChannelManager::GetFeatureMap(chip::EndpointId endpoint) +{ + if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT) + { + return mDynamicEndpointFeatureMap; + } + + uint32_t featureMap = 0; + Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} diff --git a/examples/tv-app/android/java/ChannelManager.h b/examples/tv-app/android/java/ChannelManager.h index e7fb8e3411b7f8..0439900f7c37f2 100644 --- a/examples/tv-app/android/java/ChannelManager.h +++ b/examples/tv-app/android/java/ChannelManager.h @@ -40,6 +40,8 @@ class ChannelManager : public ChannelDelegate bool HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber) override; bool HandleSkipChannel(const uint16_t & count) override; + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + private: jobject mChannelManagerObject = nullptr; jmethodID mGetChannelListMethod = nullptr; @@ -49,4 +51,7 @@ class ChannelManager : public ChannelDelegate jmethodID mChangeChannelMethod = nullptr; jmethodID mChangeChannelByNumberMethod = nullptr; jmethodID mSkipChannelMethod = nullptr; + + // TODO: set this based upon meta data from app + uint32_t mDynamicEndpointFeatureMap = 3; }; diff --git a/examples/tv-app/android/java/ContentLauncherManager.cpp b/examples/tv-app/android/java/ContentLauncherManager.cpp index 3b2be958a0686d..81fa61bb168c58 100644 --- a/examples/tv-app/android/java/ContentLauncherManager.cpp +++ b/examples/tv-app/android/java/ContentLauncherManager.cpp @@ -18,6 +18,7 @@ #include "ContentLauncherManager.h" #include "TvApp-JNI.h" +#include #include #include #include @@ -272,3 +273,10 @@ void ContentLauncherManager::InitializeWithObjects(jobject managerObject) env->ExceptionClear(); } } + +uint32_t ContentLauncherManager::GetFeatureMap(chip::EndpointId endpoint) +{ + uint32_t featureMap = 0; + Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} diff --git a/examples/tv-app/android/java/ContentLauncherManager.h b/examples/tv-app/android/java/ContentLauncherManager.h index a034afddf86fce..79a35de13a534a 100644 --- a/examples/tv-app/android/java/ContentLauncherManager.h +++ b/examples/tv-app/android/java/ContentLauncherManager.h @@ -47,6 +47,8 @@ class ContentLauncherManager : public ContentLauncherDelegate CHIP_ERROR HandleGetAcceptHeaderList(AttributeValueEncoder & aEncoder) override; uint32_t HandleGetSupportedStreamingProtocols() override; + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + private: jobject mContentLauncherManagerObject = nullptr; jmethodID mGetAcceptHeaderMethod = nullptr; diff --git a/examples/tv-app/android/java/KeypadInputManager.cpp b/examples/tv-app/android/java/KeypadInputManager.cpp index f8c19a136c2609..e4cfdada55413d 100644 --- a/examples/tv-app/android/java/KeypadInputManager.cpp +++ b/examples/tv-app/android/java/KeypadInputManager.cpp @@ -18,6 +18,7 @@ #include "KeypadInputManager.h" #include "TvApp-JNI.h" +#include #include #include #include @@ -86,3 +87,15 @@ void KeypadInputManager::InitializeWithObjects(jobject managerObject) env->ExceptionClear(); } } + +uint32_t KeypadInputManager::GetFeatureMap(chip::EndpointId endpoint) +{ + if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT) + { + return mDynamicEndpointFeatureMap; + } + + uint32_t featureMap = 0; + Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} diff --git a/examples/tv-app/android/java/KeypadInputManager.h b/examples/tv-app/android/java/KeypadInputManager.h index 416c878699b70c..8c43cc043d67ec 100644 --- a/examples/tv-app/android/java/KeypadInputManager.h +++ b/examples/tv-app/android/java/KeypadInputManager.h @@ -34,7 +34,12 @@ class KeypadInputManager : public KeypadInputDelegate void HandleSendKey(CommandResponseHelper & helper, const chip::app::Clusters::KeypadInput::CecKeyCode & keyCode) override; + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + private: jobject mKeypadInputManagerObject = nullptr; jmethodID mSendKeyMethod = nullptr; + + // TODO: set this based upon meta data from app + uint32_t mDynamicEndpointFeatureMap = 7; }; diff --git a/examples/tv-app/android/java/MediaPlaybackManager.cpp b/examples/tv-app/android/java/MediaPlaybackManager.cpp index 85d2e60671e0b3..0bc9244b7b3d50 100644 --- a/examples/tv-app/android/java/MediaPlaybackManager.cpp +++ b/examples/tv-app/android/java/MediaPlaybackManager.cpp @@ -17,6 +17,7 @@ #include "MediaPlaybackManager.h" #include "TvApp-JNI.h" +#include #include #include #include @@ -298,3 +299,15 @@ CHIP_ERROR MediaPlaybackManager::HandleGetSampledPosition(AttributeValueEncoder return aEncoder.Encode(response); } + +uint32_t MediaPlaybackManager::GetFeatureMap(chip::EndpointId endpoint) +{ + if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT) + { + return mDynamicEndpointFeatureMap; + } + + uint32_t featureMap = 0; + Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} diff --git a/examples/tv-app/android/java/MediaPlaybackManager.h b/examples/tv-app/android/java/MediaPlaybackManager.h index 74f28126447136..822fcf55fafd55 100644 --- a/examples/tv-app/android/java/MediaPlaybackManager.h +++ b/examples/tv-app/android/java/MediaPlaybackManager.h @@ -81,6 +81,8 @@ class MediaPlaybackManager : public MediaPlaybackDelegate void HandleNext(CommandResponseHelper & helper) override; void HandleStartOver(CommandResponseHelper & helper) override; + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + private: jobject mMediaPlaybackManagerObject = nullptr; jmethodID mRequestMethod = nullptr; @@ -90,4 +92,7 @@ class MediaPlaybackManager : public MediaPlaybackDelegate uint64_t HandleMediaRequestGetAttribute(MediaPlaybackRequestAttribute attribute); chip::app::Clusters::MediaPlayback::Commands::PlaybackResponse::Type HandleMediaRequest(MediaPlaybackRequest mediaPlaybackRequest, uint64_t deltaPositionMilliseconds); + + // TODO: set this based upon meta data from app + uint32_t mDynamicEndpointFeatureMap = 3; }; diff --git a/examples/tv-app/linux/AppImpl.cpp b/examples/tv-app/linux/AppImpl.cpp index 2cc16ac69b8ad0..06c98290e8a5a9 100644 --- a/examples/tv-app/linux/AppImpl.cpp +++ b/examples/tv-app/linux/AppImpl.cpp @@ -22,6 +22,7 @@ #include "AppImpl.h" #include +#include #include #include #include @@ -138,6 +139,12 @@ static const int kDescriptorAttributeArraySize = 254; // CONTENT APP ENDPOINT: contains the following clusters: // - Descriptor // - Application Basic +// - Keypad Input +// - Application Launcher +// - Account Login +// - Content Launcher +// - Target Navigator +// - Channel // Declare Descriptor cluster attributes DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(descriptorAttrs) @@ -148,23 +155,27 @@ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_DEVICE_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttrib DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Application Basic information cluster attributes -// TODO: add missing attributes once schema is updated DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(applicationBasicAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VENDOR_NAME_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* VendorName */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VENDOR_ID_ATTRIBUTE_ID, INT16U, 1, 0), /* VendorID */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_NAME_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* ApplicationName */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_PRODUCT_ID_ATTRIBUTE_ID, INT16U, 1, 0), /* ProductID */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_STATUS_ATTRIBUTE_ID, INT8U, 1, 0), /* ApplicationStatus */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_VERSION_ATTRIBUTE_ID, CHAR_STRING, kNameSize, 0), /* ApplicationVersion */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_ALLOWED_VENDOR_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, + 0), /* AllowedVendorList */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Keypad Input cluster attributes DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(keypadInputAttrs) -DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); +DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ + DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Application Launcher cluster attributes -// TODO: add missing attributes once schema is updated +// NOTE: Does not make sense for content app to be able to set the AP feature flag DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(applicationLauncherAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_LAUNCHER_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* catalog list */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_APPLICATION_LAUNCHER_CURRENT_APP_ATTRIBUTE_ID, STRUCT, 1, 0), /* current app */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Account Login cluster attributes @@ -176,18 +187,20 @@ DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(contentLauncherAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CONTENT_LAUNCHER_ACCEPT_HEADER_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* accept header list */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CONTENT_LAUNCHER_SUPPORTED_STREAMING_PROTOCOLS_ATTRIBUTE_ID, BITMAP32, 1, - 0), /* streaming protocols */ + 0), /* streaming protocols */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Media Playback cluster attributes -// TODO: add missing attributes once schema is updated DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(mediaPlaybackAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_STATE_ATTRIBUTE_ID, ENUM8, 1, 0), /* current state */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_START_TIME_ATTRIBUTE_ID, EPOCH_US, 1, 0), /* start time */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_DURATION_ATTRIBUTE_ID, INT64U, 1, 0), /* duration */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_POSITION_ATTRIBUTE_ID, STRUCT, 1, 0), /* playback speed */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SPEED_ATTRIBUTE_ID, SINGLE, 1, 0), /* playback speed */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SEEK_RANGE_END_ATTRIBUTE_ID, INT64U, 1, 0), /* seek range end */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_MEDIA_PLAYBACK_PLAYBACK_SEEK_RANGE_START_ATTRIBUTE_ID, INT64U, 1, 0), /* seek range start */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); // Declare Target Navigator cluster attributes @@ -201,6 +214,7 @@ DECLARE_DYNAMIC_ATTRIBUTE_LIST_BEGIN(channelAttrs) DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_LIST_ATTRIBUTE_ID, ARRAY, kDescriptorAttributeArraySize, 0), /* channel list */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_LINEUP_ATTRIBUTE_ID, STRUCT, 1, 0), /* lineup */ DECLARE_DYNAMIC_ATTRIBUTE(ZCL_CHANNEL_CURRENT_CHANNEL_ATTRIBUTE_ID, STRUCT, 1, 0), /* current channel */ + DECLARE_DYNAMIC_ATTRIBUTE(ZCL_FEATURE_MAP_SERVER_ATTRIBUTE_ID, BITMAP32, 4, 0), /* FeatureMap */ DECLARE_DYNAMIC_ATTRIBUTE_LIST_END(); constexpr CommandId keypadInputIncomingCommands[] = { diff --git a/examples/tv-app/linux/include/channel/ChannelManager.cpp b/examples/tv-app/linux/include/channel/ChannelManager.cpp index 4e070258b00543..53c83a287b3294 100644 --- a/examples/tv-app/linux/include/channel/ChannelManager.cpp +++ b/examples/tv-app/linux/include/channel/ChannelManager.cpp @@ -16,6 +16,7 @@ */ #include "ChannelManager.h" +#include #include using namespace chip; @@ -172,3 +173,15 @@ bool ChannelManager::HandleSkipChannel(const uint16_t & count) mCurrentChannel = mChannels[mCurrentChannelIndex]; return true; } + +uint32_t ChannelManager::GetFeatureMap(chip::EndpointId endpoint) +{ + if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT) + { + return mDynamicEndpointFeatureMap; + } + + uint32_t featureMap = 0; + Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} diff --git a/examples/tv-app/linux/include/channel/ChannelManager.h b/examples/tv-app/linux/include/channel/ChannelManager.h index 7ea0cf7423b335..e56681e4810a65 100644 --- a/examples/tv-app/linux/include/channel/ChannelManager.h +++ b/examples/tv-app/linux/include/channel/ChannelManager.h @@ -41,8 +41,14 @@ class ChannelManager : public ChannelDelegate bool HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber) override; bool HandleSkipChannel(const uint16_t & count) override; + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + protected: uint16_t mCurrentChannelIndex; ChannelInfoType mCurrentChannel; std::vector mChannels; + +private: + // TODO: set this based upon meta data from app + uint32_t mDynamicEndpointFeatureMap = 3; }; diff --git a/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.cpp b/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.cpp index a56323156587ed..ceb37ec3b2cdd3 100644 --- a/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.cpp +++ b/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.cpp @@ -17,6 +17,7 @@ */ #include "ContentLauncherManager.h" +#include using namespace std; using namespace chip::app; @@ -186,3 +187,15 @@ uint32_t ContentLauncherManager::HandleGetSupportedStreamingProtocols() ChipLogProgress(Zcl, "ContentLauncherManager::HandleGetSupportedStreamingProtocols"); return mSupportedStreamingProtocols; } + +uint32_t ContentLauncherManager::GetFeatureMap(chip::EndpointId endpoint) +{ + if (endpoint >= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT) + { + return mDynamicEndpointFeatureMap; + } + + uint32_t featureMap = 0; + Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} diff --git a/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.h b/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.h index 6033ac68275737..7073d89dd05c9e 100644 --- a/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.h +++ b/examples/tv-app/linux/include/content-launcher/ContentLauncherManager.h @@ -51,6 +51,8 @@ class ContentLauncherManager : public ContentLauncherDelegate CHIP_ERROR HandleGetAcceptHeaderList(AttributeValueEncoder & aEncoder) override; uint32_t HandleGetSupportedStreamingProtocols() override; + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + protected: std::list mAcceptHeaderList; uint32_t mSupportedStreamingProtocols; @@ -58,4 +60,6 @@ class ContentLauncherManager : public ContentLauncherDelegate private: EndpointId mEndpointId; + // TODO: set this based upon meta data from app + uint32_t mDynamicEndpointFeatureMap = 3; }; diff --git a/examples/tv-app/linux/include/keypad-input/KeypadInputManager.cpp b/examples/tv-app/linux/include/keypad-input/KeypadInputManager.cpp index 7f30c648ee6361..84bae2833554e4 100644 --- a/examples/tv-app/linux/include/keypad-input/KeypadInputManager.cpp +++ b/examples/tv-app/linux/include/keypad-input/KeypadInputManager.cpp @@ -17,6 +17,7 @@ */ #include "KeypadInputManager.h" +#include using namespace chip; using namespace chip::app::Clusters::KeypadInput; @@ -94,3 +95,15 @@ void KeypadInputManager::HandleSendKey(CommandResponseHelper= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT) + { + return mDynamicEndpointFeatureMap; + } + + uint32_t featureMap = 0; + Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} diff --git a/examples/tv-app/linux/include/keypad-input/KeypadInputManager.h b/examples/tv-app/linux/include/keypad-input/KeypadInputManager.h index 6936c694fa511a..79a83b3e65017f 100644 --- a/examples/tv-app/linux/include/keypad-input/KeypadInputManager.h +++ b/examples/tv-app/linux/include/keypad-input/KeypadInputManager.h @@ -29,4 +29,10 @@ class KeypadInputManager : public KeypadInputDelegate { public: void HandleSendKey(CommandResponseHelper & helper, const CecKeyCodeType & keyCode) override; + + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + +private: + // TODO: set this based upon meta data from app + uint32_t mDynamicEndpointFeatureMap = 7; }; diff --git a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp index 9e26f9af2bfa29..d080b9e395ab13 100644 --- a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp +++ b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.cpp @@ -16,6 +16,7 @@ */ #include "MediaPlaybackManager.h" +#include using namespace std; using namespace chip::app::DataModel; @@ -236,3 +237,15 @@ void MediaPlaybackManager::HandleStartOver(CommandResponseHelper= EMBER_AF_CONTENT_LAUNCH_CLUSTER_SERVER_ENDPOINT_COUNT) + { + return mDynamicEndpointFeatureMap; + } + + uint32_t featureMap = 0; + Attributes::FeatureMap::Get(endpoint, &featureMap); + return featureMap; +} diff --git a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h index 1c35764e666e74..ec02313fe9442a 100644 --- a/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h +++ b/examples/tv-app/linux/include/media-playback/MediaPlaybackManager.h @@ -51,6 +51,8 @@ class MediaPlaybackManager : public MediaPlaybackDelegate void HandleNext(CommandResponseHelper & helper) override; void HandleStartOver(CommandResponseHelper & helper) override; + uint32_t GetFeatureMap(chip::EndpointId endpoint) override; + protected: // NOTE: it does not make sense to have default state of playing with a speed of 0, but // the CI test cases expect these values, and need to be fixed. @@ -64,4 +66,8 @@ class MediaPlaybackManager : public MediaPlaybackDelegate static const int kPlaybackMaxForwardSpeed = 10; static const int kPlaybackMaxRewindSpeed = -10; + +private: + // TODO: set this based upon meta data from app + uint32_t mDynamicEndpointFeatureMap = 3; }; diff --git a/src/app/clusters/channel-server/channel-delegate.h b/src/app/clusters/channel-server/channel-delegate.h index 4845858cc490a3..60f5aba15af1c3 100644 --- a/src/app/clusters/channel-server/channel-delegate.h +++ b/src/app/clusters/channel-server/channel-delegate.h @@ -44,6 +44,9 @@ class Delegate virtual bool HandleChangeChannelByNumber(const uint16_t & majorNumber, const uint16_t & minorNumber) = 0; virtual bool HandleSkipChannel(const uint16_t & count) = 0; + bool HasFeature(chip::EndpointId endpoint, ChannelFeature feature); + virtual uint32_t GetFeatureMap(chip::EndpointId endpoint) = 0; + virtual ~Delegate() = default; }; diff --git a/src/app/clusters/channel-server/channel-server.cpp b/src/app/clusters/channel-server/channel-server.cpp index fab495dac4db33..453b01939e2b8d 100644 --- a/src/app/clusters/channel-server/channel-server.cpp +++ b/src/app/clusters/channel-server/channel-server.cpp @@ -115,18 +115,10 @@ void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate) } } -bool HasFeature(chip::EndpointId endpoint, ChannelFeature feature) +bool Delegate::HasFeature(chip::EndpointId endpoint, ChannelFeature feature) { - bool hasFeature = false; - uint32_t featureMap = 0; - - EmberAfStatus status = Attributes::FeatureMap::Get(endpoint, &featureMap); - if (EMBER_ZCL_STATUS_SUCCESS == status) - { - hasFeature = (featureMap & chip::to_underlying(feature)); - } - - return hasFeature; + uint32_t featureMap = GetFeatureMap(endpoint); + return (featureMap & chip::to_underlying(feature)); } } // namespace Channel @@ -150,6 +142,7 @@ class ChannelAttrAccess : public app::AttributeAccessInterface CHIP_ERROR ReadChannelListAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate); CHIP_ERROR ReadLineupAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate); CHIP_ERROR ReadCurrentChannelAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate); + CHIP_ERROR ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, Delegate * delegate); }; ChannelAttrAccess gChannelAttrAccess; @@ -162,7 +155,7 @@ CHIP_ERROR ChannelAttrAccess::Read(const app::ConcreteReadAttributePath & aPath, switch (aPath.mAttributeId) { case app::Clusters::Channel::Attributes::ChannelList::Id: { - if (isDelegateNull(delegate, endpoint) || !HasFeature(endpoint, ChannelFeature::kChannelList)) + if (isDelegateNull(delegate, endpoint) || !delegate->HasFeature(endpoint, ChannelFeature::kChannelList)) { return aEncoder.EncodeEmptyList(); } @@ -170,7 +163,7 @@ CHIP_ERROR ChannelAttrAccess::Read(const app::ConcreteReadAttributePath & aPath, return ReadChannelListAttribute(aEncoder, delegate); } case app::Clusters::Channel::Attributes::Lineup::Id: { - if (isDelegateNull(delegate, endpoint) || !HasFeature(endpoint, ChannelFeature::kLineupInfo)) + if (isDelegateNull(delegate, endpoint) || !delegate->HasFeature(endpoint, ChannelFeature::kLineupInfo)) { return CHIP_NO_ERROR; } @@ -185,6 +178,14 @@ CHIP_ERROR ChannelAttrAccess::Read(const app::ConcreteReadAttributePath & aPath, return ReadCurrentChannelAttribute(aEncoder, delegate); } + case app::Clusters::Channel::Attributes::FeatureMap::Id: { + if (isDelegateNull(delegate, endpoint)) + { + return CHIP_NO_ERROR; + } + + return ReadFeatureFlagAttribute(endpoint, aEncoder, delegate); + } default: { break; } @@ -193,6 +194,13 @@ CHIP_ERROR ChannelAttrAccess::Read(const app::ConcreteReadAttributePath & aPath, return CHIP_NO_ERROR; } +CHIP_ERROR ChannelAttrAccess::ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, + Delegate * delegate) +{ + uint32_t featureFlag = delegate->GetFeatureMap(endpoint); + return aEncoder.Encode(featureFlag); +} + CHIP_ERROR ChannelAttrAccess::ReadChannelListAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate) { return delegate->HandleGetChannelList(aEncoder); diff --git a/src/app/clusters/content-launch-server/content-launch-delegate.h b/src/app/clusters/content-launch-server/content-launch-delegate.h index 5fb6e02e5450e3..0c0f65d22675d7 100644 --- a/src/app/clusters/content-launch-server/content-launch-delegate.h +++ b/src/app/clusters/content-launch-server/content-launch-delegate.h @@ -51,6 +51,9 @@ class Delegate virtual uint32_t HandleGetSupportedStreamingProtocols() = 0; + bool HasFeature(chip::EndpointId endpoint, ContentLauncherFeature feature); + virtual uint32_t GetFeatureMap(chip::EndpointId endpoint) = 0; + virtual ~Delegate() = default; }; diff --git a/src/app/clusters/content-launch-server/content-launch-server.cpp b/src/app/clusters/content-launch-server/content-launch-server.cpp index 77224806dfda04..3cbeea158d7ee3 100644 --- a/src/app/clusters/content-launch-server/content-launch-server.cpp +++ b/src/app/clusters/content-launch-server/content-launch-server.cpp @@ -120,18 +120,10 @@ void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate) } } -bool HasFeature(chip::EndpointId endpoint, ContentLauncherFeature feature) +bool Delegate::HasFeature(chip::EndpointId endpoint, ContentLauncherFeature feature) { - bool hasFeature = false; - uint32_t featureMap = 0; - - EmberAfStatus status = Attributes::FeatureMap::Get(endpoint, &featureMap); - if (EMBER_ZCL_STATUS_SUCCESS == status) - { - hasFeature = (featureMap & chip::to_underlying(feature)); - } - - return hasFeature; + uint32_t featureMap = GetFeatureMap(endpoint); + return (featureMap & chip::to_underlying(feature)); } } // namespace ContentLauncher @@ -154,6 +146,7 @@ class ContentLauncherAttrAccess : public app::AttributeAccessInterface private: CHIP_ERROR ReadAcceptHeaderAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate); CHIP_ERROR ReadSupportedStreamingProtocolsAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate); + CHIP_ERROR ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, Delegate * delegate); }; ContentLauncherAttrAccess gContentLauncherAttrAccess; @@ -181,6 +174,14 @@ CHIP_ERROR ContentLauncherAttrAccess::Read(const app::ConcreteReadAttributePath return ReadSupportedStreamingProtocolsAttribute(aEncoder, delegate); } + case app::Clusters::ContentLauncher::Attributes::FeatureMap::Id: { + if (isDelegateNull(delegate, endpoint)) + { + return CHIP_NO_ERROR; + } + + return ReadFeatureFlagAttribute(endpoint, aEncoder, delegate); + } default: { break; } @@ -189,6 +190,13 @@ CHIP_ERROR ContentLauncherAttrAccess::Read(const app::ConcreteReadAttributePath return CHIP_NO_ERROR; } +CHIP_ERROR ContentLauncherAttrAccess::ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, + Delegate * delegate) +{ + uint32_t featureFlag = delegate->GetFeatureMap(endpoint); + return aEncoder.Encode(featureFlag); +} + CHIP_ERROR ContentLauncherAttrAccess::ReadAcceptHeaderAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate) { return delegate->HandleGetAcceptHeaderList(aEncoder); @@ -220,7 +228,8 @@ bool emberAfContentLauncherClusterLaunchContentCallback(CommandHandler * command Delegate * delegate = GetDelegate(endpoint); - VerifyOrExit(isDelegateNull(delegate, endpoint) != true && HasFeature(endpoint, ContentLauncherFeature::kContentSearch), + VerifyOrExit(isDelegateNull(delegate, endpoint) != true && + delegate->HasFeature(endpoint, ContentLauncherFeature::kContentSearch), err = CHIP_ERROR_INCORRECT_STATE); delegate->HandleLaunchContent(responder, decodableParameterList, autoplay, data.HasValue() ? data.Value() : CharSpan()); @@ -253,7 +262,7 @@ bool emberAfContentLauncherClusterLaunchURLCallback(CommandHandler * commandObj, app::CommandResponseHelper responder(commandObj, commandPath); Delegate * delegate = GetDelegate(endpoint); - VerifyOrExit(isDelegateNull(delegate, endpoint) != true && HasFeature(endpoint, ContentLauncherFeature::kURLPlayback), + VerifyOrExit(isDelegateNull(delegate, endpoint) != true && delegate->HasFeature(endpoint, ContentLauncherFeature::kURLPlayback), err = CHIP_ERROR_INCORRECT_STATE); { delegate->HandleLaunchUrl(responder, contentUrl, displayString.HasValue() ? displayString.Value() : CharSpan(), diff --git a/src/app/clusters/keypad-input-server/keypad-input-delegate.h b/src/app/clusters/keypad-input-server/keypad-input-delegate.h index 24fd57573eff0a..65e217bb1a84c9 100644 --- a/src/app/clusters/keypad-input-server/keypad-input-delegate.h +++ b/src/app/clusters/keypad-input-server/keypad-input-delegate.h @@ -36,6 +36,10 @@ class Delegate public: virtual void HandleSendKey(CommandResponseHelper & helper, const CecKeyCode & keyCode) = 0; + bool HasFeature(chip::EndpointId endpoint, KeypadInputFeature feature); + + virtual uint32_t GetFeatureMap(chip::EndpointId endpoint) = 0; + virtual ~Delegate() = default; }; diff --git a/src/app/clusters/keypad-input-server/keypad-input-server.cpp b/src/app/clusters/keypad-input-server/keypad-input-server.cpp index 1389caa20c1326..2dce476b1766c5 100644 --- a/src/app/clusters/keypad-input-server/keypad-input-server.cpp +++ b/src/app/clusters/keypad-input-server/keypad-input-server.cpp @@ -25,12 +25,15 @@ #include #include +#include #include #include #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED #include #endif // CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED #include +#include +#include #include using namespace chip; @@ -97,18 +100,10 @@ void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate) } } -bool HasFeature(chip::EndpointId endpoint, KeypadInputFeature feature) +bool Delegate::HasFeature(chip::EndpointId endpoint, KeypadInputFeature feature) { - bool hasFeature = false; - uint32_t featureMap = 0; - - EmberAfStatus status = Attributes::FeatureMap::Get(endpoint, &featureMap); - if (EMBER_ZCL_STATUS_SUCCESS == status) - { - hasFeature = (featureMap & chip::to_underlying(feature)); - } - - return hasFeature; + uint32_t featureMap = GetFeatureMap(endpoint); + return (featureMap & chip::to_underlying(feature)); } } // namespace KeypadInput @@ -116,6 +111,57 @@ bool HasFeature(chip::EndpointId endpoint, KeypadInputFeature feature) } // namespace app } // namespace chip +// ----------------------------------------------------------------------------- +// Attribute Accessor Implementation + +namespace { + +class KeypadInputAttrAccess : public app::AttributeAccessInterface +{ +public: + KeypadInputAttrAccess() : app::AttributeAccessInterface(Optional::Missing(), KeypadInput::Id) {} + + CHIP_ERROR Read(const app::ConcreteReadAttributePath & aPath, app::AttributeValueEncoder & aEncoder) override; + +private: + CHIP_ERROR ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, Delegate * delegate); +}; + +KeypadInputAttrAccess gKeypadInputAttrAccess; + +CHIP_ERROR KeypadInputAttrAccess::Read(const app::ConcreteReadAttributePath & aPath, app::AttributeValueEncoder & aEncoder) +{ + EndpointId endpoint = aPath.mEndpointId; + Delegate * delegate = GetDelegate(endpoint); + + if (isDelegateNull(delegate, endpoint)) + { + return CHIP_NO_ERROR; + } + + switch (aPath.mAttributeId) + { + case app::Clusters::KeypadInput::Attributes::FeatureMap::Id: { + return ReadFeatureFlagAttribute(endpoint, aEncoder, delegate); + } + + default: { + break; + } + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR KeypadInputAttrAccess::ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, + Delegate * delegate) +{ + uint32_t featureFlag = delegate->GetFeatureMap(endpoint); + return aEncoder.Encode(featureFlag); +} + +} // anonymous namespace + // ----------------------------------------------------------------------------- // Matter Framework Callbacks Implementation @@ -142,4 +188,7 @@ bool emberAfKeypadInputClusterSendKeyCallback(app::CommandHandler * command, con return true; } -void MatterKeypadInputPluginServerInitCallback() {} +void MatterKeypadInputPluginServerInitCallback() +{ + registerAttributeAccessOverride(&gKeypadInputAttrAccess); +} diff --git a/src/app/clusters/media-playback-server/media-playback-delegate.h b/src/app/clusters/media-playback-server/media-playback-delegate.h index b5e64d3a6479c2..64b85b85480318 100644 --- a/src/app/clusters/media-playback-server/media-playback-delegate.h +++ b/src/app/clusters/media-playback-server/media-playback-delegate.h @@ -59,6 +59,8 @@ class Delegate virtual void HandleNext(CommandResponseHelper & helper) = 0; virtual void HandleStartOver(CommandResponseHelper & helper) = 0; + virtual uint32_t GetFeatureMap(chip::EndpointId endpoint) = 0; + virtual ~Delegate() = default; }; diff --git a/src/app/clusters/media-playback-server/media-playback-server.cpp b/src/app/clusters/media-playback-server/media-playback-server.cpp index 1c43463736ec36..c4ae274e393ac7 100644 --- a/src/app/clusters/media-playback-server/media-playback-server.cpp +++ b/src/app/clusters/media-playback-server/media-playback-server.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -124,6 +125,7 @@ class MediaPlaybackAttrAccess : public app::AttributeAccessInterface CHIP_ERROR ReadPlaybackSpeedAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate); CHIP_ERROR ReadSeekRangeStartAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate); CHIP_ERROR ReadSeekRangeEndAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate); + CHIP_ERROR ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, Delegate * delegate); }; MediaPlaybackAttrAccess gMediaPlaybackAttrAccess; @@ -161,6 +163,9 @@ CHIP_ERROR MediaPlaybackAttrAccess::Read(const app::ConcreteReadAttributePath & case app::Clusters::MediaPlayback::Attributes::SeekRangeEnd::Id: { return ReadSeekRangeEndAttribute(aEncoder, delegate); } + case app::Clusters::ContentLauncher::Attributes::FeatureMap::Id: { + return ReadFeatureFlagAttribute(endpoint, aEncoder, delegate); + } default: { break; } @@ -169,6 +174,13 @@ CHIP_ERROR MediaPlaybackAttrAccess::Read(const app::ConcreteReadAttributePath & return CHIP_NO_ERROR; } +CHIP_ERROR MediaPlaybackAttrAccess::ReadFeatureFlagAttribute(EndpointId endpoint, app::AttributeValueEncoder & aEncoder, + Delegate * delegate) +{ + uint32_t featureFlag = delegate->GetFeatureMap(endpoint); + return aEncoder.Encode(featureFlag); +} + CHIP_ERROR MediaPlaybackAttrAccess::ReadCurrentStateAttribute(app::AttributeValueEncoder & aEncoder, Delegate * delegate) { MediaPlayback::PlaybackStateEnum currentState = delegate->HandleGetCurrentState();