summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--udev_lib.c24
-rw-r--r--udev_lib.h2
-rw-r--r--udev_sysfs.c63
-rw-r--r--udev_sysfs.h10
-rw-r--r--wait_for_sysfs.c13
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);