Blame view

samples/kobject/kset-example.c 6.94 KB
44bfe16e1   Greg Kroah-Hartman   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   Tejun Heo   include cleanup: ...
13
  #include <linux/slab.h>
44bfe16e1   Greg Kroah-Hartman   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   Emese Revfy   Driver core: Cons...
91
  static const struct sysfs_ops foo_sysfs_ops = {
44bfe16e1   Greg Kroah-Hartman   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   Rastislav Barlik   samples/kobject: ...
124
125
126
127
128
  	int ret;
  
  	ret = kstrtoint(buf, 10, &foo_obj->foo);
  	if (ret < 0)
  		return ret;
44bfe16e1   Greg Kroah-Hartman   kobject: add samp...
129
130
  	return count;
  }
de5109898   Rusty Russell   samples/kobject/:...
131
  /* Sysfs attributes cannot be world-writable. */
44bfe16e1   Greg Kroah-Hartman   kobject: add samp...
132
  static struct foo_attribute foo_attribute =
de5109898   Rusty Russell   samples/kobject/:...
133
  	__ATTR(foo, 0664, foo_show, foo_store);
44bfe16e1   Greg Kroah-Hartman   kobject: add samp...
134
135
  
  /*
20ef9f46a   Radu Voicilas   kset-example: Spe...
136
   * More complex function where we determine which variable is being accessed by
44bfe16e1   Greg Kroah-Hartman   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   Rastislav Barlik   samples/kobject: ...
155
156
157
158
159
  	int var, ret;
  
  	ret = kstrtoint(buf, 10, &var);
  	if (ret < 0)
  		return ret;
44bfe16e1   Greg Kroah-Hartman   kobject: add samp...
160

44bfe16e1   Greg Kroah-Hartman   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   Rusty Russell   samples/kobject/:...
169
  	__ATTR(baz, 0664, b_show, b_store);
44bfe16e1   Greg Kroah-Hartman   kobject: add samp...
170
  static struct foo_attribute bar_attribute =
de5109898   Rusty Russell   samples/kobject/:...
171
  	__ATTR(bar, 0664, b_show, b_store);
44bfe16e1   Greg Kroah-Hartman   kobject: add samp...
172
173
  
  /*
20ef9f46a   Radu Voicilas   kset-example: Spe...
174
   * Create a group of attributes so that we can create and destroy them all
44bfe16e1   Greg Kroah-Hartman   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   Li Zefan   kobject: should u...
224
  		kobject_put(&foo->kobj);
44bfe16e1   Greg Kroah-Hartman   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   Qinghuang Feng   samples: mark {st...
241
  static int __init example_init(void)
44bfe16e1   Greg Kroah-Hartman   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   Bjorn Helgaas   kobject: fix kset...
273
  	kset_unregister(example_kset);
44bfe16e1   Greg Kroah-Hartman   kobject: add samp...
274
275
  	return -EINVAL;
  }
7ec7fb394   Qinghuang Feng   samples: mark {st...
276
  static void __exit example_exit(void)
44bfe16e1   Greg Kroah-Hartman   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   Greg Kroah-Hartman   samples/kobject: ...
286
  MODULE_LICENSE("GPL v2");
44bfe16e1   Greg Kroah-Hartman   kobject: add samp...
287
  MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");