hal/hald/linux2 classdev.c, 1.3, 1.4 classdev.h, 1.1, 1.2 coldplug.c, 1.1, 1.2 hotplug.c, 1.1, 1.2 ids.c, 1.2, 1.3 physdev.c, 1.2, 1.3 util.c, 1.1, 1.2 util.h, 1.1, 1.2

David Zeuthen david at freedesktop.org
Sun Jan 23 15:12:01 PST 2005


Update of /cvs/hal/hal/hald/linux2
In directory gabe:/tmp/cvs-serv21396/hald/linux2

Modified Files:
	classdev.c classdev.h coldplug.c hotplug.c ids.c physdev.c 
	util.c util.h 
Log Message:
2005-01-23  David Zeuthen  <davidz at redhat.com>

	* hald/linux2/util.h: Add prototypes for hal_util_set_driver () and
	hal_util_path_ascend ().

	* hald/linux2/util.c (hal_util_set_driver): New function
	(hal_util_path_ascend): New function

	* hald/linux2/physdev.c: Set both linux.sysfs_path and 
	linux.sysfs_path_device. The former is the real sysfs path for both
	class and bus devices while the latter always is a location in 
	/sys/devices; incidently the latter may not always exists. The former
	is used for remove events while the latter is used for determing
	child/parent relationships.
	(scsi_add): New function
	(scsi_compute_udi): New function

	* hald/linux2/ids.c (ids_find_pnp): Use strcasecmp instead of strcmp

	* hald/linux2/hotplug.c (hotplug_event_begin): Cope with the fact
	that there may be holes in /sys/devices; e.g. look at the
	target0:0:0:0 stuff. So, for a class device ascend all the way up
	until we find a hal device object that can be our parent.

	* hald/linux2/coldplug.c: Euwh, too much simplification here; we
	need to insert class devs between bus devs in the coldplug queue
	as e.g. scsi_host is a class dev but sits between bus devs.

	* hald/linux2/classdev.h: Make hotplug_event_begin_add_classdev take
	the sysfs path of the corresponding device in /sys/devices (which
	may not be a physical device, e.g. class scsi_host)

	* hald/linux2/classdev.c (net_add): New function
	(net_compute_udi): New function
	(scsi_host_add): New function
	(scsi_host_compute_udi): New function



Index: classdev.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/classdev.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- classdev.c	22 Jan 2005 20:13:42 -0000	1.3
+++ classdev.c	23 Jan 2005 23:11:59 -0000	1.4
@@ -28,6 +28,8 @@
 #endif
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 #include <mntent.h>
 #include <errno.h>
@@ -37,6 +39,21 @@
 #include <sys/un.h>
 #include <sys/utsname.h>
 #include <unistd.h>
+#include <ctype.h>
+#include <unistd.h>
+
+#include <limits.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <net/if_arp.h> /* for ARPHRD_... */
+#include <sys/socket.h>
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <net/if.h>
 
 #include <glib.h>
 #include <dbus/dbus.h>
@@ -59,12 +76,12 @@
 /*--------------------------------------------------------------------------------------------------------------*/
 
 static HalDevice *
-input_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev)
+input_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
 {
 	HalDevice *d;
 
 	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 	if (physdev != NULL) {
 		hal_device_property_set_string (d, "input.physical_device", physdev->udi);
 		hal_device_property_set_string (d, "info.parent", physdev->udi);
@@ -102,7 +119,8 @@
 /*--------------------------------------------------------------------------------------------------------------*/
 
 static HalDevice *
-bluetooth_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev)
+bluetooth_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, 
+	       const gchar *sysfs_path_in_devices)
 {
 	HalDevice *d;
 
@@ -113,7 +131,7 @@
 	}
 
 	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 	hal_device_property_set_string (d, "info.parent", physdev->udi);
 
 	hal_device_property_set_string (d, "info.category", "bluetooth_hci");
@@ -122,6 +140,8 @@
 	hal_device_property_set_string (d, "bluetooth_hci.physical_device", physdev->udi);
 	hal_util_set_string_from_file (d, "bluetooth_hci.interface_name", sysfs_path, "name");
 
+	hal_device_property_set_string (d, "info.product", "Bluetooth Host Controller Interface");
+
 out:
 	return d;
 }
@@ -141,6 +161,196 @@
 
 /*--------------------------------------------------------------------------------------------------------------*/
 
