3 * Copyright (c) 2020 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 uint16_t ConnectivityManagerImpl::mConnectivityFlag;
260 struct GDBusWpaSupplicant ConnectivityManagerImpl::mWpaSupplicant;
262 bool ConnectivityManagerImpl::_HaveIPv4InternetConnectivity()
264 return ((mConnectivityFlag & kFlag_HaveIPv4InternetConnectivity) != 0);
267 bool ConnectivityManagerImpl::_HaveIPv6InternetConnectivity()
269 return ((mConnectivityFlag & kFlag_HaveIPv6InternetConnectivity) != 0);
272 ConnectivityManager::WiFiStationMode ConnectivityManagerImpl::_GetWiFiStationMode()
274 if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
276 mWiFiStationMode = (mWpaSupplicant.iface != nullptr) ? kWiFiStationMode_Enabled : kWiFiStationMode_Disabled;
279 return mWiFiStationMode;
282 CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationMode(ConnectivityManager::WiFiStationMode val)
284 CHIP_ERROR err = CHIP_NO_ERROR;
286 VerifyOrExit(val != ConnectivityManager::kWiFiStationMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
288 if (mWiFiStationMode != val)
290 ChipLogProgress(DeviceLayer, "WiFi station mode change: %s -> %s", WiFiStationModeToStr(mWiFiStationMode),
291 WiFiStationModeToStr(val));
294 mWiFiStationMode = val;
299 uint32_t ConnectivityManagerImpl::_GetWiFiStationReconnectIntervalMS()
301 return mWiFiStationReconnectIntervalMS;
304 CHIP_ERROR ConnectivityManagerImpl::_SetWiFiStationReconnectIntervalMS(uint32_t val)
306 mWiFiStationReconnectIntervalMS = val;
308 return CHIP_NO_ERROR;
311 bool ConnectivityManagerImpl::_IsWiFiStationEnabled()
313 return GetWiFiStationMode() == kWiFiStationMode_Enabled;
316 bool ConnectivityManagerImpl::_IsWiFiStationConnected()
319 const gchar * state = nullptr;
321 if (mWpaSupplicant.state != GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED)
323 ChipLogProgress(DeviceLayer, "wpa_supplicant: _IsWiFiStationConnected: interface not connected");
327 state = wpa_fi_w1_wpa_supplicant1_interface_get_state(mWpaSupplicant.iface);
328 if (g_strcmp0(state, "completed") == 0)
330 SetFlag(mConnectivityFlag, kFlag_HaveIPv4InternetConnectivity, true);
331 SetFlag(mConnectivityFlag, kFlag_HaveIPv6InternetConnectivity, true);
338 bool ConnectivityManagerImpl::_IsWiFiStationApplicationControlled()
340 return mWiFiStationMode == ConnectivityManager::kWiFiStationMode_ApplicationControlled;
343 bool ConnectivityManagerImpl::_IsWiFiStationProvisioned()
346 const gchar * bss = nullptr;
348 if (mWpaSupplicant.state != GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED)
350 ChipLogProgress(DeviceLayer, "wpa_supplicant: _IsWiFiStationProvisioned: interface not connected");
354 bss = wpa_fi_w1_wpa_supplicant1_interface_get_current_bss(mWpaSupplicant.iface);
355 if (g_str_match_string("BSSs", bss, true))
363 void ConnectivityManagerImpl::_ClearWiFiStationProvision()
365 if (mWpaSupplicant.state != GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED)
367 ChipLogProgress(DeviceLayer, "wpa_supplicant: _ClearWiFiStationProvision: interface not connected");
371 if (mWiFiStationMode != kWiFiStationMode_ApplicationControlled)
373 GError * err = nullptr;
374 wpa_fi_w1_wpa_supplicant1_interface_call_remove_all_networks_sync(mWpaSupplicant.iface, nullptr, &err);
378 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to remove all networks with error: %s",
379 err ? err->message : "unknown error");
385 bool ConnectivityManagerImpl::_CanStartWiFiScan()
387 return mWpaSupplicant.state == GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED &&
388 mWpaSupplicant.scanState == GDBusWpaSupplicant::WIFI_SCANNING_IDLE;
391 CHIP_ERROR ConnectivityManagerImpl::_SetWiFiAPMode(WiFiAPMode val)
393 CHIP_ERROR err = CHIP_NO_ERROR;
395 VerifyOrExit(val != kWiFiAPMode_NotSupported, err = CHIP_ERROR_INVALID_ARGUMENT);
397 if (mWiFiAPMode != val)
399 ChipLogProgress(DeviceLayer, "WiFi AP mode change: %s -> %s", WiFiAPModeToStr(mWiFiAPMode), WiFiAPModeToStr(val));
402 SystemLayer.ScheduleWork(DriveAPState, NULL);
409 void ConnectivityManagerImpl::_DemandStartWiFiAP()
411 if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
413 ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand start WiFi AP");
414 mLastAPDemandTime = System::Layer::GetClock_MonotonicMS();
415 SystemLayer.ScheduleWork(DriveAPState, NULL);
419 ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand start WiFi AP ignored, mode: %s", WiFiAPModeToStr(mWiFiAPMode));
423 void ConnectivityManagerImpl::_StopOnDemandWiFiAP()
425 if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
427 ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand stop WiFi AP");
428 mLastAPDemandTime = 0;
429 SystemLayer.ScheduleWork(DriveAPState, NULL);
433 ChipLogProgress(DeviceLayer, "wpa_supplicant: Demand stop WiFi AP ignored, mode: %s", WiFiAPModeToStr(mWiFiAPMode));
437 void ConnectivityManagerImpl::_MaintainOnDemandWiFiAP()
439 if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
441 if (mWiFiAPState == kWiFiAPState_Active)
443 mLastAPDemandTime = System::Layer::GetClock_MonotonicMS();
448 void ConnectivityManagerImpl::_SetWiFiAPIdleTimeoutMS(uint32_t val)
450 mWiFiAPIdleTimeoutMS = val;
451 SystemLayer.ScheduleWork(DriveAPState, NULL);
454 void ConnectivityManagerImpl::_OnWpaInterfaceProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data)
456 GError * err = nullptr;
457 WpaFiW1Wpa_supplicant1Interface * iface = wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus_finish(res, &err);
459 if (mWpaSupplicant.iface)
461 g_object_unref(mWpaSupplicant.iface);
462 mWpaSupplicant.iface = nullptr;
465 if (iface != nullptr && err == nullptr)
467 mWpaSupplicant.iface = iface;
468 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_INTERFACE_CONNECTED;
469 ChipLogProgress(DeviceLayer, "wpa_supplicant: connected to wpa_supplicant interface proxy");
473 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to create wpa_supplicant1 interface proxy %s: %s",
474 mWpaSupplicant.interfacePath, err ? err->message : "unknown error");
476 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_NOT_CONNECTED;
483 void ConnectivityManagerImpl::_OnWpaInterfaceReady(GObject * source_object, GAsyncResult * res, gpointer user_data)
485 GError * err = nullptr;
488 wpa_fi_w1_wpa_supplicant1_call_get_interface_finish(mWpaSupplicant.proxy, &mWpaSupplicant.interfacePath, res, &err);
491 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_GOT_INTERFACE_PATH;
492 ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface: %s", mWpaSupplicant.interfacePath);
494 wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName,
495 mWpaSupplicant.interfacePath, nullptr, _OnWpaInterfaceProxyReady,
500 GError * error = nullptr;
501 GVariant * args = nullptr;
502 GVariantBuilder builder;
504 ChipLogProgress(DeviceLayer, "wpa_supplicant: can't find interface %s: %s", CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME,
505 err ? err->message : "unknown error");
507 ChipLogProgress(DeviceLayer, "wpa_supplicant: try to create interface %s", CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME);
509 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
510 g_variant_builder_add(&builder, "{sv}", "Ifname", g_variant_new_string(CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME));
511 args = g_variant_builder_end(&builder);
513 result = wpa_fi_w1_wpa_supplicant1_call_create_interface_sync(mWpaSupplicant.proxy, args, &mWpaSupplicant.interfacePath,
518 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_GOT_INTERFACE_PATH;
519 ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface: %s", mWpaSupplicant.interfacePath);
521 wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
522 kWpaSupplicantServiceName, mWpaSupplicant.interfacePath, nullptr,
523 _OnWpaInterfaceProxyReady, nullptr);
527 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to create interface %s: %s",
528 CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME, error ? error->message : "unknown error");
530 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_NO_INTERFACE_PATH;
532 if (mWpaSupplicant.interfacePath)
534 g_free(mWpaSupplicant.interfacePath);
535 mWpaSupplicant.interfacePath = nullptr;
539 if (error != nullptr)
547 void ConnectivityManagerImpl::_OnWpaInterfaceAdded(WpaFiW1Wpa_supplicant1 * proxy, const gchar * path, GVariant * properties,
550 if (mWpaSupplicant.interfacePath)
553 mWpaSupplicant.interfacePath = const_cast<gchar *>(path);
554 if (mWpaSupplicant.interfacePath)
556 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_GOT_INTERFACE_PATH;
557 ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface added: %s", mWpaSupplicant.interfacePath);
559 wpa_fi_w1_wpa_supplicant1_interface_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName,
560 mWpaSupplicant.interfacePath, nullptr, _OnWpaInterfaceProxyReady,
565 void ConnectivityManagerImpl::_OnWpaInterfaceRemoved(WpaFiW1Wpa_supplicant1 * proxy, const gchar * path, GVariant * properties,
568 if (mWpaSupplicant.interfacePath == nullptr)
571 if (g_strcmp0(mWpaSupplicant.interfacePath, path) == 0)
573 ChipLogProgress(DeviceLayer, "wpa_supplicant: WiFi interface removed: %s", path);
575 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_NO_INTERFACE_PATH;
577 if (mWpaSupplicant.interfacePath)
579 g_free(mWpaSupplicant.interfacePath);
580 mWpaSupplicant.interfacePath = nullptr;
583 if (mWpaSupplicant.iface)
585 g_object_unref(mWpaSupplicant.iface);
586 mWpaSupplicant.iface = nullptr;
589 mWpaSupplicant.scanState = GDBusWpaSupplicant::WIFI_SCANNING_IDLE;
593 void ConnectivityManagerImpl::_OnWpaProxyReady(GObject * source_object, GAsyncResult * res, gpointer user_data)
595 GError * err = nullptr;
597 mWpaSupplicant.proxy = wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus_finish(res, &err);
598 if (mWpaSupplicant.proxy != nullptr && err == nullptr)
600 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_CONNECTED;
601 ChipLogProgress(DeviceLayer, "wpa_supplicant: connected to wpa_supplicant proxy");
603 g_signal_connect(mWpaSupplicant.proxy, "interface-added", G_CALLBACK(_OnWpaInterfaceAdded), NULL);
605 g_signal_connect(mWpaSupplicant.proxy, "interface-removed", G_CALLBACK(_OnWpaInterfaceRemoved), NULL);
607 wpa_fi_w1_wpa_supplicant1_call_get_interface(mWpaSupplicant.proxy, CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME, nullptr,
608 _OnWpaInterfaceReady, nullptr);
612 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to create wpa_supplicant proxy %s",
613 err ? err->message : "unknown error");
614 mWpaSupplicant.state = GDBusWpaSupplicant::WPA_NOT_CONNECTED;
621 void ConnectivityManagerImpl::StartWiFiManagement()
623 mConnectivityFlag = 0;
624 mWpaSupplicant.state = GDBusWpaSupplicant::INIT;
625 mWpaSupplicant.scanState = GDBusWpaSupplicant::WIFI_SCANNING_IDLE;
626 mWpaSupplicant.proxy = nullptr;
627 mWpaSupplicant.iface = nullptr;
628 mWpaSupplicant.interfacePath = nullptr;
629 mWpaSupplicant.networkPath = nullptr;
631 wpa_fi_w1_wpa_supplicant1_proxy_new_for_bus(G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kWpaSupplicantServiceName,
632 kWpaSupplicantObjectPath, nullptr, _OnWpaProxyReady, nullptr);
635 void ConnectivityManagerImpl::DriveAPState()
637 CHIP_ERROR err = CHIP_NO_ERROR;
638 WiFiAPState targetState;
642 // If the AP interface is not under application control...
643 if (mWiFiAPMode != kWiFiAPMode_ApplicationControlled)
645 // Determine the target (desired) state for AP interface...
647 // The target state is 'NotActive' if the application has expressly disabled the AP interface.
648 if (mWiFiAPMode == kWiFiAPMode_Disabled)
650 targetState = kWiFiAPState_NotActive;
653 // The target state is 'Active' if the application has expressly enabled the AP interface.
654 else if (mWiFiAPMode == kWiFiAPMode_Enabled)
656 targetState = kWiFiAPState_Active;
659 // The target state is 'Active' if the AP mode is 'On demand, when no station is available'
660 // and the station interface is not provisioned or the application has disabled the station
662 else if (mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision &&
663 (!IsWiFiStationProvisioned() || GetWiFiStationMode() == kWiFiStationMode_Disabled))
665 targetState = kWiFiAPState_Active;
668 // The target state is 'Active' if the AP mode is one of the 'On demand' modes and there
669 // has been demand for the AP within the idle timeout period.
670 else if (mWiFiAPMode == kWiFiAPMode_OnDemand || mWiFiAPMode == kWiFiAPMode_OnDemand_NoStationProvision)
672 now = System::Layer::GetClock_MonotonicMS();
674 if (mLastAPDemandTime != 0 && now < (mLastAPDemandTime + mWiFiAPIdleTimeoutMS))
676 targetState = kWiFiAPState_Active;
678 // Compute the amount of idle time before the AP should be deactivated and
679 // arm a timer to fire at that time.
680 apTimeout = (uint32_t)((mLastAPDemandTime + mWiFiAPIdleTimeoutMS) - now);
681 err = SystemLayer.StartTimer(apTimeout, DriveAPState, NULL);
683 ChipLogProgress(DeviceLayer, "Next WiFi AP timeout in %" PRIu32 " s", apTimeout / 1000);
687 targetState = kWiFiAPState_NotActive;
691 // Otherwise the target state is 'NotActive'.
694 targetState = kWiFiAPState_NotActive;
697 // If the current AP state does not match the target state...
698 if (mWiFiAPState != targetState)
700 if (targetState == kWiFiAPState_Active)
702 err = ConfigureWiFiAP();
705 ChangeWiFiAPState(kWiFiAPState_Active);
709 if (mWpaSupplicant.networkPath)
711 GError * error = nullptr;
713 gboolean result = wpa_fi_w1_wpa_supplicant1_interface_call_remove_network_sync(
714 mWpaSupplicant.iface, mWpaSupplicant.networkPath, nullptr, &error);
718 ChipLogProgress(DeviceLayer, "wpa_supplicant: removed network: %s", mWpaSupplicant.networkPath);
719 g_free(mWpaSupplicant.networkPath);
720 mWpaSupplicant.networkPath = nullptr;
721 ChangeWiFiAPState(kWiFiAPState_NotActive);
725 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to stop AP mode with error: %s",
726 error ? error->message : "unknown error");
727 err = CHIP_ERROR_INTERNAL;
730 if (error != nullptr)
738 if (err != CHIP_NO_ERROR)
740 SetWiFiAPMode(kWiFiAPMode_Disabled);
741 ChipLogError(DeviceLayer, "Drive AP state failed: %s", ErrorStr(err));
745 CHIP_ERROR ConnectivityManagerImpl::ConfigureWiFiAP()
747 CHIP_ERROR ret = CHIP_NO_ERROR;
748 GError * err = nullptr;
749 GVariant * args = nullptr;
750 GVariantBuilder builder;
752 uint16_t channel = 1;
753 uint16_t discriminator = 0;
756 channel = MapFrequency(kWiFi_BAND_2_4_GHZ, CHIP_DEVICE_CONFIG_WIFI_AP_CHANNEL);
758 if (ConfigurationMgr().GetSetupDiscriminator(discriminator) != CHIP_NO_ERROR)
761 snprintf(ssid, 32, "%s%04u", CHIP_DEVICE_CONFIG_WIFI_AP_SSID_PREFIX, discriminator);
763 ChipLogProgress(DeviceLayer, "wpa_supplicant: ConfigureWiFiAP, ssid: %s, channel: %d", ssid, channel);
765 // Clean up current network if exists
766 if (mWpaSupplicant.networkPath)
768 g_object_unref(mWpaSupplicant.networkPath);
769 mWpaSupplicant.networkPath = nullptr;
772 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
773 g_variant_builder_add(&builder, "{sv}", "ssid", g_variant_new_string(ssid));
774 g_variant_builder_add(&builder, "{sv}", "key_mgmt", g_variant_new_string("NONE"));
775 g_variant_builder_add(&builder, "{sv}", "mode", g_variant_new_int32(2));
776 g_variant_builder_add(&builder, "{sv}", "frequency", g_variant_new_int32(channel));
777 args = g_variant_builder_end(&builder);
779 gboolean result = wpa_fi_w1_wpa_supplicant1_interface_call_add_network_sync(mWpaSupplicant.iface, args,
780 &mWpaSupplicant.networkPath, nullptr, &err);
784 GError * error = nullptr;
786 ChipLogProgress(DeviceLayer, "wpa_supplicant: added network: SSID: %s: %s", ssid, mWpaSupplicant.networkPath);
788 result = wpa_fi_w1_wpa_supplicant1_interface_call_select_network_sync(mWpaSupplicant.iface, mWpaSupplicant.networkPath,
792 ChipLogProgress(DeviceLayer, "wpa_supplicant: succeeded to start softAP: SSID: %s", ssid);
796 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to start softAP: SSID: %s: %s", ssid,
797 error ? error->message : "unknown error");
799 ret = CHIP_ERROR_INTERNAL;
802 if (error != nullptr)
807 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to add network: %s: %s", ssid, err ? err->message : "unknown error");
809 if (mWpaSupplicant.networkPath)
811 g_object_unref(mWpaSupplicant.networkPath);
812 mWpaSupplicant.networkPath = nullptr;
815 ret = CHIP_ERROR_INTERNAL;
824 void ConnectivityManagerImpl::ChangeWiFiAPState(WiFiAPState newState)
826 if (mWiFiAPState != newState)
828 ChipLogProgress(DeviceLayer, "WiFi AP state change: %s -> %s", WiFiAPStateToStr(mWiFiAPState), WiFiAPStateToStr(newState));
829 mWiFiAPState = newState;
833 void ConnectivityManagerImpl::DriveAPState(::chip::System::Layer * aLayer, void * aAppState, ::chip::System::Error aError)
835 sInstance.DriveAPState();
837 #endif // CHIP_DEVICE_CONFIG_ENABLE_WPA
839 CHIP_ERROR ConnectivityManagerImpl::ProvisionWiFiNetwork(const char * ssid, const char * key)
841 #if CHIP_DEVICE_CONFIG_ENABLE_WPA
842 CHIP_ERROR ret = CHIP_NO_ERROR;
843 GError * err = nullptr;
844 GVariant * args = nullptr;
845 GVariantBuilder builder;
848 // Clean up current network if exists
849 if (mWpaSupplicant.networkPath)
851 GError * error = nullptr;
853 result = wpa_fi_w1_wpa_supplicant1_interface_call_remove_network_sync(mWpaSupplicant.iface, mWpaSupplicant.networkPath,
858 ChipLogProgress(DeviceLayer, "wpa_supplicant: removed network: %s", mWpaSupplicant.networkPath);
859 g_free(mWpaSupplicant.networkPath);
860 mWpaSupplicant.networkPath = nullptr;
864 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to stop AP mode with error: %s",
865 error ? error->message : "unknown error");
866 ret = CHIP_ERROR_INTERNAL;
869 if (error != nullptr)
875 g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
876 g_variant_builder_add(&builder, "{sv}", "ssid", g_variant_new_string(ssid));
877 g_variant_builder_add(&builder, "{sv}", "psk", g_variant_new_string(key));
878 g_variant_builder_add(&builder, "{sv}", "key_mgmt", g_variant_new_string("WPA-PSK"));
879 args = g_variant_builder_end(&builder);
881 result = wpa_fi_w1_wpa_supplicant1_interface_call_add_network_sync(mWpaSupplicant.iface, args, &mWpaSupplicant.networkPath,
886 GError * error = nullptr;
888 ChipLogProgress(DeviceLayer, "wpa_supplicant: added network: SSID: %s: %s", ssid, mWpaSupplicant.networkPath);
890 result = wpa_fi_w1_wpa_supplicant1_interface_call_select_network_sync(mWpaSupplicant.iface, mWpaSupplicant.networkPath,
894 GError * gerror = nullptr;
896 ChipLogProgress(DeviceLayer, "wpa_supplicant: connected to network: SSID: %s", ssid);
898 result = wpa_fi_w1_wpa_supplicant1_interface_call_save_config_sync(mWpaSupplicant.iface, nullptr, &gerror);
902 ChipLogProgress(DeviceLayer, "wpa_supplicant: save config succeeded!");
906 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to save config: %s",
907 gerror ? gerror->message : "unknown error");
910 if (gerror != nullptr)
911 g_error_free(gerror);
913 // Iterate on the network interface to see if we already have beed assigned addresses.
914 // The temporary hack for getting IP address change on linux for network provisioning in the rendezvous session.
915 // This should be removed or find a better place once we depercate the rendezvous session.
916 for (chip::Inet::InterfaceAddressIterator it; it.HasCurrent(); it.Next())
918 char ifName[chip::Inet::InterfaceIterator::kMaxIfNameLength];
919 if (it.IsUp() && CHIP_NO_ERROR == it.GetInterfaceName(ifName, sizeof(ifName)) &&
920 strncmp(ifName, CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME, sizeof(ifName)) == 0)
922 chip::Inet::IPAddress addr = it.GetAddress();
925 ChipDeviceEvent event;
926 event.Type = DeviceEventType::kInternetConnectivityChange;
927 event.InternetConnectivityChange.IPv4 = kConnectivity_Established;
928 event.InternetConnectivityChange.IPv6 = kConnectivity_NoChange;
929 addr.ToString(event.InternetConnectivityChange.address);
931 ChipLogDetail(DeviceLayer, "Got IP address on interface: %s IP: %s", ifName,
932 event.InternetConnectivityChange.address);
934 PlatformMgr().PostEvent(&event);
939 // Run dhclient for IP on WiFi.
940 // TODO: The wifi can be managed by networkmanager on linux so we don't have to care about this.
942 sprintf(cmdBuffer, "dhclient -nw %s", CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME);
943 int dhclientSystemRet = system(cmdBuffer);
944 if (dhclientSystemRet != 0)
946 ChipLogError(DeviceLayer, "Failed to run dhclient, system() returns %d", dhclientSystemRet);
950 ChipLogProgress(DeviceLayer, "dhclient is running on the %s interface.", CHIP_DEVICE_CONFIG_WIFI_STATION_IF_NAME);
953 // Return success as long as the device is connected to the network
958 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to connect to network: SSID: %s: %s", ssid,
959 error ? error->message : "unknown error");
961 ret = CHIP_ERROR_INTERNAL;
964 if (error != nullptr)
969 ChipLogProgress(DeviceLayer, "wpa_supplicant: failed to add network: %s: %s", ssid, err ? err->message : "unknown error");
971 if (mWpaSupplicant.networkPath)
973 g_object_unref(mWpaSupplicant.networkPath);
974 mWpaSupplicant.networkPath = nullptr;
977 ret = CHIP_ERROR_INTERNAL;
986 return CHIP_ERROR_NOT_IMPLEMENTED;
990 } // namespace DeviceLayer