155106Storek /* 255106Storek * Copyright (c) 1992 The Regents of the University of California. 355106Storek * All rights reserved. 455106Storek * 555106Storek * This software was developed by the Computer Systems Engineering group 655106Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 755106Storek * contributed to Berkeley. 855106Storek * 955499Sbostic * All advertising materials mentioning features or use of this software 1055499Sbostic * must display the following acknowledgement: 1155499Sbostic * This product includes software developed by the University of 1255499Sbostic * California, Lawrence Berkeley Laboratories. 1355499Sbostic * 1455106Storek * %sccs.include.redist.c% 1555106Storek * 16*56536Sbostic * @(#)ms.c 7.3 (Berkeley) 10/11/92 1755106Storek * 1855106Storek * from: $Header: ms.c,v 1.4 92/06/17 05:35:50 torek Exp $ (LBL) 1955106Storek */ 2055106Storek 2155106Storek /* 2255106Storek * Mouse driver. 2355106Storek */ 2455106Storek 25*56536Sbostic #include <sys/param.h> 26*56536Sbostic #include <sys/conf.h> 27*56536Sbostic #include <sys/ioctl.h> 28*56536Sbostic #include <sys/kernel.h> 29*56536Sbostic #include <sys/proc.h> 30*56536Sbostic #include <sys/syslog.h> 31*56536Sbostic #include <sys/systm.h> 32*56536Sbostic #include <sys/tty.h> 3355106Storek 34*56536Sbostic #include <sparc/dev/vuid_event.h> 35*56536Sbostic #include <sparc/dev/event_var.h> 3655106Storek 3755106Storek /* 3855106Storek * Mouse state. A Mouse Systems mouse is a fairly simple device, 3955106Storek * producing five-byte blobs of the form: 4055106Storek * 4155106Storek * b dx dy dx dy 4255106Storek * 4355106Storek * where b is the button state, encoded as 0x80|(~buttons)---there are 4455106Storek * three buttons (4=left, 2=middle, 1=right)---and dx,dy are X and Y 4555106Storek * delta values, none of which have are in [0x80..0x87]. (This lets 4655106Storek * us sync up with the mouse after an error.) 4755106Storek */ 4855106Storek struct ms_softc { 4955106Storek short ms_byteno; /* input byte number, for decode */ 5055106Storek char ms_mb; /* mouse button state */ 5155106Storek char ms_ub; /* user button state */ 5255106Storek int ms_dx; /* delta-x */ 5355106Storek int ms_dy; /* delta-y */ 5455106Storek struct tty *ms_mouse; /* downlink for output to mouse */ 5555106Storek void (*ms_open) __P((struct tty *)); /* enable dataflow */ 5655106Storek void (*ms_close) __P((struct tty *));/* disable dataflow */ 5755106Storek volatile int ms_ready; /* event queue is ready */ 5855106Storek struct evvar ms_events; /* event queue state */ 5955106Storek } ms_softc; 6055106Storek 6155106Storek /* 6255106Storek * Attach the mouse serial (down-link) interface. 6355106Storek * Do we need to set it to 1200 baud, 8 bits? 6455106Storek * Test by power cycling and not booting SunOS before BSD? 6555106Storek */ 6655106Storek void 6755106Storek ms_serial(tp, iopen, iclose) 6855106Storek struct tty *tp; 6955106Storek void (*iopen)(), (*iclose)(); 7055106Storek { 7155106Storek 7255106Storek ms_softc.ms_mouse = tp; 7355106Storek ms_softc.ms_open = iopen; 7455106Storek ms_softc.ms_close = iclose; 7555106Storek } 7655106Storek 7755106Storek void 7855106Storek ms_rint(c) 7955106Storek register int c; 8055106Storek { 8155106Storek register struct firm_event *fe; 8255106Storek register struct ms_softc *ms = &ms_softc; 8355106Storek register int mb, ub, d, get, put, any; 8455106Storek static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 }; 8555106Storek static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT }; 8655106Storek 8755106Storek /* 8855106Storek * Discard input if not ready. Drop sync on parity or framing 8955106Storek * error; gain sync on button byte. 9055106Storek */ 9155106Storek if (ms->ms_ready == 0) 9255106Storek return; 9355106Storek if (c & (TTY_FE|TTY_PE)) { 9455106Storek log(LOG_WARNING, 9555106Storek "mouse input parity or framing error (0x%x)\n", c); 9655106Storek ms->ms_byteno = -1; 9755106Storek return; 9855106Storek } 9955106Storek if ((unsigned)(c - 0x80) < 8) /* if in 0x80..0x87 */ 10055106Storek ms->ms_byteno = 0; 10155106Storek 10255106Storek /* 10355106Storek * Run the decode loop, adding to the current information. 10455106Storek * We add, rather than replace, deltas, so that if the event queue 10555106Storek * fills, we accumulate data for when it opens up again. 10655106Storek */ 10755106Storek switch (ms->ms_byteno) { 10855106Storek 10955106Storek case -1: 11055106Storek return; 11155106Storek 11255106Storek case 0: 11355106Storek /* buttons */ 11455106Storek ms->ms_byteno = 1; 11555106Storek ms->ms_mb = (~c) & 0x7; 11655106Storek return; 11755106Storek 11855106Storek case 1: 11955106Storek /* first delta-x */ 12055106Storek ms->ms_byteno = 2; 12155106Storek ms->ms_dx += (char)c; 12255106Storek return; 12355106Storek 12455106Storek case 2: 12555106Storek /* first delta-y */ 12655106Storek ms->ms_byteno = 3; 12755106Storek ms->ms_dy += (char)c; 12855106Storek return; 12955106Storek 13055106Storek case 3: 13155106Storek /* second delta-x */ 13255106Storek ms->ms_byteno = 4; 13355106Storek ms->ms_dx += (char)c; 13455106Storek return; 13555106Storek 13655106Storek case 4: 13755106Storek /* second delta-x */ 13855106Storek ms->ms_byteno = -1; /* wait for button-byte again */ 13955106Storek ms->ms_dy += (char)c; 14055106Storek break; 14155106Storek 14255106Storek default: 14355106Storek panic("ms_rint"); 14455106Storek /* NOTREACHED */ 14555106Storek } 14655106Storek 14755106Storek /* 14855106Storek * We have at least one event (mouse button, delta-X, or 14955106Storek * delta-Y; possibly all three, and possibly three separate 15055106Storek * button events). Deliver these events until we are out 15155106Storek * of changes or out of room. As events get delivered, 15255106Storek * mark them `unchanged'. 15355106Storek */ 15455106Storek any = 0; 15555106Storek get = ms->ms_events.ev_get; 15655106Storek put = ms->ms_events.ev_put; 15755106Storek fe = &ms->ms_events.ev_q[put]; 15855106Storek 15955106Storek /* NEXT prepares to put the next event, backing off if necessary */ 16055106Storek #define NEXT \ 16155106Storek if ((++put) % EV_QSIZE == get) { \ 16255106Storek put--; \ 16355106Storek goto out; \ 16455106Storek } 16555106Storek /* ADVANCE completes the `put' of the event */ 16655106Storek #define ADVANCE \ 16755106Storek fe++; \ 16855106Storek if (put >= EV_QSIZE) { \ 16955106Storek put = 0; \ 17055106Storek fe = &ms->ms_events.ev_q[0]; \ 17155106Storek } \ 17255106Storek any = 1 17355106Storek 17455106Storek mb = ms->ms_mb; 17555106Storek ub = ms->ms_ub; 17655106Storek while ((d = mb ^ ub) != 0) { 17755106Storek /* 17855106Storek * Mouse button change. Convert up to three changes 17955106Storek * to the `first' change, and drop it into the event queue. 18055106Storek */ 18155106Storek NEXT; 18255106Storek d = to_one[d - 1]; /* from 1..7 to {1,2,4} */ 18355106Storek fe->id = to_id[d - 1]; /* from {1,2,4} to ID */ 18455106Storek fe->value = mb & d ? VKEY_DOWN : VKEY_UP; 18555106Storek fe->time = time; 18655106Storek ADVANCE; 18755106Storek ub ^= d; 18855106Storek } 18955106Storek if (ms->ms_dx) { 19055106Storek NEXT; 19155106Storek fe->id = LOC_X_DELTA; 19255106Storek fe->value = ms->ms_dx; 19355106Storek fe->time = time; 19455106Storek ADVANCE; 19555106Storek ms->ms_dx = 0; 19655106Storek } 19755106Storek if (ms->ms_dy) { 19855106Storek NEXT; 19955106Storek fe->id = LOC_Y_DELTA; 20055106Storek fe->value = ms->ms_dy; 20155106Storek fe->time = time; 20255106Storek ADVANCE; 20355106Storek ms->ms_dy = 0; 20455106Storek } 20555106Storek out: 20655106Storek if (any) { 20755106Storek ms->ms_ub = ub; 20855106Storek ms->ms_events.ev_put = put; 20955106Storek EV_WAKEUP(&ms->ms_events); 21055106Storek } 21155106Storek } 21255106Storek 21355106Storek int 21455106Storek msopen(dev, flags, mode, p) 21555106Storek dev_t dev; 21655106Storek int flags, mode; 21755106Storek struct proc *p; 21855106Storek { 21955106Storek int s, error; 22055106Storek 22155106Storek if (ms_softc.ms_events.ev_io) 22255106Storek return (EBUSY); 22355106Storek ms_softc.ms_events.ev_io = p; 22455106Storek ev_init(&ms_softc.ms_events); /* may cause sleep */ 22555106Storek ms_softc.ms_ready = 1; /* start accepting events */ 22655106Storek (*ms_softc.ms_open)(ms_softc.ms_mouse); 22755106Storek return (0); 22855106Storek } 22955106Storek 23055106Storek int 23155106Storek msclose(dev, flags, mode, p) 23255106Storek dev_t dev; 23355106Storek int flags, mode; 23455106Storek struct proc *p; 23555106Storek { 23655106Storek 23755106Storek ms_softc.ms_ready = 0; /* stop accepting events */ 23855106Storek ev_fini(&ms_softc.ms_events); 23955106Storek (*ms_softc.ms_close)(ms_softc.ms_mouse); 24055106Storek ms_softc.ms_events.ev_io = NULL; 24155106Storek return (0); 24255106Storek } 24355106Storek 24455106Storek int 24555106Storek msread(dev, uio, flags) 24655106Storek dev_t dev; 24755106Storek struct uio *uio; 24855106Storek int flags; 24955106Storek { 25055106Storek 25155106Storek return (ev_read(&ms_softc.ms_events, uio, flags)); 25255106Storek } 25355106Storek 25455106Storek /* this routine should not exist, but is convenient to write here for now */ 25555106Storek int 25655106Storek mswrite(dev, uio, flags) 25755106Storek dev_t dev; 25855106Storek struct uio *uio; 25955106Storek int flags; 26055106Storek { 26155106Storek 26255106Storek return (EOPNOTSUPP); 26355106Storek } 26455106Storek 26555106Storek int 26655106Storek msioctl(dev, cmd, data, flag, p) 26755106Storek dev_t dev; 26855106Storek int cmd; 26955106Storek register caddr_t data; 27055106Storek int flag; 27155106Storek struct proc *p; 27255106Storek { 27355106Storek int s; 27455106Storek 27555106Storek switch (cmd) { 27655106Storek 27755106Storek case FIONBIO: /* we will remove this someday (soon???) */ 27855106Storek return (0); 27955106Storek 28055106Storek case FIOASYNC: 28155106Storek ms_softc.ms_events.ev_async = *(int *)data != 0; 28255106Storek return (0); 28355106Storek 28455106Storek case TIOCSPGRP: 28555106Storek if (*(int *)data != ms_softc.ms_events.ev_io->p_pgid) 28655106Storek return (EPERM); 28755106Storek return (0); 28855106Storek 28955106Storek case VUIDGFORMAT: 29055106Storek /* we only do firm_events */ 29155106Storek *(int *)data = VUID_FIRM_EVENT; 29255106Storek return (0); 29355106Storek 29455106Storek case VUIDSFORMAT: 29555106Storek if (*(int *)data != VUID_FIRM_EVENT) 29655106Storek return (EINVAL); 29755106Storek return (0); 29855106Storek } 29955106Storek return (ENOTTY); 30055106Storek } 30155106Storek 30255106Storek int 30355106Storek msselect(dev, rw, p) 30455106Storek dev_t dev; 30555106Storek int rw; 30655106Storek struct proc *p; 30755106Storek { 30855106Storek 30955106Storek return (ev_select(&ms_softc.ms_events, rw, p)); 31055106Storek } 311