1*44bfe16eSGreg Kroah-Hartman /* 2*44bfe16eSGreg Kroah-Hartman * Sample kset and ktype implementation 3*44bfe16eSGreg Kroah-Hartman * 4*44bfe16eSGreg Kroah-Hartman * Copyright (C) 2004-2007 Greg Kroah-Hartman <greg@kroah.com> 5*44bfe16eSGreg Kroah-Hartman * Copyright (C) 2007 Novell Inc. 6*44bfe16eSGreg Kroah-Hartman * 7*44bfe16eSGreg Kroah-Hartman * Released under the GPL version 2 only. 8*44bfe16eSGreg Kroah-Hartman * 9*44bfe16eSGreg Kroah-Hartman */ 10*44bfe16eSGreg Kroah-Hartman #include <linux/kobject.h> 11*44bfe16eSGreg Kroah-Hartman #include <linux/string.h> 12*44bfe16eSGreg Kroah-Hartman #include <linux/sysfs.h> 13*44bfe16eSGreg Kroah-Hartman #include <linux/module.h> 14*44bfe16eSGreg Kroah-Hartman #include <linux/init.h> 15*44bfe16eSGreg Kroah-Hartman 16*44bfe16eSGreg Kroah-Hartman /* 17*44bfe16eSGreg Kroah-Hartman * This module shows how to create a kset in sysfs called 18*44bfe16eSGreg Kroah-Hartman * /sys/kernel/kset-example 19*44bfe16eSGreg Kroah-Hartman * Then tree kobjects are created and assigned to this kset, "foo", "baz", 20*44bfe16eSGreg Kroah-Hartman * and "bar". In those kobjects, attributes of the same name are also 21*44bfe16eSGreg Kroah-Hartman * created and if an integer is written to these files, it can be later 22*44bfe16eSGreg Kroah-Hartman * read out of it. 23*44bfe16eSGreg Kroah-Hartman */ 24*44bfe16eSGreg Kroah-Hartman 25*44bfe16eSGreg Kroah-Hartman 26*44bfe16eSGreg Kroah-Hartman /* 27*44bfe16eSGreg Kroah-Hartman * This is our "object" that we will create a few of and register them with 28*44bfe16eSGreg Kroah-Hartman * sysfs. 29*44bfe16eSGreg Kroah-Hartman */ 30*44bfe16eSGreg Kroah-Hartman struct foo_obj { 31*44bfe16eSGreg Kroah-Hartman struct kobject kobj; 32*44bfe16eSGreg Kroah-Hartman int foo; 33*44bfe16eSGreg Kroah-Hartman int baz; 34*44bfe16eSGreg Kroah-Hartman int bar; 35*44bfe16eSGreg Kroah-Hartman }; 36*44bfe16eSGreg Kroah-Hartman #define to_foo_obj(x) container_of(x, struct foo_obj, kobj) 37*44bfe16eSGreg Kroah-Hartman 38*44bfe16eSGreg Kroah-Hartman /* a custom attribute that works just for a struct foo_obj. */ 39*44bfe16eSGreg Kroah-Hartman struct foo_attribute { 40*44bfe16eSGreg Kroah-Hartman struct attribute attr; 41*44bfe16eSGreg Kroah-Hartman ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf); 42*44bfe16eSGreg Kroah-Hartman ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count); 43*44bfe16eSGreg Kroah-Hartman }; 44*44bfe16eSGreg Kroah-Hartman #define to_foo_attr(x) container_of(x, struct foo_attribute, attr) 45*44bfe16eSGreg Kroah-Hartman 46*44bfe16eSGreg Kroah-Hartman /* 47*44bfe16eSGreg Kroah-Hartman * The default show function that must be passed to sysfs. This will be 48*44bfe16eSGreg Kroah-Hartman * called by sysfs for whenever a show function is called by the user on a 49*44bfe16eSGreg Kroah-Hartman * sysfs file associated with the kobjects we have registered. We need to 50*44bfe16eSGreg Kroah-Hartman * transpose back from a "default" kobject to our custom struct foo_obj and 51*44bfe16eSGreg Kroah-Hartman * then call the show function for that specific object. 52*44bfe16eSGreg Kroah-Hartman */ 53*44bfe16eSGreg Kroah-Hartman static ssize_t foo_attr_show(struct kobject *kobj, 54*44bfe16eSGreg Kroah-Hartman struct attribute *attr, 55*44bfe16eSGreg Kroah-Hartman char *buf) 56*44bfe16eSGreg Kroah-Hartman { 57*44bfe16eSGreg Kroah-Hartman struct foo_attribute *attribute; 58*44bfe16eSGreg Kroah-Hartman struct foo_obj *foo; 59*44bfe16eSGreg Kroah-Hartman 60*44bfe16eSGreg Kroah-Hartman attribute = to_foo_attr(attr); 61*44bfe16eSGreg Kroah-Hartman foo = to_foo_obj(kobj); 62*44bfe16eSGreg Kroah-Hartman 63*44bfe16eSGreg Kroah-Hartman if (!attribute->show) 64*44bfe16eSGreg Kroah-Hartman return -EIO; 65*44bfe16eSGreg Kroah-Hartman 66*44bfe16eSGreg Kroah-Hartman return attribute->show(foo, attribute, buf); 67*44bfe16eSGreg Kroah-Hartman } 68*44bfe16eSGreg Kroah-Hartman 69*44bfe16eSGreg Kroah-Hartman /* 70*44bfe16eSGreg Kroah-Hartman * Just like the default show function above, but this one is for when the 71*44bfe16eSGreg Kroah-Hartman * sysfs "store" is requested (when a value is written to a file.) 72*44bfe16eSGreg Kroah-Hartman */ 73*44bfe16eSGreg Kroah-Hartman static ssize_t foo_attr_store(struct kobject *kobj, 74*44bfe16eSGreg Kroah-Hartman struct attribute *attr, 75*44bfe16eSGreg Kroah-Hartman const char *buf, size_t len) 76*44bfe16eSGreg Kroah-Hartman { 77*44bfe16eSGreg Kroah-Hartman struct foo_attribute *attribute; 78*44bfe16eSGreg Kroah-Hartman struct foo_obj *foo; 79*44bfe16eSGreg Kroah-Hartman 80*44bfe16eSGreg Kroah-Hartman attribute = to_foo_attr(attr); 81*44bfe16eSGreg Kroah-Hartman foo = to_foo_obj(kobj); 82*44bfe16eSGreg Kroah-Hartman 83*44bfe16eSGreg Kroah-Hartman if (!attribute->store) 84*44bfe16eSGreg Kroah-Hartman return -EIO; 85*44bfe16eSGreg Kroah-Hartman 86*44bfe16eSGreg Kroah-Hartman return attribute->store(foo, attribute, buf, len); 87*44bfe16eSGreg Kroah-Hartman } 88*44bfe16eSGreg Kroah-Hartman 89*44bfe16eSGreg Kroah-Hartman /* Our custom sysfs_ops that we will associate with our ktype later on */ 90*44bfe16eSGreg Kroah-Hartman static struct sysfs_ops foo_sysfs_ops = { 91*44bfe16eSGreg Kroah-Hartman .show = foo_attr_show, 92*44bfe16eSGreg Kroah-Hartman .store = foo_attr_store, 93*44bfe16eSGreg Kroah-Hartman }; 94*44bfe16eSGreg Kroah-Hartman 95*44bfe16eSGreg Kroah-Hartman /* 96*44bfe16eSGreg Kroah-Hartman * The release function for our object. This is REQUIRED by the kernel to 97*44bfe16eSGreg Kroah-Hartman * have. We free the memory held in our object here. 98*44bfe16eSGreg Kroah-Hartman * 99*44bfe16eSGreg Kroah-Hartman * NEVER try to get away with just a "blank" release function to try to be 100*44bfe16eSGreg Kroah-Hartman * smarter than the kernel. Turns out, no one ever is... 101*44bfe16eSGreg Kroah-Hartman */ 102*44bfe16eSGreg Kroah-Hartman static void foo_release(struct kobject *kobj) 103*44bfe16eSGreg Kroah-Hartman { 104*44bfe16eSGreg Kroah-Hartman struct foo_obj *foo; 105*44bfe16eSGreg Kroah-Hartman 106*44bfe16eSGreg Kroah-Hartman foo = to_foo_obj(kobj); 107*44bfe16eSGreg Kroah-Hartman kfree(foo); 108*44bfe16eSGreg Kroah-Hartman } 109*44bfe16eSGreg Kroah-Hartman 110*44bfe16eSGreg Kroah-Hartman /* 111*44bfe16eSGreg Kroah-Hartman * The "foo" file where the .foo variable is read from and written to. 112*44bfe16eSGreg Kroah-Hartman */ 113*44bfe16eSGreg Kroah-Hartman static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr, 114*44bfe16eSGreg Kroah-Hartman char *buf) 115*44bfe16eSGreg Kroah-Hartman { 116*44bfe16eSGreg Kroah-Hartman return sprintf(buf, "%d\n", foo_obj->foo); 117*44bfe16eSGreg Kroah-Hartman } 118*44bfe16eSGreg Kroah-Hartman 119*44bfe16eSGreg Kroah-Hartman static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr, 120*44bfe16eSGreg Kroah-Hartman const char *buf, size_t count) 121*44bfe16eSGreg Kroah-Hartman { 122*44bfe16eSGreg Kroah-Hartman sscanf(buf, "%du", &foo_obj->foo); 123*44bfe16eSGreg Kroah-Hartman return count; 124*44bfe16eSGreg Kroah-Hartman } 125*44bfe16eSGreg Kroah-Hartman 126*44bfe16eSGreg Kroah-Hartman static struct foo_attribute foo_attribute = 127*44bfe16eSGreg Kroah-Hartman __ATTR(foo, 0666, foo_show, foo_store); 128*44bfe16eSGreg Kroah-Hartman 129*44bfe16eSGreg Kroah-Hartman /* 130*44bfe16eSGreg Kroah-Hartman * More complex function where we determine which varible is being accessed by 131*44bfe16eSGreg Kroah-Hartman * looking at the attribute for the "baz" and "bar" files. 132*44bfe16eSGreg Kroah-Hartman */ 133*44bfe16eSGreg Kroah-Hartman static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr, 134*44bfe16eSGreg Kroah-Hartman char *buf) 135*44bfe16eSGreg Kroah-Hartman { 136*44bfe16eSGreg Kroah-Hartman int var; 137*44bfe16eSGreg Kroah-Hartman 138*44bfe16eSGreg Kroah-Hartman if (strcmp(attr->attr.name, "baz") == 0) 139*44bfe16eSGreg Kroah-Hartman var = foo_obj->baz; 140*44bfe16eSGreg Kroah-Hartman else 141*44bfe16eSGreg Kroah-Hartman var = foo_obj->bar; 142*44bfe16eSGreg Kroah-Hartman return sprintf(buf, "%d\n", var); 143*44bfe16eSGreg Kroah-Hartman } 144*44bfe16eSGreg Kroah-Hartman 145*44bfe16eSGreg Kroah-Hartman static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr, 146*44bfe16eSGreg Kroah-Hartman const char *buf, size_t count) 147*44bfe16eSGreg Kroah-Hartman { 148*44bfe16eSGreg Kroah-Hartman int var; 149*44bfe16eSGreg Kroah-Hartman 150*44bfe16eSGreg Kroah-Hartman sscanf(buf, "%du", &var); 151*44bfe16eSGreg Kroah-Hartman if (strcmp(attr->attr.name, "baz") == 0) 152*44bfe16eSGreg Kroah-Hartman foo_obj->baz = var; 153*44bfe16eSGreg Kroah-Hartman else 154*44bfe16eSGreg Kroah-Hartman foo_obj->bar = var; 155*44bfe16eSGreg Kroah-Hartman return count; 156*44bfe16eSGreg Kroah-Hartman } 157*44bfe16eSGreg Kroah-Hartman 158*44bfe16eSGreg Kroah-Hartman static struct foo_attribute baz_attribute = 159*44bfe16eSGreg Kroah-Hartman __ATTR(baz, 0666, b_show, b_store); 160*44bfe16eSGreg Kroah-Hartman static struct foo_attribute bar_attribute = 161*44bfe16eSGreg Kroah-Hartman __ATTR(bar, 0666, b_show, b_store); 162*44bfe16eSGreg Kroah-Hartman 163*44bfe16eSGreg Kroah-Hartman /* 164*44bfe16eSGreg Kroah-Hartman * Create a group of attributes so that we can create and destory them all 165*44bfe16eSGreg Kroah-Hartman * at once. 166*44bfe16eSGreg Kroah-Hartman */ 167*44bfe16eSGreg Kroah-Hartman static struct attribute *foo_default_attrs[] = { 168*44bfe16eSGreg Kroah-Hartman &foo_attribute.attr, 169*44bfe16eSGreg Kroah-Hartman &baz_attribute.attr, 170*44bfe16eSGreg Kroah-Hartman &bar_attribute.attr, 171*44bfe16eSGreg Kroah-Hartman NULL, /* need to NULL terminate the list of attributes */ 172*44bfe16eSGreg Kroah-Hartman }; 173*44bfe16eSGreg Kroah-Hartman 174*44bfe16eSGreg Kroah-Hartman /* 175*44bfe16eSGreg Kroah-Hartman * Our own ktype for our kobjects. Here we specify our sysfs ops, the 176*44bfe16eSGreg Kroah-Hartman * release function, and the set of default attributes we want created 177*44bfe16eSGreg Kroah-Hartman * whenever a kobject of this type is registered with the kernel. 178*44bfe16eSGreg Kroah-Hartman */ 179*44bfe16eSGreg Kroah-Hartman static struct kobj_type foo_ktype = { 180*44bfe16eSGreg Kroah-Hartman .sysfs_ops = &foo_sysfs_ops, 181*44bfe16eSGreg Kroah-Hartman .release = foo_release, 182*44bfe16eSGreg Kroah-Hartman .default_attrs = foo_default_attrs, 183*44bfe16eSGreg Kroah-Hartman }; 184*44bfe16eSGreg Kroah-Hartman 185*44bfe16eSGreg Kroah-Hartman static struct kset *example_kset; 186*44bfe16eSGreg Kroah-Hartman static struct foo_obj *foo_obj; 187*44bfe16eSGreg Kroah-Hartman static struct foo_obj *bar_obj; 188*44bfe16eSGreg Kroah-Hartman static struct foo_obj *baz_obj; 189*44bfe16eSGreg Kroah-Hartman 190*44bfe16eSGreg Kroah-Hartman static struct foo_obj *create_foo_obj(const char *name) 191*44bfe16eSGreg Kroah-Hartman { 192*44bfe16eSGreg Kroah-Hartman struct foo_obj *foo; 193*44bfe16eSGreg Kroah-Hartman int retval; 194*44bfe16eSGreg Kroah-Hartman 195*44bfe16eSGreg Kroah-Hartman /* allocate the memory for the whole object */ 196*44bfe16eSGreg Kroah-Hartman foo = kzalloc(sizeof(*foo), GFP_KERNEL); 197*44bfe16eSGreg Kroah-Hartman if (!foo) 198*44bfe16eSGreg Kroah-Hartman return NULL; 199*44bfe16eSGreg Kroah-Hartman 200*44bfe16eSGreg Kroah-Hartman /* 201*44bfe16eSGreg Kroah-Hartman * As we have a kset for this kobject, we need to set it before calling 202*44bfe16eSGreg Kroah-Hartman * the kobject core. 203*44bfe16eSGreg Kroah-Hartman */ 204*44bfe16eSGreg Kroah-Hartman foo->kobj.kset = example_kset; 205*44bfe16eSGreg Kroah-Hartman 206*44bfe16eSGreg Kroah-Hartman /* 207*44bfe16eSGreg Kroah-Hartman * Initialize and add the kobject to the kernel. All the default files 208*44bfe16eSGreg Kroah-Hartman * will be created here. As we have already specified a kset for this 209*44bfe16eSGreg Kroah-Hartman * kobject, we don't have to set a parent for the kobject, the kobject 210*44bfe16eSGreg Kroah-Hartman * will be placed beneath that kset automatically. 211*44bfe16eSGreg Kroah-Hartman */ 212*44bfe16eSGreg Kroah-Hartman retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name); 213*44bfe16eSGreg Kroah-Hartman if (retval) { 214*44bfe16eSGreg Kroah-Hartman kfree(foo); 215*44bfe16eSGreg Kroah-Hartman return NULL; 216*44bfe16eSGreg Kroah-Hartman } 217*44bfe16eSGreg Kroah-Hartman 218*44bfe16eSGreg Kroah-Hartman /* 219*44bfe16eSGreg Kroah-Hartman * We are always responsible for sending the uevent that the kobject 220*44bfe16eSGreg Kroah-Hartman * was added to the system. 221*44bfe16eSGreg Kroah-Hartman */ 222*44bfe16eSGreg Kroah-Hartman kobject_uevent(&foo->kobj, KOBJ_ADD); 223*44bfe16eSGreg Kroah-Hartman 224*44bfe16eSGreg Kroah-Hartman return foo; 225*44bfe16eSGreg Kroah-Hartman } 226*44bfe16eSGreg Kroah-Hartman 227*44bfe16eSGreg Kroah-Hartman static void destroy_foo_obj(struct foo_obj *foo) 228*44bfe16eSGreg Kroah-Hartman { 229*44bfe16eSGreg Kroah-Hartman kobject_put(&foo->kobj); 230*44bfe16eSGreg Kroah-Hartman } 231*44bfe16eSGreg Kroah-Hartman 232*44bfe16eSGreg Kroah-Hartman static int example_init(void) 233*44bfe16eSGreg Kroah-Hartman { 234*44bfe16eSGreg Kroah-Hartman /* 235*44bfe16eSGreg Kroah-Hartman * Create a kset with the name of "kset_example", 236*44bfe16eSGreg Kroah-Hartman * located under /sys/kernel/ 237*44bfe16eSGreg Kroah-Hartman */ 238*44bfe16eSGreg Kroah-Hartman example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj); 239*44bfe16eSGreg Kroah-Hartman if (!example_kset) 240*44bfe16eSGreg Kroah-Hartman return -ENOMEM; 241*44bfe16eSGreg Kroah-Hartman 242*44bfe16eSGreg Kroah-Hartman /* 243*44bfe16eSGreg Kroah-Hartman * Create three objects and register them with our kset 244*44bfe16eSGreg Kroah-Hartman */ 245*44bfe16eSGreg Kroah-Hartman foo_obj = create_foo_obj("foo"); 246*44bfe16eSGreg Kroah-Hartman if (!foo_obj) 247*44bfe16eSGreg Kroah-Hartman goto foo_error; 248*44bfe16eSGreg Kroah-Hartman 249*44bfe16eSGreg Kroah-Hartman bar_obj = create_foo_obj("bar"); 250*44bfe16eSGreg Kroah-Hartman if (!bar_obj) 251*44bfe16eSGreg Kroah-Hartman goto bar_error; 252*44bfe16eSGreg Kroah-Hartman 253*44bfe16eSGreg Kroah-Hartman baz_obj = create_foo_obj("baz"); 254*44bfe16eSGreg Kroah-Hartman if (!baz_obj) 255*44bfe16eSGreg Kroah-Hartman goto baz_error; 256*44bfe16eSGreg Kroah-Hartman 257*44bfe16eSGreg Kroah-Hartman return 0; 258*44bfe16eSGreg Kroah-Hartman 259*44bfe16eSGreg Kroah-Hartman baz_error: 260*44bfe16eSGreg Kroah-Hartman destroy_foo_obj(bar_obj); 261*44bfe16eSGreg Kroah-Hartman bar_error: 262*44bfe16eSGreg Kroah-Hartman destroy_foo_obj(foo_obj); 263*44bfe16eSGreg Kroah-Hartman foo_error: 264*44bfe16eSGreg Kroah-Hartman return -EINVAL; 265*44bfe16eSGreg Kroah-Hartman } 266*44bfe16eSGreg Kroah-Hartman 267*44bfe16eSGreg Kroah-Hartman static void example_exit(void) 268*44bfe16eSGreg Kroah-Hartman { 269*44bfe16eSGreg Kroah-Hartman destroy_foo_obj(baz_obj); 270*44bfe16eSGreg Kroah-Hartman destroy_foo_obj(bar_obj); 271*44bfe16eSGreg Kroah-Hartman destroy_foo_obj(foo_obj); 272*44bfe16eSGreg Kroah-Hartman kset_unregister(example_kset); 273*44bfe16eSGreg Kroah-Hartman } 274*44bfe16eSGreg Kroah-Hartman 275*44bfe16eSGreg Kroah-Hartman module_init(example_init); 276*44bfe16eSGreg Kroah-Hartman module_exit(example_exit); 277*44bfe16eSGreg Kroah-Hartman MODULE_LICENSE("GPL"); 278*44bfe16eSGreg Kroah-Hartman MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>"); 279