NetworkManager r3619 - in trunk: . marshallers src



Author: dcbw
Date: Tue Apr 29 23:03:00 2008
New Revision: 3619
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3619&view=rev

Log:
2008-04-29  Dan Williams  <dcbw redhat com>

	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



Modified:
   trunk/ChangeLog
   trunk/marshallers/nm-marshal.list
   trunk/src/NetworkManager.c
   trunk/src/nm-hal-manager.c
   trunk/src/nm-hal-manager.h
   trunk/src/nm-manager.c
   trunk/src/nm-manager.h

Modified: trunk/marshallers/nm-marshal.list
==============================================================================
--- trunk/marshallers/nm-marshal.list	(original)
+++ trunk/marshallers/nm-marshal.list	Tue Apr 29 23:03:00 2008
@@ -8,6 +8,7 @@
 VOID:STRING,STRING
 VOID:STRING,UCHAR
 VOID:STRING,OBJECT
+VOID:STRING,STRING,POINTER
 VOID:OBJECT,UINT,UINT
 VOID:STRING,INT
 VOID:STRING,UINT

Modified: trunk/src/NetworkManager.c
==============================================================================
--- trunk/src/NetworkManager.c	(original)
+++ trunk/src/NetworkManager.c	Tue Apr 29 23:03:00 2008
@@ -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 @@
 		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 @@
 	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 @@
 		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 @@
 	g_main_loop_run (main_loop);
 
 done:
-	if (hal_manager)
-		nm_hal_manager_destroy (hal_manager);
-
 	if (policy)
 		nm_policy_destroy (policy);
 

Modified: trunk/src/nm-hal-manager.c
==============================================================================
--- trunk/src/nm-hal-manager.c	(original)
+++ trunk/src/nm-hal-manager.c	Tue Apr 29 23:03:00 2008
@@ -8,6 +8,7 @@
 #include <dbus/dbus-glib-lowlevel.h>
 
 #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 @@
 /* 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 @@
 	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 @@
 /* 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 @@
 	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 @@
 /* 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 @@
 	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 @@
 
 	/* 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 @@
 	}
 
 	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 @@
 }
 
 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 @@
 	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 @@
 	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 @@
 	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 );*/
-
-	/* 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;
+//	nm_debug ("nm_hal_device_new_capability() called with udi = %s, capability = %s", udi, capability );
 
-	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 @@
 	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 @@
 
 		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 @@
 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 @@
 					  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 @@
 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 @@
 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 @@
 }
 
 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 @@
 		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 @@
 }
 
 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 @@
 	}
 
 	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 @@
 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 @@
 					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 @@
 					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);
+void
+nm_hal_manager_query_devices (NMHalManager *self)
+{
+	NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
+
+	/* Find hardware we care about */
+	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 (NMManager *nm_manager)
+nm_hal_manager_new (void)
 {
-	NMHalManager *manager;
-	NMDBusManager *dbus_mgr;
+	NMHalManager *self;
+	NMHalManagerPrivate *priv;
 
-	g_return_val_if_fail (NM_IS_MANAGER (nm_manager), NULL);
+	self = NM_HAL_MANAGER (g_object_new (NM_TYPE_HAL_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;
+	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;
 	}
 
-	manager = g_slice_new0 (NMHalManager);
-	manager->nm_manager = g_object_ref (nm_manager);
-	manager->dbus_mgr = dbus_mgr;
+	if (!hal_init (self)) {
+		g_object_unref (self);
+		self = NULL;
+	}
 
-	register_built_in_creators (manager);
+	return self;
+}
 
-	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);
+static void
+nm_hal_manager_init (NMHalManager *self)
+{
+	NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
 
-	g_signal_connect (nm_manager,
-					  "state-changed",
-					  G_CALLBACK (nm_manager_state_changed),
-					  manager);
+	priv->rfkilled = FALSE;
 
-	hal_init (manager);
+	priv->dbus_mgr = nm_dbus_manager_get ();
 
-	return manager;
-}
+	register_built_in_creators (self);
 
-void
-nm_hal_manager_start (NMHalManager *manager)
-{
-	/* Find hardware we care about */
-	add_killswitch_devices (manager);
-	add_initial_devices (manager);
+	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 @@
 	g_slice_free (DeviceCreator, data);
 }
 
-void
-nm_hal_manager_destroy (NMHalManager *manager)
+static void
+dispose (GObject *object)
 {
-	if (!manager)
-		return;
+	NMHalManager *self = NM_HAL_MANAGER (object);
+	NMHalManagerPrivate *priv = NM_HAL_MANAGER_GET_PRIVATE (self);
 
-	if (manager->add_devices_id) {
-		g_source_remove (manager->add_devices_id);
-		manager->add_devices_id = 0;
+	if (priv->disposed) {
+		G_OBJECT_CLASS (nm_hal_manager_parent_class)->dispose (object);
+		return;
 	}
+	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);
+}
+

