diff options
-rw-r--r-- | udev_lib.c | 24 | ||||
-rw-r--r-- | udev_lib.h | 2 | ||||
-rw-r--r-- | udev_sysfs.c | 63 | ||||
-rw-r--r-- | udev_sysfs.h | 10 | ||||
-rw-r--r-- | wait_for_sysfs.c | 13 |
5 files changed, 77 insertions, 35 deletions
diff --git a/udev_lib.c b/udev_lib.c index 6807f817a1..a3fab9632d 100644 --- a/udev_lib.c +++ b/udev_lib.c @@ -28,6 +28,7 @@ #include <dirent.h> #include <sys/stat.h> #include <sys/mman.h> +#include <sys/utsname.h> #include "udev.h" #include "logging.h" @@ -72,6 +73,29 @@ void udev_set_values(struct udevice *udev, const char* devpath, udev->type = get_device_type(devpath, subsystem); } +int kernel_release_satisfactory(int version, int patchlevel, int sublevel) +{ + static struct utsname uts; + static int kversion = 0; + static int kpatchlevel; + static int ksublevel; + + if (kversion == 0) { + if (uname(&uts) != 0) + return -1; + + if (sscanf (uts.release, "%u.%u.%u", &kversion, &kpatchlevel, &ksublevel) != 3) { + kversion = 0; + return -1; + } + } + + if (kversion >= version && kpatchlevel >= patchlevel && ksublevel >= sublevel) + return 1; + else + return 0; +} + int create_path(const char *path) { char p[NAME_SIZE]; diff --git a/udev_lib.h b/udev_lib.h index 2bc9ba82ab..80dc49cd54 100644 --- a/udev_lib.h +++ b/udev_lib.h @@ -79,12 +79,12 @@ do { \ extern char get_device_type(const char *path, const char *subsystem); extern void udev_set_values(struct udevice *udev, const char* devpath, const char *subsystem, const char* action); +extern int kernel_release_satisfactory(int version, int patchlevel, int sublevel); extern int create_path(const char *path); extern int file_map(const char *filename, char **buf, size_t *bufsize); extern void file_unmap(char *buf, size_t bufsize); extern size_t buf_get_line(char *buf, size_t buflen, size_t cur); extern void no_trailing_slash(char *path); - typedef int (*file_fnct_t)(const char *filename, void *data); extern int call_foreach_file(file_fnct_t fnct, const char *dirname, const char *suffix, void *data); diff --git a/udev_sysfs.c b/udev_sysfs.c index a11c430df0..1953dd7775 100644 --- a/udev_sysfs.c +++ b/udev_sysfs.c @@ -28,14 +28,13 @@ #include <errno.h> #include <sys/stat.h> -#include "logging.h" +#include "libsysfs/sysfs/libsysfs.h" #include "udev_version.h" #include "udev_sysfs.h" -#include "libsysfs/sysfs/libsysfs.h" +#include "udev_lib.h" +#include "logging.h" -/* list of subsystem specific files - * NULL if there is no file to wait for - */ +/* list of subsystem specific files, NULL if there is no file to wait for */ static struct subsystem_file { char *subsystem; char *file; @@ -204,6 +203,13 @@ static int class_device_expect_no_device_link(struct sysfs_class_device *class_d struct class_device *classdevice; int len; + /* the kernel may tell us what to wait for */ + if (kernel_release_satisfactory(2,6,10) > 0) + if (getenv("PHYSDEVPATH") == NULL) { + dbg("the kernel says, that there is no physical device for '%s'", class_dev->path); + return 1; + } + 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 */ @@ -229,7 +235,7 @@ static int class_device_expect_no_device_link(struct sysfs_class_device *class_d return 0; } -/* skip waiting for the bus */ +/* skip waiting for the bus of the devices device */ static int class_device_expect_no_bus(struct sysfs_class_device *class_dev) { static char *devices_without_bus[] = { @@ -250,14 +256,14 @@ static int class_device_expect_no_bus(struct sysfs_class_device *class_dev) 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, +/* wait for a devices device specific file to show up */ +int wait_for_devices_device(struct sysfs_device *devices_dev, const char **error) { - static struct bus_file { + static struct device_file { char *bus; char *file; - } bus_files[] = { + } device_files[] = { { .bus = "scsi", .file = "vendor" }, { .bus = "usb", .file = "idVendor" }, { .bus = "usb", .file = "iInterface" }, @@ -272,9 +278,16 @@ int wait_for_bus_device(struct sysfs_device *devices_dev, { .bus = "ieee1394", .file = "address" }, { NULL, NULL } }; - struct bus_file *busfile; + struct device_file *devicefile; int loop; + /* the kernel may tell us what to wait for */ + if (kernel_release_satisfactory(2,6,10) > 0) + if (getenv("PHYSDEVBUS") == NULL) { + dbg("the kernel says, that there is no bus for '%s'", devices_dev->path); + return 0; + } + /* wait for the bus device link to the devices device */ loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND; while (--loop) { @@ -291,22 +304,22 @@ int wait_for_bus_device(struct sysfs_device *devices_dev, } dbg("bus device link found for bus '%s'", devices_dev->bus); - /* wait for a bus specific file to show up */ + /* wait for a bus device specific file to show up */ loop = WAIT_MAX_SECONDS * WAIT_LOOP_PER_SECOND; while (--loop) { int found_bus_type = 0; - for (busfile = bus_files; busfile->bus != NULL; busfile++) { - if (strcmp(devices_dev->bus, busfile->bus) == 0) { + for (devicefile = device_files; devicefile->bus != NULL; devicefile++) { + if (strcmp(devices_dev->bus, devicefile->bus) == 0) { char filename[SYSFS_PATH_MAX]; struct stat stats; found_bus_type = 1; - snprintf(filename, SYSFS_PATH_MAX-1, "%s/%s", devices_dev->path, busfile->file); - dbg("looking at bus '%s' for specific file '%s'", devices_dev->bus, filename); + snprintf(filename, SYSFS_PATH_MAX-1, "%s/%s", devices_dev->path, devicefile->file); + dbg("looking at bus '%s' device for specific file '%s'", devices_dev->bus, filename); if (stat(filename, &stats) == 0) { - dbg("bus '%s' specific file '%s' found", devices_dev->bus, busfile->file); + dbg("bus '%s' device specific file '%s' found", devices_dev->bus, devicefile->file); return 0; } } @@ -321,14 +334,14 @@ int wait_for_bus_device(struct sysfs_device *devices_dev, usleep(1000 * 1000 / WAIT_LOOP_PER_SECOND); } - dbg("error: getting bus '%s' specific file '%s'", devices_dev->bus, busfile->file); + dbg("error: getting '%s' device specific file '%s'", devices_dev->bus, devicefile->file); if (error) - *error = "bus specific file unavailable"; + *error = "bus device specific file unavailable"; return -1; } -struct sysfs_class_device *open_class_device_wait(const char *path) +struct sysfs_class_device *wait_class_device_open(const char *path) { struct sysfs_class_device *class_dev; int loop; @@ -358,7 +371,7 @@ int wait_for_class_device(struct sysfs_class_device *class_dev, /* 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; + return 0; } /* the symlink may be on the parent device */ @@ -388,16 +401,16 @@ int wait_for_class_device(struct sysfs_class_device *class_dev, } dbg("device symlink found pointing to '%s'", devices_dev->path); - /* wait for the bus value */ + /* wait for the devices device */ 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); } + + return wait_for_devices_device(devices_dev, error); } -struct sysfs_device *open_devices_device_wait(const char *path) +struct sysfs_device *wait_devices_device_open(const char *path) { struct sysfs_device *devices_dev; int loop; diff --git a/udev_sysfs.h b/udev_sysfs.h index 922db1be79..98ff53e11a 100644 --- a/udev_sysfs.h +++ b/udev_sysfs.h @@ -28,9 +28,13 @@ #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); + +/* /sys/class /sys/block devices */ +extern struct sysfs_class_device *wait_class_device_open(const char *path); 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); + +/* /sys/devices devices */ +extern struct sysfs_device *wait_devices_device_open(const char *path); +extern int wait_for_devices_device(struct sysfs_device *devices_dev, const char **error); #endif /* _UDEV_SYSFS_H_ */ diff --git a/wait_for_sysfs.c b/wait_for_sysfs.c index 42b9d383dc..84a25adb97 100644 --- a/wait_for_sysfs.c +++ b/wait_for_sysfs.c @@ -32,10 +32,11 @@ #include <errno.h> #include <sys/stat.h> -#include "logging.h" +#include "libsysfs/sysfs/libsysfs.h" +#include "udev_lib.h" #include "udev_version.h" #include "udev_sysfs.h" -#include "libsysfs/sysfs/libsysfs.h" +#include "logging.h" #ifdef LOG unsigned char logname[LOGNAME_SIZE]; @@ -106,7 +107,7 @@ int main(int argc, char *argv[], char *envp[]) } /* open the class device we are called for */ - class_dev = open_class_device_wait(filename); + class_dev = wait_class_device_open(filename); if (!class_dev) { dbg("error: class device unavailable (probably remove has beaten us)"); goto exit; @@ -132,15 +133,15 @@ int main(int argc, char *argv[], char *envp[]) filename[SYSFS_PATH_MAX-1] = '\0'; /* open the path we are called for */ - devices_dev = open_devices_device_wait(filename); + devices_dev = wait_devices_device_open(filename); if (!devices_dev) { dbg("error: devices device unavailable (probably remove has beaten us)"); goto exit; } dbg("devices device opened '%s'", filename); - /* wait for the bus value */ - wait_for_bus_device(devices_dev, &error); + /* wait for the devices device */ + wait_for_devices_device(devices_dev, &error); sysfs_close_device(devices_dev); |