blob: c6babf25e5f74cb120cd416d6361556bd78820c6 [file] [log] [blame]
/*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* 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 <platform/internal/CHIPDeviceLayerInternal.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ConnectivityManager.h>
#include <platform/DiagnosticDataProvider.h>
#include <platform/bouffalolab/common/BLConfig.h>
#include <platform/bouffalolab/common/DiagnosticDataProviderImpl.h>
#include <platform/internal/BLEManager.h>
#include <platform/internal/GenericConnectivityManagerImpl_UDP.ipp>
#if INET_CONFIG_ENABLE_TCP_ENDPOINT
#include <platform/internal/GenericConnectivityManagerImpl_TCP.ipp>
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
#include <platform/internal/GenericConnectivityManagerImpl_WiFi.ipp>
#if CHIP_DEVICE_LAYER_TARGET_BL602
#include <platform/bouffalolab/BL602/NetworkCommissioningDriver.h>
#endif
#if CHIP_DEVICE_LAYER_TARGET_BL702
#include <platform/bouffalolab/BL702/NetworkCommissioningDriver.h>
#endif
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
#include <platform/internal/BLEManager.h>
#include <platform/internal/GenericConnectivityManagerImpl_BLE.ipp>
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
#include <platform/internal/GenericConnectivityManagerImpl_Thread.ipp>
#endif
using namespace ::chip;
using namespace ::chip::Inet;
using namespace ::chip::System;
using namespace ::chip::DeviceLayer::Internal;
namespace chip {
namespace DeviceLayer {
ConnectivityManagerImpl ConnectivityManagerImpl::sInstance;
CHIP_ERROR ConnectivityManagerImpl::_Init()
{
// Initialize the generic base classes that require it.
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_Init();
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
mWiFiStationState = ConnectivityManager::kWiFiStationState_NotConnected;
ReturnErrorOnFailure(SetWiFiStationMode(kWiFiStationMode_Enabled));
PlatformMgr().AddEventHandler(NetworkCommissioning::NetworkEventHandler, 0);
#endif
return CHIP_NO_ERROR;
}
void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
{
// Forward the event to the generic base classes as needed.
#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_OnPlatformEvent(event);
#endif
}
#if CHIP_DEVICE_CONFIG_ENABLE_WIFI
bool ConnectivityManagerImpl::_IsWiFiStationEnabled(void)
{
return GetWiFiStationMode() == kWiFiStationMode_Enabled;
}
bool ConnectivityManagerImpl::_IsWiFiStationProvisioned(void)
{
CHIP_ERROR err = CHIP_NO_ERROR;
char ssid[64] = { 0 };
char psk[64] = { 0 };
size_t ssidLen = 0;
size_t pskLen = 0;
err = PersistedStorage::KeyValueStoreMgr().Get(BLConfig::kConfigKey_WiFiSSID, (void *) ssid, 64, &ssidLen, 0);
SuccessOrExit(err);
err = PersistedStorage::KeyValueStoreMgr().Get(BLConfig::kConfigKey_WiFiPassword, (void *) psk, 64, &pskLen, 0);
SuccessOrExit(err);
return (ssidLen != 0);
exit:
return false;
}
CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(WiFiStationMode val)
{
CHIP_ERROR err = CHIP_NO_ERROR;
VerifyOrExit(val != kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
if (val != kWiFiStationMode_ApplicationControlled)
{
DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL);
}
if (mWiFiStationMode != val)
{
ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode),
WiFiStationModeToStr(val));
}
mWiFiStationMode = val;
exit:
return err;
}
void ConnectivityManagerImpl::ChangeWiFiStationState(WiFiStationState newState)
{
if (mWiFiStationState != newState)
{
ChipLogProgress(DeviceLayer, "WiFi station state change: %s -> %s", WiFiStationStateToStr(mWiFiStationState),
WiFiStationStateToStr(newState));
mWiFiStationState = newState;
ConnectivityMgrImpl().DriveStationState();
SystemLayer().ScheduleLambda([]() { NetworkCommissioning::BLWiFiDriver::GetInstance().OnNetworkStatusChange(); });
}
}
void ConnectivityManagerImpl::_ClearWiFiStationProvision(void)
{
CHIP_ERROR err = CHIP_NO_ERROR;
err = PersistedStorage::KeyValueStoreMgr().Delete(BLConfig::kConfigKey_WiFiSSID);
SuccessOrExit(err);
err = PersistedStorage::KeyValueStoreMgr().Delete(BLConfig::kConfigKey_WiFiPassword);
SuccessOrExit(err);
exit:
return;
}
void ConnectivityManagerImpl::_OnWiFiStationProvisionChange(void)
{
DeviceLayer::SystemLayer().ScheduleWork(DriveStationState, NULL);
}
CHIP_ERROR ConnectivityManagerImpl::ConnectProvisionedWiFiNetwork(void)
{
char ssid[64] = { 0 };
char psk[64] = { 0 };
size_t ssidLen = 0;
size_t pskLen = 0;
ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Get(BLConfig::kConfigKey_WiFiSSID, (void *) ssid, 64, &ssidLen, 0));
ReturnErrorOnFailure(PersistedStorage::KeyValueStoreMgr().Get(BLConfig::kConfigKey_WiFiPassword, (void *) psk, 64, &pskLen, 0));
NetworkCommissioning::BLWiFiDriver::GetInstance().ConnectWiFiNetwork(ssid, ssidLen, psk, pskLen);
return CHIP_NO_ERROR;
}
void ConnectivityManagerImpl::OnWiFiStationConnected()
{
ChipDeviceEvent event;
event.Type = DeviceEventType::kWiFiConnectivityChange;
event.WiFiConnectivityChange.Result = kConnectivity_Established;
PlatformMgr().PostEventOrDie(&event);
WiFiDiagnosticsDelegate * delegate = GetDiagnosticDataProvider().GetWiFiDiagnosticsDelegate();
if (delegate)
{
delegate->OnConnectionStatusChanged(
chip::to_underlying(chip::app::Clusters::WiFiNetworkDiagnostics::ConnectionStatusEnum::kConnected));
}
}
void ConnectivityManagerImpl::DriveStationState()
{
ChipLogProgress(DeviceLayer, "DriveStationState: mWiFiStationState=%s", WiFiStationStateToStr(mWiFiStationState));
switch (mWiFiStationState)
{
case ConnectivityManager::kWiFiStationState_NotConnected: {
if (GetWiFiStationMode() == ConnectivityManager::kWiFiStationMode_Enabled && IsWiFiStationProvisioned())
{
ConnectProvisionedWiFiNetwork();
}
}
break;
case ConnectivityManager::kWiFiStationState_Connecting: {
ChipLogProgress(DeviceLayer, "Wi-Fi station is connecting to AP");
}
break;
case ConnectivityManager::kWiFiStationState_Connecting_Succeeded: {
ChipLogProgress(DeviceLayer, "Wi-Fi station successfully connects to AP");
mConnectivityFlag.ClearAll();
mConnectivityFlag.Set(ConnectivityFlags::kAwaitingConnectivity);
}
break;
case ConnectivityManager::kWiFiStationState_Connecting_Failed: {
ChipLogProgress(DeviceLayer, "Wi-Fi station connecting failed");
mConnectivityFlag.ClearAll();
OnWiFiStationDisconnected();
if (ConnectivityManager::kWiFiStationState_Connecting == mWiFiStationState)
{
SystemLayer().ScheduleLambda([]() { NetworkCommissioning::BLWiFiDriver::GetInstance().OnConnectWiFiNetwork(false); });
}
}
break;
case ConnectivityManager::kWiFiStationState_Connected: {
ChipLogProgress(DeviceLayer, "Wi-Fi station connected.");
OnWiFiStationConnected();
SystemLayer().ScheduleLambda([]() { NetworkCommissioning::BLWiFiDriver::GetInstance().OnConnectWiFiNetwork(true); });
}
break;
case ConnectivityManager::kWiFiStationState_Disconnecting: {
ChipLogProgress(DeviceLayer, "Wi-Fi station is disconnecting to AP");
mConnectivityFlag.ClearAll();
}
break;
default:
break;
}
}
void ConnectivityManagerImpl::DriveStationState(::chip::System::Layer * aLayer, void * aAppState)
{
ConnectivityMgrImpl().DriveStationState();
}
#endif
#if CHIP_DEVICE_CONFIG_ENABLE_ETHERNET || CHIP_DEVICE_CONFIG_ENABLE_WIFI
void ConnectivityManagerImpl::OnConnectivityChanged(struct netif * interface)
{
bool haveIPv4Conn = false;
bool haveIPv6Conn = false;
const bool hadIPv4Conn = mConnectivityFlag.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity);
const bool hadIPv6Conn = mConnectivityFlag.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity);
IPAddress addr;
if (interface != NULL && netif_is_up(interface) && netif_is_link_up(interface))
{
mConnectivityFlag.Clear(ConnectivityFlags::kAwaitingConnectivity);
if (!ip4_addr_isany(netif_ip4_addr(interface)) && !ip4_addr_isany(netif_ip4_gw(interface)))
{
haveIPv4Conn = true;
char addrStr[INET_ADDRSTRLEN];
ip4addr_ntoa_r(netif_ip4_addr(interface), addrStr, sizeof(addrStr));
IPAddress::FromString(addrStr, addr);
if (0 != memcmp(netif_ip4_addr(interface), &m_ip4addr, sizeof(ip4_addr_t)))
{
ChipLogProgress(DeviceLayer, "IPv4 Address Assigned, %s", ip4addr_ntoa(netif_ip4_addr(interface)));
memcpy(&m_ip4addr, netif_ip4_addr(interface), sizeof(ip4_addr_t));
ConnectivityMgrImpl().OnIPv4AddressAvailable();
}
}
// Search among the IPv6 addresses assigned to the interface for a Global Unicast
// address (2000::/3) that is in the valid state. If such an address is found...
for (uint32_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++)
{
if (!ip6_addr_islinklocal(netif_ip6_addr(interface, i)) && ip6_addr_isvalid(netif_ip6_addr_state(interface, i)))
{
haveIPv6Conn = true;
if (0 != memcmp(netif_ip6_addr(interface, i), m_ip6addr + i, sizeof(ip6_addr_t)))
{
ChipLogProgress(DeviceLayer, "IPv6 Address Assigned, %s", ip6addr_ntoa(netif_ip6_addr(interface, i)));
memcpy(m_ip6addr + i, netif_ip6_addr(interface, i), sizeof(ip6_addr_t));
ConnectivityMgrImpl().OnIPv6AddressAvailable();
}
}
}
}
// If the internet connectivity state has changed...
if (haveIPv4Conn != hadIPv4Conn || haveIPv6Conn != hadIPv6Conn)
{
// Update the current state.
mConnectivityFlag.Set(ConnectivityFlags::kHaveIPv4InternetConnectivity, haveIPv4Conn);
mConnectivityFlag.Set(ConnectivityFlags::kHaveIPv6InternetConnectivity, haveIPv6Conn);
// Alert other components of the state change.
ChipDeviceEvent event;
event.Type = DeviceEventType::kInternetConnectivityChange;
event.InternetConnectivityChange.IPv4 = GetConnectivityChange(hadIPv4Conn, haveIPv4Conn);
event.InternetConnectivityChange.IPv6 = GetConnectivityChange(hadIPv6Conn, haveIPv6Conn);
event.InternetConnectivityChange.ipAddress = addr;
PlatformMgr().PostEventOrDie(&event);
if (haveIPv4Conn != hadIPv4Conn)
{
memset(&m_ip4addr, 0, sizeof(ip4_addr_t));
ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv4", (haveIPv4Conn) ? "ESTABLISHED" : "LOST");
}
if (haveIPv6Conn != hadIPv6Conn)
{
memset(&m_ip6addr, 0, sizeof(ip6_addr_t) * LWIP_IPV6_NUM_ADDRESSES);
ChipLogProgress(DeviceLayer, "%s Internet connectivity %s", "IPv6", (haveIPv6Conn) ? "ESTABLISHED" : "LOST");
}
}
}
void ConnectivityManagerImpl::OnIPv4AddressAvailable()
{
ChipDeviceEvent event;
event.Type = DeviceEventType::kInterfaceIpAddressChanged;
event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV4_Assigned;
PlatformMgr().PostEventOrDie(&event);
}
void ConnectivityManagerImpl::OnIPv6AddressAvailable()
{
ChipDeviceEvent event;
event.Type = DeviceEventType::kInterfaceIpAddressChanged;
event.InterfaceIpAddressChanged.Type = InterfaceIpChangeType::kIpV6_Assigned;
PlatformMgr().PostEventOrDie(&event);
}
#endif
} // namespace DeviceLayer
} // namespace chip