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