134 lines
4.9 KiB
Diff
134 lines
4.9 KiB
Diff
From 339229e4c698c61e20a28bfc33d8501490891427 Mon Sep 17 00:00:00 2001
|
|
From: Gary Ching-Pang Lin <chingpang@gmail.com>
|
|
Date: Tue, 20 Sep 2011 08:36:35 +0000
|
|
Subject: core: improving handling of rfkill (bgo #655773)
|
|
|
|
This commit improves the handling of rfkill.
|
|
|
|
- The original two passes check gathers the states of platform
|
|
and non-platform switches in two separate loops. Now we gather
|
|
the both states in one loop and determine the final states later.
|
|
|
|
- A new rule is used to determine the states of switches.
|
|
|
|
if (platform_state == UNBLOCKED)
|
|
choose non_platform_state;
|
|
else
|
|
choose platform_state;
|
|
|
|
The state is UNBLOCKED if and only if both the platform and
|
|
non-platform switches are unblocked, so the ambiguous state in
|
|
bgo#655773 will not happen.
|
|
|
|
Original code always preferred the platform switch state over
|
|
the device switch state, so if the platform switch was UNBLOCKED
|
|
but the device was BLOCKED, NM would treat the device as
|
|
UNBLOCKED and try to activate it, and obviously fail.
|
|
---
|
|
diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c
|
|
index 72501c2..3e855b7 100644
|
|
--- a/src/nm-udev-manager.c
|
|
+++ b/src/nm-udev-manager.c
|
|
@@ -195,78 +195,50 @@ recheck_killswitches (NMUdevManager *self)
|
|
NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self);
|
|
GSList *iter;
|
|
RfKillState poll_states[RFKILL_TYPE_MAX];
|
|
+ RfKillState platform_states[RFKILL_TYPE_MAX];
|
|
gboolean platform_checked[RFKILL_TYPE_MAX];
|
|
int i;
|
|
|
|
/* Default state is unblocked */
|
|
for (i = 0; i < RFKILL_TYPE_MAX; i++) {
|
|
poll_states[i] = RFKILL_UNBLOCKED;
|
|
+ platform_states[i] = RFKILL_UNBLOCKED;
|
|
platform_checked[i] = FALSE;
|
|
}
|
|
|
|
- /* Perform two passes here; the first pass is for non-platform switches,
|
|
- * which typically if hardkilled cannot be changed except by a physical
|
|
- * hardware switch. The second pass checks platform killswitches, which
|
|
- * take precedence over device killswitches, because typically platform
|
|
- * killswitches control device killswitches. That is, a hardblocked device
|
|
- * switch can often be unblocked by a platform switch. Thus if we have
|
|
- * a hardblocked device switch and a softblocked platform switch, the
|
|
- * combined state should be softblocked since the platform switch can be
|
|
- * unblocked to change the device switch.
|
|
- */
|
|
-
|
|
- /* Device switches first */
|
|
+ /* Poll the states of all killswitches */
|
|
for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) {
|
|
Killswitch *ks = iter->data;
|
|
GUdevDevice *device;
|
|
RfKillState dev_state;
|
|
int sysfs_state;
|
|
|
|
- if (ks->platform == FALSE) {
|
|
- device = g_udev_client_query_by_subsystem_and_name (priv->client, "rfkill", ks->name);
|
|
- if (device) {
|
|
- sysfs_state = g_udev_device_get_property_as_int (device, "RFKILL_STATE");
|
|
- dev_state = sysfs_state_to_nm_state (sysfs_state);
|
|
+ device = g_udev_client_query_by_subsystem_and_name (priv->client, "rfkill", ks->name);
|
|
+ if (device) {
|
|
+ sysfs_state = g_udev_device_get_property_as_int (device, "RFKILL_STATE");
|
|
+ dev_state = sysfs_state_to_nm_state (sysfs_state);
|
|
+ if (ks->platform == FALSE) {
|
|
if (dev_state > poll_states[ks->rtype])
|
|
poll_states[ks->rtype] = dev_state;
|
|
- g_object_unref (device);
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- /* Platform switches next; their state overwrites device state */
|
|
- for (iter = priv->killswitches; iter; iter = g_slist_next (iter)) {
|
|
- Killswitch *ks = iter->data;
|
|
- GUdevDevice *device;
|
|
- RfKillState dev_state;
|
|
- int sysfs_state;
|
|
-
|
|
- if (ks->platform == TRUE) {
|
|
- device = g_udev_client_query_by_subsystem_and_name (priv->client, "rfkill", ks->name);
|
|
- if (device) {
|
|
- sysfs_state = g_udev_device_get_property_as_int (device, "RFKILL_STATE");
|
|
- dev_state = sysfs_state_to_nm_state (sysfs_state);
|
|
-
|
|
- if (platform_checked[ks->rtype] == FALSE) {
|
|
- /* Overwrite device state with platform state for first
|
|
- * platform switch found.
|
|
- */
|
|
- poll_states[ks->rtype] = dev_state;
|
|
- platform_checked[ks->rtype] = TRUE;
|
|
- } else {
|
|
- /* If there are multiple platform switches of the same type,
|
|
- * take the "worst" state for all of that type.
|
|
- */
|
|
- if (dev_state > poll_states[ks->rtype])
|
|
- poll_states[ks->rtype] = dev_state;
|
|
- }
|
|
- g_object_unref (device);
|
|
+ } else {
|
|
+ platform_checked[ks->rtype] = TRUE;
|
|
+ if (dev_state > platform_states[ks->rtype])
|
|
+ platform_states[ks->rtype] = dev_state;
|
|
}
|
|
+ g_object_unref (device);
|
|
}
|
|
}
|
|
|
|
/* Log and emit change signal for final rfkill states */
|
|
for (i = 0; i < RFKILL_TYPE_MAX; i++) {
|
|
+ if (platform_checked[i] == TRUE) {
|
|
+ /* blocked platform switch state overrides device state, otherwise
|
|
+ * let the device state stand. (bgo #655773)
|
|
+ */
|
|
+ if (platform_states[i] != RFKILL_UNBLOCKED)
|
|
+ poll_states[i] = platform_states[i];
|
|
+ }
|
|
+
|
|
if (poll_states[i] != priv->rfkill_states[i]) {
|
|
nm_log_dbg (LOGD_RFKILL, "%s rfkill state now '%s'",
|
|
rfkill_type_to_desc (i),
|
|
--
|
|
cgit v0.9.0.2-2-gbebe
|