+static HalDevice *
+net_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+	const gchar *ifname;
+	guint media_type;
+	gint flags;
+
+	d = NULL;
+
+	if (physdev == NULL) {
+		goto out;
+	}
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+
+	if (!hal_util_set_driver (d, "net.linux.driver", sysfs_path)) {
+		hal_device_store_remove (hald_get_tdl (), d);
+		d = NULL;
+		goto out;
+	}
+
+	hal_device_property_set_string (d, "info.category", "net");
+	hal_device_add_capability (d, "net");
+
+	hal_device_property_set_string (d, "net.physical_device", physdev->udi);
+
+	ifname = hal_util_get_last_element (sysfs_path);
+	hal_device_property_set_string (d, "net.interface", ifname);
+
+	hal_util_set_string_from_file (d, "net.address", sysfs_path, "address");
+	hal_util_set_int_from_file (d, "net.linux.ifindex", sysfs_path, "ifindex", 10);
+
+	hal_util_set_int_from_file (d, "net.arp_proto_hw_id", sysfs_path, "type", 10);
+	media_type = hal_device_property_get_int (d, "net.arp_proto_hw_id");
+
+	if (media_type == ARPHRD_ETHER) {
+		FILE *f;
+		gboolean is_wireless;
+		const char *addr;
+
+		is_wireless = FALSE;
+
+		f = fopen ("/proc/net/wireless", "ro");
+		if (f != NULL) {
+			unsigned int i;
+			unsigned int ifname_len;
+			char buf[128];
+
+			ifname_len = strlen (ifname);
+
+			do {
+				if (fgets (buf, sizeof (buf), f) == NULL)
+					break;
+
+				for (i=0; i < sizeof (buf); i++) {
+					if (isspace (buf[i]))
+						continue;
+					else
+						break;
+				}
+
+				if (strncmp (ifname, buf + i, ifname_len) == 0) {
+					is_wireless = TRUE;
+					break;
+				}
+
+			} while (TRUE);
+			fclose (f);
+		}
+
+		if (is_wireless) {
+		/* Check to see if this interface supports wireless extensions */
+		/*
+		snprintf (wireless_path, SYSFS_PATH_MAX, "%s/wireless", sysfs_path);
+		if (stat (wireless_path, &statbuf) == 0) {
+		*/
+			hal_device_property_set_string (d, "info.category", "net.80211");
+			hal_device_add_capability (d, "net.80211");
+		} else {
+			gint have_link;
+
+			hal_device_property_set_string (d, "info.category", "net.80203");
+			hal_device_add_capability (d, "net.80203");
+
+			hal_util_get_int_from_file (sysfs_path, "carrier", &have_link, 10);
+			hal_device_property_set_bool (d, "net.80203.link", have_link != 0);
+			if (have_link != 0) {
+				HAL_INFO (("FIXME: no speed file in sysfs; assuming link speed is 100Mbps"));
+				hal_device_property_set_uint64 (d, "net.80203.rate", 100 * 1000 * 1000);
+			}
+		}
+
+		addr = hal_device_property_get_string (d, "net.address");
+		if (addr != NULL) {
+			unsigned int a5, a4, a3, a2, a1, a0;
+			
+			if (sscanf (addr, "%x:%x:%x:%x:%x:%x",
+				    &a5, &a4, &a3, &a2, &a1, &a0) == 6) {
+				dbus_uint64_t mac_address;
+				
+				mac_address = 
+					((dbus_uint64_t)a5<<40) |
+					((dbus_uint64_t)a4<<32) | 
+					((dbus_uint64_t)a3<<24) | 
+					((dbus_uint64_t)a2<<16) | 
+					((dbus_uint64_t)a1<< 8) | 
+					((dbus_uint64_t)a0<< 0);
+				
+				hal_device_property_set_uint64 (d, is_wireless ? "net.80211.mac_address" : 
+								"net.80203.mac_address",
+								mac_address);
+			}
+		}
+	}
+
+	hal_util_get_int_from_file (sysfs_path, "flags", &flags, 16);
+	hal_device_property_set_bool (d, "net.interface_up", flags & IFF_UP);
+
+	hal_device_property_set_string (d, "info.product", "Networking Interface");
+
+
+out:
+	return d;
+}
+
+static gboolean
+net_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/net_%s",
+			      hal_device_property_get_string (d, "net.address"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+scsi_host_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+	gint host_num;
+	const gchar *last_elem;
+
+	d = NULL;
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL) {
+		goto out;
+	}
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path_in_devices);
+	
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+
+	hal_device_property_set_string (d, "info.category", "scsi_host");
+	hal_device_add_capability (d, "scsi_host");
+
+	hal_device_property_set_string (d, "info.product", "SCSI Host Adapter");
+
+	last_elem = hal_util_get_last_element (sysfs_path);
+	sscanf (last_elem, "host%d", &host_num);
+	hal_device_property_set_int (d, "scsi_host.host", host_num);
+
+out:
+	return d;
+}
+
+static gboolean
+scsi_host_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_scsi_host",
+			      hal_device_property_get_string (d, "info.parent"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
 static gboolean
 classdev_remove (HalDevice *d)
 {
@@ -159,7 +369,7 @@
 struct ClassDevHandler_s
 {
 	const gchar *subsystem;
-	HalDevice *(*add) (const gchar *sysfs_path, const gchar *device_file, HalDevice *parent);
+	HalDevice *(*add) (const gchar *sysfs_path, const gchar *device_file, HalDevice *parent, const gchar *sysfs_path_in_devices);
 	const gchar *prober;
 	gboolean (*post_probing) (HalDevice *d);
 	gboolean (*compute_udi) (HalDevice *d);
@@ -188,9 +398,31 @@
 	.remove       = classdev_remove
 };
 
+static ClassDevHandler classdev_handler_net = 
+{ 
+	.subsystem    = "net",
+	.add          = net_add,
+	.prober       = NULL,
+	.post_probing = NULL,
+	.compute_udi  = net_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_scsi_host = 
+{ 
+	.subsystem    = "scsi_host",
+	.add          = scsi_host_add,
+	.prober       = NULL,
+	.post_probing = NULL,
+	.compute_udi  = scsi_host_compute_udi,
+	.remove       = classdev_remove
+};
+
 static ClassDevHandler *classdev_handlers[] = {
 	&classdev_handler_input,
 	&classdev_handler_bluetooth,
+	&classdev_handler_net,
+	&classdev_handler_scsi_host,
 	NULL
 };
 
@@ -249,7 +481,7 @@
 
 void
 hotplug_event_begin_add_classdev (const gchar *subsystem, const gchar *sysfs_path, const gchar *device_file, 
-				  HalDevice *physdev, void *end_token)
+				  HalDevice *physdev, const gchar *sysfs_path_in_devices, void *end_token)
 {
 	guint i;
 
@@ -263,7 +495,7 @@
 			HalDevice *d;
 
 			/* attempt to add the device */
-			d = handler->add (sysfs_path, device_file, physdev);
+			d = handler->add (sysfs_path, device_file, physdev, sysfs_path_in_devices);
 			if (d == NULL) {
 				/* didn't find anything - thus, ignore this hotplug event */
 				hotplug_event_end (end_token);
@@ -302,7 +534,7 @@
 
 	HAL_INFO (("class_rem: subsys=%s sysfs_path=%s", subsystem, sysfs_path));
 
-	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path_device", sysfs_path);
+	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", sysfs_path);
 	if (d == NULL) {
 		HAL_WARNING (("Error removing device"));
 	} else {

Index: classdev.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/classdev.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- classdev.h	18 Jan 2005 19:48:13 -0000	1.1
+++ classdev.h	23 Jan 2005 23:11:59 -0000	1.2
@@ -28,7 +28,7 @@
 
 #include <glib.h>
 
-void hotplug_event_begin_add_classdev (const gchar *subsystem, const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, void *end_token);
+void hotplug_event_begin_add_classdev (const gchar *subsystem, const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices, void *end_token);
 
 void hotplug_event_begin_remove_classdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token);
 

Index: coldplug.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/coldplug.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- coldplug.c	18 Jan 2005 19:48:13 -0000	1.1
+++ coldplug.c	23 Jan 2005 23:11:59 -0000	1.2
@@ -51,10 +51,12 @@
 #include "hotplug.h"
 
 
-static void 
-coldplug_compute_visit_device (const gchar *path, GHashTable *sysfs_to_bus_map);
+static void
+coldplug_compute_visit_device (const gchar *path, 
+			       GHashTable *sysfs_to_bus_map, 
+			       GHashTable *sysfs_to_class_in_devices_map);
 
-/*#define HAL_COLDPLUG_VERBOSE*/
+#define HAL_COLDPLUG_VERBOSE
 
 /** This function serves one major purpose : build an ordered list of
  *  pairs (sysfs path, subsystem) to process when starting up:
@@ -63,7 +65,7 @@
  *  the tree; e.g. bus-device A is not processed before bus-device B
  *  if B is a parent of A connection-wise.
  *
- *  After all bus-devices are added to the list, then all block are
+ *  After all bus-devices are added to the list, then all block devices are
  *  processed in the order they appear.
  *
  *  Finally, all class devices are added to the list.
@@ -78,9 +80,11 @@
 	GError *err = NULL;
 	gchar path[HAL_PATH_MAX];
 	gchar path1[HAL_PATH_MAX];
+	gchar path2[HAL_PATH_MAX];
 	const gchar *f;
 	const gchar *f1;
 	const gchar *f2;
+	GSList *li;
 
 	/** Mapping from sysfs path to subsystem for bus devices. This is consulted
 	 *  when traversing /sys/devices
@@ -102,6 +106,22 @@
 	 */
 	GHashTable *sysfs_to_bus_map = NULL;
 
+        /** Mapping from sysfs path in /sys/devices to the pairs (sysfs class path, classname)
+	 *  for class devices; note that more than one class device might map to a physical device
+	 *
+	 * Example:
+	 *
+	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-1/1-1:1.0/host7  -> (/sys/class/scsi_host/host7, scsi_host)
+	 * /sys/devices/platform/i8042/serio0/serio2 -> (/sys/class/input/event2, input, /sys/class/input/mouse1, input)
+	 */
+	GHashTable *sysfs_to_class_in_devices_map = NULL;
+
+	/* Class devices without device links; string list; example
+	 *
+	 * (/sys/class/input/mice, mouse, /sys/class/mem/null, mem, ...)
+	 */
+	GSList *sysfs_other_class_dev = NULL;
+
 	/* build bus map */
 	sysfs_to_bus_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 	g_snprintf (path, HAL_PATH_MAX, "%s/bus", hal_sysfs_path);
@@ -159,90 +179,107 @@
 	}
 	g_dir_close (dir);
 
-	/* Now traverse /sys/devices and consult the map we've just
-	 * built; this includes adding a) bus devices; and b) class
-	 * devices that sit in /sys/devices */
-	g_snprintf (path, HAL_PATH_MAX, "%s/devices", hal_sysfs_path);
+	/* build class map and class device map */
+	sysfs_to_class_in_devices_map = g_hash_table_new (g_str_hash, g_str_equal);
+	g_snprintf (path, HAL_PATH_MAX, "%s/class" , hal_sysfs_path);
 	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
-		HAL_ERROR (("Unable to open %/devices: %s", hal_sysfs_path, err->message));
-		g_error_free (err);
+		HAL_ERROR (("Unable to open %/class: %s", hal_sysfs_path, err->message));
 		goto error;
 	}
 	while ((f = g_dir_read_name (dir)) != NULL) {
 		GDir *dir1;
 
-		g_snprintf (path, HAL_PATH_MAX, "%s/devices/%s", hal_sysfs_path, f);
+		g_snprintf (path, HAL_PATH_MAX, "%s/class/%s" , hal_sysfs_path, f);
 		if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
-			HAL_ERROR (("Unable to open %/devices/%s: %s", hal_sysfs_path, f, err->message));
+			HAL_ERROR (("Unable to open %/class/%s: %s", hal_sysfs_path, f, err->message));
 			g_error_free (err);
 			goto error;
 		}
 		while ((f1 = g_dir_read_name (dir1)) != NULL) {
+			gchar *target;
+			gchar *normalized_target;
 
-			g_snprintf (path, HAL_PATH_MAX, "%s/devices/%s/%s", hal_sysfs_path, f, f1);
-			coldplug_compute_visit_device (path, sysfs_to_bus_map);
+			g_snprintf (path1, HAL_PATH_MAX, "%s/class/%s/%s/device", hal_sysfs_path, f, f1);
+			/* Accept net devices without device links too, they may be coldplugged PCMCIA devices */
+			if (((target = g_file_read_link (path1, NULL)) == NULL)) {
+				/* no device link */
+				g_snprintf (path1, HAL_PATH_MAX, "%s/class/%s/%s", hal_sysfs_path, f, f1);
+				sysfs_other_class_dev = g_slist_append (sysfs_other_class_dev, g_strdup (path1));
+				sysfs_other_class_dev = g_slist_append (sysfs_other_class_dev, g_strdup (f));
+			} else {
+				GSList *classdev_strings;
 
+				g_snprintf (path2, HAL_PATH_MAX, "%s/class/%s/%s", hal_sysfs_path, f, f1);
+				if (target) {
+					normalized_target = hal_util_get_normalized_path (path2, target);
+					g_free (target);
+				}
+
+				classdev_strings = g_hash_table_lookup (sysfs_to_class_in_devices_map,
+									normalized_target);
+
+				classdev_strings = g_slist_append (classdev_strings, g_strdup (path2));
+				classdev_strings = g_slist_append (classdev_strings, g_strdup (f));
+				g_hash_table_replace (sysfs_to_class_in_devices_map,
+						      normalized_target, classdev_strings);
+			}				
 		}
 		g_dir_close (dir1);
 	}
 	g_dir_close (dir);
 
-	g_hash_table_destroy (sysfs_to_bus_map);
-
-
-	/* add class devices */
-	g_snprintf (path, HAL_PATH_MAX, "%s/class", hal_sysfs_path);
+	/* Now traverse /sys/devices and consult the map we've just
+	 * built; this includes adding a) bus devices; and b) class
+	 * devices that sit in /sys/devices */
+	g_snprintf (path, HAL_PATH_MAX, "%s/devices", hal_sysfs_path);
 	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
-		HAL_ERROR (("Unable to open %/class: %s", hal_sysfs_path, err->message));
+		HAL_ERROR (("Unable to open %/devices: %s", hal_sysfs_path, err->message));
+		g_error_free (err);
 		goto error;
 	}
 	while ((f = g_dir_read_name (dir)) != NULL) {
 		GDir *dir1;
 
-		g_snprintf (path, HAL_PATH_MAX, "%s/class/%s", hal_sysfs_path, f);
+		g_snprintf (path, HAL_PATH_MAX, "%s/devices/%s", hal_sysfs_path, f);
 		if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
-			HAL_ERROR (("Unable to open %/class/%s: %s", hal_sysfs_path, f, err->message));
+			HAL_ERROR (("Unable to open %/devices/%s: %s", hal_sysfs_path, f, err->message));
 			g_error_free (err);
 			goto error;
 		}
 		while ((f1 = g_dir_read_name (dir1)) != NULL) {
-			HotplugEvent *hotplug_event;
-			gchar *target;
-			gchar *normalized_target;
-
-			g_snprintf (path, HAL_PATH_MAX, "%s/class/%s/%s", hal_sysfs_path, f, f1);
-#ifdef HAL_COLDPLUG_VERBOSE
-			printf ("class: %s (%s)\n", path, f);
-#endif
-
-			g_snprintf (path1, HAL_PATH_MAX, "%s/class/%s/%s/device", hal_sysfs_path, f, f1);
-			if (((target = g_file_read_link (path1, NULL)) != NULL)) {
-				normalized_target = hal_util_get_normalized_path (path1, target);
-				g_free (target);
-			} else {
-				normalized_target = NULL;
-			}
 
+			g_snprintf (path, HAL_PATH_MAX, "%s/devices/%s/%s", hal_sysfs_path, f, f1);
+			coldplug_compute_visit_device (path, sysfs_to_bus_map, sysfs_to_class_in_devices_map);
+		}
+		g_dir_close (dir1);
+	}
+	g_dir_close (dir);
 
