1 /*
2 * linux/drivers/char/busmouse.c
3 *
4 * Copyright (C) 1995 - 1998 Russell King <linux@arm.linux.org.uk>
5 * Protocol taken from original busmouse.c
6 * read() waiting taken from psaux.c
7 *
8 * Medium-level interface for quadrature or bus mice.
9 */
10
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/sched.h>
14 #include <linux/signal.h>
15 #include <linux/slab.h>
16 #include <linux/errno.h>
17 #include <linux/mm.h>
18 #include <linux/poll.h>
19 #include <linux/miscdevice.h>
20 #include <linux/random.h>
21 #include <linux/init.h>
22 #include <linux/smp_lock.h>
23
24 #include <asm/uaccess.h>
25 #include <asm/system.h>
26 #include <asm/io.h>
27
28 #include "busmouse.h"
29
30 /* Uncomment this if your mouse drivers expect the kernel to
31 * return with EAGAIN if the mouse does not have any events
32 * available, even if the mouse is opened in blocking mode.
33 * Please report use of this "feature" to the author using the
34 * above address.
35 */
36 /*#define BROKEN_MOUSE*/
37
38 struct busmouse_data {
39 struct miscdevice miscdev;
40 struct busmouse *ops;
41 spinlock_t lock;
42
43 wait_queue_head_t wait;
44 struct fasync_struct *fasyncptr;
45 char active;
46 char buttons;
47 char ready;
48 int dxpos;
49 int dypos;
50 };
51
52 #define NR_MICE 15
53 #define FIRST_MOUSE 0
54 #define DEV_TO_MOUSE(dev) MINOR_TO_MOUSE(MINOR(dev))
55 #define MINOR_TO_MOUSE(minor) ((minor) - FIRST_MOUSE)
56
57 /*
58 * List of mice and guarding semaphore. You must take the semaphore
59 * before you take the misc device semaphore if you need both
60 */
61
62 static struct busmouse_data *busmouse_data[NR_MICE];
63 static DECLARE_MUTEX(mouse_sem);
64
65 /**
66 * busmouse_add_movement - notification of a change of mouse position
67 * @mousedev: mouse number
68 * @dx: delta X movement
69 * @dy: delta Y movement
70 * @buttons: new button state
71 *
72 * Updates the mouse position and button information. The mousedev
73 * parameter is the value returned from register_busmouse. The
74 * movement information is updated, and the new button state is
75 * saved. A waiting user thread is woken.
76 */
77
busmouse_add_movementbuttons(int mousedev,int dx,int dy,int buttons)78 void busmouse_add_movementbuttons(int mousedev, int dx, int dy, int buttons)
79 {
80 struct busmouse_data *mse = busmouse_data[mousedev];
81 int changed;
82
83 spin_lock(&mse->lock);
84 changed = (dx != 0 || dy != 0 || mse->buttons != buttons);
85
86 if (changed) {
87 add_mouse_randomness((buttons << 16) + (dy << 8) + dx);
88
89 mse->buttons = buttons;
90 mse->dxpos += dx;
91 mse->dypos += dy;
92 mse->ready = 1;
93
94 /*
95 * keep dx/dy reasonable, but still able to track when X (or
96 * whatever) must page or is busy (i.e. long waits between
97 * reads)
98 */
99 if (mse->dxpos < -2048)
100 mse->dxpos = -2048;
101 if (mse->dxpos > 2048)
102 mse->dxpos = 2048;
103 if (mse->dypos < -2048)
104 mse->dypos = -2048;
105 if (mse->dypos > 2048)
106 mse->dypos = 2048;
107 }
108
109 spin_unlock(&mse->lock);
110
111 if (changed) {
112 wake_up(&mse->wait);
113
114 kill_fasync(&mse->fasyncptr, SIGIO, POLL_IN);
115 }
116 }
117
118 /**
119 * busmouse_add_movement - notification of a change of mouse position
120 * @mousedev: mouse number
121 * @dx: delta X movement
122 * @dy: delta Y movement
123 *
124 * Updates the mouse position. The mousedev parameter is the value
125 * returned from register_busmouse. The movement information is
126 * updated, and a waiting user thread is woken.
127 */
128
busmouse_add_movement(int mousedev,int dx,int dy)129 void busmouse_add_movement(int mousedev, int dx, int dy)
130 {
131 struct busmouse_data *mse = busmouse_data[mousedev];
132
133 busmouse_add_movementbuttons(mousedev, dx, dy, mse->buttons);
134 }
135
136 /**
137 * busmouse_add_buttons - notification of a change of button state
138 * @mousedev: mouse number
139 * @clear: mask of buttons to clear
140 * @eor: mask of buttons to change
141 *
142 * Updates the button state. The mousedev parameter is the value
143 * returned from register_busmouse. The buttons are updated by:
144 * new_state = (old_state & ~clear) ^ eor
145 * A waiting user thread is woken up.
146 */
147
busmouse_add_buttons(int mousedev,int clear,int eor)148 void busmouse_add_buttons(int mousedev, int clear, int eor)
149 {
150 struct busmouse_data *mse = busmouse_data[mousedev];
151
152 busmouse_add_movementbuttons(mousedev, 0, 0, (mse->buttons & ~clear) ^ eor);
153 }
154
busmouse_fasync(int fd,struct file * filp,int on)155 static int busmouse_fasync(int fd, struct file *filp, int on)
156 {
157 struct busmouse_data *mse = (struct busmouse_data *)filp->private_data;
158 int retval;
159
160 retval = fasync_helper(fd, filp, on, &mse->fasyncptr);
161 if (retval < 0)
162 return retval;
163 return 0;
164 }
165
busmouse_release(struct inode * inode,struct file * file)166 static int busmouse_release(struct inode *inode, struct file *file)
167 {
168 struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
169 int ret = 0;
170
171 lock_kernel();
172 busmouse_fasync(-1, file, 0);
173
174 if (--mse->active == 0) {
175 if (mse->ops->release)
176 ret = mse->ops->release(inode, file);
177 if (mse->ops->owner)
178 __MOD_DEC_USE_COUNT(mse->ops->owner);
179 mse->ready = 0;
180 }
181 unlock_kernel();
182
183 return ret;
184 }
185
busmouse_open(struct inode * inode,struct file * file)186 static int busmouse_open(struct inode *inode, struct file *file)
187 {
188 struct busmouse_data *mse;
189 unsigned int mousedev;
190 int ret;
191
192 mousedev = DEV_TO_MOUSE(inode->i_rdev);
193 if (mousedev >= NR_MICE)
194 return -EINVAL;
195
196 down(&mouse_sem);
197 mse = busmouse_data[mousedev];
198 ret = -ENODEV;
199 if (!mse || !mse->ops) /* shouldn't happen, but... */
200 goto end;
201
202 if (mse->ops->owner && !try_inc_mod_count(mse->ops->owner))
203 goto end;
204
205 ret = 0;
206 if (mse->ops->open) {
207 ret = mse->ops->open(inode, file);
208 if (ret && mse->ops->owner)
209 __MOD_DEC_USE_COUNT(mse->ops->owner);
210 }
211
212 if (ret)
213 goto end;
214
215 file->private_data = mse;
216
217 if (mse->active++)
218 goto end;
219
220 spin_lock_irq(&mse->lock);
221
222 mse->ready = 0;
223 mse->dxpos = 0;
224 mse->dypos = 0;
225 mse->buttons = mse->ops->init_button_state;
226
227 spin_unlock_irq(&mse->lock);
228 end:
229 up(&mouse_sem);
230 return ret;
231 }
232
busmouse_write(struct file * file,const char * buffer,size_t count,loff_t * ppos)233 static ssize_t busmouse_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
234 {
235 return -EINVAL;
236 }
237
busmouse_read(struct file * file,char * buffer,size_t count,loff_t * ppos)238 static ssize_t busmouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
239 {
240 struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
241 DECLARE_WAITQUEUE(wait, current);
242 int dxpos, dypos, buttons;
243
244 if (count < 3)
245 return -EINVAL;
246
247 spin_lock_irq(&mse->lock);
248
249 if (!mse->ready) {
250 #ifdef BROKEN_MOUSE
251 spin_unlock_irq(&mse->lock);
252 return -EAGAIN;
253 #else
254 if (file->f_flags & O_NONBLOCK) {
255 spin_unlock_irq(&mse->lock);
256 return -EAGAIN;
257 }
258
259 add_wait_queue(&mse->wait, &wait);
260 repeat:
261 set_current_state(TASK_INTERRUPTIBLE);
262 if (!mse->ready && !signal_pending(current)) {
263 spin_unlock_irq(&mse->lock);
264 schedule();
265 spin_lock_irq(&mse->lock);
266 goto repeat;
267 }
268
269 current->state = TASK_RUNNING;
270 remove_wait_queue(&mse->wait, &wait);
271
272 if (signal_pending(current)) {
273 spin_unlock_irq(&mse->lock);
274 return -ERESTARTSYS;
275 }
276 #endif
277 }
278
279 dxpos = mse->dxpos;
280 dypos = mse->dypos;
281 buttons = mse->buttons;
282
283 if (dxpos < -127)
284 dxpos =- 127;
285 if (dxpos > 127)
286 dxpos = 127;
287 if (dypos < -127)
288 dypos =- 127;
289 if (dypos > 127)
290 dypos = 127;
291
292 mse->dxpos -= dxpos;
293 mse->dypos -= dypos;
294
295 /* This is something that many drivers have apparantly
296 * forgotten... If the X and Y positions still contain
297 * information, we still have some info ready for the
298 * user program...
299 */
300 mse->ready = mse->dxpos || mse->dypos;
301
302 spin_unlock_irq(&mse->lock);
303
304 /* Write out data to the user. Format is:
305 * byte 0 - identifer (0x80) and (inverted) mouse buttons
306 * byte 1 - X delta position +/- 127
307 * byte 2 - Y delta position +/- 127
308 */
309 if (put_user((char)buttons | 128, buffer) ||
310 put_user((char)dxpos, buffer + 1) ||
311 put_user((char)dypos, buffer + 2))
312 return -EFAULT;
313
314 if (count > 3 && clear_user(buffer + 3, count - 3))
315 return -EFAULT;
316
317 file->f_dentry->d_inode->i_atime = CURRENT_TIME;
318
319 return count;
320 }
321
322 /* No kernel lock held - fine */
busmouse_poll(struct file * file,poll_table * wait)323 static unsigned int busmouse_poll(struct file *file, poll_table *wait)
324 {
325 struct busmouse_data *mse = (struct busmouse_data *)file->private_data;
326
327 poll_wait(file, &mse->wait, wait);
328
329 if (mse->ready)
330 return POLLIN | POLLRDNORM;
331
332 return 0;
333 }
334
335 struct file_operations busmouse_fops=
336 {
337 owner: THIS_MODULE,
338 read: busmouse_read,
339 write: busmouse_write,
340 poll: busmouse_poll,
341 open: busmouse_open,
342 release: busmouse_release,
343 fasync: busmouse_fasync,
344 };
345
346 /**
347 * register_busmouse - register a bus mouse interface
348 * @ops: busmouse structure for the mouse
349 *
350 * Registers a mouse with the driver. The return is mouse number on
351 * success and a negative errno code on an error. The passed ops
352 * structure most not be freed until the mouser is unregistered
353 */
354
register_busmouse(struct busmouse * ops)355 int register_busmouse(struct busmouse *ops)
356 {
357 unsigned int msedev = MINOR_TO_MOUSE(ops->minor);
358 struct busmouse_data *mse;
359 int ret;
360
361 if (msedev >= NR_MICE) {
362 printk(KERN_ERR "busmouse: trying to allocate mouse on minor %d\n",
363 ops->minor);
364 return -EINVAL;
365 }
366
367 mse = kmalloc(sizeof(*mse), GFP_KERNEL);
368 if (!mse)
369 return -ENOMEM;
370
371 down(&mouse_sem);
372 if (busmouse_data[msedev])
373 {
374 up(&mouse_sem);
375 kfree(mse);
376 return -EBUSY;
377 }
378
379 memset(mse, 0, sizeof(*mse));
380
381 mse->miscdev.minor = ops->minor;
382 mse->miscdev.name = ops->name;
383 mse->miscdev.fops = &busmouse_fops;
384 mse->ops = ops;
385 mse->lock = (spinlock_t)SPIN_LOCK_UNLOCKED;
386 init_waitqueue_head(&mse->wait);
387
388 busmouse_data[msedev] = mse;
389
390 ret = misc_register(&mse->miscdev);
391 if (!ret)
392 ret = msedev;
393 up(&mouse_sem);
394
395 return ret;
396 }
397
398 /**
399 * unregister_busmouse - unregister a bus mouse interface
400 * @mousedev: Mouse number to release
401 *
402 * Unregister a previously installed mouse handler. The mousedev
403 * passed is the return code from a previous call to register_busmouse
404 */
405
406
unregister_busmouse(int mousedev)407 int unregister_busmouse(int mousedev)
408 {
409 int err = -EINVAL;
410
411 if (mousedev < 0)
412 return 0;
413 if (mousedev >= NR_MICE) {
414 printk(KERN_ERR "busmouse: trying to free mouse on"
415 " mousedev %d\n", mousedev);
416 return -EINVAL;
417 }
418
419 down(&mouse_sem);
420
421 if (!busmouse_data[mousedev]) {
422 printk(KERN_WARNING "busmouse: trying to free free mouse"
423 " on mousedev %d\n", mousedev);
424 goto fail;
425 }
426
427 if (busmouse_data[mousedev]->active) {
428 printk(KERN_ERR "busmouse: trying to free active mouse"
429 " on mousedev %d\n", mousedev);
430 goto fail;
431 }
432
433 err = misc_deregister(&busmouse_data[mousedev]->miscdev);
434
435 kfree(busmouse_data[mousedev]);
436 busmouse_data[mousedev] = NULL;
437 fail:
438 up(&mouse_sem);
439 return err;
440 }
441
442 EXPORT_SYMBOL(busmouse_add_movementbuttons);
443 EXPORT_SYMBOL(busmouse_add_movement);
444 EXPORT_SYMBOL(busmouse_add_buttons);
445 EXPORT_SYMBOL(register_busmouse);
446 EXPORT_SYMBOL(unregister_busmouse);
447
448 MODULE_LICENSE("GPL");
449