* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / char / busmouse.c
blob42c2642f669800a1388f05fa4016cdaa96fd4eea
1 /*
2 * linux/drivers/char/mouse.c
4 * Copyright (C) 1995 - 1998 Russell King
5 * Protocol taken from busmouse.c
6 * read() waiting taken from psaux.c
8 * Medium-level interface for quadrature or bus mice.
10 * Currently, the majority of kernel busmice drivers in the
11 * kernel common code to talk to userspace. This driver
12 * attempts to rectify this situation by presenting a
13 * simple and safe interface to the mice and user.
15 * This driver:
16 * - is SMP safe
17 * - handles multiple opens
18 * - handles the wakeups and locking
19 * - has optional blocking reads
22 #include <linux/module.h>
23 #include <linux/config.h>
24 #include <linux/kernel.h>
25 #include <linux/sched.h>
26 #include <linux/signal.h>
27 #include <linux/malloc.h>
28 #include <linux/errno.h>
29 #include <linux/mm.h>
30 #include <linux/poll.h>
31 #include <linux/miscdevice.h>
32 #include <linux/random.h>
33 #include <linux/init.h>
35 #include <asm/uaccess.h>
36 #include <asm/system.h>
37 #include <asm/io.h>
39 #include "busmouse.h"
41 /* Uncomment this if your mouse drivers expect the kernel to
42 * return with EAGAIN if the mouse does not have any events
43 * available, even if the mouse is opened in nonblocking mode.
45 * Should this be on a per-mouse basis? If so, add an entry to
46 * the struct busmouse structure and add the relevent flag to
47 * the drivers.
49 /*#define BROKEN_MOUSE*/
51 extern int adb_mouse_init(void);
52 extern int logi_busmouse_init(void);
53 extern int ms_bus_mouse_init(void);
54 extern int atixl_busmouse_init(void);
55 extern int amiga_mouse_init(void);
56 extern int atari_mouse_init(void);
57 extern int sun_mouse_init(void);
58 extern void mouse_rpc_init (void);
60 struct busmouse_data {
61 struct miscdevice miscdev;
62 struct busmouse *ops;
63 spinlock_t lock;
65 wait_queue_head_t wait;
66 struct fasync_struct *fasyncptr;
67 char active;
68 char buttons;
69 char latch_buttons;
70 char ready;
71 int dxpos;
72 int dypos;
75 #define NR_MICE 15
76 #define FIRST_MOUSE 0
77 #define DEV_TO_MOUSE(dev) MINOR_TO_MOUSE(MINOR(dev))
78 #define MINOR_TO_MOUSE(minor) ((minor) - FIRST_MOUSE)
80 static struct busmouse_data *busmouse_data[NR_MICE];
82 /* a mouse driver just has to interface with these functions
83 * These are !!!OLD!!! Do not use!!!
85 void add_mouse_movement(int dx, int dy)
87 struct busmouse_data *mse = busmouse_data[MINOR_TO_MOUSE(6)];
89 mse->dxpos += dx;
90 mse->dypos += dy;
91 mse->ready = 1;
92 wake_up(&mse->wait);
95 int add_mouse_buttonchange(int set, int value)
97 struct busmouse_data *mse = busmouse_data[MINOR_TO_MOUSE(6)];
99 mse->buttons = (mse->buttons & ~set) ^ value;
100 mse->ready = 1;
101 wake_up(&mse->wait);
102 return mse->buttons;
105 /* New interface. !!! Use this one !!!
106 * These routines will most probably be called from interrupt.
108 void
109 busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons)
111 struct busmouse_data *mse = busmouse_data[mousedev];
112 int changed;
114 spin_lock(&mse->lock);
115 changed = (dx != 0 || dy != 0 || mse->buttons != buttons);
117 if (changed) {
118 add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
120 mse->buttons = buttons;
121 // mse->latch_buttons |= buttons;
122 mse->dxpos += dx;
123 mse->dypos += dy;
124 mse->ready = 1;
127 * keep dx/dy reasonable, but still able to track when X (or
128 * whatever) must page or is busy (i.e. long waits between
129 * reads)
131 if (mse->dxpos < -2048)
132 mse->dxpos = -2048;
133 if (mse->dxpos > 2048)
134 mse->dxpos = 2048;
135 if (mse->dypos < -2048)
136 mse->dypos = -2048;
137 if (mse->dypos > 2048)
138 mse->dypos = 2048;
141 spin_unlock(&mse->lock);
143 if (changed) {
144 wake_up(&mse->wait);
146 if (mse->fasyncptr)
147 kill_fasync(mse->fasyncptr, SIGIO, POLL_IN);
151 void
152 busmouse_add_movement(int mousedev, int dx, int dy)
154 struct busmouse_data *mse = busmouse_data[mousedev];
156 busmouse_add_movementbuttons(mousedev, dx, dy, mse->buttons);
159 void
160 busmouse_add_buttons(int mousedev, int clear, int eor)
162 struct busmouse_data *mse = busmouse_data[mousedev];
164 busmouse_add_movementbuttons(mousedev, 0, 0, (mse->buttons & ~clear) ^ eor);
167 static int
168 busmouse_fasync(int fd, struct file *filp, int on)
170 struct busmouse_data *mse = (struct busmouse_data *)filp->private_data;
171 int retval;
173 retval = fasync_helper(fd, filp, on, &mse->fasyncptr);
174 if (retval < 0)
175 return retval;
176 return 0;
179 static int
180 busmouse_release(struct inode *inode, struct file *file)
182 struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
183 int ret = 0;
185 busmouse_fasync(-1, file, 0);
187 if (--mse->active == 0) {
188 if (mse->ops &&
189 mse->ops->release)
190 ret = mse->ops->release(inode, file);
192 mse->ready = 0;
194 MOD_DEC_USE_COUNT;
197 return ret;
200 static int
201 busmouse_open(struct inode *inode, struct file *file)
203 struct busmouse_data *mse;
204 unsigned long flags;
205 unsigned int mousedev;
206 int ret = 0;
208 mousedev = DEV_TO_MOUSE(inode->i_rdev);
209 if (mousedev >= NR_MICE)
210 return -EINVAL;
211 mse = busmouse_data[mousedev];
212 if (!mse)
213 /* shouldn't happen, but... */
214 return -ENODEV;
216 if (mse->ops &&
217 mse->ops->open)
218 ret = mse->ops->open(inode, file);
220 if (ret)
221 return ret;
223 file->private_data = mse;
225 if (mse->active++)
226 return 0;
228 MOD_INC_USE_COUNT;
230 spin_lock_irqsave(&mse->lock, flags);
232 mse->ready = 0;
233 mse->dxpos = 0;
234 mse->dypos = 0;
235 if (mse->ops)
236 mse->buttons = mse->ops->init_button_state;
237 else
238 mse->buttons = 7;
240 spin_unlock_irqrestore(&mse->lock, flags);
242 return 0;
245 static ssize_t
246 busmouse_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
248 return -EINVAL;
251 static ssize_t
252 busmouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
254 struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
255 DECLARE_WAITQUEUE(wait, current);
256 unsigned long flags;
257 int dxpos, dypos, buttons;
259 if (count < 3)
260 return -EINVAL;
262 spin_lock_irqsave(&mse->lock, flags);
264 if (!mse->ready) {
265 #ifdef BROKEN_MOUSE
266 spin_unlock_irqrestore(&mse->lock, flags);
267 return -EAGAIN;
268 #else
269 if (file->f_flags & O_NONBLOCK) {
270 spin_unlock_irqrestore(&mse->lock, flags);
271 return -EAGAIN;
274 add_wait_queue(&mse->wait, &wait);
275 repeat:
276 set_current_state(TASK_INTERRUPTIBLE);
277 if (!mse->ready && !signal_pending(current)) {
278 spin_unlock_irqrestore(&mse->lock, flags);
279 schedule();
280 spin_lock_irqsave(&mse->lock, flags);
281 goto repeat;
284 current->state = TASK_RUNNING;
285 remove_wait_queue(&mse->wait, &wait);
287 if (signal_pending(current)) {
288 spin_unlock_irqrestore(&mse->lock, flags);
289 return -ERESTARTSYS;
291 #endif
294 dxpos = mse->dxpos;
295 dypos = mse->dypos;
296 buttons = mse->buttons;
297 // mse->latch_buttons = mse->buttons;
299 if (dxpos < -127)
300 dxpos =- 127;
301 if (dxpos > 127)
302 dxpos = 127;
303 if (dypos < -127)
304 dypos =- 127;
305 if (dypos > 127)
306 dypos = 127;
308 mse->dxpos -= dxpos;
309 mse->dypos -= dypos;
311 /* This is something that many drivers have apparantly
312 * forgotten... If the X and Y positions still contain
313 * information, we still have some info ready for the
314 * user program...
316 mse->ready = mse->dxpos || mse->dypos;
318 spin_unlock_irqrestore(&mse->lock, flags);
320 /* Write out data to the user. Format is:
321 * byte 0 - identifer (0x80) and (inverted) mouse buttons
322 * byte 1 - X delta position +/- 127
323 * byte 2 - Y delta position +/- 127
325 if (put_user((char)buttons | 128, buffer) ||
326 put_user((char)dxpos, buffer + 1) ||
327 put_user((char)dypos, buffer + 2))
328 return -EFAULT;
330 if (count > 3 && clear_user(buffer + 3, count - 3))
331 return -EFAULT;
333 file->f_dentry->d_inode->i_atime = CURRENT_TIME;
335 return count;
338 static unsigned int
339 busmouse_poll(struct file *file, poll_table *wait)
341 struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
343 poll_wait(file, &mse->wait, wait);
345 if (mse->ready)
346 return POLLIN | POLLRDNORM;
348 return 0;
351 struct file_operations busmouse_fops=
353 NULL, /* busmouse_seek */
354 busmouse_read,
355 busmouse_write,
356 NULL, /* busmouse_readdir */
357 busmouse_poll,
358 NULL, /* busmouse_ioctl */
359 NULL, /* busmouse_mmap */
360 busmouse_open,
361 NULL, /* busmouse_flush */
362 busmouse_release,
363 NULL,
364 busmouse_fasync,
368 register_busmouse(struct busmouse *ops)
370 unsigned int msedev = MINOR_TO_MOUSE(ops->minor);
371 struct busmouse_data *mse;
372 int ret;
374 if (msedev >= NR_MICE) {
375 printk(KERN_ERR "busmouse: trying to allocate mouse on minor %d\n",
376 ops->minor);
377 return -EINVAL;
380 if (busmouse_data[msedev])
381 return -EBUSY;
383 mse = kmalloc(sizeof(*mse), GFP_KERNEL);
384 if (!mse)
385 return -ENOMEM;
387 memset(mse, 0, sizeof(*mse));
389 mse->miscdev.minor = ops->minor;
390 mse->miscdev.name = ops->name;
391 mse->miscdev.fops = &busmouse_fops;
392 mse->ops = ops;
393 mse->lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
394 init_waitqueue_head(&mse->wait);
396 busmouse_data[msedev] = mse;
398 ret = misc_register(&mse->miscdev);
399 if (!ret)
400 ret = msedev;
402 return ret;
406 unregister_busmouse(int mousedev)
408 if (mousedev < 0)
409 return 0;
410 if (mousedev >= NR_MICE) {
411 printk(KERN_ERR "busmouse: trying to free mouse on"
412 " mousedev %d\n", mousedev);
413 return -EINVAL;
416 if (!busmouse_data[mousedev]) {
417 printk(KERN_WARNING "busmouse: trying to free free mouse"
418 " on mousedev %d\n", mousedev);
419 return -EINVAL;
422 if (busmouse_data[mousedev]->active) {
423 printk(KERN_ERR "busmouse: trying to free active mouse"
424 " on mousedev %d\n", mousedev);
425 return -EINVAL;
428 misc_deregister(&busmouse_data[mousedev]->miscdev);
430 kfree(busmouse_data[mousedev]);
431 busmouse_data[mousedev] = NULL;
432 return 0;
435 int __init
436 bus_mouse_init(void)
438 #ifdef CONFIG_LOGIBUSMOUSE
439 logi_busmouse_init();
440 #endif
441 #ifdef CONFIG_MS_BUSMOUSE
442 ms_bus_mouse_init();
443 #endif
444 #ifdef CONFIG_ATIXL_BUSMOUSE
445 atixl_busmouse_init();
446 #endif
447 #ifdef CONFIG_AMIGAMOUSE
448 amiga_mouse_init();
449 #endif
450 #ifdef CONFIG_ATARIMOUSE
451 atari_mouse_init();
452 #endif
453 #ifdef CONFIG_SUN_MOUSE
454 sun_mouse_init();
455 #endif
456 #ifdef CONFIG_ADB_MOUSE
457 adb_mouse_init();
458 #endif
459 #ifdef CONFIG_RPCMOUSE
460 mouse_rpc_init();
461 #endif
462 return 0;
465 EXPORT_SYMBOL(busmouse_add_movementbuttons);
466 EXPORT_SYMBOL(busmouse_add_movement);
467 EXPORT_SYMBOL(busmouse_add_buttons);
468 EXPORT_SYMBOL(register_busmouse);
469 EXPORT_SYMBOL(unregister_busmouse);
471 #ifdef MODULE
473 init_module(void)
475 return bus_mouse_init();
478 void
479 cleanup_module(void)
482 #endif