17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate * Mouse streams module.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/param.h>
337c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
347c478bd9Sstevel@tonic-gate #include <sys/signal.h>
357c478bd9Sstevel@tonic-gate #include <sys/termios.h>
367c478bd9Sstevel@tonic-gate #include <sys/termio.h>
377c478bd9Sstevel@tonic-gate #include <sys/stream.h>
387c478bd9Sstevel@tonic-gate #include <sys/stropts.h>
397c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
407c478bd9Sstevel@tonic-gate #include <sys/tty.h>
417c478bd9Sstevel@tonic-gate #include <sys/strtty.h>
427c478bd9Sstevel@tonic-gate #include <sys/time.h>
437c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
447c478bd9Sstevel@tonic-gate #include <sys/file.h>
457c478bd9Sstevel@tonic-gate #include <sys/uio.h>
467c478bd9Sstevel@tonic-gate #include <sys/errno.h>
477c478bd9Sstevel@tonic-gate #include <sys/debug.h>
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate #include <sys/vuid_event.h>
507c478bd9Sstevel@tonic-gate #include <sys/msreg.h>
517c478bd9Sstevel@tonic-gate #include <sys/msio.h>
527c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
537c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate /*
597c478bd9Sstevel@tonic-gate * This is the loadable module wrapper.
607c478bd9Sstevel@tonic-gate */
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate static struct streamtab ms_info;
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate static struct fmodsw fsw = {
657c478bd9Sstevel@tonic-gate "ms",
667c478bd9Sstevel@tonic-gate &ms_info,
677c478bd9Sstevel@tonic-gate D_MP | D_MTPERMOD
687c478bd9Sstevel@tonic-gate };
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate * Module linkage information for the kernel.
727c478bd9Sstevel@tonic-gate */
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate static struct modlstrmod modlstrmod = {
757c478bd9Sstevel@tonic-gate &mod_strmodops, "streams module for mouse", &fsw
767c478bd9Sstevel@tonic-gate };
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
797c478bd9Sstevel@tonic-gate MODREV_1, &modlstrmod, NULL
807c478bd9Sstevel@tonic-gate };
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate int
_init(void)847c478bd9Sstevel@tonic-gate _init(void)
857c478bd9Sstevel@tonic-gate {
867c478bd9Sstevel@tonic-gate return (mod_install(&modlinkage));
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate int
_fini(void)907c478bd9Sstevel@tonic-gate _fini(void)
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate return (EBUSY);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)967c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
977c478bd9Sstevel@tonic-gate {
987c478bd9Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop));
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate #define BYTECLIP(x) (char)((x) > 127 ? 127 : ((x) < -128 ? -128 : (x)))
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate struct msdata {
1047c478bd9Sstevel@tonic-gate struct ms_softc msd_softc;
1057c478bd9Sstevel@tonic-gate queue_t *msd_readq; /* upstream read queue */
1067c478bd9Sstevel@tonic-gate mblk_t *msd_iocpending; /* "ioctl" awaiting buffer */
1077c478bd9Sstevel@tonic-gate int msd_flags; /* random flags */
1087c478bd9Sstevel@tonic-gate int msd_iocid; /* ID of "ioctl" being waited for */
1097c478bd9Sstevel@tonic-gate int msd_iocerror; /* error return from "ioctl" */
1107c478bd9Sstevel@tonic-gate char msd_oldbutt; /* button state at last sample */
1117c478bd9Sstevel@tonic-gate short msd_state; /* state counter for input routine */
1127c478bd9Sstevel@tonic-gate short msd_jitter;
1137c478bd9Sstevel@tonic-gate timeout_id_t msd_timeout_id; /* id returned by timeout() */
1147c478bd9Sstevel@tonic-gate bufcall_id_t msd_reioctl_id; /* id returned by bufcall() */
1157c478bd9Sstevel@tonic-gate bufcall_id_t msd_resched_id; /* id returned by bufcall() */
1167c478bd9Sstevel@tonic-gate int msd_baud_rate; /* mouse baud rate */
1177c478bd9Sstevel@tonic-gate int msd_rcnt_baud_chng; /* baud changed recently */
1187c478bd9Sstevel@tonic-gate int msd_data_pkt_cnt; /* no of packets since last baud change */
1197c478bd9Sstevel@tonic-gate int msd_qenable_more; /* enable msrserv if baud changed recently */
1207c478bd9Sstevel@tonic-gate int msd_hold_baud_stup; /* # of packets to wait for baud setup */
1217c478bd9Sstevel@tonic-gate };
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate #define MS_OPEN 0x00000001 /* mouse is open for business */
1247c478bd9Sstevel@tonic-gate #define MS_IOCWAIT 0x00000002 /* "open" waiting for ioctl to finish */
1257c478bd9Sstevel@tonic-gate #define MS_IOCTOSS 0x00000004 /* Toss ioctl returns */
1267c478bd9Sstevel@tonic-gate
1277c478bd9Sstevel@tonic-gate /*
1287c478bd9Sstevel@tonic-gate * Input routine states. See msinput().
1297c478bd9Sstevel@tonic-gate */
1307c478bd9Sstevel@tonic-gate #define MS_WAIT_BUTN 0
1317c478bd9Sstevel@tonic-gate #define MS_WAIT_X 1
1327c478bd9Sstevel@tonic-gate #define MS_WAIT_Y 2
1337c478bd9Sstevel@tonic-gate #define MS_WAIT_X2 3
1347c478bd9Sstevel@tonic-gate #define MS_WAIT_Y2 4
1357c478bd9Sstevel@tonic-gate #define MS_PKT_SZ 5
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate * This module supports mice runing at 1200, 4800 and 9600 baud rates.
1397c478bd9Sstevel@tonic-gate *
1407c478bd9Sstevel@tonic-gate * If there was a baud change recently, then we want to wait
1417c478bd9Sstevel@tonic-gate * for some time to make sure that no other baud change is on its way.
1427c478bd9Sstevel@tonic-gate * If the second baud rate change is done then the packets between
1437c478bd9Sstevel@tonic-gate * changes are garbage and are thrown away during the baud change.
1447c478bd9Sstevel@tonic-gate */
1457c478bd9Sstevel@tonic-gate /*
1467c478bd9Sstevel@tonic-gate * The following #defines were tuned by experimentations.
1477c478bd9Sstevel@tonic-gate */
1487c478bd9Sstevel@tonic-gate #define MS_HOLD_BAUD_STUP 48
1497c478bd9Sstevel@tonic-gate #define MS_CNT_TOB1200 7
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate static int ms_overrun_msg; /* Message when overrun circular buffer */
1537c478bd9Sstevel@tonic-gate static int ms_overrun_cnt; /* Increment when overrun circular buffer */
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate /*
1567c478bd9Sstevel@tonic-gate * Max pixel delta of jitter controlled. As this number increases the jumpiness
1577c478bd9Sstevel@tonic-gate * of the ms increases, i.e., the coarser the motion for medium speeds.
1587c478bd9Sstevel@tonic-gate */
1597c478bd9Sstevel@tonic-gate static int ms_jitter_thresh = 0;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate /*
1627c478bd9Sstevel@tonic-gate * ms_jitter_thresh is the maximum number of jitters suppressed. Thus,
1637c478bd9Sstevel@tonic-gate * hz/ms_jitter_thresh is the maximum interval of jitters suppressed. As
1647c478bd9Sstevel@tonic-gate * ms_jitter_thresh increases, a wider range of jitter is suppressed. However,
1657c478bd9Sstevel@tonic-gate * the more inertia the mouse seems to have, i.e., the slower the mouse is to
1667c478bd9Sstevel@tonic-gate * react.
1677c478bd9Sstevel@tonic-gate */
1687c478bd9Sstevel@tonic-gate
1697c478bd9Sstevel@tonic-gate /*
1707c478bd9Sstevel@tonic-gate * Measure how many (ms_speed_count) ms deltas exceed threshold
1717c478bd9Sstevel@tonic-gate * (ms_speedlimit). If ms_speedlaw then throw away deltas over ms_speedlimit.
1727c478bd9Sstevel@tonic-gate * This is to keep really bad mice that jump around from getting too far.
1737c478bd9Sstevel@tonic-gate */
1747c478bd9Sstevel@tonic-gate static int ms_speedlimit = 48;
1757c478bd9Sstevel@tonic-gate static int ms_speedlaw = 0;
1767c478bd9Sstevel@tonic-gate static int ms_speed_count;
1777c478bd9Sstevel@tonic-gate static int msjitterrate = 12;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate #define JITTER_TIMEOUT (hz/msjitterrate)
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate static clock_t msjittertimeout; /* Timeout used when mstimeout in effect */
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate * Mouse buffer size in bytes. Place here as variable so that one could
1857c478bd9Sstevel@tonic-gate * massage it using adb if it turns out to be too small.
1867c478bd9Sstevel@tonic-gate */
1877c478bd9Sstevel@tonic-gate static int MS_BUF_BYTES = 4096;
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate
1907c478bd9Sstevel@tonic-gate static int MS_DEBUG;
1917c478bd9Sstevel@tonic-gate
192*166fc016SToomas Soome static int msopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *credp);
1937c478bd9Sstevel@tonic-gate static int msclose(queue_t *q, int flag, cred_t *credp);
194*166fc016SToomas Soome static int mswput(queue_t *q, mblk_t *mp);
195*166fc016SToomas Soome static int msrput(queue_t *q, mblk_t *mp);
196*166fc016SToomas Soome static int msrserv(queue_t *q);
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate static struct module_info msmiinfo = {
1997c478bd9Sstevel@tonic-gate 0,
2007c478bd9Sstevel@tonic-gate "ms",
2017c478bd9Sstevel@tonic-gate 0,
2027c478bd9Sstevel@tonic-gate INFPSZ,
2037c478bd9Sstevel@tonic-gate 2048,
2047c478bd9Sstevel@tonic-gate 128
2057c478bd9Sstevel@tonic-gate };
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate static struct qinit msrinit = {
208*166fc016SToomas Soome msrput,
209*166fc016SToomas Soome msrserv,
2107c478bd9Sstevel@tonic-gate msopen,
2117c478bd9Sstevel@tonic-gate msclose,
212*166fc016SToomas Soome NULL,
2137c478bd9Sstevel@tonic-gate &msmiinfo
2147c478bd9Sstevel@tonic-gate };
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate static struct module_info msmoinfo = {
2177c478bd9Sstevel@tonic-gate 0,
2187c478bd9Sstevel@tonic-gate "ms",
2197c478bd9Sstevel@tonic-gate 0,
2207c478bd9Sstevel@tonic-gate INFPSZ,
2217c478bd9Sstevel@tonic-gate 2048,
2227c478bd9Sstevel@tonic-gate 128
2237c478bd9Sstevel@tonic-gate };
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate static struct qinit mswinit = {
226*166fc016SToomas Soome mswput,
227*166fc016SToomas Soome NULL,
2287c478bd9Sstevel@tonic-gate msopen,
2297c478bd9Sstevel@tonic-gate msclose,
230*166fc016SToomas Soome NULL,
2317c478bd9Sstevel@tonic-gate &msmoinfo
2327c478bd9Sstevel@tonic-gate };
2337c478bd9Sstevel@tonic-gate
2347c478bd9Sstevel@tonic-gate static struct streamtab ms_info = {
2357c478bd9Sstevel@tonic-gate &msrinit,
2367c478bd9Sstevel@tonic-gate &mswinit,
2377c478bd9Sstevel@tonic-gate NULL,
2387c478bd9Sstevel@tonic-gate NULL,
2397c478bd9Sstevel@tonic-gate };
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate static void msresched(void *);
2427c478bd9Sstevel@tonic-gate static void msreioctl(void *);
2437c478bd9Sstevel@tonic-gate static void msioctl(queue_t *q, mblk_t *mp);
244*166fc016SToomas Soome static int ms_getparms(Ms_parms *data);
245*166fc016SToomas Soome static int ms_setparms(Ms_parms *data);
2467c478bd9Sstevel@tonic-gate static void msflush(struct msdata *msd);
247*166fc016SToomas Soome static void msinput(struct msdata *msd, char c);
2487c478bd9Sstevel@tonic-gate static void msincr(void *);
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate /*
2517c478bd9Sstevel@tonic-gate * Dummy qbufcall callback routine used by open and close.
2527c478bd9Sstevel@tonic-gate * The framework will wake up qwait_sig when we return from
2537c478bd9Sstevel@tonic-gate * this routine (as part of leaving the perimeters.)
2547c478bd9Sstevel@tonic-gate * (The framework enters the perimeters before calling the qbufcall() callback
2557c478bd9Sstevel@tonic-gate * and leaves the perimeters after the callback routine has executed. The
2567c478bd9Sstevel@tonic-gate * framework performs an implicit wakeup of any thread in qwait/qwait_sig
2577c478bd9Sstevel@tonic-gate * when it leaves the perimeter. See qwait(9E).)
2587c478bd9Sstevel@tonic-gate */
2597c478bd9Sstevel@tonic-gate /* ARGSUSED */
2607c478bd9Sstevel@tonic-gate static void
dummy_callback(void * arg)2617c478bd9Sstevel@tonic-gate dummy_callback(void *arg)
262*166fc016SToomas Soome {
263*166fc016SToomas Soome }
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate /*
2667c478bd9Sstevel@tonic-gate * Open a mouse.
2677c478bd9Sstevel@tonic-gate */
2687c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2697c478bd9Sstevel@tonic-gate static int
msopen(queue_t * q,dev_t * devp,int oflag,int sflag,cred_t * credp)270*166fc016SToomas Soome msopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *credp)
2717c478bd9Sstevel@tonic-gate {
272*166fc016SToomas Soome struct mousebuf *b;
273*166fc016SToomas Soome struct ms_softc *ms;
274*166fc016SToomas Soome struct msdata *msd;
2757c478bd9Sstevel@tonic-gate mblk_t *mp;
2767c478bd9Sstevel@tonic-gate mblk_t *datap;
277*166fc016SToomas Soome struct iocblk *iocb;
278*166fc016SToomas Soome struct termios *cb;
2797c478bd9Sstevel@tonic-gate int error = 0;
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate if (q->q_ptr != NULL)
2827c478bd9Sstevel@tonic-gate return (0); /* already attached */
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate if (sflag != MODOPEN)
2857c478bd9Sstevel@tonic-gate return (EINVAL);
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate /*
2887c478bd9Sstevel@tonic-gate * Allocate an msdata structure.
2897c478bd9Sstevel@tonic-gate */
2907c478bd9Sstevel@tonic-gate msd = kmem_zalloc(sizeof (struct msdata), KM_SLEEP);
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate /*
2937c478bd9Sstevel@tonic-gate * Set up queue pointers, so that the "put" procedure will accept
2947c478bd9Sstevel@tonic-gate * the reply to the "ioctl" message we send down.
2957c478bd9Sstevel@tonic-gate */
2967c478bd9Sstevel@tonic-gate q->q_ptr = msd;
2977c478bd9Sstevel@tonic-gate WR(q)->q_ptr = msd;
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate qprocson(q);
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate /*
3027c478bd9Sstevel@tonic-gate * Setup tty modes.
3037c478bd9Sstevel@tonic-gate */
3047c478bd9Sstevel@tonic-gate while ((mp = mkiocb(TCSETSF)) == NULL) {
3057c478bd9Sstevel@tonic-gate bufcall_id_t id = qbufcall(q, sizeof (struct iocblk),
3067c478bd9Sstevel@tonic-gate BPRI_HI, dummy_callback, NULL);
3077c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) {
3087c478bd9Sstevel@tonic-gate qunbufcall(q, id);
3097c478bd9Sstevel@tonic-gate kmem_free(msd, sizeof (struct msdata));
3107c478bd9Sstevel@tonic-gate qprocsoff(q);
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate return (EINTR);
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate }
3157c478bd9Sstevel@tonic-gate while ((datap = allocb(sizeof (struct termios), BPRI_HI)) == NULL) {
3167c478bd9Sstevel@tonic-gate bufcall_id_t id = qbufcall(q, sizeof (struct termios),
3177c478bd9Sstevel@tonic-gate BPRI_HI, dummy_callback, NULL);
3187c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) {
3197c478bd9Sstevel@tonic-gate qunbufcall(q, id);
3207c478bd9Sstevel@tonic-gate freemsg(mp);
3217c478bd9Sstevel@tonic-gate kmem_free(msd, sizeof (struct msdata));
3227c478bd9Sstevel@tonic-gate qprocsoff(q);
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate return (EINTR);
3257c478bd9Sstevel@tonic-gate }
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate iocb = (struct iocblk *)mp->b_rptr;
3307c478bd9Sstevel@tonic-gate iocb->ioc_count = sizeof (struct termios);
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate cb = (struct termios *)datap->b_wptr;
3337c478bd9Sstevel@tonic-gate cb->c_iflag = 0;
3347c478bd9Sstevel@tonic-gate cb->c_oflag = 0;
3357c478bd9Sstevel@tonic-gate cb->c_cflag = CREAD|CS8|B9600;
3367c478bd9Sstevel@tonic-gate cb->c_lflag = 0;
3377c478bd9Sstevel@tonic-gate bzero(cb->c_cc, NCCS);
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (*cb);
3407c478bd9Sstevel@tonic-gate datap->b_datap->db_type = M_DATA;
3417c478bd9Sstevel@tonic-gate mp->b_cont = datap;
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate msd->msd_flags |= MS_IOCWAIT; /* indicate that we're waiting for */
3447c478bd9Sstevel@tonic-gate msd->msd_iocid = iocb->ioc_id; /* this response */
3457c478bd9Sstevel@tonic-gate msd->msd_baud_rate = B9600;
3467c478bd9Sstevel@tonic-gate msd->msd_rcnt_baud_chng = 1;
3477c478bd9Sstevel@tonic-gate msd->msd_data_pkt_cnt = 0;
3487c478bd9Sstevel@tonic-gate msd->msd_qenable_more = 0;
3497c478bd9Sstevel@tonic-gate msd->msd_hold_baud_stup = MS_HOLD_BAUD_STUP;
3507c478bd9Sstevel@tonic-gate putnext(WR(q), mp);
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate ms = &msd->msd_softc;
3537c478bd9Sstevel@tonic-gate /*
3547c478bd9Sstevel@tonic-gate * Now wait for it. Let our read queue put routine wake us up
3557c478bd9Sstevel@tonic-gate * when it arrives.
3567c478bd9Sstevel@tonic-gate */
3577c478bd9Sstevel@tonic-gate while (msd->msd_flags & MS_IOCWAIT) {
3587c478bd9Sstevel@tonic-gate if (!qwait_sig(q)) {
3597c478bd9Sstevel@tonic-gate error = EINTR;
3607c478bd9Sstevel@tonic-gate goto error;
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate if ((error = msd->msd_iocerror) != 0)
3647c478bd9Sstevel@tonic-gate goto error;
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate * Set up private data.
3687c478bd9Sstevel@tonic-gate */
3697c478bd9Sstevel@tonic-gate msd->msd_state = MS_WAIT_BUTN;
3707c478bd9Sstevel@tonic-gate msd->msd_readq = q;
3717c478bd9Sstevel@tonic-gate msd->msd_iocpending = NULL;
3727c478bd9Sstevel@tonic-gate
3737c478bd9Sstevel@tonic-gate /*
3747c478bd9Sstevel@tonic-gate * Allocate buffer and initialize data.
3757c478bd9Sstevel@tonic-gate */
3767c478bd9Sstevel@tonic-gate if (ms->ms_buf == 0) {
3777c478bd9Sstevel@tonic-gate ms->ms_bufbytes = MS_BUF_BYTES;
3787c478bd9Sstevel@tonic-gate b = kmem_zalloc((uint_t)ms->ms_bufbytes, KM_SLEEP);
3797c478bd9Sstevel@tonic-gate b->mb_size = 1 + (ms->ms_bufbytes - sizeof (struct mousebuf))
3807c478bd9Sstevel@tonic-gate / sizeof (struct mouseinfo);
3817c478bd9Sstevel@tonic-gate ms->ms_buf = b;
3827c478bd9Sstevel@tonic-gate ms->ms_vuidaddr = VKEY_FIRST;
3837c478bd9Sstevel@tonic-gate msjittertimeout = JITTER_TIMEOUT;
3847c478bd9Sstevel@tonic-gate msflush(msd);
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate msd->msd_flags = MS_OPEN;
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate /*
3907c478bd9Sstevel@tonic-gate * Tell the module below us that it should return input immediately.
3917c478bd9Sstevel@tonic-gate */
3927c478bd9Sstevel@tonic-gate (void) putnextctl1(WR(q), M_CTL, MC_SERVICEIMM);
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate return (0);
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate error:
3977c478bd9Sstevel@tonic-gate qprocsoff(q);
3987c478bd9Sstevel@tonic-gate kmem_free(msd, sizeof (struct msdata));
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate return (error);
4017c478bd9Sstevel@tonic-gate }
4027c478bd9Sstevel@tonic-gate
4037c478bd9Sstevel@tonic-gate /*
4047c478bd9Sstevel@tonic-gate * Close the mouse
4057c478bd9Sstevel@tonic-gate */
4067c478bd9Sstevel@tonic-gate /* ARGSUSED1 */
4077c478bd9Sstevel@tonic-gate static int
msclose(queue_t * q,int flag,cred_t * credp)408*166fc016SToomas Soome msclose(queue_t *q, int flag, cred_t *credp)
4097c478bd9Sstevel@tonic-gate {
410*166fc016SToomas Soome struct msdata *msd = (struct msdata *)q->q_ptr;
411*166fc016SToomas Soome struct ms_softc *ms;
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate /*
4147c478bd9Sstevel@tonic-gate * Tell the module below us that it need not return input immediately.
4157c478bd9Sstevel@tonic-gate */
4167c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_CTL, MC_SERVICEDEF);
4177c478bd9Sstevel@tonic-gate
4187c478bd9Sstevel@tonic-gate qprocsoff(q);
4197c478bd9Sstevel@tonic-gate /*
4207c478bd9Sstevel@tonic-gate * Since we're about to destroy our private data, turn off
4217c478bd9Sstevel@tonic-gate * our open flag first, so we don't accept any more input
4227c478bd9Sstevel@tonic-gate * and try to use that data.
4237c478bd9Sstevel@tonic-gate */
4247c478bd9Sstevel@tonic-gate msd->msd_flags = 0;
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate if (msd->msd_jitter) {
4277c478bd9Sstevel@tonic-gate (void) quntimeout(q, msd->msd_timeout_id);
4287c478bd9Sstevel@tonic-gate msd->msd_jitter = 0;
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate if (msd->msd_reioctl_id) {
4317c478bd9Sstevel@tonic-gate qunbufcall(q, msd->msd_reioctl_id);
4327c478bd9Sstevel@tonic-gate msd->msd_reioctl_id = 0;
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate if (msd->msd_resched_id) {
4357c478bd9Sstevel@tonic-gate qunbufcall(q, msd->msd_resched_id);
4367c478bd9Sstevel@tonic-gate msd->msd_resched_id = 0;
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate if (msd->msd_iocpending != NULL) {
4397c478bd9Sstevel@tonic-gate /*
4407c478bd9Sstevel@tonic-gate * We were holding an "ioctl" response pending the
4417c478bd9Sstevel@tonic-gate * availability of an "mblk" to hold data to be passed up;
4427c478bd9Sstevel@tonic-gate * another "ioctl" came through, which means that "ioctl"
4437c478bd9Sstevel@tonic-gate * must have timed out or been aborted.
4447c478bd9Sstevel@tonic-gate */
4457c478bd9Sstevel@tonic-gate freemsg(msd->msd_iocpending);
4467c478bd9Sstevel@tonic-gate msd->msd_iocpending = NULL;
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate ms = &msd->msd_softc;
4497c478bd9Sstevel@tonic-gate /* Free mouse buffer */
4507c478bd9Sstevel@tonic-gate if (ms->ms_buf != NULL)
4517c478bd9Sstevel@tonic-gate kmem_free(ms->ms_buf, (uint_t)ms->ms_bufbytes);
4527c478bd9Sstevel@tonic-gate /* Free msdata structure */
4537c478bd9Sstevel@tonic-gate kmem_free((void *)msd, sizeof (*msd));
4547c478bd9Sstevel@tonic-gate return (0);
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate
4577c478bd9Sstevel@tonic-gate /*
4587c478bd9Sstevel@tonic-gate * Read queue service routine.
4597c478bd9Sstevel@tonic-gate * Turn buffered mouse events into stream messages.
4607c478bd9Sstevel@tonic-gate */
461*166fc016SToomas Soome static int
msrserv(queue_t * q)462*166fc016SToomas Soome msrserv(queue_t *q)
4637c478bd9Sstevel@tonic-gate {
4647c478bd9Sstevel@tonic-gate struct msdata *msd = (struct msdata *)q->q_ptr;
465*166fc016SToomas Soome struct ms_softc *ms;
466*166fc016SToomas Soome struct mousebuf *b;
467*166fc016SToomas Soome struct mouseinfo *mi;
468*166fc016SToomas Soome int button_number;
469*166fc016SToomas Soome int hwbit;
4707c478bd9Sstevel@tonic-gate mblk_t *bp;
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate /*
4737c478bd9Sstevel@tonic-gate * Handle the case of a queue which is backenabled before
4747c478bd9Sstevel@tonic-gate * initialization is complete.
4757c478bd9Sstevel@tonic-gate */
4767c478bd9Sstevel@tonic-gate if (!(msd->msd_flags & MS_OPEN)) {
477*166fc016SToomas Soome return (1);
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate ms = &msd->msd_softc;
4817c478bd9Sstevel@tonic-gate b = ms->ms_buf;
4827c478bd9Sstevel@tonic-gate if (msd->msd_rcnt_baud_chng && ms->ms_oldoff != b->mb_off) {
4837c478bd9Sstevel@tonic-gate int no_pkt = b->mb_off - ms->ms_oldoff;
4847c478bd9Sstevel@tonic-gate int i;
4857c478bd9Sstevel@tonic-gate no_pkt = no_pkt > 0 ? no_pkt : (b->mb_size - no_pkt);
4867c478bd9Sstevel@tonic-gate if (no_pkt < msd->msd_hold_baud_stup) {
4877c478bd9Sstevel@tonic-gate msd->msd_qenable_more = 1;
488*166fc016SToomas Soome return (0);
4897c478bd9Sstevel@tonic-gate } else {
4907c478bd9Sstevel@tonic-gate /*
4917c478bd9Sstevel@tonic-gate * throw away packets in beginning (mostly garbage)
4927c478bd9Sstevel@tonic-gate */
4937c478bd9Sstevel@tonic-gate for (i = 0; i < msd->msd_hold_baud_stup; i++) {
4947c478bd9Sstevel@tonic-gate ms->ms_oldoff++; /* next event */
4957c478bd9Sstevel@tonic-gate /* circular buffer wraparound */
4967c478bd9Sstevel@tonic-gate if (ms->ms_oldoff >= b->mb_size)
4977c478bd9Sstevel@tonic-gate ms->ms_oldoff = 0;
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate msd->msd_rcnt_baud_chng = 0;
5007c478bd9Sstevel@tonic-gate msd->msd_data_pkt_cnt = 0;
5017c478bd9Sstevel@tonic-gate msd->msd_qenable_more = 0;
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate }
5047c478bd9Sstevel@tonic-gate while (canputnext(q) && ms->ms_oldoff != b->mb_off) {
5057c478bd9Sstevel@tonic-gate mi = &b->mb_info[ms->ms_oldoff];
5067c478bd9Sstevel@tonic-gate switch (ms->ms_readformat) {
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate case MS_3BYTE_FORMAT: {
509*166fc016SToomas Soome char *cp;
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate if ((bp = allocb(3, BPRI_HI)) != NULL) {
5127c478bd9Sstevel@tonic-gate cp = (char *)bp->b_wptr;
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate *cp++ = 0x80 | mi->mi_buttons;
5157c478bd9Sstevel@tonic-gate /* Update read buttons */
5167c478bd9Sstevel@tonic-gate ms->ms_prevbuttons = mi->mi_buttons;
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate *cp++ = mi->mi_x;
5197c478bd9Sstevel@tonic-gate *cp++ = -mi->mi_y;
5207c478bd9Sstevel@tonic-gate /* lower pri to avoid mouse droppings */
5217c478bd9Sstevel@tonic-gate bp->b_wptr = (uchar_t *)cp;
5227c478bd9Sstevel@tonic-gate putnext(q, bp);
5237c478bd9Sstevel@tonic-gate } else {
5247c478bd9Sstevel@tonic-gate if (msd->msd_resched_id)
5257c478bd9Sstevel@tonic-gate qunbufcall(q, msd->msd_resched_id);
5267c478bd9Sstevel@tonic-gate msd->msd_resched_id = qbufcall(q, 3, BPRI_HI,
5277c478bd9Sstevel@tonic-gate msresched, msd);
5287c478bd9Sstevel@tonic-gate if (msd->msd_resched_id == 0)
529*166fc016SToomas Soome return (0); /* try again later */
5307c478bd9Sstevel@tonic-gate /* bufcall failed; just pitch this event */
5317c478bd9Sstevel@tonic-gate /* or maybe flush queue? */
5327c478bd9Sstevel@tonic-gate }
5337c478bd9Sstevel@tonic-gate ms->ms_oldoff++; /* next event */
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate /* circular buffer wraparound */
5367c478bd9Sstevel@tonic-gate if (ms->ms_oldoff >= b->mb_size)
5377c478bd9Sstevel@tonic-gate ms->ms_oldoff = 0;
5387c478bd9Sstevel@tonic-gate break;
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate case MS_VUID_FORMAT: {
542*166fc016SToomas Soome Firm_event *fep;
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate bp = NULL;
5457c478bd9Sstevel@tonic-gate switch (ms->ms_eventstate) {
5467c478bd9Sstevel@tonic-gate
5477c478bd9Sstevel@tonic-gate case EVENT_BUT3:
5487c478bd9Sstevel@tonic-gate case EVENT_BUT2:
5497c478bd9Sstevel@tonic-gate case EVENT_BUT1:
5507c478bd9Sstevel@tonic-gate /* Test the button. Send an event if it changed. */
5517c478bd9Sstevel@tonic-gate button_number = ms->ms_eventstate - EVENT_BUT1;
5527c478bd9Sstevel@tonic-gate hwbit = MS_HW_BUT1 >> button_number;
5537c478bd9Sstevel@tonic-gate if ((ms->ms_prevbuttons & hwbit) !=
5547c478bd9Sstevel@tonic-gate (mi->mi_buttons & hwbit)) {
5557c478bd9Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event),
5567c478bd9Sstevel@tonic-gate BPRI_HI)) != NULL) {
5577c478bd9Sstevel@tonic-gate fep = (Firm_event *)bp->b_wptr;
5587c478bd9Sstevel@tonic-gate fep->id = vuid_id_addr(ms->ms_vuidaddr) |
5597c478bd9Sstevel@tonic-gate vuid_id_offset(BUT(1) + button_number);
5607c478bd9Sstevel@tonic-gate fep->pair_type = FE_PAIR_NONE;
5617c478bd9Sstevel@tonic-gate fep->pair = 0;
5627c478bd9Sstevel@tonic-gate /* Update read buttons and set value */
5637c478bd9Sstevel@tonic-gate if (mi->mi_buttons & hwbit) {
5647c478bd9Sstevel@tonic-gate fep->value = 0;
5657c478bd9Sstevel@tonic-gate ms->ms_prevbuttons |= hwbit;
5667c478bd9Sstevel@tonic-gate } else {
5677c478bd9Sstevel@tonic-gate fep->value = 1;
5687c478bd9Sstevel@tonic-gate ms->ms_prevbuttons &= ~hwbit;
5697c478bd9Sstevel@tonic-gate }
5707c478bd9Sstevel@tonic-gate fep->time = mi->mi_time;
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate } else {
5737c478bd9Sstevel@tonic-gate if (msd->msd_resched_id)
5747c478bd9Sstevel@tonic-gate qunbufcall(q, msd->msd_resched_id);
5757c478bd9Sstevel@tonic-gate msd->msd_resched_id = qbufcall(q,
5767c478bd9Sstevel@tonic-gate sizeof (Firm_event),
5777c478bd9Sstevel@tonic-gate BPRI_HI, msresched, msd);
5787c478bd9Sstevel@tonic-gate if (msd->msd_resched_id == 0)
579*166fc016SToomas Soome return (0); /* try again later */
5807c478bd9Sstevel@tonic-gate /* bufcall failed; just pitch this event */
5817c478bd9Sstevel@tonic-gate /* or maybe flush queue? */
5827c478bd9Sstevel@tonic-gate ms->ms_eventstate = EVENT_X;
5837c478bd9Sstevel@tonic-gate }
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate break;
5867c478bd9Sstevel@tonic-gate
5877c478bd9Sstevel@tonic-gate case EVENT_Y:
5887c478bd9Sstevel@tonic-gate /* Send y if changed. */
5897c478bd9Sstevel@tonic-gate if (mi->mi_y != 0) {
5907c478bd9Sstevel@tonic-gate
5917c478bd9Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event),
5927c478bd9Sstevel@tonic-gate BPRI_HI)) != NULL) {
5937c478bd9Sstevel@tonic-gate fep = (Firm_event *)bp->b_wptr;
5947c478bd9Sstevel@tonic-gate fep->id = vuid_id_addr(ms->ms_vuidaddr) |
5957c478bd9Sstevel@tonic-gate vuid_id_offset(LOC_Y_DELTA);
5967c478bd9Sstevel@tonic-gate fep->pair_type = FE_PAIR_ABSOLUTE;
5977c478bd9Sstevel@tonic-gate fep->pair = (uchar_t)LOC_Y_ABSOLUTE;
5987c478bd9Sstevel@tonic-gate fep->value = -mi->mi_y;
5997c478bd9Sstevel@tonic-gate fep->time = mi->mi_time;
6007c478bd9Sstevel@tonic-gate } else {
6017c478bd9Sstevel@tonic-gate if (msd->msd_resched_id)
6027c478bd9Sstevel@tonic-gate qunbufcall(q, msd->msd_resched_id);
6037c478bd9Sstevel@tonic-gate msd->msd_resched_id = qbufcall(q,
6047c478bd9Sstevel@tonic-gate sizeof (Firm_event),
6057c478bd9Sstevel@tonic-gate BPRI_HI, msresched, msd);
6067c478bd9Sstevel@tonic-gate if (msd->msd_resched_id == 0)
607*166fc016SToomas Soome return (0); /* try again later */
6087c478bd9Sstevel@tonic-gate /* bufcall failed; just pitch this event */
6097c478bd9Sstevel@tonic-gate /* or maybe flush queue? */
6107c478bd9Sstevel@tonic-gate ms->ms_eventstate = EVENT_X;
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate }
6137c478bd9Sstevel@tonic-gate break;
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate case EVENT_X:
6167c478bd9Sstevel@tonic-gate /* Send x if changed. */
6177c478bd9Sstevel@tonic-gate if (mi->mi_x != 0) {
6187c478bd9Sstevel@tonic-gate if ((bp = allocb(sizeof (Firm_event),
6197c478bd9Sstevel@tonic-gate BPRI_HI)) != NULL) {
6207c478bd9Sstevel@tonic-gate fep = (Firm_event *)bp->b_wptr;
6217c478bd9Sstevel@tonic-gate fep->id = vuid_id_addr(ms->ms_vuidaddr) |
6227c478bd9Sstevel@tonic-gate vuid_id_offset(LOC_X_DELTA);
6237c478bd9Sstevel@tonic-gate fep->pair_type = FE_PAIR_ABSOLUTE;
6247c478bd9Sstevel@tonic-gate fep->pair = (uchar_t)LOC_X_ABSOLUTE;
6257c478bd9Sstevel@tonic-gate fep->value = mi->mi_x;
6267c478bd9Sstevel@tonic-gate fep->time = mi->mi_time;
6277c478bd9Sstevel@tonic-gate } else {
6287c478bd9Sstevel@tonic-gate if (msd->msd_resched_id)
6297c478bd9Sstevel@tonic-gate qunbufcall(q, msd->msd_resched_id);
6307c478bd9Sstevel@tonic-gate msd->msd_resched_id = qbufcall(q,
6317c478bd9Sstevel@tonic-gate sizeof (Firm_event),
6327c478bd9Sstevel@tonic-gate BPRI_HI, msresched, msd);
6337c478bd9Sstevel@tonic-gate if (msd->msd_resched_id == 0)
634*166fc016SToomas Soome return (0); /* try again later */
6357c478bd9Sstevel@tonic-gate /* bufcall failed; just pitch this event */
6367c478bd9Sstevel@tonic-gate /* or maybe flush queue? */
6377c478bd9Sstevel@tonic-gate ms->ms_eventstate = EVENT_X;
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate }
6407c478bd9Sstevel@tonic-gate break;
6417c478bd9Sstevel@tonic-gate
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate if (bp != NULL) {
6447c478bd9Sstevel@tonic-gate /* lower pri to avoid mouse droppings */
6457c478bd9Sstevel@tonic-gate bp->b_wptr += sizeof (Firm_event);
6467c478bd9Sstevel@tonic-gate putnext(q, bp);
6477c478bd9Sstevel@tonic-gate }
6487c478bd9Sstevel@tonic-gate if (ms->ms_eventstate == EVENT_X) {
6497c478bd9Sstevel@tonic-gate ms->ms_eventstate = EVENT_BUT3;
6507c478bd9Sstevel@tonic-gate ms->ms_oldoff++; /* next event */
6517c478bd9Sstevel@tonic-gate
6527c478bd9Sstevel@tonic-gate /* circular buffer wraparound */
6537c478bd9Sstevel@tonic-gate if (ms->ms_oldoff >= b->mb_size)
6547c478bd9Sstevel@tonic-gate ms->ms_oldoff = 0;
6557c478bd9Sstevel@tonic-gate } else
6567c478bd9Sstevel@tonic-gate ms->ms_eventstate--;
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate }
660*166fc016SToomas Soome return (0);
6617c478bd9Sstevel@tonic-gate }
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate static void
msresched(void * msdptr)6647c478bd9Sstevel@tonic-gate msresched(void *msdptr)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate queue_t *q;
6677c478bd9Sstevel@tonic-gate struct msdata *msd = msdptr;
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate msd->msd_resched_id = 0;
6707c478bd9Sstevel@tonic-gate if ((q = msd->msd_readq) != 0)
6717c478bd9Sstevel@tonic-gate qenable(q); /* run the service procedure */
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate /*
6757c478bd9Sstevel@tonic-gate * Line discipline output queue put procedure: handles M_IOCTL
6767c478bd9Sstevel@tonic-gate * messages.
6777c478bd9Sstevel@tonic-gate */
678*166fc016SToomas Soome static int
mswput(queue_t * q,mblk_t * mp)679*166fc016SToomas Soome mswput(queue_t *q, mblk_t *mp)
6807c478bd9Sstevel@tonic-gate {
6817c478bd9Sstevel@tonic-gate
6827c478bd9Sstevel@tonic-gate /*
6837c478bd9Sstevel@tonic-gate * Process M_FLUSH, and some M_IOCTL, messages here; pass
6847c478bd9Sstevel@tonic-gate * everything else down.
6857c478bd9Sstevel@tonic-gate */
6867c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) {
6877c478bd9Sstevel@tonic-gate
6887c478bd9Sstevel@tonic-gate case M_FLUSH:
6897c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW)
6907c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA);
6917c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR)
6927c478bd9Sstevel@tonic-gate flushq(RD(q), FLUSHDATA);
6936937e379SToomas Soome /* FALLTHROUGH */
6947c478bd9Sstevel@tonic-gate default:
6957c478bd9Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */
6967c478bd9Sstevel@tonic-gate break;
6977c478bd9Sstevel@tonic-gate
6987c478bd9Sstevel@tonic-gate case M_IOCTL:
6997c478bd9Sstevel@tonic-gate msioctl(q, mp);
7007c478bd9Sstevel@tonic-gate break;
7017c478bd9Sstevel@tonic-gate }
702*166fc016SToomas Soome return (0);
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate
7057c478bd9Sstevel@tonic-gate static void
msreioctl(void * msdptr)7067c478bd9Sstevel@tonic-gate msreioctl(void *msdptr)
7077c478bd9Sstevel@tonic-gate {
7087c478bd9Sstevel@tonic-gate struct msdata *msd = msdptr;
7097c478bd9Sstevel@tonic-gate queue_t *q;
7107c478bd9Sstevel@tonic-gate mblk_t *mp;
7117c478bd9Sstevel@tonic-gate
7127c478bd9Sstevel@tonic-gate msd->msd_reioctl_id = 0;
7137c478bd9Sstevel@tonic-gate q = msd->msd_readq;
7147c478bd9Sstevel@tonic-gate if ((mp = msd->msd_iocpending) != NULL) {
7157c478bd9Sstevel@tonic-gate msd->msd_iocpending = NULL; /* not pending any more */
7167c478bd9Sstevel@tonic-gate msioctl(WR(q), mp);
7177c478bd9Sstevel@tonic-gate }
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate static void
msioctl(queue_t * q,mblk_t * mp)721*166fc016SToomas Soome msioctl(queue_t *q, mblk_t *mp)
7227c478bd9Sstevel@tonic-gate {
7237c478bd9Sstevel@tonic-gate struct msdata *msd;
724*166fc016SToomas Soome struct ms_softc *ms;
725*166fc016SToomas Soome struct iocblk *iocp;
7267c478bd9Sstevel@tonic-gate Vuid_addr_probe *addr_probe;
7277c478bd9Sstevel@tonic-gate uint_t ioctlrespsize;
7287c478bd9Sstevel@tonic-gate int err = 0;
7297c478bd9Sstevel@tonic-gate mblk_t *datap;
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate msd = (struct msdata *)q->q_ptr;
7327c478bd9Sstevel@tonic-gate if (msd == NULL) {
7337c478bd9Sstevel@tonic-gate err = EINVAL;
7347c478bd9Sstevel@tonic-gate goto out;
7357c478bd9Sstevel@tonic-gate }
7367c478bd9Sstevel@tonic-gate ms = &msd->msd_softc;
7377c478bd9Sstevel@tonic-gate
7387c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
7397c478bd9Sstevel@tonic-gate
7407c478bd9Sstevel@tonic-gate if (MS_DEBUG)
7417c478bd9Sstevel@tonic-gate printf("mswput(M_IOCTL,%x)\n", iocp->ioc_cmd);
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate switch (iocp->ioc_cmd) {
7447c478bd9Sstevel@tonic-gate case VUIDSFORMAT:
7457c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (int));
7467c478bd9Sstevel@tonic-gate if (err != 0)
7477c478bd9Sstevel@tonic-gate break;
7487c478bd9Sstevel@tonic-gate if (*(int *)mp->b_cont->b_rptr == ms->ms_readformat)
7497c478bd9Sstevel@tonic-gate break;
7507c478bd9Sstevel@tonic-gate ms->ms_readformat = *(int *)mp->b_cont->b_rptr;
7517c478bd9Sstevel@tonic-gate /*
7527c478bd9Sstevel@tonic-gate * Flush mouse buffer because the messages upstream of us
7537c478bd9Sstevel@tonic-gate * are in the old format.
7547c478bd9Sstevel@tonic-gate */
7557c478bd9Sstevel@tonic-gate msflush(msd);
7567c478bd9Sstevel@tonic-gate break;
7577c478bd9Sstevel@tonic-gate
7587c478bd9Sstevel@tonic-gate case VUIDGFORMAT:
7597c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) {
7607c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (int);
7617c478bd9Sstevel@tonic-gate goto allocfailure;
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate *(int *)datap->b_wptr = ms->ms_readformat;
7647c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (int);
7657c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL)
7667c478bd9Sstevel@tonic-gate freemsg(mp->b_cont);
7677c478bd9Sstevel@tonic-gate mp->b_cont = datap;
7687c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (int);
7697c478bd9Sstevel@tonic-gate break;
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate case VUIDSADDR:
7727c478bd9Sstevel@tonic-gate case VUIDGADDR:
7737c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (Vuid_addr_probe));
7747c478bd9Sstevel@tonic-gate if (err != 0)
7757c478bd9Sstevel@tonic-gate break;
7767c478bd9Sstevel@tonic-gate addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr;
7777c478bd9Sstevel@tonic-gate if (addr_probe->base != VKEY_FIRST) {
7787c478bd9Sstevel@tonic-gate err = ENODEV;
7797c478bd9Sstevel@tonic-gate break;
7807c478bd9Sstevel@tonic-gate }
7817c478bd9Sstevel@tonic-gate if (iocp->ioc_cmd == VUIDSADDR)
7827c478bd9Sstevel@tonic-gate ms->ms_vuidaddr = addr_probe->data.next;
7837c478bd9Sstevel@tonic-gate else
7847c478bd9Sstevel@tonic-gate addr_probe->data.current = ms->ms_vuidaddr;
7857c478bd9Sstevel@tonic-gate break;
7867c478bd9Sstevel@tonic-gate
7877c478bd9Sstevel@tonic-gate case MSIOGETPARMS:
7887c478bd9Sstevel@tonic-gate if (MS_DEBUG)
7897c478bd9Sstevel@tonic-gate printf("ms_getparms\n");
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (Ms_parms), BPRI_HI)) == NULL) {
7927c478bd9Sstevel@tonic-gate ioctlrespsize = sizeof (Ms_parms);
7937c478bd9Sstevel@tonic-gate goto allocfailure;
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate err = ms_getparms((Ms_parms *)datap->b_wptr);
7967c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (Ms_parms);
7977c478bd9Sstevel@tonic-gate if (mp->b_cont != NULL)
7987c478bd9Sstevel@tonic-gate freemsg(mp->b_cont);
7997c478bd9Sstevel@tonic-gate mp->b_cont = datap;
8007c478bd9Sstevel@tonic-gate iocp->ioc_count = sizeof (Ms_parms);
8017c478bd9Sstevel@tonic-gate break;
8027c478bd9Sstevel@tonic-gate
8037c478bd9Sstevel@tonic-gate case MSIOSETPARMS:
8047c478bd9Sstevel@tonic-gate if (MS_DEBUG)
8057c478bd9Sstevel@tonic-gate printf("ms_setparms\n");
8067c478bd9Sstevel@tonic-gate
8077c478bd9Sstevel@tonic-gate err = miocpullup(mp, sizeof (Ms_parms));
8087c478bd9Sstevel@tonic-gate if (err != 0)
8097c478bd9Sstevel@tonic-gate break;
8107c478bd9Sstevel@tonic-gate err = ms_setparms((Ms_parms *)mp->b_cont->b_rptr);
8117c478bd9Sstevel@tonic-gate break;
8127c478bd9Sstevel@tonic-gate
8137c478bd9Sstevel@tonic-gate default:
8147c478bd9Sstevel@tonic-gate putnext(q, mp); /* pass it down the line */
8157c478bd9Sstevel@tonic-gate return;
8167c478bd9Sstevel@tonic-gate }
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate out:
8197c478bd9Sstevel@tonic-gate if (err != 0)
8207c478bd9Sstevel@tonic-gate miocnak(q, mp, 0, err);
8217c478bd9Sstevel@tonic-gate else {
8227c478bd9Sstevel@tonic-gate iocp->ioc_rval = 0;
8237c478bd9Sstevel@tonic-gate iocp->ioc_error = 0; /* brain rot */
8247c478bd9Sstevel@tonic-gate mp->b_datap->db_type = M_IOCACK;
8257c478bd9Sstevel@tonic-gate qreply(q, mp);
8267c478bd9Sstevel@tonic-gate }
8277c478bd9Sstevel@tonic-gate return;
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate allocfailure:
8307c478bd9Sstevel@tonic-gate /*
8317c478bd9Sstevel@tonic-gate * We needed to allocate something to handle this "ioctl", but
8327c478bd9Sstevel@tonic-gate * couldn't; save this "ioctl" and arrange to get called back when
8337c478bd9Sstevel@tonic-gate * it's more likely that we can get what we need.
8347c478bd9Sstevel@tonic-gate * If there's already one being saved, throw it out, since it
8357c478bd9Sstevel@tonic-gate * must have timed out.
8367c478bd9Sstevel@tonic-gate */
8377c478bd9Sstevel@tonic-gate if (msd->msd_iocpending != NULL)
8387c478bd9Sstevel@tonic-gate freemsg(msd->msd_iocpending);
8397c478bd9Sstevel@tonic-gate msd->msd_iocpending = mp;
8407c478bd9Sstevel@tonic-gate if (msd->msd_reioctl_id)
8417c478bd9Sstevel@tonic-gate qunbufcall(q, msd->msd_reioctl_id);
8427c478bd9Sstevel@tonic-gate msd->msd_reioctl_id = qbufcall(q, ioctlrespsize, BPRI_HI,
8437c478bd9Sstevel@tonic-gate msreioctl, msd);
8447c478bd9Sstevel@tonic-gate }
8457c478bd9Sstevel@tonic-gate
8467c478bd9Sstevel@tonic-gate static int
ms_getparms(Ms_parms * data)847*166fc016SToomas Soome ms_getparms(Ms_parms *data)
8487c478bd9Sstevel@tonic-gate {
8497c478bd9Sstevel@tonic-gate data->jitter_thresh = ms_jitter_thresh;
8507c478bd9Sstevel@tonic-gate data->speed_law = ms_speedlaw;
8517c478bd9Sstevel@tonic-gate data->speed_limit = ms_speedlimit;
8527c478bd9Sstevel@tonic-gate return (0);
8537c478bd9Sstevel@tonic-gate }
8547c478bd9Sstevel@tonic-gate
8557c478bd9Sstevel@tonic-gate static int
ms_setparms(Ms_parms * data)856*166fc016SToomas Soome ms_setparms(Ms_parms *data)
8577c478bd9Sstevel@tonic-gate {
8587c478bd9Sstevel@tonic-gate ms_jitter_thresh = data->jitter_thresh;
8597c478bd9Sstevel@tonic-gate ms_speedlaw = data->speed_law;
8607c478bd9Sstevel@tonic-gate ms_speedlimit = data->speed_limit;
8617c478bd9Sstevel@tonic-gate return (0);
8627c478bd9Sstevel@tonic-gate }
8637c478bd9Sstevel@tonic-gate
8647c478bd9Sstevel@tonic-gate static void
msflush(struct msdata * msd)865*166fc016SToomas Soome msflush(struct msdata *msd)
8667c478bd9Sstevel@tonic-gate {
867*166fc016SToomas Soome struct ms_softc *ms = &msd->msd_softc;
868*166fc016SToomas Soome queue_t *q;
8697c478bd9Sstevel@tonic-gate
8707c478bd9Sstevel@tonic-gate ms->ms_oldoff = 0;
8717c478bd9Sstevel@tonic-gate ms->ms_eventstate = EVENT_BUT3;
8727c478bd9Sstevel@tonic-gate ms->ms_buf->mb_off = 0;
8737c478bd9Sstevel@tonic-gate ms->ms_prevbuttons = MS_HW_BUT1 | MS_HW_BUT2 | MS_HW_BUT3;
8747c478bd9Sstevel@tonic-gate msd->msd_oldbutt = ms->ms_prevbuttons;
8757c478bd9Sstevel@tonic-gate if ((q = msd->msd_readq) != NULL && q->q_next != NULL)
8767c478bd9Sstevel@tonic-gate (void) putnextctl1(q, M_FLUSH, FLUSHR);
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate
8807c478bd9Sstevel@tonic-gate /*
8817c478bd9Sstevel@tonic-gate * Mouse read queue put procedure.
8827c478bd9Sstevel@tonic-gate */
883*166fc016SToomas Soome static int
msrput(queue_t * q,mblk_t * mp)884*166fc016SToomas Soome msrput(queue_t *q, mblk_t *mp)
8857c478bd9Sstevel@tonic-gate {
886*166fc016SToomas Soome struct msdata *msd = (struct msdata *)q->q_ptr;
887*166fc016SToomas Soome mblk_t *bp;
888*166fc016SToomas Soome char *readp;
889*166fc016SToomas Soome mblk_t *imp;
890*166fc016SToomas Soome mblk_t *datap;
891*166fc016SToomas Soome struct iocblk *iocb;
892*166fc016SToomas Soome struct termios *cb;
8937c478bd9Sstevel@tonic-gate struct iocblk *iocp;
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate if (msd == 0)
896*166fc016SToomas Soome return (0);
8977c478bd9Sstevel@tonic-gate
8987c478bd9Sstevel@tonic-gate switch (mp->b_datap->db_type) {
8997c478bd9Sstevel@tonic-gate
9007c478bd9Sstevel@tonic-gate case M_FLUSH:
9017c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHW)
9027c478bd9Sstevel@tonic-gate flushq(WR(q), FLUSHDATA);
9037c478bd9Sstevel@tonic-gate if (*mp->b_rptr & FLUSHR)
9047c478bd9Sstevel@tonic-gate flushq(q, FLUSHDATA);
9056937e379SToomas Soome /* FALLTHROUGH */
9067c478bd9Sstevel@tonic-gate default:
9077c478bd9Sstevel@tonic-gate putnext(q, mp);
908*166fc016SToomas Soome return (0);
9097c478bd9Sstevel@tonic-gate
9107c478bd9Sstevel@tonic-gate case M_BREAK:
9117c478bd9Sstevel@tonic-gate if (msd->msd_flags & MS_IOCTOSS) {
9127c478bd9Sstevel@tonic-gate freemsg(mp);
913*166fc016SToomas Soome return (0);
9147c478bd9Sstevel@tonic-gate }
9157c478bd9Sstevel@tonic-gate
9167c478bd9Sstevel@tonic-gate if (msd->msd_rcnt_baud_chng && msd->msd_data_pkt_cnt == 0) {
9177c478bd9Sstevel@tonic-gate freemsg(mp);
918*166fc016SToomas Soome return (0);
9197c478bd9Sstevel@tonic-gate }
9207c478bd9Sstevel@tonic-gate
9217c478bd9Sstevel@tonic-gate /*
9227c478bd9Sstevel@tonic-gate * If we are sampling a 4800 baud mouse at 9600,
9237c478bd9Sstevel@tonic-gate * we want to wait for long time because there is no
9247c478bd9Sstevel@tonic-gate * fixed timeframe for receiving break. If we are sampling
9257c478bd9Sstevel@tonic-gate * a 1200 baud mouse at 4800 or 9600 baud rate then
9267c478bd9Sstevel@tonic-gate * it is guaranteed that break will be received very soon.
9277c478bd9Sstevel@tonic-gate */
9287c478bd9Sstevel@tonic-gate if (msd->msd_rcnt_baud_chng) {
9297c478bd9Sstevel@tonic-gate switch (msd->msd_baud_rate) {
9307c478bd9Sstevel@tonic-gate case B9600:
9317c478bd9Sstevel@tonic-gate msd->msd_hold_baud_stup = MS_HOLD_BAUD_STUP/2;
9327c478bd9Sstevel@tonic-gate msd->msd_baud_rate = B4800;
9337c478bd9Sstevel@tonic-gate break;
9347c478bd9Sstevel@tonic-gate
9357c478bd9Sstevel@tonic-gate case B4800:
9367c478bd9Sstevel@tonic-gate if (msd->msd_data_pkt_cnt <= MS_CNT_TOB1200) {
9377c478bd9Sstevel@tonic-gate msd->msd_hold_baud_stup =
9387c478bd9Sstevel@tonic-gate MS_HOLD_BAUD_STUP/6;
9397c478bd9Sstevel@tonic-gate msd->msd_baud_rate = B1200;
9407c478bd9Sstevel@tonic-gate } else {
9417c478bd9Sstevel@tonic-gate msd->msd_hold_baud_stup =
9427c478bd9Sstevel@tonic-gate MS_HOLD_BAUD_STUP;
9437c478bd9Sstevel@tonic-gate msd->msd_baud_rate = B9600;
9447c478bd9Sstevel@tonic-gate }
9457c478bd9Sstevel@tonic-gate break;
9467c478bd9Sstevel@tonic-gate
9477c478bd9Sstevel@tonic-gate case B1200:
9487c478bd9Sstevel@tonic-gate default:
9497c478bd9Sstevel@tonic-gate msd->msd_hold_baud_stup = MS_HOLD_BAUD_STUP;
9507c478bd9Sstevel@tonic-gate msd->msd_baud_rate = B9600;
9517c478bd9Sstevel@tonic-gate break;
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate } else {
9547c478bd9Sstevel@tonic-gate msd->msd_hold_baud_stup = MS_HOLD_BAUD_STUP;
9557c478bd9Sstevel@tonic-gate msd->msd_baud_rate = B9600;
9567c478bd9Sstevel@tonic-gate }
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate /*
9597c478bd9Sstevel@tonic-gate * Change baud rate.
9607c478bd9Sstevel@tonic-gate */
9617c478bd9Sstevel@tonic-gate if ((imp = mkiocb(TCSETSF)) == NULL) {
962*166fc016SToomas Soome return (0);
9637c478bd9Sstevel@tonic-gate }
9647c478bd9Sstevel@tonic-gate if ((datap = allocb(sizeof (struct termios),
9657c478bd9Sstevel@tonic-gate BPRI_HI)) == NULL) {
9667c478bd9Sstevel@tonic-gate freemsg(imp);
967*166fc016SToomas Soome return (0);
9687c478bd9Sstevel@tonic-gate }
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate iocb = (struct iocblk *)imp->b_rptr;
9717c478bd9Sstevel@tonic-gate iocb->ioc_count = sizeof (struct termios);
9727c478bd9Sstevel@tonic-gate
9737c478bd9Sstevel@tonic-gate cb = (struct termios *)datap->b_rptr;
9747c478bd9Sstevel@tonic-gate cb->c_iflag = 0;
9757c478bd9Sstevel@tonic-gate cb->c_oflag = 0;
9767c478bd9Sstevel@tonic-gate cb->c_cflag = CREAD|CS8|msd->msd_baud_rate;
9777c478bd9Sstevel@tonic-gate cb->c_lflag = 0;
9787c478bd9Sstevel@tonic-gate bzero(cb->c_cc, NCCS);
9797c478bd9Sstevel@tonic-gate
9807c478bd9Sstevel@tonic-gate datap->b_wptr += sizeof (*cb);
9817c478bd9Sstevel@tonic-gate datap->b_datap->db_type = M_DATA;
9827c478bd9Sstevel@tonic-gate imp->b_cont = datap;
9837c478bd9Sstevel@tonic-gate
9847c478bd9Sstevel@tonic-gate msd->msd_flags |= MS_IOCTOSS|MS_IOCWAIT;
9857c478bd9Sstevel@tonic-gate msd->msd_iocid = iocb->ioc_id;
9867c478bd9Sstevel@tonic-gate msflush(msd);
9877c478bd9Sstevel@tonic-gate flushq(q, FLUSHALL);
9887c478bd9Sstevel@tonic-gate putnext(WR(q), imp);
9897c478bd9Sstevel@tonic-gate freemsg(mp);
9907c478bd9Sstevel@tonic-gate msd->msd_rcnt_baud_chng = 1;
9917c478bd9Sstevel@tonic-gate msd->msd_data_pkt_cnt = 0;
9927c478bd9Sstevel@tonic-gate if (MS_DEBUG)
9937c478bd9Sstevel@tonic-gate printf("baud %x\n", msd->msd_baud_rate);
994*166fc016SToomas Soome return (0);
9957c478bd9Sstevel@tonic-gate
9967c478bd9Sstevel@tonic-gate case M_IOCACK:
9977c478bd9Sstevel@tonic-gate case M_IOCNAK:
9987c478bd9Sstevel@tonic-gate /*
9997c478bd9Sstevel@tonic-gate * If we are doing an "ioctl" ourselves, check if this
10007c478bd9Sstevel@tonic-gate * is the reply to that code. If so, wake up the
10017c478bd9Sstevel@tonic-gate * "open" routine, and toss the reply, otherwise just
10027c478bd9Sstevel@tonic-gate * pass it up.
10037c478bd9Sstevel@tonic-gate */
10047c478bd9Sstevel@tonic-gate iocp = (struct iocblk *)mp->b_rptr;
10057c478bd9Sstevel@tonic-gate if (!(msd->msd_flags & MS_IOCWAIT) ||
10067c478bd9Sstevel@tonic-gate iocp->ioc_id != msd->msd_iocid) {
10077c478bd9Sstevel@tonic-gate /*
10087c478bd9Sstevel@tonic-gate * This isn't the reply we're looking for. Move along.
10097c478bd9Sstevel@tonic-gate */
10107c478bd9Sstevel@tonic-gate putnext(q, mp);
10117c478bd9Sstevel@tonic-gate } else {
10127c478bd9Sstevel@tonic-gate msd->msd_flags &= ~MS_IOCWAIT;
10137c478bd9Sstevel@tonic-gate msd->msd_iocerror = iocp->ioc_error;
10147c478bd9Sstevel@tonic-gate /*
10157c478bd9Sstevel@tonic-gate * If we sent down a request to change the baud rate.
10167c478bd9Sstevel@tonic-gate * This is the reply. Just ignore it.
10177c478bd9Sstevel@tonic-gate */
10187c478bd9Sstevel@tonic-gate if (msd->msd_flags & MS_IOCTOSS) {
10197c478bd9Sstevel@tonic-gate msd->msd_flags &= ~MS_IOCTOSS;
10207c478bd9Sstevel@tonic-gate msflush(msd);
10217c478bd9Sstevel@tonic-gate flushq(q, FLUSHALL);
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate freemsg(mp);
10247c478bd9Sstevel@tonic-gate }
1025*166fc016SToomas Soome return (0);
10267c478bd9Sstevel@tonic-gate
10277c478bd9Sstevel@tonic-gate case M_DATA:
10287c478bd9Sstevel@tonic-gate if ((msd->msd_flags & MS_IOCTOSS) ||
10297c478bd9Sstevel@tonic-gate !(msd->msd_flags & MS_OPEN)) {
10307c478bd9Sstevel@tonic-gate freemsg(mp);
1031*166fc016SToomas Soome return (0);
10327c478bd9Sstevel@tonic-gate }
10337c478bd9Sstevel@tonic-gate break;
10347c478bd9Sstevel@tonic-gate }
10357c478bd9Sstevel@tonic-gate
10367c478bd9Sstevel@tonic-gate /*
10377c478bd9Sstevel@tonic-gate * A data message, consisting of bytes from the mouse.
10387c478bd9Sstevel@tonic-gate * Hand each byte to our input routine.
10397c478bd9Sstevel@tonic-gate */
10407c478bd9Sstevel@tonic-gate bp = mp;
10417c478bd9Sstevel@tonic-gate
10427c478bd9Sstevel@tonic-gate do {
10437c478bd9Sstevel@tonic-gate readp = (char *)bp->b_rptr;
10447c478bd9Sstevel@tonic-gate while (readp < (char *)bp->b_wptr) {
10457c478bd9Sstevel@tonic-gate if (msd->msd_rcnt_baud_chng)
10467c478bd9Sstevel@tonic-gate msd->msd_data_pkt_cnt++;
10477c478bd9Sstevel@tonic-gate msinput(msd, *readp++);
10487c478bd9Sstevel@tonic-gate }
10497c478bd9Sstevel@tonic-gate bp->b_rptr = (unsigned char *)readp;
10507c478bd9Sstevel@tonic-gate } while ((bp = bp->b_cont) != NULL); /* next block, if any */
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate freemsg(mp);
1053*166fc016SToomas Soome return (0);
10547c478bd9Sstevel@tonic-gate }
10557c478bd9Sstevel@tonic-gate
10567c478bd9Sstevel@tonic-gate /*
10577c478bd9Sstevel@tonic-gate * Mouse input routine; process a byte received from a mouse and
10587c478bd9Sstevel@tonic-gate * assemble into a mouseinfo message for the window system.
10597c478bd9Sstevel@tonic-gate *
10607c478bd9Sstevel@tonic-gate * The MSC mice send a five-byte packet organized as
10617c478bd9Sstevel@tonic-gate * button, dx, dy, dx, dy
10627c478bd9Sstevel@tonic-gate * where dx and dy can be any signed byte value. The mouseinfo message
10637c478bd9Sstevel@tonic-gate * is organized as
10647c478bd9Sstevel@tonic-gate * dx, dy, button, timestamp
10657c478bd9Sstevel@tonic-gate * Our strategy is to add up the 2 dx and the 2 dy in the five-byte
10667c478bd9Sstevel@tonic-gate * packet, then send the mouseinfo message up.
10677c478bd9Sstevel@tonic-gate *
10687c478bd9Sstevel@tonic-gate * Basic algorithm: throw away bytes until we get a [potential]
10697c478bd9Sstevel@tonic-gate * button byte. Collect button; Collect dx1; Collect dy1; Collect dx2
10707c478bd9Sstevel@tonic-gate * and add it to dx1; Collect dy2 and add it to dy1; Send button,
10717c478bd9Sstevel@tonic-gate * dx, dy, timestamp.
10727c478bd9Sstevel@tonic-gate *
10737c478bd9Sstevel@tonic-gate * Watch out for overflow!
10747c478bd9Sstevel@tonic-gate */
10757c478bd9Sstevel@tonic-gate
10767c478bd9Sstevel@tonic-gate static void
msinput(struct msdata * msd,char c)1077*166fc016SToomas Soome msinput(struct msdata *msd, char c)
10787c478bd9Sstevel@tonic-gate {
1079*166fc016SToomas Soome struct ms_softc *ms;
1080*166fc016SToomas Soome struct mousebuf *b;
1081*166fc016SToomas Soome struct mouseinfo *mi;
1082*166fc016SToomas Soome int jitter_radius;
1083*166fc016SToomas Soome int temp;
10847c478bd9Sstevel@tonic-gate
10857c478bd9Sstevel@tonic-gate ms = &msd->msd_softc;
10867c478bd9Sstevel@tonic-gate b = ms->ms_buf;
10877c478bd9Sstevel@tonic-gate if (b == NULL)
10887c478bd9Sstevel@tonic-gate return;
10897c478bd9Sstevel@tonic-gate
10907c478bd9Sstevel@tonic-gate mi = &b->mb_info[b->mb_off];
10917c478bd9Sstevel@tonic-gate
10927c478bd9Sstevel@tonic-gate switch (msd->msd_state) {
10937c478bd9Sstevel@tonic-gate
10947c478bd9Sstevel@tonic-gate case MS_WAIT_BUTN:
10957c478bd9Sstevel@tonic-gate if ((c & 0xf8) != 0x80) {
10967c478bd9Sstevel@tonic-gate if (MS_DEBUG)
10977c478bd9Sstevel@tonic-gate printf("Mouse input char %x discarded\n",
10987c478bd9Sstevel@tonic-gate (int)c & 0xff);
10997c478bd9Sstevel@tonic-gate if (msd->msd_rcnt_baud_chng) {
11007c478bd9Sstevel@tonic-gate msflush(msd);
11017c478bd9Sstevel@tonic-gate flushq(msd->msd_readq, FLUSHALL);
11027c478bd9Sstevel@tonic-gate msd->msd_hold_baud_stup++;
11037c478bd9Sstevel@tonic-gate }
11047c478bd9Sstevel@tonic-gate return;
11057c478bd9Sstevel@tonic-gate }
11067c478bd9Sstevel@tonic-gate
11077c478bd9Sstevel@tonic-gate /*
11087c478bd9Sstevel@tonic-gate * Probably a button byte.
11097c478bd9Sstevel@tonic-gate * Lower 3 bits are left, middle, right.
11107c478bd9Sstevel@tonic-gate */
11117c478bd9Sstevel@tonic-gate mi->mi_buttons = c & (MS_HW_BUT1 | MS_HW_BUT2 | MS_HW_BUT3);
11127c478bd9Sstevel@tonic-gate break;
11137c478bd9Sstevel@tonic-gate
11147c478bd9Sstevel@tonic-gate case MS_WAIT_X:
11157c478bd9Sstevel@tonic-gate /*
11167c478bd9Sstevel@tonic-gate * Delta X byte. Add the delta X from this sample to
11177c478bd9Sstevel@tonic-gate * the delta X we're accumulating in the current event.
11187c478bd9Sstevel@tonic-gate */
11197c478bd9Sstevel@tonic-gate temp = (int)(mi->mi_x + c);
11207c478bd9Sstevel@tonic-gate mi->mi_x = BYTECLIP(temp);
11217c478bd9Sstevel@tonic-gate uniqtime32(&mi->mi_time); /* record time when sample arrived */
11227c478bd9Sstevel@tonic-gate break;
11237c478bd9Sstevel@tonic-gate
11247c478bd9Sstevel@tonic-gate case MS_WAIT_Y:
11257c478bd9Sstevel@tonic-gate /*
11267c478bd9Sstevel@tonic-gate * Delta Y byte. Add the delta Y from this sample to
11277c478bd9Sstevel@tonic-gate * the delta Y we're accumulating in the current event.
11287c478bd9Sstevel@tonic-gate * (Subtract, actually, because the mouse reports
11297c478bd9Sstevel@tonic-gate * increasing Y up the screen.)
11307c478bd9Sstevel@tonic-gate */
11317c478bd9Sstevel@tonic-gate temp = (int)(mi->mi_y - c);
11327c478bd9Sstevel@tonic-gate mi->mi_y = BYTECLIP(temp);
11337c478bd9Sstevel@tonic-gate break;
11347c478bd9Sstevel@tonic-gate
11357c478bd9Sstevel@tonic-gate case MS_WAIT_X2:
11367c478bd9Sstevel@tonic-gate /*
11377c478bd9Sstevel@tonic-gate * Second delta X byte.
11387c478bd9Sstevel@tonic-gate */
11397c478bd9Sstevel@tonic-gate temp = (int)(mi->mi_x + c);
11407c478bd9Sstevel@tonic-gate mi->mi_x = BYTECLIP(temp);
11417c478bd9Sstevel@tonic-gate uniqtime32(&mi->mi_time);
11427c478bd9Sstevel@tonic-gate break;
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate case MS_WAIT_Y2:
11457c478bd9Sstevel@tonic-gate /*
11467c478bd9Sstevel@tonic-gate * Second delta Y byte.
11477c478bd9Sstevel@tonic-gate */
11487c478bd9Sstevel@tonic-gate temp = (int)(mi->mi_y - c);
11497c478bd9Sstevel@tonic-gate mi->mi_y = BYTECLIP(temp);
11507c478bd9Sstevel@tonic-gate break;
11517c478bd9Sstevel@tonic-gate
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate
11547c478bd9Sstevel@tonic-gate /*
11557c478bd9Sstevel@tonic-gate * Done yet?
11567c478bd9Sstevel@tonic-gate */
11577c478bd9Sstevel@tonic-gate if (msd->msd_state == MS_WAIT_Y2)
11587c478bd9Sstevel@tonic-gate msd->msd_state = MS_WAIT_BUTN; /* BONG. Start again. */
11597c478bd9Sstevel@tonic-gate else {
11607c478bd9Sstevel@tonic-gate msd->msd_state += 1;
11617c478bd9Sstevel@tonic-gate return;
11627c478bd9Sstevel@tonic-gate }
11637c478bd9Sstevel@tonic-gate
11647c478bd9Sstevel@tonic-gate if (msd->msd_jitter) {
11657c478bd9Sstevel@tonic-gate (void) quntimeout(msd->msd_readq, msd->msd_timeout_id);
11667c478bd9Sstevel@tonic-gate msd->msd_jitter = 0;
11677c478bd9Sstevel@tonic-gate }
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate if (mi->mi_buttons == msd->msd_oldbutt) {
11707c478bd9Sstevel@tonic-gate /*
11717c478bd9Sstevel@tonic-gate * Buttons did not change; did position?
11727c478bd9Sstevel@tonic-gate */
11737c478bd9Sstevel@tonic-gate if (mi->mi_x == 0 && mi->mi_y == 0) {
11747c478bd9Sstevel@tonic-gate /* no, position did not change - boring event */
11757c478bd9Sstevel@tonic-gate return;
11767c478bd9Sstevel@tonic-gate }
11777c478bd9Sstevel@tonic-gate
11787c478bd9Sstevel@tonic-gate /*
11797c478bd9Sstevel@tonic-gate * Did the mouse move more than the jitter threshhold?
11807c478bd9Sstevel@tonic-gate */
11817c478bd9Sstevel@tonic-gate jitter_radius = ms_jitter_thresh;
11827c478bd9Sstevel@tonic-gate if (ABS((int)mi->mi_x) <= jitter_radius &&
11837c478bd9Sstevel@tonic-gate ABS((int)mi->mi_y) <= jitter_radius) {
11847c478bd9Sstevel@tonic-gate /*
11857c478bd9Sstevel@tonic-gate * Mouse moved less than the jitter threshhold.
11867c478bd9Sstevel@tonic-gate * Don't indicate an event; keep accumulating motions.
11877c478bd9Sstevel@tonic-gate * After "msjittertimeout" ticks expire, treat
11887c478bd9Sstevel@tonic-gate * the accumulated delta as the real delta.
11897c478bd9Sstevel@tonic-gate */
11907c478bd9Sstevel@tonic-gate msd->msd_jitter = 1;
11917c478bd9Sstevel@tonic-gate msd->msd_timeout_id = qtimeout(msd->msd_readq,
11927c478bd9Sstevel@tonic-gate msincr, msd, msjittertimeout);
11937c478bd9Sstevel@tonic-gate return;
11947c478bd9Sstevel@tonic-gate }
11957c478bd9Sstevel@tonic-gate }
11967c478bd9Sstevel@tonic-gate msd->msd_oldbutt = mi->mi_buttons;
11977c478bd9Sstevel@tonic-gate msincr(msd);
11987c478bd9Sstevel@tonic-gate }
11997c478bd9Sstevel@tonic-gate
12007c478bd9Sstevel@tonic-gate /*
12017c478bd9Sstevel@tonic-gate * Increment the mouse sample pointer.
12027c478bd9Sstevel@tonic-gate * Called either immediately after a sample or after a jitter timeout.
12037c478bd9Sstevel@tonic-gate */
12047c478bd9Sstevel@tonic-gate static void
msincr(void * arg)12057c478bd9Sstevel@tonic-gate msincr(void *arg)
12067c478bd9Sstevel@tonic-gate {
12077c478bd9Sstevel@tonic-gate struct msdata *msd = arg;
1208*166fc016SToomas Soome struct ms_softc *ms = &msd->msd_softc;
1209*166fc016SToomas Soome struct mousebuf *b;
1210*166fc016SToomas Soome struct mouseinfo *mi;
12117c478bd9Sstevel@tonic-gate char oldbutt;
1212*166fc016SToomas Soome short xc, yc;
1213*166fc016SToomas Soome int wake;
1214*166fc016SToomas Soome int speedlimit = ms_speedlimit;
1215*166fc016SToomas Soome int xabs, yabs;
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate /*
12187c478bd9Sstevel@tonic-gate * No longer waiting for jitter timeout
12197c478bd9Sstevel@tonic-gate */
12207c478bd9Sstevel@tonic-gate msd->msd_jitter = 0;
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate b = ms->ms_buf;
12237c478bd9Sstevel@tonic-gate if (b == NULL)
12247c478bd9Sstevel@tonic-gate return;
12257c478bd9Sstevel@tonic-gate mi = &b->mb_info[b->mb_off];
12267c478bd9Sstevel@tonic-gate
12277c478bd9Sstevel@tonic-gate if (ms_speedlaw) {
12287c478bd9Sstevel@tonic-gate xabs = ABS((int)mi->mi_x);
12297c478bd9Sstevel@tonic-gate yabs = ABS((int)mi->mi_y);
12307c478bd9Sstevel@tonic-gate if (xabs > speedlimit || yabs > speedlimit)
12317c478bd9Sstevel@tonic-gate ms_speed_count++;
12327c478bd9Sstevel@tonic-gate if (xabs > speedlimit)
12337c478bd9Sstevel@tonic-gate mi->mi_x = 0;
12347c478bd9Sstevel@tonic-gate if (yabs > speedlimit)
12357c478bd9Sstevel@tonic-gate mi->mi_y = 0;
12367c478bd9Sstevel@tonic-gate }
12377c478bd9Sstevel@tonic-gate
12387c478bd9Sstevel@tonic-gate oldbutt = mi->mi_buttons;
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate xc = yc = 0;
12417c478bd9Sstevel@tonic-gate
12427c478bd9Sstevel@tonic-gate /* See if we need to wake up anyone waiting for input */
12437c478bd9Sstevel@tonic-gate wake = b->mb_off == ms->ms_oldoff;
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate /* Adjust circular buffer pointer */
12467c478bd9Sstevel@tonic-gate if (++b->mb_off >= b->mb_size) {
12477c478bd9Sstevel@tonic-gate b->mb_off = 0;
12487c478bd9Sstevel@tonic-gate mi = b->mb_info;
12497c478bd9Sstevel@tonic-gate } else {
12507c478bd9Sstevel@tonic-gate mi++;
12517c478bd9Sstevel@tonic-gate }
12527c478bd9Sstevel@tonic-gate
12537c478bd9Sstevel@tonic-gate /*
12547c478bd9Sstevel@tonic-gate * If over-took read index then flush buffer so that mouse state
12557c478bd9Sstevel@tonic-gate * is consistent.
12567c478bd9Sstevel@tonic-gate */
12577c478bd9Sstevel@tonic-gate if (b->mb_off == ms->ms_oldoff) {
12587c478bd9Sstevel@tonic-gate if (ms_overrun_msg)
12597c478bd9Sstevel@tonic-gate cmn_err(CE_WARN,
12607c478bd9Sstevel@tonic-gate "Mouse buffer flushed when overrun.\n");
12617c478bd9Sstevel@tonic-gate msflush(msd);
12627c478bd9Sstevel@tonic-gate ms_overrun_cnt++;
12637c478bd9Sstevel@tonic-gate mi = b->mb_info;
12647c478bd9Sstevel@tonic-gate }
12657c478bd9Sstevel@tonic-gate
12667c478bd9Sstevel@tonic-gate /* Remember current buttons and fractional part of x & y */
12677c478bd9Sstevel@tonic-gate mi->mi_buttons = oldbutt;
12687c478bd9Sstevel@tonic-gate mi->mi_x = (char)xc;
12697c478bd9Sstevel@tonic-gate mi->mi_y = (char)yc;
12707c478bd9Sstevel@tonic-gate if (wake || msd->msd_qenable_more)
12717c478bd9Sstevel@tonic-gate qenable(msd->msd_readq); /* run the service procedure */
12727c478bd9Sstevel@tonic-gate }
1273