-			hotplug_event = g_new0 (HotplugEvent, 1);
-			hotplug_event->is_add = TRUE;
-			g_strlcpy (hotplug_event->subsystem, f, sizeof (hotplug_event->subsystem));
-			g_strlcpy (hotplug_event->sysfs_path, path, sizeof (hotplug_event->sysfs_path));
-			hal_util_get_device_file (path, hotplug_event->device_file, sizeof (hotplug_event->device_file));
-			if (normalized_target != NULL)
-				g_strlcpy (hotplug_event->wait_for_sysfs_path, normalized_target, sizeof (hotplug_event->wait_for_sysfs_path));
-			else
-				hotplug_event->wait_for_sysfs_path[0] = '\0';
-			hotplug_event->net_ifindex = -1;
+	g_hash_table_destroy (sysfs_to_bus_map);
+	g_hash_table_destroy (sysfs_to_class_in_devices_map);
 
-			hotplug_event_enqueue (hotplug_event);
+	/* we are guaranteed, per construction, that the len of this list is even */
+	for (li = sysfs_other_class_dev; li != NULL; li = g_slist_next (g_slist_next (li))) {
+		gchar *sysfs_path;
+		gchar *subsystem;
+		HotplugEvent *hotplug_event;
 
-			g_free (normalized_target);
+		sysfs_path = (gchar *) li->data;
+		subsystem = (gchar *) li->next->data;
 
-		}
-		g_dir_close (dir1);
+#ifdef HAL_COLDPLUG_VERBOSE
+		printf ("class: %s (%s) (no device link)\n", sysfs_path, subsystem);
+#endif
+		hotplug_event = g_new0 (HotplugEvent, 1);
+		hotplug_event->is_add = TRUE;
+		g_strlcpy (hotplug_event->subsystem, subsystem, sizeof (hotplug_event->subsystem));
+		g_strlcpy (hotplug_event->sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs_path));
+		hal_util_get_device_file (sysfs_path, hotplug_event->device_file, sizeof (hotplug_event->device_file));
+		hotplug_event->net_ifindex = -1;
+		
+		hotplug_event_enqueue (hotplug_event);
 	}
