NetworkManager r3537 - in trunk: . introspection system-settings/plugins/ifcfg-fedora system-settings/plugins/ifcfg-suse system-settings/src



Author: dcbw
Date: Tue Apr  8 02:36:39 2008
New Revision: 3537
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3537&view=rev

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

	* introspection/nm-settings-system.xml
	  introspection/Makefile.am
		- Define the unmanaged devices interface for the system settings service

	* system-settings/src/nm-system-config-hal-manager.c
	  system-settings/src/nm-system-config-hal-manager.h
	  system-settings/src/nm-system-config-hal-manager-private.h
	  system-settings/src/Makefile.am
		- Add a lightweight HAL manager object for tracking network devices for
			the purpose of determining unmanaged devices and which devices need
			the default DHCP connections

	* system-settings/src/nm-system-config-interface.c
	  system-settings/src/nm-system-config-interface.h
		- (nm_system_config_interface_init): add the HAL manager as an argument
		- (nm_system_config_interface_get_unmanaged_devices): implement
		- Define 'unmanaged-devices-changed' signal

	* system-settings/src/dbus-settings.c
	  system-settings/src/dbus-settings.h
		- Implement the unmanaged devices interface; some cleanups

	* system-settings/plugins/ifcfg-suse/plugin.c
		- Fixup for plugin interface changes

	* system-settings/plugins/ifcfg-fedora/plugin.c
		- (get_ether_device_udi): new function; find the device that has
			a specified MAC address and return its UDI
		- (get_udi_for_connection): new function; try to find the specific
			device a connection is locked to, if any
		- (device_added_cb, device_removed_cb): update unmanaged device list in
			response to HAL events
		- (get_unmanaged_devices): new function; return unmanaged device list
		- (build_one_connection): set the connection's locked device, if any
		- (write_auto_wired_connection): remove
		- (kill_old_auto_wired_file): remove the ifcfg-Auto Wired file if found
		- (handle_connection_changed): alert listeners that the unmanaged device
			list has changed
		- (init): fixup for plugin interface changes, implement unmanaged devices

	* system-settings/plugins/ifcfg-fedora/parser.c
	  system-settings/plugins/ifcfg-fedora/parser.h
		- (connection_data_free): clean up connection UDI



Added:
   trunk/introspection/nm-settings-system.xml
   trunk/system-settings/src/nm-system-config-hal-manager-private.h
   trunk/system-settings/src/nm-system-config-hal-manager.c
   trunk/system-settings/src/nm-system-config-hal-manager.h
Modified:
   trunk/ChangeLog
   trunk/introspection/Makefile.am
   trunk/system-settings/plugins/ifcfg-fedora/parser.c
   trunk/system-settings/plugins/ifcfg-fedora/parser.h
   trunk/system-settings/plugins/ifcfg-fedora/plugin.c
   trunk/system-settings/plugins/ifcfg-suse/plugin.c
   trunk/system-settings/src/Makefile.am
   trunk/system-settings/src/dbus-settings.c
   trunk/system-settings/src/dbus-settings.h
   trunk/system-settings/src/nm-system-config-interface.c
   trunk/system-settings/src/nm-system-config-interface.h

Modified: trunk/introspection/Makefile.am
==============================================================================
--- trunk/introspection/Makefile.am	(original)
+++ trunk/introspection/Makefile.am	Tue Apr  8 02:36:39 2008
@@ -9,6 +9,7 @@
 	nm-manager.xml					\
 	nm-manager-client.xml				\
 	nm-settings.xml					\
+	nm-settings-system.xml \
 	nm-exported-connection.xml		\
 	nm-vpn-plugin.xml				\
 	nm-vpn-connection.xml			\

Added: trunk/introspection/nm-settings-system.xml
==============================================================================
--- (empty file)
+++ trunk/introspection/nm-settings-system.xml	Tue Apr  8 02:36:39 2008
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<node name="/" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0";>
+  <interface name="org.freedesktop.NetworkManagerSettings.System">
+    <tp:docstring>
+      Implemented by the system settings service to provide additional settings to NetworkManager.
+    </tp:docstring>
+
+    <property name="UnmanagedDevices" type="ao" access="read">
+      <tp:docstring>
+        The list of HAL UDIs of devices that should not be managed by NetworkManager.
+      </tp:docstring>
+    </property>
+
+    <signal name="PropertiesChanged">
+        <arg name="properties" type="a{sv}" tp:type="String_Variant_Map">
+            <tp:docstring>
+                A dictionary mapping property names to variant boxed values
+            </tp:docstring>
+        </arg>
+    </signal>
+
+  </interface>
+</node>

Modified: trunk/system-settings/plugins/ifcfg-fedora/parser.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/parser.c	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/parser.c	Tue Apr  8 02:36:39 2008
@@ -112,6 +112,8 @@
 	g_hash_table_destroy (cdata->ppp_secrets);
 
 	g_free (cdata->ifcfg_path);
+	g_free (cdata->udi);
+
 	memset (cdata, 0, sizeof (ConnectionData));
 	g_free (cdata);
 }

