1
2
3
4
5
6
7
8
9
10#include <linux/kobject.h>
11#include <linux/string.h>
12#include <linux/sysfs.h>
13#include <linux/module.h>
14#include <linux/init.h>
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30struct foo_obj {
31 struct kobject kobj;
32 int foo;
33 int baz;
34 int bar;
35};
36#define to_foo_obj(x) container_of(x, struct foo_obj, kobj)
37
38
39struct foo_attribute {
40 struct attribute attr;
41 ssize_t (*show)(struct foo_obj *foo, struct foo_attribute *attr, char *buf);
42 ssize_t (*store)(struct foo_obj *foo, struct foo_attribute *attr, const char *buf, size_t count);
43};
44#define to_foo_attr(x) container_of(x, struct foo_attribute, attr)
45
46
47
48
49
50
51
52
53static ssize_t foo_attr_show(struct kobject *kobj,
54 struct attribute *attr,
55 char *buf)
56{
57 struct foo_attribute *attribute;
58 struct foo_obj *foo;
59
60 attribute = to_foo_attr(attr);
61 foo = to_foo_obj(kobj);
62
63 if (!attribute->show)
64 return -EIO;
65
66 return attribute->show(foo, attribute, buf);
67}
68
69
70
71
72
73static ssize_t foo_attr_store(struct kobject *kobj,
74 struct attribute *attr,
75 const char *buf, size_t len)
76{
77 struct foo_attribute *attribute;
78 struct foo_obj *foo;
79
80 attribute = to_foo_attr(attr);
81 foo = to_foo_obj(kobj);
82
83 if (!attribute->store)
84 return -EIO;
85
86 return attribute->store(foo, attribute, buf, len);
87}
88
89
90static struct sysfs_ops foo_sysfs_ops = {
91 .show = foo_attr_show,
92 .store = foo_attr_store,
93};
94
95
96
97
98
99
100
101
102static void foo_release(struct kobject *kobj)
103{
104 struct foo_obj *foo;
105
106 foo = to_foo_obj(kobj);
107 kfree(foo);
108}
109
110
111
112
113static ssize_t foo_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
114 char *buf)
115{
116 return sprintf(buf, "%d\n", foo_obj->foo);
117}
118
119static ssize_t foo_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
120 const char *buf, size_t count)
121{
122 sscanf(buf, "%du", &foo_obj->foo);
123 return count;
124}
125
126static struct foo_attribute foo_attribute =
127 __ATTR(foo, 0666, foo_show, foo_store);
128
129
130
131
132
133static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
134 char *buf)
135{
136 int var;
137
138 if (strcmp(attr->attr.name, "baz") == 0)
139 var = foo_obj->baz;
140 else
141 var = foo_obj->bar;
142 return sprintf(buf, "%d\n", var);
143}
144
145static ssize_t b_store(struct foo_obj *foo_obj, struct foo_attribute *attr,
146 const char *buf, size_t count)
147{
148 int var;
149
150 sscanf(buf, "%du", &var);
151 if (strcmp(attr->attr.name, "baz") == 0)
152 foo_obj->baz = var;
153 else
154 foo_obj->bar = var;
155 return count;
156}
157
158static struct foo_attribute baz_attribute =
159 __ATTR(baz, 0666, b_show, b_store);
160static struct foo_attribute bar_attribute =
161 __ATTR(bar, 0666, b_show, b_store);
162
163
164
165
166
167static struct attribute *foo_default_attrs[] = {
168 &foo_attribute.attr,
169 &baz_attribute.attr,
170 &bar_attribute.attr,
171 NULL,
172};
173
174
175
176
177
178
179static struct kobj_type foo_ktype = {
180 .sysfs_ops = &foo_sysfs_ops,
181 .release = foo_release,
182 .default_attrs = foo_default_attrs,
183};
184
185static struct kset *example_kset;
186static struct foo_obj *foo_obj;
187static struct foo_obj *bar_obj;
188static struct foo_obj *baz_obj;
189
190static struct foo_obj *create_foo_obj(const char *name)
191{
192 struct foo_obj *foo;
193 int retval;
194
195
196 foo = kzalloc(sizeof(*foo), GFP_KERNEL);
197 if (!foo)
198 return NULL;
199
200
201
202
203
204 foo->kobj.kset = example_kset;
205
206
207
208
209
210
211
212 retval = kobject_init_and_add(&foo->kobj, &foo_ktype, NULL, "%s", name);
213 if (retval) {
214 kobject_put(&foo->kobj);
215 return NULL;
216 }
217
218
219
220
221
222 kobject_uevent(&foo->kobj, KOBJ_ADD);
223
224 return foo;
225}
226
227static void destroy_foo_obj(struct foo_obj *foo)
228{
229 kobject_put(&foo->kobj);
230}
231
232static int __init example_init(void)
233{
234
235
236
237
238 example_kset = kset_create_and_add("kset_example", NULL, kernel_kobj);
239 if (!example_kset)
240 return -ENOMEM;
241
242
243
244
245 foo_obj = create_foo_obj("foo");
246 if (!foo_obj)
247 goto foo_error;
248
249 bar_obj = create_foo_obj("bar");
250 if (!bar_obj)
251 goto bar_error;
252
253 baz_obj = create_foo_obj("baz");
254 if (!baz_obj)
255 goto baz_error;
256
257 return 0;
258
259baz_error:
260 destroy_foo_obj(bar_obj);
261bar_error:
262 destroy_foo_obj(foo_obj);
263foo_error:
264 return -EINVAL;
265}
266
267static void __exit example_exit(void)
268{
269 destroy_foo_obj(baz_obj);
270 destroy_foo_obj(bar_obj);
271 destroy_foo_obj(foo_obj);
272 kset_unregister(example_kset);
273}
274
275module_init(example_init);
276module_exit(example_exit);
277MODULE_LICENSE("GPL");
278MODULE_AUTHOR("Greg Kroah-Hartman <greg@kroah.com>");
279