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.
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>
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>
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
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
;
65 wait_queue_head_t wait
;
66 struct fasync_struct
*fasyncptr
;
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)];
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
;
105 /* New interface. !!! Use this one !!!
106 * These routines will most probably be called from interrupt.
109 busmouse_add_movementbuttons(int mousedev
, int dx
, int dy
, int buttons
)
111 struct busmouse_data
*mse
= busmouse_data
[mousedev
];
114 spin_lock(&mse
->lock
);
115 changed
= (dx
!= 0 || dy
!= 0 || mse
->buttons
!= buttons
);
118 add_mouse_randomness((buttons
<< 16) + (dy
<< 8) + dx
);
120 mse
->buttons
= buttons
;
121 // mse->latch_buttons |= buttons;
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
131 if (mse
->dxpos
< -2048)
133 if (mse
->dxpos
> 2048)
135 if (mse
->dypos
< -2048)
137 if (mse
->dypos
> 2048)
141 spin_unlock(&mse
->lock
);
147 kill_fasync(mse
->fasyncptr
, SIGIO
, POLL_IN
);
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
);
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
);
168 busmouse_fasync(int fd
, struct file
*filp
, int on
)
170 struct busmouse_data
*mse
= (struct busmouse_data
*)filp
->private_data
;
173 retval
= fasync_helper(fd
, filp
, on
, &mse
->fasyncptr
);
180 busmouse_release(struct inode
*inode
, struct file
*file
)
182 struct busmouse_data
*mse
= (struct busmouse_data
*)file
->private_data
;
185 busmouse_fasync(-1, file
, 0);
187 if (--mse
->active
== 0) {
190 ret
= mse
->ops
->release(inode
, file
);
201 busmouse_open(struct inode
*inode
, struct file
*file
)
203 struct busmouse_data
*mse
;
205 unsigned int mousedev
;
208 mousedev
= DEV_TO_MOUSE(inode
->i_rdev
);
209 if (mousedev
>= NR_MICE
)
211 mse
= busmouse_data
[mousedev
];
213 /* shouldn't happen, but... */
218 ret
= mse
->ops
->open(inode
, file
);
223 file
->private_data
= mse
;
230 spin_lock_irqsave(&mse
->lock
, flags
);
236 mse
->buttons
= mse
->ops
->init_button_state
;
240 spin_unlock_irqrestore(&mse
->lock
, flags
);
246 busmouse_write(struct file
*file
, const char *buffer
, size_t count
, loff_t
*ppos
)
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
);
257 int dxpos
, dypos
, buttons
;
262 spin_lock_irqsave(&mse
->lock
, flags
);
266 spin_unlock_irqrestore(&mse
->lock
, flags
);
269 if (file
->f_flags
& O_NONBLOCK
) {
270 spin_unlock_irqrestore(&mse
->lock
, flags
);
274 add_wait_queue(&mse
->wait
, &wait
);
276 set_current_state(TASK_INTERRUPTIBLE
);
277 if (!mse
->ready
&& !signal_pending(current
)) {
278 spin_unlock_irqrestore(&mse
->lock
, flags
);
280 spin_lock_irqsave(&mse
->lock
, flags
);
284 current
->state
= TASK_RUNNING
;
285 remove_wait_queue(&mse
->wait
, &wait
);
287 if (signal_pending(current
)) {
288 spin_unlock_irqrestore(&mse
->lock
, flags
);
296 buttons
= mse
->buttons
;
297 // mse->latch_buttons = mse->buttons;
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
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))
330 if (count
> 3 && clear_user(buffer
+ 3, count
- 3))
333 file
->f_dentry
->d_inode
->i_atime
= CURRENT_TIME
;
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
);
346 return POLLIN
| POLLRDNORM
;
351 struct file_operations busmouse_fops
=
353 NULL
, /* busmouse_seek */
356 NULL
, /* busmouse_readdir */
358 NULL
, /* busmouse_ioctl */
359 NULL
, /* busmouse_mmap */
361 NULL
, /* busmouse_flush */
368 register_busmouse(struct busmouse
*ops
)
370 unsigned int msedev
= MINOR_TO_MOUSE(ops
->minor
);
371 struct busmouse_data
*mse
;
374 if (msedev
>= NR_MICE
) {
375 printk(KERN_ERR
"busmouse: trying to allocate mouse on minor %d\n",
380 if (busmouse_data
[msedev
])
383 mse
= kmalloc(sizeof(*mse
), GFP_KERNEL
);
387 memset(mse
, 0, sizeof(*mse
));
389 mse
->miscdev
.minor
= ops
->minor
;
390 mse
->miscdev
.name
= ops
->name
;
391 mse
->miscdev
.fops
= &busmouse_fops
;
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
);
406 unregister_busmouse(int mousedev
)
410 if (mousedev
>= NR_MICE
) {
411 printk(KERN_ERR
"busmouse: trying to free mouse on"
412 " mousedev %d\n", mousedev
);
416 if (!busmouse_data
[mousedev
]) {
417 printk(KERN_WARNING
"busmouse: trying to free free mouse"
418 " on mousedev %d\n", mousedev
);
422 if (busmouse_data
[mousedev
]->active
) {
423 printk(KERN_ERR
"busmouse: trying to free active mouse"
424 " on mousedev %d\n", mousedev
);
428 misc_deregister(&busmouse_data
[mousedev
]->miscdev
);
430 kfree(busmouse_data
[mousedev
]);
431 busmouse_data
[mousedev
] = NULL
;
438 #ifdef CONFIG_LOGIBUSMOUSE
439 logi_busmouse_init();
441 #ifdef CONFIG_MS_BUSMOUSE
444 #ifdef CONFIG_ATIXL_BUSMOUSE
445 atixl_busmouse_init();
447 #ifdef CONFIG_AMIGAMOUSE
450 #ifdef CONFIG_ATARIMOUSE
453 #ifdef CONFIG_SUN_MOUSE
456 #ifdef CONFIG_ADB_MOUSE
459 #ifdef CONFIG_RPCMOUSE
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
);
475 return bus_mouse_init();