Modified: trunk/system-settings/plugins/ifcfg-fedora/parser.h
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/parser.h	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/parser.h	Tue Apr  8 02:36:39 2008
@@ -35,6 +35,7 @@
 
 typedef struct {
 	char *ifcfg_path;
+	char *udi;
 	gboolean ignored;
 	gboolean exported;
 

Modified: trunk/system-settings/plugins/ifcfg-fedora/plugin.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/plugin.c	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/plugin.c	Tue Apr  8 02:36:39 2008
@@ -26,12 +26,21 @@
 #include <sys/inotify.h>
 #include <unistd.h>
 #include <errno.h>
+#include <net/ethernet.h>
+#include <netinet/ether.h>
+
+#include <dbus/dbus-glib.h>
 
 #include <nm-setting-connection.h>
 #include <nm-setting-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-gsm.h>
+#include <nm-setting-cdma.h>
+#include <nm-setting-pppoe.h>
 #include <nm-setting-wireless-security.h>
 #include <nm-setting-8021x.h>
 
+#include "nm-dbus-glib-types.h"
 #include "plugin.h"
 #include "parser.h"
 #include "shvar.h"
@@ -53,6 +62,10 @@
 
 typedef struct {
 	gboolean initialized;
+
+	DBusGConnection *g_connection;
+	NMSystemConfigHalManager *hal_mgr;
+
 	GSList *connections;
 
 	int ifd;
@@ -72,31 +85,186 @@
 	return error_quark;
 }
 
-#define AUTO_WIRED_STAMP_FILE SYSCONFDIR"/NetworkManager/auto-wired-stamp"
-#define AUTO_WIRED_FILE_NAME  _("Auto Wired")
+static char *
+get_ether_device_udi (SCPluginIfcfg *plugin, GByteArray *mac, GSList *devices)
+{
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	GError *error = NULL;
+	GSList *iter;
+	char *udi = NULL;
+
+	if (!priv->g_connection || !mac)
+		return NULL;
+
+	for (iter = devices; !udi && iter; iter = g_slist_next (iter)) {
+		DBusGProxy *dev_proxy;
+		char *address = NULL;
+
+		dev_proxy = dbus_g_proxy_new_for_name (priv->g_connection,
+		                                       "org.freedesktop.Hal",
+		                                       iter->data,
+		                                       "org.freedesktop.Hal.Device");
+		if (!dev_proxy)
+			continue;
+
+		if (dbus_g_proxy_call_with_timeout (dev_proxy,
+		                                    "GetPropertyString", 10000, &error,
+		                                    G_TYPE_STRING, "net.address", G_TYPE_INVALID,
+		                                    G_TYPE_STRING, &address, G_TYPE_INVALID)) {		
+			struct ether_addr *dev_mac;
+
+			if (address && strlen (address)) {
+				dev_mac = ether_aton (address);
+				if (!memcmp (dev_mac->ether_addr_octet, mac->data, ETH_ALEN))
+					udi = g_strdup (iter->data);
+			}
+		} else {
+			g_error_free (error);
+			error = NULL;
+		}
+		g_free (address);
+		g_object_unref (dev_proxy);
+	}
+
+	return udi;
+}
+
+static NMDeviceType
+get_device_type_for_connection (NMConnection *connection)
+{
+	NMDeviceType devtype = DEVICE_TYPE_UNKNOWN;
+	NMSettingConnection *s_con;
+
+	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+	if (!s_con)
+		return DEVICE_TYPE_UNKNOWN;
+
+	if (   !strcmp (s_con->type, NM_SETTING_WIRED_SETTING_NAME)
+	    || !strcmp (s_con->type, NM_SETTING_PPPOE_SETTING_NAME)) {
+		if (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED))
+			devtype = DEVICE_TYPE_802_3_ETHERNET;
+	} else if (!strcmp (s_con->type, NM_SETTING_WIRELESS_SETTING_NAME)) {
+		if (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS))
+			devtype = DEVICE_TYPE_802_11_WIRELESS;
+	} else if (!strcmp (s_con->type, NM_SETTING_GSM_SETTING_NAME)) {
+		if (nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM))
+			devtype = DEVICE_TYPE_GSM;
+	} else if (!strcmp (s_con->type, NM_SETTING_CDMA_SETTING_NAME)) {
+		if (nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA))
+			devtype = DEVICE_TYPE_CDMA;
+	}
+
+	return devtype;
+}
+
+static char *
+get_udi_for_connection (SCPluginIfcfg *plugin, NMConnection *connection, NMDeviceType devtype)
+{
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	NMSettingWired *s_wired;
+	NMSettingWireless *s_wireless;
+	char *udi = NULL;
+	GSList *devices = NULL;
+
+	if (devtype == DEVICE_TYPE_UNKNOWN)
+		devtype = get_device_type_for_connection (connection);
+
+	switch (devtype) {
+	case DEVICE_TYPE_802_3_ETHERNET:
+		s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
+		if (s_wired) {
+			devices = nm_system_config_hal_manager_get_devices_of_type (priv->hal_mgr, DEVICE_TYPE_802_3_ETHERNET);
+			udi = get_ether_device_udi (plugin, s_wired->mac_address, devices);
+		}
+		break;
+
+	case DEVICE_TYPE_802_11_WIRELESS:
+		s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
+		if (s_wireless) {
+			devices = nm_system_config_hal_manager_get_devices_of_type (priv->hal_mgr, DEVICE_TYPE_802_11_WIRELESS);
+			udi = get_ether_device_udi (plugin, s_wireless->mac_address, devices);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	g_slist_foreach (devices, (GFunc) g_free, NULL);
+	g_slist_free (devices);
+
+	return udi;
+}
 
 static void
-write_auto_wired_connection (const char *profile_path)
+device_added_cb (NMSystemConfigHalManager *hal_mgr,
+                 const char *udi,
+                 NMDeviceType devtype,
+                 gpointer user_data)
 {
-	GError *error = NULL;
-	char *path;
-	const char *contents = "# Written by nm-system-settings\nTYPE=Ethernet\nBOOTPROTO=dhcp\nONBOOT=yes\nUSERCTL=yes\nPEERDNS=yes\n";
+	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	GSList *iter;
+	gboolean changed = FALSE;
 
-	/* Write out a default autoconnect ethernet connection */
-	if (g_file_test (AUTO_WIRED_STAMP_FILE, G_FILE_TEST_EXISTS) || !profile_path)
-		return;
+	/* Try to get the UDI for all connections that don't have a UDI yet */
+	for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
+		NMConnection *connection = NM_CONNECTION (iter->data);
+		ConnectionData *cdata = connection_data_get (connection);
 
-	path = g_strdup_printf ("%s/ifcfg-%s", profile_path, AUTO_WIRED_FILE_NAME);
-	if (g_file_test (path, G_FILE_TEST_EXISTS))
-		return;
+		if (!cdata->udi) {
+			cdata->udi = get_udi_for_connection (plugin, connection, devtype);
+			if (cdata->udi && cdata->ignored)
+				changed = TRUE;
+		}
+	}
 
-	PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "writing default Auto Wired connection");
-	if (!g_file_set_contents (path, contents, -1, &error)) {
-		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "could not write default wired connection: %s (%d).", error->message, error->code);
-		g_error_free (error);
-	} else {
-		g_file_set_contents (AUTO_WIRED_STAMP_FILE, "", -1, NULL);
+	if (changed)
+		g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+}
+
+static void
+device_removed_cb (NMSystemConfigHalManager *hal_mgr,
+                   const char *udi,
+                   NMDeviceType devtype,
+                   gpointer user_data)
+{
+	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	GSList *iter;
+	gboolean changed = FALSE;
+
+	/* Try to get the UDI for all connections that don't have a UDI yet */
+	for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
+		NMConnection *connection = NM_CONNECTION (iter->data);
+		ConnectionData *cdata = connection_data_get (connection);
+
+		if (cdata->udi && !strcmp (cdata->udi, udi)) {
+			g_free (cdata->udi);
+			cdata->udi = NULL;
+			if (cdata->ignored)
+				changed = TRUE;
+		}
+	}
+
+	if (changed)
+		g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+}
+
+static GSList *
+get_unmanaged_devices (NMSystemConfigInterface *config)
+{
+	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	GSList *copy = NULL, *iter;
+
+	for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
+		ConnectionData *cdata = connection_data_get (NM_CONNECTION (iter->data));
+
+		if (cdata->ignored && cdata->udi)
+			copy = g_slist_append (copy, g_strdup (cdata->udi));
 	}
+	return copy;
 }
 
 struct FindInfo {
@@ -143,7 +311,7 @@
 }
 
 static NMConnection *
-build_one_connection (const char *path)
+build_one_connection (SCPluginIfcfg *plugin, const char *path)
 {
 	NMConnection *connection;
 	GError *error = NULL;
@@ -155,6 +323,9 @@
 	connection = parser_parse_file (path, &error);
 	if (connection) {
 		NMSettingConnection *s_con;
+		ConnectionData *cdata = connection_data_get (connection);
+
+		cdata->udi = get_udi_for_connection (plugin, connection, DEVICE_TYPE_UNKNOWN);
 
 		s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
 		g_assert (s_con);
@@ -169,7 +340,8 @@
 }
 
 static NMConnection *
-handle_new_ifcfg (const char *basename,
+handle_new_ifcfg (SCPluginIfcfg *plugin,
+                  const char *basename,
                   const int inotify_fd,
                   GHashTable *watch_table)
 {
@@ -187,7 +359,7 @@
 		return NULL;
 	}
 
-	connection = build_one_connection (path);
+	connection = build_one_connection (plugin, path);
 	if (!connection)
 		goto out;
 
@@ -204,8 +376,8 @@
 
 	cdata = connection_data_get (connection);
 	if (cdata->ignored) {
-		PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' because "
-		              "NM_CONTROLLED was false.", basename);
+		PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its "
+		              "device because NM_CONTROLLED was false.", basename);
 	}
 
 out:
