prepare for class devices showing up in /sys/devices

Kay Sievers kay.sievers at vrfy.org
Tue Jul 4 06:48:30 PDT 2006


With kernel 2.6.18, it's possible for class devices to show up in the
/sys/devices/ tree.

This just prepares HAL to detect the correct device type. In the end,
we should definitely merge the classdev and physdev types in HAL to a
single device, cause it doesn't really makes sense to distinguish between
the both.

Thanks,
Kay
-------------- next part --------------
Index: ChangeLog
===================================================================
RCS file: /cvs/hal/hal/ChangeLog,v
retrieving revision 1.925
diff -u -p -r1.925 ChangeLog
--- ChangeLog	3 Jul 2006 16:42:01 -0000	1.925
+++ ChangeLog	4 Jul 2006 13:39:48 -0000
@@ -1,3 +1,8 @@
+2006-07-04  Kay Sievers  <kay.sievers at vrfy.org>
+
+	* hald/linux2/hotplug.c: (hotplug_event_begin_sysfs): Prepare for
+	new class devices showing up in /sys/devices instead of /sys/class.
+
 2006-07-03  Danny Kukawka  <danny.kukawka at web.de>
 
 	* libhal-storage/libhal-storage.c: (libhal_drive_free),
Index: hald/linux2/hotplug.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/hotplug.c,v
retrieving revision 1.20
diff -u -p -r1.20 hotplug.c
--- hald/linux2/hotplug.c	23 Jan 2006 12:15:50 -0000	1.20
+++ hald/linux2/hotplug.c	4 Jul 2006 13:39:48 -0000
@@ -130,26 +130,87 @@ out:
 static void
 hotplug_event_begin_sysfs (HotplugEvent *hotplug_event)
 {
-	static char sys_devices_path[HAL_PATH_MAX];
-	static char sys_class_path[HAL_PATH_MAX];
-	static char sys_block_path[HAL_PATH_MAX];
-	static gsize sys_devices_path_len;
-	static gsize sys_class_path_len;
-	static gsize sys_block_path_len;
-
-	sys_devices_path_len = g_snprintf (sys_devices_path, HAL_PATH_MAX, "%s/devices", get_hal_sysfs_path ());
-	sys_class_path_len   = g_snprintf (sys_class_path, HAL_PATH_MAX, "%s/class", get_hal_sysfs_path ());
-	sys_block_path_len   = g_snprintf (sys_block_path, HAL_PATH_MAX, "%s/block", get_hal_sysfs_path ());
+	HalDevice *d;
+	char subsystem[HAL_PATH_MAX];
+	gchar *subsystem_target;
 
-	if (hotplug_event->action == HOTPLUG_ACTION_ADD && hal_device_store_match_key_value_string (hald_get_gdl (),
+	d = hal_device_store_match_key_value_string (hald_get_gdl (),
 						     "linux.sysfs_path",
-						     hotplug_event->sysfs.sysfs_path)) {
+						     hotplug_event->sysfs.sysfs_path);
+
+	/* FIXME: we should reprobe the device instead of skipping the event */
+	if (d != NULL && hotplug_event->action == HOTPLUG_ACTION_ADD) {
 		HAL_ERROR (("devpath %s already present in the store, ignore event", hotplug_event->sysfs.sysfs_path));
 		hotplug_event_end ((void *) hotplug_event);
 		return;
 	}
 
-	if (strncmp (hotplug_event->sysfs.sysfs_path, sys_devices_path, sys_devices_path_len) == 0) {
+	/* get device type from already known device object */
+	if (d != NULL) {
+		HotplugEventType type;
+
+		type = hal_device_property_get_int (d, "linux.hotplug_type");
+		if (type == HOTPLUG_EVENT_SYSFS_BUS) {
+			HAL_INFO (("%s is a bus device (store)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BUS;
+		} else if (type == HOTPLUG_EVENT_SYSFS_CLASS) {
+			HAL_INFO (("%s is a class device (store)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_CLASS;
+		} else if (type == HOTPLUG_EVENT_SYSFS_BLOCK) {
+			HAL_INFO (("%s is a block device (store)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
+		}
+	}
+
+	/*
+	 * determine device type by "subsystem" link (from kernel 2.6.18, class devices
+	 * start to move from /class to /devices and have a "subsystem" link pointing
+	 * back to the "class" or "bus" directory
+	 */
+	if (hotplug_event->type == HOTPLUG_EVENT_SYSFS) {
+		g_snprintf (subsystem, HAL_PATH_MAX, "%s/subsystem", hotplug_event->sysfs.sysfs_path);
+		subsystem_target = g_file_read_link (subsystem, NULL);
+		if (subsystem_target != NULL) {
+			if (strstr(subsystem_target, "/bus/") != NULL) {
+				HAL_INFO (("%s is a bus device (subsystem)", hotplug_event->sysfs.sysfs_path));
+				hotplug_event->type = HOTPLUG_EVENT_SYSFS_BUS;
+			} else if (strstr(subsystem_target, "/class/") != NULL) {
+				HAL_INFO (("%s is a class device (subsystem)", hotplug_event->sysfs.sysfs_path));
+				hotplug_event->type = HOTPLUG_EVENT_SYSFS_CLASS;
+			} else if (strstr(subsystem_target, "/block") != NULL) {
+				HAL_INFO (("%s is a block device (subsystem)", hotplug_event->sysfs.sysfs_path));
+				hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
+			}
+			g_free (subsystem_target);
+		}
+	}
+
+	/* older kernels get the device type from the devpath */
+	if (hotplug_event->type == HOTPLUG_EVENT_SYSFS) {
+		char sys_devices_path[HAL_PATH_MAX];
+		char sys_class_path[HAL_PATH_MAX];
+		char sys_block_path[HAL_PATH_MAX];
+		gsize sys_devices_path_len;
+		gsize sys_class_path_len;
+		gsize sys_block_path_len;
+
+		sys_devices_path_len = g_snprintf (sys_devices_path, HAL_PATH_MAX, "%s/devices", get_hal_sysfs_path ());
+		sys_class_path_len   = g_snprintf (sys_class_path, HAL_PATH_MAX, "%s/class", get_hal_sysfs_path ());
+		sys_block_path_len   = g_snprintf (sys_block_path, HAL_PATH_MAX, "%s/block", get_hal_sysfs_path ());
+
+		if (strncmp (hotplug_event->sysfs.sysfs_path, sys_devices_path, sys_devices_path_len) == 0) {
+			HAL_INFO (("%s is a bus device (devpath)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BUS;
+		} else if (strncmp (hotplug_event->sysfs.sysfs_path, sys_class_path, sys_class_path_len) == 0) {
+			HAL_INFO (("%s is a class device (devpath)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_CLASS;
+		} else if (strncmp (hotplug_event->sysfs.sysfs_path, sys_block_path, sys_block_path_len) == 0) {
+			HAL_INFO (("%s is a block device (devpath)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
+		}
+	}
+
+	if (hotplug_event->type == HOTPLUG_EVENT_SYSFS_BUS) {
 		if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
 			HalDevice *parent;
 			parent = hal_util_find_closest_ancestor (hotplug_event->sysfs.sysfs_path);
@@ -162,11 +223,11 @@ hotplug_event_begin_sysfs (HotplugEvent 
 							    hotplug_event->sysfs.sysfs_path, 
 							    (void *) hotplug_event);
 		}
-	} else if (strncmp (hotplug_event->sysfs.sysfs_path, sys_class_path, sys_class_path_len) == 0) {
+	} else if (hotplug_event->type == HOTPLUG_EVENT_SYSFS_CLASS) {
 		if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
 			gchar *target;
 			HalDevice *physdev;
-			char physdevpath[256];
+			char physdevpath[HAL_PATH_MAX];
 			gchar *sysfs_path_in_devices;
 
 			sysfs_path_in_devices = NULL;
@@ -175,7 +236,7 @@ hotplug_event_begin_sysfs (HotplugEvent 
 			 * so if index doesn't match, go ahead and find a new sysfs path
 			 */
 			fixup_net_device_for_renaming (hotplug_event);
-			
+
 			g_snprintf (physdevpath, HAL_PATH_MAX, "%s/device", hotplug_event->sysfs.sysfs_path);
 			if (((target = g_file_read_link (physdevpath, NULL)) != NULL)) {
 				gchar *normalized_target;
@@ -196,9 +257,7 @@ hotplug_event_begin_sysfs (HotplugEvent 
 					/* go up one directory */
 					if (!hal_util_path_ascend (normalized_target))
 						break;
-
 				} while (physdev == NULL);
-
 				g_free (normalized_target);
 			} else {
 				physdev = NULL;
@@ -218,23 +277,27 @@ hotplug_event_begin_sysfs (HotplugEvent 
 							     hotplug_event->sysfs.sysfs_path,
 							     (void *) hotplug_event);
 		}
-	} else if (strncmp (hotplug_event->sysfs.sysfs_path, sys_block_path, sys_block_path_len) == 0) {
-		gchar *parent_path;
+	} else if (hotplug_event->type == HOTPLUG_EVENT_SYSFS_BLOCK) {
 		gboolean is_partition;
+		size_t len;
 
-		parent_path = hal_util_get_parent_path (hotplug_event->sysfs.sysfs_path);
-		is_partition = (strcmp (parent_path, sys_block_path) != 0);
+		len = strlen(hotplug_event->sysfs.sysfs_path);
+		is_partition = isdigit(hotplug_event->sysfs.sysfs_path[len - 1]);
 
 		if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
 			HalDevice *parent;
 
 			if (is_partition) {
+				gchar *parent_path;
+				parent_path = hal_util_get_parent_path (hotplug_event->sysfs.sysfs_path);
+
 				parent = hal_device_store_match_key_value_string (hald_get_gdl (),
 										  "linux.sysfs_path_device",
 										  parent_path);
+				g_free (parent_path);
 			} else {
 				gchar *target;
-				char physdevpath[256];
+				char physdevpath[HAL_PATH_MAX];
 
 				g_snprintf (physdevpath, HAL_PATH_MAX, "%s/device", hotplug_event->sysfs.sysfs_path);
 				if (((target = g_file_read_link (physdevpath, NULL)) != NULL)) {
@@ -261,8 +324,6 @@ hotplug_event_begin_sysfs (HotplugEvent 
 							     is_partition,
 							     (void *) hotplug_event);
 		}
-
-		g_free (parent_path);
 	} else {
 		/* just ignore this hotplug event */
 		hotplug_event_end ((void *) hotplug_event);


More information about the hal mailing list