| /* |
| * |
| * Copyright (c) 2022 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 |
| * Open IoT SDK key-value storage base on flash TDBStore. |
| */ |
| |
| #include <platform/internal/CHIPDeviceLayerInternal.h> |
| |
| #include <lib/core/CHIPEncoding.h> |
| #include <lib/support/CHIPMem.h> |
| #include <lib/support/CHIPMemString.h> |
| #include <lib/support/CodeUtils.h> |
| #include <lib/support/logging/CHIPLogging.h> |
| #include <system/SystemMutex.h> |
| |
| namespace chip { |
| namespace DeviceLayer { |
| namespace Internal { |
| |
| // *** CAUTION ***: Changing the values of these keys can *break* existing devices. |
| const KVPsaPsStore::Key KVPsaPsStore::kMatterFactory_KeyOffset = 0x0; |
| const KVPsaPsStore::Key KVPsaPsStore::kMatterConfig_KeyOffset = 0x1; |
| const KVPsaPsStore::Key KVPsaPsStore::kMatterCounter_KeyOffset = 0x2; |
| const KVPsaPsStore::Key KVPsaPsStore::kMatterKvs_KeyOffset = 0x3; |
| |
| // Keys stored in the Matter factory group |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_SerialNum = GetPsaPaKey(kMatterFactory_KeyOffset, 0x00); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_MfrDeviceId = GetPsaPaKey(kMatterFactory_KeyOffset, 0x01); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_MfrDeviceCert = GetPsaPaKey(kMatterFactory_KeyOffset, 0x02); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_MfrDeviceICACerts = GetPsaPaKey(kMatterFactory_KeyOffset, 0x03); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_MfrDevicePrivateKey = GetPsaPaKey(kMatterFactory_KeyOffset, 0x04); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_HardwareVersion = GetPsaPaKey(kMatterFactory_KeyOffset, 0x05); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_ManufacturingDate = GetPsaPaKey(kMatterFactory_KeyOffset, 0x06); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_SetupPinCode = GetPsaPaKey(kMatterFactory_KeyOffset, 0x07); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_SetupDiscriminator = GetPsaPaKey(kMatterFactory_KeyOffset, 0x08); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_Spake2pIterationCount = GetPsaPaKey(kMatterFactory_KeyOffset, 0x09); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_Spake2pSalt = GetPsaPaKey(kMatterFactory_KeyOffset, 0x0A); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_Spake2pVerifier = GetPsaPaKey(kMatterFactory_KeyOffset, 0x0B); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_VendorId = GetPsaPaKey(kMatterFactory_KeyOffset, 0x0C); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_ProductId = GetPsaPaKey(kMatterFactory_KeyOffset, 0x0D); |
| |
| // Keys stored in the Matter config group |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_ServiceConfig = GetPsaPaKey(kMatterConfig_KeyOffset, 0x00); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_PairedAccountId = GetPsaPaKey(kMatterConfig_KeyOffset, 0x01); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_ServiceId = GetPsaPaKey(kMatterConfig_KeyOffset, 0x02); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_LastUsedEpochKeyId = GetPsaPaKey(kMatterConfig_KeyOffset, 0x03); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_FailSafeArmed = GetPsaPaKey(kMatterConfig_KeyOffset, 0x04); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_WiFiStationSecType = GetPsaPaKey(kMatterConfig_KeyOffset, 0x05); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_RegulatoryLocation = GetPsaPaKey(kMatterConfig_KeyOffset, 0x06); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_CountryCode = GetPsaPaKey(kMatterConfig_KeyOffset, 0x07); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_LocationCapability = GetPsaPaKey(kMatterConfig_KeyOffset, 0x08); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_UniqueId = GetPsaPaKey(kMatterConfig_KeyOffset, 0x09); |
| |
| // Keys stored in the Matter counters group |
| const KVPsaPsStore::Key KVPsaPsStore::kCounterKey_RebootCount = GetPsaPaKey(kMatterCounter_KeyOffset, 0x00); |
| const KVPsaPsStore::Key KVPsaPsStore::kCounterKey_UpTime = GetPsaPaKey(kMatterCounter_KeyOffset, 0x01); |
| const KVPsaPsStore::Key KVPsaPsStore::kCounterKey_TotalOperationalHours = GetPsaPaKey(kMatterCounter_KeyOffset, 0x02); |
| const KVPsaPsStore::Key KVPsaPsStore::kCounterKey_BootReason = GetPsaPaKey(kMatterCounter_KeyOffset, 0x03); |
| |
| // Keys stored in the Matter key-value group |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_KvsStringKeyMap = GetPsaPaKey(kMatterKvs_KeyOffset, 0x00); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_KvsFirstKeySlot = GetPsaPaKey(kMatterKvs_KeyOffset, 0x01); |
| const KVPsaPsStore::Key KVPsaPsStore::kConfigKey_KvsLastKeySlot = GetPsaPaKey(kMatterKvs_KeyOffset, KVS_MAX_ENTRIES); |
| |
| // NVS helper variables |
| const KVPsaPsStore::Key KVPsaPsStore::kMinConfigKey_MatterConfig = GetPsaPaKey(kMatterConfig_KeyOffset, 0x00); |
| const KVPsaPsStore::Key KVPsaPsStore::kMaxConfigKey_MatterConfig = GetPsaPaKey(kMatterConfig_KeyOffset, 0xFF); |
| const KVPsaPsStore::Key KVPsaPsStore::kMinConfigKey_MatterCounter = GetPsaPaKey(kMatterCounter_KeyOffset, 0x00); |
| const KVPsaPsStore::Key KVPsaPsStore::kMaxConfigKey_MatterCounter = GetPsaPaKey(kMatterCounter_KeyOffset, 0xFF); |
| |
| const KVPsaPsStore::Key KVPsaPsStore::kMinMatterPsaPaKeyRegion = GetPsaPaKey(kMatterFactory_KeyOffset, 0x00); |
| const KVPsaPsStore::Key KVPsaPsStore::kMaxMatterPsaPaKeyRegion = GetPsaPaKey(kMatterKvs_KeyOffset, 0xFF); |
| |
| char mKvsStoredKeyString[KVS_MAX_ENTRIES][PersistentStorageDelegate::kKeyLengthMax + 1]; |
| chip::System::Mutex mKvsStoredKeyMutex; |
| |
| bool KVPsaPsStore::initialized = false; |
| |
| CHIP_ERROR KVPsaPsStore::Init(void) |
| { |
| if (initialized) |
| { |
| return CHIP_NO_ERROR; |
| } |
| |
| memset(mKvsStoredKeyString, 0, sizeof(mKvsStoredKeyString)); |
| size_t outLen; |
| CHIP_ERROR err = ReadConfigValueBin(kConfigKey_KvsStringKeyMap, reinterpret_cast<uint8_t *>(mKvsStoredKeyString), |
| sizeof(mKvsStoredKeyString), outLen); |
| |
| if ((err != CHIP_NO_ERROR) && (err != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)) // Initial boot |
| { |
| return err; |
| } |
| |
| chip::System::Mutex::Init(mKvsStoredKeyMutex); |
| initialized = true; |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::ReadConfigValue(Key key, bool & val) |
| { |
| if (!ConfigValueExists(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| size_t actual_size = 0; |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_get(key, 0, sizeof(val), reinterpret_cast<void *>(&val), &actual_size)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| if (actual_size != sizeof(val)) |
| { |
| return CHIP_ERROR_BAD_REQUEST; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::ReadConfigValue(Key key, uint32_t & val) |
| { |
| |
| if (!ConfigValueExists(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| size_t actual_size = 0; |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_get(key, 0, sizeof(val), reinterpret_cast<void *>(&val), &actual_size)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| if (actual_size != sizeof(val)) |
| { |
| return CHIP_ERROR_BAD_REQUEST; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::ReadConfigValue(Key key, uint64_t & val) |
| { |
| if (!ConfigValueExists(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| size_t actual_size = 0; |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_get(key, 0, sizeof(val), reinterpret_cast<void *>(&val), &actual_size)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| if (actual_size != sizeof(val)) |
| { |
| return CHIP_ERROR_BAD_REQUEST; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) |
| { |
| // Note: The system expect adding the terminator char. |
| CHIP_ERROR err = ReadConfigValueBin(key, reinterpret_cast<uint8_t *>(buf), (bufSize - 1), outLen); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| buf[outLen] = 0; |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) |
| { |
| return ReadConfigValueBin(key, buf, bufSize, outLen, 0); |
| } |
| |
| CHIP_ERROR KVPsaPsStore::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen, size_t offset) |
| { |
| size_t keySize; |
| if (!ConfigValueExists(key, keySize)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| if (buf != NULL) |
| { |
| size_t actual_size = 0; |
| size_t readLength = bufSize >= (keySize - offset) ? keySize - offset : bufSize; |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_get(key, offset, readLength, reinterpret_cast<void *>(buf), &actual_size)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| outLen = actual_size; |
| if (bufSize < keySize - offset) |
| { |
| return CHIP_ERROR_BUFFER_TOO_SMALL; |
| } |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::ReadConfigValueCounter(Key counterId, uint32_t & val) |
| { |
| Key key = kMinConfigKey_MatterCounter + counterId; |
| |
| if (!ConfigValueExists(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| size_t actual_size = 0; |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_get(key, 0, sizeof(val), reinterpret_cast<void *>(&val), &actual_size)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| if (actual_size != sizeof(val)) |
| { |
| return CHIP_ERROR_BAD_REQUEST; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::WriteConfigValue(Key key, bool val) |
| { |
| if (!ValidConfigKey(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_set(key, sizeof(val), reinterpret_cast<void *>(&val), PSA_STORAGE_FLAG_NONE)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::WriteConfigValue(Key key, uint32_t val) |
| { |
| if (!ValidConfigKey(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_set(key, sizeof(val), reinterpret_cast<void *>(&val), PSA_STORAGE_FLAG_NONE)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::WriteConfigValue(Key key, uint64_t val) |
| { |
| if (!ValidConfigKey(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_set(key, sizeof(val), reinterpret_cast<void *>(&val), PSA_STORAGE_FLAG_NONE)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::WriteConfigValueStr(Key key, const char * str) |
| { |
| return WriteConfigValueBin(key, reinterpret_cast<const uint8_t *>(str), (str != nullptr) ? strlen(str) : 0); |
| } |
| |
| CHIP_ERROR KVPsaPsStore::WriteConfigValueStr(Key key, const char * str, size_t strLen) |
| { |
| return WriteConfigValueBin(key, reinterpret_cast<const uint8_t *>(str), (strLen > 0) ? strLen : 1); |
| } |
| |
| CHIP_ERROR KVPsaPsStore::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) |
| { |
| if (!ValidConfigKey(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| // Two different behavior: If the pointer is not null, the value is updated |
| // or create. If the pointer is null, the key is removed if it exist. |
| if (data != nullptr) |
| { |
| CHIP_ERROR err = PsaStatus2ChipError( |
| psa_ps_set(key, dataLen, const_cast<void *>(reinterpret_cast<const void *>(data)), PSA_STORAGE_FLAG_NONE)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| } |
| else if (ConfigValueExists(key)) |
| { |
| return ClearConfigValue(key); |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::WriteConfigValueCounter(Key counterId, uint32_t val) |
| { |
| Key key = kMinConfigKey_MatterCounter + counterId; |
| |
| if (!ValidConfigKey(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_set(key, sizeof(val), reinterpret_cast<void *>(&val), PSA_STORAGE_FLAG_NONE)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::ClearConfigValue(Key key) |
| { |
| if (!ValidConfigKey(key)) |
| { |
| return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| CHIP_ERROR err = PsaStatus2ChipError(psa_ps_remove(key)); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::FactoryResetConfig() |
| { |
| // Deletes all Config and KVS group objects. |
| // Factory and Counter type objects are NOT deleted. |
| |
| if (Init() != CHIP_NO_ERROR) |
| { |
| return CHIP_ERROR_INTERNAL; |
| } |
| |
| // Iterate over all the Matter Config objects and delete each one. |
| CHIP_ERROR err = ForEachObject(kMinConfigKey_MatterConfig, kMaxConfigKey_MatterConfig, false, |
| [](const Key & key, const size_t & size) -> CHIP_ERROR { return ClearConfigValue(key); }); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| // Iterate over all the Matter KVS objects and delete each one (including KVS key map). |
| err = ForEachObject(kConfigKey_KvsStringKeyMap, kConfigKey_KvsLastKeySlot, false, |
| [](const Key & key, const size_t & size) -> CHIP_ERROR { return ClearConfigValue(key); }); |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| |
| mKvsStoredKeyMutex.Lock(); |
| memset(mKvsStoredKeyString, 0, sizeof(mKvsStoredKeyString)); |
| mKvsStoredKeyMutex.Unlock(); |
| |
| return err; |
| } |
| |
| void KVPsaPsStore::RunConfigUnitTest() |
| { |
| // Run common unit test. |
| ::chip::DeviceLayer::Internal::RunConfigUnitTest<KVPsaPsStore>(); |
| } |
| |
| bool KVPsaPsStore::ValidConfigKey(Key key) |
| { |
| // Returns true if the key is in the Matter reserved key range. |
| return ((key >= kMinMatterPsaPaKeyRegion) && (key <= kMaxMatterPsaPaKeyRegion)); |
| } |
| |
| bool KVPsaPsStore::ValidKvsKey(Key key) |
| { |
| // Returns true if the key is in the KVS group range. |
| return ((key >= kConfigKey_KvsFirstKeySlot) && (key <= kConfigKey_KvsLastKeySlot)); |
| } |
| |
| void KVPsaPsStore::KVSKeyMapUpdate() |
| { |
| OnScheduleKVSKeyMapUpdate(nullptr, nullptr); |
| } |
| |
| void KVPsaPsStore::ScheduleKVSKeyMapUpdate() |
| { |
| CHIP_ERROR err = SystemLayer().StartTimer( |
| std::chrono::duration_cast<System::Clock::Timeout>(System::Clock::Seconds32(KVS_KEY_MAP_UPDATE_DELAY_SEC)), |
| OnScheduleKVSKeyMapUpdate, NULL); |
| if (err != CHIP_NO_ERROR) |
| { |
| ChipLogError(DeviceLayer, "Start KVS key map update timer failed: %" CHIP_ERROR_FORMAT, err.Format()); |
| } |
| } |
| |
| void KVPsaPsStore::OnScheduleKVSKeyMapUpdate(System::Layer * systemLayer, void * appState) |
| { |
| mKvsStoredKeyMutex.Lock(); |
| CHIP_ERROR err = WriteConfigValueBin(kConfigKey_KvsStringKeyMap, reinterpret_cast<const uint8_t *>(mKvsStoredKeyString), |
| sizeof(mKvsStoredKeyString)); |
| if (err != CHIP_NO_ERROR) |
| { |
| ChipLogError(DeviceLayer, "KVS key map update failed: %" CHIP_ERROR_FORMAT, err.Format()); |
| } |
| mKvsStoredKeyMutex.Unlock(); |
| } |
| |
| bool KVPsaPsStore::ConfigValueExists(Key key, size_t & size) |
| { |
| if (!ValidConfigKey(key)) |
| { |
| return false; |
| } |
| |
| psa_storage_info_t info; |
| psa_status_t status = psa_ps_get_info(key, &info); |
| if (status == PSA_SUCCESS) |
| { |
| size = info.size; |
| } |
| |
| return (status == PSA_SUCCESS); |
| } |
| |
| bool KVPsaPsStore::ConfigValueExists(Key key) |
| { |
| size_t size; |
| return ConfigValueExists(key, size); |
| } |
| |
| CHIP_ERROR KVPsaPsStore::ForEachObject(Key firstKey, Key lastKey, bool addNewRecord, ForEachObjectFunct funct) |
| { |
| CHIP_ERROR err; |
| // Iterates through the specified range of object key ids. |
| // Invokes the callers CB function when appropriate. |
| |
| for (Key key = firstKey; key <= lastKey; ++key) |
| { |
| // Check if object with current key exists. |
| psa_storage_info_t info; |
| psa_status_t status = psa_ps_get_info(key, &info); |
| switch (status) |
| { |
| case PSA_SUCCESS: |
| if (!addNewRecord) |
| { |
| // Invoke the caller's function |
| // (for retrieve,store,delete,enumerate GroupKey operations). |
| err = funct(key, info.size); |
| } |
| break; |
| case PSA_ERROR_DOES_NOT_EXIST: |
| if (addNewRecord) |
| { |
| // Invoke caller's function |
| // (for add GroupKey operation). |
| err = funct(key, info.size); |
| } |
| break; |
| default: |
| err = PsaStatus2ChipError(status); |
| break; |
| } |
| |
| if (err != CHIP_NO_ERROR) |
| { |
| return err; |
| } |
| } |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR KVPsaPsStore::PsaStatus2ChipError(psa_status_t status) |
| { |
| CHIP_ERROR err; |
| |
| switch (status) |
| { |
| case PSA_SUCCESS: |
| err = CHIP_NO_ERROR; |
| break; |
| case PSA_ERROR_DOES_NOT_EXIST: |
| err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| break; |
| default: |
| err = CHIP_ERROR(ChipError::Range::kPlatform, (status * (-1))); |
| break; |
| } |
| |
| return err; |
| } |
| |
| #define CONVERT_INDEX_TO_KEY(index) (KVPsaPsStore::kConfigKey_KvsFirstKeySlot + index) |
| #define CONVERT_KEY_TO_INDEX(key) (key - KVPsaPsStore::kConfigKey_KvsFirstKeySlot) |
| |
| KVPsaPsStoreKeyBuilder::KVPsaPsStoreKeyBuilder(const char * key) |
| { |
| uint8_t firstEmptyKeySlot = KVS_MAX_ENTRIES; |
| |
| if (KVPsaPsStore::Init() != CHIP_NO_ERROR) |
| { |
| return; |
| } |
| |
| valid = false; |
| existing = false; |
| mKvsStoredKeyMutex.Lock(); |
| |
| // Check if key already exists, find the first empty slot in the same time |
| for (uint8_t keyIndex = 0; keyIndex < KVS_MAX_ENTRIES; keyIndex++) |
| { |
| if (strcmp(key, mKvsStoredKeyString[keyIndex]) == 0) |
| { |
| keyValue = CONVERT_INDEX_TO_KEY(keyIndex); |
| if (KVPsaPsStore::ValidKvsKey(keyValue)) |
| { |
| valid = true; |
| existing = true; |
| } |
| return; |
| } |
| |
| if ((keyIndex < firstEmptyKeySlot) && (mKvsStoredKeyString[keyIndex][0] == 0)) |
| { |
| firstEmptyKeySlot = keyIndex; |
| } |
| } |
| |
| // Key does not exist, reserve a slot for it |
| keyValue = CONVERT_INDEX_TO_KEY(firstEmptyKeySlot); |
| if (KVPsaPsStore::ValidKvsKey(keyValue)) |
| { |
| memset(buffer, 0, sizeof(buffer)); |
| size_t keyLength = strlen(key) <= (sizeof(buffer) - 1) ? strlen(key) : (sizeof(buffer) - 1); |
| if (keyLength < strlen(key)) |
| { |
| ChipLogError(DeviceLayer, "String key length is too long. Truncated to %d bytes", (sizeof(buffer) - 1)); |
| } |
| memcpy(buffer, key, keyLength); |
| buffer[keyLength] = 0; |
| |
| valid = true; |
| } |
| } |
| |
| KVPsaPsStoreKeyBuilder::~KVPsaPsStoreKeyBuilder() |
| { |
| mKvsStoredKeyMutex.Unlock(); |
| } |
| |
| void KVPsaPsStoreKeyBuilder::AddKey() |
| { |
| if (!valid || existing) |
| { |
| return; |
| } |
| |
| auto keyIndex = CONVERT_KEY_TO_INDEX(keyValue); |
| memset(mKvsStoredKeyString[keyIndex], 0, sizeof(mKvsStoredKeyString[keyIndex])); |
| Platform::CopyString(mKvsStoredKeyString[keyIndex], buffer); |
| KVPsaPsStore::ScheduleKVSKeyMapUpdate(); |
| } |
| |
| void KVPsaPsStoreKeyBuilder::RemoveKey() |
| { |
| if (!valid) |
| { |
| return; |
| } |
| |
| auto keyIndex = CONVERT_KEY_TO_INDEX(keyValue); |
| memset(mKvsStoredKeyString[keyIndex], 0, sizeof(mKvsStoredKeyString[keyIndex])); |
| KVPsaPsStore::ScheduleKVSKeyMapUpdate(); |
| } |
| |
| } // namespace Internal |
| } // namespace DeviceLayer |
| } // namespace chip |