blob: b921aec6fdeb4faee9fa5cb475fc0d7f4cd16e1f [file] [log] [blame]
/*
*
* Copyright (c) 2020 Project CHIP Authors
* Copyright (c) 2020 Google LLC.
* Copyright (c) 2018 Nest Labs, Inc.
*
* 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
* Utilities for accessing persisted device configuration on
* platforms based on the NXP K32W SDK.
*/
/* this file behaves like a config.h, comes first */
#include <platform/internal/CHIPDeviceLayerInternal.h>
#include <platform/nxp/k32w/k32w0/K32W0Config.h>
#include <lib/core/CHIPEncoding.h>
#include <platform/internal/testing/ConfigUnitTest.h>
#include "FreeRTOS.h"
namespace chip {
namespace DeviceLayer {
namespace Internal {
osaMutexId_t K32WConfig::pdmMutexHandle = NULL;
#if CHIP_DEVICE_LAYER_ENABLE_PDM_LOGS
static void PDM_SystemCallback(uint32_t number, PDM_eSystemEventCode code)
{
uint8_t capacity = PDM_u8GetSegmentCapacity();
uint8_t occupancy = PDM_u8GetSegmentOccupancy();
ChipLogProgress(DeviceLayer, "[PDM]Event (number, code): (%lu, %d)", number, code);
ChipLogProgress(DeviceLayer, "[PDM]Capacity: %hhu", capacity);
ChipLogProgress(DeviceLayer, "[PDM]Occupancy: %hhu", occupancy);
}
#endif
CHIP_ERROR K32WConfig::Init()
{
CHIP_ERROR err = CHIP_NO_ERROR;
int status;
/* Initialise the Persistent Data Manager */
pdmMutexHandle = OSA_MutexCreate();
VerifyOrExit((NULL != pdmMutexHandle), err = CHIP_ERROR_NO_MEMORY);
status = PDM_Init();
SuccessOrExit(err = MapPdmInitStatusToChipError(status));
#if CHIP_DEVICE_LAYER_ENABLE_PDM_LOGS
PDM_vRegisterSystemCallback(PDM_SystemCallback);
#endif
err = RamStorage::Init(kNvmIdChipConfigData, kRamBufferInitialSize);
exit:
if (err != CHIP_NO_ERROR)
{
if (pdmMutexHandle)
{
OSA_MutexDestroy(pdmMutexHandle);
}
RamStorage::FreeBuffer();
}
return err;
}
void K32WConfig::MutexLock(osaMutexId_t mutexId, uint32_t millisec)
{
osaStatus_t status = OSA_MutexLock(mutexId, millisec);
if (osaStatus_Success != status)
{
ChipLogProgress(DeviceLayer, "OSA mutex lock failed.");
}
}
void K32WConfig::MutexUnlock(osaMutexId_t mutexId)
{
osaStatus_t status = OSA_MutexUnlock(mutexId);
if (osaStatus_Success != status)
{
ChipLogProgress(DeviceLayer, "OSA mutex unlock failed.");
}
}
CHIP_ERROR K32WConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
{
CHIP_ERROR err;
uint16_t sizeToRead = bufSize;
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
err = RamStorage::Read(key, 0, (uint8_t *) buf, &sizeToRead);
SuccessOrExit(err);
outLen = sizeToRead;
exit:
return err;
}
CHIP_ERROR K32WConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
{
return ReadConfigValueStr(key, (char *) buf, bufSize, outLen);
}
CHIP_ERROR K32WConfig::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val)
{
Key key = kMinConfigKey_ChipCounter + counterIdx;
return ReadConfigValue(key, val);
}
CHIP_ERROR K32WConfig::WriteConfigValueStr(Key key, const char * str)
{
return WriteConfigValueStr(key, str, (str != NULL) ? strlen(str) : 0);
}
CHIP_ERROR K32WConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen)
{
CHIP_ERROR err;
PDM_teStatus status;
RamStorage::Buffer buffer;
MutexLock(pdmMutexHandle, osaWaitForever_c);
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND);
if (!str)
{
err = RamStorage::Delete(key, -1);
}
else
{
err = RamStorage::Write(key, (uint8_t *) str, strLen);
SuccessOrExit(err);
buffer = RamStorage::GetBuffer();
status = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, buffer, buffer->ramBufferLen + kRamDescHeaderSize);
SuccessOrExit(err = MapPdmStatusToChipError(status));
}
exit:
MutexUnlock(pdmMutexHandle);
return err;
}
CHIP_ERROR K32WConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
{
return WriteConfigValueStr(key, (char *) data, dataLen);
}
CHIP_ERROR K32WConfig::WriteConfigValueCounter(uint8_t counterIdx, uint32_t val)
{
Key key = kMinConfigKey_ChipCounter + counterIdx;
return WriteConfigValue(key, val);
}
CHIP_ERROR K32WConfig::ClearConfigValue(Key key)
{
CHIP_ERROR err = CHIP_NO_ERROR;
PDM_teStatus status;
RamStorage::Buffer buffer;
MutexLock(pdmMutexHandle, osaWaitForever_c);
VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id.
err = RamStorage::Delete(key, -1);
SuccessOrExit(err);
buffer = RamStorage::GetBuffer();
status = PDM_eSaveRecordDataInIdleTask(kNvmIdChipConfigData, buffer, buffer->ramBufferLen + kRamDescHeaderSize);
SuccessOrExit(err = MapPdmStatusToChipError(status));
exit:
MutexUnlock(pdmMutexHandle);
return err;
}
bool K32WConfig::ConfigValueExists(Key key)
{
CHIP_ERROR err;
uint16_t sizeToRead;
bool found = false;
if (ValidConfigKey(key))
{
err = RamStorage::Read(key, 0, NULL, &sizeToRead);
found = (err == CHIP_NO_ERROR && sizeToRead != 0);
}
return found;
}
CHIP_ERROR K32WConfig::FactoryResetConfig(void)
{
CHIP_ERROR err = CHIP_NO_ERROR;
PDM_teStatus status;
RamStorage::Buffer buffer;
MutexLock(pdmMutexHandle, osaWaitForever_c);
FactoryResetConfigInternal(kMinConfigKey_ChipCounter, kMaxConfigKey_ChipCounter);
FactoryResetConfigInternal(kMinConfigKey_ChipConfig, kMaxConfigKey_ChipConfig);
FactoryResetConfigInternal(kMinConfigKey_KVSKey, kMaxConfigKey_KVSKey);
FactoryResetConfigInternal(kMinConfigKey_KVSValue, kMaxConfigKey_KVSValue);
buffer = RamStorage::GetBuffer();
status = PDM_eSaveRecordData(kNvmIdChipConfigData, buffer, buffer->ramBufferLen + kRamDescHeaderSize);
SuccessOrExit(err = MapPdmStatusToChipError(status));
exit:
RamStorage::FreeBuffer();
MutexUnlock(pdmMutexHandle);
return err;
}
void K32WConfig::FactoryResetConfigInternal(Key firstKey, Key lastKey)
{
for (Key key = firstKey; key <= lastKey; key++)
{
RamStorage::Delete(key, -1);
}
}
CHIP_ERROR K32WConfig::MapPdmStatusToChipError(PDM_teStatus status)
{
CHIP_ERROR err;
switch (status)
{
case PDM_E_STATUS_OK:
err = CHIP_NO_ERROR;
break;
default:
err = CHIP_ERROR(ChipError::Range::kPlatform, status);
break;
}
return err;
}
CHIP_ERROR K32WConfig::MapPdmInitStatusToChipError(int status)
{
return (status == 0) ? CHIP_NO_ERROR : CHIP_ERROR(ChipError::Range::kPlatform, status);
}
bool K32WConfig::ValidConfigKey(Key key)
{
// Returns true if the key is in the valid CHIP Config PDM key range.
if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_KVSValue))
{
return true;
}
return false;
}
void K32WConfig::RunConfigUnitTest() {}
} // namespace Internal
} // namespace DeviceLayer
} // namespace chip