/* * * Copyright (c) 2020 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 * Utilities for accessing persisted device configuration on * platforms based on the Qorvo QPG platforms. */ /* this file behaves like a config.h, comes first */ #include #include #include #include #include #include #include #include "FreeRTOS.h" #include "qvCHIP.h" namespace chip { namespace DeviceLayer { namespace Internal { CHIP_ERROR QPGConfig::Init() { // KVS will already be initialized in qvCHIP_Init before this is called from CHIP stack return CHIP_NO_ERROR; } CHIP_ERROR QPGConfig::ReadConfigValue(Key key, bool & val) { uint16_t length; length = sizeof(bool); return MapNVMError(qvCHIP_Nvm_Restore(key, reinterpret_cast(&val), &length)); } CHIP_ERROR QPGConfig::ReadConfigValue(Key key, uint32_t & val) { uint16_t length; length = sizeof(uint32_t); return MapNVMError(qvCHIP_Nvm_Restore(key, reinterpret_cast(&val), &length)); } CHIP_ERROR QPGConfig::ReadConfigValue(Key key, uint64_t & val) { uint16_t length; length = sizeof(uint64_t); return MapNVMError(qvCHIP_Nvm_Restore(key, reinterpret_cast(&val), &length)); } CHIP_ERROR QPGConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) { qvStatus_t res; uint16_t length; if ((buf == NULL) || (bufSize > UINT16_MAX)) { return CHIP_ERROR_INVALID_ARGUMENT; } length = static_cast(bufSize); res = qvCHIP_Nvm_Restore(key, Uint8::from_char(buf), &length); if (length > bufSize) { return CHIP_ERROR_BUFFER_TOO_SMALL; } if (res == QV_STATUS_NO_ERROR) { outLen = length; buf[outLen] = 0; } return MapNVMError(res); } CHIP_ERROR QPGConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) { uint8_t buffer[255]; uint16_t length; qvStatus_t res; if ((buf == NULL) || (bufSize > UINT16_MAX)) { return CHIP_ERROR_INVALID_ARGUMENT; } length = static_cast(bufSize); res = qvCHIP_Nvm_Restore(key, buffer, &length); if (res == QV_STATUS_NO_ERROR) { outLen = length; if (outLen > bufSize) { return CHIP_ERROR_BUFFER_TOO_SMALL; } memcpy(buf, buffer, outLen); buf[outLen] = 0; } return MapNVMError(res); } CHIP_ERROR QPGConfig::WriteConfigValue(Key key, bool val) { uint16_t length; length = sizeof(bool); return MapNVMError(qvCHIP_Nvm_Backup(key, reinterpret_cast(&val), length)); } CHIP_ERROR QPGConfig::WriteConfigValue(Key key, uint32_t val) { uint16_t length; length = sizeof(uint32_t); return MapNVMError(qvCHIP_Nvm_Backup(key, reinterpret_cast(&val), length)); } CHIP_ERROR QPGConfig::WriteConfigValue(Key key, uint64_t val) { uint16_t length; length = sizeof(uint64_t); return MapNVMError(qvCHIP_Nvm_Backup(key, reinterpret_cast(&val), length)); } CHIP_ERROR QPGConfig::WriteConfigValueStr(Key key, const char * str) { return WriteConfigValueStr(key, str, (str != NULL) ? strlen(str) : 0); } CHIP_ERROR QPGConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen) { if (strLen > UINT16_MAX) { return CHIP_ERROR_INVALID_ARGUMENT; } if (str == NULL) { qvCHIP_Nvm_ClearValue(key); } else { return MapNVMError(qvCHIP_Nvm_Backup(key, Uint8::from_const_char(str), static_cast(strLen))); } return CHIP_NO_ERROR; } CHIP_ERROR QPGConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) { if (dataLen > UINT16_MAX) { return CHIP_ERROR_BUFFER_TOO_SMALL; } if (data == NULL) { qvCHIP_Nvm_ClearValue(key); } else { return MapNVMError(qvCHIP_Nvm_Backup(key, data, static_cast(dataLen))); } return CHIP_NO_ERROR; } CHIP_ERROR QPGConfig::ClearConfigValue(Key key) { qvCHIP_Nvm_ClearValue(key); return CHIP_NO_ERROR; } bool QPGConfig::ConfigValueExists(Key key) { uint16_t dummy = 0; return qvCHIP_Nvm_ValueExists(key, &dummy); } CHIP_ERROR QPGConfig::FactoryResetConfig(void) { for (Key key = kMinConfigKey_ChipConfig; key <= kMaxConfigKey_ChipConfig; key++) { ClearConfigValue(key); } return CHIP_NO_ERROR; } CHIP_ERROR QPGConfig::ForEachRecord(Key firstKey, Key lastKey, bool addNewRecord, ForEachRecordFunct funct) { CHIP_ERROR err = CHIP_NO_ERROR; uint16_t length; for (Key nvmKey = firstKey; nvmKey <= lastKey; ++nvmKey) { if (qvCHIP_Nvm_ValueExists(nvmKey, &length)) { if (!addNewRecord) { // Invoke the caller's function // (for retrieve,store,delete,enumerate GroupKey operations). err = funct(nvmKey, length); } } else { if (addNewRecord) { // Invoke caller's function // (for add GroupKey operation). err = funct(nvmKey, length); } } SuccessOrExit(err); } exit: return err; } CHIP_ERROR QPGConfig::MapNVMError(qvStatus_t aStatus) { switch (aStatus) { case QV_STATUS_NO_ERROR: return CHIP_NO_ERROR; case QV_STATUS_BUFFER_TOO_SMALL: return CHIP_ERROR_BUFFER_TOO_SMALL; case QV_STATUS_INVALID_ARGUMENT: return CHIP_ERROR_INVALID_ARGUMENT; case QV_STATUS_KEY_LEN_TOO_SMALL: return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; case QV_STATUS_INVALID_DATA: return CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; default: break; } return CHIP_ERROR_INTERNAL; } void QPGConfig::RunConfigUnitTest() { // Run common unit test ::chip::DeviceLayer::Internal::RunConfigUnitTest(); } } // namespace Internal } // namespace DeviceLayer } // namespace chip