Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
462 giacomo 1
/*
2
 * class.c - basic device class management
3
 *
4
 * Copyright (c) 2002-3 Patrick Mochel
5
 * Copyright (c) 2002-3 Open Source Development Labs
6
 * Copyright (c) 2003 Greg Kroah-Hartman
7
 * Copyright (c) 2003 IBM Corp.
8
 *
9
 * This file is released under the GPLv2
10
 *
11
 */
12
 
13
#undef DEBUG
14
 
15
#include <linuxcomp.h>
16
 
17
#include <linux/device.h>
18
#include <linux/module.h>
19
#include <linux/init.h>
20
#include <linux/string.h>
21
#include "base.h"
22
 
23
#define to_class_attr(_attr) container_of(_attr,struct class_attribute,attr)
24
#define to_class(obj) container_of(obj,struct class,subsys.kset.kobj)
25
 
26
static ssize_t
27
class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
28
{
29
	struct class_attribute * class_attr = to_class_attr(attr);
30
	struct class * dc = to_class(kobj);
31
	ssize_t ret = 0;
32
 
33
	if (class_attr->show)
34
		ret = class_attr->show(dc,buf);
35
	return ret;
36
}
37
 
38
static ssize_t
39
class_attr_store(struct kobject * kobj, struct attribute * attr,
40
		 const char * buf, size_t count)
41
{
42
	struct class_attribute * class_attr = to_class_attr(attr);
43
	struct class * dc = to_class(kobj);
44
	ssize_t ret = 0;
45
 
46
	if (class_attr->store)
47
		ret = class_attr->store(dc,buf,count);
48
	return ret;
49
}
50
 
51
static struct sysfs_ops class_sysfs_ops = {
52
	.show	= class_attr_show,
53
	.store	= class_attr_store,
54
};
55
 
56
static struct kobj_type ktype_class = {
57
	.sysfs_ops	= &class_sysfs_ops,
58
};
59
 
60
/* Hotplug events for classes go to the class_obj subsys */
61
static decl_subsys(class,&ktype_class,NULL);
62
 
63
 
64
int class_create_file(struct class * cls, const struct class_attribute * attr)
65
{
66
	int error;
67
	if (cls) {
68
		error = 0;//sysfs_create_file(&cls->subsys.kset.kobj,&attr->attr);
69
	} else
70
		error = -EINVAL;
71
	return error;
72
}
73
 
74
void class_remove_file(struct class * cls, const struct class_attribute * attr)
75
{
76
	//if (cls)
77
	//	sysfs_remove_file(&cls->subsys.kset.kobj,&attr->attr);
78
}
79
 
80
struct class * class_get(struct class * cls)
81
{
82
	if (cls)
83
		return container_of(subsys_get(&cls->subsys),struct class,subsys);
84
	return NULL;
85
}
86
 
87
void class_put(struct class * cls)
88
{
89
	subsys_put(&cls->subsys);
90
}
91
 
92
int class_register(struct class * cls)
93
{
94
	pr_debug("device class '%s': registering\n",cls->name);
95
 
96
	INIT_LIST_HEAD(&cls->children);
97
	INIT_LIST_HEAD(&cls->interfaces);
98
	kobject_set_name(&cls->subsys.kset.kobj,cls->name);
99
	subsys_set_kset(cls,class_subsys);
100
	subsystem_register(&cls->subsys);
101
 
102
	return 0;
103
}
104
 
105
void class_unregister(struct class * cls)
106
{
107
	pr_debug("device class '%s': unregistering\n",cls->name);
108
	subsystem_unregister(&cls->subsys);
109
}
110
 
111
/* Class Device Stuff */
112
 
113
int class_device_create_file(struct class_device * class_dev,
114
			     const struct class_device_attribute * attr)
115
{
116
	int error = -EINVAL;
117
	if (class_dev)
118
		error = 0;//sysfs_create_file(&class_dev->kobj, &attr->attr);
119
	return error;
120
}
121
 
122
void class_device_remove_file(struct class_device * class_dev,
123
			      const struct class_device_attribute * attr)
124
{
125
	//if (class_dev)
126
	//	sysfs_remove_file(&class_dev->kobj, &attr->attr);
127
}
128
 
129
static int class_device_dev_link(struct class_device * class_dev)
130
{
131
	//if (class_dev->dev)
132
	//	return sysfs_create_link(&class_dev->kobj,
133
	//				 &class_dev->dev->kobj, "device");
134
	return 0;
135
}
136
 
137
static void class_device_dev_unlink(struct class_device * class_dev)
138
{
139
	//if (class_dev->dev)
140
	//	sysfs_remove_link(&class_dev->kobj, "device");
141
}
142
 
143
static int class_device_driver_link(struct class_device * class_dev)
144
{
145
	//if ((class_dev->dev) && (class_dev->dev->driver))
146
	//	return sysfs_create_link(&class_dev->kobj,
147
	//				 &class_dev->dev->driver->kobj, "driver");
148
	return 0;
149
}
150
 
151
static void class_device_driver_unlink(struct class_device * class_dev)
152
{
153
	//if ((class_dev->dev) && (class_dev->dev->driver))
154
	//	sysfs_remove_link(&class_dev->kobj, "driver");
155
}
156
 
