mse.c revision 144783
1139749Simp/*-
2138755Simp * Copyright (c) 2004 M. Warner Losh
3138755Simp * All rights reserved.
4138755Simp *
5138755Simp * Redistribution and use in source and binary forms, with or without
6138755Simp * modification, are permitted provided that the following conditions
7138755Simp * are met:
8138755Simp * 1. Redistributions of source code must retain the above copyright
9140040Simp *    notice, this list of conditions and the following disclaimer.
10138755Simp * 2. Redistributions in binary form must reproduce the above copyright
11140040Simp *    notice, this list of conditions and the following disclaimer in the
12140040Simp *    documentation and/or other materials provided with the distribution.
13138755Simp *
14138755Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15138755Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16138755Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17140040Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18140040Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19138755Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20138755Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21138755Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22138755Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23138755Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24138755Simp * SUCH DAMAGE.
25138755Simp *
26138755Simp * $FreeBSD: head/sys/dev/mse/mse.c 144783 2005-04-08 05:22:58Z imp $
27138755Simp */
28138755Simp
29138755Simp/*
30637Snate * Copyright 1992 by the University of Guelph
31637Snate *
32637Snate * Permission to use, copy and modify this
33637Snate * software and its documentation for any purpose and without
34637Snate * fee is hereby granted, provided that the above copyright
35637Snate * notice appear in all copies and that both that copyright
36637Snate * notice and this permission notice appear in supporting
37637Snate * documentation.
38637Snate * University of Guelph makes no representations about the suitability of
39637Snate * this software for any purpose.  It is provided "as is"
40637Snate * without express or implied warranty.
41637Snate */
42637Snate/*
43637Snate * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
44637Snate * the X386 port, courtesy of
45637Snate * Rick Macklem, rick@snowhite.cis.uoguelph.ca
46637Snate * Caveats: The driver currently uses spltty(), but doesn't use any
47637Snate * generic tty code. It could use splmse() (that only masks off the
48637Snate * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
49637Snate * (This may be worth the effort, since the Logitech generates 30/60
50637Snate * interrupts/sec continuously while it is open.)
51637Snate * NB: The ATI has NOT been tested yet!
52637Snate */
53637Snate
54637Snate/*
55637Snate * Modification history:
564259Sjkh * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
574259Sjkh *   improved probe based on input from Logitech.
58637Snate *
59637Snate * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
60637Snate *   fixes to make it work with Microsoft InPort busmouse
61637Snate *
62637Snate * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
63637Snate *   added patches for new "select" interface
64637Snate *
65637Snate * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
66637Snate *   changed position of some spl()'s in mseread
67637Snate *
68637Snate * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
69637Snate *   limit maximum negative x/y value to -127 to work around XFree problem
70637Snate *   that causes spurious button pushes.
71637Snate */
72637Snate
732056Swollman#include <sys/param.h>
743745Swollman#include <sys/systm.h>
7512658Sbde#include <sys/conf.h>
762056Swollman#include <sys/kernel.h>
77129882Sphk#include <sys/module.h>
7858229Syokota#include <sys/bus.h>
7929368Speter#include <sys/poll.h>
8071286Swollman#include <sys/selinfo.h>
812056Swollman#include <sys/uio.h>
8266860Sphk#include <sys/mouse.h>
83637Snate
8458229Syokota#include <machine/bus.h>
857430Sbde#include <machine/clock.h>
8658229Syokota#include <machine/resource.h>
8758229Syokota#include <sys/rman.h>
887430Sbde
8958229Syokota#include <isa/isavar.h>
90637Snate
91138755Simp#include <dev/mse/msevar.h>
9231603Syokota
93138755Simpdevclass_t	mse_devclass;
94637Snate
9512675Sjulianstatic	d_open_t	mseopen;
9612675Sjulianstatic	d_close_t	mseclose;
9712675Sjulianstatic	d_read_t	mseread;
9831603Syokotastatic  d_ioctl_t	mseioctl;
9929368Speterstatic	d_poll_t	msepoll;
10012675Sjulian
10147625Sphkstatic struct cdevsw mse_cdevsw = {
102126080Sphk	.d_version =	D_VERSION,
103126080Sphk	.d_flags =	D_NEEDGIANT,
104111815Sphk	.d_open =	mseopen,
105111815Sphk	.d_close =	mseclose,
106111815Sphk	.d_read =	mseread,
107111815Sphk	.d_ioctl =	mseioctl,
108111815Sphk	.d_poll =	msepoll,
109111815Sphk	.d_name =	"mse",
11047625Sphk};
11112675Sjulian
11292765Salfredstatic	void		mseintr(void *);
11358229Syokotastatic	timeout_t	msetimeout;
11412675Sjulian
115637Snate#define	MSE_UNIT(dev)		(minor(dev) >> 1)
116637Snate#define	MSE_NBLOCKIO(dev)	(minor(dev) & 0x1)
117637Snate
118637Snate#define	MSEPRI	(PZERO + 3)
119637Snate
120138755Simpint
121138755Simpmse_common_attach(device_t dev)
122637Snate{
12358229Syokota	mse_softc_t *sc;
124138755Simp	int unit, flags, rid;
125637Snate
12658229Syokota	sc = device_get_softc(dev);
12758229Syokota	unit = device_get_unit(dev);
12858229Syokota
12958229Syokota	rid = 0;
130138755Simp	sc->sc_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
131138755Simp					     RF_ACTIVE);
13258229Syokota	if (sc->sc_intr == NULL) {
13358229Syokota		bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
13458229Syokota		return ENXIO;
13558229Syokota	}
13658229Syokota
13758229Syokota	if (BUS_SETUP_INTR(device_get_parent(dev), dev, sc->sc_intr,
138144783Simp	    INTR_TYPE_TTY, mseintr, sc, &sc->sc_ih)) {
13958229Syokota		bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
14058229Syokota		bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_intr);
14158229Syokota		return ENXIO;
14258229Syokota	}
14358229Syokota	flags = device_get_flags(dev);
14458229Syokota	sc->mode.accelfactor = (flags & MSE_CONFIG_ACCEL) >> 4;
14558229Syokota	callout_handle_init(&sc->sc_callout);
14658229Syokota
14758229Syokota	sc->sc_dev = make_dev(&mse_cdevsw, unit << 1, 0, 0, 0600,
148144783Simp	  "mse%d", unit);
14958229Syokota	sc->sc_ndev = make_dev(&mse_cdevsw, (unit<<1)+1, 0, 0, 0600,
150144783Simp	  "nmse%d", unit);
15158229Syokota	return 0;
152637Snate}
153637Snate
154637Snate/*
155637Snate * Exclusive open the mouse, initialize it and enable interrupts.
156637Snate */
15712675Sjulianstatic	int
158144783Simpmseopen(struct cdev *dev, int flags, int fmt, struct thread *td)
159637Snate{
16058229Syokota	mse_softc_t *sc;
161637Snate	int s;
162637Snate
16358229Syokota	sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
16458229Syokota	if (sc == NULL)
165637Snate		return (ENXIO);
16620688Sjoerg	if (sc->sc_mousetype == MSE_NONE)
16720688Sjoerg		return (ENXIO);
168637Snate	if (sc->sc_flags & MSESC_OPEN)
169637Snate		return (EBUSY);
170637Snate	sc->sc_flags |= MSESC_OPEN;
17131603Syokota	sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS;
172637Snate	sc->sc_deltax = sc->sc_deltay = 0;
17331603Syokota	sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE;
17458229Syokota	sc->sc_watchdog = FALSE;
17558229Syokota	sc->sc_callout = timeout(msetimeout, dev, hz*2);
17631603Syokota	sc->mode.level = 0;
17731603Syokota	sc->status.flags = 0;
17831603Syokota	sc->status.button = sc->status.obutton = 0;
17931603Syokota	sc->status.dx = sc->status.dy = sc->status.dz = 0;
180637Snate
181637Snate	/*
182637Snate	 * Initialize mouse interface and enable interrupts.
183637Snate	 */
184637Snate	s = spltty();
18558229Syokota	(*sc->sc_enablemouse)(sc->sc_iot, sc->sc_ioh);
186637Snate	splx(s);
187637Snate	return (0);
188637Snate}
189637Snate
190637Snate/*
191637Snate * mseclose: just turn off mouse innterrupts.
192637Snate */
19312675Sjulianstatic	int
194144783Simpmseclose(struct cdev *dev, int flags, int fmt, struct thread *td)
195637Snate{
19658229Syokota	mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
197637Snate	int s;
198637Snate
19958229Syokota	untimeout(msetimeout, dev, sc->sc_callout);
20058229Syokota	callout_handle_init(&sc->sc_callout);
201637Snate	s = spltty();
20258229Syokota	(*sc->sc_disablemouse)(sc->sc_iot, sc->sc_ioh);
203637Snate	sc->sc_flags &= ~MSESC_OPEN;
204637Snate	splx(s);
205637Snate	return(0);
206637Snate}
207637Snate
2088876Srgrimes/*
209637Snate * mseread: return mouse info using the MSC serial protocol, but without
210637Snate * using bytes 4 and 5.
211637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...)
212637Snate */
21312675Sjulianstatic	int
214144783Simpmseread(struct cdev *dev, struct uio *uio, int ioflag)
215637Snate{
21658229Syokota	mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
217637Snate	int xfer, s, error;
218637Snate
219637Snate	/*
220637Snate	 * If there are no protocol bytes to be read, set up a new protocol
221637Snate	 * packet.
222637Snate	 */
223637Snate	s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
22431603Syokota	if (sc->sc_bytesread >= sc->mode.packetsize) {
225637Snate		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
226637Snate		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
227637Snate			if (MSE_NBLOCKIO(dev)) {
228637Snate				splx(s);
229637Snate				return (0);
230637Snate			}
231637Snate			sc->sc_flags |= MSESC_WANT;
232111748Sdes			error = tsleep(sc, MSEPRI | PCATCH,
23346571Speter				"mseread", 0);
23446571Speter			if (error) {
235637Snate				splx(s);
236637Snate				return (error);
237637Snate			}
238637Snate		}
239637Snate
240637Snate		/*
241637Snate		 * Generate protocol bytes.
242637Snate		 * For some reason X386 expects 5 bytes but never uses
243637Snate		 * the fourth or fifth?
244637Snate		 */
24531603Syokota		sc->sc_bytes[0] = sc->mode.syncmask[1]
24631603Syokota		    | (sc->sc_buttons & ~sc->mode.syncmask[0]);
247637Snate		if (sc->sc_deltax > 127)
248637Snate			sc->sc_deltax = 127;
249637Snate		if (sc->sc_deltax < -127)
250637Snate			sc->sc_deltax = -127;
251637Snate		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
252637Snate		if (sc->sc_deltay > 127)
253637Snate			sc->sc_deltay = 127;
254637Snate		if (sc->sc_deltay < -127)
255637Snate			sc->sc_deltay = -127;
256637Snate		sc->sc_bytes[1] = sc->sc_deltax;
257637Snate		sc->sc_bytes[2] = sc->sc_deltay;
258637Snate		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
25931603Syokota		sc->sc_bytes[5] = sc->sc_bytes[6] = 0;
26031603Syokota		sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS;
261637Snate		sc->sc_obuttons = sc->sc_buttons;
262637Snate		sc->sc_deltax = sc->sc_deltay = 0;
263637Snate		sc->sc_bytesread = 0;
264637Snate	}
265637Snate	splx(s);
26631603Syokota	xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread);
26746571Speter	error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio);
26846571Speter	if (error)
269637Snate		return (error);
270637Snate	sc->sc_bytesread += xfer;
271637Snate	return(0);
272637Snate}
273637Snate
274637Snate/*
27531603Syokota * mseioctl: process ioctl commands.
27631603Syokota */
27731603Syokotastatic int
278144783Simpmseioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
27931603Syokota{
28058229Syokota	mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
28131603Syokota	mousestatus_t status;
28231603Syokota	int err = 0;
28331603Syokota	int s;
28431603Syokota
28531603Syokota	switch (cmd) {
28631603Syokota
28731603Syokota	case MOUSE_GETHWINFO:
28831603Syokota		s = spltty();
28931603Syokota		*(mousehw_t *)addr = sc->hw;
29031603Syokota		if (sc->mode.level == 0)
29131603Syokota			((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
29231603Syokota		splx(s);
29331603Syokota		break;
29431603Syokota
29531603Syokota	case MOUSE_GETMODE:
29631603Syokota		s = spltty();
29731603Syokota		*(mousemode_t *)addr = sc->mode;
29831603Syokota		switch (sc->mode.level) {
29931603Syokota		case 0:
30031603Syokota			break;
30131603Syokota		case 1:
30231603Syokota			((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
30331603Syokota	    		((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
30431603Syokota	    		((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
30531603Syokota			break;
30631603Syokota		}
30731603Syokota		splx(s);
30831603Syokota		break;
30931603Syokota
31031603Syokota	case MOUSE_SETMODE:
31131603Syokota		switch (((mousemode_t *)addr)->level) {
31231603Syokota		case 0:
31331603Syokota		case 1:
31431603Syokota			break;
31531603Syokota		default:
31631603Syokota			return (EINVAL);
31731603Syokota		}
31831603Syokota		if (((mousemode_t *)addr)->accelfactor < -1)
31931603Syokota			return (EINVAL);
32031603Syokota		else if (((mousemode_t *)addr)->accelfactor >= 0)
32131603Syokota			sc->mode.accelfactor =
32231603Syokota			    ((mousemode_t *)addr)->accelfactor;
32331603Syokota		sc->mode.level = ((mousemode_t *)addr)->level;
32431603Syokota		switch (sc->mode.level) {
32531603Syokota		case 0:
32631603Syokota			sc->sc_bytesread = sc->mode.packetsize
32731603Syokota			    = MOUSE_MSC_PACKETSIZE;
32831603Syokota			break;
32931603Syokota		case 1:
33031603Syokota			sc->sc_bytesread = sc->mode.packetsize
33131603Syokota			    = MOUSE_SYS_PACKETSIZE;
33231603Syokota			break;
33331603Syokota		}
33431603Syokota		break;
33531603Syokota
33631603Syokota	case MOUSE_GETLEVEL:
33731603Syokota		*(int *)addr = sc->mode.level;
33831603Syokota		break;
33931603Syokota
34031603Syokota	case MOUSE_SETLEVEL:
34131603Syokota		switch (*(int *)addr) {
34231603Syokota		case 0:
34331603Syokota			sc->mode.level = *(int *)addr;
34431603Syokota			sc->sc_bytesread = sc->mode.packetsize
34531603Syokota			    = MOUSE_MSC_PACKETSIZE;
34631603Syokota			break;
34731603Syokota		case 1:
34831603Syokota			sc->mode.level = *(int *)addr;
34931603Syokota			sc->sc_bytesread = sc->mode.packetsize
35031603Syokota			    = MOUSE_SYS_PACKETSIZE;
35131603Syokota			break;
35231603Syokota		default:
35331603Syokota			return (EINVAL);
35431603Syokota		}
35531603Syokota		break;
35631603Syokota
35731603Syokota	case MOUSE_GETSTATUS:
35831603Syokota		s = spltty();
35931603Syokota		status = sc->status;
36031603Syokota		sc->status.flags = 0;
36131603Syokota		sc->status.obutton = sc->status.button;
36231603Syokota		sc->status.button = 0;
36331603Syokota		sc->status.dx = 0;
36431603Syokota		sc->status.dy = 0;
36531603Syokota		sc->status.dz = 0;
36631603Syokota		splx(s);
36731603Syokota		*(mousestatus_t *)addr = status;
36831603Syokota		break;
36931603Syokota
37031603Syokota	case MOUSE_READSTATE:
37131603Syokota	case MOUSE_READDATA:
37231603Syokota		return (ENODEV);
37331603Syokota
37431603Syokota#if (defined(MOUSE_GETVARS))
37531603Syokota	case MOUSE_GETVARS:
37631603Syokota	case MOUSE_SETVARS:
37731603Syokota		return (ENODEV);
37831603Syokota#endif
37931603Syokota
38031603Syokota	default:
38131603Syokota		return (ENOTTY);
38231603Syokota	}
38331603Syokota	return (err);
38431603Syokota}
38531603Syokota
38631603Syokota/*
38729368Speter * msepoll: check for mouse input to be processed.
388637Snate */
38912675Sjulianstatic	int
390144783Simpmsepoll(struct cdev *dev, int events, struct thread *td)
391637Snate{
39258229Syokota	mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
393637Snate	int s;
39429368Speter	int revents = 0;
395637Snate
396637Snate	s = spltty();
39746568Speter	if (events & (POLLIN | POLLRDNORM)) {
39831603Syokota		if (sc->sc_bytesread != sc->mode.packetsize ||
39931603Syokota		    sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
40029368Speter		    (sc->sc_obuttons ^ sc->sc_buttons) != 0)
40129368Speter			revents |= events & (POLLIN | POLLRDNORM);
40229368Speter		else {
40329368Speter			/*
40429368Speter			 * Since this is an exclusive open device, any previous
40529368Speter			 * proc pointer is trash now, so we can just assign it.
40629368Speter			 */
40783366Sjulian			selrecord(td, &sc->sc_selp);
40829368Speter		}
40946568Speter	}
410637Snate	splx(s);
41129368Speter	return (revents);
412637Snate}
413637Snate
414637Snate/*
41558229Syokota * msetimeout: watchdog timer routine.
41658229Syokota */
41758229Syokotastatic void
418144783Simpmsetimeout(void *arg)
41958229Syokota{
420130585Sphk	struct cdev *dev;
42158229Syokota	mse_softc_t *sc;
42258229Syokota
423130585Sphk	dev = (struct cdev *)arg;
42458229Syokota	sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
42558229Syokota	if (sc->sc_watchdog) {
42658229Syokota		if (bootverbose)
42758229Syokota			printf("mse%d: lost interrupt?\n", MSE_UNIT(dev));
42858229Syokota		mseintr(sc);
42958229Syokota	}
43058229Syokota	sc->sc_watchdog = TRUE;
43158229Syokota	sc->sc_callout = timeout(msetimeout, dev, hz);
43258229Syokota}
43358229Syokota
43458229Syokota/*
435637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
436637Snate */
43740565Sbdestatic void
438144783Simpmseintr(void *arg)
439637Snate{
44031603Syokota	/*
44131603Syokota	 * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP)
44231603Syokota	 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
44331603Syokota	 */
44431603Syokota	static int butmap[8] = {
44531603Syokota		0,
44631603Syokota		MOUSE_BUTTON3DOWN,
44731603Syokota		MOUSE_BUTTON2DOWN,
44831603Syokota		MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
44931603Syokota		MOUSE_BUTTON1DOWN,
45031603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
45131603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
45231603Syokota        	MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
45331603Syokota	};
45458229Syokota	mse_softc_t *sc = arg;
45531603Syokota	int dx, dy, but;
45631603Syokota	int sign;
457637Snate
458637Snate#ifdef DEBUG
459637Snate	static int mse_intrcnt = 0;
460637Snate	if((mse_intrcnt++ % 10000) == 0)
461637Snate		printf("mseintr\n");
462637Snate#endif /* DEBUG */
463637Snate	if ((sc->sc_flags & MSESC_OPEN) == 0)
464637Snate		return;
465637Snate
46658229Syokota	(*sc->sc_getmouse)(sc->sc_iot, sc->sc_ioh, &dx, &dy, &but);
46731603Syokota	if (sc->mode.accelfactor > 0) {
46831603Syokota		sign = (dx < 0);
46931603Syokota		dx = dx * dx / sc->mode.accelfactor;
47031603Syokota		if (dx == 0)
47131603Syokota			dx = 1;
47231603Syokota		if (sign)
47331603Syokota			dx = -dx;
47431603Syokota		sign = (dy < 0);
47531603Syokota		dy = dy * dy / sc->mode.accelfactor;
47631603Syokota		if (dy == 0)
47731603Syokota			dy = 1;
47831603Syokota		if (sign)
47931603Syokota			dy = -dy;
48031603Syokota	}
48131603Syokota	sc->sc_deltax += dx;
48231603Syokota	sc->sc_deltay += dy;
48331603Syokota	sc->sc_buttons = but;
484637Snate
48531603Syokota	but = butmap[~but & MOUSE_MSC_BUTTONS];
48631603Syokota	sc->status.dx += dx;
48731603Syokota	sc->status.dy += dy;
48831603Syokota	sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0)
48931603Syokota	    | (sc->status.button ^ but);
49031603Syokota	sc->status.button = but;
49131603Syokota
49258229Syokota	sc->sc_watchdog = FALSE;
49358229Syokota
494637Snate	/*
495637Snate	 * If mouse state has changed, wake up anyone wanting to know.
496637Snate	 */
497637Snate	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
498637Snate	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
4998876Srgrimes		if (sc->sc_flags & MSESC_WANT) {
5008876Srgrimes			sc->sc_flags &= ~MSESC_WANT;
501111748Sdes			wakeup(sc);
5028876Srgrimes		}
503122352Stanimura		selwakeuppri(&sc->sc_selp, MSEPRI);
504637Snate	}
505637Snate}
506