vserver 1.9.5.x5
[linux-2.6.git] / drivers / base / class_simple.c
1 /*
2  * class_simple.c - a "simple" interface for classes for simple char devices.
3  *
4  * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
5  * Copyright (c) 2003-2004 IBM Corp.
6  *
7  * This file is released under the GPLv2
8  *
9  */
10
11 #include <linux/config.h>
12 #include <linux/device.h>
13 #include <linux/kdev_t.h>
14 #include <linux/err.h>
15
16 struct class_simple {
17         struct class_device_attribute attr;
18         struct class class;
19 };
20 #define to_class_simple(d) container_of(d, struct class_simple, class)
21
22 struct simple_dev {
23         struct list_head node;
24         dev_t dev;
25         struct class_device class_dev;
26 };
27 #define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
28
29 static LIST_HEAD(simple_dev_list);
30 static DEFINE_SPINLOCK(simple_dev_list_lock);
31
32 static void release_simple_dev(struct class_device *class_dev)
33 {
34         struct simple_dev *s_dev = to_simple_dev(class_dev);
35         kfree(s_dev);
36 }
37
38 static ssize_t show_dev(struct class_device *class_dev, char *buf)
39 {
40         struct simple_dev *s_dev = to_simple_dev(class_dev);
41         return print_dev_t(buf, s_dev->dev);
42 }
43
44 static void class_simple_release(struct class *class)
45 {
46         struct class_simple *cs = to_class_simple(class);
47         kfree(cs);
48 }
49
50 /**
51  * class_simple_create - create a struct class_simple structure
52  * @owner: pointer to the module that is to "own" this struct class_simple
53  * @name: pointer to a string for the name of this class.
54  *
55  * This is used to create a struct class_simple pointer that can then be used
56  * in calls to class_simple_device_add().  This is used when you do not wish to
57  * create a full blown class support for a type of char devices.
58  *
59  * Note, the pointer created here is to be destroyed when finished by making a
60  * call to class_simple_destroy().
61  */
62 struct class_simple *class_simple_create(struct module *owner, char *name)
63 {
64         struct class_simple *cs;
65         int retval;
66
67         cs = kmalloc(sizeof(*cs), GFP_KERNEL);
68         if (!cs) {
69                 retval = -ENOMEM;
70                 goto error;
71         }
72         memset(cs, 0x00, sizeof(*cs));
73
74         cs->class.name = name;
75         cs->class.class_release = class_simple_release;
76         cs->class.release = release_simple_dev;
77
78         cs->attr.attr.name = "dev";
79         cs->attr.attr.mode = S_IRUGO;
80         cs->attr.attr.owner = owner;
81         cs->attr.show = show_dev;
82         cs->attr.store = NULL;
83
84         retval = class_register(&cs->class);
85         if (retval)
86                 goto error;
87
88         return cs;
89
90 error:
91         kfree(cs);
92         return ERR_PTR(retval);
93 }
94 EXPORT_SYMBOL(class_simple_create);
95
96 /**
97  * class_simple_destroy - destroys a struct class_simple structure
98  * @cs: pointer to the struct class_simple that is to be destroyed
99  *
100  * Note, the pointer to be destroyed must have been created with a call to
101  * class_simple_create().
102  */
103 void class_simple_destroy(struct class_simple *cs)
104 {
105         if ((cs == NULL) || (IS_ERR(cs)))
106                 return;
107
108         class_unregister(&cs->class);
109 }
110 EXPORT_SYMBOL(class_simple_destroy);
111
112 /**
113  * class_simple_device_add - adds a class device to sysfs for a character driver
114  * @cs: pointer to the struct class_simple that this device should be registered to.
115  * @dev: the dev_t for the device to be added.
116  * @device: a pointer to a struct device that is assiociated with this class device.
117  * @fmt: string for the class device's name
118  *
119  * This function can be used by simple char device classes that do not
120  * implement their own class device registration.  A struct class_device will
121  * be created in sysfs, registered to the specified class.  A "dev" file will
122  * be created, showing the dev_t for the device.  The pointer to the struct
123  * class_device will be returned from the call.  Any further sysfs files that
124  * might be required can be created using this pointer.
125  * Note: the struct class_simple passed to this function must have previously been
126  * created with a call to class_simple_create().
127  */
128 struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...)
129 {
130         va_list args;
131         struct simple_dev *s_dev = NULL;
132         int retval;
133
134         if ((cs == NULL) || (IS_ERR(cs))) {
135                 retval = -ENODEV;
136                 goto error;
137         }
138
139         s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
140         if (!s_dev) {
141                 retval = -ENOMEM;
142                 goto error;
143         }
144         memset(s_dev, 0x00, sizeof(*s_dev));
145
146         s_dev->dev = dev;
147         s_dev->class_dev.dev = device;
148         s_dev->class_dev.class = &cs->class;
149
150         va_start(args, fmt);
151         vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
152         va_end(args);
153         retval = class_device_register(&s_dev->class_dev);
154         if (retval)
155                 goto error;
156
157         class_device_create_file(&s_dev->class_dev, &cs->attr);
158
159         spin_lock(&simple_dev_list_lock);
160         list_add(&s_dev->node, &simple_dev_list);
161         spin_unlock(&simple_dev_list_lock);
162
163         return &s_dev->class_dev;
164
165 error:
166         kfree(s_dev);
167         return ERR_PTR(retval);
168 }
169 EXPORT_SYMBOL(class_simple_device_add);
170
171 /**
172  * class_simple_set_hotplug - set the hotplug callback in the embedded struct class
173  * @cs: pointer to the struct class_simple to hold the pointer
174  * @hotplug: function pointer to the hotplug function
175  *
176  * Implement and set a hotplug function to add environment variables specific to this
177  * class on the hotplug event.
178  */
179 int class_simple_set_hotplug(struct class_simple *cs,
180         int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size))
181 {
182         if ((cs == NULL) || (IS_ERR(cs)))
183                 return -ENODEV;
184         cs->class.hotplug = hotplug;
185         return 0;
186 }
187 EXPORT_SYMBOL(class_simple_set_hotplug);
188
189 /**
190  * class_simple_device_remove - removes a class device that was created with class_simple_device_add()
191  * @dev: the dev_t of the device that was previously registered.
192  *
193  * This call unregisters and cleans up a class device that was created with a
194  * call to class_device_simple_add()
195  */
196 void class_simple_device_remove(dev_t dev)
197 {
198         struct simple_dev *s_dev = NULL;
199         int found = 0;
200
201         spin_lock(&simple_dev_list_lock);
202         list_for_each_entry(s_dev, &simple_dev_list, node) {
203                 if (s_dev->dev == dev) {
204                         found = 1;
205                         break;
206                 }
207         }
208         if (found) {
209                 list_del(&s_dev->node);
210                 spin_unlock(&simple_dev_list_lock);
211                 class_device_unregister(&s_dev->class_dev);
212         } else {
213                 spin_unlock(&simple_dev_list_lock);
214         }
215 }
216 EXPORT_SYMBOL(class_simple_device_remove);