157
 
158
static ssize_t
159
class_device_attr_show(struct kobject * kobj, struct attribute * attr,
160
		       char * buf)
161
{
162
	struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
163
	struct class_device * cd = to_class_dev(kobj);
164
	ssize_t ret = 0;
165
 
166
	if (class_dev_attr->show)
167
		ret = class_dev_attr->show(cd,buf);
168
	return ret;
169
}
170
 
171
static ssize_t
172
class_device_attr_store(struct kobject * kobj, struct attribute * attr,
173
			const char * buf, size_t count)
174
{
175
	struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
176
	struct class_device * cd = to_class_dev(kobj);
177
	ssize_t ret = 0;
178
 
179
	if (class_dev_attr->store)
180
		ret = class_dev_attr->store(cd,buf,count);
181
	return ret;
182
}
183
 
184
static struct sysfs_ops class_dev_sysfs_ops = {
185
	.show	= class_device_attr_show,
186
	.store	= class_device_attr_store,
187
};
188
 
189
static void class_dev_release(struct kobject * kobj)
190
{
191
	struct class_device *cd = to_class_dev(kobj);
192
	struct class * cls = cd->class;
193
 
194
	pr_debug("device class '%s': release.\n",cd->class_id);
195
 
196
	if (cls->release)
197
		cls->release(cd);
198
	else {
199
		printk(KERN_ERR "Device class '%s' does not have a release() function, "
200
			"it is broken and must be fixed.\n",
201
			cd->class_id);
202
		WARN_ON(1);
203
	}
204
}
205
 
206
static struct kobj_type ktype_class_device = {
207
	.sysfs_ops	= &class_dev_sysfs_ops,
208
	.release	= class_dev_release,
209
};
210
 
211
static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
212
{
213
	struct kobj_type *ktype = get_ktype(kobj);
214
 
215
	if (ktype == &ktype_class_device) {
216
		struct class_device *class_dev = to_class_dev(kobj);
217
		if (class_dev->class)
218
			return 1;
219
	}
220
	return 0;
221
}
222
 
223
static char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
224
{
225
	struct class_device *class_dev = to_class_dev(kobj);
226
 
227
	return class_dev->class->name;
228
}
229
 
230
static int class_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
231
			 int num_envp, char *buffer, int buffer_size)
232
{
233
	struct class_device *class_dev = to_class_dev(kobj);
234
	int retval = 0;
235
 
236
	pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
237
	if (class_dev->class->hotplug) {
238
		/* have the bus specific function add its stuff */
239
		retval = class_dev->class->hotplug (class_dev, envp, num_envp,
240
						    buffer, buffer_size);
241
			if (retval) {
242
			pr_debug ("%s - hotplug() returned %d\n",
243
				  __FUNCTION__, retval);
244
		}
245
	}
246
 
247
	return retval;
248
}
249
 
250
static struct kset_hotplug_ops class_hotplug_ops = {
251
	.filter =	class_hotplug_filter,
252
	.name =		class_hotplug_name,
253
	.hotplug =	class_hotplug,
254
};
255
 
256
static decl_subsys(class_obj, &ktype_class_device, &class_hotplug_ops);
257
 
258
void class_device_initialize(struct class_device *class_dev)
259
{
260
	kobj_set_kset_s(class_dev, class_obj_subsys);
261
	kobject_init(&class_dev->kobj);
262
	INIT_LIST_HEAD(&class_dev->node);
263
}
264
 
265
int class_device_add(struct class_device *class_dev)
266
{
267
	struct class * parent;
268
	struct class_interface * class_intf;
269
	struct list_head * entry;
270
	int error;
271
 
272
	class_dev = class_device_get(class_dev);
273
	if (!class_dev || !strlen(class_dev->class_id))
274
		return -EINVAL;
275
 
276
	parent = class_get(class_dev->class);
277
 
278
	pr_debug("CLASS: registering class device: ID = '%s'\n",
279
		 class_dev->class_id);
280
 
281
	/* first, register with generic layer. */
282
	kobject_set_name(&class_dev->kobj, class_dev->class_id);
283
	if (parent)
284
		class_dev->kobj.parent = &parent->subsys.kset.kobj;
285
 
286
	if ((error = kobject_add(&class_dev->kobj)))
287
		goto register_done;
288
 
289
	/* now take care of our own registration */
290
	if (parent) {
291
		//down_write(&parent->subsys.rwsem);
292
		list_add_tail(&class_dev->node, &parent->children);
293
		list_for_each(entry, &parent->interfaces) {
294
			class_intf = container_of(entry, struct class_interface, node);
295
			if (class_intf->add)
296
				class_intf->add(class_dev);
297
		}
298
		//up_write(&parent->subsys.rwsem);
299
	}
300
 
301
	class_device_dev_link(class_dev);
302
	class_device_driver_link(class_dev);
303
 
304
 register_done:
305
	if (error && parent)
306
		class_put(parent);
307
	class_device_put(class_dev);
308
	return error;
309
}
310
 
