Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6fcf53ac authored by Kay Sievers's avatar Kay Sievers Committed by Greg Kroah-Hartman
Browse files

Driver Core: add nodename callbacks



This adds the nodename callback for struct class, struct device_type and
struct device, to allow drivers to send userspace hints on the device
name and subdirectory that should be used for it.

Signed-off-by: default avatarKay Sievers <kay.sievers@vrfy.org>
Signed-off-by: default avatarJan Blunck <jblunck@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent acc0e90f
Loading
Loading
Loading
Loading
+50 −1
Original line number Diff line number Diff line
@@ -162,10 +162,18 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
	struct device *dev = to_dev(kobj);
	int retval = 0;

	/* add the major/minor if present */
	/* add device node properties if present */
	if (MAJOR(dev->devt)) {
		const char *tmp;
		const char *name;

		add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
		add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
		name = device_get_nodename(dev, &tmp);
		if (name) {
			add_uevent_var(env, "DEVNAME=%s", name);
			kfree(tmp);
		}
	}

	if (dev->type && dev->type->name)
@@ -1128,6 +1136,47 @@ static struct device *next_device(struct klist_iter *i)
	return dev;
}

/**
 * device_get_nodename - path of device node file
 * @dev: device
 * @tmp: possibly allocated string
 *
 * Return the relative path of a possible device node.
 * Non-default names may need to allocate a memory to compose
 * a name. This memory is returned in tmp and needs to be
 * freed by the caller.
 */
const char *device_get_nodename(struct device *dev, const char **tmp)
{
	char *s;

	*tmp = NULL;

	/* the device type may provide a specific name */
	if (dev->type && dev->type->nodename)
		*tmp = dev->type->nodename(dev);
	if (*tmp)
		return *tmp;

	/* the class may provide a specific name */
	if (dev->class && dev->class->nodename)
		*tmp = dev->class->nodename(dev);
	if (*tmp)
		return *tmp;

	/* return name without allocation, tmp == NULL */
	if (strchr(dev_name(dev), '!') == NULL)
		return dev_name(dev);

	/* replace '!' in the name with '/' */
	*tmp = kstrdup(dev_name(dev), GFP_KERNEL);
	if (!*tmp)
		return NULL;
	while ((s = strchr(*tmp, '!')))
		s[0] = '/';
	return *tmp;
}

/**
 * device_for_each_child - device child iterator.
 * @parent: parent struct device.
+3 −0
Original line number Diff line number Diff line
@@ -194,6 +194,7 @@ struct class {
	struct kobject			*dev_kobj;

	int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
	char *(*nodename)(struct device *dev);

	void (*class_release)(struct class *class);
	void (*dev_release)(struct device *dev);
@@ -289,6 +290,7 @@ struct device_type {
	const char *name;
	struct attribute_group **groups;
	int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
	char *(*nodename)(struct device *dev);
	void (*release)(struct device *dev);

	struct dev_pm_ops *pm;
@@ -488,6 +490,7 @@ extern struct device *device_find_child(struct device *dev, void *data,
extern int device_rename(struct device *dev, char *new_name);
extern int device_move(struct device *dev, struct device *new_parent,
		       enum dpm_order dpm_order);
extern const char *device_get_nodename(struct device *dev, const char **tmp);

/*
 * Root device objects for grouping under /sys/devices