if (strlen(b->var)) \
strcpy(a->var, b->var);
-int add_config_dev(struct config_device *new_dev)
-{
- struct list_head *tmp;
- struct config_device *tmp_dev;
-
- /* update the values if we already have the device */
- list_for_each(tmp, &config_device_list) {
- struct config_device *dev = list_entry(tmp, struct config_device, node);
- if (strcmp_pattern(new_dev->name, dev->name))
- continue;
- if (strncmp(dev->bus, new_dev->bus, sizeof(dev->name)))
- continue;
- copy_var(dev, new_dev, type);
- copy_string(dev, new_dev, bus);
- copy_string(dev, new_dev, sysfs_file);
- copy_string(dev, new_dev, sysfs_value);
- copy_string(dev, new_dev, id);
- copy_string(dev, new_dev, place);
- copy_string(dev, new_dev, kernel_name);
- copy_string(dev, new_dev, exec_program);
- copy_string(dev, new_dev, symlink);
- return 0;
- }
-
- /* not found, add new structure to the device list */
- tmp_dev = malloc(sizeof(*tmp_dev));
- if (!tmp_dev)
- return -ENOMEM;
- memcpy(tmp_dev, new_dev, sizeof(*tmp_dev));
- list_add_tail(&tmp_dev->node, &config_device_list);
- //dump_config_dev(tmp_dev);
- return 0;
-}
-
int add_perm_dev(struct perm_device *new_dev)
{
struct list_head *tmp;
return mode;
}
-static void build_kernel_number(struct sysfs_class_device *class_dev, struct udevice *udev)
-{
- char *dig;
-
- dig = class_dev->name + strlen(class_dev->name);
- while (isdigit(*(dig-1)))
- dig--;
- strfieldcpy(udev->kernel_number, dig);
- dbg("kernel_number='%s'", udev->kernel_number);
-}
-
static void apply_format(struct udevice *udev, unsigned char *string)
{
char name[NAME_SIZE];
strcat(pos, udev->bus_id);
dbg("substitute bus_id '%s'", udev->bus_id);
break;
+ case 'k':
+ if (strlen(udev->kernel_name) == 0)
+ break;
+ strcat(pos, udev->kernel_name);
+ dbg("substitute kernel name '%s'", udev->kernel_name);
+ break;
case 'n':
if (strlen(udev->kernel_number) == 0)
break;
return -ENODEV;
}
-static int do_label(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device)
+static int match_pair(struct sysfs_class_device *class_dev, struct sysfs_device *sysfs_device, struct sysfs_pair *pair)
{
struct sysfs_attribute *tmpattr = NULL;
+ char *c;
+
+ if ((pair == NULL) || (pair->file[0] == '\0') || (pair->value == '\0'))
+ return -ENODEV;
+
+ dbg("look for device attribute '%s'", pair->file);
+ /* try to find the attribute in the class device directory */
+ tmpattr = sysfs_get_classdev_attr(class_dev, pair->file);
+ if (tmpattr)
+ goto label_found;
+
+ /* look in the class device directory if present */
+ if (sysfs_device) {
+ tmpattr = sysfs_get_device_attr(sysfs_device, pair->file);
+ if (tmpattr)
+ goto label_found;
+ }
+
+ return -ENODEV;
+
+label_found:
+ c = tmpattr->value + strlen(tmpattr->value)-1;
+ if (*c == '\n')
+ *c = 0x00;
+ dbg("compare attribute '%s' value '%s' with '%s'",
+ pair->file, tmpattr->value, pair->value);
+ if (strcmp_pattern(pair->value, tmpattr->value) != 0)
+ return -ENODEV;
+
+ dbg("found matching attribute '%s' with value '%s'",
+ pair->file, pair->value);
+ return 0;
+}
+
+static int do_label(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device)
+{
+ struct sysfs_pair *pair;
struct config_device *dev;
struct list_head *tmp;
- char *c;
+ int i;
+ int match;
list_for_each(tmp, &config_device_list) {
dev = list_entry(tmp, struct config_device, node);
continue;
}
- dbg("look for device attribute '%s'", dev->sysfs_file);
- /* try to find the attribute in the class device directory */
- tmpattr = sysfs_get_classdev_attr(class_dev, dev->sysfs_file);
- if (tmpattr)
- goto label_found;
-
- /* look in the class device directory if present */
- if (sysfs_device) {
- tmpattr = sysfs_get_device_attr(sysfs_device, dev->sysfs_file);
- if (tmpattr)
- goto label_found;
+ match = 1;
+ for (i = 0; i < MAX_SYSFS_PAIRS; ++i) {
+ pair = &dev->sysfs_pair[i];
+ if ((pair->file[0] == '\0') || (pair->value[0] == '\0'))
+ break;
+ if (match_pair(class_dev, sysfs_device, pair) != 0) {
+ match = 0;
+ break;
+ }
}
-
- continue;
-
-label_found:
- c = tmpattr->value + strlen(tmpattr->value)-1;
- if (*c == '\n')
- *c = 0x00;
- dbg("compare attribute '%s' value '%s' with '%s'",
- dev->sysfs_file, tmpattr->value, dev->sysfs_value);
- if (strcmp_pattern(dev->sysfs_value, tmpattr->value) != 0)
+ if (match == 0)
continue;
+ /* found match */
strfieldcpy(udev->name, dev->name);
strfieldcpy(udev->symlink, dev->symlink);
- dbg("found matching attribute '%s', '%s' becomes '%s' ",
- dev->sysfs_file, class_dev->name, udev->name);
+ dbg("found matching attribute, '%s' becomes '%s' ",
+ class_dev->name, udev->name);
return 0;
}
struct sysfs_device *sysfs_device;
struct sysfs_class_device *class_dev_parent;
int loop;
- int retval;
- char filename[SYSFS_PATH_MAX + 6];
/* FIXME!!! */
/* This is needed here as we can easily out-race the placement of the
* class device really shows up. For now, we live with the time
* delay...
*/
-// sleep(1);
+ sleep(1);
+
+#if 0 /* FIXME
+ Something like this could also work, but for some reason doesn't,
+ I also tried just stat() on the device symlink, but that still
+ has nasty races, I'm probably doing something stupid... :( */
loop = 10;
while (loop--) {
struct stat buf;
+ int retval;
+ char filename[SYSFS_PATH_MAX + 6];
strcpy(filename, class_dev->path);
strcat(filename, "/device");
retval = stat(filename, &buf);
if (!retval)
break;
-#if 0
+
/* bah, let's go backwards up a level to see if the device is there,
* as block partitions don't point to the physical device. Need to fix that
* up in the kernel...
*/
if (strcmp(class_dev->classname, SYSFS_BLOCK_NAME) == 0) {
if (isdigit(class_dev->path[strlen(class_dev->path)-1])) {
- char *temp = strrchr(filename, '/');
- if (temp) {
- *temp = 0x00;
- temp = strrchr(filename, '/');
- if (temp) {
- *temp = 0x00;
- strcat(filename, "/device");
- dbg("looking for '%s'", filename);
- retval = stat(filename, &buf);
- if (!retval)
- break;
- }
+ class_dev_parent = sysfs_get_classdev_parent(class_dev);
+ if (class_dev_parent == NULL) {
+ dbg("sysfs_get_classdev_parent for class device '%s' failed", class_dev->name);
+ } else {
+ strcpy(filename, class_dev_parent->path);
+ strcat(filename, "/device");
+ dbg("looking for '%s'", filename);
+ retval = stat(filename, &buf);
+ if (!retval)
+ break;
}
}
}
-#endif
-// class_dev_parent = sysfs_get_classdev_parent(class_dev);
-// if (class_dev_parent == NULL) {
-// dbg("sysfs_get_classdev_parent for class device '%s' failed", class_dev->name);
-// } else {
-// strcpy(filename, class_dev_parent->path);
-// strcat(filename, "/device");
-// dbg("looking for '%s'", filename);
-// retval = stat(filename, &buf);
-// if (!retval)
-// break;
-// }
-// }
-// }
/* sleep to give the kernel a chance to create the device file */
sleep(1);
}
-// retval = -ENODEV;
-
-// sleep(1);
-
+#endif
loop = 1; /* FIXME put a real value in here for when everything is fixed... */
while (loop--) {
/* find the sysfs_device for this class device */
}
}
/* sleep to give the kernel a chance to create the link */
- /* sleep(1); */
+ sleep(1);
}
-// dbg("Timed out waiting for device symlink, continuing on anyway...");
+ dbg("Timed out waiting for device symlink, continuing on anyway...");
exit:
return sysfs_device;
}
struct sysfs_class_device *class_dev_parent = NULL;
int retval = 0;
struct perm_device *perm;
+ char *pos;
udev->mode = 0;
dbg("class_dev->name = '%s'", class_dev->name);
}
- build_kernel_number(class_dev, udev);
+ 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);
/* rules are looked at in priority order */
retval = do_callout(class_dev, udev, sysfs_device);