On Wed, 2016-06-08 at 16:20 -0400, Tony Espy wrote: > 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
This hunk wouldn't apply upstream since config.h.in gets auto- generated... so can just be removed from the patch. > 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; > + } nm_clear_g_source(&priv->rfkill_initial_id) replaces all 4 of these lines; but as below I don't think we'd really need them. > + 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" ); For your own patches in Ubuntu, wouldn't you need to clear rfkill_initial_id here too? Just in case WWAN gets emitted before WLAN. > + 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_s > tate, > + kill_s > tate_free); > } This looks a bit odd; what is the timeout supposed to do? I'd expect that the urfkill-manager would emit the initial state signals when it got the initial states from the GDBusProxy and then the manager would update. Which shouldn't need a timeout to update the states... what problem did the timeout solve for you here? > + > 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); See below... > + 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 the urfkill-manager got destroyed/finalized while the proxy creation was in-flight, you'll crash here because of the 'self' assignment, since 'user_data'/self is already de-allocated. But that's fairly easy to handle, what you want to do is just: NMUrfkillManager *self; .... wwan_proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) return; self = NM_URFKILL_MANAGER (user_data); alternatively, you can g_object_ref (self) in the g_dbus_proxy_new() call and then unref everywhere this function returns, but that's not really worth it. > + 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); g_clear_object() for style points. > +} > + > +static void > +nm_urfkill_manager_init (NMUrfkillManager *self) > +{ > + self->urfkill_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, > + "org.freedesktop.URf > kill", > + 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); Need to g_object_unref() them too otherwise they get leaked. > + 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_clear_object() for style points. > + 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__ */ > + _______________________________________________ networkmanager-list mailing list networkmanager-list@gnome.org https://mail.gnome.org/mailman/listinfo/networkmanager-list