144bfe16eSGreg Kroah-Hartman /*
244bfe16eSGreg Kroah-Hartman  * Sample kset and ktype implementation
344bfe16eSGreg Kroah-Hartman  *
444bfe16eSGreg Kroah-Hartman  * Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>
544bfe16eSGreg Kroah-Hartman  * Copyright (C) 2007 Novell Inc.
644bfe16eSGreg Kroah-Hartman  *
744bfe16eSGreg Kroah-Hartman  * Released under the GPL version 2 only.
844bfe16eSGreg Kroah-Hartman  *
944bfe16eSGreg Kroah-Hartman  */
1044bfe16eSGreg Kroah-Hartman #include <linux/kobject.h>
1144bfe16eSGreg Kroah-Hartman #include <linux/string.h>
1244bfe16eSGreg Kroah-Hartman #include <linux/sysfs.h>
1344bfe16eSGreg Kroah-Hartman #include <linux/module.h>
1444bfe16eSGreg Kroah-Hartman #include <linux/init.h>
1544bfe16eSGreg Kroah-Hartman 
1644bfe16eSGreg Kroah-Hartman /*
1744bfe16eSGreg Kroah-Hartman  * This module shows how to create a kset in sysfs called
1844bfe16eSGreg Kroah-Hartman  * /sys/kernel/kset-example
1944bfe16eSGreg Kroah-Hartman  * Then tree kobjects are created and assigned to this kset, "foo", "baz",
2044bfe16eSGreg Kroah-Hartman  * and "bar".  In those kobjects, attributes of the same name are also
2144bfe16eSGreg Kroah-Hartman  * created and if an integer is written to these files, it can be later
2244bfe16eSGreg Kroah-Hartman  * read out of it.
2344bfe16eSGreg Kroah-Hartman  */
2444bfe16eSGreg Kroah-Hartman 
2544bfe16eSGreg Kroah-Hartman 
2644bfe16eSGreg Kroah-Hartman /*
2744bfe16eSGreg Kroah-Hartman  * This is our "object" that we will create a few of and register them with
2844bfe16eSGreg Kroah-Hartman  * sysfs.
2944bfe16eSGreg Kroah-Hartman  */
3044bfe16eSGreg Kroah-Hartman struct foo_obj {
3144bfe16eSGreg Kroah-Hartman 	struct kobject kobj;
3244bfe16eSGreg Kroah-Hartman 	int foo;
3344bfe16eSGreg Kroah-Hartman 	int baz;
3444bfe16eSGreg Kroah-Hartman 	int bar;
3544bfe16eSGreg Kroah-Hartman };
3644bfe16eSGreg Kroah-Hartman #define to_foo_obj(x) container_of(x, struct foo_obj, kobj)
3744bfe16eSGreg Kroah-Hartman 
3844bfe16eSGreg Kroah-Hartman /* a custom attribute that works just for a struct foo_obj. */
3944bfe16eSGreg Kroah-Hartman struct foo_attribute {
4044bfe16eSGreg Kroah-Hartman 	struct attribute attr;
4144bfe16eSGreg Kroah-Hartman 	ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);
4244bfe16eSGreg Kroah-Hartman 	ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count);
4344bfe16eSGreg Kroah-Hartman };
4444bfe16eSGreg Kroah-Hartman #define to_foo_attr(x) container_of(x, struct foo_attribute, attr)
4544bfe16eSGreg Kroah-Hartman 
4644bfe16eSGreg Kroah-Hartman /*
4744bfe16eSGreg Kroah-Hartman  * The default show function that must be passed to sysfs.  This will be
4844bfe16eSGreg Kroah-Hartman  * called by sysfs for whenever a show function is called by the user on a
4944bfe16eSGreg Kroah-Hartman  * sysfs file associated with the kobjects we have registered.  We need to
5044bfe16eSGreg Kroah-Hartman  * transpose back from a "default" kobject to our custom struct foo_obj and
5144bfe16eSGreg Kroah-Hartman  * then call the show function for that specific object.
5244bfe16eSGreg Kroah-Hartman  */
5344bfe16eSGreg Kroah-Hartman static ssize_t foo_attr_show(struct kobject *kobj,
5444bfe16eSGreg Kroah-Hartman 			     struct attribute *attr,
5544bfe16eSGreg Kroah-Hartman 			     char *buf)
5644bfe16eSGreg Kroah-Hartman {
5744bfe16eSGreg Kroah-Hartman 	struct foo_attribute *attribute;
5844bfe16eSGreg Kroah-Hartman 	struct foo_obj *foo;
5944bfe16eSGreg Kroah-Hartman 
6044bfe16eSGreg Kroah-Hartman 	attribute = to_foo_attr(attr);
6144bfe16eSGreg Kroah-Hartman 	foo = to_foo_obj(kobj);
6244bfe16eSGreg Kroah-Hartman 
6344bfe16eSGreg Kroah-Hartman 	if (!attribute->show)
6444bfe16eSGreg Kroah-Hartman 		return -EIO;
6544bfe16eSGreg Kroah-Hartman 
6644bfe16eSGreg Kroah-Hartman 	return attribute->show(foo, attribute, buf);
6744bfe16eSGreg Kroah-Hartman }
6844bfe16eSGreg Kroah-Hartman 
6944bfe16eSGreg Kroah-Hartman /*
7044bfe16eSGreg Kroah-Hartman  * Just like the default show function above, but this one is for when the
7144bfe16eSGreg Kroah-Hartman  * sysfs "store" is requested (when a value is written to a file.)
7244bfe16eSGreg Kroah-Hartman  */
7344bfe16eSGreg Kroah-Hartman static ssize_t foo_attr_store(struct kobject *kobj,
7444bfe16eSGreg Kroah-Hartman 			      struct attribute *attr,
7544bfe16eSGreg Kroah-Hartman 			      const char *buf, size_t len)
7644bfe16eSGreg Kroah-Hartman {
7744bfe16eSGreg Kroah-Hartman 	struct foo_attribute *attribute;
7844bfe16eSGreg Kroah-Hartman 	struct foo_obj *foo;
7944bfe16eSGreg Kroah-Hartman 
8044bfe16eSGreg Kroah-Hartman 	attribute = to_foo_attr(attr);
8144bfe16eSGreg Kroah-Hartman 	foo = to_foo_obj(kobj);
8244bfe16eSGreg Kroah-Hartman 
8344bfe16eSGreg Kroah-Hartman 	if (!attribute->store)
8444bfe16eSGreg Kroah-Hartman 		return -EIO;
8544bfe16eSGreg Kroah-Hartman 
8644bfe16eSGreg Kroah-Hartman 	return attribute->store(foo, attribute, buf, len);
8744bfe16eSGreg Kroah-Hartman }
8844bfe16eSGreg Kroah-Hartman 
8944bfe16eSGreg Kroah-Hartman /* Our custom sysfs_ops that we will associate with our ktype later on */
9044bfe16eSGreg Kroah-Hartman static struct sysfs_ops foo_sysfs_ops = {
9144bfe16eSGreg Kroah-Hartman 	.show = foo_attr_show,
9244bfe16eSGreg Kroah-Hartman 	.store = foo_attr_store,
9344bfe16eSGreg Kroah-Hartman };
9444bfe16eSGreg Kroah-Hartman 
9544bfe16eSGreg Kroah-Hartman /*
9644bfe16eSGreg Kroah-Hartman  * The release function for our object.  This is REQUIRED by the kernel to
9744bfe16eSGreg Kroah-Hartman  * have.  We free the memory held in our object here.
9844bfe16eSGreg Kroah-Hartman  *
9944bfe16eSGreg Kroah-Hartman  * NEVER try to get away with just a "blank" release function to try to be
10044bfe16eSGreg Kroah-Hartman  * smarter than the kernel.  Turns out, no one ever is...
10144bfe16eSGreg Kroah-Hartman  */
10244bfe16eSGreg Kroah-Hartman static void foo_release(struct kobject *kobj)
10344bfe16eSGreg Kroah-Hartman {
10444bfe16eSGreg Kroah-Hartman 	struct foo_obj *foo;
10544bfe16eSGreg Kroah-Hartman 
10644bfe16eSGreg Kroah-Hartman 	foo = to_foo_obj(kobj);
10744bfe16eSGreg Kroah-Hartman 	kfree(foo);
10844bfe16eSGreg Kroah-Hartman }
10944bfe16eSGreg Kroah-Hartman 
11044bfe16eSGreg Kroah-Hartman /*
11144bfe16eSGreg Kroah-Hartman  * The "foo" file where the .foo variable is read from and written to.
11244bfe16eSGreg Kroah-Hartman  */
11344bfe16eSGreg Kroah-Hartman static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
11444bfe16eSGreg Kroah-Hartman 			char *buf)
11544bfe16eSGreg Kroah-Hartman {
11644bfe16eSGreg Kroah-Hartman 	return sprintf(buf, "%d\n", foo_obj->foo);
11744bfe16eSGreg Kroah-Hartman }
11844bfe16eSGreg Kroah-Hartman 
11944bfe16eSGreg Kroah-Hartman static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
12044bfe16eSGreg Kroah-Hartman 			 const char *buf, size_t count)
12144bfe16eSGreg Kroah-Hartman {
12244bfe16eSGreg Kroah-Hartman 	sscanf(buf, "%du", &foo_obj->foo);
12344bfe16eSGreg Kroah-Hartman 	return count;
12444bfe16eSGreg Kroah-Hartman }
12544bfe16eSGreg Kroah-Hartman 
12644bfe16eSGreg Kroah-Hartman static struct foo_attribute foo_attribute =
12744bfe16eSGreg Kroah-Hartman 	__ATTR(foo, 0666, foo_show, foo_store);
12844bfe16eSGreg Kroah-Hartman 
12944bfe16eSGreg Kroah-Hartman /*
13044bfe16eSGreg Kroah-Hartman  * More complex function where we determine which varible is being accessed by
13144bfe16eSGreg Kroah-Hartman  * looking at the attribute for the "baz" and "bar" files.
13244bfe16eSGreg Kroah-Hartman  */
13344bfe16eSGreg Kroah-Hartman static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
13444bfe16eSGreg Kroah-Hartman 		      char *buf)
13544bfe16eSGreg Kroah-Hartman {
13644bfe16eSGreg Kroah-Hartman 	int var;
13744bfe16eSGreg Kroah-Hartman 
13844bfe16eSGreg Kroah-Hartman 	if (strcmp(attr->attr.name, "baz") == 0)
13944bfe16eSGreg Kroah-Hartman 		var = foo_obj->baz;
14044bfe16eSGreg Kroah-Hartman 	else
14144bfe16eSGreg Kroah-Hartman 		var = foo_obj->bar;
14244bfe16eSGreg Kroah-Hartman 	return sprintf(buf, "%d\n", var);
14344bfe16eSGreg Kroah-Hartman }
14444bfe16eSGreg Kroah-Hartman 
14544bfe16eSGreg Kroah-Hartman static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
14644bfe16eSGreg Kroah-Hartman 		       const char *buf, size_t count)
14744bfe16eSGreg Kroah-Hartman {
14844bfe16eSGreg Kroah-Hartman 	int var;
14944bfe16eSGreg Kroah-Hartman 
15044bfe16eSGreg Kroah-Hartman 	sscanf(buf, "%du", &var);
15144bfe16eSGreg Kroah-Hartman 	if (strcmp(attr->attr.name, "baz") == 0)
15244bfe16eSGreg Kroah-Hartman 		foo_obj->baz = var;
15344bfe16eSGreg Kroah-Hartman 	else
15444bfe16eSGreg Kroah-Hartman 		foo_obj->bar = var;
15544bfe16eSGreg Kroah-Hartman 	return count;
15644bfe16eSGreg Kroah-Hartman }
15744bfe16eSGreg Kroah-Hartman 
15844bfe16eSGreg Kroah-Hartman static struct foo_attribute baz_attribute =
15944bfe16eSGreg Kroah-Hartman 	__ATTR(baz, 0666, b_show, b_store);
16044bfe16eSGreg Kroah-Hartman static struct foo_attribute bar_attribute =
16144bfe16eSGreg Kroah-Hartman 	__ATTR(bar, 0666, b_show, b_store);
16244bfe16eSGreg Kroah-Hartman 
16344bfe16eSGreg Kroah-Hartman /*
16444bfe16eSGreg Kroah-Hartman  * Create a group of attributes so that we can create and destory them all
16544bfe16eSGreg Kroah-Hartman  * at once.
16644bfe16eSGreg Kroah-Hartman  */
16744bfe16eSGreg Kroah-Hartman static struct attribute *foo_default_attrs[] = {
16844bfe16eSGreg Kroah-Hartman 	&foo_attribute.attr,
16944bfe16eSGreg Kroah-Hartman 	&baz_attribute.attr,
17044bfe16eSGreg Kroah-Hartman 	&bar_attribute.attr,
17144bfe16eSGreg Kroah-Hartman 	NULL,	/* need to NULL terminate the list of attributes */
17244bfe16eSGreg Kroah-Hartman };
17344bfe16eSGreg Kroah-Hartman 
17444bfe16eSGreg Kroah-Hartman /*
17544bfe16eSGreg Kroah-Hartman  * Our own ktype for our kobjects.  Here we specify our sysfs ops, the
17644bfe16eSGreg Kroah-Hartman  * release function, and the set of default attributes we want created
17744bfe16eSGreg Kroah-Hartman  * whenever a kobject of this type is registered with the kernel.
17844bfe16eSGreg Kroah-Hartman  */
17944bfe16eSGreg Kroah-Hartman static struct kobj_type foo_ktype = {
18044bfe16eSGreg Kroah-Hartman 	.sysfs_ops = &foo_sysfs_ops,
18144bfe16eSGreg Kroah-Hartman 	.release = foo_release,
18244bfe16eSGreg Kroah-Hartman 	.default_attrs = foo_default_attrs,
18344bfe16eSGreg Kroah-Hartman };
18444bfe16eSGreg Kroah-Hartman 
18544bfe16eSGreg Kroah-Hartman static struct kset *example_kset;
18644bfe16eSGreg Kroah-Hartman static struct foo_obj *foo_obj;
18744bfe16eSGreg Kroah-Hartman static struct foo_obj *bar_obj;
18844bfe16eSGreg Kroah-Hartman static struct foo_obj *baz_obj;
18944bfe16eSGreg Kroah-Hartman 
19044bfe16eSGreg Kroah-Hartman static struct foo_obj *create_foo_obj(const char *name)
19144bfe16eSGreg Kroah-Hartman {
19244bfe16eSGreg Kroah-Hartman 	struct foo_obj *foo;
19344bfe16eSGreg Kroah-Hartman 	int retval;
19444bfe16eSGreg Kroah-Hartman 
19544bfe16eSGreg Kroah-Hartman 	/* allocate the memory for the whole object */
19644bfe16eSGreg Kroah-Hartman 	foo = kzalloc(sizeof(*foo), GFP_KERNEL);
19744bfe16eSGreg Kroah-Hartman 	if (!foo)
19844bfe16eSGreg Kroah-Hartman 		return NULL;
19944bfe16eSGreg Kroah-Hartman 
20044bfe16eSGreg Kroah-Hartman 	/*
20144bfe16eSGreg Kroah-Hartman 	 * As we have a kset for this kobject, we need to set it before calling
20244bfe16eSGreg Kroah-Hartman 	 * the kobject core.
20344bfe16eSGreg Kroah-Hartman 	 */
20444bfe16eSGreg Kroah-Hartman 	foo->kobj.kset = example_kset;
20544bfe16eSGreg Kroah-Hartman 
20644bfe16eSGreg Kroah-Hartman 	/*
20744bfe16eSGreg Kroah-Hartman 	 * Initialize and add the kobject to the kernel.  All the default files
20844bfe16eSGreg Kroah-Hartman 	 * will be created here.  As we have already specified a kset for this
20944bfe16eSGreg Kroah-Hartman 	 * kobject, we don't have to set a parent for the kobject, the kobject
21044bfe16eSGreg Kroah-Hartman 	 * will be placed beneath that kset automatically.
21144bfe16eSGreg Kroah-Hartman 	 */
21244bfe16eSGreg Kroah-Hartman 	retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);
21344bfe16eSGreg Kroah-Hartman 	if (retval) {
21444bfe16eSGreg Kroah-Hartman 		kfree(foo);
21544bfe16eSGreg Kroah-Hartman 		return NULL;
21644bfe16eSGreg Kroah-Hartman 	}
21744bfe16eSGreg Kroah-Hartman 
21844bfe16eSGreg Kroah-Hartman 	/*
21944bfe16eSGreg Kroah-Hartman 	 * We are always responsible for sending the uevent that the kobject
22044bfe16eSGreg Kroah-Hartman 	 * was added to the system.
22144bfe16eSGreg Kroah-Hartman 	 */
22244bfe16eSGreg Kroah-Hartman 	kobject_uevent(&foo->kobj, KOBJ_ADD);
22344bfe16eSGreg Kroah-Hartman 
22444bfe16eSGreg Kroah-Hartman 	return foo;
22544bfe16eSGreg Kroah-Hartman }
22644bfe16eSGreg Kroah-Hartman 
22744bfe16eSGreg Kroah-Hartman static void destroy_foo_obj(struct foo_obj *foo)
22844bfe16eSGreg Kroah-Hartman {
22944bfe16eSGreg Kroah-Hartman 	kobject_put(&foo->kobj);
23044bfe16eSGreg Kroah-Hartman }
23144bfe16eSGreg Kroah-Hartman 
23244bfe16eSGreg Kroah-Hartman static int example_init(void)
23344bfe16eSGreg Kroah-Hartman {
23444bfe16eSGreg Kroah-Hartman 	/*
23544bfe16eSGreg Kroah-Hartman 	 * Create a kset with the name of "kset_example",
23644bfe16eSGreg Kroah-Hartman 	 * located under /sys/kernel/
23744bfe16eSGreg Kroah-Hartman 	 */
23844bfe16eSGreg Kroah-Hartman 	example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj);
23944bfe16eSGreg Kroah-Hartman 	if (!example_kset)
24044bfe16eSGreg Kroah-Hartman 		return -ENOMEM;
24144bfe16eSGreg Kroah-Hartman 
24244bfe16eSGreg Kroah-Hartman 	/*
24344bfe16eSGreg Kroah-Hartman 	 * Create three objects and register them with our kset
24444bfe16eSGreg Kroah-Hartman 	 */
24544bfe16eSGreg Kroah-Hartman 	foo_obj = create_foo_obj("foo");
24644bfe16eSGreg Kroah-Hartman 	if (!foo_obj)
24744bfe16eSGreg Kroah-Hartman 		goto foo_error;
24844bfe16eSGreg Kroah-Hartman 
24944bfe16eSGreg Kroah-Hartman 	bar_obj = create_foo_obj("bar");
25044bfe16eSGreg Kroah-Hartman 	if (!bar_obj)
25144bfe16eSGreg Kroah-Hartman 		goto bar_error;
25244bfe16eSGreg Kroah-Hartman 
25344bfe16eSGreg Kroah-Hartman 	baz_obj = create_foo_obj("baz");
25444bfe16eSGreg Kroah-Hartman 	if (!baz_obj)
25544bfe16eSGreg Kroah-Hartman 		goto baz_error;
25644bfe16eSGreg Kroah-Hartman 
25744bfe16eSGreg Kroah-Hartman 	return 0;
25844bfe16eSGreg Kroah-Hartman 
25944bfe16eSGreg Kroah-Hartman baz_error:
26044bfe16eSGreg Kroah-Hartman 	destroy_foo_obj(bar_obj);
26144bfe16eSGreg Kroah-Hartman bar_error:
26244bfe16eSGreg Kroah-Hartman 	destroy_foo_obj(foo_obj);
26344bfe16eSGreg Kroah-Hartman foo_error:
26444bfe16eSGreg Kroah-Hartman 	return -EINVAL;
26544bfe16eSGreg Kroah-Hartman }
26644bfe16eSGreg Kroah-Hartman 
26744bfe16eSGreg Kroah-Hartman static void example_exit(void)
26844bfe16eSGreg Kroah-Hartman {
26944bfe16eSGreg Kroah-Hartman 	destroy_foo_obj(baz_obj);
27044bfe16eSGreg Kroah-Hartman 	destroy_foo_obj(bar_obj);
27144bfe16eSGreg Kroah-Hartman 	destroy_foo_obj(foo_obj);
27244bfe16eSGreg Kroah-Hartman 	kset_unregister(example_kset);
27344bfe16eSGreg Kroah-Hartman }
27444bfe16eSGreg Kroah-Hartman 
27544bfe16eSGreg Kroah-Hartman module_init(example_init);
27644bfe16eSGreg Kroah-Hartman module_exit(example_exit);
27744bfe16eSGreg Kroah-Hartman MODULE_LICENSE("GPL");
27844bfe16eSGreg Kroah-Hartman MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
279