Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Sample kset and ktype implementation
0004  *
0005  * Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com>
0006  * Copyright (C) 2007 Novell Inc.
0007  */
0008 #include <linux/kobject.h>
0009 #include <linux/string.h>
0010 #include <linux/sysfs.h>
0011 #include <linux/slab.h>
0012 #include <linux/module.h>
0013 #include <linux/init.h>
0014 
0015 /*
0016  * This module shows how to create a kset in sysfs called
0017  * /sys/kernel/kset-example
0018  * Then tree kobjects are created and assigned to this kset, "foo", "baz",
0019  * and "bar".  In those kobjects, attributes of the same name are also
0020  * created and if an integer is written to these files, it can be later
0021  * read out of it.
0022  */
0023 
0024 
0025 /*
0026  * This is our "object" that we will create a few of and register them with
0027  * sysfs.
0028  */
0029 struct foo_obj {
0030     struct kobject kobj;
0031     int foo;
0032     int baz;
0033     int bar;
0034 };
0035 #define to_foo_obj(x) container_of(x, struct foo_obj, kobj)
0036 
0037 /* a custom attribute that works just for a struct foo_obj. */
0038 struct foo_attribute {
0039     struct attribute attr;
0040     ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);
0041     ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count);
0042 };
0043 #define to_foo_attr(x) container_of(x, struct foo_attribute, attr)
0044 
0045 /*
0046  * The default show function that must be passed to sysfs.  This will be
0047  * called by sysfs for whenever a show function is called by the user on a
0048  * sysfs file associated with the kobjects we have registered.  We need to
0049  * transpose back from a "default" kobject to our custom struct foo_obj and
0050  * then call the show function for that specific object.
0051  */
0052 static ssize_t foo_attr_show(struct kobject *kobj,
0053                  struct attribute *attr,
0054                  char *buf)
0055 {
0056     struct foo_attribute *attribute;
0057     struct foo_obj *foo;
0058 
0059     attribute = to_foo_attr(attr);
0060     foo = to_foo_obj(kobj);
0061 
0062     if (!attribute->show)
0063         return -EIO;
0064 
0065     return attribute->show(foo, attribute, buf);
0066 }
0067 
0068 /*
0069  * Just like the default show function above, but this one is for when the
0070  * sysfs "store" is requested (when a value is written to a file.)
0071  */
0072 static ssize_t foo_attr_store(struct kobject *kobj,
0073                   struct attribute *attr,
0074                   const char *buf, size_t len)
0075 {
0076     struct foo_attribute *attribute;
0077     struct foo_obj *foo;
0078 
0079     attribute = to_foo_attr(attr);
0080     foo = to_foo_obj(kobj);
0081 
0082     if (!attribute->store)
0083         return -EIO;
0084 
0085     return attribute->store(foo, attribute, buf, len);
0086 }
0087 
0088 /* Our custom sysfs_ops that we will associate with our ktype later on */
0089 static const struct sysfs_ops foo_sysfs_ops = {
0090     .show = foo_attr_show,
0091     .store = foo_attr_store,
0092 };
0093 
0094 /*
0095  * The release function for our object.  This is REQUIRED by the kernel to
0096  * have.  We free the memory held in our object here.
0097  *
0098  * NEVER try to get away with just a "blank" release function to try to be
0099  * smarter than the kernel.  Turns out, no one ever is...
0100  */
0101 static void foo_release(struct kobject *kobj)
0102 {
0103     struct foo_obj *foo;
0104 
0105     foo = to_foo_obj(kobj);
0106     kfree(foo);
0107 }
0108 
0109 /*
0110  * The "foo" file where the .foo variable is read from and written to.
0111  */
0112 static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
0113             char *buf)
0114 {
0115     return sysfs_emit(buf, "%d\n", foo_obj->foo);
0116 }
0117 
0118 static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
0119              const char *buf, size_t count)
0120 {
0121     int ret;
0122 
0123     ret = kstrtoint(buf, 10, &foo_obj->foo);
0124     if (ret < 0)
0125         return ret;
0126 
0127     return count;
0128 }
0129 
0130 /* Sysfs attributes cannot be world-writable. */
0131 static struct foo_attribute foo_attribute =
0132     __ATTR(foo, 0664, foo_show, foo_store);
0133 
0134 /*
0135  * More complex function where we determine which variable is being accessed by
0136  * looking at the attribute for the "baz" and "bar" files.
0137  */
0138 static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
0139               char *buf)
0140 {
0141     int var;
0142 
0143     if (strcmp(attr->attr.name, "baz") == 0)
0144         var = foo_obj->baz;
0145     else
0146         var = foo_obj->bar;
0147     return sysfs_emit(buf, "%d\n", var);
0148 }
0149 
0150 static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
0151                const char *buf, size_t count)
0152 {
0153     int var, ret;
0154 
0155     ret = kstrtoint(buf, 10, &var);
0156     if (ret < 0)
0157         return ret;
0158 
0159     if (strcmp(attr->attr.name, "baz") == 0)
0160         foo_obj->baz = var;
0161     else
0162         foo_obj->bar = var;
0163     return count;
0164 }
0165 
0166 static struct foo_attribute baz_attribute =
0167     __ATTR(baz, 0664, b_show, b_store);
0168 static struct foo_attribute bar_attribute =
0169     __ATTR(bar, 0664, b_show, b_store);
0170 
0171 /*
0172  * Create a group of attributes so that we can create and destroy them all
0173  * at once.
0174  */
0175 static struct attribute *foo_default_attrs[] = {
0176     &foo_attribute.attr,
0177     &baz_attribute.attr,
0178     &bar_attribute.attr,
0179     NULL,   /* need to NULL terminate the list of attributes */
0180 };
0181 ATTRIBUTE_GROUPS(foo_default);
0182 
0183 /*
0184  * Our own ktype for our kobjects.  Here we specify our sysfs ops, the
0185  * release function, and the set of default attributes we want created
0186  * whenever a kobject of this type is registered with the kernel.
0187  */
0188 static struct kobj_type foo_ktype = {
0189     .sysfs_ops = &foo_sysfs_ops,
0190     .release = foo_release,
0191     .default_groups = foo_default_groups,
0192 };
0193 
0194 static struct kset *example_kset;
0195 static struct foo_obj *foo_obj;
0196 static struct foo_obj *bar_obj;
0197 static struct foo_obj *baz_obj;
0198 
0199 static struct foo_obj *create_foo_obj(const char *name)
0200 {
0201     struct foo_obj *foo;
0202     int retval;
0203 
0204     /* allocate the memory for the whole object */
0205     foo = kzalloc(sizeof(*foo), GFP_KERNEL);
0206     if (!foo)
0207         return NULL;
0208 
0209     /*
0210      * As we have a kset for this kobject, we need to set it before calling
0211      * the kobject core.
0212      */
0213     foo->kobj.kset = example_kset;
0214 
0215     /*
0216      * Initialize and add the kobject to the kernel.  All the default files
0217      * will be created here.  As we have already specified a kset for this
0218      * kobject, we don't have to set a parent for the kobject, the kobject
0219      * will be placed beneath that kset automatically.
0220      */
0221     retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);
0222     if (retval) {
0223         kobject_put(&foo->kobj);
0224         return NULL;
0225     }
0226 
0227     /*
0228      * We are always responsible for sending the uevent that the kobject
0229      * was added to the system.
0230      */
0231     kobject_uevent(&foo->kobj, KOBJ_ADD);
0232 
0233     return foo;
0234 }
0235 
0236 static void destroy_foo_obj(struct foo_obj *foo)
0237 {
0238     kobject_put(&foo->kobj);
0239 }
0240 
0241 static int __init example_init(void)
0242 {
0243     /*
0244      * Create a kset with the name of "kset_example",
0245      * located under /sys/kernel/
0246      */
0247     example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj);
0248     if (!example_kset)
0249         return -ENOMEM;
0250 
0251     /*
0252      * Create three objects and register them with our kset
0253      */
0254     foo_obj = create_foo_obj("foo");
0255     if (!foo_obj)
0256         goto foo_error;
0257 
0258     bar_obj = create_foo_obj("bar");
0259     if (!bar_obj)
0260         goto bar_error;
0261 
0262     baz_obj = create_foo_obj("baz");
0263     if (!baz_obj)
0264         goto baz_error;
0265 
0266     return 0;
0267 
0268 baz_error:
0269     destroy_foo_obj(bar_obj);
0270 bar_error:
0271     destroy_foo_obj(foo_obj);
0272 foo_error:
0273     kset_unregister(example_kset);
0274     return -EINVAL;
0275 }
0276 
0277 static void __exit example_exit(void)
0278 {
0279     destroy_foo_obj(baz_obj);
0280     destroy_foo_obj(bar_obj);
0281     destroy_foo_obj(foo_obj);
0282     kset_unregister(example_kset);
0283 }
0284 
0285 module_init(example_init);
0286 module_exit(example_exit);
0287 MODULE_LICENSE("GPL v2");
0288 MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");