diff --git a/src/app/clusters/network-commissioning/network-commissioning.cpp b/src/app/clusters/network-commissioning/network-commissioning.cpp index ff16ceeff50c6c..57c559ca8d4fb5 100644 --- a/src/app/clusters/network-commissioning/network-commissioning.cpp +++ b/src/app/clusters/network-commissioning/network-commissioning.cpp @@ -1152,28 +1152,57 @@ void Instance::HandleQueryIdentity(HandlerContext & ctx, const Commands::QueryId } #endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_PDC -Instance * Instance::NetworkRecord[CHIP_MAX_NETWORK_TYPES]; +Instance::InstanceRecord * Instance::sInstanceRecord = nullptr; void Instance::RecordNetwork(Instance * currentNetwork) { - for (size_t i = 0; i < CHIP_MAX_NETWORK_TYPES; ++i) + InstanceRecord * curr = sInstanceRecord; + while (curr) { - if (NetworkRecord[i] == nullptr) + if (curr->mInstance == currentNetwork) { - NetworkRecord[i] = currentNetwork; return; } + curr = curr->next; } + + InstanceRecord * newInstanceRecord = reinterpret_cast(Platform::MemoryAlloc(sizeof(InstanceRecord))); + newInstanceRecord->mInstance = currentNetwork; + newInstanceRecord->next = sInstanceRecord; + sInstanceRecord = newInstanceRecord; } void Instance::DisconnectOtherNetworks(Instance * currentNetwork) { - for (size_t i = 0; i < CHIP_MAX_NETWORK_TYPES; ++i) + InstanceRecord * curr = sInstanceRecord; + while (curr) { - if (NetworkRecord[i] != nullptr && NetworkRecord[i] != currentNetwork && NetworkRecord[i]->mpWirelessDriver) + if (curr->mInstance != currentNetwork && curr->mInstance->mpWirelessDriver) { - NetworkRecord[i]->mpWirelessDriver->DisconnectNetwork(); + uint8_t networkNo = 0; + uint8_t maxNetworks = curr->mInstance->mpBaseDriver->GetMaxNetworks(); + bool haveConnectedNetwork = false; + EnumerateAndRelease(curr->mInstance->mpBaseDriver->GetNetworks(), [&](const Network & network) { + if (network.connected) + { + haveConnectedNetwork = true; + return Loop::Break; + } + ++networkNo; + return (networkNo == maxNetworks) ? Loop::Break : Loop::Continue; + }); + + if (!haveConnectedNetwork) + { + /* It's different to check the media driver connection state here. + * Check the `Connected` flag in `NetworkInfoStruct` in stead, if not set, + * exec `DisconnectDriver` for driver. However, the physical media connection + * may not necessarily exist in this case, such as after initialization. + */ + curr->mInstance->mpWirelessDriver->DisconnectDriver(); + } } + curr = curr->next; } } diff --git a/src/app/clusters/network-commissioning/network-commissioning.h b/src/app/clusters/network-commissioning/network-commissioning.h index d6d13d5703d4ea..65bcc112281495 100644 --- a/src/app/clusters/network-commissioning/network-commissioning.h +++ b/src/app/clusters/network-commissioning/network-commissioning.h @@ -33,8 +33,6 @@ namespace app { namespace Clusters { namespace NetworkCommissioning { -#define CHIP_MAX_NETWORK_TYPES 3 - // TODO: Use macro to disable some wifi or thread class Instance : public CommandHandlerInterface, public AttributeAccessInterface, @@ -83,12 +81,19 @@ class Instance : public CommandHandlerInterface, void SendNonConcurrentConnectNetworkResponse(); #endif + class InstanceRecord + { + public: + Instance * mInstance; + InstanceRecord * next; + }; + // Array for recording NetworkCommissioningInstance. - static Instance * NetworkRecord[CHIP_MAX_NETWORK_TYPES]; + static InstanceRecord * sInstanceRecord; // Record current network. - static void RecordNetwork(Instance *currentNetwork); + static void RecordNetwork(Instance * currentNetwork); // Disconnect networks (if connected) in the array other than the current network. - static void DisconnectOtherNetworks(Instance *currentNetwork); + static void DisconnectOtherNetworks(Instance * currentNetwork); EndpointId mEndpointId = kInvalidEndpointId; const BitFlags mFeatureFlags; @@ -142,8 +147,26 @@ class Instance : public CommandHandlerInterface, Instance(EndpointId aEndpointId, DeviceLayer::NetworkCommissioning::WiFiDriver * apDelegate); Instance(EndpointId aEndpointId, DeviceLayer::NetworkCommissioning::ThreadDriver * apDelegate); Instance(EndpointId aEndpointId, DeviceLayer::NetworkCommissioning::EthernetDriver * apDelegate); - virtual ~Instance() = default; -}; + virtual ~Instance() + { + InstanceRecord * prev = nullptr; + InstanceRecord * curr = sInstanceRecord; + while (curr && curr->mInstance != this) + { + prev = curr; + curr = curr->next; + } + if (!prev) + { + sInstanceRecord = curr->next; + } + else + { + prev->next = curr->next; + } + Platform::MemoryFree(curr); + } +}; // namespace NetworkCommissioning // NetworkDriver for the devices that don't have / don't need a real network driver. class NullNetworkDriver : public DeviceLayer::NetworkCommissioning::EthernetDriver diff --git a/src/include/platform/NetworkCommissioning.h b/src/include/platform/NetworkCommissioning.h index 4e8e0fe98d9513..118b590b23449c 100644 --- a/src/include/platform/NetworkCommissioning.h +++ b/src/include/platform/NetworkCommissioning.h @@ -219,9 +219,9 @@ class WirelessDriver : public Internal::BaseDriver virtual CHIP_ERROR RevertConfiguration() = 0; /** - * @brief Disconnects network if it has connected. + * @brief Disconnects driver, but maybe it is not connected on media driver. */ - virtual CHIP_ERROR DisconnectNetwork() { return CHIP_NO_ERROR; } + virtual CHIP_ERROR DisconnectDriver() { return CHIP_NO_ERROR; } virtual uint8_t GetScanNetworkTimeoutSeconds() = 0; virtual uint8_t GetConnectNetworkTimeoutSeconds() = 0;