3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2019 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #include <platform/internal/CHIPDeviceLayerInternal.h>
21 #include <platform/ConnectivityManager.h>
22 #include <platform/internal/BLEManager.h>
27 #include <support/CodeUtils.h>
28 #include <support/logging/CHIPLogging.h>
30 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
31 #include <platform/internal/GenericConnectivityManagerImpl_BLE.cpp>
34 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
35 #include <platform/internal/GenericConnectivityManagerImpl_Thread.cpp>
38 #if CHIP_DEVICE_CONFIG_ENABLE_WPA
39 #include <platform/internal/GenericConnectivityManagerImpl_WiFi.cpp>
42 using namespace ::chip;
43 using namespace ::chip::TLV;
44 using namespace ::chip::DeviceLayer::Internal;
46 #if CHIP_DEVICE_CONFIG_ENABLE_WPA
48 const char kWpaSupplicantServiceName[] = "fi.w1.wpa_supplicant1";
49 const char kWpaSupplicantObjectPath[] = "/fi/w1/wpa_supplicant1";
51 constexpr uint16_t kWiFi_BAND_2_4_GHZ = 2400;
52 constexpr uint16_t kWiFi_BAND_5_0_GHZ = 5000;
54 uint16_t Map2400MHz(const uint8_t inChannel)
56 uint16_t frequency = 0;
58 if (inChannel >= 1 && inChannel <= 13)
60 frequency = static_cast<uint16_t>(2412 + ((inChannel - 1) * 5));
62 else if (inChannel == 14)
70 uint16_t Map5000MHz(const uint8_t inChannel)
72 uint16_t frequency = 0;
208 static uint16_t MapFrequency(const uint16_t inBand, const uint8_t inChannel)
210 uint16_t frequency = 0;
212 if (inBand == kWiFi_BAND_2_4_GHZ)
214 frequency = Map2400MHz(inChannel);
216 else if (inBand == kWiFi_BAND_5_0_GHZ)
218 frequency = Map5000MHz(inChannel);
227 namespace DeviceLayer {
229 ConnectivityManagerImpl ConnectivityManagerImpl::sInstance;
231 CHIP_ERROR ConnectivityManagerImpl::_Init()
233 CHIP_ERROR err = CHIP_NO_ERROR;
235 mWiFiStationMode = kWiFiStationMode_Disabled;
236 mWiFiStationReconnectIntervalMS = CHIP_DEVICE_CONFIG_WIFI_STATION_RECONNECT_INTERVAL;
238 // Initialize the generic base classes that require it.
239 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
240 GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_Init();
249 void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
251 // Forward the event to the generic base classes as needed.
252 #if CHIP_DEVICE_CONFIG_ENABLE_THREAD
253 GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_OnPlatformEvent(event);
257 #if CHIP_DEVICE_CONFIG_ENABLE_WPA
259 BitFlags<Internal::GenericConnectivityManagerImpl_WiFi<ConnectivityManagerImpl>::ConnectivityFlags>
260 ConnectivityManagerImpl::mConnectivityFlag;
261 struct GDBusWpaSupplicant ConnectivityManagerImpl::mWpaSupplicant;
263 bool ConnectivityManagerImpl::_HaveIPv4InternetConnectivity()
265 return mConnectivityFlag.Has(ConnectivityFlags::kHaveIPv4InternetConnectivity);
268 bool ConnectivityManagerImpl::_HaveIPv6InternetConnectivity()
270 return mConnectivityFlag.Has(ConnectivityFlags::kHaveIPv6InternetConnectivity);
273 ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode()
275 if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
277 mWiFiStationMode = (mWpaSupplicant.iface != nullptr) ? kWiFiStationMode_Enabled : kWiFiStationMode_Disabled;
280 return mWiFiStationMode;
283 CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(ConnectivityManager::WiFiStationMode val)
285 CHIP_ERROR err = CHIP_NO_ERROR;
287 VerifyOrExit(val != ConnectivityManager::kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
289 if (mWiFiStationMode != val)
291 ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode),
292 WiFiStationModeToStr(val));
295 mWiFiStationMode = val;
300 uint32_t ConnectivityManagerImpl::_GetWiFiStationReconnectIntervalMS()
302 return mWiFiStationReconnectIntervalMS;
305 CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationReconnectIntervalMS(uint32_t val)
307 mWiFiStationReconnectIntervalMS = val;
309 return CHIP_NO_ERROR;
312 bool ConnectivityManagerImpl::_IsWiFiStationEnabled()
314 return GetWiFiStationMode() == kWiFiStationMode_Enabled;
317 bool ConnectivityManagerImpl::_IsWiFiStationConnected()
320 const gchar * state = nullptr;
322 if (mWpaSupplicant.state != GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED)
324 ChipLogProgress(DeviceLayer, "wpa_supplicant: _IsWiFiStationConnected: interface not connected");
328 state = wpa_fi_w1_wpa_supplicant1_interface_get_state(mWpaSupplicant.iface);
329 if (g_strcmp0(state, "completed") == 0)
331 mConnectivityFlag.Set(ConnectivityFlags::kHaveIPv4InternetConnectivity)
332 .Set(ConnectivityFlags::kHaveIPv6InternetConnectivity);
339 bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled()
341 return mWiFiStationMode == ConnectivityManager::kWiFiStationMode_ApplicationControlled;
344 bool ConnectivityManagerImpl::_IsWiFiStationProvisioned()
347 const gchar * bss = nullptr;
349 if (mWpaSupplicant.state != GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED)
351 ChipLogProgress(DeviceLayer, "wpa_supplicant: _IsWiFiStationProvisioned: interface not connected");
355 bss = wpa_fi_w1_wpa_supplicant1_interface_get_current_bss(mWpaSupplicant.iface);
356 if (g_str_match_string("BSSs", bss, true))
364 void ConnectivityManagerImpl::_ClearWiFiStationProvision()
366 if (mWpaSupplicant.state != GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED)
368 ChipLogProgress(DeviceLayer, "wpa_supplicant: _ClearWiFiStationProvision: interface not connected");
372 if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
374 GError * err = nullptr;
375 wpa_fi_w1_wpa_supplicant1_interface_call_remove_all_networks_sync(mWpaSupplicant.iface, nullptr, &err);
379 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to remove all networks with error: %s",
380 err ? err->message : "unknown error");
386 bool ConnectivityManagerImpl::_CanStartWiFiScan()
388 return mWpaSupplicant.state == GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED &&
389 mWpaSupplicant.scanState == GDBusWpaSupplicant::WIFI_SCANNING_IDLE;
392 CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val)
394 CHIP_ERROR err = CHIP_NO_ERROR;
396 VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
398 if (mWiFiAPMode != val)
400 ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val));
403 SystemLayer.ScheduleWork(DriveAPState, NULL);
410 void ConnectivityManagerImpl::_DemandStartWiFiAP()
412 if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
414 ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand start WiFi AP");
415 mLastAPDemandTime = System::Layer::GetClock_MonotonicMS();
416 SystemLayer.ScheduleWork(DriveAPState, NULL);
420 ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand start WiFi AP ignored, mode: %s", WiFiAPModeToStr(mWiFiAPMode));
424 void ConnectivityManagerImpl::_StopOnDemandWiFiAP()
426 if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
428 ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand stop WiFi AP");
429 mLastAPDemandTime = 0;
430 SystemLayer.ScheduleWork(DriveAPState, NULL);
434 ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand stop WiFi AP ignored, mode: %s", WiFiAPModeToStr(mWiFiAPMode));
438 void ConnectivityManagerImpl::_MaintainOnDemandWiFiAP()
440 if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
442 if (mWiFiAPState == kWiFiAPState_Active)
444 mLastAPDemandTime = System::Layer::GetClock_MonotonicMS();
449 void ConnectivityManagerImpl::_SetWiFiAPIdleTimeoutMS(uint32_t val)
451 mWiFiAPIdleTimeoutMS = val;
452 SystemLayer.ScheduleWork(DriveAPState, NULL);
455 void ConnectivityManagerImpl::_OnWpaInterfaceProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data)
457 GError * err = nullptr;
458 WpaFiW1Wpa_supplicant1Interface * iface = wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus_finish(res, &err);
460 if (mWpaSupplicant.iface)
462 g_object_unref(mWpaSupplicant.iface);
463 mWpaSupplicant.iface = nullptr;
466 if (iface != nullptr && err == nullptr)
468 mWpaSupplicant.iface = iface;
469 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED;
470 ChipLogProgress(DeviceLayer, "wpa_supplicant: connected to wpa_supplicant interface proxy");
474 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to create wpa_supplicant1 interface proxy %s: %s",
475 mWpaSupplicant.interfacePath, err ? err->message : "unknown error");
477 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_NOT_CONNECTED;
484 void ConnectivityManagerImpl::_OnWpaInterfaceReady(GObject * source_object, GAsyncResult * res, gpointer user_data)
486 GError * err = nullptr;
489 wpa_fi_w1_wpa_supplicant1_call_get_interface_finish(mWpaSupplicant.proxy, &mWpaSupplicant.interfacePath, res, &err);
492 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_GOT_INTERFACE_PATH;
493 ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface: %s", mWpaSupplicant.interfacePath);
495 wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName,
496 mWpaSupplicant.interfacePath, nullptr, _OnWpaInterfaceProxyReady,
501 GError * error = nullptr;
502 GVariant * args = nullptr;
503 GVariantBuilder builder;
505 ChipLogProgress(DeviceLayer, "wpa_supplicant: can't find interface %s: %s", CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME,
506 err ? err->message : "unknown error");
508 ChipLogProgress(DeviceLayer, "wpa_supplicant: try to create interface %s", CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME);
510 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
511 g_variant_builder_add(&builder, "{sv}", "Ifname", g_variant_new_string(CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME));
512 args = g_variant_builder_end(&builder);
514 result = wpa_fi_w1_wpa_supplicant1_call_create_interface_sync(mWpaSupplicant.proxy, args, &mWpaSupplicant.interfacePath,
519 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_GOT_INTERFACE_PATH;
520 ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface: %s", mWpaSupplicant.interfacePath);
522 wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
523 kWpaSupplicantServiceName, mWpaSupplicant.interfacePath, nullptr,
524 _OnWpaInterfaceProxyReady, nullptr);
528 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to create interface %s: %s",
529 CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME, error ? error->message : "unknown error");
531 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_NO_INTERFACE_PATH;
533 if (mWpaSupplicant.interfacePath)
535 g_free(mWpaSupplicant.interfacePath);
536 mWpaSupplicant.interfacePath = nullptr;
540 if (error != nullptr)
548 void ConnectivityManagerImpl::_OnWpaInterfaceAdded(WpaFiW1Wpa_supplicant1 * proxy, const gchar * path, GVariant * properties,
551 if (mWpaSupplicant.interfacePath)
554 mWpaSupplicant.interfacePath = const_cast<gchar *>(path);
555 if (mWpaSupplicant.interfacePath)
557 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_GOT_INTERFACE_PATH;
558 ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface added: %s", mWpaSupplicant.interfacePath);
560 wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName,
561 mWpaSupplicant.interfacePath, nullptr, _OnWpaInterfaceProxyReady,
566 void ConnectivityManagerImpl::_OnWpaInterfaceRemoved(WpaFiW1Wpa_supplicant1 * proxy, const gchar * path, GVariant * properties,
569 if (mWpaSupplicant.interfacePath == nullptr)
572 if (g_strcmp0(mWpaSupplicant.interfacePath, path) == 0)
574 ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface removed: %s", path);
576 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_NO_INTERFACE_PATH;
578 if (mWpaSupplicant.interfacePath)
580 g_free(mWpaSupplicant.interfacePath);
581 mWpaSupplicant.interfacePath = nullptr;
584 if (mWpaSupplicant.iface)
586 g_object_unref(mWpaSupplicant.iface);
587 mWpaSupplicant.iface = nullptr;
590 mWpaSupplicant.scanState = GDBusWpaSupplicant::WIFI_SCANNING_IDLE;
594 void ConnectivityManagerImpl::_OnWpaProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data)
596 GError * err = nullptr;
598 mWpaSupplicant.proxy = wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus_finish(res, &err);
599 if (mWpaSupplicant.proxy != nullptr && err == nullptr)
601 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_CONNECTED;
602 ChipLogProgress(DeviceLayer, "wpa_supplicant: connected to wpa_supplicant proxy");
604 g_signal_connect(mWpaSupplicant.proxy, "interface-added", G_CALLBACK(_OnWpaInterfaceAdded), NULL);
606 g_signal_connect(mWpaSupplicant.proxy, "interface-removed", G_CALLBACK(_OnWpaInterfaceRemoved), NULL);
608 wpa_fi_w1_wpa_supplicant1_call_get_interface(mWpaSupplicant.proxy, CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME, nullptr,
609 _OnWpaInterfaceReady, nullptr);
613 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to create wpa_supplicant proxy %s",
614 err ? err->message : "unknown error");
615 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_NOT_CONNECTED;
622 void ConnectivityManagerImpl::StartWiFiManagement()
624 mConnectivityFlag.ClearAll();
625 mWpaSupplicant.state = GDBusWpaSupplicant::INIT;
626 mWpaSupplicant.scanState = GDBusWpaSupplicant::WIFI_SCANNING_IDLE;
627 mWpaSupplicant.proxy = nullptr;
628 mWpaSupplicant.iface = nullptr;
629 mWpaSupplicant.interfacePath = nullptr;
630 mWpaSupplicant.networkPath = nullptr;
632 wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName,
633 kWpaSupplicantObjectPath, nullptr, _OnWpaProxyReady, nullptr);
636 void ConnectivityManagerImpl::DriveAPState()
638 CHIP_ERROR err = CHIP_NO_ERROR;
639 WiFiAPState targetState;
643 // If the AP interface is not under application control...
644 if (mWiFiAPMode != kWiFiAPMode_ApplicationControlled)
646 // Determine the target (desired) state for AP interface...
648 // The target state is 'NotActive' if the application has expressly disabled the AP interface.
649 if (mWiFiAPMode == kWiFiAPMode_Disabled)
651 targetState = kWiFiAPState_NotActive;
654 // The target state is 'Active' if the application has expressly enabled the AP interface.
655 else if (mWiFiAPMode == kWiFiAPMode_Enabled)
657 targetState = kWiFiAPState_Active;
660 // The target state is 'Active' if the AP mode is 'On demand, when no station is available'
661 // and the station interface is not provisioned or the application has disabled the station
663 else if (mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision &&
664 (!IsWiFiStationProvisioned() || GetWiFiStationMode() == kWiFiStationMode_Disabled))
666 targetState = kWiFiAPState_Active;
669 // The target state is 'Active' if the AP mode is one of the 'On demand' modes and there
670 // has been demand for the AP within the idle timeout period.
671 else if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
673 now = System::Layer::GetClock_MonotonicMS();
675 if (mLastAPDemandTime != 0 && now < (mLastAPDemandTime + mWiFiAPIdleTimeoutMS))
677 targetState = kWiFiAPState_Active;
679 // Compute the amount of idle time before the AP should be deactivated and
680 // arm a timer to fire at that time.
681 apTimeout = (uint32_t)((mLastAPDemandTime + mWiFiAPIdleTimeoutMS) - now);
682 err = SystemLayer.StartTimer(apTimeout, DriveAPState, NULL);
684 ChipLogProgress(DeviceLayer, "Next WiFi AP timeout in %" PRIu32 " s", apTimeout / 1000);
688 targetState = kWiFiAPState_NotActive;
692 // Otherwise the target state is 'NotActive'.
695 targetState = kWiFiAPState_NotActive;
698 // If the current AP state does not match the target state...
699 if (mWiFiAPState != targetState)
701 if (targetState == kWiFiAPState_Active)
703 err = ConfigureWiFiAP();
706 ChangeWiFiAPState(kWiFiAPState_Active);
710 if (mWpaSupplicant.networkPath)
712 GError * error = nullptr;
714 gboolean result = wpa_fi_w1_wpa_supplicant1_interface_call_remove_network_sync(
715 mWpaSupplicant.iface, mWpaSupplicant.networkPath, nullptr, &error);
719 ChipLogProgress(DeviceLayer, "wpa_supplicant: removed network: %s", mWpaSupplicant.networkPath);
720 g_free(mWpaSupplicant.networkPath);
721 mWpaSupplicant.networkPath = nullptr;
722 ChangeWiFiAPState(kWiFiAPState_NotActive);
726 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to stop AP mode with error: %s",
727 error ? error->message : "unknown error");
728 err = CHIP_ERROR_INTERNAL;
731 if (error != nullptr)
739 if (err != CHIP_NO_ERROR)
741 SetWiFiAPMode(kWiFiAPMode_Disabled);
742 ChipLogError(DeviceLayer, "Drive AP state failed: %s", ErrorStr(err));
746 CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP()
748 CHIP_ERROR ret = CHIP_NO_ERROR;
749 GError * err = nullptr;
750 GVariant * args = nullptr;
751 GVariantBuilder builder;
753 uint16_t channel = 1;
754 uint16_t discriminator = 0;
757 channel = MapFrequency(kWiFi_BAND_2_4_GHZ, CHIP_DEVICE_CONFIG_WIFI_AP_CHANNEL);
759 if (ConfigurationMgr().GetSetupDiscriminator(discriminator) != CHIP_NO_ERROR)
762 snprintf(ssid, 32, "%s%04u", CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX, discriminator);
764 ChipLogProgress(DeviceLayer, "wpa_supplicant: ConfigureWiFiAP, ssid: %s, channel: %d", ssid, channel);
766 // Clean up current network if exists
767 if (mWpaSupplicant.networkPath)
769 g_object_unref(mWpaSupplicant.networkPath);
770 mWpaSupplicant.networkPath = nullptr;
773 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
774 g_variant_builder_add(&builder, "{sv}", "ssid", g_variant_new_string(ssid));
775 g_variant_builder_add(&builder, "{sv}", "key_mgmt", g_variant_new_string("NONE"));
776 g_variant_builder_add(&builder, "{sv}", "mode", g_variant_new_int32(2));
777 g_variant_builder_add(&builder, "{sv}", "frequency", g_variant_new_int32(channel));
778 args = g_variant_builder_end(&builder);
780 gboolean result = wpa_fi_w1_wpa_supplicant1_interface_call_add_network_sync(mWpaSupplicant.iface, args,
781 &mWpaSupplicant.networkPath, nullptr, &err);
785 GError * error = nullptr;
787 ChipLogProgress(DeviceLayer, "wpa_supplicant: added network: SSID: %s: %s", ssid, mWpaSupplicant.networkPath);
789 result = wpa_fi_w1_wpa_supplicant1_interface_call_select_network_sync(mWpaSupplicant.iface, mWpaSupplicant.networkPath,
793 ChipLogProgress(DeviceLayer, "wpa_supplicant: succeeded to start softAP: SSID: %s", ssid);
797 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to start softAP: SSID: %s: %s", ssid,
798 error ? error->message : "unknown error");
800 ret = CHIP_ERROR_INTERNAL;
803 if (error != nullptr)
808 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to add network: %s: %s", ssid, err ? err->message : "unknown error");
810 if (mWpaSupplicant.networkPath)
812 g_object_unref(mWpaSupplicant.networkPath);
813 mWpaSupplicant.networkPath = nullptr;
816 ret = CHIP_ERROR_INTERNAL;
825 void ConnectivityManagerImpl::ChangeWiFiAPState(WiFiAPState newState)
827 if (mWiFiAPState != newState)
829 ChipLogProgress(DeviceLayer, "WiFi AP state change: %s -> %s", WiFiAPStateToStr(mWiFiAPState), WiFiAPStateToStr(newState));
830 mWiFiAPState = newState;
834 void ConnectivityManagerImpl::DriveAPState(::chip::System::Layer * aLayer, void * aAppState, ::chip::System::Error aError)
836 sInstance.DriveAPState();
838 #endif // CHIP_DEVICE_CONFIG_ENABLE_WPA
840 CHIP_ERROR ConnectivityManagerImpl::ProvisionWiFiNetwork(const char * ssid, const char * key)
842 #if CHIP_DEVICE_CONFIG_ENABLE_WPA
843 CHIP_ERROR ret = CHIP_NO_ERROR;
844 GError * err = nullptr;
845 GVariant * args = nullptr;
846 GVariantBuilder builder;
849 // Clean up current network if exists
850 if (mWpaSupplicant.networkPath)
852 GError * error = nullptr;
854 result = wpa_fi_w1_wpa_supplicant1_interface_call_remove_network_sync(mWpaSupplicant.iface, mWpaSupplicant.networkPath,
859 ChipLogProgress(DeviceLayer, "wpa_supplicant: removed network: %s", mWpaSupplicant.networkPath);
860 g_free(mWpaSupplicant.networkPath);
861 mWpaSupplicant.networkPath = nullptr;
865 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to stop AP mode with error: %s",
866 error ? error->message : "unknown error");
867 ret = CHIP_ERROR_INTERNAL;
870 if (error != nullptr)
876 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
877 g_variant_builder_add(&builder, "{sv}", "ssid", g_variant_new_string(ssid));
878 g_variant_builder_add(&builder, "{sv}", "psk", g_variant_new_string(key));
879 g_variant_builder_add(&builder, "{sv}", "key_mgmt", g_variant_new_string("WPA-PSK"));
880 args = g_variant_builder_end(&builder);
882 result = wpa_fi_w1_wpa_supplicant1_interface_call_add_network_sync(mWpaSupplicant.iface, args, &mWpaSupplicant.networkPath,
887 GError * error = nullptr;
889 ChipLogProgress(DeviceLayer, "wpa_supplicant: added network: SSID: %s: %s", ssid, mWpaSupplicant.networkPath);
891 result = wpa_fi_w1_wpa_supplicant1_interface_call_select_network_sync(mWpaSupplicant.iface, mWpaSupplicant.networkPath,
895 GError * gerror = nullptr;
897 ChipLogProgress(DeviceLayer, "wpa_supplicant: connected to network: SSID: %s", ssid);
899 result = wpa_fi_w1_wpa_supplicant1_interface_call_save_config_sync(mWpaSupplicant.iface, nullptr, &gerror);
903 ChipLogProgress(DeviceLayer, "wpa_supplicant: save config succeeded!");
907 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to save config: %s",
908 gerror ? gerror->message : "unknown error");
911 if (gerror != nullptr)
912 g_error_free(gerror);
914 // Iterate on the network interface to see if we already have beed assigned addresses.
915 // The temporary hack for getting IP address change on linux for network provisioning in the rendezvous session.
916 // This should be removed or find a better place once we depercate the rendezvous session.
917 for (chip::Inet::InterfaceAddressIterator it; it.HasCurrent(); it.Next())
919 char ifName[chip::Inet::InterfaceIterator::kMaxIfNameLength];
920 if (it.IsUp() && CHIP_NO_ERROR == it.GetInterfaceName(ifName, sizeof(ifName)) &&
921 strncmp(ifName, CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME, sizeof(ifName)) == 0)
923 chip::Inet::IPAddress addr = it.GetAddress();
926 ChipDeviceEvent event;
927 event.Type = DeviceEventType::kInternetConnectivityChange;
928 event.InternetConnectivityChange.IPv4 = kConnectivity_Established;
929 event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
930 addr.ToString(event.InternetConnectivityChange.address);
932 ChipLogDetail(DeviceLayer, "Got IP address on interface: %s IP: %s", ifName,
933 event.InternetConnectivityChange.address);
935 PlatformMgr().PostEvent(&event);
940 // Run dhclient for IP on WiFi.
941 // TODO: The wifi can be managed by networkmanager on linux so we don't have to care about this.
943 sprintf(cmdBuffer, "dhclient -nw %s", CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME);
944 int dhclientSystemRet = system(cmdBuffer);
945 if (dhclientSystemRet != 0)
947 ChipLogError(DeviceLayer, "Failed to run dhclient, system() returns %d", dhclientSystemRet);
951 ChipLogProgress(DeviceLayer, "dhclient is running on the %s interface.", CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME);
954 // Return success as long as the device is connected to the network
959 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to connect to network: SSID: %s: %s", ssid,
960 error ? error->message : "unknown error");
962 ret = CHIP_ERROR_INTERNAL;
965 if (error != nullptr)
970 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to add network: %s: %s", ssid, err ? err->message : "unknown error");
972 if (mWpaSupplicant.networkPath)
974 g_object_unref(mWpaSupplicant.networkPath);
975 mWpaSupplicant.networkPath = nullptr;
978 ret = CHIP_ERROR_INTERNAL;
987 return CHIP_ERROR_NOT_IMPLEMENTED;
991 } // namespace DeviceLayer