@@ -253,13 +425,46 @@
 }
 
 static void
+kill_old_auto_wired_file (void)
+{
+	char *path;
+	const char *match = "# Written by nm-system-settings\nTYPE=Ethernet\nBOOTPROTO=dhcp\nONBOOT=yes\nUSERCTL=yes\nPEERDNS=yes\n";
+	char *contents = NULL;
+	gsize length = 0;
+
+	path = g_strdup_printf (IFCFG_DIR "/ifcfg-Auto Wired");
+	if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+		g_free (path);
+		return;
+	}
+
+	if (!g_file_get_contents (path, &contents, &length, NULL))
+		goto out;
+
+	if (!length && !contents)
+		goto out;
+
+	if (   (length != strlen (match))
+	    && (length != (strlen (match) - 1))
+	    && (length != (strlen (match) + 1)))
+		goto out;
+
+	if (strncmp (contents, match, MIN (length, strlen (match))))
+		goto out;
+
+	unlink (path);
+
+out:
+	g_free (contents);
+	g_free (path);
+}
+
+static void
 read_all_connections (SCPluginIfcfg *plugin)
 {
 	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	GDir *dir;
 	const char *item;
-	GSList *iter;
-	gboolean have_wired = FALSE;
 
 	clear_all_connections (plugin);
 
@@ -269,31 +474,25 @@
 	if (dir) {
 		while ((item = g_dir_read_name (dir))) {
 			NMConnection *connection;
+			ConnectionData *cdata;
 
 			if (strncmp (item, IFCFG_TAG, strlen (IFCFG_TAG)))
 				continue;
 
-			connection = handle_new_ifcfg (item, priv->ifd, priv->watch_table);
-			if (connection)
+			connection = handle_new_ifcfg (plugin, item, priv->ifd, priv->watch_table);
+			if (connection) {
 				priv->connections = g_slist_append (priv->connections, connection);
+				cdata = connection_data_get (connection);
+				if (cdata->ignored && cdata->udi)
+					g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+			}
 		}
 		g_dir_close (dir);
 	} else {
 		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "couldn't access network config directory '" IFCFG_DIR "'.");
 	}
 
-	/* Check if we need to write out the auto wired connection */
-	for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
-		NMConnection *connection = NM_CONNECTION (iter->data);
-		NMSettingConnection *s_con;
-
-		s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
-		if (!strcmp (s_con->type, NM_SETTING_WIRED_SETTING_NAME))
-			have_wired = TRUE;
-	}
-
-	if (!have_wired)
-		write_auto_wired_connection (IFCFG_DIR);
+	kill_old_auto_wired_file ();
 }
 
 static GSList *
@@ -427,7 +626,7 @@
 	}
 
 	/* Could return NULL if the connection got deleted */
-	new_connection = build_one_connection (filename);
+	new_connection = build_one_connection (plugin, filename);
 
 	existing = find_connection_by_path (priv->connections, filename);
 	if (!existing) {
@@ -440,6 +639,11 @@
 			if (!new_cdata->ignored) {
 				new_cdata->exported = TRUE;
 				g_signal_emit_by_name (plugin, "connection-added", new_connection);
+			} else {
+				PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its "
+				              "device because NM_CONTROLLED was false.", basename);
+				if (new_cdata->udi)
+					g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
 			}
 		}
 		g_free (filename);
@@ -466,24 +670,34 @@
 			g_assert (new_cdata);
 
 			connection_data_copy_secrets (new_cdata, existing_cdata);
+			g_free (existing_cdata->udi);
+			existing_cdata->udi = new_cdata->udi ? g_strdup (new_cdata->udi) : NULL;
 
 			if (new_cdata->ignored && !existing_cdata->ignored) {
 				/* connection now ignored */
+				PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its "
+				              "device because NM_CONTROLLED was false.", basename);
+
 				existing_cdata->ignored = TRUE;
 				g_signal_emit_by_name (plugin, "connection-removed", existing);
 				existing_cdata->exported = FALSE;
+				if (existing_cdata->udi)
+					g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
 			} else if (!new_cdata->ignored && existing_cdata->ignored) {
 				/* connection no longer ignored, let the system settings
 				 * service know about it now.
 				 */
 				existing_cdata->ignored = FALSE;
 				existing_cdata->exported = TRUE;
+				if (existing_cdata->udi)
+					g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
 				g_signal_emit_by_name (plugin, "connection-added", existing);
 			} else if (!new_cdata->ignored && !existing_cdata->ignored) {
 				/* connection updated and not ignored */
 				g_signal_emit_by_name (plugin, "connection-updated", existing);
 			} else if (new_cdata->ignored && existing_cdata->ignored) {
-				/* do nothing */
+				if (existing_cdata->udi)
+					g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
 			}
 		}
 		g_object_unref (new_connection);
@@ -495,6 +709,10 @@
 		priv->connections = g_slist_remove (priv->connections, existing);
 		if (!existing_cdata->ignored)
 			g_signal_emit_by_name (plugin, "connection-removed", existing);
+		else {
+			if (existing_cdata->udi)
+				g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
+		}
 		g_object_unref (existing);
 		PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "    removed connection");
 	}
@@ -521,7 +739,7 @@
 		return;
 
 	/* New connection */
-	connection = handle_new_ifcfg (basename, priv->ifd, priv->watch_table);
+	connection = handle_new_ifcfg (plugin, basename, priv->ifd, priv->watch_table);
 	if (!connection)
 		return;
 
@@ -533,6 +751,9 @@
 	if (!cdata->ignored) {
 		cdata->exported = TRUE;
 		g_signal_emit_by_name (plugin, "connection-added", connection);
+	} else {
+		if (cdata->udi)
+			g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
 	}
 }
 
@@ -665,9 +886,10 @@
 }
 
 static void
-init (NMSystemConfigInterface *config)
+init (NMSystemConfigInterface *config, NMSystemConfigHalManager *hal_manager)
 {
 	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config);
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
 	GError *error = NULL;
 
 	if (!sc_plugin_inotify_init (plugin, &error)) {
@@ -675,17 +897,38 @@
 		              error->message ? error->message : "(unknown)");
 		g_error_free (error);
 	}
+
+	priv->hal_mgr = g_object_ref (hal_manager);
+	g_signal_connect (priv->hal_mgr, "device-added", G_CALLBACK (device_added_cb), config);
+	g_signal_connect (priv->hal_mgr, "device-removed", G_CALLBACK (device_removed_cb), config);
 }
 
 static void
 sc_plugin_ifcfg_init (SCPluginIfcfg *plugin)
 {
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	GError *error = NULL;
+
+	priv->g_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+	if (!priv->g_connection) {
+		PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "    dbus-glib error: %s",
+		              error->message ? error->message : "(unknown)");
+		g_free (error);
+	}
 }
 
 static void
 dispose (GObject *object)
 {
-	clear_all_connections (SC_PLUGIN_IFCFG (object));
+	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (object);
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+
+	clear_all_connections (plugin);
+
+	g_object_unref (priv->hal_mgr);
+
+	if (priv->g_connection)
+		g_object_unref (priv->g_connection);
 
 	G_OBJECT_CLASS (sc_plugin_ifcfg_parent_class)->dispose (object);
 }
@@ -739,6 +982,7 @@
 	/* interface implementation */
 	system_config_interface_class->get_connections = get_connections;
 	system_config_interface_class->get_secrets = get_secrets;
