diff options
| author | Michael Biebl <biebl@debian.org> | 2011-05-04 21:35:57 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2011-05-04 21:35:57 +0200 |
| commit | 3241555aff5c969104e492501097f4cb8837bcca (patch) | |
| tree | 6d15a02d02a9f1bfcda6075ae2b8c71537d8038d /src/nm-udev-manager.c | |
| parent | e1b66c145e71e7bc6a06845dd17788fb7b8e158e (diff) | |
| parent | 9f806e97a24bba61417ae312fcc0da40914266fb (diff) | |
Merge commit 'upstream/0.8.999' into experimental
Diffstat (limited to 'src/nm-udev-manager.c')
| -rw-r--r-- | src/nm-udev-manager.c | 135 |
1 files changed, 106 insertions, 29 deletions
diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index 3563a574..41a4e15b 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c @@ -74,6 +74,7 @@ typedef struct { char *driver; RfKillType rtype; gint state; + gboolean platform; } Killswitch; RfKillState @@ -91,7 +92,7 @@ rfkill_type_to_desc (RfKillType rtype) if (rtype == 0) return "WiFi"; else if (rtype == 1) - return "WWan"; + return "WWAN"; else if (rtype == 2) return "WiMAX"; return "unknown"; @@ -113,8 +114,8 @@ static Killswitch * killswitch_new (GUdevDevice *device, RfKillType rtype) { Killswitch *ks; - GUdevDevice *parent = NULL; - const char *driver; + GUdevDevice *parent = NULL, *grandparent = NULL; + const char *driver, *subsys, *parent_subsys = NULL; ks = g_malloc0 (sizeof (Killswitch)); ks->name = g_strdup (g_udev_device_get_name (device)); @@ -123,17 +124,33 @@ killswitch_new (GUdevDevice *device, RfKillType rtype) ks->rtype = rtype; driver = g_udev_device_get_property (device, "DRIVER"); - if (!driver) { - parent = g_udev_device_get_parent (device); - if (parent) + subsys = g_udev_device_get_subsystem (device); + + /* Check parent for various attributes */ + parent = g_udev_device_get_parent (device); + if (parent) { + parent_subsys = g_udev_device_get_subsystem (parent); + if (!driver) driver = g_udev_device_get_property (parent, "DRIVER"); + if (!driver) { + /* Sigh; try the grandparent */ + grandparent = g_udev_device_get_parent (parent); + if (grandparent) + driver = g_udev_device_get_property (parent, "DRIVER"); + } } - if (driver) - ks->driver = g_strdup (driver); + if (!driver) + driver = "(unknown)"; + ks->driver = g_strdup (driver); + + if (g_strcmp0 (subsys, "platform") == 0 || g_strcmp0 (parent_subsys, "platform") == 0) + ks->platform = TRUE; + + if (grandparent) + g_object_unref (grandparent); if (parent) g_object_unref (parent); - return ks; } @@ -178,28 +195,77 @@ recheck_killswitches (NMUdevManager *self) NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); GSList *iter; RfKillState poll_states[RFKILL_TYPE_MAX]; + gboolean platform_checked[RFKILL_TYPE_MAX]; int i; /* Default state is unblocked */ - for (i = 0; i < RFKILL_TYPE_MAX; i++) + for (i = 0; i < RFKILL_TYPE_MAX; i++) { poll_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 */ 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); + if (dev_state > poll_states[ks->rtype]) + poll_states[ks->rtype] = dev_state; + g_object_unref (device); + } + } + } - device = g_udev_client_query_by_subsystem_and_name (priv->client, "rfkill", ks->name); - if (!device) - continue; - - dev_state = sysfs_state_to_nm_state (g_udev_device_get_property_as_int (device, "RFKILL_STATE")); - 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); + } + } } + /* Log and emit change signal for final rfkill states */ for (i = 0; i < RFKILL_TYPE_MAX; i++) { if (poll_states[i] != priv->rfkill_states[i]) { nm_log_dbg (LOGD_RFKILL, "%s rfkill state now '%s'", @@ -385,8 +451,12 @@ device_creator (NMUdevManager *manager, } if (!driver) { - nm_log_warn (LOGD_HW, "%s: couldn't determine device driver; ignoring...", path); - goto out; + if (g_str_has_prefix (ifname, "easytether")) { + driver = "easytether"; + } else { + nm_log_warn (LOGD_HW, "%s: couldn't determine device driver; ignoring...", path); + goto out; + } } ifindex = g_udev_device_get_sysfs_attr_as_int (udev_device, "ifindex"); @@ -420,13 +490,26 @@ net_add (NMUdevManager *self, GUdevDevice *device) gint etype; const char *iface; const char *tmp; + gboolean is_ctc; g_return_if_fail (device != NULL); + iface = g_udev_device_get_name (device); + if (!iface) { + nm_log_dbg (LOGD_HW, "failed to get device's interface"); + return; + } + etype = g_udev_device_get_sysfs_attr_as_int (device, "type"); - if (etype != 1) { + is_ctc = (strncmp (iface, "ctc", 3) == 0) && (etype == 256); + + /* Ignore devices that don't report Ethernet encapsulation, except for + * s390 CTC-type devices that report 256 for some reason. + * FIXME: use something other than interface name to detect CTC here. + */ + if ((etype != 1) && (is_ctc == FALSE)) { nm_log_dbg (LOGD_HW, "ignoring interface with type %d", etype); - return; /* Not using ethernet encapsulation, don't care */ + return; } /* Not all ethernet devices are immediately usable; newer mobile broadband @@ -454,12 +537,6 @@ net_add (NMUdevManager *self, GUdevDevice *device) } } - iface = g_udev_device_get_name (device); - if (!iface) { - nm_log_dbg (LOGD_HW, "failed to get device's interface"); - return; - } - g_signal_emit (self, signals[DEVICE_ADDED], 0, device, device_creator); } |