Modified: trunk/src/nm-hal-manager.h
==============================================================================
--- trunk/src/nm-hal-manager.h	(original)
+++ trunk/src/nm-hal-manager.h	Tue Apr 29 23:03:00 2008
@@ -1,12 +1,47 @@
 #ifndef NM_HAL_MANAGER_H
 #define NM_HAL_MANAGER_H
 
-#include "nm-manager.h"
+#include <glib/gtypes.h>
+#include <glib-object.h>
 
-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 */

Modified: trunk/src/nm-manager.c
==============================================================================
--- trunk/src/nm-manager.c	(original)
+++ trunk/src/nm-manager.c	Tue Apr 29 23:03:00 2008
@@ -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 @@
 									 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 @@
 	NMState state;
 
 	NMDBusManager *dbus_mgr;
+	NMHalManager *hal_mgr;
 
 	GHashTable *user_connections;
 	DBusGProxy *user_proxy;
@@ -80,6 +103,7 @@
 	gboolean sleeping;
 
 	guint poke_id;
+	guint add_devices_id;
 
 	NMVPNManager *vpn_manager;
 	guint vpn_manager_id;
@@ -278,6 +302,18 @@
 }
 
 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)
 {
 	NMManager *manager = NM_MANAGER (object);
@@ -292,8 +328,15 @@
 	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 @@
 	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 @@
 	                                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 @@
 	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 @@
 
 	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 @@
 }
 
 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 @@
 	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;
+
+	/* 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, g_object_ref (device));
+	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,105 +1443,108 @@
 	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) {
-			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);
+		NMDevice *device = NM_DEVICE (iter->data);
 
-			g_signal_emit (manager, signals[DEVICE_REMOVED], 0, device);
-			g_object_unref (device);
+		if (!strcmp (nm_device_get_udi (device), udi)) {
+			priv->devices = g_slist_delete_link (priv->devices, iter);
+			remove_one_device (self, device);
 			break;
 		}
 	}
 }
 
-GSList *
-nm_manager_get_devices (NMManager *manager)
+static void
+hal_manager_rfkill_changed_cb (NMHalManager *hal_mgr,
+                               gboolean rfkilled,
+                               gpointer user_data)
 {
-	g_return_val_if_fail (NM_IS_MANAGER (manager), NULL);
+	NMManager *self = NM_MANAGER (user_data);
+	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
+	gboolean enabled = !rfkilled;
 
-	return NM_MANAGER_GET_PRIVATE (manager)->devices;
+	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 gboolean
-impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err)
+static void
+hal_manager_hal_reappeared_cb (NMHalManager *hal_mgr,
+                               gpointer user_data)
 {
-	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
+	NMManager *self = NM_MANAGER (user_data);
+	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
 	GSList *iter;
 
-	*devices = g_ptr_array_sized_new (g_slist_length (priv->devices));
+	/* 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;
 
-	for (iter = priv->devices; iter; iter = iter->next)
-		g_ptr_array_add (*devices, g_strdup (nm_device_get_udi (NM_DEVICE (iter->data))));
+		if (nm_hal_manager_udi_exists (priv->hal_mgr, nm_device_get_udi (device)))
+			continue;
 
-	return TRUE;
+		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);
 }
 
-NMDevice *
-nm_manager_get_device_by_path (NMManager *manager, const char *path)
+GSList *
+nm_manager_get_devices (NMManager *manager)
 {
-	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;
+	return NM_MANAGER_GET_PRIVATE (manager)->devices;
 }
 
-NMDevice *
-nm_manager_get_device_by_udi (NMManager *manager, const char *udi)
+static gboolean
+impl_manager_get_devices (NMManager *manager, GPtrArray **devices, GError **err)
 {
+	NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager);
 	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);
+	*devices = g_ptr_array_sized_new (g_slist_length (priv->devices));
 
-		if (!strcmp (nm_device_get_udi (device), udi))
-			return device;
-	}
+	for (iter = priv->devices; iter; iter = iter->next)
+		g_ptr_array_add (*devices, g_strdup (nm_device_get_udi (NM_DEVICE (iter->data))));
 
-	return NULL;
+	return TRUE;
 }
 
 static NMActRequest *
@@ -1494,14 +1610,6 @@
 	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 @@
 		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 @@
 	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 @@
 	} 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 @@
 	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;
-}
-

Modified: trunk/src/nm-manager.h
==============================================================================
--- trunk/src/nm-manager.h	(original)
+++ trunk/src/nm-manager.h	Tue Apr 29 23:03:00 2008
@@ -56,12 +56,7 @@
 
 /* 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 @@
                                            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 */
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]