-	g_dir_close (dir);
+	g_slist_free (sysfs_other_class_dev);
 
 	/* add block devices */
 	g_snprintf (path, HAL_PATH_MAX, "%s/block", hal_sysfs_path);
@@ -319,12 +356,17 @@
 }
 
 static void
-coldplug_compute_visit_device (const gchar *path, GHashTable *sysfs_to_bus_map)
+coldplug_compute_visit_device (const gchar *path, 
+			       GHashTable *sysfs_to_bus_map, 
+			       GHashTable *sysfs_to_class_in_devices_map)
 {
 	gchar *bus;
 	GError *err;
 	GDir *dir;
 	const gchar *f;
+	/*HStringPair *pair;*/
+	GSList *class_devs;
+	GSList *i;
 
 	bus = g_hash_table_lookup (sysfs_to_bus_map, path);
 	if (bus != NULL) {
@@ -350,6 +392,33 @@
 		hotplug_event_enqueue (hotplug_event);
 	}
 
+	/* we are guaranteed, per construction, that the len of this list is even */
+	class_devs = g_hash_table_lookup (sysfs_to_class_in_devices_map, path);
+	for (i = class_devs; i != NULL; i = g_slist_next (g_slist_next (i))) {
+		gchar *sysfs_path;
+		gchar *subsystem;
+		HotplugEvent *hotplug_event;
+
+		sysfs_path = (gchar *) i->data;
+		subsystem = (gchar *) i->next->data;
+
+#ifdef HAL_COLDPLUG_VERBOSE
+		printf ("class: %s (%s) (%s)\n", path, subsystem, sysfs_path);
+#endif
+		hotplug_event = g_new0 (HotplugEvent, 1);
+		hotplug_event->is_add = TRUE;
+		g_strlcpy (hotplug_event->subsystem, subsystem, sizeof (hotplug_event->subsystem));
+		g_strlcpy (hotplug_event->sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs_path));
+		hal_util_get_device_file (sysfs_path, hotplug_event->device_file, sizeof (hotplug_event->device_file));
+		if (path != NULL)
+			g_strlcpy (hotplug_event->wait_for_sysfs_path, path, sizeof (hotplug_event->wait_for_sysfs_path));
+		else
+			hotplug_event->wait_for_sysfs_path[0] = '\0';
+		hotplug_event->net_ifindex = -1;
+		
+		hotplug_event_enqueue (hotplug_event);
+	}
+
 	/* visit children; dont follow symlinks though.. */
 	err = NULL;
 	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