+	system_config_interface_class->get_unmanaged_devices = get_unmanaged_devices;
 	system_config_interface_class->init = init;
 }
 

Modified: trunk/system-settings/plugins/ifcfg-suse/plugin.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-suse/plugin.c	(original)
+++ trunk/system-settings/plugins/ifcfg-suse/plugin.c	Tue Apr  8 02:36:39 2008
@@ -326,7 +326,7 @@
 }
 
 static void
-init (NMSystemConfigInterface *config)
+init (NMSystemConfigInterface *config, NMSystemConfigHalManager *hal_manager)
 {
 	GFile *file;
 	GFileMonitor *monitor;

Modified: trunk/system-settings/src/Makefile.am
==============================================================================
--- trunk/system-settings/src/Makefile.am	(original)
+++ trunk/system-settings/src/Makefile.am	Tue Apr  8 02:36:39 2008
@@ -1,16 +1,23 @@
 INCLUDES = -I${top_srcdir} \
            -I${top_srcdir}/include \
            -I${top_srcdir}/libnm-util \
-           -I${top_srcdir}/libnm-glib
+           -I${top_srcdir}/libnm-glib \
+           -I${top_builddir}/marshallers
 
 sbin_PROGRAMS = nm-system-settings
 
+BUILT_SOURCES = \
+	nm-settings-system-glue.h
+
 nm_system_settings_SOURCES = \
 	dbus-settings.c \
 	dbus-settings.h \
 	main.c \
 	nm-system-config-interface.c \
-	nm-system-config-interface.h
+	nm-system-config-interface.h \
+	nm-system-config-hal-manager.c \
+	nm-system-config-hal-manager.h \
+	nm-system-config-hal-manager-private.h
 
 nm_system_settings_CPPFLAGS = \
 	$(DBUS_CFLAGS) \
@@ -32,10 +39,15 @@
 	$(GTHREAD_LIBS) \
 	$(GMODULE_LIBS) \
 	$(top_builddir)/libnm-util/libnm-util.la \
-	$(top_builddir)/libnm-glib/libnm_glib.la
+	$(top_builddir)/libnm-glib/libnm_glib.la \
+	$(top_builddir)/marshallers/libmarshallers.la
 
 nm_system_settings_LDFLAGS = -rdynamic
 
+nm-settings-system-glue.h: $(top_srcdir)/introspection/nm-settings-system.xml
+	dbus-binding-tool --prefix=nm_settings_system --mode=glib-server --output=nm-settings-system-glue.h $(top_srcdir)/introspection/nm-settings-system.xml
+
+
 dbusservicedir = $(DBUS_SYS_DIR)
 dbusservice_DATA = nm-system-settings.conf
 
@@ -46,4 +58,6 @@
 	$(dbusservice_DATA) \
 	$(dbusactivation_DATA)
 
+CLEANFILES = \
+	$(BUILT_SOURCES)
 

Modified: trunk/system-settings/src/dbus-settings.c
==============================================================================
--- trunk/system-settings/src/dbus-settings.c	(original)
+++ trunk/system-settings/src/dbus-settings.c	Tue Apr  8 02:36:39 2008
@@ -26,6 +26,7 @@
 
 #include <nm-setting-connection.h>
 
+#include "nm-dbus-glib-types.h"
 #include "dbus-settings.h"
 #include "nm-system-config-interface.h"
 #include "nm-utils.h"
@@ -150,7 +151,6 @@
 static void
 nm_sysconfig_exported_connection_init (NMSysconfigExportedConnection *sysconfig_exported_connection)
 {
-	
 }
 
 NMSysconfigExportedConnection *
@@ -174,21 +174,42 @@
  * NMSettings
  */
 
+#include "nm-settings-system-glue.h"
+
+typedef struct {
+	GSList *connections;
+	GHashTable *unmanaged_devices;
+} NMSysconfigSettingsPrivate;
+
 G_DEFINE_TYPE (NMSysconfigSettings, nm_sysconfig_settings, NM_TYPE_SETTINGS);
 
+#define NM_SYSCONFIG_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsPrivate))
+
+enum {
+	PROPERTIES_CHANGED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+enum {
+	PROP_0,
+	PROP_UNMANAGED_DEVICES,
+
+	LAST_PROP
+};
+
 static GPtrArray *
-nm_sysconfig_settings_list_connections (NMSettings *settings)
+list_connections (NMSettings *settings)
 {
+	NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (settings);
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
 	GPtrArray *connections;
-	NMSysconfigSettings *sysconfig_settings;
 	GSList *iter;
 
-	g_return_val_if_fail (NM_IS_SYSCONFIG_SETTINGS (settings), NULL);
-
-	sysconfig_settings = NM_SYSCONFIG_SETTINGS (settings);
-
 	connections = g_ptr_array_new ();
-	for (iter = sysconfig_settings->connections; iter; iter = g_slist_next (iter)) {
+	for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
 		NMExportedConnection *exported = NM_EXPORTED_CONNECTION (iter->data);
 		NMConnection *connection;
 		char *path;
@@ -204,33 +225,145 @@
 }
 
 static void
-nm_sysconfig_settings_finalize (GObject *object)
+settings_finalize (GObject *object)
 {
-	NMSysconfigSettings *settings = NM_SYSCONFIG_SETTINGS (object);
+	NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object);
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
 
-	if (settings->connections) {
-		g_slist_foreach (settings->connections, (GFunc) g_object_unref, NULL);
-		g_slist_free (settings->connections);
-		settings->connections = NULL;
+	if (priv->connections) {
+		g_slist_foreach (priv->connections, (GFunc) g_object_unref, NULL);
+		g_slist_free (priv->connections);
+		priv->connections = NULL;
 	}
 
+	g_hash_table_destroy (priv->unmanaged_devices);
+
 	G_OBJECT_CLASS (nm_sysconfig_settings_parent_class)->finalize (object);
 }
 
 static void
+add_one_unmanaged_device (gpointer key, gpointer data, gpointer user_data)
+{
+	GPtrArray *devices = (GPtrArray *) user_data;
+
+	g_ptr_array_add (devices, g_strdup (key));	
+}
+
+static char*
+uscore_to_wincaps (const char *uscore)
+{
+	const char *p;
+	GString *str;
+	gboolean last_was_uscore;
+
+	last_was_uscore = TRUE;
+  
+	str = g_string_new (NULL);
+	p = uscore;
+	while (p && *p) {
+		if (*p == '-' || *p == '_')
+			last_was_uscore = TRUE;
+		else {
+			if (last_was_uscore) {
+				g_string_append_c (str, g_ascii_toupper (*p));
+				last_was_uscore = FALSE;
+			} else
+				g_string_append_c (str, *p);
+		}
+		++p;
+	}
+
+	return g_string_free (str, FALSE);
+}
+
+static void
+notify (GObject *object, GParamSpec *pspec)
+{
+	GValue *value;
+	GHashTable *hash;
+
+	value = g_slice_new0 (GValue);
+	hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+
+	g_value_init (value, pspec->value_type);
+	g_object_get_property (object, pspec->name, value);
+	g_hash_table_insert (hash, uscore_to_wincaps (pspec->name), value);
+	g_signal_emit (object, signals[PROPERTIES_CHANGED], 0, hash);
+	g_hash_table_destroy (hash);
+	g_value_unset (value);
+	g_slice_free (GValue, value);
+}
+
+static GPtrArray *
+get_unmanaged_devices (NMSysconfigSettings *self)
+{
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	GPtrArray *devices;
+
+ 	devices = g_ptr_array_sized_new (3);
+	g_hash_table_foreach (priv->unmanaged_devices, (GHFunc) add_one_unmanaged_device, devices);
+	return devices;
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec)
+{
+	NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object);
+
+	switch (prop_id) {
+	case PROP_UNMANAGED_DEVICES:
+		g_value_take_boxed (value, get_unmanaged_devices (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
 nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (class);	
 	NMSettingsClass *settings_class = NM_SETTINGS_CLASS (class);
 	
-	object_class->finalize = nm_sysconfig_settings_finalize;
-	settings_class->list_connections = nm_sysconfig_settings_list_connections;
+	g_type_class_add_private (settings_class, sizeof (NMSysconfigSettingsPrivate));
+
+	/* virtual methods */
+	object_class->notify = notify;
+	object_class->get_property = get_property;
+	object_class->finalize = settings_finalize;
+	settings_class->list_connections = list_connections;
+
+	/* properties */
+	g_object_class_install_property
+		(object_class, PROP_UNMANAGED_DEVICES,
+		 g_param_spec_boxed (NM_SYSCONFIG_SETTINGS_UNMANAGED_DEVICES,
+							 "Unamanged devices",
+							 "Unmanaged devices",
+							 DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH,
+							 G_PARAM_READABLE));
+
+	/* signals */
+	signals[PROPERTIES_CHANGED] = 
+	                g_signal_new ("properties-changed",
+	                              G_OBJECT_CLASS_TYPE (object_class),
+	                              G_SIGNAL_RUN_FIRST,
+	                              G_STRUCT_OFFSET (NMSysconfigSettingsClass, properties_changed),
+	                              NULL, NULL,
+	                              g_cclosure_marshal_VOID__BOXED,
+	                              G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_VARIANT);
+
+	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (settings_class),
+	                                 &dbus_glib_nm_settings_system_object_info);
 }
 
 static void
-nm_sysconfig_settings_init (NMSysconfigSettings *sysconfig_settings)
+nm_sysconfig_settings_init (NMSysconfigSettings *self)
 {
-	sysconfig_settings->connections = NULL;
+	NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	priv->unmanaged_devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
 }
 
 NMSysconfigSettings *
@@ -244,37 +377,41 @@
 }
 
 void
-nm_sysconfig_settings_add_connection (NMSysconfigSettings *settings,
+nm_sysconfig_settings_add_connection (NMSysconfigSettings *self,
                                       NMConnection *connection,
                                       DBusGConnection *g_connection)
 {
+	NMSysconfigSettingsPrivate *priv;
 	NMSysconfigExportedConnection *exported;
 
-	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (settings));
+	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
 	g_return_if_fail (NM_IS_CONNECTION (connection));
 
+	priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
 	exported = nm_sysconfig_exported_connection_new (connection, g_connection);
 	if (!exported) {
 		g_warning ("%s: couldn't export the connection!", __func__);
 		return;
 	}
 
-	settings->connections = g_slist_append (settings->connections, exported);
+	priv->connections = g_slist_append (priv->connections, exported);
 
-	nm_settings_signal_new_connection (NM_SETTINGS (settings),
+	nm_settings_signal_new_connection (NM_SETTINGS (self),
 	                                   NM_EXPORTED_CONNECTION (exported));
 }
 
 static void
-remove_connection (NMSysconfigSettings *settings,
+remove_connection (NMSysconfigSettings *self,
                    NMConnection *connection)
 {
+	NMSysconfigSettingsPrivate *priv;
 	GSList *iter;
 
-	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (settings));
+	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
 	g_return_if_fail (NM_IS_CONNECTION (connection));
 
-	for (iter = settings->connections; iter; iter = g_slist_next (iter)) {
+	priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
 		NMSysconfigExportedConnection *item = NM_SYSCONFIG_EXPORTED_CONNECTION (iter->data);
 		NMExportedConnection *exported = NM_EXPORTED_CONNECTION (item);
 		NMConnection *wrapped;
@@ -282,7 +419,7 @@
 		wrapped = nm_exported_connection_get_connection (exported);
 
 		if (wrapped == connection) {
-			settings->connections = g_slist_remove (settings->connections, iter);
+			priv->connections = g_slist_remove_link (priv->connections, iter);
 			nm_exported_connection_signal_removed (exported);
 			g_object_unref (item);
 			g_slist_free (iter);
@@ -299,22 +436,23 @@
 }
 
 void
-nm_sysconfig_settings_update_connection (NMSysconfigSettings *settings,
+nm_sysconfig_settings_update_connection (NMSysconfigSettings *self,
                                          NMConnection *connection)
 {
+	NMSysconfigSettingsPrivate *priv;
 	GHashTable *hash;
 	GSList *iter;
 	NMSysconfigExportedConnection *found = NULL;
 
-	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (settings));
+	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
 	g_return_if_fail (NM_IS_CONNECTION (connection));
 
-	for (iter = settings->connections; iter; iter = g_slist_next (iter)) {
+	priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+	for (iter = priv->connections; iter; iter = g_slist_next (iter)) {
 		NMSysconfigExportedConnection *item = NM_SYSCONFIG_EXPORTED_CONNECTION (iter->data);
 		NMConnection *wrapped;
 
 		wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (item));
-
 		if (wrapped == connection) {
 			found = item;
 			break;
@@ -328,7 +466,7 @@
 
 	/* If the connection is no longer valid, it gets removed */
 	if (!nm_connection_verify (connection)) {
-		remove_connection (settings, connection);
+		remove_connection (self, connection);
 		return;
 	}
 
@@ -337,3 +475,25 @@
 	g_hash_table_destroy (hash);
 }
 
+void
+nm_sysconfig_settings_update_unamanged_devices (NMSysconfigSettings *self,
+                                                GSList *new_list)
+{
+	NMSysconfigSettingsPrivate *priv;
+	GSList *iter;
+
+	g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
+
+	priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self);
+
+	g_hash_table_remove_all (priv->unmanaged_devices);
+	for (iter = new_list; iter; iter = g_slist_next (iter)) {
+		if (!g_hash_table_lookup (priv->unmanaged_devices, iter->data)) {
+			g_hash_table_insert (priv->unmanaged_devices,
+			                     g_strdup (iter->data),
+			                     GUINT_TO_POINTER (1));
+		}
+	}
+	g_object_notify (G_OBJECT (self), NM_SYSCONFIG_SETTINGS_UNMANAGED_DEVICES);
+}
+

Modified: trunk/system-settings/src/dbus-settings.h
==============================================================================
--- trunk/system-settings/src/dbus-settings.h	(original)
+++ trunk/system-settings/src/dbus-settings.h	Tue Apr  8 02:36:39 2008
@@ -43,12 +43,12 @@
 
 struct _NMSysconfigExportedConnection
 {
-    NMExportedConnection parent_instance;
+	NMExportedConnection parent_instance;
 };
 
 struct _NMSysconfigExportedConnectionClass
 {
-    NMExportedConnectionClass parent_class;
+	NMExportedConnectionClass parent_class;
 };
 
 GType nm_sysconfig_exported_connection_get_type (void);
@@ -68,16 +68,19 @@
 #define NM_IS_SYSCONFIG_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  NM_TYPE_SYSCONFIG_SETTINGS))
 #define NM_SYSCONFIG_SETTINGS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsClass))
 
+#define NM_SYSCONFIG_SETTINGS_UNMANAGED_DEVICES "unmanaged-devices"
+
 struct _NMSysconfigSettings
 {
-    NMSettings parent_instance;
-
-    GSList *connections;
+	NMSettings parent_instance;
 };
 
 struct _NMSysconfigSettingsClass
 {
-    NMSettingsClass parent_class;
+	NMSettingsClass parent_class;
+
+	/* Signals */
+	void (*properties_changed) (NMSysconfigSettings *settings, GHashTable *properties);
 };
 
 GType nm_sysconfig_settings_get_type (void);
@@ -94,4 +97,7 @@
 void nm_sysconfig_settings_update_connection (NMSysconfigSettings *settings,
                                               NMConnection *connection);
 
+void nm_sysconfig_settings_update_unamanged_devices (NMSysconfigSettings *settings,
+                                                     GSList *new_list);
+
 #endif  /* __DBUS_SETTINGS_H__ */

Added: trunk/system-settings/src/nm-system-config-hal-manager-private.h
==============================================================================
--- (empty file)
+++ trunk/system-settings/src/nm-system-config-hal-manager-private.h	Tue Apr  8 02:36:39 2008
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008 Dan Williams
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+/* *** Not to be used by system settings service plugins *** */
+
+#ifndef NM_SYSTEM_CONFIG_HAL_MANAGER_PRIVATE_H
+#define NM_SYSTEM_CONFIG_HAL_MANAGER_PRIVATE_H
+
+#include "nm-system-config-hal-manager.h"
+
+NMSystemConfigHalManager *nm_system_config_hal_manager_get (DBusGConnection *g_connection);
+
+void nm_system_config_hal_manager_reinit_dbus (NMSystemConfigHalManager *manager,
+                                               DBusGConnection *g_connection);
+
+void nm_system_config_hal_manager_deinit_dbus (NMSystemConfigHalManager *manager);
+
+#endif /* NM_SYSTEM_CONFIG_HAL_MANAGER_PRIVATE_H */

Added: trunk/system-settings/src/nm-system-config-hal-manager.c
==============================================================================
--- (empty file)
+++ trunk/system-settings/src/nm-system-config-hal-manager.c	Tue Apr  8 02:36:39 2008
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2008 Dan Williams
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+
+#include <string.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include "nm-marshal.h"
+#include "nm-dbus-glib-types.h"
+#include "nm-system-config-hal-manager.h"
+#include "nm-system-config-hal-manager-private.h"
+
+#define NUM_DEVICE_TYPES	DEVICE_TYPE_CDMA
+
+typedef struct {
+	DBusGConnection *g_connection;
+	DBusGProxy *proxy;
+	GHashTable *devices;
+} NMSystemConfigHalManagerPrivate;
+
+#define NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+                                                     NM_TYPE_SYSTEM_CONFIG_HAL_MANAGER, \
+                                                     NMSystemConfigHalManagerPrivate))
+
+G_DEFINE_TYPE (NMSystemConfigHalManager, nm_system_config_hal_manager, G_TYPE_OBJECT)
+
+enum {
+	DEVICE_ADDED,
+	DEVICE_REMOVED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static NMDeviceType
+get_type_for_udi (NMSystemConfigHalManager *manager, const char *udi)
+{
+	NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
+	NMDeviceType devtype = DEVICE_TYPE_UNKNOWN;
+	DBusGProxy *dev_proxy;
+	GError *error = NULL;
+	GSList *capabilities = NULL, *iter;
+
+	dev_proxy = dbus_g_proxy_new_for_name (priv->g_connection,
+	                                       "org.freedesktop.Hal",
+	                                       udi,
+	                                       "org.freedesktop.Hal.Device");
+	if (!dev_proxy)
+		return DEVICE_TYPE_UNKNOWN;
+
+	if (!dbus_g_proxy_call_with_timeout (dev_proxy,
+	                                     "GetPropertyStringList", 10000, &error,
+	                                     G_TYPE_STRING, "info.capabilities", G_TYPE_INVALID,
+	                                     DBUS_TYPE_G_LIST_OF_STRING, &capabilities, G_TYPE_INVALID)) {		
+		g_error_free (error);
+		goto out;
+	}
+
+	if (!g_slist_length (capabilities))
+		goto out;
+
+	for (iter = capabilities; iter && (devtype == DEVICE_TYPE_UNKNOWN); iter = g_slist_next (iter)) {
+		if (!strcmp (iter->data, "net.80203"))
+			devtype = DEVICE_TYPE_802_3_ETHERNET;
+		else if (!strcmp (iter->data, "net.80211"))
+			devtype = DEVICE_TYPE_802_11_WIRELESS;
+		else if (!strcmp (iter->data, "modem")) {
+			GSList *csets = NULL, *elt;
+
+			if (dbus_g_proxy_call_with_timeout (dev_proxy,
+			                                    "GetPropertyStringList", 10000, &error,
+			                                    G_TYPE_STRING, "modem.command_sets", G_TYPE_INVALID,
+			                                    DBUS_TYPE_G_LIST_OF_STRING, &csets, G_TYPE_INVALID)) {		
+				for (elt = csets; elt && (devtype == DEVICE_TYPE_UNKNOWN); elt = g_slist_next (elt)) {
+					if (!strcmp (elt->data, "GSM-07.07"))
+						devtype = DEVICE_TYPE_GSM;
+					else if (!strcmp (elt->data, "IS-707-A"))
+						devtype = DEVICE_TYPE_CDMA;
+				}
+			}
+		}
+	}
+
+	g_boxed_free (DBUS_TYPE_G_LIST_OF_STRING, capabilities);
+
+out:
+	g_object_unref (dev_proxy);
+	return devtype;
+}
+
+static void
+device_added_cb (DBusGProxy *proxy, const char *udi, gpointer user_data)
+{
+	NMSystemConfigHalManager *manager = NM_SYSTEM_CONFIG_HAL_MANAGER (user_data);
+	NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
+	NMDeviceType devtype;
+
+	if (!g_hash_table_lookup (priv->devices, udi)) {
+		devtype = get_type_for_udi (manager, udi);
+		if (devtype != DEVICE_TYPE_UNKNOWN) {
+			g_hash_table_insert (priv->devices, g_strdup (udi), GUINT_TO_POINTER (devtype));
+			g_signal_emit (manager, signals[DEVICE_ADDED], 0, udi, devtype);
+		}
+	}
+}
+
+static void
+device_removed_cb (DBusGProxy *proxy, const char *udi, gpointer user_data)
+{
+	NMSystemConfigHalManager *manager = NM_SYSTEM_CONFIG_HAL_MANAGER (user_data);
+	NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
+	NMDeviceType devtype;
+
+	devtype = GPOINTER_TO_UINT (g_hash_table_lookup (priv->devices, udi));
+	if (devtype != DEVICE_TYPE_UNKNOWN) {
+		g_signal_emit (manager, signals[DEVICE_REMOVED], 0, udi, devtype);
+		g_hash_table_remove (priv->devices, udi);
+	}
+}
+
+static void
+device_new_capability_cb (DBusGProxy *proxy,
+                          const char *udi,
+                          const char *capability,
+                          gpointer user_data)
+{
+	NMSystemConfigHalManager *manager = NM_SYSTEM_CONFIG_HAL_MANAGER (user_data);
+	NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
+	NMDeviceType devtype;
+
+	if (!g_hash_table_lookup (priv->devices, udi)) {
+		devtype = get_type_for_udi (manager, udi);
+		if (devtype != DEVICE_TYPE_UNKNOWN) {
+			g_hash_table_insert (priv->devices, g_strdup (udi), GUINT_TO_POINTER (devtype));
+			g_signal_emit (manager, signals[DEVICE_ADDED], 0, udi, devtype);
+		}
+	}
+}
+
+static void
+initial_add_devices_of_type (NMSystemConfigHalManager *manager, const char *capability)
+{
+	NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
+	GSList *devices = NULL, *iter;
+	GError *error = NULL;
+
+	if (!dbus_g_proxy_call_with_timeout (priv->proxy,
+	                                     "FindDeviceByCapability", 10000, &error,
+	                                     G_TYPE_STRING, capability, G_TYPE_INVALID,
+	                                     DBUS_TYPE_G_LIST_OF_STRING, &devices, G_TYPE_INVALID)) {		
+		g_warning ("%s: could not get device from HAL: %s (%d).",
+		           __func__, error->message, error->code);
+		g_error_free (error);
+		return;
+	}
+
+	for (iter = devices; iter; iter = g_slist_next (iter))
+		device_added_cb (priv->proxy, (const char *) iter->data, manager);
+
+	if (devices)
+		g_boxed_free (DBUS_TYPE_G_LIST_OF_STRING, devices);
+}
+
+static gboolean
+init_dbus (NMSystemConfigHalManager *manager, DBusGConnection *g_connection)
+{
+	NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
+
+	priv->g_connection = g_connection;
+	priv->proxy = dbus_g_proxy_new_for_name (priv->g_connection,
+	                                         "org.freedesktop.Hal",
+	                                         "/org/freedesktop/Hal/Manager",
+	                                         "org.freedesktop.Hal.Manager");
+	if (!priv->proxy) {
+		g_warning ("Could not get the HAL object!");
+		priv->g_connection = NULL;
+		return FALSE;
+	}
+
+	dbus_g_proxy_add_signal (priv->proxy, "DeviceAdded", G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "DeviceAdded", G_CALLBACK (device_added_cb), manager, NULL);
+
+	dbus_g_proxy_add_signal (priv->proxy, "DeviceRemoved", G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "DeviceRemoved", G_CALLBACK (device_removed_cb), manager, NULL);
+
+	dbus_g_object_register_marshaller (nm_marshal_VOID__STRING_STRING,
+									   G_TYPE_NONE,
+									   G_TYPE_STRING, G_TYPE_STRING,
+									   G_TYPE_INVALID);
+	dbus_g_proxy_add_signal (priv->proxy, "NewCapability", G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+	dbus_g_proxy_connect_signal (priv->proxy, "NewCapability", G_CALLBACK (device_new_capability_cb), manager, NULL);
+
+	initial_add_devices_of_type (manager, "net.80203");
+	initial_add_devices_of_type (manager, "net.80211");
+	initial_add_devices_of_type (manager, "modem");
+
+	return TRUE;
+}
+
+static void
+remove_all_devices (gpointer key, gpointer data, gpointer user_data)
+{
+	NMSystemConfigHalManager *manager = NM_SYSTEM_CONFIG_HAL_MANAGER (user_data);
+
+	g_signal_emit (manager, signals[DEVICE_REMOVED], 0, key, GPOINTER_TO_UINT (data));
+}
+
+static void
+cleanup_dbus (NMSystemConfigHalManager *manager)
+{
+	NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
+
+	g_hash_table_foreach (priv->devices, (GHFunc) remove_all_devices, manager);
+	g_hash_table_remove_all (priv->devices);
+
+	if (priv->proxy) {
+		g_object_unref (priv->proxy);
+		priv->proxy = NULL;
+	}
+
+	priv->g_connection = NULL;
+}
+
+static NMSystemConfigHalManager *
+nm_system_config_hal_manager_new (DBusGConnection *g_connection)
+{
+	NMSystemConfigHalManager *manager;
+
+	g_return_val_if_fail (g_connection != NULL, NULL);
+
+	manager = g_object_new (NM_TYPE_SYSTEM_CONFIG_HAL_MANAGER, NULL);
+
+	if (!init_dbus (manager, g_connection)) {
+		g_object_unref (manager);
+		return NULL;
+	}
+
+	return manager;
+}
+
+NMSystemConfigHalManager *
+nm_system_config_hal_manager_get (DBusGConnection *g_connection)
+{
+	static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+	static NMSystemConfigHalManager *singleton = NULL;
+
+	g_static_mutex_lock (&mutex);
+	if (!singleton)
+		singleton = nm_system_config_hal_manager_new (g_connection);
+	else
+		g_object_ref (singleton);
+	g_static_mutex_unlock (&mutex);
+
+	return singleton;
+}
+
+static void
+nm_system_config_hal_manager_init (NMSystemConfigHalManager *manager)
+{
+	NMSystemConfigHalManagerPrivate *priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
+
+	priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+}
+
+static void
+dispose (GObject *object)
+{
+	cleanup_dbus (NM_SYSTEM_CONFIG_HAL_MANAGER (object));
+
+	G_OBJECT_CLASS (nm_system_config_hal_manager_parent_class)->dispose (object);
+}
+
+static void
+nm_system_config_hal_manager_class_init (NMSystemConfigHalManagerClass *manager_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (manager_class);
+
+	g_type_class_add_private (manager_class, sizeof (NMSystemConfigHalManagerPrivate));
+
+	/* virtual methods */
+	object_class->dispose = dispose;
+
+	/* signals */
+	signals[DEVICE_ADDED] =
+		g_signal_new ("device-added",
+					  G_OBJECT_CLASS_TYPE (object_class),
+					  G_SIGNAL_RUN_FIRST,
+					  G_STRUCT_OFFSET (NMSystemConfigHalManagerClass, device_added),
+					  NULL, NULL,
+					  nm_marshal_VOID__STRING_UINT,
+					  G_TYPE_NONE, 2,
+					  G_TYPE_STRING,
+					  G_TYPE_UINT);
+
+	signals[DEVICE_REMOVED] =
+		g_signal_new ("device-removed",
+					  G_OBJECT_CLASS_TYPE (object_class),
+					  G_SIGNAL_RUN_FIRST,
+					  G_STRUCT_OFFSET (NMSystemConfigHalManagerClass, device_removed),
+					  NULL, NULL,
+					  nm_marshal_VOID__STRING_UINT,
+					  G_TYPE_NONE, 2,
+					  G_TYPE_STRING,
+					  G_TYPE_UINT);
+}
+
+void
+nm_system_config_hal_manager_reinit_dbus (NMSystemConfigHalManager *manager,
+                                          DBusGConnection *g_connection)
+{
+	init_dbus (manager, g_connection);
+}
+
+void
+nm_system_config_hal_manager_deinit_dbus (NMSystemConfigHalManager *manager)
+{
+	cleanup_dbus (manager);
+}
+
+typedef struct {
+	NMDeviceType devtype;
+	GSList **list;
+} GetDeviceInfo;
+
+static void
+add_devices_of_type (gpointer key, gpointer data, gpointer user_data)
+{
+	GetDeviceInfo *info = (GetDeviceInfo *) user_data;
+
+	if (GPOINTER_TO_UINT (data) == info->devtype)
+		*(info->list) = g_slist_append (*(info->list), g_strdup (key));
+}
+
+GSList *
+nm_system_config_hal_manager_get_devices_of_type (NMSystemConfigHalManager *manager,
+                                                  NMDeviceType devtype)
+{
+	NMSystemConfigHalManagerPrivate *priv;
+	GetDeviceInfo info;
+	GSList *list = NULL;
+
+	g_return_val_if_fail (NM_IS_SYSTEM_CONFIG_HAL_MANAGER (manager), NULL);
+	g_return_val_if_fail (devtype <= NUM_DEVICE_TYPES, NULL);
+
+	priv = NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager);
+	info.devtype = devtype;
+	info.list = &list;
+	g_hash_table_foreach (priv->devices, (GHFunc) add_devices_of_type, &info);
+
+	return list;
+}
+
+DBusGProxy *
+nm_system_config_hal_manager_get_hal_proxy (NMSystemConfigHalManager *manager)
+{
+	g_return_val_if_fail (NM_IS_SYSTEM_CONFIG_HAL_MANAGER (manager), NULL);
+
+	return NM_SYSTEM_CONFIG_HAL_MANAGER_GET_PRIVATE (manager)->proxy;
+}
+

Added: trunk/system-settings/src/nm-system-config-hal-manager.h
==============================================================================
--- (empty file)
+++ trunk/system-settings/src/nm-system-config-hal-manager.h	Tue Apr  8 02:36:39 2008
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 Dan Williams
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef NM_SYSTEM_CONFIG_HAL_MANAGER_H
+#define NM_SYSTEM_CONFIG_HAL_MANAGER_H
+
+#include <glib/gtypes.h>
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+#include "NetworkManager.h"
+
+#define NM_TYPE_SYSTEM_CONFIG_HAL_MANAGER            (nm_system_config_hal_manager_get_type ())
+#define NM_SYSTEM_CONFIG_HAL_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SYSTEM_CONFIG_HAL_MANAGER, NMSystemConfigHalManager))
+#define NM_SYSTEM_CONFIG_HAL_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SYSTEM_CONFIG_HAL_MANAGER, NMSystemConfigHalManagerClass))
+#define NM_IS_SYSTEM_CONFIG_HAL_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SYSTEM_CONFIG_HAL_MANAGER))
+#define NM_IS_SYSTEM_CONFIG_HAL_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SYSTEM_CONFIG_HAL_MANAGER))
+#define NM_SYSTEM_CONFIG_HAL_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SYSTEM_CONFIG_HAL_MANAGER, NMSystemConfigHalManagerClass))
+
+typedef struct {
+	GObject parent;
+} NMSystemConfigHalManager;
+
+typedef struct {
+	GObjectClass parent;
+
+	/* Signals */
+	void (*device_added) (NMSystemConfigHalManager *manager, const char *udi, NMDeviceType type);
+	void (*device_removed) (NMSystemConfigHalManager *manager, const char *udi, NMDeviceType type);
+} NMSystemConfigHalManagerClass;
+
+GType nm_system_config_hal_manager_get_type (void);
+
+/* Returned list is allocated and must be freed by caller */
+GSList *nm_system_config_hal_manager_get_devices_of_type (NMSystemConfigHalManager *manager, NMDeviceType devtype);
+
+DBusGProxy *nm_system_config_hal_manager_get_hal_proxy (NMSystemConfigHalManager *manager);
+
+#endif /* NM_SYSTEM_CONFIG_HAL_MANAGER_H */

Modified: trunk/system-settings/src/nm-system-config-interface.c
==============================================================================
--- trunk/system-settings/src/nm-system-config-interface.c	(original)
+++ trunk/system-settings/src/nm-system-config-interface.c	Tue Apr  8 02:36:39 2008
@@ -76,6 +76,14 @@
 				  G_TYPE_NONE, 1,
 				  G_TYPE_OBJECT);
 
+	g_signal_new ("unmanaged-devices-changed",
+				  iface_type,
+				  G_SIGNAL_RUN_FIRST,
+				  G_STRUCT_OFFSET (NMSystemConfigInterface, unmanaged_devices_changed),
+				  NULL, NULL,
+				  g_cclosure_marshal_VOID__VOID,
+				  G_TYPE_NONE, 0);
+
 	initialized = TRUE;
 }
 
@@ -110,12 +118,13 @@
 }
 
 void
-nm_system_config_interface_init (NMSystemConfigInterface *config)
+nm_system_config_interface_init (NMSystemConfigInterface *config,
+                                 NMSystemConfigHalManager *hal_manager)
 {
 	g_return_if_fail (config != NULL);
 
 	if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->init)
-		NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->init (config);
+		NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->init (config, hal_manager);
 }
 
 GSList *
@@ -142,3 +151,13 @@
 	return NULL;
 }
 
+GSList *
+nm_system_config_interface_get_unmanaged_devices (NMSystemConfigInterface *config)
+{
+	g_return_val_if_fail (config != NULL, NULL);
+
+	if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_unmanaged_devices)
+		return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->get_unmanaged_devices (config);
+	return NULL;
+}
+

