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