@@ -367,7 +436,9 @@
 
 			if (!S_ISLNK (statbuf.st_mode)) {
 				/* recursion fun */
-				coldplug_compute_visit_device (path_child, sysfs_to_bus_map);
+				coldplug_compute_visit_device (path_child, 
+							       sysfs_to_bus_map, 
+							       sysfs_to_class_in_devices_map);
 			}
 		}
 	}

Index: hotplug.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/hotplug.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- hotplug.c	18 Jan 2005 19:48:13 -0000	1.1
+++ hotplug.c	23 Jan 2005 23:11:59 -0000	1.2
@@ -71,6 +71,7 @@
 	hotplug_event_process_queue ();
 }
 
+
 static void
 hotplug_event_begin (HotplugEvent *hotplug_event)
 {
@@ -106,6 +107,9 @@
 			gchar *target;
 			HalDevice *physdev;
 			char physdevpath[256];
+			gchar *sysfs_path_in_devices;
+
+			sysfs_path_in_devices = NULL;
 
 			/* TODO: fixup net devices by looking at ifindex */
 			
@@ -116,9 +120,22 @@
 				normalized_target = hal_util_get_normalized_path (hotplug_event->sysfs_path, target);
 				g_free (target);
 
-				physdev = hal_device_store_match_key_value_string (hald_get_gdl (), 
-										   "linux.sysfs_path_device", 
-										   normalized_target);
+				sysfs_path_in_devices = g_strdup (normalized_target);
+
+				/* there may be ''holes'' in /sys/devices so try hard to find the closest match */
+				do {
+					physdev = hal_device_store_match_key_value_string (hald_get_gdl (), 
+											   "linux.sysfs_path_device", 
+											   normalized_target);
+					if (physdev != NULL)
+						break;
+
+					/* go up one directory */
+					if (!hal_util_path_ascend (normalized_target))
+						break;
+
+				} while (physdev == NULL);
+
 				g_free (normalized_target);
 			} else {
 				physdev = NULL;
@@ -128,7 +145,11 @@
 							  hotplug_event->sysfs_path,
 							  hotplug_event->device_file,
 							  physdev,
+							  sysfs_path_in_devices,
 							  (void *) hotplug_event);
