import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / sbus / char / sunmouse.c
1 /* sunmouse.c: Sun mouse driver for the Sparc
2  *
3  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
4  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
5  *
6  * Parts based on the psaux.c driver written by:
7  * Johan Myreen.
8  *
9  * Dec/19/95 Added SunOS mouse ioctls - miguel.
10  * Jan/5/96  Added VUID support, sigio support - miguel.
11  * Mar/5/96  Added proper mouse stream support - miguel.
12  * Sep/96    Allow more than one reader -miguel.
13  * Aug/97    Added PCI 8042 controller support -DaveM
14  */
15
16 /* The mouse is run off of one of the Zilog serial ports.  On
17  * that port is the mouse and the keyboard, each gets a zs channel.
18  * The mouse itself is mouse-systems in nature.  So the protocol is:
19  *
20  * Byte 1) Button state which is bit-encoded as
21  *            0x4 == left-button down, else up
22  *            0x2 == middle-button down, else up
23  *            0x1 == right-button down, else up
24  *
25  * Byte 2) Delta-x
26  * Byte 3) Delta-y
27  * Byte 4) Delta-x again
28  * Byte 5) Delta-y again
29  *
30  * One day this driver will have to support more than one mouse in the system.
31  *
32  * This driver has two modes of operation: the default VUID_NATIVE is
33  * set when the device is opened and allows the application to see the
34  * mouse character stream as we get it from the serial (for gpm for
35  * example).  The second method, VUID_FIRM_EVENT will provide cooked
36  * events in Firm_event records as expected by SunOS/Solaris applications.
37  *
38  * FIXME: We need to support more than one mouse.
39  * */
40
41 #include <linux/config.h>
42 #include <linux/kernel.h>
43 #include <linux/sched.h>
44 #include <linux/fcntl.h>
45 #include <linux/signal.h>
46 #include <linux/timer.h>
47 #include <linux/errno.h>
48 #include <linux/miscdevice.h>
49 #include <linux/mm.h>
50 #include <linux/poll.h>
51 #include <linux/spinlock.h>
52 #include <linux/smp_lock.h>
53 #include <linux/init.h>
54 #include <asm/uaccess.h>
55 #include <asm/system.h>
56 #include <asm/vuid_event.h>
57 #include <linux/random.h>
58 /* The following keeps track of software state for the Sun
59  * mouse.
60  */
61 #define STREAM_SIZE   2048
62 #define EV_SIZE       (STREAM_SIZE/sizeof (Firm_event))
63 #define BUTTON_LEFT   4
64 #define BUTTON_MIDDLE 2
65 #define BUTTON_RIGHT  1
66
67 struct sun_mouse {
68         unsigned char transaction[5];  /* Each protocol transaction */
69         unsigned char byte;            /* Counter, starts at 0 */
70         unsigned char button_state;    /* Current button state */
71         unsigned char prev_state;      /* Previous button state */
72         int delta_x;                   /* Current delta-x */
73         int delta_y;                   /* Current delta-y */
74         int active;                    /* set if device is open */
75         int vuid_mode;                 /* VUID_NATIVE or VUID_FIRM_EVENT */
76         wait_queue_head_t proc_list;
77         struct fasync_struct *fasync;
78         
79         /* The event/stream queue */
80         spinlock_t lock;
81         unsigned int head;
82         unsigned int tail;
83         union {
84                 char stream [STREAM_SIZE];
85                 Firm_event ev [EV_SIZE];
86         } queue;
87 };
88
89 static struct sun_mouse sunmouse;
90 #define gen_events (sunmouse.vuid_mode != VUID_NATIVE)
91 #define bstate sunmouse.button_state
92 #define pstate sunmouse.prev_state
93
94 extern void mouse_put_char(char ch);
95
96 #undef SMOUSE_DEBUG
97
98 static int
99 push_event (Firm_event *ev)
100 {
101         unsigned long flags;
102         int next, ret;
103         
104         spin_lock_irqsave(&sunmouse.lock, flags);
105
106         next = (sunmouse.head + 1) % EV_SIZE;
107         ret = 0;
108         if (next != sunmouse.tail) {
109                 sunmouse.queue.ev [sunmouse.head] = *ev;
110                 sunmouse.head = next;
111                 ret = 1;
112         }
113
114         spin_unlock_irqrestore(&sunmouse.lock, flags);
115
116         return ret;
117 }
118
119 static int
120 queue_empty (void)
121 {
122         return sunmouse.head == sunmouse.tail;
123 }
124
125 /* Must be invoked under the sunmouse.lock */
126 static void get_from_queue (Firm_event *p)
127 {
128         *p = sunmouse.queue.ev [sunmouse.tail];
129         sunmouse.tail = (sunmouse.tail + 1) % EV_SIZE;
130 }
131
132 static void
133 push_char (char c)
134 {
135         unsigned long flags;
136         int next;
137
138         spin_lock_irqsave(&sunmouse.lock, flags);
139
140         next = (sunmouse.head + 1) % STREAM_SIZE;
141         if (next != sunmouse.tail) {
142 #ifdef SMOUSE_DEBUG
143                 printk("P<%02x>\n", (unsigned char)c);
144 #endif
145                 sunmouse.queue.stream [sunmouse.head] = c;
146                 sunmouse.head = next;
147         }
148
149         spin_unlock_irqrestore(&sunmouse.lock, flags);
150
151         kill_fasync (&sunmouse.fasync, SIGIO, POLL_IN);
152         wake_up_interruptible (&sunmouse.proc_list);
153 }
154
155 /* Auto baud rate "detection".  ;-) */
156 static int mouse_baud = 4800;           /* Initial rate set by zilog driver. */
157
158 /* Change the baud rate after receiving too many "bogon bytes". */
159 void sun_mouse_change_baud(void)
160 {
161         extern void rs_change_mouse_baud(int newbaud);
162
163         if(mouse_baud == 1200)
164                 mouse_baud = 2400;
165         else if(mouse_baud == 2400)
166                 mouse_baud = 4800;
167         else if(mouse_baud == 4800)
168                 mouse_baud = 9600;
169         else
170                 mouse_baud = 1200;
171
172         rs_change_mouse_baud(mouse_baud);
173 }
174
175 /* This tries to monitor the mouse state so that it
176  * can automatically adjust to the correct baud rate.
177  * The mouse spits out BRKs when the baud rate is
178  * incorrect.
179  *
180  * It returns non-zero if we should ignore this byte.
181  */
182 int mouse_baud_detection(unsigned char c, int is_break)
183 {
184         static int mouse_got_break = 0;
185         static int ctr = 0;
186
187         if (is_break) {
188                 /* Let a few normal bytes go by before
189                  * we jump the gun and say we need to
190                  * try another baud rate.
191                  */
192                 if (mouse_got_break && ctr < 8)
193                         return 1;
194
195                 /* OK, we need to try another baud rate. */
196                 sun_mouse_change_baud();
197                 ctr = 0;
198                 mouse_got_break = 1;
199                 return 1;
200         }
201         if (mouse_got_break) {
202                 ctr++;
203                 if (c == 0x87) {
204                         printk(KERN_INFO "sunmouse: Successfully "
205                                "adjusted to %d baud.\n", mouse_baud);
206                         mouse_got_break = 0;
207                 }
208                 return 1;
209         }
210
211         return 0;
212 }
213
214 /* You ask me, why does this cap the lower bound at -127 and not
215  * -128?  Because the xf86 mouse code is crap and treats -128
216  * as an illegal value and resets it's protocol state machine
217  * when it sees this value.
218  */
219 #define CLIP(__X)       (((__X) > 127) ? 127 : (((__X) < -127) ? -127 : (__X)))
220
221 /* The following is called from the serial driver when bytes/breaks
222  * are received on the Mouse line.
223  */
224 void
225 sun_mouse_inbyte(unsigned char byte, int is_break)
226 {
227         signed char mvalue;
228         int d, pushed = 0;
229         Firm_event ev;
230
231         add_mouse_randomness (byte);
232 #if 0
233         {
234                 static int xxx = 0;
235                 printk("mouse(%02x:%d) ",
236                        byte, is_break);
237                 if (byte == 0x87) {
238                         xxx = 0;
239                         printk("\n");
240                 }
241         }
242 #endif
243         if (mouse_baud_detection(byte, is_break))
244                 return;
245
246         if(!sunmouse.active)
247                 return;
248
249         /* Ignore this if it is garbage. */
250         if (sunmouse.byte == 69) {
251                 if (byte != 0x87)
252                         return;
253
254                 /* Ok, we've begun the state machine. */
255                 sunmouse.byte = 0;
256         }
257 #if 0
258         /* If the mouse sends us a byte from 0x80 to 0x87
259          * we are starting at byte zero in the transaction
260          * protocol.
261          */
262         if((byte & ~0x0f) == 0x80) 
263                 sunmouse.byte = 0;
264 #endif
265
266         mvalue = (signed char) byte;
267         switch(sunmouse.byte) {
268         case 0:
269                 /* If we get a bogus button byte, just skip it.
270                  * When we get here the baud detection code has
271                  * passed, so the only other things which can
272                  * cause this are dropped serial characters and
273                  * confused mouse.  We check this because otherwise
274                  * begin posting erroneous mouse events.
275                  */
276                 if ((byte & 0xf0) != 0x80)
277                         return;
278
279                 /* Button state */
280                 sunmouse.button_state = (~byte) & 0x7;
281 #ifdef SMOUSE_DEBUG
282                 printk("B<Left %s, Middle %s, Right %s>",
283                        ((sunmouse.button_state & 0x4) ? "DOWN" : "UP"),
284                        ((sunmouse.button_state & 0x2) ? "DOWN" : "UP"),
285                        ((sunmouse.button_state & 0x1) ? "DOWN" : "UP"));
286 #endif
287                 /* To deal with the Sparcbook 3 */
288                 if (byte & 0x8) {
289                         sunmouse.byte += 2;
290                         sunmouse.delta_y = 0;
291                         sunmouse.delta_x = 0;
292                 }
293                 sunmouse.byte++;
294                 return;
295         case 1:
296                 /* Delta-x 1 */
297 #ifdef SMOUSE_DEBUG
298                 printk("DX1<%d>", mvalue);
299 #endif
300                 sunmouse.delta_x = mvalue;
301                 sunmouse.byte++;
302                 return;
303         case 2:
304                 /* Delta-y 1 */
305 #ifdef SMOUSE_DEBUG
306                 printk("DY1<%d>", mvalue);
307 #endif
308                 sunmouse.delta_y = mvalue;
309                 sunmouse.byte++;
310                 return;
311         case 3:
312                 /* Delta-x 2 */
313 #ifdef SMOUSE_DEBUG
314                 printk("DX2<%d>", mvalue);
315 #endif
316                 sunmouse.delta_x += mvalue;
317                 sunmouse.delta_x = CLIP(sunmouse.delta_x);
318                 sunmouse.byte++;
319                 return;
320         case 4:
321                 /* Last byte, Delta-y 2 */
322 #ifdef SMOUSE_DEBUG
323                 printk("DY2<%d>", mvalue);
324 #endif
325                 sunmouse.delta_y += mvalue;
326                 sunmouse.delta_y = CLIP(sunmouse.delta_y);
327                 sunmouse.byte = 0;  /* Back to button state */
328                 break;
329         case 69:
330                 /* Until we get the (0x80 -> 0x87) value we aren't
331                  * in the middle of a real transaction, so just
332                  * return.
333                  */
334                 return;
335         default:
336                 printk("sunmouse: bogon transaction state\n");
337                 sunmouse.byte = 69;  /* What could cause this? */
338                 return;
339         };
340
341         if (!gen_events) {
342                 push_char (~sunmouse.button_state & 0x87);
343                 push_char (sunmouse.delta_x);
344                 push_char (sunmouse.delta_y);
345                 return;
346         }
347
348         d = bstate ^ pstate;
349         pstate = bstate;
350         if (d) {
351                 if (d & BUTTON_LEFT) {
352                         ev.id = MS_LEFT;
353                         ev.value = bstate & BUTTON_LEFT;
354                 }
355                 if (d & BUTTON_RIGHT) {
356                         ev.id = MS_RIGHT;
357                         ev.value = bstate & BUTTON_RIGHT;
358                 }
359                 if (d & BUTTON_MIDDLE) {
360                         ev.id = MS_MIDDLE;
361                         ev.value = bstate & BUTTON_MIDDLE;
362                 }
363                 ev.time = xtime;
364                 ev.value = ev.value ? VKEY_DOWN : VKEY_UP;
365                 pushed += push_event (&ev);
366         }
367         if (sunmouse.delta_x) {
368                 ev.id = LOC_X_DELTA;
369                 ev.time = xtime;
370                 ev.value = sunmouse.delta_x;
371                 pushed += push_event (&ev);
372                 sunmouse.delta_x = 0;
373         }
374         if (sunmouse.delta_y) {
375                 ev.id = LOC_Y_DELTA;
376                 ev.time = xtime;
377                 ev.value = sunmouse.delta_y;
378                 pushed += push_event (&ev);
379         }
380         
381         if (pushed != 0) {
382                 /* We just completed a transaction, wake up whoever is awaiting
383                  * this event.
384                  */
385                 kill_fasync (&sunmouse.fasync, SIGIO, POLL_IN);
386                 wake_up_interruptible(&sunmouse.proc_list);
387         }
388         return;
389 }
390
391 static int
392 sun_mouse_open(struct inode * inode, struct file * file)
393 {
394         spin_lock_irq(&sunmouse.lock);
395         if (sunmouse.active++)
396                 goto out;
397         sunmouse.delta_x = sunmouse.delta_y = 0;
398         sunmouse.button_state = 0x80;
399         sunmouse.vuid_mode = VUID_NATIVE;
400 out:
401         spin_unlock_irq(&sunmouse.lock);
402         return 0;
403 }
404
405 static int sun_mouse_fasync (int fd, struct file *filp, int on)
406 {
407         int retval;
408
409         retval = fasync_helper (fd, filp, on, &sunmouse.fasync);
410         if (retval < 0)
411                 return retval;
412         return 0;
413 }
414
415 static int
416 sun_mouse_close(struct inode *inode, struct file *file)
417 {
418         sun_mouse_fasync (-1, file, 0);
419
420         spin_lock_irq(&sunmouse.lock);
421         sunmouse.active--;
422         spin_unlock_irq(&sunmouse.lock);
423
424         return 0;
425 }
426
427 static ssize_t
428 sun_mouse_write(struct file *file, const char *buffer,
429                 size_t count, loff_t *ppos)
430 {
431         return -EINVAL;  /* foo on you */
432 }
433
434 static ssize_t
435 sun_mouse_read(struct file *file, char *buffer,
436                size_t count, loff_t *ppos)
437 {
438         DECLARE_WAITQUEUE(wait, current);
439         unsigned long flags;
440
441         if (queue_empty ()) {
442                 if (file->f_flags & O_NONBLOCK)
443                         return -EWOULDBLOCK;
444                 add_wait_queue (&sunmouse.proc_list, &wait);
445 repeat:
446                 set_current_state(TASK_INTERRUPTIBLE);
447                 if (queue_empty() && !signal_pending(current)) {
448                         schedule();
449                         goto repeat;
450                 }
451                 current->state = TASK_RUNNING;
452                 remove_wait_queue (&sunmouse.proc_list, &wait);
453         }
454         if (gen_events) {
455                 char *p = buffer, *end = buffer+count;
456                 
457                 spin_lock_irqsave(&sunmouse.lock, flags);
458                 while (p < end && !queue_empty ()){
459                         Firm_event this_event;
460
461                         get_from_queue(&this_event);
462                         spin_unlock_irqrestore(&sunmouse.lock, flags);
463
464 #ifdef CONFIG_SPARC32_COMPAT
465                         if (current->thread.flags & SPARC_FLAG_32BIT) {
466                                 if ((end - p) <
467                                     ((sizeof(Firm_event) - sizeof(struct timeval) +
468                                       (sizeof(u32) * 2))))
469                                         break;
470                                 if (copy_to_user((Firm_event *)p, &this_event,
471                                                  sizeof(Firm_event)-sizeof(struct timeval)))
472                                         return -EFAULT;
473                                 p += sizeof(Firm_event)-sizeof(struct timeval);
474                                 if (__put_user(this_event.time.tv_sec, (u32 *)p))
475                                         return -EFAULT;
476                                 p += sizeof(u32);
477                                 if (__put_user(this_event.time.tv_usec, (u32 *)p))
478                                         return -EFAULT;
479                                 p += sizeof(u32);
480                         } else
481 #endif  
482                         {       
483                                 if ((end - p) < sizeof(Firm_event))
484                                         break;
485                                 if (copy_to_user((Firm_event *)p, &this_event,
486                                                  sizeof(Firm_event)))
487                                         return -EFAULT;
488                                 p += sizeof (Firm_event);
489                         }
490                         spin_lock_irqsave(&sunmouse.lock, flags);
491                 }
492                 spin_unlock_irqrestore(&sunmouse.lock, flags);
493                 file->f_dentry->d_inode->i_atime = CURRENT_TIME;
494                 return p-buffer;
495         } else {
496                 int c, limit = 3;
497
498                 if (count < limit)
499                         limit = count;
500                 for (c = 0; c < limit; c++) {
501                         unsigned char val;
502                         int empty = 0;
503
504                         spin_lock_irqsave(&sunmouse.lock, flags);
505                         if (queue_empty()) {
506                                 empty = 1;
507                                 val = 0;
508                         } else {
509                                 val = sunmouse.queue.stream[sunmouse.tail];
510                                 sunmouse.tail = (sunmouse.tail + 1) % STREAM_SIZE;
511                         }
512                         spin_unlock_irqrestore(&sunmouse.lock, flags);
513
514                         if (empty)
515                                 break;
516
517                         put_user(val, buffer);
518                         buffer++;
519                 }
520                 while (c < count) {
521                         if (c >= 5)
522                                 break;
523                         put_user(0, buffer);
524                         buffer++;
525                         c++;
526                 }
527                 file->f_dentry->d_inode->i_atime = CURRENT_TIME;
528                 return c;
529         }
530         /* Only called if nothing was sent */
531         if (signal_pending(current))
532                 return -ERESTARTSYS;
533         return 0;
534 }
535
536 static unsigned int sun_mouse_poll(struct file *file, poll_table *wait)
537 {
538         poll_wait(file, &sunmouse.proc_list, wait);
539         if(!queue_empty())
540                 return POLLIN | POLLRDNORM;
541         return 0;
542 }
543 int
544 sun_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
545 {
546         int i;
547         
548         switch (cmd){
549                 /* VUIDGFORMAT - Get input device byte stream format */
550         case _IOR('v', 2, int):
551                 if (put_user(sunmouse.vuid_mode, (int *) arg))
552                         return -EFAULT;
553                 break;
554
555                 /* VUIDSFORMAT - Set input device byte stream format*/
556         case _IOW('v', 1, int):
557                 if (get_user(i, (int *) arg))
558                         return -EFAULT;
559                 if (i == VUID_NATIVE || i == VUID_FIRM_EVENT){
560                         int value;
561
562                         if (get_user(value, (int *)arg))
563                                 return -EFAULT;
564
565                         spin_lock_irq(&sunmouse.lock);
566                         sunmouse.vuid_mode = value;
567                         sunmouse.head = sunmouse.tail = 0;
568                         spin_unlock_irq(&sunmouse.lock);
569                 } else
570                         return -EINVAL;
571                 break;
572
573         case 0x8024540b:
574         case 0x40245408:
575                 /* This is a buggy application doing termios on the mouse driver */
576                 /* we ignore it.  I keep this check here so that we will notice   */
577                 /* future mouse vuid ioctls */
578                 return -ENOTTY;
579                 
580         default:
581 #ifdef DEBUG
582                 printk ("[MOUSE-ioctl: %8.8x]\n", cmd);
583 #endif
584                 return -EINVAL;
585         }
586         return 0;
587 }
588
589 struct file_operations sun_mouse_fops = {
590         read:           sun_mouse_read,
591         write:          sun_mouse_write,
592         poll:           sun_mouse_poll,
593         ioctl:          sun_mouse_ioctl,
594         open:           sun_mouse_open,
595         release:        sun_mouse_close,
596         fasync:         sun_mouse_fasync,
597 };
598
599 static struct miscdevice sun_mouse_mouse = {
600         SUN_MOUSE_MINOR, "sunmouse", &sun_mouse_fops
601 };
602
603 void sun_mouse_zsinit(void)
604 {
605         printk("Sun Mouse-Systems mouse driver version 1.00\n");
606
607         sunmouse.active = 0;
608         misc_register (&sun_mouse_mouse);
609         sunmouse.delta_x = sunmouse.delta_y = 0;
610         sunmouse.button_state = 0x80;
611         init_waitqueue_head(&sunmouse.proc_list);
612         spin_lock_init(&sunmouse.lock);
613         sunmouse.byte = 69;
614 }