1d9d16e16SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
240efcb05SGreg Kroah-Hartman /*
340efcb05SGreg Kroah-Hartman  * Sample kobject implementation
440efcb05SGreg Kroah-Hartman  *
540efcb05SGreg Kroah-Hartman  * Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>
640efcb05SGreg Kroah-Hartman  * Copyright (C) 2007 Novell Inc.
740efcb05SGreg Kroah-Hartman  */
840efcb05SGreg Kroah-Hartman #include <linux/kobject.h>
940efcb05SGreg Kroah-Hartman #include <linux/string.h>
1040efcb05SGreg Kroah-Hartman #include <linux/sysfs.h>
1140efcb05SGreg Kroah-Hartman #include <linux/module.h>
1240efcb05SGreg Kroah-Hartman #include <linux/init.h>
1340efcb05SGreg Kroah-Hartman 
1440efcb05SGreg Kroah-Hartman /*
1540efcb05SGreg Kroah-Hartman  * This module shows how to create a simple subdirectory in sysfs called
1640efcb05SGreg Kroah-Hartman  * /sys/kernel/kobject-example  In that directory, 3 files are created:
1740efcb05SGreg Kroah-Hartman  * "foo", "baz", and "bar".  If an integer is written to these files, it can be
1840efcb05SGreg Kroah-Hartman  * later read out of it.
1940efcb05SGreg Kroah-Hartman  */
2040efcb05SGreg Kroah-Hartman 
2140efcb05SGreg Kroah-Hartman static int foo;
2240efcb05SGreg Kroah-Hartman static int baz;
2340efcb05SGreg Kroah-Hartman static int bar;
2440efcb05SGreg Kroah-Hartman 
2540efcb05SGreg Kroah-Hartman /*
2640efcb05SGreg Kroah-Hartman  * The "foo" file where a static variable is read from and written to.
2740efcb05SGreg Kroah-Hartman  */
foo_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)2840efcb05SGreg Kroah-Hartman static ssize_t foo_show(struct kobject *kobj, struct kobj_attribute *attr,
2940efcb05SGreg Kroah-Hartman 			char *buf)
3040efcb05SGreg Kroah-Hartman {
31*5a242d85SNguyen Dinh Phi 	return sysfs_emit(buf, "%d\n", foo);
3240efcb05SGreg Kroah-Hartman }
3340efcb05SGreg Kroah-Hartman 
foo_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)3440efcb05SGreg Kroah-Hartman static ssize_t foo_store(struct kobject *kobj, struct kobj_attribute *attr,
3540efcb05SGreg Kroah-Hartman 			 const char *buf, size_t count)
3640efcb05SGreg Kroah-Hartman {
375fd637e7SRastislav Barlik 	int ret;
385fd637e7SRastislav Barlik 
395fd637e7SRastislav Barlik 	ret = kstrtoint(buf, 10, &foo);
405fd637e7SRastislav Barlik 	if (ret < 0)
415fd637e7SRastislav Barlik 		return ret;
425fd637e7SRastislav Barlik 
4340efcb05SGreg Kroah-Hartman 	return count;
4440efcb05SGreg Kroah-Hartman }
4540efcb05SGreg Kroah-Hartman 
46de510989SRusty Russell /* Sysfs attributes cannot be world-writable. */
4740efcb05SGreg Kroah-Hartman static struct kobj_attribute foo_attribute =
48de510989SRusty Russell 	__ATTR(foo, 0664, foo_show, foo_store);
4940efcb05SGreg Kroah-Hartman 
5040efcb05SGreg Kroah-Hartman /*
51a115bc07SRadu Voicilas  * More complex function where we determine which variable is being accessed by
5240efcb05SGreg Kroah-Hartman  * looking at the attribute for the "baz" and "bar" files.
5340efcb05SGreg Kroah-Hartman  */
b_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)5440efcb05SGreg Kroah-Hartman static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr,
5540efcb05SGreg Kroah-Hartman 		      char *buf)
5640efcb05SGreg Kroah-Hartman {
5740efcb05SGreg Kroah-Hartman 	int var;
5840efcb05SGreg Kroah-Hartman 
5940efcb05SGreg Kroah-Hartman 	if (strcmp(attr->attr.name, "baz") == 0)
6040efcb05SGreg Kroah-Hartman 		var = baz;
6140efcb05SGreg Kroah-Hartman 	else
6240efcb05SGreg Kroah-Hartman 		var = bar;
63*5a242d85SNguyen Dinh Phi 	return sysfs_emit(buf, "%d\n", var);
6440efcb05SGreg Kroah-Hartman }
6540efcb05SGreg Kroah-Hartman 
b_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)6640efcb05SGreg Kroah-Hartman static ssize_t b_store(struct kobject *kobj, struct kobj_attribute *attr,
6740efcb05SGreg Kroah-Hartman 		       const char *buf, size_t count)
6840efcb05SGreg Kroah-Hartman {
695fd637e7SRastislav Barlik 	int var, ret;
7040efcb05SGreg Kroah-Hartman 
715fd637e7SRastislav Barlik 	ret = kstrtoint(buf, 10, &var);
725fd637e7SRastislav Barlik 	if (ret < 0)
735fd637e7SRastislav Barlik 		return ret;
745fd637e7SRastislav Barlik 
7540efcb05SGreg Kroah-Hartman 	if (strcmp(attr->attr.name, "baz") == 0)
7640efcb05SGreg Kroah-Hartman 		baz = var;
7740efcb05SGreg Kroah-Hartman 	else
7840efcb05SGreg Kroah-Hartman 		bar = var;
7940efcb05SGreg Kroah-Hartman 	return count;
8040efcb05SGreg Kroah-Hartman }
8140efcb05SGreg Kroah-Hartman 
8240efcb05SGreg Kroah-Hartman static struct kobj_attribute baz_attribute =
83de510989SRusty Russell 	__ATTR(baz, 0664, b_show, b_store);
8440efcb05SGreg Kroah-Hartman static struct kobj_attribute bar_attribute =
85de510989SRusty Russell 	__ATTR(bar, 0664, b_show, b_store);
8640efcb05SGreg Kroah-Hartman 
8740efcb05SGreg Kroah-Hartman 
8840efcb05SGreg Kroah-Hartman /*
89a115bc07SRadu Voicilas  * Create a group of attributes so that we can create and destroy them all
9040efcb05SGreg Kroah-Hartman  * at once.
9140efcb05SGreg Kroah-Hartman  */
9240efcb05SGreg Kroah-Hartman static struct attribute *attrs[] = {
9340efcb05SGreg Kroah-Hartman 	&foo_attribute.attr,
9440efcb05SGreg Kroah-Hartman 	&baz_attribute.attr,
9540efcb05SGreg Kroah-Hartman 	&bar_attribute.attr,
9640efcb05SGreg Kroah-Hartman 	NULL,	/* need to NULL terminate the list of attributes */
9740efcb05SGreg Kroah-Hartman };
9840efcb05SGreg Kroah-Hartman 
9940efcb05SGreg Kroah-Hartman /*
10040efcb05SGreg Kroah-Hartman  * An unnamed attribute group will put all of the attributes directly in
10140efcb05SGreg Kroah-Hartman  * the kobject directory.  If we specify a name, a subdirectory will be
10240efcb05SGreg Kroah-Hartman  * created for the attributes with the directory being the name of the
10340efcb05SGreg Kroah-Hartman  * attribute group.
10440efcb05SGreg Kroah-Hartman  */
10540efcb05SGreg Kroah-Hartman static struct attribute_group attr_group = {
10640efcb05SGreg Kroah-Hartman 	.attrs = attrs,
10740efcb05SGreg Kroah-Hartman };
10840efcb05SGreg Kroah-Hartman 
10940efcb05SGreg Kroah-Hartman static struct kobject *example_kobj;
11040efcb05SGreg Kroah-Hartman 
example_init(void)1117ec7fb39SQinghuang Feng static int __init example_init(void)
11240efcb05SGreg Kroah-Hartman {
11340efcb05SGreg Kroah-Hartman 	int retval;
11440efcb05SGreg Kroah-Hartman 
11540efcb05SGreg Kroah-Hartman 	/*
11640efcb05SGreg Kroah-Hartman 	 * Create a simple kobject with the name of "kobject_example",
11740efcb05SGreg Kroah-Hartman 	 * located under /sys/kernel/
11840efcb05SGreg Kroah-Hartman 	 *
11940efcb05SGreg Kroah-Hartman 	 * As this is a simple directory, no uevent will be sent to
12040efcb05SGreg Kroah-Hartman 	 * userspace.  That is why this function should not be used for
12140efcb05SGreg Kroah-Hartman 	 * any type of dynamic kobjects, where the name and number are
12240efcb05SGreg Kroah-Hartman 	 * not known ahead of time.
12340efcb05SGreg Kroah-Hartman 	 */
12440efcb05SGreg Kroah-Hartman 	example_kobj = kobject_create_and_add("kobject_example", kernel_kobj);
12540efcb05SGreg Kroah-Hartman 	if (!example_kobj)
12640efcb05SGreg Kroah-Hartman 		return -ENOMEM;
12740efcb05SGreg Kroah-Hartman 
12840efcb05SGreg Kroah-Hartman 	/* Create the files associated with this kobject */
12940efcb05SGreg Kroah-Hartman 	retval = sysfs_create_group(example_kobj, &attr_group);
13040efcb05SGreg Kroah-Hartman 	if (retval)
13140efcb05SGreg Kroah-Hartman 		kobject_put(example_kobj);
13240efcb05SGreg Kroah-Hartman 
13340efcb05SGreg Kroah-Hartman 	return retval;
13440efcb05SGreg Kroah-Hartman }
13540efcb05SGreg Kroah-Hartman 
example_exit(void)1367ec7fb39SQinghuang Feng static void __exit example_exit(void)
13740efcb05SGreg Kroah-Hartman {
13840efcb05SGreg Kroah-Hartman 	kobject_put(example_kobj);
13940efcb05SGreg Kroah-Hartman }
14040efcb05SGreg Kroah-Hartman 
14140efcb05SGreg Kroah-Hartman module_init(example_init);
14240efcb05SGreg Kroah-Hartman module_exit(example_exit);
14307afb6acSGreg Kroah-Hartman MODULE_LICENSE("GPL v2");
14440efcb05SGreg Kroah-Hartman MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
145