Home | History | Annotate | Line # | Download | only in dev
ms.c revision 1.2
      1 /*
      2  * based on:
      3  *
      4  * Copyright (c) 1992, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * This software was developed by the Computer Systems Engineering group
      8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
      9  * contributed to Berkeley.
     10  *
     11  * All advertising materials mentioning features or use of this software
     12  * must display the following acknowledgement:
     13  *	This product includes software developed by the University of
     14  *	California, Lawrence Berkeley Laboratory.
     15  *
     16  * Redistribution and use in source and binary forms, with or without
     17  * modification, are permitted provided that the following conditions
     18  * are met:
     19  * 1. Redistributions of source code must retain the above copyright
     20  *    notice, this list of conditions and the following disclaimer.
     21  * 2. Redistributions in binary form must reproduce the above copyright
     22  *    notice, this list of conditions and the following disclaimer in the
     23  *    documentation and/or other materials provided with the distribution.
     24  * 3. All advertising materials mentioning features or use of this software
     25  *    must display the following acknowledgement:
     26  *	This product includes software developed by the University of
     27  *	California, Berkeley and its contributors.
     28  * 4. Neither the name of the University nor the names of its contributors
     29  *    may be used to endorse or promote products derived from this software
     30  *    without specific prior written permission.
     31  *
     32  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     34  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     35  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     36  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     40  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     41  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     42  * SUCH DAMAGE.
     43  *
     44  *	@(#)ms.c	8.1 (Berkeley) 6/11/93
     45  *
     46  * from: Header: ms.c,v 1.5 92/11/26 01:28:47 torek Exp  (LBL)
     47  * $Id: ms.c,v 1.2 1994/02/13 21:10:50 chopps Exp $
     48  */
     49 
     50 /*
     51  * Mouse driver.
     52  */
     53 
     54 #include <sys/param.h>
     55 #include <sys/conf.h>
     56 #include <sys/ioctl.h>
     57 #include <sys/kernel.h>
     58 #include <sys/proc.h>
     59 #include <sys/syslog.h>
     60 #include <sys/systm.h>
     61 #include <sys/tty.h>
     62 
     63 #include <amiga/dev/event_var.h>
     64 #include <amiga/dev/vuid_event.h>
     65 
     66 #include <amiga/amiga/custom.h>
     67 #include <amiga/amiga/cia.h>
     68 
     69 #include "mouse.h"
     70 #if NMOUSE > 0
     71 
     72 /* there's really no more physical ports on an amiga.. */
     73 #if NMOUSE > 2
     74 #undef NMOUSE
     75 #define NMOUSE 2
     76 #endif
     77 
     78 void msintr (int unit);
     79 
     80 /* Amiga mice are hooked up to one of the two "game" ports, where
     81    the main mouse is usually on the first port, and port 2 can
     82    be used by a joystick. Nevertheless, we support two mouse
     83    devices, /dev/mouse0 and /dev/mouse1 (with a link of /dev/mouse to
     84    the device that represents the port of the mouse in use). */
     85 
     86 struct ms_softc {
     87 	u_char	ms_horc;	   /* horizontal counter on last scan */
     88   	u_char	ms_verc;	   /* vertical counter on last scan */
     89 	char	ms_mb;		   /* mouse button state */
     90 	char	ms_ub;		   /* user button state */
     91 	int	ms_dx;		   /* delta-x */
     92 	int	ms_dy;		   /* delta-y */
     93 	volatile int ms_ready;	   /* event queue is ready */
     94 	struct	evvar ms_events;   /* event queue state */
     95 } ms_softc[NMOUSE];
     96 
     97 
     98 /* enable scanner, called when someone opens the device.
     99    Assume caller already validated range of dev. */
    100 void
    101 ms_enable (dev_t dev)
    102 {
    103   int unit = minor (dev);
    104   struct ms_softc *ms = &ms_softc[unit];
    105 
    106   /* use this as flag to the "interrupt" to tell it when to
    107      shut off (when it's reset to 0). */
    108   ms->ms_ready = 1;
    109 
    110   timeout ((timeout_t) msintr, (caddr_t) unit, 2);
    111 }
    112 
    113 /* disable scanner. Just set ms_ready to 0, and after the next
    114    timeout taken, no further timeouts will be initiated. */
    115 void
    116 ms_disable (dev_t dev)
    117 {
    118   struct ms_softc *ms = &ms_softc[minor (dev)];
    119   int s = splhigh ();
    120 
    121   ms->ms_ready = 0;
    122   /* sync with the interrupt */
    123   tsleep ((caddr_t) ms, PZERO - 1, "mouse-disable", 0);
    124   splx (s);
    125 }
    126 
    127 
    128 void
    129 msintr (int unit)
    130 {
    131   struct ms_softc *ms = &ms_softc[unit];
    132   register struct firm_event *fe;
    133   register int mb, ub, d, get, put, any;
    134   static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 };
    135   static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT };
    136   u_short pot;
    137   u_char  pra;
    138   u_short count;
    139   u_char  *horc = ((u_char *) &count) + 1;
    140   u_char  *verc = (u_char *) &count;
    141   short	  dx, dy;
    142 
    143   /* BTW: we're emulating a mousesystems serial mouse here.. */
    144 
    145   /* first read the three buttons. */
    146   pot  = custom.potgor;
    147   pra  = ciaa.pra;
    148   pot  >>= unit == 0 ? 8 : 12;	/* contains right and middle button */
    149   pra  >>= unit == 0 ? 6 : 7;	/* contains left button */
    150   mb = (pot & 4) / 4 + (pot & 1) * 2 + (pra & 1) * 4;
    151   mb ^= 0x07;
    152 
    153   /* read current values of counter registers */
    154   count = unit == 0 ? custom.joy0dat : custom.joy1dat;
    155 
    156   /* take care of wraparound */
    157   dx = *horc - ms->ms_horc;
    158   if (dx < -127)
    159     dx += 255;
    160   else if (dx > 127)
    161     dx -= 255;
    162   dy = *verc - ms->ms_verc;
    163   if (dy < -127)
    164     dy += 255;
    165   else if (dy > 127)
    166     dy -= 255;
    167 
    168   /* remember current values for next scan */
    169   ms->ms_horc = *horc;
    170   ms->ms_verc = *verc;
    171 
    172   ms->ms_dx = dx;
    173   ms->ms_dy = dy;
    174   ms->ms_mb = mb;
    175 
    176   if (dx || dy || ms->ms_ub != ms->ms_mb)
    177     {
    178 
    179       /* We have at least one event (mouse button, delta-X, or
    180 	 delta-Y; possibly all three, and possibly three separate
    181 	 button events).  Deliver these events until we are out
    182 	 of changes or out of room.  As events get delivered,
    183 	 mark them `unchanged'. */
    184 
    185       any = 0;
    186       get = ms->ms_events.ev_get;
    187       put = ms->ms_events.ev_put;
    188       fe = &ms->ms_events.ev_q[put];
    189 
    190       /* NEXT prepares to put the next event, backing off if necessary */
    191 #define	NEXT \
    192       if ((++put) % EV_QSIZE == get)  \
    193 	{ \
    194           put--; \
    195 	  goto out; \
    196 	}
    197       /* ADVANCE completes the `put' of the event */
    198 #define	ADVANCE \
    199       fe++; \
    200       if (put >= EV_QSIZE) \
    201 	{ \
    202 	  put = 0; \
    203 	  fe = &ms->ms_events.ev_q[0]; \
    204 	} \
    205       any = 1
    206 
    207       mb = ms->ms_mb;
    208       ub = ms->ms_ub;
    209       while ((d = mb ^ ub) != 0)
    210 	{
    211 	  /* Mouse button change.  Convert up to three changes
    212 	     to the `first' change, and drop it into the event queue. */
    213 
    214 	  NEXT;
    215 	  d = to_one[d - 1];		/* from 1..7 to {1,2,4} */
    216 	  fe->id = to_id[d - 1];		/* from {1,2,4} to ID */
    217 	  fe->value = mb & d ? VKEY_DOWN : VKEY_UP;
    218 	  fe->time = time;
    219 	  ADVANCE;
    220 	  ub ^= d;
    221 	}
    222       if (ms->ms_dx)
    223 	{
    224 	  NEXT;
    225 	  fe->id = LOC_X_DELTA;
    226 	  fe->value = ms->ms_dx;
    227 	  fe->time = time;
    228 	  ADVANCE;
    229 	  ms->ms_dx = 0;
    230 	}
    231       if (ms->ms_dy)
    232 	{
    233 	  NEXT;
    234 	  fe->id = LOC_Y_DELTA;
    235 	  fe->value = ms->ms_dy;
    236 	  fe->time = time;
    237 	  ADVANCE;
    238 	  ms->ms_dy = 0;
    239 	}
    240 out:
    241       if (any)
    242 	{
    243 	  ms->ms_ub = ub;
    244 	  ms->ms_events.ev_put = put;
    245 	  EV_WAKEUP(&ms->ms_events);
    246 	}
    247     }
    248 
    249   /* reschedule handler, or if terminating, handshake with ms_disable */
    250   if (ms->ms_ready)
    251     timeout ((timeout_t) msintr, (caddr_t) unit, 2);
    252   else
    253     wakeup ((caddr_t) ms);
    254 
    255 }
    256 
    257 int
    258 msopen (dev, flags, mode, p)
    259      dev_t dev;
    260      int flags, mode;
    261      struct proc *p;
    262 {
    263   int unit = minor (dev);
    264   struct ms_softc *ms = &ms_softc[unit];
    265   int s, error;
    266 
    267   if (unit >= NMOUSE)
    268     return EXDEV;
    269 
    270   if (ms->ms_events.ev_io)
    271     return EBUSY;
    272 
    273   ms->ms_events.ev_io = p;
    274   ev_init (&ms->ms_events);	/* may cause sleep */
    275   ms_enable (dev);
    276   return 0;
    277 }
    278 
    279 int
    280 msclose (dev, flags, mode, p)
    281      dev_t dev;
    282      int flags, mode;
    283      struct proc *p;
    284 {
    285   int unit = minor (dev);
    286   struct ms_softc *ms = &ms_softc[unit];
    287 
    288   ms_disable (dev);
    289   ev_fini (&ms->ms_events);
    290   ms->ms_events.ev_io = NULL;
    291   return 0;
    292 }
    293 
    294 int
    295 msread (dev, uio, flags)
    296      dev_t dev;
    297      struct uio *uio;
    298      int flags;
    299 {
    300   int unit = minor (dev);
    301   struct ms_softc *ms = &ms_softc[unit];
    302 
    303   return ev_read (&ms->ms_events, uio, flags);
    304 }
    305 
    306 /* this routine should not exist, but is convenient to write here for now */
    307 int
    308 mswrite (dev, uio, flags)
    309      dev_t dev;
    310      struct uio *uio;
    311      int flags;
    312 {
    313   return EOPNOTSUPP;
    314 }
    315 
    316 int
    317 msioctl (dev, cmd, data, flag, p)
    318      dev_t dev;
    319      int cmd;
    320      register caddr_t data;
    321      int flag;
    322      struct proc *p;
    323 {
    324   int unit = minor (dev);
    325   struct ms_softc *ms = &ms_softc[unit];
    326 
    327   switch (cmd)
    328     {
    329     case FIONBIO:		/* we will remove this someday (soon???) */
    330       return 0;
    331 
    332     case FIOASYNC:
    333       ms->ms_events.ev_async = *(int *)data != 0;
    334       return 0;
    335 
    336     case TIOCSPGRP:
    337       if (*(int *)data != ms->ms_events.ev_io->p_pgid)
    338 	return EPERM;
    339       return 0;
    340 
    341     case VUIDGFORMAT:
    342       /* we only do firm_events */
    343       *(int *)data = VUID_FIRM_EVENT;
    344       return 0;
    345 
    346     case VUIDSFORMAT:
    347       if (*(int *)data != VUID_FIRM_EVENT)
    348 	return EINVAL;
    349       return 0;
    350     }
    351 
    352   return ENOTTY;
    353 }
    354 
    355 int
    356 msselect (dev, rw, p)
    357      dev_t dev;
    358      int rw;
    359      struct proc *p;
    360 {
    361   int unit = minor (dev);
    362   struct ms_softc *ms = &ms_softc[unit];
    363 
    364   return ev_select (&ms->ms_events, rw, p);
    365 }
    366 
    367 void
    368 mouseattach() {}
    369 #endif /* NMOUSE > 0 */
    370