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