Skip to content

Commit

Permalink
Merge branch 'release_2.5-1.4' into bugfix/rs9116-sleep-manager
Browse files Browse the repository at this point in the history
  • Loading branch information
rosahay-silabs authored Dec 11, 2024
2 parents 4739c53 + ce3e2a4 commit 03ca2d7
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 21 deletions.
3 changes: 3 additions & 0 deletions examples/platform/silabs/MatterConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ CHIP_ERROR SilabsMatterConfig::InitMatter(const char * appName)
// Register ReadHandler::ApplicationCallback
app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(
&app::Silabs::ApplicationSleepManager::GetInstance());

// Register ICDStateObserver
chip::Server::GetInstance().GetICDManager().RegisterObserver(&app::Silabs::ApplicationSleepManager::GetInstance());
#endif // SL_MATTER_ENABLE_APP_SLEEP_MANAGER

// Init Matter Server and Start Event Loop
Expand Down
18 changes: 12 additions & 6 deletions examples/platform/silabs/SilabsTestEventTriggerDelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,27 @@

#include "SilabsTestEventTriggerDelegate.h"
#include <ProvisionManager.h>
#include <lib/core/ErrorStr.h>

using namespace ::chip::DeviceLayer;

namespace chip {

bool SilabsTestEventTriggerDelegate::DoesEnableKeyMatch(const ByteSpan & enableKey) const
{
uint8_t storedEnableKey[TestEventTriggerDelegate::kEnableKeyLength];
MutableByteSpan enableKeySpan(storedEnableKey);
uint8_t storedEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0 };
MutableByteSpan storedEnableKeySpan(storedEnableKey);

// Return false if we were not able to get the enableKey
VerifyOrReturnValue(
Silabs::Provision::Manager::GetInstance().GetStorage().GetTestEventTriggerKey(enableKeySpan) == CHIP_NO_ERROR, false);
CHIP_ERROR error = Silabs::Provision::Manager::GetInstance().GetStorage().GetTestEventTriggerKey(storedEnableKeySpan);
if (error != CHIP_NO_ERROR)
{
// If we fail to read the enableKey from storage, the MutableByteSpan is not modified by the getter which leaves the span equal to a zero bytepsan (size = 0).
// This guarantees that we will be able to inform the stack that the test event trigger is not enabled when the stack tries
// to match the zero bytespan to our enableKey.
ChipLogError(DeviceLayer, "Failed to get test event trigger key: %s", ErrorStr(error));
}

return (!enableKeySpan.empty() && enableKeySpan.data_equal(enableKey));
return storedEnableKeySpan.data_equal(enableKey);
}

} // namespace chip
14 changes: 5 additions & 9 deletions examples/platform/silabs/provision/ProvisionStorageDefault.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ CHIP_ERROR WritePage(uint32_t addr, const uint8_t * data, size_t size, size_t ma
// The flash driver fails if the size is not a multiple of 4 (32-bits)
size_t size_32 = RoundNearest(size, 4);
// If the input data is smaller than the 32-bit size, pad the buffer with "0xff"
if(size_32 != size)
if (size_32 != size)
{
uint8_t * p = (uint8_t *) data;
VerifyOrReturnError(size_32 <= max, CHIP_ERROR_BUFFER_TOO_SMALL);
Expand Down Expand Up @@ -666,12 +666,7 @@ CHIP_ERROR Storage::SetOtaTlvEncryptionKey(const ByteSpan & value)
}
#endif // OTA_ENCRYPTION_ENABLE

/**
* @brief Reads the test event trigger key from NVM. If the key isn't present, returns default value if defined.
*
* @param[out] keySpan output buffer. Must be at least large enough for 16 bytes (ken length)
* @return CHIP_ERROR
*/
#ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLED
CHIP_ERROR Storage::GetTestEventTriggerKey(MutableByteSpan & keySpan)
{
constexpr size_t kEnableKeyLength = 16; // Expected byte size of the EnableKey
Expand All @@ -683,7 +678,7 @@ CHIP_ERROR Storage::GetTestEventTriggerKey(MutableByteSpan & keySpan)
err = SilabsConfig::ReadConfigValueBin(SilabsConfig::kConfigKey_Test_Event_Trigger_Key, keySpan.data(), kEnableKeyLength,
keyLength);
#ifndef NDEBUG
#ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLED
#ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLE_KEY
if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
{

Expand All @@ -696,12 +691,13 @@ CHIP_ERROR Storage::GetTestEventTriggerKey(MutableByteSpan & keySpan)
}
err = CHIP_NO_ERROR;
}
#endif // SL_MATTER_TEST_EVENT_TRIGGER_ENABLED
#endif // SL_MATTER_TEST_EVENT_TRIGGER_ENABLE_KEY
#endif // NDEBUG

keySpan.reduce_size(kEnableKeyLength);
return err;
}
#endif // SL_MATTER_TEST_EVENT_TRIGGER_ENABLED

} // namespace Provision