311
int class_device_register(struct class_device *class_dev)
312
{
313
	class_device_initialize(class_dev);
314
	return class_device_add(class_dev);
315
}
316
 
317
void class_device_del(struct class_device *class_dev)
318
{
319
	struct class * parent = class_dev->class;
320
	struct class_interface * class_intf;
321
	struct list_head * entry;
322
 
323
	if (parent) {
324
		//down_write(&parent->subsys.rwsem);
325
		list_del_init(&class_dev->node);
326
		list_for_each(entry, &parent->interfaces) {
327
			class_intf = container_of(entry, struct class_interface, node);
328
			if (class_intf->remove)
329
				class_intf->remove(class_dev);
330
		}
331
		//up_write(&parent->subsys.rwsem);
332
	}
333
 
334
	class_device_dev_unlink(class_dev);
335
	class_device_driver_unlink(class_dev);
336
 
337
	kobject_del(&class_dev->kobj);
338
 
339
	if (parent)
340
		class_put(parent);
341
}
342
 
343
void class_device_unregister(struct class_device *class_dev)
344
{
345
	pr_debug("CLASS: Unregistering class device. ID = '%s'\n",
346
		 class_dev->class_id);
347
	class_device_del(class_dev);
348
	class_device_put(class_dev);
349
}
350
 
351
int class_device_rename(struct class_device *class_dev, char *new_name)
352
{
353
	class_dev = class_device_get(class_dev);
354
	if (!class_dev)
355
		return -EINVAL;
356
 
357
	pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id,
358
		 new_name);
359
 
360
	strncpy(class_dev->class_id, new_name, KOBJ_NAME_LEN);
361
 
362
	kobject_rename(&class_dev->kobj, new_name);
363
 
364
	class_device_put(class_dev);
365
 
366
	return 0;
367
}
368
 
369
struct class_device * class_device_get(struct class_device *class_dev)
370
{
371
	if (class_dev)
372
		return to_class_dev(kobject_get(&class_dev->kobj));
373
	return NULL;
374
}
375
 
376
void class_device_put(struct class_device *class_dev)
377
{
378
	kobject_put(&class_dev->kobj);
379
}
380
 
381
 
382
int class_interface_register(struct class_interface *class_intf)
383
{
384
	struct class * parent;
385
	struct class_device * class_dev;
386
	struct list_head * entry;
387
 
388
	if (!class_intf || !class_intf->class)
389
		return -ENODEV;
390
 
391
	parent = class_get(class_intf->class);
392
	if (!parent)
393
		return -EINVAL;
394
 
395
	//down_write(&parent->subsys.rwsem);
396
	list_add_tail(&class_intf->node, &parent->interfaces);
397
 
398
	if (class_intf->add) {
399
		list_for_each(entry, &parent->children) {
400
			class_dev = container_of(entry, struct class_device, node);
401
			class_intf->add(class_dev);
402
		}
403
	}
404
	//up_write(&parent->subsys.rwsem);
405
 
406
	return 0;
407
}
408
 
409
void class_interface_unregister(struct class_interface *class_intf)
410
{
411
	struct class * parent = class_intf->class;
412
	struct list_head * entry;
413
 
414
	if (!parent)
415
		return;
416
 
417
	//down_write(&parent->subsys.rwsem);
418
	list_del_init(&class_intf->node);
419
 
420
	if (class_intf->remove) {
421
		list_for_each(entry, &parent->children) {
422
			struct class_device *class_dev = container_of(entry, struct class_device, node);
423
			class_intf->remove(class_dev);
424
		}
425
	}
426
	//up_write(&parent->subsys.rwsem);
427
 
428
	class_put(parent);
429
}
430
 
431
 
432
 
433
int __init classes_init(void)
434
{
435
	int retval;
436
 
437
	retval = subsystem_register(&class_subsys);
438
	if (retval)
439
		return retval;
440
 
441
	/* ick, this is ugly, the things we go through to keep from showing up
442
	 * in sysfs... */
443
	subsystem_init(&class_obj_subsys);
444
	if (!class_obj_subsys.kset.subsys)
445
			class_obj_subsys.kset.subsys = &class_obj_subsys;
446
	return 0;
447
}
448
 
449
EXPORT_SYMBOL(class_create_file);
450
EXPORT_SYMBOL(class_remove_file);
451
EXPORT_SYMBOL(class_register);
452
EXPORT_SYMBOL(class_unregister);
453
EXPORT_SYMBOL(class_get);
454
EXPORT_SYMBOL(class_put);
455
 
456
EXPORT_SYMBOL(class_device_register);
457
EXPORT_SYMBOL(class_device_unregister);
458
EXPORT_SYMBOL(class_device_initialize);
459
EXPORT_SYMBOL(class_device_add);
460
EXPORT_SYMBOL(class_device_del);
461
EXPORT_SYMBOL(class_device_get);
462
EXPORT_SYMBOL(class_device_put);
463
EXPORT_SYMBOL(class_device_create_file);
464
EXPORT_SYMBOL(class_device_remove_file);
465
 
466
EXPORT_SYMBOL(class_interface_register);
467
EXPORT_SYMBOL(class_interface_unregister);