| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // clang-format off |
| #include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h> |
| #include <Weave/DeviceLayer/internal/GenericConfigurationManagerImpl.ipp> |
| |
| #include "src/connectivity/weave/adaptation/configuration_manager_delegate_impl.h" |
| #include "src/connectivity/weave/adaptation/group_key_store_impl.h" |
| // clang-format on |
| |
| #include <lib/fdio/fd.h> |
| #include <lib/fdio/fdio.h> |
| #include <lib/fit/defer.h> |
| #include <lib/syslog/cpp/macros.h> |
| #include <net/ethernet.h> |
| #include <sys/stat.h> |
| #include <unistd.h> |
| #include <zircon/status.h> |
| |
| #include <filesystem> |
| |
| #include "src/lib/files/file.h" |
| #include "src/lib/fsl/vmo/file.h" |
| #include "src/lib/fsl/vmo/strings.h" |
| #include "weave_inspector.h" |
| |
| namespace nl { |
| namespace Weave { |
| namespace DeviceLayer { |
| |
| namespace { |
| |
| using nl::Weave::WeaveInspector; |
| using ::nl::Weave::DeviceLayer::Internal::EnvironmentConfig; |
| using ::nl::Weave::DeviceLayer::Internal::GenericConfigurationManagerImpl; |
| using ::nl::Weave::DeviceLayer::Internal::WeaveConfigManager; |
| using ::nl::Weave::Profiles::Security::AppKeys::GroupKeyStoreBase; |
| |
| // Store path and keys for static device information. |
| constexpr char kDeviceInfoStorePath[] = "/config/data/device_info.json"; |
| constexpr char kDeviceInfoRuntimePath[] = "/data/device_info.json"; |
| constexpr char kDeviceInfoSchemaPath[] = "/pkg/data/device_info_schema.json"; |
| constexpr char kDeviceInfoConfigKey_BleDeviceNamePrefix[] = "ble-device-name-prefix"; |
| constexpr char kDeviceInfoConfigKey_DeviceId[] = "device-id"; |
| constexpr char kDeviceInfoConfigKey_DeviceIdPath[] = "device-id-path"; |
| constexpr char kDeviceInfoConfigKey_EnableThread[] = "enable-thread"; |
| constexpr char kDeviceInfoConfigKey_EnableWoBLE[] = "enable-woble"; |
| constexpr char kDeviceInfoConfigKey_EnableWoBLEAdvertisement[] = "enable-woble-advertisement"; |
| constexpr char kDeviceInfoConfigKey_FirmwareRevision[] = "firmware-revision"; |
| constexpr char kDeviceInfoConfigKey_MfrDeviceCertPath[] = "mfr-device-cert-path"; |
| constexpr char kDeviceInfoConfigKey_MfrDeviceCertAllowLocal[] = "mfr-device-cert-allow-local"; |
| constexpr char kDeviceInfoConfigKey_PrivateKeyPath[] = "mfr-private-key-path"; |
| constexpr char kDeviceInfoConfigKey_ProductId[] = "product-id"; |
| constexpr char kDeviceInfoConfigKey_SerialNumber[] = "serial-number"; |
| constexpr char kDeviceInfoConfigKey_ThreadJoinableDurationSec[] = "thread-joinable-duration-sec"; |
| constexpr char kDeviceInfoConfigKey_VendorId[] = "vendor-id"; |
| constexpr char kDeviceInfoConfigKey_AppletPaths[] = "applet-paths"; |
| |
| // Maximum number of chars in hex for a uint64_t. |
| constexpr int kWeaveDeviceIdMaxLength = 16; |
| |
| // Maximum size of Weave certificate. |
| constexpr int kWeaveCertificateMaxLength = UINT16_MAX; |
| |
| // Storage path for data files. |
| const std::string kDataPath = "/data/"; |
| |
| // The required size of a buffer supplied to GetPrimaryWiFiMACAddress. |
| constexpr size_t kWiFiMacAddressBufSize = |
| sizeof(Profiles::DeviceDescription::WeaveDeviceDescriptor::PrimaryWiFiMACAddress); |
| // Fake MAC address returned by GetPrimaryWiFiMACAddress |
| constexpr uint8_t kFakeMacAddress[kWiFiMacAddressBufSize] = {0xFF}; |
| |
| } // unnamed namespace |
| |
| ConfigurationManagerDelegateImpl::ConfigurationManagerDelegateImpl() |
| : device_info_(WeaveConfigManager::CreateInstance(kDeviceInfoStorePath)) {} |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::Init() { |
| WEAVE_ERROR err = WEAVE_NO_ERROR; |
| auto context = PlatformMgrImpl().GetComponentContextForProcess(); |
| bool fail_safe_armed = false; |
| |
| FX_CHECK(context->svc()->Connect(hwinfo_device_.NewRequest()) == ZX_OK) |
| << "Failed to connect to hwinfo device service."; |
| FX_CHECK(context->svc()->Connect(weave_factory_data_manager_.NewRequest()) == ZX_OK) |
| << "Failed to connect to weave factory data manager service."; |
| FX_CHECK(context->svc()->Connect(factory_store_provider_.NewRequest()) == ZX_OK) |
| << "Failed to connect to factory store"; |
| |
| err = EnvironmentConfig::Init(); |
| if (err != WEAVE_NO_ERROR) { |
| return err; |
| } |
| |
| // If the fail-safe was armed when the device last shutdown or weavestack crashed, |
| // erase weave data. |
| if (GetFailSafeArmed(fail_safe_armed) == WEAVE_NO_ERROR && fail_safe_armed) { |
| FX_LOGS(WARNING) |
| << "Fail safe was not disarmed before weavestack was shutdown, erasing Weave data."; |
| InitiateFactoryReset(); |
| } |
| |
| if (files::IsFile(kDeviceInfoRuntimePath)) { |
| err = device_info_->SetConfiguration(kDeviceInfoRuntimePath, kDeviceInfoSchemaPath, |
| /*should_replace*/ true); |
| // The runtime device info is primarily used for testing and is applied as best-effort. |
| // Failures are logged but proceed with the built-in configuration. |
| if (err != WEAVE_NO_ERROR) { |
| FX_LOGS(WARNING) << "Failed to apply runtime device info: " << ErrorStr(err); |
| } |
| } |
| |
| err = static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_)->_Init(); |
| if (err != WEAVE_NO_ERROR) { |
| return err; |
| } |
| |
| err = GetAndStoreHWInfo(); |
| if (err != WEAVE_NO_ERROR && err != WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND) { |
| return err; |
| } |
| |
| err = GetAndStorePairingCode(); |
| if (err != WEAVE_NO_ERROR && err != WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND) { |
| return err; |
| } |
| |
| return WEAVE_NO_ERROR; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetDeviceId(uint64_t& device_id) { |
| WEAVE_ERROR err = |
| EnvironmentConfig::ReadConfigValue(EnvironmentConfig::kConfigKey_MfrDeviceId, device_id); |
| if (err == WEAVE_NO_ERROR) { |
| return WEAVE_NO_ERROR; |
| } |
| |
| err = device_info_->ReadConfigValue(kDeviceInfoConfigKey_DeviceId, &device_id); |
| if (err != WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND) { |
| return err; |
| } |
| |
| char path[PATH_MAX] = {'\0'}; |
| size_t out_size; |
| err = device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_DeviceIdPath, path, sizeof(path), |
| &out_size); |
| if (err == WEAVE_NO_ERROR) { |
| err = GetDeviceIdFromFactory(path, &device_id); |
| FX_CHECK(err == WEAVE_NO_ERROR) << "Failed getting device id from factory at path: " << path; |
| impl_->StoreManufacturerDeviceId(device_id); |
| return err; |
| } |
| |
| err = GetDeviceIdFromFactory(path, &device_id); |
| if (err != WEAVE_NO_ERROR) { |
| return err; |
| } |
| |
| return impl_->StoreManufacturerDeviceId(device_id); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetManufacturerDeviceCertificate(uint8_t* buf, |
| size_t buf_size, |
| size_t& out_len) { |
| WEAVE_ERROR err = EnvironmentConfig::ReadConfigValueBin( |
| EnvironmentConfig::kConfigKey_MfrDeviceCert, buf, buf_size, out_len); |
| if (err == WEAVE_NO_ERROR) { |
| return err; |
| } |
| |
| err = GetAndStoreMfrDeviceCert(); |
| if (err != WEAVE_NO_ERROR) { |
| return err; |
| } |
| |
| return EnvironmentConfig::ReadConfigValueBin(EnvironmentConfig::kConfigKey_MfrDeviceCert, buf, |
| buf_size, out_len); |
| } |
| |
| bool ConfigurationManagerDelegateImpl::IsFullyProvisioned() { |
| return ConnectivityMgr().IsWiFiStationProvisioned() && |
| // TODO(fxbug.dev/58252) Due to incomplete implementation of ThreadStackManager, this |
| // predicate does not yet include the line `ConnectivityMgr().IsThreadProvisioned() &&`, |
| // but should once complete. |
| ConfigurationMgr().IsPairedToAccount() && ConfigurationMgr().IsMemberOfFabric(); |
| } |
| |
| bool ConfigurationManagerDelegateImpl::IsPairedToAccount() { |
| // By default, just use the generic implementation in Weave Device Layer. |
| return static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_) |
| ->_IsPairedToAccount(); |
| } |
| |
| bool ConfigurationManagerDelegateImpl::IsMemberOfFabric() { |
| // By default, just use the generic implementation in Weave Device Layer. |
| return static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_) |
| ->_IsMemberOfFabric(); |
| } |
| |
| GroupKeyStoreBase* ConfigurationManagerDelegateImpl::GetGroupKeyStore() { |
| return &group_key_store_; |
| } |
| |
| bool ConfigurationManagerDelegateImpl::CanFactoryReset() { return true; } |
| |
| void ConfigurationManagerDelegateImpl::InitiateFactoryReset() { |
| EnvironmentConfig::FactoryResetConfig(); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::ReadPersistedStorageValue(Key key, uint32_t& value) { |
| WEAVE_ERROR err = EnvironmentConfig::ReadConfigValue(key, value); |
| return (err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND) |
| ? WEAVE_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND |
| : err; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::WritePersistedStorageValue(Key key, uint32_t value) { |
| WEAVE_ERROR err = EnvironmentConfig::WriteConfigValue(key, value); |
| return (err != WEAVE_NO_ERROR) ? WEAVE_ERROR_PERSISTED_STORAGE_FAIL : err; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetVendorId(uint16_t& vendor_id) { |
| return device_info_->ReadConfigValue(kDeviceInfoConfigKey_VendorId, &vendor_id); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetProductId(uint16_t& product_id) { |
| return device_info_->ReadConfigValue(kDeviceInfoConfigKey_ProductId, &product_id); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetFirmwareRevision(char* buf, size_t buf_size, |
| size_t& out_len) { |
| return device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_FirmwareRevision, buf, buf_size, |
| &out_len); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetBleDeviceNamePrefix(char* device_name_prefix, |
| size_t device_name_prefix_size, |
| size_t* out_len) { |
| return device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_BleDeviceNamePrefix, |
| device_name_prefix, device_name_prefix_size, out_len); |
| } |
| |
| bool ConfigurationManagerDelegateImpl::IsThreadEnabled() { |
| bool is_enabled = false; |
| device_info_->ReadConfigValue(kDeviceInfoConfigKey_EnableThread, &is_enabled); |
| return is_enabled; |
| } |
| |
| bool ConfigurationManagerDelegateImpl::IsWoBLEEnabled() { |
| bool is_enabled = false; |
| device_info_->ReadConfigValue(kDeviceInfoConfigKey_EnableWoBLE, &is_enabled); |
| return is_enabled; |
| } |
| |
| bool ConfigurationManagerDelegateImpl::IsWoBLEAdvertisementEnabled() { |
| bool is_enabled = IsWoBLEEnabled(); |
| if (is_enabled) { |
| device_info_->ReadConfigValue(kDeviceInfoConfigKey_EnableWoBLEAdvertisement, &is_enabled); |
| } |
| return is_enabled; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetDeviceDescriptorTLV(uint8_t* buf, size_t buf_size, |
| size_t& encoded_len) { |
| return static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_) |
| ->_GetDeviceDescriptorTLV(buf, buf_size, encoded_len); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetAndStoreHWInfo() { |
| fuchsia::hwinfo::DeviceInfo device_info; |
| WEAVE_ERROR err; |
| char serial[ConfigurationManager::kMaxSerialNumberLength + 1]; |
| size_t serial_size = 0; |
| if (ZX_OK == hwinfo_device_->GetInfo(&device_info) && device_info.has_serial_number()) { |
| return impl_->StoreSerialNumber(device_info.serial_number().c_str(), |
| device_info.serial_number().length()); |
| } else if ((err = |
| device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_SerialNumber, serial, |
| ConfigurationManager::kMaxSerialNumberLength + 1, |
| &serial_size)) == WEAVE_NO_ERROR) { |
| return impl_->StoreSerialNumber(serial, serial_size); |
| } |
| return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetAndStorePairingCode() { |
| fuchsia::weave::FactoryDataManager_GetPairingCode_Result pairing_code_result; |
| fuchsia::weave::FactoryDataManager_GetPairingCode_Response pairing_code_response; |
| std::string pairing_code; |
| char read_value[ConfigurationManager::kMaxPairingCodeLength + 1]; |
| size_t read_value_size = 0; |
| WEAVE_ERROR err; |
| |
| // If a pairing code is provided in config-data, it takes precedent over the |
| // value provided by the factory data manager. |
| err = device_info_->ReadConfigValueStr(EnvironmentConfig::kConfigKey_PairingCode, read_value, |
| ConfigurationManager::kMaxPairingCodeLength + 1, |
| &read_value_size); |
| if (err == WEAVE_NO_ERROR) { |
| return impl_->StorePairingCode(read_value, read_value_size); |
| } |
| |
| // Otherwise, use the factory data manager as the source of truth. |
| zx_status_t status = weave_factory_data_manager_->GetPairingCode(&pairing_code_result); |
| if (ZX_OK != status || !pairing_code_result.is_response()) { |
| return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| pairing_code_response = pairing_code_result.response(); |
| if (pairing_code_response.pairing_code.size() > ConfigurationManager::kMaxPairingCodeLength) { |
| return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| return impl_->StorePairingCode((const char*)pairing_code_response.pairing_code.data(), |
| pairing_code_response.pairing_code.size()); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetAndStoreMfrDeviceCert() { |
| char path[PATH_MAX] = {'\0'}; |
| char mfr_cert[kWeaveCertificateMaxLength]; |
| std::string cert; |
| size_t out_size; |
| zx_status_t status; |
| WEAVE_ERROR err; |
| bool allow_local = false; |
| std::filesystem::path full_path(kDataPath); |
| |
| // Check if a test cert was provided and read the same. |
| err = EnvironmentConfig::ReadConfigValue(EnvironmentConfig::kConfigKey_MfrDeviceCertAllowLocal, |
| allow_local); |
| if (err != WEAVE_NO_ERROR) { |
| device_info_->ReadConfigValue(kDeviceInfoConfigKey_MfrDeviceCertAllowLocal, &allow_local); |
| } |
| if (allow_local) { |
| err = device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_MfrDeviceCertPath, path, |
| sizeof(path), &out_size); |
| if (err != WEAVE_NO_ERROR) { |
| FX_LOGS(ERROR) << "Local manufacturer cert path not found"; |
| return err; |
| } |
| |
| full_path.append(path); |
| if (!files::ReadFileToString(full_path.string(), &cert)) { |
| FX_LOGS(ERROR) << "failed reading " << path; |
| return ZX_ERR_INTERNAL; |
| } |
| |
| return impl_->StoreManufacturerDeviceCertificate(reinterpret_cast<uint8_t*>(cert.data()), |
| cert.size()); |
| } |
| |
| // Read file from factory. |
| err = device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_MfrDeviceCertPath, path, sizeof(path), |
| &out_size); |
| |
| if (err != WEAVE_NO_ERROR) { |
| FX_LOGS(ERROR) << "No manufacturer device certificate was found"; |
| return err; |
| } |
| |
| status = ReadFactoryFile(path, mfr_cert, sizeof(mfr_cert), &out_size); |
| if (status != ZX_OK) { |
| FX_LOGS(ERROR) << "Failed getting manufacturer certificate from factory with status " |
| << zx_status_get_string(status) << " for path: " << path; |
| return WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| } |
| |
| return impl_->StoreManufacturerDeviceCertificate(reinterpret_cast<uint8_t*>(mfr_cert), out_size); |
| } |
| |
| zx_status_t ConfigurationManagerDelegateImpl::GetPrivateKeyForSigning( |
| std::vector<uint8_t>* signing_key) { |
| char path[PATH_MAX] = {'\0'}; |
| std::filesystem::path full_path(kDataPath); |
| WEAVE_ERROR err; |
| size_t out_len; |
| |
| err = device_info_->ReadConfigValueStr(kDeviceInfoConfigKey_PrivateKeyPath, path, sizeof(path), |
| &out_len); |
| if (err == WEAVE_DEVICE_ERROR_CONFIG_NOT_FOUND) { |
| return ZX_ERR_NOT_FOUND; |
| } else if (err != WEAVE_NO_ERROR) { |
| FX_LOGS(ERROR) << "Failed to read private key."; |
| return ZX_ERR_INTERNAL; |
| } |
| |
| full_path.append(path); |
| if (!files::ReadFileToVector(full_path.string(), signing_key)) { |
| return ZX_ERR_INTERNAL; |
| } |
| return ZX_OK; |
| } |
| |
| zx_status_t ConfigurationManagerDelegateImpl::ReadFactoryFile(const char* path, char* buf, |
| size_t buf_size, size_t* out_len) { |
| fuchsia::io::DirectorySyncPtr factory_directory; |
| zx_status_t status; |
| struct stat statbuf; |
| int dir_fd; |
| |
| // Open the factory store directory as a file descriptor. |
| status = factory_store_provider_->GetFactoryStore(factory_directory.NewRequest()); |
| if (status != ZX_OK) { |
| FX_LOGS(ERROR) << "Failed to get factory store: " << zx_status_get_string(status); |
| return status; |
| } |
| status = fdio_fd_create(factory_directory.Unbind().TakeChannel().release(), &dir_fd); |
| if (status != ZX_OK || dir_fd < 0) { |
| FX_LOGS(ERROR) << "Failed to open factory store: " << zx_status_get_string(status); |
| return status; |
| } |
| |
| auto close_dir_defer = fit::defer([&] { close(dir_fd); }); |
| |
| // Grab the fd of the corresponding file path and validate. |
| int fd = openat(dir_fd, path, O_RDONLY); |
| if (fd < 0) { |
| FX_LOGS(ERROR) << "Failed to open " << path << ": " << strerror(errno); |
| return ZX_ERR_IO; |
| } |
| |
| auto close_fd_defer = fit::defer([&] { close(fd); }); |
| |
| // Check the size of the file. |
| if (fstat(fd, &statbuf) < 0) { |
| FX_LOGS(ERROR) << "Could not stat file: " << path << ": " << strerror(errno); |
| return ZX_ERR_IO; |
| } |
| size_t file_size = static_cast<size_t>(statbuf.st_size); |
| if (file_size > buf_size) { |
| FX_LOGS(ERROR) << "File too large for buffer: File size = " << file_size |
| << ", buffer size = " << buf_size; |
| return ZX_ERR_BUFFER_TOO_SMALL; |
| } |
| |
| // Read up to buf_size bytes into buf. |
| size_t total_read = 0; |
| ssize_t current_read = 0; |
| while ((current_read = read(fd, buf + total_read, buf_size - total_read)) > 0) { |
| total_read += current_read; |
| } |
| |
| // Store the total size read. |
| if (out_len) { |
| *out_len = total_read; |
| } |
| |
| // Confirm that the last read was successful. |
| if (current_read < 0) { |
| FX_LOGS(ERROR) << "Failed to read from file: " << strerror(errno); |
| status = ZX_ERR_IO; |
| } |
| |
| return status; |
| } |
| |
| zx_status_t ConfigurationManagerDelegateImpl::GetDeviceIdFromFactory(const char* path, |
| uint64_t* factory_device_id) { |
| zx_status_t status; |
| char output[kWeaveDeviceIdMaxLength + 1] = {'\0'}; |
| |
| status = ReadFactoryFile(path, output, kWeaveDeviceIdMaxLength, nullptr); |
| if (status != ZX_OK) { |
| FX_LOGS(ERROR) << "Failed to read " << path << ": " << zx_status_get_string(status); |
| return status; |
| } |
| |
| if (output[0] == '\0') { |
| FX_LOGS(ERROR) << "File containing device ID was empty."; |
| return ZX_ERR_IO; |
| } |
| |
| *factory_device_id = strtoull(output, NULL, 16); |
| if (errno == ERANGE) { |
| FX_LOGS(ERROR) << "Failed to strtoull device ID: " << strerror(errno); |
| return ZX_ERR_IO; |
| } |
| |
| return ZX_OK; |
| } |
| |
| zx_status_t ConfigurationManagerDelegateImpl::GetAppletPathList(std::vector<std::string>& out) { |
| return device_info_->ReadConfigValueArray(kDeviceInfoConfigKey_AppletPaths, out); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetPrimaryWiFiMACAddress(uint8_t* mac_address) { |
| // This is setting the MAC address to FF:0:0:0:0:0; this is for a few reasons: |
| // 1. The actual value of the MAC address in the descriptor is not currently used. |
| // 2. The MAC address is PII, so it should not be transmitted unless necessary. |
| // 3. Some value should still be transmitted as some tools or other devices use the presence of |
| // an WiFi MAC address to determine if WiFi is supported. |
| // The best way to meet these requirements is to provide a faked-out MAC address instead. |
| std::memcpy(mac_address, kFakeMacAddress, kWiFiMacAddressBufSize); |
| return WEAVE_NO_ERROR; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetThreadJoinableDuration(uint32_t* duration) { |
| return device_info_->ReadConfigValue(kDeviceInfoConfigKey_ThreadJoinableDurationSec, duration); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::GetFailSafeArmed(bool& fail_safe_armed) { |
| return static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_) |
| ->_GetFailSafeArmed(fail_safe_armed); |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::SetFailSafeArmed(bool fail_safe_armed) { |
| WEAVE_ERROR err = static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_) |
| ->_SetFailSafeArmed(fail_safe_armed); |
| std::string inspect_reason = WeaveInspector::kFailSafeReason_Nominal; |
| std::string inspect_status = fail_safe_armed ? WeaveInspector::kFailSafeState_Armed |
| : WeaveInspector::kFailSafeState_Disarmed; |
| if (err != WEAVE_NO_ERROR) { |
| inspect_reason = fail_safe_armed ? WeaveInspector::kFailSafeReason_FailsafeArmFailed |
| : WeaveInspector::kFailSafeReason_FailsafeDisarmFailed; |
| inspect_status = fail_safe_armed ? WeaveInspector::kFailSafeState_Disarmed |
| : WeaveInspector::kFailSafeState_Armed; |
| } |
| |
| auto& inspector = WeaveInspector::GetWeaveInspector(); |
| inspector.NotifyFailSafeStateChange(inspect_status, inspect_reason); |
| |
| return err; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::StoreFabricId(uint64_t fabric_id) { |
| WEAVE_ERROR err = static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_) |
| ->_StoreFabricId(fabric_id); |
| if (err != WEAVE_NO_ERROR) { |
| return err; |
| } |
| |
| auto& inspector = WeaveInspector::GetWeaveInspector(); |
| if (fabric_id != kFabricIdNotSpecified) { |
| inspector.NotifyPairingStateChange(WeaveInspector::kPairingState_FabricCreatedOrJoined); |
| return err; |
| } |
| inspector.NotifyPairingStateChange(WeaveInspector::kPairingState_LeftFabric); |
| return err; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::StoreServiceProvisioningData( |
| uint64_t service_id, const uint8_t* service_config, size_t service_config_len, |
| const char* account_id, size_t account_id_len) { |
| WEAVE_ERROR err = |
| static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_) |
| ->_StoreServiceProvisioningData(service_id, service_config, service_config_len, |
| account_id, account_id_len); |
| if (err != WEAVE_NO_ERROR) { |
| return err; |
| } |
| |
| auto& inspector = WeaveInspector::GetWeaveInspector(); |
| inspector.NotifyPairingStateChange(WeaveInspector::kPairingState_RegisterServicePending); |
| return err; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::StoreServiceConfig(const uint8_t* service_config, |
| size_t service_config_len) { |
| WEAVE_ERROR err = static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_) |
| ->_StoreServiceConfig(service_config, service_config_len); |
| if (err != WEAVE_NO_ERROR) { |
| return err; |
| } |
| |
| auto& inspector = WeaveInspector::GetWeaveInspector(); |
| inspector.NotifyPairingStateChange(WeaveInspector::kPairingState_ServiceConfigUpdated); |
| return err; |
| } |
| |
| WEAVE_ERROR ConfigurationManagerDelegateImpl::StorePairedAccountId(const char* account_id, |
| size_t account_id_len) { |
| WEAVE_ERROR err = static_cast<GenericConfigurationManagerImpl<ConfigurationManagerImpl>*>(impl_) |
| ->_StorePairedAccountId(account_id, account_id_len); |
| if (err != WEAVE_NO_ERROR) { |
| return err; |
| } |
| |
| auto& inspector = WeaveInspector::GetWeaveInspector(); |
| inspector.NotifyPairingStateChange(WeaveInspector::kPairingState_RegisterServiceCompleted); |
| return err; |
| } |
| |
| } // namespace DeviceLayer |
| } // namespace Weave |
| } // namespace nl |