/* * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include "NetworkCommissioningDriver.h" #include "WiFiManager.h" namespace chip { namespace DeviceLayer { namespace NetworkCommissioning { #if CHIP_DEVICE_CONFIG_ENABLE_WIFI namespace { constexpr char kWiFiSSIDKeyName[] = "wifi-ssid"; constexpr char kWiFiCredentialsKeyName[] = "wifi-pass"; } // namespace CHIP_ERROR TizenWiFiDriver::Init(BaseDriver::NetworkStatusChangeCallback * networkStatusChangeCallback) { CHIP_ERROR err; size_t ssidLen = 0; size_t credentialsLen = 0; err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiCredentialsKeyName, mSavedNetwork.credentials, sizeof(mSavedNetwork.credentials), &credentialsLen); if (err == CHIP_ERROR_NOT_FOUND) { return CHIP_NO_ERROR; } err = PersistedStorage::KeyValueStoreMgr().Get(kWiFiSSIDKeyName, mSavedNetwork.ssid, sizeof(mSavedNetwork.ssid), &ssidLen); if (err == CHIP_ERROR_NOT_FOUND) { return CHIP_NO_ERROR; } static_assert(sizeof(mSavedNetwork.credentials) <= UINT8_MAX, "credentialsLen might not fit"); mSavedNetwork.credentialsLen = static_cast(credentialsLen); static_assert(sizeof(mSavedNetwork.ssid) <= UINT8_MAX, "ssidLen might not fit"); mSavedNetwork.ssidLen = static_cast(ssidLen); mStagingNetwork = mSavedNetwork; return err; } CHIP_ERROR TizenWiFiDriver::CommitConfiguration() { ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiSSIDKeyName, mStagingNetwork.ssid, mStagingNetwork.ssidLen)); ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Put(kWiFiCredentialsKeyName, mStagingNetwork.credentials, mStagingNetwork.credentialsLen)); mSavedNetwork = mStagingNetwork; return CHIP_NO_ERROR; } CHIP_ERROR TizenWiFiDriver::RevertConfiguration() { mStagingNetwork = mSavedNetwork; return CHIP_NO_ERROR; } bool TizenWiFiDriver::NetworkMatch(const WiFiNetwork & network, ByteSpan networkId) { return networkId.size() == network.ssidLen && memcmp(networkId.data(), network.ssid, network.ssidLen) == 0; } Status TizenWiFiDriver::AddOrUpdateNetwork(ByteSpan ssid, ByteSpan credentials, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) { outDebugText.reduce_size(0); outNetworkIndex = 0; VerifyOrReturnError(mStagingNetwork.ssidLen == 0 || NetworkMatch(mStagingNetwork, ssid), Status::kBoundsExceeded); static_assert(sizeof(WiFiNetwork::ssid) <= std::numeric_limits::max(), "Max length of WiFi ssid exceeds the limit of ssidLen field"); static_assert(sizeof(WiFiNetwork::credentials) <= std::numeric_limits::max(), "Max length of WiFi credentials exceeds the limit of credentialsLen field"); VerifyOrReturnError(credentials.size() <= sizeof(mStagingNetwork.credentials), Status::kOutOfRange); VerifyOrReturnError(ssid.size() <= sizeof(mStagingNetwork.ssid), Status::kOutOfRange); memcpy(mStagingNetwork.credentials, credentials.data(), credentials.size()); mStagingNetwork.credentialsLen = static_cast(credentials.size()); memcpy(mStagingNetwork.ssid, ssid.data(), ssid.size()); mStagingNetwork.ssidLen = static_cast(ssid.size()); return Status::kSuccess; } Status TizenWiFiDriver::RemoveNetwork(ByteSpan networkId, MutableCharSpan & outDebugText, uint8_t & outNetworkIndex) { outDebugText.reduce_size(0); outNetworkIndex = 0; VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); // Use empty ssid for representing invalid network mStagingNetwork.ssidLen = 0; return Status::kSuccess; } Status TizenWiFiDriver::ReorderNetwork(ByteSpan networkId, uint8_t index, MutableCharSpan & outDebugText) { outDebugText.reduce_size(0); VerifyOrReturnError(NetworkMatch(mStagingNetwork, networkId), Status::kNetworkIDNotFound); // We only support one network, so reorder is actually no-op. return Status::kSuccess; } void TizenWiFiDriver::ConnectNetwork(ByteSpan networkId, ConnectCallback * callback) { CHIP_ERROR err = CHIP_NO_ERROR; Status networkingStatus = Status::kSuccess; VerifyOrExit(NetworkMatch(mStagingNetwork, networkId), networkingStatus = Status::kNetworkIDNotFound); ChipLogProgress(NetworkProvisioning, "TizenNetworkCommissioningDelegate: SSID: %.*s", static_cast(sizeof(mStagingNetwork.ssid)), reinterpret_cast(mStagingNetwork.ssid)); err = DeviceLayer::Internal::WiFiMgr().Connect(reinterpret_cast(mStagingNetwork.ssid), reinterpret_cast(mStagingNetwork.credentials), callback); exit: if (err != CHIP_NO_ERROR) { networkingStatus = Status::kUnknownError; } if (networkingStatus != Status::kSuccess) { ChipLogError(NetworkProvisioning, "Failed to connect to WiFi network: %s", chip::ErrorStr(err)); callback->OnResult(networkingStatus, CharSpan(), 0); } } void TizenWiFiDriver::ScanNetworks(ByteSpan ssid, WiFiDriver::ScanCallback * callback) { CHIP_ERROR err = DeviceLayer::Internal::WiFiMgr().StartWiFiScan(ssid, callback); if (err != CHIP_NO_ERROR) { callback->OnFinished(Status::kUnknownError, CharSpan(), nullptr); } } uint32_t TizenWiFiDriver::GetSupportedWiFiBandsMask() const { return static_cast((1UL << chip::to_underlying(WiFiBandEnum::k2g4)) | (1UL << chip::to_underlying(WiFiBandEnum::k5g))); } size_t TizenWiFiDriver::WiFiNetworkIterator::Count() { return driver->mStagingNetwork.ssidLen == 0 ? 0 : 1; } bool TizenWiFiDriver::WiFiNetworkIterator::Next(Network & item) { if (exhausted || driver->mStagingNetwork.ssidLen == 0) { return false; } memcpy(item.networkID, driver->mStagingNetwork.ssid, driver->mStagingNetwork.ssidLen); item.networkIDLen = driver->mStagingNetwork.ssidLen; item.connected = false; exhausted = true; Network configuredNetwork; CHIP_ERROR err = DeviceLayer::Internal::WiFiMgr().GetConfiguredNetwork(configuredNetwork); if (err == CHIP_NO_ERROR) { if (DeviceLayer::Internal::WiFiMgr().IsWiFiStationConnected() && configuredNetwork.networkIDLen == item.networkIDLen && memcmp(configuredNetwork.networkID, item.networkID, item.networkIDLen) == 0) { item.connected = true; } } return true; } #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI } // namespace NetworkCommissioning } // namespace DeviceLayer } // namespace chip