summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgreg@kroah.com <greg@kroah.com>2004-01-23 00:21:13 -0800
committerGreg KH <gregkh@suse.de>2005-04-26 21:13:17 -0700
commit724257d97b452dd563ea1a3a5cdc53b18e8dcb34 (patch)
tree2021f7d6e49f5dd15b7a4e4f61151a6c59eba28a
parentbb513a064ce00e8efca1c697955d4a34b6782c29 (diff)
[PATCH] add support for figuring out which device on the sysfs "chain" the rule applies to.
This should fix one of the more annoying things to me about udev, and gets rid of a TODO item.
-rw-r--r--namedev.c113
-rw-r--r--test/udev-test.pl9
2 files changed, 75 insertions, 47 deletions
diff --git a/namedev.c b/namedev.c
index e0d396e6ff..6b1aa297ea 100644
--- a/namedev.c
+++ b/namedev.c
@@ -585,50 +585,19 @@ exit:
return sysfs_device;
}
-int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *udev)
+static int match_rule(struct config_device *dev, struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device)
{
- struct sysfs_device *sysfs_device = NULL;
- struct config_device *dev;
- struct perm_device *perm;
- char *pos;
-
- udev->mode = 0;
-
- /* find the sysfs_device associated with this class device */
- sysfs_device = get_sysfs_device(class_dev);
- if (sysfs_device) {
- dbg("sysfs_device->path='%s'", sysfs_device->path);
- dbg("sysfs_device->bus_id='%s'", sysfs_device->bus_id);
- dbg("sysfs_device->bus='%s'", sysfs_device->bus);
- strfieldcpy(udev->bus_id, sysfs_device->bus_id);
- wait_for_device_to_initialize(sysfs_device);
- } else {
- dbg("class_dev->name = '%s'", class_dev->name);
- }
-
- strfieldcpy(udev->kernel_name, class_dev->name);
-
- /* get kernel number */
- pos = class_dev->name + strlen(class_dev->name);
- while (isdigit(*(pos-1)))
- pos--;
- strfieldcpy(udev->kernel_number, pos);
- dbg("kernel_number='%s'", udev->kernel_number);
-
- /* look for a matching rule to apply */
- list_for_each_entry(dev, &config_device_list, node) {
- dbg("process rule");
-
+ while (1) {
/* check for matching bus value */
if (dev->bus[0] != '\0') {
if (sysfs_device == NULL) {
dbg("device has no bus");
- continue;
+ goto no_good;
}
dbg("check for " FIELD_BUS " dev->bus='%s' sysfs_device->bus='%s'", dev->bus, sysfs_device->bus);
if (strcmp_pattern(dev->bus, sysfs_device->bus) != 0) {
dbg(FIELD_BUS " is not matching");
- continue;
+ goto no_good;
} else {
dbg(FIELD_BUS " matches");
}
@@ -639,7 +608,7 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
dbg("check for " FIELD_KERNEL " dev->kernel='%s' class_dev->name='%s'", dev->kernel, class_dev->name);
if (strcmp_pattern(dev->kernel, class_dev->name) != 0) {
dbg(FIELD_KERNEL " is not matching");
- continue;
+ goto no_good;
} else {
dbg(FIELD_KERNEL " matches");
}
@@ -650,7 +619,7 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
dbg("check " FIELD_ID);
if (match_id(dev, class_dev, sysfs_device) != 0) {
dbg(FIELD_ID " is not matching");
- continue;
+ goto no_good;
} else {
dbg(FIELD_ID " matches");
}
@@ -661,7 +630,7 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
dbg("check " FIELD_PLACE);
if (match_place(dev, class_dev, sysfs_device) != 0) {
dbg(FIELD_PLACE " is not matching");
- continue;
+ goto no_good;
} else {
dbg(FIELD_PLACE " matches");
}
@@ -672,7 +641,7 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
dbg("check " FIELD_SYSFS " pairs");
if (match_sysfs_pairs(dev, class_dev, sysfs_device) != 0) {
dbg(FIELD_SYSFS " is not matching");
- continue;
+ goto no_good;
} else {
dbg(FIELD_SYSFS " matches");
}
@@ -684,7 +653,7 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
apply_format(udev, dev->program);
if (execute_program(dev->program, udev->program_result, NAME_SIZE) != 0) {
dbg(FIELD_PROGRAM " returned nozero");
- continue;
+ goto no_good;
} else {
dbg(FIELD_PROGRAM " returned successful");
}
@@ -697,7 +666,7 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
dev->result, udev->program_result);
if (strcmp_pattern(dev->result, udev->program_result) != 0) {
dbg(FIELD_RESULT " is not matching");
- continue;
+ goto no_good;
} else {
dbg(FIELD_RESULT " matches");
}
@@ -709,12 +678,62 @@ int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *ud
return -1;
}
- /* Yup, this rule belongs to us! */
- info("configured rule in '%s' at line %i applied, '%s' becomes '%s'",
- udev_rules_filename, dev->config_line, udev->kernel_name, dev->name);
- strfieldcpy(udev->name, dev->name);
- strfieldcpy(udev->symlink, dev->symlink);
- goto found;
+ /* Yeah, we matched! */
+ return 0;
+
+no_good:
+ sysfs_device = sysfs_get_device_parent(sysfs_device);
+ if (sysfs_device == NULL)
+ return -ENODEV;
+ dbg("sysfs_device->path='%s'", sysfs_device->path);
+ dbg("sysfs_device->bus_id='%s'", sysfs_device->bus_id);
+ dbg("sysfs_device->bus='%s'", sysfs_device->bus);
+ }
+
+}
+
+int namedev_name_device(struct sysfs_class_device *class_dev, struct udevice *udev)
+{
+ struct sysfs_device *sysfs_device = NULL;
+ struct config_device *dev;
+ struct perm_device *perm;
+ char *pos;
+
+ udev->mode = 0;
+
+ /* find the sysfs_device associated with this class device */
+ sysfs_device = get_sysfs_device(class_dev);
+ if (sysfs_device) {
+ dbg("sysfs_device->path='%s'", sysfs_device->path);
+ dbg("sysfs_device->bus_id='%s'", sysfs_device->bus_id);
+ dbg("sysfs_device->bus='%s'", sysfs_device->bus);
+ strfieldcpy(udev->bus_id, sysfs_device->bus_id);
+ wait_for_device_to_initialize(sysfs_device);
+ } else {
+ dbg("class_dev->name = '%s'", class_dev->name);
+ }
+
+ strfieldcpy(udev->kernel_name, class_dev->name);
+
+ /* get kernel number */
+ pos = class_dev->name + strlen(class_dev->name);
+ while (isdigit(*(pos-1)))
+ pos--;
+ strfieldcpy(udev->kernel_number, pos);
+ dbg("kernel_number='%s'", udev->kernel_number);
+
+ /* look for a matching rule to apply */
+ list_for_each_entry(dev, &config_device_list, node) {
+ dbg("process rule");
+
+ if (match_rule(dev, class_dev, udev, sysfs_device) == 0) {
+ /* Yup, this rule belongs to us! */
+ info("configured rule in '%s' at line %i applied, '%s' becomes '%s'",
+ udev_rules_filename, dev->config_line, udev->kernel_name, dev->name);
+ strfieldcpy(udev->name, dev->name);
+ strfieldcpy(udev->symlink, dev->symlink);
+ goto found;
+ }
}
/* no rule was found so we use the kernel name */
diff --git a/test/udev-test.pl b/test/udev-test.pl
index b7013e4bde..0700e53576 100644
--- a/test/udev-test.pl
+++ b/test/udev-test.pl
@@ -319,6 +319,15 @@ EOF
KERNEL="ttyUSB0", NAME="visor", SYMLINK="first-%n second-%n third-%n"
EOF
},
+ {
+ desc => "sysfs parent heirachy",
+ subsys => "tty",
+ devpath => "class/tty/ttyUSB0",
+ expected => "visor" ,
+ conf => <<EOF
+SYSFS_idProduct="2008", NAME="visor"
+EOF
+ },
);
# set env