1*55106Storek /* 2*55106Storek * Copyright (c) 1992 The Regents of the University of California. 3*55106Storek * All rights reserved. 4*55106Storek * 5*55106Storek * This software was developed by the Computer Systems Engineering group 6*55106Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7*55106Storek * contributed to Berkeley. 8*55106Storek * 9*55106Storek * %sccs.include.redist.c% 10*55106Storek * 11*55106Storek * @(#)ms.c 7.1 (Berkeley) 07/13/92 12*55106Storek * 13*55106Storek * from: $Header: ms.c,v 1.4 92/06/17 05:35:50 torek Exp $ (LBL) 14*55106Storek */ 15*55106Storek 16*55106Storek /* 17*55106Storek * Mouse driver. 18*55106Storek */ 19*55106Storek 20*55106Storek #include "sys/param.h" 21*55106Storek #include "sys/conf.h" 22*55106Storek #include "sys/ioctl.h" 23*55106Storek #include "sys/kernel.h" 24*55106Storek #include "sys/proc.h" 25*55106Storek #include "sys/syslog.h" 26*55106Storek #include "sys/systm.h" 27*55106Storek #include "sys/tty.h" 28*55106Storek 29*55106Storek #include "vuid_event.h" 30*55106Storek #include "event_var.h" 31*55106Storek 32*55106Storek /* 33*55106Storek * Mouse state. A Mouse Systems mouse is a fairly simple device, 34*55106Storek * producing five-byte blobs of the form: 35*55106Storek * 36*55106Storek * b dx dy dx dy 37*55106Storek * 38*55106Storek * where b is the button state, encoded as 0x80|(~buttons)---there are 39*55106Storek * three buttons (4=left, 2=middle, 1=right)---and dx,dy are X and Y 40*55106Storek * delta values, none of which have are in [0x80..0x87]. (This lets 41*55106Storek * us sync up with the mouse after an error.) 42*55106Storek */ 43*55106Storek struct ms_softc { 44*55106Storek short ms_byteno; /* input byte number, for decode */ 45*55106Storek char ms_mb; /* mouse button state */ 46*55106Storek char ms_ub; /* user button state */ 47*55106Storek int ms_dx; /* delta-x */ 48*55106Storek int ms_dy; /* delta-y */ 49*55106Storek struct tty *ms_mouse; /* downlink for output to mouse */ 50*55106Storek void (*ms_open) __P((struct tty *)); /* enable dataflow */ 51*55106Storek void (*ms_close) __P((struct tty *));/* disable dataflow */ 52*55106Storek volatile int ms_ready; /* event queue is ready */ 53*55106Storek struct evvar ms_events; /* event queue state */ 54*55106Storek } ms_softc; 55*55106Storek 56*55106Storek /* 57*55106Storek * Attach the mouse serial (down-link) interface. 58*55106Storek * Do we need to set it to 1200 baud, 8 bits? 59*55106Storek * Test by power cycling and not booting SunOS before BSD? 60*55106Storek */ 61*55106Storek void 62*55106Storek ms_serial(tp, iopen, iclose) 63*55106Storek struct tty *tp; 64*55106Storek void (*iopen)(), (*iclose)(); 65*55106Storek { 66*55106Storek 67*55106Storek ms_softc.ms_mouse = tp; 68*55106Storek ms_softc.ms_open = iopen; 69*55106Storek ms_softc.ms_close = iclose; 70*55106Storek } 71*55106Storek 72*55106Storek void 73*55106Storek ms_rint(c) 74*55106Storek register int c; 75*55106Storek { 76*55106Storek register struct firm_event *fe; 77*55106Storek register struct ms_softc *ms = &ms_softc; 78*55106Storek register int mb, ub, d, get, put, any; 79*55106Storek static const char to_one[] = { 1, 2, 2, 4, 4, 4, 4 }; 80*55106Storek static const int to_id[] = { MS_RIGHT, MS_MIDDLE, 0, MS_LEFT }; 81*55106Storek 82*55106Storek /* 83*55106Storek * Discard input if not ready. Drop sync on parity or framing 84*55106Storek * error; gain sync on button byte. 85*55106Storek */ 86*55106Storek if (ms->ms_ready == 0) 87*55106Storek return; 88*55106Storek if (c & (TTY_FE|TTY_PE)) { 89*55106Storek log(LOG_WARNING, 90*55106Storek "mouse input parity or framing error (0x%x)\n", c); 91*55106Storek ms->ms_byteno = -1; 92*55106Storek return; 93*55106Storek } 94*55106Storek if ((unsigned)(c - 0x80) < 8) /* if in 0x80..0x87 */ 95*55106Storek ms->ms_byteno = 0; 96*55106Storek 97*55106Storek /* 98*55106Storek * Run the decode loop, adding to the current information. 99*55106Storek * We add, rather than replace, deltas, so that if the event queue 100*55106Storek * fills, we accumulate data for when it opens up again. 101*55106Storek */ 102*55106Storek switch (ms->ms_byteno) { 103*55106Storek 104*55106Storek case -1: 105*55106Storek return; 106*55106Storek 107*55106Storek case 0: 108*55106Storek /* buttons */ 109*55106Storek ms->ms_byteno = 1; 110*55106Storek ms->ms_mb = (~c) & 0x7; 111*55106Storek return; 112*55106Storek 113*55106Storek case 1: 114*55106Storek /* first delta-x */ 115*55106Storek ms->ms_byteno = 2; 116*55106Storek ms->ms_dx += (char)c; 117*55106Storek return; 118*55106Storek 119*55106Storek case 2: 120*55106Storek /* first delta-y */ 121*55106Storek ms->ms_byteno = 3; 122*55106Storek ms->ms_dy += (char)c; 123*55106Storek return; 124*55106Storek 125*55106Storek case 3: 126*55106Storek /* second delta-x */ 127*55106Storek ms->ms_byteno = 4; 128*55106Storek ms->ms_dx += (char)c; 129*55106Storek return; 130*55106Storek 131*55106Storek case 4: 132*55106Storek /* second delta-x */ 133*55106Storek ms->ms_byteno = -1; /* wait for button-byte again */ 134*55106Storek ms->ms_dy += (char)c; 135*55106Storek break; 136*55106Storek 137*55106Storek default: 138*55106Storek panic("ms_rint"); 139*55106Storek /* NOTREACHED */ 140*55106Storek } 141*55106Storek 142*55106Storek /* 143*55106Storek * We have at least one event (mouse button, delta-X, or 144*55106Storek * delta-Y; possibly all three, and possibly three separate 145*55106Storek * button events). Deliver these events until we are out 146*55106Storek * of changes or out of room. As events get delivered, 147*55106Storek * mark them `unchanged'. 148*55106Storek */ 149*55106Storek any = 0; 150*55106Storek get = ms->ms_events.ev_get; 151*55106Storek put = ms->ms_events.ev_put; 152*55106Storek fe = &ms->ms_events.ev_q[put]; 153*55106Storek 154*55106Storek /* NEXT prepares to put the next event, backing off if necessary */ 155*55106Storek #define NEXT \ 156*55106Storek if ((++put) % EV_QSIZE == get) { \ 157*55106Storek put--; \ 158*55106Storek goto out; \ 159*55106Storek } 160*55106Storek /* ADVANCE completes the `put' of the event */ 161*55106Storek #define ADVANCE \ 162*55106Storek fe++; \ 163*55106Storek if (put >= EV_QSIZE) { \ 164*55106Storek put = 0; \ 165*55106Storek fe = &ms->ms_events.ev_q[0]; \ 166*55106Storek } \ 167*55106Storek any = 1 168*55106Storek 169*55106Storek mb = ms->ms_mb; 170*55106Storek ub = ms->ms_ub; 171*55106Storek while ((d = mb ^ ub) != 0) { 172*55106Storek /* 173*55106Storek * Mouse button change. Convert up to three changes 174*55106Storek * to the `first' change, and drop it into the event queue. 175*55106Storek */ 176*55106Storek NEXT; 177*55106Storek d = to_one[d - 1]; /* from 1..7 to {1,2,4} */ 178*55106Storek fe->id = to_id[d - 1]; /* from {1,2,4} to ID */ 179*55106Storek fe->value = mb & d ? VKEY_DOWN : VKEY_UP; 180*55106Storek fe->time = time; 181*55106Storek ADVANCE; 182*55106Storek ub ^= d; 183*55106Storek } 184*55106Storek if (ms->ms_dx) { 185*55106Storek NEXT; 186*55106Storek fe->id = LOC_X_DELTA; 187*55106Storek fe->value = ms->ms_dx; 188*55106Storek fe->time = time; 189*55106Storek ADVANCE; 190*55106Storek ms->ms_dx = 0; 191*55106Storek } 192*55106Storek if (ms->ms_dy) { 193*55106Storek NEXT; 194*55106Storek fe->id = LOC_Y_DELTA; 195*55106Storek fe->value = ms->ms_dy; 196*55106Storek fe->time = time; 197*55106Storek ADVANCE; 198*55106Storek ms->ms_dy = 0; 199*55106Storek } 200*55106Storek out: 201*55106Storek if (any) { 202*55106Storek ms->ms_ub = ub; 203*55106Storek ms->ms_events.ev_put = put; 204*55106Storek EV_WAKEUP(&ms->ms_events); 205*55106Storek } 206*55106Storek } 207*55106Storek 208*55106Storek int 209*55106Storek msopen(dev, flags, mode, p) 210*55106Storek dev_t dev; 211*55106Storek int flags, mode; 212*55106Storek struct proc *p; 213*55106Storek { 214*55106Storek int s, error; 215*55106Storek 216*55106Storek if (ms_softc.ms_events.ev_io) 217*55106Storek return (EBUSY); 218*55106Storek ms_softc.ms_events.ev_io = p; 219*55106Storek ev_init(&ms_softc.ms_events); /* may cause sleep */ 220*55106Storek ms_softc.ms_ready = 1; /* start accepting events */ 221*55106Storek (*ms_softc.ms_open)(ms_softc.ms_mouse); 222*55106Storek return (0); 223*55106Storek } 224*55106Storek 225*55106Storek int 226*55106Storek msclose(dev, flags, mode, p) 227*55106Storek dev_t dev; 228*55106Storek int flags, mode; 229*55106Storek struct proc *p; 230*55106Storek { 231*55106Storek 232*55106Storek ms_softc.ms_ready = 0; /* stop accepting events */ 233*55106Storek ev_fini(&ms_softc.ms_events); 234*55106Storek (*ms_softc.ms_close)(ms_softc.ms_mouse); 235*55106Storek ms_softc.ms_events.ev_io = NULL; 236*55106Storek return (0); 237*55106Storek } 238*55106Storek 239*55106Storek int 240*55106Storek msread(dev, uio, flags) 241*55106Storek dev_t dev; 242*55106Storek struct uio *uio; 243*55106Storek int flags; 244*55106Storek { 245*55106Storek 246*55106Storek return (ev_read(&ms_softc.ms_events, uio, flags)); 247*55106Storek } 248*55106Storek 249*55106Storek /* this routine should not exist, but is convenient to write here for now */ 250*55106Storek int 251*55106Storek mswrite(dev, uio, flags) 252*55106Storek dev_t dev; 253*55106Storek struct uio *uio; 254*55106Storek int flags; 255*55106Storek { 256*55106Storek 257*55106Storek return (EOPNOTSUPP); 258*55106Storek } 259*55106Storek 260*55106Storek int 261*55106Storek msioctl(dev, cmd, data, flag, p) 262*55106Storek dev_t dev; 263*55106Storek int cmd; 264*55106Storek register caddr_t data; 265*55106Storek int flag; 266*55106Storek struct proc *p; 267*55106Storek { 268*55106Storek int s; 269*55106Storek 270*55106Storek switch (cmd) { 271*55106Storek 272*55106Storek case FIONBIO: /* we will remove this someday (soon???) */ 273*55106Storek return (0); 274*55106Storek 275*55106Storek case FIOASYNC: 276*55106Storek ms_softc.ms_events.ev_async = *(int *)data != 0; 277*55106Storek return (0); 278*55106Storek 279*55106Storek case TIOCSPGRP: 280*55106Storek if (*(int *)data != ms_softc.ms_events.ev_io->p_pgid) 281*55106Storek return (EPERM); 282*55106Storek return (0); 283*55106Storek 284*55106Storek case VUIDGFORMAT: 285*55106Storek /* we only do firm_events */ 286*55106Storek *(int *)data = VUID_FIRM_EVENT; 287*55106Storek return (0); 288*55106Storek 289*55106Storek case VUIDSFORMAT: 290*55106Storek if (*(int *)data != VUID_FIRM_EVENT) 291*55106Storek return (EINVAL); 292*55106Storek return (0); 293*55106Storek } 294*55106Storek return (ENOTTY); 295*55106Storek } 296*55106Storek 297*55106Storek int 298*55106Storek msselect(dev, rw, p) 299*55106Storek dev_t dev; 300*55106Storek int rw; 301*55106Storek struct proc *p; 302*55106Storek { 303*55106Storek 304*55106Storek return (ev_select(&ms_softc.ms_events, rw, p)); 305*55106Storek } 306