diff --git a/ChangeLog b/ChangeLog index 8f81a3b718..a06967bfc5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,44 @@ +2008-04-29 Dan Williams + + Handle HAL dropouts better; allow NM to start up even if HAL isn't up yet. + + * marshallers/nm-marshal.list + - Add marshaller + + * src/NetworkManager.c + - (main): let the NMManager handle the NMHalManager + + * src/nm-hal-manager.c + src/nm-hal-manager.h + - convert to a GObject, and emit singals when stuff changes. Let the + NMManager handle the signals, instead of the NMHalManager calling + into the NMManager. + + * src/nm-manager.c + src/nm-manager.h + - (remove_one_device): consolidate device removals here + - (dispose): use remove_one_device() + - (nm_manager_get_device_by_udi): make static + - (deferred_hal_manager_query_devices): idle handler to query the HAL + manager for devices at startup or wakeup time + - (nm_manager_new): create and monitor the HAL manager + - (hal_manager_udi_added_cb): new function; do what + nm_manager_add_device() used to do when signalled by the hal manager + - (hal_manager_udi_removed_cb): new function; do what + nm_manager_remove_device() used to do when signalled by the hal + manager + - (hal_manager_rfkill_changed_cb): handle rfkill changes from the + hal manager + - (hal_manager_hal_reappeared_cb): when HAL comes back, remove devices + in our device list that aren't known to HAL + - (impl_manager_sleep): on wakeup, re-add devices from an idle handler; + see comments on nm-hal-manager.c::nm_manager_state_changed() a few + commits ago + - (nm_manager_get_device_by_path, nm_manager_is_udi_managed, + nm_manager_activation_pending, nm_manager_wireless_enabled, + nm_manager_wireless_hardware_enabled, + nm_manager_set_wireless_hardware_enabled): remove, unused + 2008-04-28 Dan Williams Fix the device up/down ambiguities. Up/down state used to be a diff --git a/marshallers/nm-marshal.list b/marshallers/nm-marshal.list index 0878e5f339..6172f94fd7 100644 --- a/marshallers/nm-marshal.list +++ b/marshallers/nm-marshal.list @@ -8,6 +8,7 @@ VOID:UINT,UINT VOID:STRING,STRING VOID:STRING,UCHAR VOID:STRING,OBJECT +VOID:STRING,STRING,POINTER VOID:OBJECT,UINT,UINT VOID:STRING,INT VOID:STRING,UINT diff --git a/src/NetworkManager.c b/src/NetworkManager.c index 048850c86e..753a819d43 100644 --- a/src/NetworkManager.c +++ b/src/NetworkManager.c @@ -43,7 +43,6 @@ #include "NetworkManagerUtils.h" #include "nm-device-interface.h" #include "nm-manager.h" -#include "nm-hal-manager.h" #include "nm-device.h" #include "nm-device-802-3-ethernet.h" #include "nm-device-802-11-wireless.h" @@ -205,13 +204,6 @@ write_pidfile (const char *pidfile) nm_warning ("Closing %s failed: %s", pidfile, strerror (errno)); } -static gboolean -start_hal (gpointer user_data) -{ - nm_hal_manager_start ((NMHalManager *) user_data); - return FALSE; -} - /* * main * @@ -225,7 +217,6 @@ main (int argc, char *argv[]) char * user_pidfile = NULL; gboolean success; NMPolicy *policy = NULL; - NMHalManager *hal_manager = NULL; NMVPNManager *vpn_manager = NULL; NMNamedManager *named_mgr = NULL; NMDBusManager * dbus_mgr = NULL; @@ -347,11 +338,6 @@ main (int argc, char *argv[]) goto done; } - hal_manager = nm_hal_manager_new (manager); - if (!hal_manager) - goto done; - g_idle_add (start_hal, hal_manager); - /* Bring up the loopback interface. */ nm_system_enable_loopback (); @@ -362,9 +348,6 @@ main (int argc, char *argv[]) g_main_loop_run (main_loop); done: - if (hal_manager) - nm_hal_manager_destroy (hal_manager); - if (policy) nm_policy_destroy (policy); diff --git a/src/nm-hal-manager.c b/src/nm-hal-manager.c index 8c2cbb040b..f006bb9b80 100644 --- a/src/nm-hal-manager.c +++ b/src/nm-hal-manager.c @@ -8,6 +8,7 @@ #include #include "nm-hal-manager.h" +#include "nm-marshal.h" #include "nm-dbus-manager.h" #include "nm-utils.h" #include "nm-device-802-11-wireless.h" @@ -16,47 +17,61 @@ #include "nm-cdma-device.h" /* Killswitch poll frequency in seconds */ -#define NM_HAL_MANAGER_KILLSWITCH_POLL_FREQUENCY 6 +#define RFKILL_POLL_FREQUENCY 6 -struct _NMHalManager { +#define HAL_DBUS_SERVICE "org.freedesktop.Hal" + +typedef struct { LibHalContext *hal_ctx; NMDBusManager *dbus_mgr; - NMManager *nm_manager; GSList *device_creators; - gboolean nm_sleeping; - guint add_devices_id; - /* Killswitch handling */ GSList *killswitch_list; guint32 killswitch_poll_id; char *kswitch_err; + gboolean rfkilled; + + gboolean disposed; +} NMHalManagerPrivate; + +#define NM_HAL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_HAL_MANAGER, NMHalManagerPrivate)) + +G_DEFINE_TYPE (NMHalManager, nm_hal_manager, G_TYPE_OBJECT) + +enum { + UDI_ADDED, + UDI_REMOVED, + RFKILL_CHANGED, + HAL_REAPPEARED, + + LAST_SIGNAL }; -/* Device creators */ +static guint signals[LAST_SIGNAL] = { 0 }; -typedef NMDevice *(*NMDeviceCreatorFn) (NMHalManager *manager, - const char *udi, - gboolean managed); + +/* Device creators */ typedef struct { char *device_type_name; char *capability_str; - gboolean (*is_device_fn) (NMHalManager *manager, const char *udi); + gboolean (*is_device_fn) (NMHalManager *self, const char *udi); NMDeviceCreatorFn creator_fn; } DeviceCreator; static DeviceCreator * -get_creator (NMHalManager *manager, const char *udi) +get_creator (NMHalManager *self, const char *udi) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); DeviceCreator *creator; GSList *iter; - for (iter = manager->device_creators; iter; iter = iter->next) { + for (iter = priv->device_creators; iter; iter = g_slist_next (iter)) { creator = (DeviceCreator *) iter->data; - if (libhal_device_query_capability (manager->hal_ctx, udi, creator->capability_str, NULL) && - creator->is_device_fn (manager, udi)) + if (libhal_device_query_capability (priv->hal_ctx, udi, creator->capability_str, NULL) && + creator->is_device_fn (self, udi)) return creator; } @@ -92,15 +107,16 @@ nm_get_device_driver_name (LibHalContext *ctx, const char *udi) /* Wired device creator */ static gboolean -is_wired_device (NMHalManager *manager, const char *udi) +is_wired_device (NMHalManager *self, const char *udi) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); char *category; gboolean is_wired = FALSE; - if (libhal_device_property_exists (manager->hal_ctx, udi, "net.linux.ifindex", NULL) && - libhal_device_property_exists (manager->hal_ctx, udi, "info.category", NULL)) { + if (libhal_device_property_exists (priv->hal_ctx, udi, "net.linux.ifindex", NULL) && + libhal_device_property_exists (priv->hal_ctx, udi, "info.category", NULL)) { - category = libhal_device_get_property_string (manager->hal_ctx, udi, "info.category", NULL); + category = libhal_device_get_property_string (priv->hal_ctx, udi, "info.category", NULL); if (category) { is_wired = strcmp (category, "net.80203") == 0; libhal_free_string (category); @@ -110,21 +126,22 @@ is_wired_device (NMHalManager *manager, const char *udi) return is_wired; } -static NMDevice * -wired_device_creator (NMHalManager *manager, const char *udi, gboolean managed) +static GObject * +wired_device_creator (NMHalManager *self, const char *udi, gboolean managed) { - NMDevice *device; + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); + GObject *device; char *iface; char *driver; - iface = libhal_device_get_property_string (manager->hal_ctx, udi, "net.interface", NULL); + iface = libhal_device_get_property_string (priv->hal_ctx, udi, "net.interface", NULL); if (!iface) { nm_warning ("Couldn't get interface for %s, ignoring.", udi); return NULL; } - driver = nm_get_device_driver_name (manager->hal_ctx, udi); - device = (NMDevice *) nm_device_802_3_ethernet_new (udi, iface, driver, managed); + driver = nm_get_device_driver_name (priv->hal_ctx, udi); + device = (GObject *) nm_device_802_3_ethernet_new (udi, iface, driver, managed); libhal_free_string (iface); g_free (driver); @@ -135,15 +152,16 @@ wired_device_creator (NMHalManager *manager, const char *udi, gboolean managed) /* Wireless device creator */ static gboolean -is_wireless_device (NMHalManager *manager, const char *udi) +is_wireless_device (NMHalManager *self, const char *udi) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); char *category; gboolean is_wireless = FALSE; - if (libhal_device_property_exists (manager->hal_ctx, udi, "net.linux.ifindex", NULL) && - libhal_device_property_exists (manager->hal_ctx, udi, "info.category", NULL)) { + if (libhal_device_property_exists (priv->hal_ctx, udi, "net.linux.ifindex", NULL) && + libhal_device_property_exists (priv->hal_ctx, udi, "info.category", NULL)) { - category = libhal_device_get_property_string (manager->hal_ctx, udi, "info.category", NULL); + category = libhal_device_get_property_string (priv->hal_ctx, udi, "info.category", NULL); if (category) { is_wireless = strcmp (category, "net.80211") == 0; libhal_free_string (category); @@ -153,21 +171,22 @@ is_wireless_device (NMHalManager *manager, const char *udi) return is_wireless; } -static NMDevice * -wireless_device_creator (NMHalManager *manager, const char *udi, gboolean managed) +static GObject * +wireless_device_creator (NMHalManager *self, const char *udi, gboolean managed) { - NMDevice *device; + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); + GObject *device; char *iface; char *driver; - iface = libhal_device_get_property_string (manager->hal_ctx, udi, "net.interface", NULL); + iface = libhal_device_get_property_string (priv->hal_ctx, udi, "net.interface", NULL); if (!iface) { nm_warning ("Couldn't get interface for %s, ignoring.", udi); return NULL; } - driver = nm_get_device_driver_name (manager->hal_ctx, udi); - device = (NMDevice *) nm_device_802_11_wireless_new (udi, iface, driver, managed); + driver = nm_get_device_driver_name (priv->hal_ctx, udi); + device = (GObject *) nm_device_802_11_wireless_new (udi, iface, driver, managed); libhal_free_string (iface); g_free (driver); @@ -178,14 +197,15 @@ wireless_device_creator (NMHalManager *manager, const char *udi, gboolean manage /* Modem device creator */ static gboolean -is_modem_device (NMHalManager *manager, const char *udi) +is_modem_device (NMHalManager *self, const char *udi) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); gboolean is_modem = FALSE; - if (libhal_device_property_exists (manager->hal_ctx, udi, "info.category", NULL)) { + if (libhal_device_property_exists (priv->hal_ctx, udi, "info.category", NULL)) { char *category; - category = libhal_device_get_property_string (manager->hal_ctx, udi, "info.category", NULL); + category = libhal_device_get_property_string (priv->hal_ctx, udi, "info.category", NULL); if (category) { is_modem = strcmp (category, "serial") == 0; libhal_free_string (category); @@ -195,30 +215,31 @@ is_modem_device (NMHalManager *manager, const char *udi) return is_modem; } -static NMDevice * -modem_device_creator (NMHalManager *manager, const char *udi, gboolean managed) +static GObject * +modem_device_creator (NMHalManager *self, const char *udi, gboolean managed) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); char *serial_device; char *parent_udi; char *driver_name = NULL; - NMDevice *device = NULL; + GObject *device = NULL; char **capabilities, **iter; gboolean type_gsm = FALSE; gboolean type_cdma = FALSE; - serial_device = libhal_device_get_property_string (manager->hal_ctx, udi, "serial.device", NULL); + serial_device = libhal_device_get_property_string (priv->hal_ctx, udi, "serial.device", NULL); /* Get the driver */ - parent_udi = libhal_device_get_property_string (manager->hal_ctx, udi, "info.parent", NULL); + parent_udi = libhal_device_get_property_string (priv->hal_ctx, udi, "info.parent", NULL); if (parent_udi) { - driver_name = libhal_device_get_property_string (manager->hal_ctx, parent_udi, "info.linux.driver", NULL); + driver_name = libhal_device_get_property_string (priv->hal_ctx, parent_udi, "info.linux.driver", NULL); libhal_free_string (parent_udi); } if (!serial_device || !driver_name) goto out; - capabilities = libhal_device_get_property_strlist (manager->hal_ctx, udi, "modem.command_sets", NULL); + capabilities = libhal_device_get_property_strlist (priv->hal_ctx, udi, "modem.command_sets", NULL); for (iter = capabilities; *iter; iter++) { if (!strcmp (*iter, "GSM-07.07")) { type_gsm = TRUE; @@ -233,7 +254,7 @@ modem_device_creator (NMHalManager *manager, const char *udi, gboolean managed) /* Compatiblity with the pre-specification bits */ if (!type_gsm && !type_cdma) { - capabilities = libhal_device_get_property_strlist (manager->hal_ctx, udi, "info.capabilities", NULL); + capabilities = libhal_device_get_property_strlist (priv->hal_ctx, udi, "info.capabilities", NULL); for (iter = capabilities; *iter; iter++) { if (!strcmp (*iter, "gsm")) { type_gsm = TRUE; @@ -248,9 +269,9 @@ modem_device_creator (NMHalManager *manager, const char *udi, gboolean managed) } if (type_gsm) - device = (NMDevice *) nm_gsm_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed); + device = (GObject *) nm_gsm_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed); else if (type_cdma) - device = (NMDevice *) nm_cdma_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed); + device = (GObject *) nm_cdma_device_new (udi, serial_device + strlen ("/dev/"), NULL, driver_name, managed); out: libhal_free_string (serial_device); @@ -260,8 +281,9 @@ out: } static void -register_built_in_creators (NMHalManager *manager) +register_built_in_creators (NMHalManager *self) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); DeviceCreator *creator; /* Wired device */ @@ -270,7 +292,7 @@ register_built_in_creators (NMHalManager *manager) creator->capability_str = g_strdup ("net.80203"); creator->is_device_fn = is_wired_device; creator->creator_fn = wired_device_creator; - manager->device_creators = g_slist_append (manager->device_creators, creator); + priv->device_creators = g_slist_append (priv->device_creators, creator); /* Wireless device */ creator = g_slice_new0 (DeviceCreator); @@ -278,7 +300,7 @@ register_built_in_creators (NMHalManager *manager) creator->capability_str = g_strdup ("net.80211"); creator->is_device_fn = is_wireless_device; creator->creator_fn = wireless_device_creator; - manager->device_creators = g_slist_append (manager->device_creators, creator); + priv->device_creators = g_slist_append (priv->device_creators, creator); /* Modem */ creator = g_slice_new0 (DeviceCreator); @@ -286,91 +308,53 @@ register_built_in_creators (NMHalManager *manager) creator->capability_str = g_strdup ("modem"); creator->is_device_fn = is_modem_device; creator->creator_fn = modem_device_creator; - manager->device_creators = g_slist_append (manager->device_creators, creator); -} - -static void -create_device_and_add_to_list (NMHalManager *manager, - DeviceCreator *creator, - const char *udi) -{ - NMDevice *dev; - gboolean managed; - - /* Make sure the device is not already in the device list */ - if ((dev = nm_manager_get_device_by_udi (manager->nm_manager, udi))) - return; - - managed = nm_manager_is_udi_managed (manager->nm_manager, udi); - dev = creator->creator_fn (manager, udi, managed); - if (dev) { - nm_info ("Found new %s device '%s'.", - creator->device_type_name, - nm_device_get_iface (dev)); - - nm_manager_add_device (manager->nm_manager, dev); - g_object_unref (dev); - } + priv->device_creators = g_slist_append (priv->device_creators, creator); } static void device_added (LibHalContext *ctx, const char *udi) { - NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx); + NMHalManager *self = NM_HAL_MANAGER (libhal_ctx_get_user_data (ctx)); DeviceCreator *creator; // nm_debug ("New device added (hal udi is '%s').", udi ); - /* Ignore device additions while asleep, all devices will - * be found and set up again on wake. - */ - if (nm_manager_get_state (manager->nm_manager) == NM_STATE_ASLEEP) - return; - /* Sometimes the device's properties (like net.interface) are not set up yet, * so this call will fail, and it will actually be added when hal sets the device's * capabilities a bit later on. */ - creator = get_creator (manager, udi); + creator = get_creator (self, udi); if (creator) - create_device_and_add_to_list (manager, creator, udi); + g_signal_emit (self, signals[UDI_ADDED], 0, udi, creator->device_type_name, creator->creator_fn); } static void device_removed (LibHalContext *ctx, const char *udi) { - NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx); - NMDevice *dev; + NMHalManager *self = NM_HAL_MANAGER (libhal_ctx_get_user_data (ctx)); // nm_debug ("Device removed (hal udi is '%s').", udi ); - if ((dev = nm_manager_get_device_by_udi (manager->nm_manager, udi))) - nm_manager_remove_device (manager->nm_manager, dev, TRUE); + g_signal_emit (self, signals[UDI_REMOVED], 0, udi); } static void device_new_capability (LibHalContext *ctx, const char *udi, const char *capability) { - NMHalManager *manager = (NMHalManager *) libhal_ctx_get_user_data (ctx); + NMHalManager *self = NM_HAL_MANAGER (libhal_ctx_get_user_data (ctx)); DeviceCreator *creator; - /*nm_debug ("nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability );*/ +// nm_debug ("nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability ); - /* Ignore device additions while asleep, all devices will - * be found and set up again on wake. - */ - if (nm_manager_get_state (manager->nm_manager) == NM_STATE_ASLEEP) - return; - - creator = get_creator (manager, udi); + creator = get_creator (self, udi); if (creator) - create_device_and_add_to_list (manager, creator, udi); + g_signal_emit (self, signals[UDI_ADDED], 0, udi, creator->device_type_name, creator->creator_fn); } -static gboolean -add_initial_devices (gpointer user_data) +static void +add_initial_devices (NMHalManager *self) { - NMHalManager *manager = (NMHalManager *) user_data; + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); DeviceCreator *creator; GSList *iter; char **devices; @@ -378,13 +362,11 @@ add_initial_devices (gpointer user_data) int i; DBusError err; - manager->add_devices_id = 0; - - for (iter = manager->device_creators; iter; iter = iter->next) { + for (iter = priv->device_creators; iter; iter = g_slist_next (iter)) { creator = (DeviceCreator *) iter->data; dbus_error_init (&err); - devices = libhal_find_device_by_capability (manager->hal_ctx, + devices = libhal_find_device_by_capability (priv->hal_ctx, creator->capability_str, &num_devices, &err); @@ -396,21 +378,19 @@ add_initial_devices (gpointer user_data) if (devices) { for (i = 0; i < num_devices; i++) { - if (creator->is_device_fn (manager, devices[i])) - create_device_and_add_to_list (manager, creator, devices[i]); + if (!creator->is_device_fn (self, devices[i])) + continue; + g_signal_emit (self, signals[UDI_ADDED], 0, devices[i], creator->device_type_name, creator->creator_fn); } } libhal_free_string_array (devices); } - - return FALSE; } typedef struct { NMHalManager *manager; - gboolean initial_state; - gboolean changed; + gboolean rfkilled; guint32 pending_polls; GSList *proxies; } NMKillswitchPollInfo; @@ -419,16 +399,20 @@ static void killswitch_getpower_done (gpointer user_data) { NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data; + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager); info->pending_polls--; - if (info->pending_polls == 0) { - g_slist_foreach (info->proxies, (GFunc) g_object_unref, NULL); - g_slist_free (info->proxies); - info->proxies = NULL; + if (info->pending_polls > 0) + return; - if (info->changed) - nm_manager_set_wireless_hardware_enabled (info->manager->nm_manager, !info->initial_state); + 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); } } @@ -438,23 +422,22 @@ killswitch_getpower_reply (DBusGProxy *proxy, gpointer user_data) { NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data; - int status; + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager); + int power; GError *err = NULL; if (dbus_g_proxy_end_call (proxy, call_id, &err, - G_TYPE_INT, &status, + G_TYPE_INT, &power, G_TYPE_INVALID)) { - if (!info->changed && info->initial_state != (status == 0) ? FALSE : TRUE) - info->changed = TRUE; + if (power == 0) + info->rfkilled = TRUE; } else { - const char *prev_err = info->manager->kswitch_err; - /* Only print the error if we haven't seen it before */ if ( err->message - && (!prev_err || strcmp (prev_err, err->message) != 0)) { + && (!priv->kswitch_err || strcmp (priv->kswitch_err, err->message) != 0)) { nm_warning ("Error getting killswitch power: %s.", err->message); - g_free (info->manager->kswitch_err); - info->manager->kswitch_err = g_strdup (err->message); + g_free (priv->kswitch_err); + priv->kswitch_err = g_strdup (err->message); } g_error_free (err); } @@ -464,9 +447,10 @@ static void poll_killswitches_real (gpointer data, gpointer user_data) { NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data; + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager); DBusGProxy *proxy; - proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (info->manager->dbus_mgr), + proxy = dbus_g_proxy_new_for_name (nm_dbus_manager_get_connection (priv->dbus_mgr), "org.freedesktop.Hal", (char *) data, "org.freedesktop.Hal.Device.KillSwitch"); @@ -484,12 +468,12 @@ static gboolean poll_killswitches (gpointer user_data) { NMKillswitchPollInfo *info = (NMKillswitchPollInfo *) user_data; + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (info->manager); - info->initial_state = nm_manager_wireless_hardware_enabled (info->manager->nm_manager); - info->changed = FALSE; + info->rfkilled = FALSE; info->pending_polls = 0; - g_slist_foreach (info->manager->killswitch_list, poll_killswitches_real, info); + g_slist_foreach (priv->killswitch_list, poll_killswitches_real, info); return TRUE; } @@ -506,12 +490,13 @@ killswitch_poll_destroy (gpointer data) } static void -add_killswitch_device (NMHalManager *manager, const char *udi) +add_killswitch_device (NMHalManager *self, const char *udi) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); char *type; GSList *iter; - type = libhal_device_get_property_string (manager->hal_ctx, udi, "killswitch.type", NULL); + type = libhal_device_get_property_string (priv->hal_ctx, udi, "killswitch.type", NULL); if (!type) return; @@ -519,27 +504,27 @@ add_killswitch_device (NMHalManager *manager, const char *udi) goto out; /* see if it's already in the list */ - for (iter = manager->killswitch_list; iter; iter = iter->next) { + for (iter = priv->killswitch_list; iter; iter = iter->next) { const char *list_udi = (const char *) iter->data; if (!strcmp (list_udi, udi)) goto out; } /* Start polling switches if this is the first switch we've found */ - if (!manager->killswitch_list) { + if (!priv->killswitch_list) { NMKillswitchPollInfo *info; info = g_slice_new0 (NMKillswitchPollInfo); - info->manager = manager; + info->manager = self; - manager->killswitch_poll_id = g_timeout_add_full (G_PRIORITY_DEFAULT, - NM_HAL_MANAGER_KILLSWITCH_POLL_FREQUENCY * 1000, + priv->killswitch_poll_id = g_timeout_add_full (G_PRIORITY_DEFAULT, + RFKILL_POLL_FREQUENCY * 1000, poll_killswitches, info, killswitch_poll_destroy); } - manager->killswitch_list = g_slist_append (manager->killswitch_list, g_strdup (udi)); + priv->killswitch_list = g_slist_append (priv->killswitch_list, g_strdup (udi)); nm_info ("Found radio killswitch %s", udi); out: @@ -547,15 +532,16 @@ out: } static void -add_killswitch_devices (NMHalManager *manager) +add_killswitch_devices (NMHalManager *self) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); char **udis; int num_udis; int i; DBusError err; dbus_error_init (&err); - udis = libhal_find_device_by_capability (manager->hal_ctx, "killswitch", &num_udis, &err); + udis = libhal_find_device_by_capability (priv->hal_ctx, "killswitch", &num_udis, &err); if (!udis) return; @@ -566,44 +552,45 @@ add_killswitch_devices (NMHalManager *manager) } for (i = 0; i < num_udis; i++) - add_killswitch_device (manager, udis[i]); + add_killswitch_device (self, udis[i]); libhal_free_string_array (udis); } static gboolean -hal_init (NMHalManager *manager) +hal_init (NMHalManager *self) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); DBusError error; DBusGConnection *connection; - manager->hal_ctx = libhal_ctx_new (); - if (!manager->hal_ctx) { + priv->hal_ctx = libhal_ctx_new (); + if (!priv->hal_ctx) { nm_warning ("Could not get connection to the HAL service."); return FALSE; } - connection = nm_dbus_manager_get_connection (manager->dbus_mgr); - libhal_ctx_set_dbus_connection (manager->hal_ctx, + connection = nm_dbus_manager_get_connection (priv->dbus_mgr); + libhal_ctx_set_dbus_connection (priv->hal_ctx, dbus_g_connection_get_connection (connection)); dbus_error_init (&error); - if (!libhal_ctx_init (manager->hal_ctx, &error)) { - nm_error ("libhal_ctx_init() failed: %s\n" - "Make sure the hal daemon is running?", - error.message); + if (!libhal_ctx_init (priv->hal_ctx, &error)) { + nm_warning ("libhal_ctx_init() failed: %s\n" + "Make sure the hal daemon is running?", + error.message); goto error; } - libhal_ctx_set_user_data (manager->hal_ctx, manager); - libhal_ctx_set_device_added (manager->hal_ctx, device_added); - libhal_ctx_set_device_removed (manager->hal_ctx, device_removed); - libhal_ctx_set_device_new_capability (manager->hal_ctx, device_new_capability); + libhal_ctx_set_user_data (priv->hal_ctx, self); + libhal_ctx_set_device_added (priv->hal_ctx, device_added); + libhal_ctx_set_device_removed (priv->hal_ctx, device_removed); + libhal_ctx_set_device_new_capability (priv->hal_ctx, device_new_capability); - libhal_device_property_watch_all (manager->hal_ctx, &error); + libhal_device_property_watch_all (priv->hal_ctx, &error); if (dbus_error_is_set (&error)) { nm_error ("libhal_device_property_watch_all(): %s", error.message); - libhal_ctx_shutdown (manager->hal_ctx, NULL); + libhal_ctx_shutdown (priv->hal_ctx, NULL); goto error; } @@ -612,41 +599,42 @@ hal_init (NMHalManager *manager) error: if (dbus_error_is_set (&error)) dbus_error_free (&error); - if (manager->hal_ctx) { - libhal_ctx_free (manager->hal_ctx); - manager->hal_ctx = NULL; + if (priv->hal_ctx) { + libhal_ctx_free (priv->hal_ctx); + priv->hal_ctx = NULL; } return FALSE; } static void -hal_deinit (NMHalManager *manager) +hal_deinit (NMHalManager *self) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); DBusError error; - if (manager->killswitch_poll_id) { - g_source_remove (manager->killswitch_poll_id); - manager->killswitch_poll_id = 0; + if (priv->killswitch_poll_id) { + g_source_remove (priv->killswitch_poll_id); + priv->killswitch_poll_id = 0; } - if (manager->killswitch_list) { - g_slist_foreach (manager->killswitch_list, (GFunc) g_free, NULL); - g_slist_free (manager->killswitch_list); - manager->killswitch_list = NULL; + if (priv->killswitch_list) { + g_slist_foreach (priv->killswitch_list, (GFunc) g_free, NULL); + g_slist_free (priv->killswitch_list); + priv->killswitch_list = NULL; } - if (!manager->hal_ctx) + if (!priv->hal_ctx) return; dbus_error_init (&error); - libhal_ctx_shutdown (manager->hal_ctx, &error); + libhal_ctx_shutdown (priv->hal_ctx, &error); if (dbus_error_is_set (&error)) { nm_warning ("libhal shutdown failed - %s", error.message); dbus_error_free (&error); } - libhal_ctx_free (manager->hal_ctx); - manager->hal_ctx = NULL; + libhal_ctx_free (priv->hal_ctx); + priv->hal_ctx = NULL; } static void @@ -656,21 +644,25 @@ name_owner_changed (NMDBusManager *dbus_mgr, const char *new, gpointer user_data) { - NMHalManager *manager = (NMHalManager *) user_data; + NMHalManager *self = NM_HAL_MANAGER (user_data); gboolean old_owner_good = (old && (strlen (old) > 0)); gboolean new_owner_good = (new && (strlen (new) > 0)); /* Only care about signals from HAL */ - if (strcmp (name, "org.freedesktop.Hal")) + if (strcmp (name, HAL_DBUS_SERVICE)) return; if (!old_owner_good && new_owner_good) { + nm_info ("HAL re-appeared"); /* HAL just appeared */ - if (!hal_init (manager)) - exit (1); + if (!hal_init (self)) + nm_warning ("Could not re-connect to HAL!!"); + else + g_signal_emit (self, signals[HAL_REAPPEARED], 0); } else if (old_owner_good && !new_owner_good) { /* HAL went away. Bad HAL. */ - hal_deinit (manager); + nm_info ("HAL disappeared"); + hal_deinit (self); } } @@ -679,94 +671,80 @@ connection_changed (NMDBusManager *dbus_mgr, DBusGConnection *connection, gpointer user_data) { - NMHalManager *manager = (NMHalManager *) user_data; - char *owner; + NMHalManager *self = NM_HAL_MANAGER (user_data); if (!connection) { - hal_deinit (manager); + hal_deinit (self); return; } - if ((owner = nm_dbus_manager_get_name_owner (dbus_mgr, "org.freedesktop.Hal"))) { - if (!hal_init (manager)) - exit (1); - g_free (owner); + if (nm_dbus_manager_name_has_owner (dbus_mgr, HAL_DBUS_SERVICE)) { + if (!hal_init (self)) + nm_warning ("Could not re-connect to HAL!!"); } } -static void -nm_manager_state_changed (NMManager *nm_manager, NMState state, gpointer user_data) -{ - NMHalManager *manager = (NMHalManager *) user_data; - - if (state == NM_STATE_ASLEEP) { - /* Save the sleep state */ - manager->nm_sleeping = TRUE; - } else if (manager->nm_sleeping) { - /* If the previous state was sleep, the next one means we just woke up */ - manager->nm_sleeping = FALSE; - - /* Punt adding back devices to an idle handler to give the manager - * time to push signals out over D-Bus when it wakes up. Since the - * signal emission might ref the old pre-sleep device, when the new - * device gets found there will be a D-Bus object path conflict between - * the old device and the new device, and dbus-glib "helpfully" asserts - * here and we die. - */ - if (manager->add_devices_id) - g_source_remove (manager->add_devices_id); - manager->add_devices_id = g_idle_add_full (G_PRIORITY_LOW, - add_initial_devices, - manager, - NULL); - } -} - -NMHalManager * -nm_hal_manager_new (NMManager *nm_manager) -{ - NMHalManager *manager; - NMDBusManager *dbus_mgr; - - g_return_val_if_fail (NM_IS_MANAGER (nm_manager), NULL); - - dbus_mgr = nm_dbus_manager_get (); - if (!nm_dbus_manager_name_has_owner (dbus_mgr, "org.freedesktop.Hal")) { - nm_warning ("Could not initialize connection to the HAL daemon."); - return NULL; - } - - manager = g_slice_new0 (NMHalManager); - manager->nm_manager = g_object_ref (nm_manager); - manager->dbus_mgr = dbus_mgr; - - register_built_in_creators (manager); - - g_signal_connect (manager->dbus_mgr, - "name-owner-changed", - G_CALLBACK (name_owner_changed), - manager); - g_signal_connect (manager->dbus_mgr, - "dbus-connection-changed", - G_CALLBACK (connection_changed), - manager); - - g_signal_connect (nm_manager, - "state-changed", - G_CALLBACK (nm_manager_state_changed), - manager); - - hal_init (manager); - - return manager; -} - void -nm_hal_manager_start (NMHalManager *manager) +nm_hal_manager_query_devices (NMHalManager *self) { + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); + /* Find hardware we care about */ - add_killswitch_devices (manager); - add_initial_devices (manager); + if (priv->hal_ctx) { + add_killswitch_devices (self); + add_initial_devices (self); + } +} + +gboolean +nm_hal_manager_udi_exists (NMHalManager *self, const char *udi) +{ + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); + + return libhal_device_property_exists (priv->hal_ctx, udi, "info.udi", NULL); +} + +NMHalManager * +nm_hal_manager_new (void) +{ + NMHalManager *self; + NMHalManagerPrivate *priv; + + self = NM_HAL_MANAGER (g_object_new (NM_TYPE_HAL_MANAGER, NULL)); + + priv = NM_HAL_MANAGER_GET_PRIVATE (self); + if (!nm_dbus_manager_name_has_owner (priv->dbus_mgr, HAL_DBUS_SERVICE)) { + nm_info ("Waiting for HAL to start..."); + return self; + } + + if (!hal_init (self)) { + g_object_unref (self); + self = NULL; + } + + return self; +} + +static void +nm_hal_manager_init (NMHalManager *self) +{ + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); + + priv->rfkilled = FALSE; + + priv->dbus_mgr = nm_dbus_manager_get (); + + register_built_in_creators (self); + + g_signal_connect (priv->dbus_mgr, + "name-owner-changed", + G_CALLBACK (name_owner_changed), + self); + g_signal_connect (priv->dbus_mgr, + "dbus-connection-changed", + G_CALLBACK (connection_changed), + self); } static void @@ -779,23 +757,88 @@ destroy_creator (gpointer data, gpointer user_data) g_slice_free (DeviceCreator, data); } -void -nm_hal_manager_destroy (NMHalManager *manager) +static void +dispose (GObject *object) { - if (!manager) + NMHalManager *self = NM_HAL_MANAGER (object); + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_hal_manager_parent_class)->dispose (object); return; - - if (manager->add_devices_id) { - g_source_remove (manager->add_devices_id); - manager->add_devices_id = 0; } + priv->disposed = TRUE; - g_free (manager->kswitch_err); + g_object_unref (priv->dbus_mgr); - g_slist_foreach (manager->device_creators, destroy_creator, NULL); - g_slist_free (manager->device_creators); + g_slist_foreach (priv->device_creators, destroy_creator, NULL); + g_slist_free (priv->device_creators); - hal_deinit (manager); - g_object_unref (manager->nm_manager); - g_slice_free (NMHalManager, manager); + hal_deinit (self); + + G_OBJECT_CLASS (nm_hal_manager_parent_class)->dispose (object); } + +static void +finalize (GObject *object) +{ + NMHalManager *self = NM_HAL_MANAGER (object); + NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self); + + g_free (priv->kswitch_err); + + G_OBJECT_CLASS (nm_hal_manager_parent_class)->finalize (object); +} + +static void +nm_hal_manager_class_init (NMHalManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMHalManagerPrivate)); + + /* virtual methods */ + object_class->dispose = dispose; + object_class->finalize = finalize; + + /* Signals */ + signals[UDI_ADDED] = + g_signal_new ("udi-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMHalManagerClass, udi_added), + NULL, NULL, + nm_marshal_VOID__STRING_STRING_POINTER, + G_TYPE_NONE, 3, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + + signals[UDI_REMOVED] = + g_signal_new ("udi-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMHalManagerClass, udi_removed), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + signals[RFKILL_CHANGED] = + g_signal_new ("rfkill-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMHalManagerClass, rfkill_changed), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); + + signals[HAL_REAPPEARED] = + g_signal_new ("hal-reappeared", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMHalManagerClass, hal_reappeared), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + diff --git a/src/nm-hal-manager.h b/src/nm-hal-manager.h index e94353f3c5..63b43435a5 100644 --- a/src/nm-hal-manager.h +++ b/src/nm-hal-manager.h @@ -1,12 +1,47 @@ #ifndef NM_HAL_MANAGER_H #define NM_HAL_MANAGER_H -#include "nm-manager.h" +#include +#include -typedef struct _NMHalManager NMHalManager; +G_BEGIN_DECLS -NMHalManager *nm_hal_manager_new (NMManager *nm_manager); -void nm_hal_manager_start (NMHalManager *manager); -void nm_hal_manager_destroy (NMHalManager *manager); +#define NM_TYPE_HAL_MANAGER (nm_hal_manager_get_type ()) +#define NM_HAL_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_HAL_MANAGER, NMHalManager)) +#define NM_HAL_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_HAL_MANAGER, NMHalManagerClass)) +#define NM_IS_HAL_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_HAL_MANAGER)) +#define NM_IS_HAL_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_HAL_MANAGER)) +#define NM_HAL_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_HAL_MANAGER, NMHalManagerClass)) + +typedef struct { + GObject parent; +} NMHalManager; + +typedef GObject *(*NMDeviceCreatorFn) (NMHalManager *manager, + const char *udi, + gboolean managed); + +typedef struct { + GObjectClass parent; + + /* Virtual functions */ + void (*udi_added) (NMHalManager *manager, + const char *udi, + const char *type_name, + NMDeviceCreatorFn creator_fn); + + void (*udi_removed) (NMHalManager *manager, const char *udi); + + void (*rfkill_changed) (NMHalManager *manager, gboolean hw_enabled); + + void (*hal_reappeared) (NMHalManager *manager); +} NMHalManagerClass; + +GType nm_hal_manager_get_type (void); + +NMHalManager *nm_hal_manager_new (void); +gboolean nm_hal_manager_get_rfkilled (NMHalManager *manager); +void nm_hal_manager_query_devices (NMHalManager *manager); +gboolean nm_hal_manager_udi_exists (NMHalManager *manager, const char *udi); #endif /* NM_HAL_MANAGER_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index fc0072ab34..9643a03f06 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -17,6 +17,7 @@ #include "nm-setting-vpn.h" #include "nm-marshal.h" #include "nm-dbus-glib-types.h" +#include "nm-hal-manager.h" static gboolean impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err); static void impl_manager_activate_connection (NMManager *manager, @@ -49,6 +50,27 @@ static void connection_added_default_handler (NMManager *manager, NMConnection *connection, NMConnectionScope scope); +static void manager_device_state_changed (NMDevice *device, + NMDeviceState state, + gpointer user_data); + +static void hal_manager_udi_added_cb (NMHalManager *hal_mgr, + const char *udi, + const char *type_name, + NMDeviceCreatorFn creator_fn, + gpointer user_data); + +static void hal_manager_udi_removed_cb (NMHalManager *hal_mgr, + const char *udi, + gpointer user_data); + +static void hal_manager_rfkill_changed_cb (NMHalManager *hal_mgr, + gboolean rfkilled, + gpointer user_data); + +static void hal_manager_hal_reappeared_cb (NMHalManager *hal_mgr, + gpointer user_data); + #define SSD_POKE_INTERVAL 120000 typedef struct { @@ -65,6 +87,7 @@ typedef struct { NMState state; NMDBusManager *dbus_mgr; + NMHalManager *hal_mgr; GHashTable *user_connections; DBusGProxy *user_proxy; @@ -80,6 +103,7 @@ typedef struct { gboolean sleeping; guint poke_id; + guint add_devices_id; NMVPNManager *vpn_manager; guint vpn_manager_id; @@ -277,6 +301,18 @@ pending_connection_info_destroy (PendingConnectionInfo *info) g_slice_free (PendingConnectionInfo, info); } +static void +remove_one_device (NMManager *manager, NMDevice *device) +{ + if (nm_device_get_managed (device)) + nm_device_set_managed (device, FALSE); + + g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager); + + g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device); + g_object_unref (device); +} + static void dispose (GObject *object) { @@ -292,8 +328,15 @@ dispose (GObject *object) pending_connection_info_destroy (priv->pending_connection_info); priv->pending_connection_info = NULL; - while (g_slist_length (priv->devices)) - nm_manager_remove_device (manager, NM_DEVICE (priv->devices->data), TRUE); + if (priv->add_devices_id) { + g_source_remove (priv->add_devices_id); + priv->add_devices_id = 0; + } + + while (g_slist_length (priv->devices)) { + remove_one_device (manager, NM_DEVICE (priv->devices->data)); + priv->devices = g_slist_remove_link (priv->devices, priv->devices); + } nm_manager_connections_destroy (manager, NM_CONNECTION_SCOPE_USER); g_hash_table_destroy (priv->user_connections); @@ -322,6 +365,7 @@ dispose (GObject *object) g_object_unref (priv->vpn_manager); g_object_unref (priv->dbus_mgr); + g_object_unref (priv->hal_mgr); G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object); } @@ -919,6 +963,18 @@ query_connections (NMManager *manager, G_TYPE_INVALID); } +static NMDevice * +nm_manager_get_device_by_udi (NMManager *manager, const char *udi) +{ + GSList *iter; + + for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { + if (!strcmp (nm_device_get_udi (NM_DEVICE (iter->data)), udi)) + return NM_DEVICE (iter->data); + } + return NULL; +} + static void handle_unmanaged_devices (NMManager *manager, GPtrArray *ops) { @@ -1140,6 +1196,17 @@ initial_get_connections (gpointer user_data) return FALSE; } +static gboolean +deferred_hal_manager_query_devices (gpointer user_data) +{ + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + + priv->add_devices_id = 0; + nm_hal_manager_query_devices (priv->hal_mgr); + + return FALSE; +} NMManager * nm_manager_new (void) @@ -1161,6 +1228,29 @@ nm_manager_new (void) g_idle_add ((GSourceFunc) initial_get_connections, NM_MANAGER (object)); + priv->hal_mgr = nm_hal_manager_new (); + g_idle_add (deferred_hal_manager_query_devices, object); + + g_signal_connect (priv->hal_mgr, + "udi-added", + G_CALLBACK (hal_manager_udi_added_cb), + NM_MANAGER (object)); + + g_signal_connect (priv->hal_mgr, + "udi-removed", + G_CALLBACK (hal_manager_udi_removed_cb), + NM_MANAGER (object)); + + g_signal_connect (priv->hal_mgr, + "rfkill-changed", + G_CALLBACK (hal_manager_rfkill_changed_cb), + NM_MANAGER (object)); + + g_signal_connect (priv->hal_mgr, + "hal-reappeared", + G_CALLBACK (hal_manager_hal_reappeared_cb), + NM_MANAGER (object)); + return NM_MANAGER (object); } @@ -1235,7 +1325,7 @@ manager_set_wireless_enabled (NMManager *manager, gboolean enabled) } static void -manager_device_state_changed (NMDeviceInterface *device, NMDeviceState state, gpointer user_data) +manager_device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data) { NMManager *manager = NM_MANAGER (user_data); @@ -1308,21 +1398,44 @@ next: g_slist_free (connections); } -void -nm_manager_add_device (NMManager *manager, NMDevice *device) +static void +hal_manager_udi_added_cb (NMHalManager *hal_mgr, + const char *udi, + const char *type_name, + NMDeviceCreatorFn creator_fn, + gpointer user_data) { - NMManagerPrivate *priv; + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + gboolean managed = TRUE; + GObject *device; + GSList *iter; + const char *iface; - g_return_if_fail (NM_IS_MANAGER (manager)); - g_return_if_fail (NM_IS_DEVICE (device)); + if (priv->sleeping) + return; - priv = NM_MANAGER_GET_PRIVATE (manager); + /* Make sure the device is not already in the device list */ + if (nm_manager_get_device_by_udi (self, udi)) + return; - priv->devices = g_slist_append (priv->devices, g_object_ref (device)); + /* Figure out if the device is managed or not */ + for (iter = priv->unmanaged_udis; iter; iter = g_slist_next (iter)) { + if (!strcmp (udi, iter->data)) { + managed = FALSE; + break; + } + } + + device = creator_fn (hal_mgr, udi, managed); + if (!device) + return; + + priv->devices = g_slist_append (priv->devices, device); g_signal_connect (device, "state-changed", G_CALLBACK (manager_device_state_changed), - manager); + self); /* Attach to the access-point-added signal so that the manager can fill * non-SSID-broadcasting APs with an SSID. @@ -1330,50 +1443,88 @@ nm_manager_add_device (NMManager *manager, NMDevice *device) if (NM_IS_DEVICE_802_11_WIRELESS (device)) { g_signal_connect (device, "hidden-ap-found", G_CALLBACK (manager_hidden_ap_found), - manager); + self); /* Set initial rfkill state */ nm_device_802_11_wireless_set_enabled (NM_DEVICE_802_11_WIRELESS (device), priv->wireless_enabled); } - nm_info ("(%s): exported as %s", - nm_device_get_iface (device), - nm_device_get_udi (device)); + iface = nm_device_get_iface (NM_DEVICE (device)); + nm_info ("Found new %s device '%s'.", type_name, iface); dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (priv->dbus_mgr), - nm_device_get_udi (device), - G_OBJECT (device)); + nm_device_get_udi (NM_DEVICE (device)), + device); + nm_info ("(%s): exported as %s", iface, udi); - g_signal_emit (manager, signals[DEVICE_ADDED], 0, device); + g_signal_emit (self, signals[DEVICE_ADDED], 0, device); } -void -nm_manager_remove_device (NMManager *manager, NMDevice *device, gboolean deactivate) +static void +hal_manager_udi_removed_cb (NMHalManager *manager, + const char *udi, + gpointer user_data) { - NMManagerPrivate *priv; + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GSList *iter; - g_return_if_fail (NM_IS_MANAGER (manager)); - g_return_if_fail (NM_IS_DEVICE (device)); - - priv = NM_MANAGER_GET_PRIVATE (manager); + g_return_if_fail (udi != NULL); for (iter = priv->devices; iter; iter = iter->next) { - if (iter->data == device) { + NMDevice *device = NM_DEVICE (iter->data); + + if (!strcmp (nm_device_get_udi (device), udi)) { priv->devices = g_slist_delete_link (priv->devices, iter); - - if (nm_device_get_managed (device)) - nm_device_set_managed (device, FALSE); - - g_signal_handlers_disconnect_by_func (device, manager_device_state_changed, manager); - - g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device); - g_object_unref (device); + remove_one_device (self, device); break; } } } +static void +hal_manager_rfkill_changed_cb (NMHalManager *hal_mgr, + gboolean rfkilled, + gpointer user_data) +{ + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + gboolean enabled = !rfkilled; + + if (priv->wireless_hw_enabled != enabled) { + nm_info ("Wireless now %s by radio killswitch", enabled ? "enabled" : "disabled"); + priv->wireless_hw_enabled = enabled; + g_object_notify (G_OBJECT (self), NM_MANAGER_WIRELESS_HARDWARE_ENABLED); + + manager_set_wireless_enabled (self, enabled); + } +} + +static void +hal_manager_hal_reappeared_cb (NMHalManager *hal_mgr, + gpointer user_data) +{ + NMManager *self = NM_MANAGER (user_data); + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); + GSList *iter; + + /* Remove devices which are no longer known to HAL */ + for (iter = priv->devices; iter; iter = g_slist_next (iter)) { + NMDevice *device = NM_DEVICE (iter->data); + GSList *next = iter->next; + + if (nm_hal_manager_udi_exists (priv->hal_mgr, nm_device_get_udi (device))) + continue; + + priv->devices = g_slist_delete_link (priv->devices, iter); + remove_one_device (self, device); + iter = next; + } + + /* Get any new ones */ + nm_hal_manager_query_devices (priv->hal_mgr); +} + GSList * nm_manager_get_devices (NMManager *manager) { @@ -1396,41 +1547,6 @@ impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err) return TRUE; } -NMDevice * -nm_manager_get_device_by_path (NMManager *manager, const char *path) -{ - GSList *iter; - - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - g_return_val_if_fail (path != NULL, NULL); - - for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { - NMDevice *device = NM_DEVICE (iter->data); - - if (!strcmp (nm_device_get_udi (device), path)) - return device; - } - - return NULL; -} - -NMDevice * -nm_manager_get_device_by_udi (NMManager *manager, const char *udi) -{ - GSList *iter; - - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - - for (iter = NM_MANAGER_GET_PRIVATE (manager)->devices; iter; iter = iter->next) { - NMDevice *device = NM_DEVICE (iter->data); - - if (!strcmp (nm_device_get_udi (device), udi)) - return device; - } - - return NULL; -} - static NMActRequest * nm_manager_get_act_request_by_path (NMManager *manager, const char *path, @@ -1494,14 +1610,6 @@ internal_activate_device (NMManager *manager, return success ? nm_act_request_get_active_connection_path (req) : NULL; } -gboolean -nm_manager_activation_pending (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->pending_connection_info != NULL; -} - static gboolean wait_for_connection_expired (gpointer data) { @@ -1578,7 +1686,7 @@ nm_manager_activate_connection (NMManager *manager, NMDeviceState state; /* Device-based connection */ - device = nm_manager_get_device_by_path (manager, device_path); + device = nm_manager_get_device_by_udi (manager, device_path); if (!device) { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_UNKNOWN_DEVICE, @@ -1773,41 +1881,6 @@ impl_manager_deactivate_connection (NMManager *manager, return nm_manager_deactivate_connection (manager, connection_path, error); } -gboolean -nm_manager_wireless_enabled (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->wireless_enabled; -} - -gboolean -nm_manager_wireless_hardware_enabled (NMManager *manager) -{ - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - return NM_MANAGER_GET_PRIVATE (manager)->wireless_hw_enabled; -} - -void -nm_manager_set_wireless_hardware_enabled (NMManager *manager, - gboolean enabled) -{ - NMManagerPrivate *priv; - - g_return_if_fail (NM_IS_MANAGER (manager)); - - priv = NM_MANAGER_GET_PRIVATE (manager); - - if (priv->wireless_hw_enabled != enabled) { - nm_info ("Wireless now %s by radio killswitch", enabled ? "enabled" : "disabled"); - priv->wireless_hw_enabled = enabled; - g_object_notify (G_OBJECT (manager), NM_MANAGER_WIRELESS_HARDWARE_ENABLED); - - manager_set_wireless_enabled (manager, enabled); - } -} - static gboolean impl_manager_sleep (NMManager *manager, gboolean sleep, GError **error) { @@ -1839,10 +1912,24 @@ impl_manager_sleep (NMManager *manager, gboolean sleep, GError **error) } else { nm_info ("Waking up..."); - while (g_slist_length (priv->devices)) - nm_manager_remove_device (manager, NM_DEVICE (priv->devices->data), FALSE); + while (g_slist_length (priv->devices)) { + remove_one_device (manager, NM_DEVICE (priv->devices->data)); + priv->devices = g_slist_remove_link (priv->devices, priv->devices); + } - priv->devices = NULL; + /* Punt adding back devices to an idle handler to give the manager + * time to push signals out over D-Bus when it wakes up. Since the + * signal emission might ref the old pre-sleep device, when the new + * device gets found there will be a D-Bus object path conflict between + * the old device and the new device, and dbus-glib "helpfully" asserts + * here and we die. + */ + if (priv->add_devices_id) + g_source_remove (priv->add_devices_id); + priv->add_devices_id = g_idle_add_full (G_PRIORITY_LOW, + deferred_hal_manager_query_devices, + manager, + NULL); } nm_manager_update_state (manager); @@ -1960,19 +2047,3 @@ nm_manager_get_active_connections_by_connection (NMManager *manager, return get_active_connections (manager, connection); } -gboolean -nm_manager_is_udi_managed (NMManager *manager, const char *udi) -{ - NMManagerPrivate *priv; - GSList *iter; - - g_return_val_if_fail (NM_IS_MANAGER (manager), FALSE); - - priv = NM_MANAGER_GET_PRIVATE (manager); - for (iter = priv->unmanaged_udis; iter; iter = g_slist_next (iter)) { - if (!strcmp (udi, iter->data)) - return FALSE; - } - return TRUE; -} - diff --git a/src/nm-manager.h b/src/nm-manager.h index fc5ff8ace9..fb53bdd597 100644 --- a/src/nm-manager.h +++ b/src/nm-manager.h @@ -56,12 +56,7 @@ NMManager *nm_manager_new (void); /* Device handling */ -void nm_manager_add_device (NMManager *manager, NMDevice *device); -void nm_manager_remove_device (NMManager *manager, NMDevice *device, gboolean deactivate); GSList *nm_manager_get_devices (NMManager *manager); -NMDevice *nm_manager_get_device_by_path (NMManager *manager, const char *path); -NMDevice *nm_manager_get_device_by_udi (NMManager *manager, const char *udi); -gboolean nm_manager_is_udi_managed (NMManager *manager, const char *udi); const char * nm_manager_activate_connection (NMManager *manager, NMConnection *connection, @@ -74,15 +69,9 @@ gboolean nm_manager_deactivate_connection (NMManager *manager, const char *connection_path, GError **error); -gboolean nm_manager_activation_pending (NMManager *manager); - /* State handling */ NMState nm_manager_get_state (NMManager *manager); -gboolean nm_manager_wireless_enabled (NMManager *manager); -gboolean nm_manager_wireless_hardware_enabled (NMManager *manager); -void nm_manager_set_wireless_hardware_enabled (NMManager *manager, - gboolean enabled); /* Connections */