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