Expand Down
2 changes: 2 additions & 0 deletions examples/platform/silabs/provision/ProvisionStorageFlash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -719,10 +719,12 @@ CHIP_ERROR Storage::SetOtaTlvEncryptionKey(const ByteSpan & value)
}
#endif // OTA_ENCRYPTION_ENABLE

#ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLED
CHIP_ERROR Storage::GetTestEventTriggerKey(MutableByteSpan & keySpan)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}
#endif // SL_MATTER_TEST_EVENT_TRIGGER_ENABLED

} // namespace Provision

Expand Down
89 changes: 84 additions & 5 deletions examples/platform/silabs/wifi/icd/ApplicationSleepManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,22 @@
******************************************************************************/

#include "ApplicationSleepManager.h"
#include <lib/core/DataModelTypes.h>
#include <lib/support/logging/CHIPLogging.h>

namespace chip {
namespace app {
namespace Silabs {

namespace {

enum class SpecialCaseVendorID : uint16_t
{
kAppleKeychain = 4996,
};

} // namespace

ApplicationSleepManager ApplicationSleepManager::mInstance;

CHIP_ERROR ApplicationSleepManager::Init()
Expand Down Expand Up @@ -92,24 +102,93 @@ bool ApplicationSleepManager::CanGoToLIBasedSleep()
ChipLogProgress(AppServer, "Commissioning Window is Open - Cannot go to LI based sleep");
canGoToLIBasedSleep = false;
}
else if (mIsInActiveMode)
{
ChipLogProgress(AppServer, "Device is in active mode - Cannot go to LI based sleep");
canGoToLIBasedSleep = false;
}
else
{
for (auto it = mFabricTable->begin(); it != mFabricTable->end(); ++it)
{
if (!mSubscriptionsInfoProvider->FabricHasAtLeastOneActiveSubscription(it->GetFabricIndex()))
{
ChipLogProgress(AppServer, "Fabric index %u has no active subscriptions - Cannot go to LI based sleep",
it->GetFabricIndex());
canGoToLIBasedSleep = false;
break;
ChipLogProgress(AppServer, "Fabric index %u has no active subscriptions", it->GetFabricIndex());
canGoToLIBasedSleep = ProcessSpecialVendorIDCase(it->GetVendorId());

if (canGoToLIBasedSleep)
{
ChipLogProgress(AppServer,
"Fabric index %u with vendor ID : %d has an edge case that allows for LI based sleep",
it->GetFabricIndex(), it->GetVendorId());
}
else
{
// Fabric doesn't meet the requirements to allow us to go to LI based sleep
break;
}
}
ChipLogProgress(AppServer, "Fabric index %u has an active subscriptions!", it->GetFabricIndex());
}
}

return canGoToLIBasedSleep;
}

bool ApplicationSleepManager::ProcessSpecialVendorIDCase(chip::VendorId vendorId)
{
bool hasValidException = false;
switch (to_underlying(vendorId))
{
case to_underlying(SpecialCaseVendorID::kAppleKeychain):
hasValidException = ProcessKeychainEdgeCase();
break;

default:
break;
}

return hasValidException;
}

bool ApplicationSleepManager::ProcessKeychainEdgeCase()
{
bool hasValidException = false;

for (auto it = mFabricTable->begin(); it != mFabricTable->end(); ++it)
{
if ((it->GetVendorId() == chip::VendorId::Apple) &&
mSubscriptionsInfoProvider->FabricHasAtLeastOneActiveSubscription(it->GetFabricIndex()))
{
hasValidException = true;
break;
}
}

return hasValidException;
}

void ApplicationSleepManager::OnEnterActiveMode()
{
mIsInActiveMode = true;
mWifiSleepManager->VerifyAndTransitionToLowPowerMode();
}

void ApplicationSleepManager::OnEnterIdleMode()
{
mIsInActiveMode = false;
mWifiSleepManager->VerifyAndTransitionToLowPowerMode();
}

void ApplicationSleepManager::OnTransitionToIdle()
{
// Nothing to do
}

void ApplicationSleepManager::OnICDModeChange()
{
// Nothing to do
}

} // namespace Silabs
} // namespace app
} // namespace chip
38 changes: 37 additions & 1 deletion examples/platform/silabs/wifi/icd/ApplicationSleepManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <app/ReadHandler.h>
#include <app/SubscriptionsInfoProvider.h>
#include <app/icd/server/ICDStateObserver.h>
#include <app/server/CommissioningWindowManager.h>
#include <credentials/FabricTable.h>
#include <platform/silabs/wifi/icd/WifiSleepManager.h>
Expand All @@ -29,7 +30,8 @@ namespace Silabs {

class ApplicationSleepManager : public chip::app::ReadHandler::ApplicationCallback,
public chip::DeviceLayer::Silabs::WifiSleepManager::ApplicationCallback,
public chip::FabricTable::Delegate
public chip::FabricTable::Delegate,
public chip::app::ICDStateObserver
{
public:
static ApplicationSleepManager & GetInstance() { return mInstance; }
Expand Down Expand Up @@ -131,20 +133,54 @@ class ApplicationSleepManager : public chip::app::ReadHandler::ApplicationCallba

void OnFabricUpdated(const chip::FabricTable & fabricTable, chip::FabricIndex fabricIndex) override {}

// ICDStateObserver implementation
void OnEnterActiveMode() override;
void OnEnterIdleMode() override;
void OnTransitionToIdle() override;
void OnICDModeChange() override;

private:
ApplicationSleepManager() = default;
~ApplicationSleepManager() = default;

ApplicationSleepManager(const ApplicationSleepManager &) = delete;
ApplicationSleepManager & operator=(const ApplicationSleepManager &) = delete;

/**
* @brief Processes special cases based on the vendor ID.
*
* This method checks if the given vendor ID has any special cases that allow
* the device to go to LI based sleep when the fabric associated to the vendor ID does not have an active subscription.
*
* @param vendorId The vendor ID to check for special cases.
* @return true if the vendor ID has a special case that allows LI based sleep, false otherwise.
*/
bool ProcessSpecialVendorIDCase(chip::VendorId vendorId);

/**
* @brief Processes the Apple Keychain edge case.
*
* Apple, when commissioning, adds two fabric to the device. One for Apple Home and one for the Appley Keychain.
* Apple Home is the active fabric which is used to communication with the device. The associated fabric also has the active
* subcription. Applye Keychain fabric acts as a safety and doesn't have an active fabric with the device. As such, we need an
* alternate method to check if the device can go to LI based sleep.
*
* This method checks if there is any fabric with the Apple Home vendor ID that
* has at least one active subscription. If such a fabric is found, it allows
* the device to go to LI based sleep.
*
* @return true if the Apple Keychain edge case allows low-power mode, false otherwise.
*/
bool ProcessKeychainEdgeCase();

static ApplicationSleepManager mInstance;
chip::FabricTable * mFabricTable = nullptr;
chip::app::SubscriptionsInfoProvider * mSubscriptionsInfoProvider = nullptr;
chip::CommissioningWindowManager * mCommissioningWindowManager = nullptr;
chip::DeviceLayer::Silabs::WifiSleepManager * mWifiSleepManager = nullptr;

bool mIsCommissionningWindowOpen = false;
bool mIsInActiveMode = false;
};

} // namespace Silabs
Expand Down
7 changes: 7 additions & 0 deletions src/platform/silabs/CHIPPlatformConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@
#define CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC SL_ICD_SUPPORTED_CLIENTS_PER_FABRIC
#endif // CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC

#ifdef SL_WIFI
#ifndef CHIP_CONFIG_ICD_OBSERVERS_POOL_SIZE
#define CHIP_CONFIG_ICD_OBSERVERS_POOL_SIZE 3
#endif // CHIP_CONFIG_ICD_OBSERVERS_POOL_SIZE
static_assert(CHIP_CONFIG_ICD_OBSERVERS_POOL_SIZE >= 3, "ICD Observers pool size must be at least 3");
#endif // SL_WIFI

#endif // defined(CHIP_CONFIG_ENABLE_ICD_SERVER) && CHIP_CONFIG_ENABLE_ICD_SERVER

/**
Expand Down
10 changes: 10 additions & 0 deletions src/platform/silabs/provision/ProvisionStorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,17 @@ struct Storage : public GenericStorage,
CHIP_ERROR GetSetupPayload(chip::MutableCharSpan & value);
CHIP_ERROR SetProvisionRequest(bool value);
CHIP_ERROR GetProvisionRequest(bool & value);

#ifdef SL_MATTER_TEST_EVENT_TRIGGER_ENABLED
/**
* @brief Reads the test event trigger key from NVM. If the key isn't present, returns default value if defined.
*
* @param[out] keySpan output buffer. Must be at least large enough for 16 bytes (key length)
* @return CHIP_ERROR
*/
CHIP_ERROR GetTestEventTriggerKey(MutableByteSpan & keySpan);
#endif // SL_MATTER_TEST_EVENT_TRIGGER_ENABLED

void SetBufferSize(size_t size) { mBufferSize = size > 0 ? size : kArgumentSizeMax; }
size_t GetBufferSize() { return mBufferSize; }

Expand Down

0 comments on commit 03ca2d7

Please sign in to comment.