Modified: trunk/system-settings/src/nm-system-config-interface.h
==============================================================================
--- trunk/system-settings/src/nm-system-config-interface.h	(original)
+++ trunk/system-settings/src/nm-system-config-interface.h	Tue Apr  8 02:36:39 2008
@@ -26,10 +26,12 @@
 #include <glib-object.h>
 #include <nm-connection.h>
 
+#include "nm-system-config-hal-manager.h"
+
 G_BEGIN_DECLS
 
 #define PLUGIN_PRINT(pname, fmt, args...) \
-	{ g_print ("   " pname ": " fmt "\n", ##args); }
+	{ g_message ("   " pname ": " fmt, ##args); }
 
 #define PLUGIN_WARN(pname, fmt, args...) \
 	{ g_warning ("   " pname ": " fmt, ##args); }
@@ -72,7 +74,7 @@
 	GTypeInterface g_iface;
 
 	/* Called when the plugin is loaded to initialize it */
-	void     (*init) (NMSystemConfigInterface *config);
+	void     (*init) (NMSystemConfigInterface *config, NMSystemConfigHalManager *hal_manager);
 
 	/* Returns the plugins currently known list of connections.  The returned
 	 * list is freed by the system settings service.
@@ -90,6 +92,13 @@
 	 */
 	GHashTable * (*get_secrets) (NMSystemConfigInterface *config, NMConnection *connection, NMSetting *setting);
 
+	/*
+	 * Return a list of HAL UDIs of devices which NetworkManager should not
+	 * manage.  Returned list will be freed by the system settings service, and
+	 * each element must be allocated using g_malloc() or its variants.
+	 */
+	GSList * (*get_unmanaged_devices) (NMSystemConfigInterface *config);
+
 	/* Signals */
 
 	/* Emitted when a new connection has been found by the plugin */
@@ -100,11 +109,15 @@
 
 	/* Emitted when any non-secret settings of the connection change */
 	void (*connection_updated) (NMSystemConfigInterface *config, NMConnection *connection);
+
+	/* Emitted when the list of unmanaged devices changes */
+	void (*unmanaged_devices_changed) (NMSystemConfigInterface *config);
 };
 
 GType nm_system_config_interface_get_type (void);
 
-void nm_system_config_interface_init (NMSystemConfigInterface *config);
+void nm_system_config_interface_init (NMSystemConfigInterface *config,
+                                      NMSystemConfigHalManager *hal_manager);
 
 GSList * nm_system_config_interface_get_connections (NMSystemConfigInterface *config);
 
@@ -112,6 +125,8 @@
                                                     NMConnection *connection,
                                                     NMSetting *setting);
 
+GSList *nm_system_config_interface_get_unmanaged_devices (NMSystemConfigInterface *config);
+
 G_END_DECLS
 
 #endif	/* NM_SYSTEM_CONFIG_INTERFACE_H */



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