patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / input / serio / serio.c
1 /*
2  * $Id: serio.c,v 1.15 2002/01/22 21:12:03 vojtech Exp $
3  *
4  *  Copyright (c) 1999-2001 Vojtech Pavlik
5  */
6
7 /*
8  *  The Serio abstraction module
9  */
10
11 /*
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25  *
26  * Should you need to contact me, the author, you can do so either by
27  * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
28  * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
29  *
30  * Changes:
31  * 20 Jul. 2003    Daniele Bellucci <bellucda@tiscali.it>
32  *                 Minor cleanups.
33  */
34
35 #include <linux/stddef.h>
36 #include <linux/module.h>
37 #include <linux/serio.h>
38 #include <linux/errno.h>
39 #include <linux/wait.h>
40 #include <linux/completion.h>
41 #include <linux/sched.h>
42 #include <linux/smp_lock.h>
43 #include <linux/suspend.h>
44 #include <linux/slab.h>
45
46 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
47 MODULE_DESCRIPTION("Serio abstraction core");
48 MODULE_LICENSE("GPL");
49
50 EXPORT_SYMBOL(serio_interrupt);
51 EXPORT_SYMBOL(serio_register_port);
52 EXPORT_SYMBOL(serio_register_port_delayed);
53 EXPORT_SYMBOL(__serio_register_port);
54 EXPORT_SYMBOL(serio_unregister_port);
55 EXPORT_SYMBOL(serio_unregister_port_delayed);
56 EXPORT_SYMBOL(__serio_unregister_port);
57 EXPORT_SYMBOL(serio_register_device);
58 EXPORT_SYMBOL(serio_unregister_device);
59 EXPORT_SYMBOL(serio_open);
60 EXPORT_SYMBOL(serio_close);
61 EXPORT_SYMBOL(serio_rescan);
62 EXPORT_SYMBOL(serio_reconnect);
63
64 struct serio_event {
65         int type;
66         struct serio *serio;
67         struct list_head node;
68 };
69
70 static DECLARE_MUTEX(serio_sem);
71 static LIST_HEAD(serio_list);
72 static LIST_HEAD(serio_dev_list);
73 static LIST_HEAD(serio_event_list);
74 static int serio_pid;
75
76 static void serio_find_dev(struct serio *serio)
77 {
78         struct serio_dev *dev;
79
80         list_for_each_entry(dev, &serio_dev_list, node) {
81                 if (serio->dev)
82                         break;
83                 if (dev->connect)
84                         dev->connect(serio, dev);
85         }
86 }
87
88 #define SERIO_RESCAN            1
89 #define SERIO_RECONNECT         2
90 #define SERIO_REGISTER_PORT     3
91 #define SERIO_UNREGISTER_PORT   4
92
93 static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
94 static DECLARE_COMPLETION(serio_exited);
95
96 static void serio_invalidate_pending_events(struct serio *serio)
97 {
98         struct serio_event *event;
99
100         list_for_each_entry(event, &serio_event_list, node)
101                 if (event->serio == serio)
102                         event->serio = NULL;
103 }
104
105 void serio_handle_events(void)
106 {
107         struct list_head *node, *next;
108         struct serio_event *event;
109
110         list_for_each_safe(node, next, &serio_event_list) {
111                 event = container_of(node, struct serio_event, node);
112
113                 down(&serio_sem);
114                 if (event->serio == NULL)
115                         goto event_done;
116
117                 switch (event->type) {
118                         case SERIO_REGISTER_PORT :
119                                 __serio_register_port(event->serio);
120                                 break;
121
122                         case SERIO_UNREGISTER_PORT :
123                                 __serio_unregister_port(event->serio);
124                                 break;
125
126                         case SERIO_RECONNECT :
127                                 if (event->serio->dev && event->serio->dev->reconnect)
128                                         if (event->serio->dev->reconnect(event->serio) == 0)
129                                                 break;
130                                 /* reconnect failed - fall through to rescan */
131
132                         case SERIO_RESCAN :
133                                 if (event->serio->dev && event->serio->dev->disconnect)
134                                         event->serio->dev->disconnect(event->serio);
135                                 serio_find_dev(event->serio);
136                                 break;
137                         default:
138                                 break;
139                 }
140 event_done:
141                 up(&serio_sem);
142                 list_del_init(node);
143                 kfree(event);
144         }
145 }
146
147 static int serio_thread(void *nothing)
148 {
149         lock_kernel();
150         daemonize("kseriod");
151         allow_signal(SIGTERM);
152
153         do {
154                 serio_handle_events();
155                 wait_event_interruptible(serio_wait, !list_empty(&serio_event_list));
156                 if (current->flags & PF_FREEZE)
157                         refrigerator(PF_FREEZE);
158         } while (!signal_pending(current));
159
160         printk(KERN_DEBUG "serio: kseriod exiting\n");
161
162         unlock_kernel();
163         complete_and_exit(&serio_exited, 0);
164 }
165
166 static void serio_queue_event(struct serio *serio, int event_type)
167 {
168         struct serio_event *event;
169
170         if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
171                 event->type = event_type;
172                 event->serio = serio;
173
174                 list_add_tail(&event->node, &serio_event_list);
175                 wake_up(&serio_wait);
176         }
177 }
178
179 void serio_rescan(struct serio *serio)
180 {
181         serio_queue_event(serio, SERIO_RESCAN);
182 }
183
184 void serio_reconnect(struct serio *serio)
185 {
186         serio_queue_event(serio, SERIO_RECONNECT);
187 }
188
189 irqreturn_t serio_interrupt(struct serio *serio,
190                 unsigned char data, unsigned int flags, struct pt_regs *regs)
191 {
192         irqreturn_t ret = IRQ_NONE;
193
194         if (serio->dev && serio->dev->interrupt) {
195                 ret = serio->dev->interrupt(serio, data, flags, regs);
196         } else {
197                 if (!flags) {
198                         if ((serio->type == SERIO_8042 ||
199                                 serio->type == SERIO_8042_XL) && (data != 0xaa))
200                                         return ret;
201                         serio_rescan(serio);
202                         ret = IRQ_HANDLED;
203                 }
204         }
205         return ret;
206 }
207
208 void serio_register_port(struct serio *serio)
209 {
210         down(&serio_sem);
211         __serio_register_port(serio);
212         up(&serio_sem);
213 }
214
215 /*
216  * Submits register request to kseriod for subsequent execution.
217  * Can be used when it is not obvious whether the serio_sem is
218  * taken or not and when delayed execution is feasible.
219  */
220 void serio_register_port_delayed(struct serio *serio)
221 {
222         serio_queue_event(serio, SERIO_REGISTER_PORT);
223 }
224
225 /*
226  * Should only be called directly if serio_sem has already been taken,
227  * for example when unregistering a serio from other input device's
228  * connect() function.
229  */
230 void __serio_register_port(struct serio *serio)
231 {
232         list_add_tail(&serio->node, &serio_list);
233         serio_find_dev(serio);
234 }
235
236 void serio_unregister_port(struct serio *serio)
237 {
238         down(&serio_sem);
239         __serio_unregister_port(serio);
240         up(&serio_sem);
241 }
242
243 /*
244  * Submits unregister request to kseriod for subsequent execution.
245  * Can be used when it is not obvious whether the serio_sem is
246  * taken or not and when delayed execution is feasible.
247  */
248 void serio_unregister_port_delayed(struct serio *serio)
249 {
250         serio_queue_event(serio, SERIO_UNREGISTER_PORT);
251 }
252
253 /*
254  * Should only be called directly if serio_sem has already been taken,
255  * for example when unregistering a serio from other input device's
256  * disconnect() function.
257  */
258 void __serio_unregister_port(struct serio *serio)
259 {
260         serio_invalidate_pending_events(serio);
261         list_del_init(&serio->node);
262         if (serio->dev && serio->dev->disconnect)
263                 serio->dev->disconnect(serio);
264 }
265
266 void serio_register_device(struct serio_dev *dev)
267 {
268         struct serio *serio;
269         down(&serio_sem);
270         list_add_tail(&dev->node, &serio_dev_list);
271         list_for_each_entry(serio, &serio_list, node)
272                 if (!serio->dev && dev->connect)
273                         dev->connect(serio, dev);
274         up(&serio_sem);
275 }
276
277 void serio_unregister_device(struct serio_dev *dev)
278 {
279         struct serio *serio;
280
281         down(&serio_sem);
282         list_del_init(&dev->node);
283
284         list_for_each_entry(serio, &serio_list, node) {
285                 if (serio->dev == dev && dev->disconnect)
286                         dev->disconnect(serio);
287                 serio_find_dev(serio);
288         }
289         up(&serio_sem);
290 }
291
292 /* called from serio_dev->connect/disconnect methods under serio_sem */
293 int serio_open(struct serio *serio, struct serio_dev *dev)
294 {
295         serio->dev = dev;
296         if (serio->open && serio->open(serio)) {
297                 serio->dev = NULL;
298                 return -1;
299         }
300         return 0;
301 }
302
303 /* called from serio_dev->connect/disconnect methods under serio_sem */
304 void serio_close(struct serio *serio)
305 {
306         if (serio->close)
307                 serio->close(serio);
308         serio->dev = NULL;
309 }
310
311 static int __init serio_init(void)
312 {
313         int pid;
314
315         pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL);
316
317         if (!pid) {
318                 printk(KERN_WARNING "serio: Failed to start kseriod\n");
319                 return -1;
320         }
321
322         serio_pid = pid;
323
324         return 0;
325 }
326
327 static void __exit serio_exit(void)
328 {
329         kill_proc(serio_pid, SIGTERM, 1);
330         wait_for_completion(&serio_exited);
331 }
332
333 module_init(serio_init);
334 module_exit(serio_exit);