+
+			g_free (sysfs_path_in_devices);
+
 		} else {
 			hotplug_event_begin_remove_classdev (hotplug_event->subsystem,
 							     hotplug_event->sysfs_path,

Index: ids.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/ids.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- ids.c	22 Jan 2005 20:13:42 -0000	1.2
+++ ids.c	23 Jan 2005 23:11:59 -0000	1.3
@@ -882,7 +882,7 @@
 
 	/* OK, so someone should optimize this lookup - send me patches */
 	for (i = 0; pnp_ids_list[2*i] != NULL; i++) {
-		if (strcmp (pnp_id, pnp_ids_list[2*i]) == 0) {
+		if (strcasecmp (pnp_id, pnp_ids_list[2*i]) == 0) {
 			*pnp_description = pnp_ids_list[2*i + 1];
 			return;
 		}

Index: physdev.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/physdev.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- physdev.c	22 Jan 2005 20:13:42 -0000	1.2
+++ physdev.c	23 Jan 2005 23:11:59 -0000	1.3
@@ -69,6 +69,7 @@
 	gint device_class;
 
 	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
 	hal_device_property_set_string (d, "info.bus", "pci");
 	if (parent != NULL) {
@@ -231,6 +232,7 @@
 	const gchar *bus_id;
 
 	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
 	if (parent != NULL) {
 		hal_device_property_set_string (d, "info.parent", parent->udi);
@@ -375,6 +377,7 @@
 	guint host, channel;
 
 	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
 	hal_device_property_set_string (d, "info.bus", "ide");
 	if (parent != NULL) {
@@ -423,6 +426,7 @@
 	HalDevice *d;
 
 	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
 	hal_device_property_set_string (d, "info.bus", "pnp");
 	if (parent != NULL) {
@@ -475,6 +479,7 @@
 	const gchar *bus_id;
 
 	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
 	hal_device_property_set_string (d, "info.bus", "serio");
 	if (parent != NULL) {
@@ -518,6 +523,7 @@
 	guint socket, function;
 
 	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
 	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
 	hal_device_property_set_string (d, "info.bus", "pcmcia");
 	if (parent != NULL) {
@@ -608,6 +614,55 @@
 
 /*--------------------------------------------------------------------------------------------------------------*/
 
+static HalDevice *
+scsi_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+	gint host_num, bus_num, target_num, lun_num;
+
+	if (parent == NULL) {
+		d = NULL;
+		goto out;
+	}
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "scsi");
+	hal_device_property_set_string (d, "info.parent", parent->udi);
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+	sscanf (bus_id, "%d:%d:%d:%d", &host_num, &bus_num, &target_num, &lun_num);
+	hal_device_property_set_int (d, "scsi.host", host_num);
+	hal_device_property_set_int (d, "scsi.bus", bus_num);
+	hal_device_property_set_int (d, "scsi.target", target_num);
+	hal_device_property_set_int (d, "scsi.lun", lun_num);
+
+	/* guestimate product name */
+	hal_device_property_set_string (d, "info.product", "SCSI Device");
+
+out:
+	return d;
+}
+
+static gboolean
+scsi_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_scsi_device_lun%d",
+			      hal_device_property_get_string (d, "info.parent"),
+			      hal_device_property_get_int (d, "scsi.lun"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
 static gboolean
 physdev_remove (HalDevice *d)
 {
@@ -669,6 +724,13 @@
 	.compute_udi = pcmcia_compute_udi,
 	.remove      = physdev_remove
 };
+
+static PhysDevHandler physdev_handler_scsi = { 
+	.subsystem   = "scsi",
+	.add         = scsi_add,
+	.compute_udi = scsi_compute_udi,
+	.remove      = physdev_remove
+};
 	
 
 static PhysDevHandler *phys_handlers[] = {
@@ -678,6 +740,7 @@
 	&physdev_handler_pnp,
 	&physdev_handler_serio,
 	&physdev_handler_pcmcia,
+	&physdev_handler_scsi,
 	NULL
 };
 
@@ -743,7 +806,7 @@
 	HAL_INFO (("phys_rem: subsys=%s sysfs_path=%s", subsystem, sysfs_path));
 
 	d = hal_device_store_match_key_value_string (hald_get_gdl (), 
-						     "linux.sysfs_path_device", 
+						     "linux.sysfs_path", 
 						     sysfs_path);
 	if (d == NULL) {
 		HAL_WARNING (("Couldn't remove device with sysfs path %s - not found", sysfs_path));

Index: util.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/util.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- util.c	18 Jan 2005 19:48:13 -0000	1.1
+++ util.c	23 Jan 2005 23:11:59 -0000	1.2
@@ -222,7 +222,7 @@
 	sysfs_path_len = strlen (sysfs_path);
 	strncpy (sysfs_path_dev_trunc, sysfs_path, HAL_PATH_MAX);
 	strncat (sysfs_path_dev_trunc + sysfs_path_len, "/dev", 4);
-	if (g_stat (sysfs_path_dev_trunc, &statbuf) != 0)
+	if (stat (sysfs_path_dev_trunc, &statbuf) != 0)
 		return FALSE;
 
 	/* get path to udevinfo */
@@ -683,3 +683,40 @@
 	return ret;
 }
 
+gboolean
+hal_util_set_driver (HalDevice *d, const char *property_name, const char *sysfs_path)
+{
+	gboolean ret;
+	gchar driver_path[HAL_PATH_MAX];
+	struct stat statbuf;
+
+	ret = FALSE;
+
+	g_snprintf (driver_path, sizeof (driver_path), "%s/driver", sysfs_path);
+	if (stat (driver_path, &statbuf) == 0) {
+		gchar buf[256];
+		memset (buf, '\0', sizeof (buf));
+		if (readlink (driver_path, buf, sizeof (buf) - 1) > 0) {
+			hal_device_property_set_string (d, property_name, hal_util_get_last_element (buf));
+			ret = TRUE;
+		}
+	}
+
+	return ret;
+}
+
+gboolean
+hal_util_path_ascend (gchar *path)
+{
+	gchar *p;
+
+	if (path == NULL)
+		return FALSE;
+
+	p = strrchr (path, '/');
+	if (p == NULL)
+		return FALSE;
+
+	*p = '\0';
+	return TRUE;
+}

Index: util.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/util.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- util.h	18 Jan 2005 19:48:13 -0000	1.1
+++ util.h	23 Jan 2005 23:11:59 -0000	1.2
@@ -54,6 +54,11 @@
 
 void hal_util_compute_udi (HalDeviceStore *store, gchar *dst, gsize dstsize, const gchar *format, ...);
 
+gboolean hal_util_set_driver (HalDevice *d, const char *property_name, const char *sysfs_path);
+
+gboolean hal_util_path_ascend (gchar *path);
+
+
 typedef void (*HelperTerminatedCB)(HalDevice *d, gboolean timed_out, gint return_code, gpointer data1, gpointer data2);
 
 gboolean helper_invoke (const gchar *path, HalDevice *d, gpointer data1, gpointer data2, HelperTerminatedCB cb, guint timeout);




More information about the hal-commit mailing list