From: Mathieu Trudel-Lapierre <mathieu.trudel-lapie...@canonical.com>
... Also do that rather than resetting the killswitch to the NM saved WirelessEnabled state if urfkill support is enabled. Gbp-Pq: Name Track-killswitch-change-signals-from-urfkill.patch --- config.h.in | 6 + configure.ac | 11 ++ src/Makefile.am | 6 + src/nm-manager.c | 112 +++++++++++++++++- src/nm-urfkill-manager.c | 289 +++++++++++++++++++++++++++++++++++++++++++++++ src/nm-urfkill-manager.h | 50 ++++++++ 6 files changed, 472 insertions(+), 2 deletions(-) create mode 100644 src/nm-urfkill-manager.c create mode 100644 src/nm-urfkill-manager.h diff --git a/config.h.in b/config.h.in index baabb79..356de31 100644 --- a/config.h.in +++ b/config.h.in @@ -261,6 +261,9 @@ /* Define if you have ModemManager1 support */ #undef WITH_MODEM_MANAGER_1 +/* Define if you have oFono support */ +#undef WITH_OFONO + /* whether to compile polkit support */ #undef WITH_POLKIT @@ -276,6 +279,9 @@ /* Define if you have Teamd control support */ #undef WITH_TEAMDCTL +/* Define if you want to build with support for the urfkill daemon */ +#undef WITH_URFKILL + /* Define if you have Wi-Fi support */ #undef WITH_WIFI diff --git a/configure.ac b/configure.ac index 2ccfa23..6ad177d 100644 --- a/configure.ac +++ b/configure.ac @@ -268,6 +268,17 @@ else fi dnl +dnl Default to using WEXT but allow it to be disabled +dnl +AC_ARG_WITH(urfkill, AS_HELP_STRING([--with-urfkill=yes], [Enable or disable support for urfkill]), ac_with_urfkill=$withval, ac_with_urfkill="yes") +if test x"$ac_with_urfkill" = x"yes"; then + AC_DEFINE(WITH_URFKILL, 1, [Define if you want to build with support for the urfkill daemon]) +else + AC_DEFINE(WITH_URFKILL, 0, [Define if you want to build with support for the urfkill daemon]) +fi +AM_CONDITIONAL(WITH_URFKILL, test x"${ac_with_urfkill}" = x"yes") + +dnl dnl Checks for libm - needed for pow() dnl LT_LIB_M diff --git a/src/Makefile.am b/src/Makefile.am index 2495bbc..49028f1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -445,6 +445,12 @@ libNetworkManager_la_SOURCES = \ NetworkManagerUtils.c \ NetworkManagerUtils.h +if WITH_URFKILL +libNetworkManager_la_SOURCES += \ + nm-urfkill-manager.c \ + nm-urfkill-manager.h \ + $(NULL) +endif if SUSPEND_RESUME_UPOWER libNetworkManager_la_SOURCES += nm-sleep-monitor-upower.c diff --git a/src/nm-manager.c b/src/nm-manager.c index 8cf70c7..8f45b0f 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -34,6 +34,7 @@ #include "nm-device-generic.h" #include "nm-platform.h" #include "nm-rfkill-manager.h" +#include "nm-urfkill-manager.h" #include "nm-dhcp-manager.h" #include "nm-settings.h" #include "nm-settings-connection.h" @@ -121,6 +122,9 @@ typedef struct { guint id; } prop_filter; NMRfkillManager *rfkill_mgr; +#if WITH_URFKILL + NMUrfkillManager *urfkill_mgr; +#endif NMSettings *settings; char *hostname; @@ -144,6 +148,7 @@ typedef struct { gboolean ifstate_force_online; guint timestamp_update_id; + guint rfkill_initial_id; gboolean startup; gboolean devices_inited; @@ -5213,6 +5218,49 @@ dbus_connection_changed_cb (NMBusManager *dbus_mgr, /**********************************************************************/ +#if WITH_URFKILL +static void +urfkill_wlan_state_changed_cb (NMUrfkillManager *mgr, + gboolean enabled, + gpointer user_data) +{ + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GError *error = NULL; + + nm_log_dbg (LOGD_RFKILL, "urfkill wlan state changed to %s", + enabled ? "enabled" : "disabled"); + + if (priv->rfkill_initial_id) { + g_source_remove (priv->rfkill_initial_id); + priv->rfkill_initial_id = 0; + } + + manager_update_radio_enabled (self, + &priv->radio_states[RFKILL_TYPE_WLAN], + enabled); + nm_manager_update_state (self); +} + +static void +urfkill_wwan_state_changed_cb (NMUrfkillManager *mgr, + gboolean enabled, + gpointer user_data) +{ + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GError *error = NULL; + + nm_log_dbg (LOGD_RFKILL, "urfkill wwan state changed to %s", + enabled ? "enabled" : "disabled" ); + + manager_update_radio_enabled (self, + &priv->radio_states[RFKILL_TYPE_WWAN], + enabled); + nm_manager_update_state (self); +} +#endif /* WITH_URFKILL */ + NM_DEFINE_SINGLETON_REGISTER (NMManager); NMManager * @@ -5234,6 +5282,44 @@ nm_connection_provider_get (void) return p; } +typedef struct KillState KillState; +struct KillState { + NMManager *manager; + gboolean wlan_enabled; + gboolean wwan_enabled; +}; + +static gboolean +rfkill_change_timeout (gpointer user_data) +{ + KillState *state = (KillState *) user_data; + NMManager *mgr = state->manager; + NMManagerPrivate *priv; + + g_return_val_if_fail (NM_IS_MANAGER (mgr), G_SOURCE_REMOVE); + + priv = NM_MANAGER_GET_PRIVATE (mgr); + + rfkill_change (priv->radio_states[RFKILL_TYPE_WLAN].desc, RFKILL_TYPE_WLAN, state->wlan_enabled); + rfkill_change (priv->radio_states[RFKILL_TYPE_WWAN].desc, RFKILL_TYPE_WWAN, state->wwan_enabled); + + return G_SOURCE_REMOVE; +} + +static void +kill_state_free (gpointer user_data) +{ + KillState *state = (KillState *) user_data; + + if (state->manager) { + g_object_unref (state->manager); + state->manager = NULL; + } + + g_slice_free (KillState, (KillState *)user_data); +} + + NMManager * nm_manager_setup (const char *state_file, gboolean initial_net_enabled, @@ -5314,16 +5400,38 @@ constructed (GObject *object) "rfkill-changed", G_CALLBACK (rfkill_manager_rfkill_changed_cb), self); +#if WITH_URFKILL + priv->urfkill_mgr = nm_urfkill_manager_new (); + + g_signal_connect (priv->urfkill_mgr, + "wlan-state-changed", + G_CALLBACK (urfkill_wlan_state_changed_cb), + self); + g_signal_connect (priv->urfkill_mgr, + "wwan-state-changed", + G_CALLBACK (urfkill_wwan_state_changed_cb), + self); + urfkill_wlan_state_changed_cb (priv->urfkill_mgr, TRUE, self); + urfkill_wwan_state_changed_cb (priv->urfkill_mgr, TRUE, self); +#endif /* Force kernel WiFi/WWAN rfkill state to follow NM saved WiFi/WWAN state * in case the BIOS doesn't save rfkill state, and to be consistent with user * changes to the WirelessEnabled/WWANEnabled properties which toggle kernel * rfkill. */ - rfkill_change (priv->radio_states[RFKILL_TYPE_WLAN].desc, RFKILL_TYPE_WLAN, priv->radio_states[RFKILL_TYPE_WLAN].user_enabled); - rfkill_change (priv->radio_states[RFKILL_TYPE_WWAN].desc, RFKILL_TYPE_WWAN, priv->radio_states[RFKILL_TYPE_WWAN].user_enabled); + KillState *kill_state = g_slice_new0 (KillState); + kill_state->manager = g_object_ref (self); + kill_state->wlan_enabled = priv->radio_states[RFKILL_TYPE_WLAN].user_enabled; + kill_state->wwan_enabled = priv->radio_states[RFKILL_TYPE_WWAN].user_enabled; + + priv->rfkill_initial_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, 10, + rfkill_change_timeout, + kill_state, + kill_state_free); } + static void nm_manager_init (NMManager *self) { diff --git a/src/nm-urfkill-manager.c b/src/nm-urfkill-manager.c new file mode 100644 index 0000000..211ebc1 --- /dev/null +++ b/src/nm-urfkill-manager.c @@ -0,0 +1,289 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2006 - 2010 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#include "config.h" +#include "nm-core-internal.h" +#include "nm-urfkill-manager.h" +#include "nm-glib.h" + +#include <gio/gio.h> +#include <string.h> +#include "nm-logging.h" + +enum { + WLAN_STATE_CHANGED, + WWAN_STATE_CHANGED, + NUMBER_OF_SIGNALS +}; + +static guint signals[NUMBER_OF_SIGNALS]; + +struct _NMUrfkillManager { + GObject parent_instance; + + guint urfkill_watch; + + GDBusProxy *wlan_proxy; + GDBusProxy *wwan_proxy; + + GCancellable *watch_cancellable; + GCancellable *wlan_proxy_cancellable; + GCancellable *wwan_proxy_cancellable; +}; + +typedef GObjectClass NMUrfkillManagerClass; + +G_DEFINE_TYPE(NMUrfkillManager, nm_urfkill_manager, G_TYPE_OBJECT) + +static void +wlan_state_changed (GDBusProxy *proxy, + GVariant *changed_properties, + const gchar* const *invalidated_properties, + gpointer user_data) +{ + NMUrfkillManager *self = NM_URFKILL_MANAGER (user_data); + gboolean enabled; + + enabled = nm_urfkill_get_wlan_state (self); + + nm_log_dbg (LOGD_RFKILL, "received state change for WLAN: %s", + enabled ? "unblocked" : "blocked"); + + g_signal_emit (self, signals[WLAN_STATE_CHANGED], 0, enabled); +} + +static void +wwan_state_changed (GDBusProxy *proxy, + GVariant *changed_properties, + const gchar* const *invalidated_properties, + gpointer user_data) +{ + NMUrfkillManager *self = NM_URFKILL_MANAGER (user_data); + gboolean enabled; + + enabled = nm_urfkill_get_wwan_state (self); + + nm_log_dbg (LOGD_RFKILL, "received state change for WWAN: %s", + enabled ? "unblocked" : "blocked"); + + g_signal_emit (self, signals[WWAN_STATE_CHANGED], 0, enabled); +} + +static void +wlan_proxy_created (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMUrfkillManager *self = NM_URFKILL_MANAGER (user_data); + GDBusProxy *wlan_proxy; + GError *error; + + wlan_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (wlan_proxy) { + self->wlan_proxy = wlan_proxy; + + g_signal_connect (self->wlan_proxy, "g-properties-changed", + G_CALLBACK (wlan_state_changed), self); + g_signal_emit (self, signals[WLAN_STATE_CHANGED], 0, + nm_urfkill_get_wlan_state (self)); + } else { + nm_log_warn (LOGD_RFKILL, "could not create URfkill WLAN device proxy"); + } +} + +static void +wwan_proxy_created (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NMUrfkillManager *self = NM_URFKILL_MANAGER (user_data); + GDBusProxy *wwan_proxy; + GError *error; + + wwan_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); + + if (wwan_proxy) { + self->wwan_proxy = wwan_proxy; + + g_signal_connect (self->wwan_proxy, "g-properties-changed", + G_CALLBACK (wwan_state_changed), self); + g_signal_emit (self, signals[WWAN_STATE_CHANGED], 0, + nm_urfkill_get_wwan_state (self)); + } else { + nm_log_warn (LOGD_RFKILL, "could not create URfkill WWAN device proxy"); + } +} + +gboolean +nm_urfkill_get_wlan_state (NMUrfkillManager *self) +{ + GVariant *state; + gboolean enabled = TRUE; + + g_return_val_if_fail (self->wlan_proxy != NULL, enabled); + + state = g_dbus_proxy_get_cached_property (self->wlan_proxy, "state"); + + if (state) { + nm_log_dbg (LOGD_RFKILL, "wlan state from urfkill: %d", + g_variant_get_int32 (state)); + enabled = (g_variant_get_int32 (state) <= 0); + g_variant_unref (state); + } else { + nm_log_warn (LOGD_RFKILL, "invalid wlan state from urfkill cached properties"); + } + + return enabled; +} + +gboolean +nm_urfkill_get_wwan_state (NMUrfkillManager *self) +{ + GVariant *state; + gboolean enabled = TRUE; + + g_return_val_if_fail (self->wwan_proxy != NULL, enabled); + + state = g_dbus_proxy_get_cached_property (self->wwan_proxy, "state"); + + if (state) { + nm_log_dbg (LOGD_RFKILL, "wwan state from urfkill: %d", + g_variant_get_int32 (state)); + enabled = (g_variant_get_int32 (state) <= 0); + g_variant_unref (state); + } else { + nm_log_warn (LOGD_RFKILL, "invalid wwan state from urfkill cached properties"); + } + + return enabled; +} + +static void +on_urfkill_appeared (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + NMUrfkillManager *self = NM_URFKILL_MANAGER (user_data); + + nm_log_info (LOGD_RFKILL, "urfkill appeared on the bus"); + + self->wlan_proxy_cancellable = g_cancellable_new (); + self->wwan_proxy_cancellable = g_cancellable_new (); + + g_dbus_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.URfkill", + "/org/freedesktop/URfkill/WLAN", + "org.freedesktop.URfkill.Killswitch", + self->wlan_proxy_cancellable, + wlan_proxy_created, + self); + + g_dbus_proxy_new (connection, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.freedesktop.URfkill", + "/org/freedesktop/URfkill/WWAN", + "org.freedesktop.URfkill.Killswitch", + self->wwan_proxy_cancellable, + wwan_proxy_created, + self); +} + +static void +on_urfkill_vanished (GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + NMUrfkillManager *self = NM_URFKILL_MANAGER (user_data); + + nm_log_info (LOGD_RFKILL, "urfkill disappeared from the bus"); + + if (self->wlan_proxy) + g_object_unref (self->wlan_proxy); + if (self->wwan_proxy) + g_object_unref (self->wwan_proxy); +} + +static void +nm_urfkill_manager_init (NMUrfkillManager *self) +{ + self->urfkill_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, + "org.freedesktop.URfkill", + 0, + on_urfkill_appeared, + on_urfkill_vanished, + self, + NULL); +} + +NMUrfkillManager * +nm_urfkill_manager_new (void) +{ + return NM_URFKILL_MANAGER (g_object_new (NM_TYPE_URFKILL_MANAGER, NULL)); +} + +static void +nm_urfkill_manager_finalize (GObject *object) +{ + NMUrfkillManager *mgr = NM_URFKILL_MANAGER (object); + + if (mgr->wlan_proxy_cancellable) + g_cancellable_cancel (mgr->wlan_proxy_cancellable); + if (mgr->wwan_proxy_cancellable) + g_cancellable_cancel (mgr->wwan_proxy_cancellable); + + if (mgr->urfkill_watch) { + g_bus_unwatch_name (mgr->urfkill_watch); + mgr->urfkill_watch = 0; + } + + if (mgr->wlan_proxy) + g_object_unref (mgr->wlan_proxy); + if (mgr->wwan_proxy) + g_object_unref (mgr->wwan_proxy); + + G_OBJECT_CLASS (nm_urfkill_manager_parent_class)->finalize (object); +} + +static void +nm_urfkill_manager_class_init (NMUrfkillManagerClass *class) +{ + class->finalize = nm_urfkill_manager_finalize; + + signals[WLAN_STATE_CHANGED] = + g_signal_new (NM_URFKILL_MANAGER_WLAN_STATE_CHANGED, + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, 0, + NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + signals[WWAN_STATE_CHANGED] = + g_signal_new (NM_URFKILL_MANAGER_WWAN_STATE_CHANGED, + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST, 0, + NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); +} + diff --git a/src/nm-urfkill-manager.h b/src/nm-urfkill-manager.h new file mode 100644 index 0000000..d99155b --- /dev/null +++ b/src/nm-urfkill-manager.h @@ -0,0 +1,50 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2006 - 2008 Red Hat, Inc. + * Copyright (C) 2006 - 2008 Novell, Inc. + */ + +#ifndef __NM_URFKILL_MANAGER_H__ +#define __NM_URFKILL_MANAGER_H__ + +#include <glib-object.h> + +#include "nm-glib.h" + +G_BEGIN_DECLS + +#define NM_TYPE_URFKILL_MANAGER (nm_urfkill_manager_get_type ()) +#define NM_URFKILL_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), NM_TYPE_URFKILL_MANAGER, NMUrfkillManager)) +#define NM_IS_URFKILL_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), NM_TYPE_URFKILL_MANAGER)) + +#define NM_URFKILL_MANAGER_WLAN_STATE_CHANGED "wlan-state-changed" +#define NM_URFKILL_MANAGER_WWAN_STATE_CHANGED "wwan-state-changed" + +typedef struct _NMUrfkillManager NMUrfkillManager; + +GType nm_urfkill_manager_get_type (void); + +NMUrfkillManager *nm_urfkill_manager_new (void); + +gboolean nm_urfkill_get_wlan_state (NMUrfkillManager *self); +gboolean nm_urfkill_get_wwan_state (NMUrfkillManager *self); + +G_END_DECLS + +#endif /* __NM_URFKILL_MANAGER_H__ */ + -- 2.7.4 _______________________________________________ networkmanager-list mailing list networkmanager-list@gnome.org https://mail.gnome.org/mailman/listinfo/networkmanager-list