linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* expose sysfs functions for sharing it
@ 2004-10-19  2:02 Kay Sievers
  2004-10-19  5:05 ` Greg KH
  0 siblings, 1 reply; 2+ messages in thread
From: Kay Sievers @ 2004-10-19  2:02 UTC (permalink / raw)
  To: linux-hotplug

[-- Attachment #1: Type: text/plain, Size: 181 bytes --]

This patch exposes the wait_for_sysfs functions to all possible users,
so we need to maintain only one list of exceptions. The last list is
hereby removed from udev.c.

Thanks,
Kay

[-- Attachment #2: udev-extract-sysfs-01.patch --]
[-- Type: text/plain, Size: 28089 bytes --]

diff -Nru a/Makefile b/Makefile
--- a/Makefile	2004-10-19 03:50:52 +02:00
+++ b/Makefile	2004-10-19 03:50:52 +02:00
@@ -212,6 +212,7 @@
 	udev_config.o	\
 	udev_add.o	\
 	udev_remove.o	\
+	udev_sysfs.o	\
 	udevdb.o	\
 	namedev.o	\
 	namedev_parse.o	\
@@ -224,6 +225,7 @@
 		namedev.h	\
 		udev_version.h	\
 		udevdb.h	\
+		udev_sysfs.h	\
 		klibc_fixups.h	\
 		logging.h	\
 		selinux.h	\
@@ -303,7 +305,7 @@
 	$(QUIET) $(STRIPCMD) $@
 
 $(WAIT): $(WAIT).o $(OBJS) $(HEADERS) $(LIBC)
-	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) $(WAIT).o $(SYSFS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
+	$(QUIET) $(LD) $(LDFLAGS) -o $@ $(CRT0) $(WAIT).o udev_sysfs.o udev_lib.o udev_config.o $(SYSFS) $(LIB_OBJS) $(ARCH_LIB_OBJS)
 	$(QUIET) $(STRIPCMD) $@
 
 #.c.o:
diff -Nru a/udev.c b/udev.c
--- a/udev.c	2004-10-19 03:50:52 +02:00
+++ b/udev.c	2004-10-19 03:50:52 +02:00
@@ -33,6 +33,7 @@
 #include "libsysfs/sysfs/libsysfs.h"
 #include "udev.h"
 #include "udev_lib.h"
+#include "udev_sysfs.h"
 #include "udev_version.h"
 #include "logging.h"
 #include "namedev.h"
@@ -76,35 +77,6 @@
 	}
 }
 
-/* list of subsystems we don't care about. not listing such systems here
- * is not critical, but it makes it faster as we don't look for the "dev" file
- */
-static int subsystem_without_dev(const char *subsystem)
-{
-	char *subsystem_blacklist[] = {
-		"scsi_host",
-		"scsi_device",
-		"usb_host",
-		"pci_bus",
-		"pcmcia_socket",
-		"bluetooth",
-		"i2c-adapter",
-		"pci_bus",
-		"ieee1394",
-		"ieee1394_host",
-		"ieee1394_node",
-		NULL
-	};
-	char **subsys;
-
-	for (subsys = subsystem_blacklist; *subsys != NULL; subsys++) {
-		if (strcmp(subsystem, *subsys) == 0)
-			return 1;
-	}
-
-	return 0;
-}
-
 int main(int argc, char *argv[], char *envp[])
 {
 	struct sigaction act;
@@ -151,7 +123,7 @@
 			dbg("no devpath?");
 			goto exit;
 		}
-		dbg("looking at '%s'", udev.devpath);
+		dbg("looking at '%s'", devpath);
 
 		/* we only care about class devices and block stuff */
 		if (!strstr(devpath, "class") && !strstr(devpath, "block")) {
@@ -164,13 +136,14 @@
 			goto exit;
 		}
 
+		udev_set_values(&udev, devpath, subsystem);
+
 		/* skip blacklisted subsystems */
-		if (subsystem_without_dev(subsystem)) {
+		if (udev.type != 'n' && subsystem_expect_no_dev(subsystem)) {
 			dbg("don't care about '%s' devices", subsystem);
 			goto exit;
 		};
 
-		udev_set_values(&udev, devpath, subsystem);
 	}
 
 	/* set signal handlers */
@@ -197,9 +170,6 @@
 	case ADD:
 		dbg("udev add");
 
-		/* init rules */
-		namedev_init();
-
 		/* open the device */
 		snprintf(path, SYSFS_PATH_MAX, "%s%s", sysfs_path, udev.devpath);
 		class_dev = sysfs_open_class_device_path(path);
@@ -208,6 +178,9 @@
 			break;
 		}
 		dbg("opened class_dev->name='%s'", class_dev->name);
+
+		/* init rules */
+		namedev_init();
 
 		/* name, create node, store in db */
 		retval = udev_add_device(&udev, class_dev);
diff -Nru a/udev_sysfs.c b/udev_sysfs.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/udev_sysfs.c	2004-10-19 03:50:52 +02:00
@@ -0,0 +1,387 @@
+/*
+ * udev_sysfs.c  - sysfs linux kernel specific knowledge
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ *	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 version 2 of the License.
+ * 
+ *	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.,
+ *	675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "logging.h"
+#include "udev_version.h"
+#include "udev_sysfs.h"
+#include "libsysfs/sysfs/libsysfs.h"
+
+/* list of subsystem specific files
+ * NULL if there is no file to wait for
+ */
+static struct subsystem_file {
+	char *subsystem;
+	char *file;
+} subsystem_files[] = {
+	{ .subsystem = "net",		.file = "ifindex" },
+	{ .subsystem = "scsi_host",	.file = "unique_id" },
+	{ .subsystem = "scsi_device",	.file = NULL },
+	{ .subsystem = "pcmcia_socket",	.file = "card_type" },
+	{ .subsystem = "usb_host",	.file = NULL },
+	{ .subsystem = "bluetooth",	.file = "address" },
+	{ .subsystem = "firmware",	.file = "data" },
+	{ .subsystem = "i2c-adapter",	.file = NULL },
+	{ .subsystem = "pci_bus",	.file = NULL },
+	{ .subsystem = "ieee1394",	.file = NULL },
+	{ .subsystem = "ieee1394_host",	.file = NULL },
+	{ .subsystem = "ieee1394_node",	.file = NULL },
+	{ NULL, NULL }
+};
+
+int subsystem_expect_no_dev(const char *subsystem)
+{
+	struct subsystem_file *file;
+
+	for (file = subsystem_files; file->subsystem != NULL; file++)
+		if (strcmp(subsystem, file->subsystem) == 0)
+			return 1;
+
+	return 0;
+}
+
+/* get subsystem specific files, returns "dev" if no other found */
+static char *get_subsystem_specific_file(const char *subsystem)
+{
+	struct subsystem_file *file;
+
+	/* look if we want to look for another file instead of "dev" */
+	for (file = subsystem_files; file->subsystem != NULL; file++)
+		if (strcmp(subsystem, file->subsystem) == 0)
+			return file->file;
+
+	return "dev";
+}
+
+/* wait for class pecific file to show up */
+static int wait_for_class_device_attributes(struct sysfs_class_device *class_dev,
+					    const char **error)
+{
+	const char *file;
+	char filename[SYSFS_PATH_MAX];
+	int loop;
+
+	file = get_subsystem_specific_file(class_dev->classname);
+	if (file == NULL) {
+		dbg("class '%s' has no file to wait for", class_dev->classname);
+		return 0;
+	}
+
+	strcpy(filename, class_dev->path);
+	strcat(filename, "/");
+	strcat(filename, file);
+	dbg("looking at class '%s' for specific file '%s' with full name %s", class_dev->classname, file, filename);
+
+	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
+	while (--loop) {
+		struct stat stats;
+
+		if (stat(class_dev->path, &stats) == -1) {
+			dbg("'%s' now disappeared (probably remove has beaten us)", class_dev->path);
+			return -ENODEV;
+		}
+
+		if (stat(filename, &stats) == 0) {
+			dbg("class '%s' specific file '%s' found", class_dev->classname, file);
+			return 0;
+		}
+
+		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
+	}
+
+	dbg("error: getting class '%s' specific file '%s'", class_dev->classname, file);
+	if (error)
+		*error = "class specific file unavailable";
+	return -ENOENT;
+}
+
+/* check if we need to wait for a physical device */
+static int class_device_expect_no_device_link(struct sysfs_class_device *class_dev)
+{
+	/* list of devices without a "device" symlink to the physical device
+	 * if device is set to NULL, no devices in that subsystem has a link */
+	static struct class_device {
+		char *subsystem;
+		char *device;
+	} class_device[] = {
+		{ .subsystem = "block",		.device = "double" },
+		{ .subsystem = "block",		.device = "nb" },
+		{ .subsystem = "block",		.device = "ram" },
+		{ .subsystem = "block",		.device = "loop" },
+		{ .subsystem = "block",		.device = "fd" },
+		{ .subsystem = "block",		.device = "md" },
+		{ .subsystem = "block",		.device = "dos_cd" },
+		{ .subsystem = "block",		.device = "rflash" },
+		{ .subsystem = "block",		.device = "rom" },
+		{ .subsystem = "block",		.device = "rrom" },
+		{ .subsystem = "block",		.device = "flash" },
+		{ .subsystem = "block",		.device = "msd" },
+		{ .subsystem = "block",		.device = "sbpcd" },
+		{ .subsystem = "block",		.device = "pcd" },
+		{ .subsystem = "block",		.device = "pf" },
+		{ .subsystem = "block",		.device = "scd" },
+		{ .subsystem = "block",		.device = "ubd" },
+		{ .subsystem = "block",		.device = "dm-" },
+		{ .subsystem = "input",		.device = "event" },
+		{ .subsystem = "input",		.device = "mice" },
+		{ .subsystem = "input",		.device = "mouse" },
+		{ .subsystem = "input",		.device = "ts" },
+		{ .subsystem = "vc",		.device = NULL },
+		{ .subsystem = "tty",		.device = NULL },
+		{ .subsystem = "cpuid",		.device = "cpu" },
+		{ .subsystem = "graphics",	.device = "fb" },
+		{ .subsystem = "mem",		.device = NULL },
+		{ .subsystem = "misc",		.device = NULL },
+		{ .subsystem = "msr",		.device = NULL },
+		{ .subsystem = "netlink",	.device = NULL },
+		{ .subsystem = "net",		.device = "sit" },
+		{ .subsystem = "net",		.device = "lo" },
+		{ .subsystem = "net",		.device = "tap" },
+		{ .subsystem = "net",		.device = "ipsec" },
+		{ .subsystem = "net",		.device = "dummy" },
+		{ .subsystem = "net",		.device = "irda" },
+		{ .subsystem = "net",		.device = "ppp" },
+		{ .subsystem = "ppp",		.device = NULL },
+		{ .subsystem = "sound",		.device = NULL },
+		{ .subsystem = "printer",	.device = "lp" },
+		{ .subsystem = "nvidia",	.device = NULL },
+		{ .subsystem = "video4linux",	.device = "vbi" },
+		{ .subsystem = "lirc",		.device = NULL },
+		{ .subsystem = "firmware",	.device = NULL },
+		{ .subsystem = "drm",		.device = NULL },
+		{ .subsystem = "pci_bus",	.device = NULL },
+		{ .subsystem = "ieee1394",	.device = NULL },
+		{ .subsystem = "ieee1394_host",	.device = NULL },
+		{ .subsystem = "ieee1394_node",	.device = NULL },
+		{ .subsystem = "raw",		.device = NULL },
+		{ NULL, NULL }
+	};
+	struct class_device *classdevice;
+	int len;
+
+	for (classdevice = class_device; classdevice->subsystem != NULL; classdevice++) {
+		if (strcmp(class_dev->classname, classdevice->subsystem) == 0) {
+			/* see if no device in this class is expected to have a device-link */
+			if (classdevice->device == NULL)
+				return 1;
+
+			len = strlen(classdevice->device);
+
+			/* see if device name matches */
+			if (strncmp(class_dev->name, classdevice->device, len) != 0)
+				continue;
+
+			/* exact name match */
+			if (strlen(class_dev->name) == len)
+				return 1;
+
+			/* name match with instance number */
+			if (isdigit(class_dev->name[len]))
+				return 1;
+		}
+	}
+
+	return 0;
+}
+
+/* skip waiting for the bus */
+static int class_device_expect_no_bus(struct sysfs_class_device *class_dev)
+{
+	static char *devices_without_bus[] = {
+		"scsi_host",
+		"i2c-adapter",
+		NULL
+	};
+	char **device;
+
+	for (device = devices_without_bus; *device != NULL; device++) {
+		int len = strlen(*device);
+
+		if (strncmp(class_dev->classname, *device, len) == 0)
+			return 1;
+	}
+
+	return 0;
+}
+
+/* wait for the bus and for a bus specific file to show up */
+int wait_for_bus_device(struct sysfs_device *devices_dev,
+			const char **error)
+{
+	static struct bus_file {
+		char *bus;
+		char *file;
+	} bus_files[] = {
+		{ .bus = "scsi",	.file = "vendor" },
+		{ .bus = "usb",		.file = "idVendor" },
+		{ .bus = "usb",		.file = "iInterface" },
+		{ .bus = "usb",		.file = "bNumEndpoints" },
+		{ .bus = "usb-serial",	.file = "detach_state" },
+		{ .bus = "ide",		.file = "detach_state" },
+		{ .bus = "pci",		.file = "vendor" },
+		{ .bus = "platform",	.file = "detach_state" },
+		{ .bus = "i2c",		.file = "detach_state" },
+		{ NULL }
+	};
+	struct bus_file *busfile;
+	int loop;
+
+	/* wait for the bus device link to the devices device */
+	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
+	while (--loop) {
+		if (sysfs_get_device_bus(devices_dev) == 0)
+			break;
+
+		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
+	}
+	if (loop == 0) {
+		dbg("error: getting bus device link");
+		if (error)
+			*error = "no bus device link";
+		return -1;
+	}
+	dbg("bus device link found for bus '%s'", devices_dev->bus);
+
+	/* wait for a bus specific file to show up */
+	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
+	while (--loop) {
+		int found = 0;
+
+		for (busfile = bus_files; busfile->bus != NULL; busfile++) {
+			if (strcmp(devices_dev->bus, busfile->bus) == 0) {
+				found = 1;
+				dbg("looking at bus '%s' for specific file '%s'", devices_dev->bus, busfile->file);
+				if (sysfs_get_device_attr(devices_dev, busfile->file) != NULL) {
+					dbg("bus '%s' specific file '%s' found", devices_dev->bus, busfile->file);
+					return 0;
+				}
+			}
+		}
+		if (found == 0) {
+			if (error)
+				*error = "unknown bus";
+			info("error: unknown bus, please report to "
+			     "<linux-hotplug-devel@lists.sourceforge.net> '%s'", devices_dev->bus);
+			return -1;
+		}
+		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
+	}
+
+	dbg("error: getting bus '%s' specific file '%s'", devices_dev->bus, busfile->file);
+	if (error)
+		*error = "bus specific file unavailable";
+	return -1;
+}
+
+
+struct sysfs_class_device *open_class_device_wait(const char *path)
+{
+	struct sysfs_class_device *class_dev;
+	int loop;
+
+	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
+	while (--loop) {
+		class_dev = sysfs_open_class_device_path(path);
+		if (class_dev)
+			break;
+
+		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
+	}
+
+	return (class_dev);
+}
+
+int wait_for_class_device(struct sysfs_class_device *class_dev,
+			  const char **error)
+{
+	struct sysfs_class_device *class_dev_parent;
+	struct sysfs_device *devices_dev = NULL;
+	int loop;
+
+	if (wait_for_class_device_attributes(class_dev, error) != 0)
+		return -ENOENT;
+
+	/* skip devices without devices-link */
+	if (class_device_expect_no_device_link(class_dev)) {
+		dbg("no device symlink expected for '%s', ", class_dev->name);
+		return -ENODEV;
+	}
+
+	/* the symlink may be on the parent device */
+	class_dev_parent = sysfs_get_classdev_parent(class_dev);
+	if (class_dev_parent)
+		dbg("looking at parent device for device link '%s'", class_dev_parent->path);
+
+	/* wait for the symlink to the devices device */
+	dbg("waiting for symlink to devices device");
+	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
+	while (--loop) {
+		if (class_dev_parent)
+			devices_dev = sysfs_get_classdev_device(class_dev_parent);
+		else
+			devices_dev = sysfs_get_classdev_device(class_dev);
+
+		if (devices_dev)
+			break;
+
+		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
+	}
+	if (!devices_dev) {
+		dbg(" error: no devices device symlink found");
+		if (error)
+			*error = "no device symlink";
+		return -ENODEV;
+	}
+	dbg("device symlink found pointing to '%s'", devices_dev->path);
+
+	/* wait for the bus value */
+	if (class_device_expect_no_bus(class_dev)) {
+		dbg("no bus device expected for '%s', ", class_dev->classname);
+		return 0;
+	} else {
+		return wait_for_bus_device(devices_dev, error);
+	}
+}
+
+struct sysfs_device *open_devices_device_wait(const char *path)
+{
+	struct sysfs_device *devices_dev;
+	int loop;
+
+	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
+	while (--loop) {
+		devices_dev = sysfs_open_device_path(path);
+		if (devices_dev)
+			break;
+
+		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
+	}
+
+	return(devices_dev);
+}
diff -Nru a/udev_sysfs.h b/udev_sysfs.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/udev_sysfs.h	2004-10-19 03:50:52 +02:00
@@ -0,0 +1,36 @@
+/*
+ * udev_sysfs.h
+ *
+ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
+ * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
+ *
+ *	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 version 2 of the License.
+ * 
+ *	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.,
+ *	675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef _UDEV_SYSFS_H_
+#define _UDEV_SYSFS_H_
+
+#include "libsysfs/sysfs/libsysfs.h"
+
+#define WAIT_MAX_SECONDS		5
+#define WAIT_LOOP_PER_SECOND		20
+
+extern int subsystem_expect_no_dev(const char *subsystem);
+extern int wait_for_bus_device(struct sysfs_device *devices_dev, const char **error);
+extern int wait_for_class_device(struct sysfs_class_device *class_dev, const char **error);
+extern struct sysfs_class_device *open_class_device_wait(const char *path);
+extern struct sysfs_device *open_devices_device_wait(const char *path);
+
+#endif /* _UDEV_SYSFS_H_ */
diff -Nru a/wait_for_sysfs.c b/wait_for_sysfs.c
--- a/wait_for_sysfs.c	2004-10-19 03:50:52 +02:00
+++ b/wait_for_sysfs.c	2004-10-19 03:50:52 +02:00
@@ -34,12 +34,9 @@
 
 #include "logging.h"
 #include "udev_version.h"
+#include "udev_sysfs.h"
 #include "libsysfs/sysfs/libsysfs.h"
 
-#ifndef FILENAME_MAX
-#define FILENAME_MAX	4096
-#endif
-
 #ifdef LOG
 unsigned char logname[LOGNAME_SIZE];
 void log_message(int level, const char *format, ...)
@@ -52,336 +49,6 @@
 }
 #endif
 
-#define WAIT_MAX_SECONDS		5
-#define WAIT_LOOP_PER_SECOND		20
-
-/* wait for specific file to show up, normally the "dev"-file */
-static int wait_for_class_device_attributes(struct sysfs_class_device *class_dev,
-					    const char **error)
-{
-	static struct class_file {
-		char *subsystem;
-		char *file;
-	} class_files[] = {
-		{ .subsystem = "net",		.file = "ifindex" },
-		{ .subsystem = "scsi_host",	.file = "unique_id" },
-		{ .subsystem = "scsi_device",	.file = NULL },
-		{ .subsystem = "pcmcia_socket",	.file = "card_type" },
-		{ .subsystem = "usb_host",	.file = NULL },
-		{ .subsystem = "bluetooth",	.file = "address" },
-		{ .subsystem = "firmware",	.file = "data" },
-		{ .subsystem = "i2c-adapter",	.file = NULL },
-		{ .subsystem = "pci_bus",	.file = NULL },
-		{ .subsystem = "ieee1394",	.file = NULL },
-		{ .subsystem = "ieee1394_host",	.file = NULL },
-		{ .subsystem = "ieee1394_node",	.file = NULL },
-		{ NULL, NULL }
-	};
-	struct class_file *classfile;
-	char *file = "dev";
-	char filename[FILENAME_MAX];
-	int loop;
-
-	/* look if we want to look for another file instead of "dev" */
-	for (classfile = class_files; classfile->subsystem != NULL; classfile++) {
-		if (strcmp(class_dev->classname, classfile->subsystem) == 0) {
-			if (classfile->file == NULL) {
-				dbg("class '%s' has no file to wait for", class_dev->classname);
-				return 0;
-			}
-			file = classfile->file;
-			break;
-		}
-	}
-
-	strcpy(filename, class_dev->path);
-	strcat(filename, "/");
-	strcat(filename, file);
-	dbg("looking at class '%s' for specific file '%s' with full name %s", class_dev->classname, class_dev->path, filename);
-
-	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
-	while (--loop) {
-		struct stat stats;
-
-		if (stat(class_dev->path, &stats) == -1) {
-			dbg("'%s' now disappeared (probably remove has beaten us)", class_dev->path);
-			return -ENODEV;
-		}
-
-		if (stat(filename, &stats) == 0) {
-			dbg("class '%s' specific file '%s' found", class_dev->classname, file);
-			return 0;
-		}
-
-		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
-	}
-
-	dbg("error: getting class '%s' specific file '%s'", class_dev->classname, file);
-	*error = "class specific file unavailable";
-	return -ENOENT;
-}
-
-/* check if we need to wait for a physical device */
-static int class_device_expect_no_device_link(struct sysfs_class_device *class_dev)
-{
-	/* list of devices without a "device" symlink to the physical device
-	 * if device is set to NULL, no devices in that subsystem has a link */
-	static struct class_device {
-		char *subsystem;
-		char *device;
-	} class_device[] = {
-		{ .subsystem = "block",		.device = "double" },
-		{ .subsystem = "block",		.device = "nb" },
-		{ .subsystem = "block",		.device = "ram" },
-		{ .subsystem = "block",		.device = "loop" },
-		{ .subsystem = "block",		.device = "fd" },
-		{ .subsystem = "block",		.device = "md" },
-		{ .subsystem = "block",		.device = "dos_cd" },
-		{ .subsystem = "block",		.device = "rflash" },
-		{ .subsystem = "block",		.device = "rom" },
-		{ .subsystem = "block",		.device = "rrom" },
-		{ .subsystem = "block",		.device = "flash" },
-		{ .subsystem = "block",		.device = "msd" },
-		{ .subsystem = "block",		.device = "sbpcd" },
-		{ .subsystem = "block",		.device = "pcd" },
-		{ .subsystem = "block",		.device = "pf" },
-		{ .subsystem = "block",		.device = "scd" },
-		{ .subsystem = "block",		.device = "ubd" },
-		{ .subsystem = "block",		.device = "dm-" },
-		{ .subsystem = "input",		.device = "event" },
-		{ .subsystem = "input",		.device = "mice" },
-		{ .subsystem = "input",		.device = "mouse" },
-		{ .subsystem = "input",		.device = "ts" },
-		{ .subsystem = "vc",		.device = NULL },
-		{ .subsystem = "tty",		.device = NULL },
-		{ .subsystem = "cpuid",		.device = "cpu" },
-		{ .subsystem = "graphics",	.device = "fb" },
-		{ .subsystem = "mem",		.device = NULL },
-		{ .subsystem = "misc",		.device = NULL },
-		{ .subsystem = "msr",		.device = NULL },
-		{ .subsystem = "netlink",	.device = NULL },
-		{ .subsystem = "net",		.device = "sit" },
-		{ .subsystem = "net",		.device = "lo" },
-		{ .subsystem = "net",		.device = "tap" },
-		{ .subsystem = "net",		.device = "ipsec" },
-		{ .subsystem = "net",		.device = "dummy" },
-		{ .subsystem = "net",		.device = "irda" },
-		{ .subsystem = "net",		.device = "ppp" },
-		{ .subsystem = "ppp",		.device = NULL },
-		{ .subsystem = "sound",		.device = NULL },
-		{ .subsystem = "printer",	.device = "lp" },
-		{ .subsystem = "nvidia",	.device = NULL },
-		{ .subsystem = "video4linux",	.device = "vbi" },
-		{ .subsystem = "lirc",		.device = NULL },
-		{ .subsystem = "firmware",	.device = NULL },
-		{ .subsystem = "drm",		.device = NULL },
-		{ .subsystem = "pci_bus",	.device = NULL },
-		{ .subsystem = "ieee1394",	.device = NULL },
-		{ .subsystem = "ieee1394_host",	.device = NULL },
-		{ .subsystem = "ieee1394_node",	.device = NULL },
-		{ .subsystem = "raw",		.device = NULL },
-		{ NULL, NULL }
-	};
-	struct class_device *classdevice;
-	int len;
-
-	for (classdevice = class_device; classdevice->subsystem != NULL; classdevice++) {
-		if (strcmp(class_dev->classname, classdevice->subsystem) == 0) {
-			/* see if no device in this class is expected to have a device-link */
-			if (classdevice->device == NULL)
-				return 1;
-
-			len = strlen(classdevice->device);
-
-			/* see if device name matches */
-			if (strncmp(class_dev->name, classdevice->device, len) != 0)
-				continue;
-
-			/* exact name match */
-			if (strlen(class_dev->name) == len)
-				return 1;
-
-			/* name match with instance number */
-			if (isdigit(class_dev->name[len]))
-				return 1;
-		}
-	}
-
-	return 0;
-}
-
-/* skip waiting for the bus */
-static int class_device_expect_no_bus(struct sysfs_class_device *class_dev)
-{
-	static char *devices_without_bus[] = {
-		"scsi_host",
-		"i2c-adapter",
-		NULL
-	};
-	char **device;
-
-	for (device = devices_without_bus; *device != NULL; device++) {
-		int len = strlen(*device);
-
-		if (strncmp(class_dev->classname, *device, len) == 0)
-			return 1;
-	}
-
-	return 0;
-}
-
-/* wait for the bus and for a bus specific file to show up */
-static int wait_for_bus_device(struct sysfs_device *devices_dev,
-			       const char **error)
-{
-	static struct bus_file {
-		char *bus;
-		char *file;
-	} bus_files[] = {
-		{ .bus = "scsi",	.file = "vendor" },
-		{ .bus = "usb",		.file = "idVendor" },
-		{ .bus = "usb",		.file = "iInterface" },
-		{ .bus = "usb",		.file = "bNumEndpoints" },
-		{ .bus = "usb-serial",	.file = "detach_state" },
-		{ .bus = "ide",		.file = "detach_state" },
-		{ .bus = "pci",		.file = "vendor" },
-		{ .bus = "platform",	.file = "detach_state" },
-		{ .bus = "i2c",		.file = "detach_state" },
-		{ NULL }
-	};
-	struct bus_file *busfile;
-	int loop;
-
-	/* wait for the bus device link to the devices device */
-	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
-	while (--loop) {
-		if (sysfs_get_device_bus(devices_dev) == 0)
-			break;
-
-		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
-	}
-	if (loop == 0) {
-		dbg("error: getting bus device link");
-		*error = "no bus device link";
-		return -1;
-	}
-	dbg("bus device link found for bus '%s'", devices_dev->bus);
-
-	/* wait for a bus specific file to show up */
-	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
-	while (--loop) {
-		int found = 0;
-
-		for (busfile = bus_files; busfile->bus != NULL; busfile++) {
-			if (strcmp(devices_dev->bus, busfile->bus) == 0) {
-				found = 1;
-				dbg("looking at bus '%s' for specific file '%s'", devices_dev->bus, busfile->file);
-				if (sysfs_get_device_attr(devices_dev, busfile->file) != NULL) {
-					dbg("bus '%s' specific file '%s' found", devices_dev->bus, busfile->file);
-					return 0;
-				}
-			}
-		}
-		if (found == 0) {
-			*error = "unknown bus";
-			info("error: unknown bus, please report to "
-			     "<linux-hotplug-devel@lists.sourceforge.net> '%s'", devices_dev->bus);
-			return -1;
-		}
-		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
-	}
-
-	dbg("error: getting bus '%s' specific file '%s'", devices_dev->bus, busfile->file);
-	*error = "bus specific file unavailable";
-	return -1;
-}
-
-
-static struct sysfs_class_device *open_class_device(const char *path)
-{
-	struct sysfs_class_device *class_dev;
-	int loop;
-
-	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
-	while (--loop) {
-		class_dev = sysfs_open_class_device_path(path);
-		if (class_dev)
-			break;
-
-		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
-	}
-
-	return (class_dev);
-}
-
-static int wait_for_class_device(struct sysfs_class_device *class_dev,
-				 const char **error)
-{
-	struct sysfs_class_device *class_dev_parent;
-	struct sysfs_device *devices_dev = NULL;
-	int loop;
-
-	if (wait_for_class_device_attributes(class_dev, error) != 0)
-		return -ENOENT;
-
-	/* skip devices without devices-link */
-	if (class_device_expect_no_device_link(class_dev)) {
-		dbg("no device symlink expected for '%s', ", class_dev->name);
-		return -ENODEV;
-	}
-
-	/* the symlink may be on the parent device */
-	class_dev_parent = sysfs_get_classdev_parent(class_dev);
-	if (class_dev_parent)
-		dbg("looking at parent device for device link '%s'", class_dev_parent->path);
-
-	/* wait for the symlink to the devices device */
-	dbg("waiting for symlink to devices device");
-	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
-	while (--loop) {
-		if (class_dev_parent)
-			devices_dev = sysfs_get_classdev_device(class_dev_parent);
-		else
-			devices_dev = sysfs_get_classdev_device(class_dev);
-
-		if (devices_dev)
-			break;
-
-		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
-	}
-	if (!devices_dev) {
-		dbg(" error: no devices device symlink found");
-		*error = "no device symlink";
-		return -ENODEV;
-	}
-	dbg("device symlink found pointing to '%s'", devices_dev->path);
-
-	/* wait for the bus value */
-	if (class_device_expect_no_bus(class_dev)) {
-		dbg("no bus device expected for '%s', ", class_dev->classname);
-		return 0;
-	} else {
-		return wait_for_bus_device(devices_dev, error);
-	}
-}
-
-static struct sysfs_device *open_devices_device(const char *path)
-{
-	struct sysfs_device *devices_dev;
-	int loop;
-
-	loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND;
-	while (--loop) {
-		devices_dev = sysfs_open_device_path(path);
-		if (devices_dev)
-			break;
-
-		usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND);
-	}
-
-	return(devices_dev);
-}
-
 int main(int argc, char *argv[], char *envp[])
 {
 	const char *devpath = "";
@@ -433,7 +100,7 @@
 		filename[SYSFS_PATH_MAX-1] = '\0';
 
 		/* open the class device we are called for */
-		class_dev = open_class_device(filename);
+		class_dev = open_class_device_wait(filename);
 		if (!class_dev) {
 			dbg("error: class device unavailable (probably remove has beaten us)");
 			goto exit;
@@ -450,7 +117,7 @@
 		filename[SYSFS_PATH_MAX-1] = '\0';
 
 		/* open the path we are called for */
-		devices_dev = open_devices_device(filename);
+		devices_dev = open_devices_device_wait(filename);
 		if (!devices_dev) {
 			dbg("error: devices device unavailable (probably remove has beaten us)");
 			goto exit;

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: expose sysfs functions for sharing it
  2004-10-19  2:02 expose sysfs functions for sharing it Kay Sievers
@ 2004-10-19  5:05 ` Greg KH
  0 siblings, 0 replies; 2+ messages in thread
From: Greg KH @ 2004-10-19  5:05 UTC (permalink / raw)
  To: linux-hotplug

On Tue, Oct 19, 2004 at 04:02:29AM +0200, Kay Sievers wrote:
> This patch exposes the wait_for_sysfs functions to all possible users,
> so we need to maintain only one list of exceptions. The last list is
> hereby removed from udev.c.

applied, thanks.

greg k-h


-------------------------------------------------------
This SF.net email is sponsored by: IT Product Guide on ITManagersJournal
Use IT products in your business? Tell us what you think of them. Give us
Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more
http://productguide.itmanagersjournal.com/guidepromo.tmpl
_______________________________________________
Linux-hotplug-devel mailing list  http://linux-hotplug.sourceforge.net
Linux-hotplug-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2004-10-19  5:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-10-19  2:02 expose sysfs functions for sharing it Kay Sievers
2004-10-19  5:05 ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).