2008-06-29 Dan Williams <dcbw@redhat.com>

* src/nm-hal-manager.c
		- Rework killswitch handling to query killswitch status immediately
			when the first killswitch is added, so that rfkill state is
			known as early as possible
		- Also treat failure of GetPower() as rfkill when the dbus method
			call times out (but not when the HAL callout returns an error)



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3781 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams 2008-06-29 15:46:31 +00:00
parent 1778405329
commit 01ea95f444
2 changed files with 87 additions and 67 deletions

View file

@ -1,3 +1,12 @@
2008-06-29 Dan Williams <dcbw@redhat.com>
* src/nm-hal-manager.c
- Rework killswitch handling to query killswitch status immediately
when the first killswitch is added, so that rfkill state is
known as early as possible
- Also treat failure of GetPower() as rfkill when the dbus method
call times out (but not when the HAL callout returns an error)
2008-06-26 Dan Williams <dcbw@redhat.com>
Patch from David Cantrell <dcantrell@redhat.com> and me

View file

@ -25,12 +25,15 @@ typedef struct {
LibHalContext *hal_ctx;
NMDBusManager *dbus_mgr;
GSList *device_creators;
gboolean rfkilled; /* Authoritative rfkill state */
/* Killswitch handling */
GSList *killswitch_list;
guint32 killswitch_poll_id;
char *kswitch_err;
gboolean rfkilled;
gboolean poll_rfkilled;
guint32 pending_polls;
GSList *poll_proxies;
gboolean disposed;
} NMHalManagerPrivate;
@ -51,6 +54,8 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
static gboolean poll_killswitches (gpointer user_data);
/* Device creators */
typedef struct {
@ -389,32 +394,43 @@ add_initial_devices (NMHalManager *self)
}
}
typedef struct {
NMHalManager *manager;
gboolean rfkilled;
guint32 pending_polls;
GSList *proxies;
} NMKillswitchPollInfo;
static void
killswitch_poll_cleanup (NMHalManager *self)
{
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
if (priv->poll_proxies) {
g_slist_foreach (priv->poll_proxies, (GFunc) g_object_unref, NULL);
g_slist_free (priv->poll_proxies);
priv->poll_proxies = NULL;
}
priv->pending_polls = 0;
priv->poll_rfkilled = FALSE;
}
static void
killswitch_getpower_done (gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager);
NMHalManager *self = NM_HAL_MANAGER (user_data);
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
info->pending_polls--;
priv->pending_polls--;
if (info->pending_polls > 0)
if (priv->pending_polls > 0)
return;
g_slist_foreach (info->proxies, (GFunc) g_object_unref, NULL);
g_slist_free (info->proxies);
info->proxies = NULL;
if (info->rfkilled != priv->rfkilled) {
priv->rfkilled = info->rfkilled;
g_signal_emit (info->manager, signals[RFKILL_CHANGED], 0, priv->rfkilled);
if (priv->poll_rfkilled != priv->rfkilled) {
priv->rfkilled = priv->poll_rfkilled;
g_signal_emit (self, signals[RFKILL_CHANGED], 0, priv->rfkilled);
}
killswitch_poll_cleanup (self);
/* Schedule next poll */
priv->killswitch_poll_id = g_timeout_add (RFKILL_POLL_FREQUENCY * 1000,
poll_killswitches,
self);
}
static void
@ -422,33 +438,50 @@ killswitch_getpower_reply (DBusGProxy *proxy,
DBusGProxyCall *call_id,
gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager);
int power;
NMHalManager *self = NM_HAL_MANAGER (user_data);
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
int power = 1;
GError *err = NULL;
if (dbus_g_proxy_end_call (proxy, call_id, &err,
G_TYPE_INT, &power,
G_TYPE_INVALID)) {
G_TYPE_INT, &power,
G_TYPE_INVALID)) {
if (power == 0)
info->rfkilled = TRUE;
priv->poll_rfkilled = TRUE;
} else {
/* Only print the error if we haven't seen it before */
if ( err->message
&& (!priv->kswitch_err || strcmp (priv->kswitch_err, err->message) != 0)) {
nm_warning ("Error getting killswitch power: %s.", err->message);
g_free (priv->kswitch_err);
priv->kswitch_err = g_strdup (err->message);
if (err->message) {
/* Only print the error if we haven't seen it before */
if (!priv->kswitch_err || strcmp (priv->kswitch_err, err->message) != 0) {
nm_warning ("Error getting killswitch power: %s.", err->message);
g_free (priv->kswitch_err);
priv->kswitch_err = g_strdup (err->message);
/* If there was an error talking to HAL, treat that as rfkilled.
* See rh #448889. On some Dell laptops, dellWirelessCtl
* may not be present, but HAL still advertises a killswitch,
* and calls to GetPower() will fail. Thus we cannot assume
* that a failure of GetPower() automatically means the wireless
* is rfkilled, because in this situation NM would never bring
* the radio up. Only assume failures between NM and HAL should
* block the radio, not failures of the HAL killswitch callout
* itself.
*/
if (strstr (err->message, "Did not receive a reply")) {
nm_warning ("HAL did not reply to killswitch power request;"
" assuming radio is blocked.");
priv->poll_rfkilled = TRUE;
}
}
}
g_error_free (err);
}
}
static void
poll_killswitches_real (gpointer data, gpointer user_data)
poll_one_killswitch (gpointer data, gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager);
NMHalManager *self = NM_HAL_MANAGER (user_data);
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
DBusGProxy *proxy;
proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr),
@ -458,36 +491,23 @@ poll_killswitches_real (gpointer data, gpointer user_data)
dbus_g_proxy_begin_call (proxy, "GetPower",
killswitch_getpower_reply,
info,
self,
killswitch_getpower_done,
G_TYPE_INVALID);
info->pending_polls++;
info->proxies = g_slist_prepend (info->proxies, proxy);
priv->pending_polls++;
priv->poll_proxies = g_slist_prepend (priv->poll_proxies, proxy);
}
static gboolean
poll_killswitches (gpointer user_data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data;
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager);
NMHalManager *self = NM_HAL_MANAGER (user_data);
NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
info->rfkilled = FALSE;
info->pending_polls = 0;
killswitch_poll_cleanup (self);
g_slist_foreach (priv->killswitch_list, poll_killswitches_real, info);
return TRUE;
}
static void
killswitch_poll_destroy (gpointer data)
{
NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) data;
if (info->proxies) {
g_slist_foreach (info->proxies, (GFunc) g_object_unref, NULL);
g_slist_free (info->proxies);
}
g_slice_free (NMKillswitchPollInfo, info);
g_slist_foreach (priv->killswitch_list, poll_one_killswitch, self);
return FALSE;
}
static void
@ -511,19 +531,9 @@ add_killswitch_device (NMHalManager *self, const char *udi)
goto out;
}
/* Start polling switches if this is the first switch we've found */
if (!priv->killswitch_list) {
NMKillswitchPollInfo *info;
info = g_slice_new0 (NMKillswitchPollInfo);
info->manager = self;
priv->killswitch_poll_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
RFKILL_POLL_FREQUENCY * 1000,
poll_killswitches,
info,
killswitch_poll_destroy);
}
/* Poll switches if this is the first switch we've found */
if (!priv->killswitch_list)
priv->killswitch_poll_id = g_idle_add (poll_killswitches, self);
priv->killswitch_list = g_slist_append (priv->killswitch_list, g_strdup (udi));
nm_info ("Found radio killswitch %s", udi);
@ -617,6 +627,7 @@ hal_deinit (NMHalManager *self)
g_source_remove (priv->killswitch_poll_id);
priv->killswitch_poll_id = 0;
}
killswitch_poll_cleanup (self);
if (priv->killswitch_list) {
g_slist_foreach (priv->killswitch_list, (GFunc) g_free, NULL);