*BSD News Article 7182


Return to BSD News archive

Path: sserve!manuel.anu.edu.au!munnari.oz.au!sgiblab!swrinde!cs.utexas.edu!sun-barr!olivea!charnel!psgrain!ee.und.ac.za!ucthpx!casper.cs.uct.ac.za!uctcs!sandi
From: sandi@uctcs.cs.uct.ac.za (Sandi Donno)
Newsgroups: comp.unix.bsd
Subject: [386BSD] Improved port of Microsoft BusMouse driver
Message-ID: <sandi.720348398@uctcs>
Date: 29 Oct 92 08:46:38 GMT
Sender: news@casper.cs.uct.ac.za (news)
Organization: Computer Science Department, University of Cape Town
Lines: 753

This is a repost of my port of busmouse.v3 to 386bsd, with a few 
improvements (thanks to Andrew Herbert, andrew@werple.apana.org.au).
This shar file contains everything needed to compile the driver,
unlike my previous post which was a patchkit.

Enjoy!
--
Sandi Donno
sandi@cs.uct.ac.za

# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	README.386bsd
#	bms.c
#	conf.c.diff
#	files.i386.diff
#	isa.h.diff
#	mouse.h
#	testmse.c
#
echo x - README.386bsd
sed 's/^X//' >README.386bsd << 'END-of-README.386bsd'
XThis driver is a port of the Microsoft busmouse driver for BSD/386
Xby Erik Forsberg (busmouse.v3) to 386bsd. I have not ported the Logitech 
Xdriver included in this package.
X
XThe following files are identical to those in the BSD/386 version:
Xmouse.h 	should be placed in /sys/sys
Xisa.h.diff 	patch should be applied to /sys/i386/isa/isa.h
X
XThe following files/patches replace those supplied with busmouse.v3:
Xbms.c		should be placed in /sys/sys/i386/isa
Xconf.c.diff	patch should be applied to /sys/i386/i386/conf.c
Xfiles.i386.diff patch should be applied to /sys/i386/conf/files.i386
X		(replaces file.i386.diff in busmouse.v3)
X
XThe following is an example of a suitable line to add in your
Xkernel configuration file:
X
Xdevice		bms0	at isa? port "IO_BMS1" tty irq 5 vector bmsintr
X
XThe testmse program from the 386bsd busmouse package by Rick Macklem, 
Xrick@snowhite.cis.uoguelph.ca, is useful for testing the mouse in
Xblocking mode. To use this program, first mknod /dev/mouse c 14 0.
X
XIf this works, then
X1) rm /dev/mouse
X2) mknod /dev/mouse c 14 1
Xto create a non-blocking device suitable for use with X386.
X
XIf you wish to get hold of busmouse.v3, it can be obtained from 
Xphysics.su.oz.au, in /XFree86.
X386bsd-busmouse.tar.Z can be obtained from athene.uni-paderborn.de, in 
X/uninstalled/386BSD/386bsd-0.1/unofficial
X
X	-- Sandi Donno (sandi@cs.uct.ac.za)
END-of-README.386bsd
echo x - bms.c
sed 's/^X//' >bms.c << 'END-of-bms.c'
X/*-
X * Copyright (c) 1992 The Regents of the University of California.
X * All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Erik Forsberg.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X/*
X *  Microsoft Bus Mouse driver.
X *  Written April 26th, 1992 for the BSDI/386 system.
X *  Please send bugs and enhancements to erik@eab.retix.com
X *  Copyright 1992, Erik Forsberg.
X */
X
X/*
X *  Ported to 386bsd Oct 17, 1992 
X *  Sandi Donno, Computer Science, University of Cape Town, South Africa
X *  Please send bug reports to sandi@cs.uct.ac.za
X *
X *  Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca -
X *  although I was only partially successful in getting the alpha release
X *  of his "driver for the Logitech and ATI Inport Bus mice for use with 
X *  386bsd and the X386 port" to work with my Microsoft mouse, I nevertheless 
X *  found his code to be an invaluable reference when porting this driver 
X *  to 386bsd.
X *
X *  Thanks also to Andrew Herbert (andrew@werple.apana.org.au) for some
X *  improvements.
X */
X
X#include "bms.h"
X
X#if NBMS > 0
X
X#include "param.h"
X#include "kernel.h"
X#include "systm.h"
X#include "buf.h"
X#include "malloc.h"
X#include "ioctl.h"
X#include "tty.h"
X#include "file.h"
X#include "proc.h"
X#include "vnode.h"
X#include "mouse.h"
X
X#include "i386/isa/isa_device.h"
X
X#define ADDR	0	/* Offset for register select */
X#define DATA	1	/* Offset for InPort data */
X#define IDENT	2	/* Offset for identification register */
X
X#define BMSUNIT(dev)	(minor(dev) >> 1)
X
Xint bmsprobe();
Xint bmsattach();
X
Xstatic int bmsaddr[NBMS];	/* Base I/O port addresses per unit */
X
X#define MSBSZ	1024		/* Output queue size (pwr of 2 is best) */
X
Xstruct ringbuf {
X	int count, first, last;
X	char queue[MSBSZ];
X};
X
Xstatic struct bms_softc {	/* Driver status information */
X	struct ringbuf inq;	/* Input queue */
X	struct proc *rsel;	/* Process selecting for Input */
X	unsigned char state;	/* Mouse driver state */
X	unsigned char status;	/* Mouse button status */
X	int x, y;		/* accumulated motion in the X,Y axis */
X} bms_softc[NBMS];
X
X#define OPEN	1		/* Device is open */
X#define ASLP	2		/* Waiting for mouse data */
X
Xstruct isa_driver bmsdriver =
X	{ bmsprobe, bmsattach, "bms" };
X
Xint bmsprobe(dvp)
X	struct isa_device *dvp;
X	{
X	int ioport = dvp->id_iobase;
X
X	/* Read identification register to see if present */
X
X	if (inb(ioport+IDENT) != 0xDE)
X		return(0);
X
X	/* Seems it was there, reset */
X
X	outb(ioport+ADDR, 0x87);
X	return(1);
X	}
X
Xint bmsattach(dvp)
X	struct isa_device *dvp;
X	{
X	int unit = dvp->id_unit;
X	int ioport = dvp->id_iobase;
X	struct bms_softc *sc = &bms_softc[unit];
X
X	/* Save I/O base address */
X
X	bmsaddr[unit] = ioport;
X
X	/* Setup initial state */
X
X	sc->state = 0;
X
X	/* Done */
X
X	return(0);
X	}
X
Xint bmsopen(dev, flag, fmt, p)
X	dev_t dev;
X	int flag, fmt;
X	struct proc *p;
X	{
X	int unit = BMSUNIT(dev);
X	struct bms_softc *sc;
X	int ioport;
X
X	/* Validate unit number */
X
X	if (unit >= NBMS)
X		return(ENXIO);
X
X	/* Get device data */
X
X	sc = &bms_softc[unit];
X	ioport = bmsaddr[unit];
X
X	/* If device does not exist */
X
X	if (ioport == 0)
X		return(ENXIO);
X
X	/* Disallow multiple opens */
X
X	if (sc->state & OPEN)
X		return(ENXIO);
X
X	/* Initialize state */
X
X	sc->state |= OPEN;
X	sc->rsel = NULL;
X	sc->status = 0;
X	sc->x = 0;
X	sc->y = 0;
X
X	/* Allocate and initialize a ring buffer */
X
X	sc->inq.count = sc->inq.first = sc->inq.last = 0;
X
X	/* Setup Bus Mouse */
X
X	outb(ioport+ADDR, 7);
X	outb(ioport+DATA, 0x09);
X
X	/* Successful open */
X
X	return(0);
X	}
X
Xint bmsclose(dev, flag, fmt, p)
X	dev_t dev;
X	int flag, fmt;
X	struct proc *p;
X	{
X	int unit, ioport;
X	struct bms_softc *sc;
X
X	/* Get unit and associated info */
X
X	unit = BMSUNIT(dev);
X	sc = &bms_softc[unit];
X	ioport = bmsaddr[unit];
X
X	/* Reset Bus Mouse */
X
X	outb(ioport+ADDR, 0x87);
X
X	/* Complete the close */
X
X	sc->state &= ~OPEN;
X
X	/* close is almost always successful */
X
X	return(0);
X	}
X
Xint bmsread(dev, uio, flag)
X	dev_t dev;
X	struct uio *uio;
X	int flag;
X	{
X	int s, error;
X	unsigned length;
X	struct bms_softc *sc;
X	unsigned char buffer[100];
X
X	/* Get device information */
X
X	sc = &bms_softc[BMSUNIT(dev)];
X
X	/* Block until mouse activity occured */
X
X	s = spltty();
X	while (sc->inq.count == 0)
X		{
X		if (minor(dev) & 0x1)
X			{
X			splx(s);
X			return(EWOULDBLOCK);
X			}
X		sc->state |= ASLP;
X		error = tsleep(sc, PZERO | PCATCH, "bmsrea", 0);
X		if (error != 0)
X			{
X			splx(s);
X			return(error);
X			}
X		}
X
X	/* Transfer as many chunks as possible */
X
X	while (sc->inq.count > 0 && uio->uio_resid > 0)
X		{
X		length = min(sc->inq.count, uio->uio_resid);
X		if (length > sizeof(buffer))
X			length = sizeof(buffer);
X
X		/* Remove a small chunk from input queue */
X
X		if (sc->inq.first + length >= MSBSZ)
X		{
X			bcopy(&sc->inq.queue[sc->inq.first], 
X		 	      buffer, MSBSZ - sc->inq.first);
X			bcopy(sc->inq.queue, &buffer[MSBSZ-sc->inq.first], 
X			      length - (MSBSZ - sc->inq.first));
X		}
X		else
X			bcopy(&sc->inq.queue[sc->inq.first], buffer, length);
X	
X		sc->inq.first = (sc->inq.first + length) % MSBSZ;
X		sc->inq.count -= length;
X
X
X		/* Copy data to user process */
X
X		error = uiomove(buffer, length, uio);
X		if (error)
X			break;
X		}
X
X	sc->x = sc->y = 0;
X
X	/* Allow interrupts again */
X
X	splx(s);
X	return(error);
X	}
X
Xint bmsioctl(dev, cmd, addr, flag, p)
X	dev_t dev;
X	caddr_t addr;
X	int cmd, flag;
X	struct proc *p;
X	{
X	struct bms_softc *sc;
X	struct mouseinfo info;
X	int s, error;
X
X	/* Get device information */
X
X	sc = &bms_softc[BMSUNIT(dev)];
X
X	/* Perform IOCTL command */
X
X	switch (cmd)
X		{
X
X	case MOUSEIOCREAD:
X
X		/* Dont modify info while calculating */
X
X		s = spltty();
X
X		/* Build mouse status octet */
X
X		info.status = sc->status;
X		if (sc->x || sc->y)
X			info.status |= MOVEMENT;
X
X		/* Encode X and Y motion as good as we can */
X
X		if (sc->x > 127)
X			info.xmotion = 127;
X		else if (sc->x < -128)
X			info.xmotion = -128;
X		else
X			info.xmotion = sc->x;
X
X		if (sc->y > 127)
X			info.ymotion = 127;
X		else if (sc->y < -128)
X			info.ymotion = -128;
X		else
X			info.ymotion = sc->y;
X
X		/* Reset historical information */
X
X		sc->x = 0;
X		sc->y = 0;
X		sc->status &= ~BUTCHNGMASK;
X
X		/* Allow interrupts and copy result buffer */
X
X		splx(s);
X		error = copyout(&info, addr, sizeof(struct mouseinfo));
X		break;
X
X	default:
X		error = EINVAL;
X		break;
X		}
X
X	/* Return error code */
X
X	return(error);
X	}
X
Xvoid bmsintr(unit)
X	int unit;
X	{
X	struct bms_softc *sc = &bms_softc[unit];
X	int ioport = bmsaddr[unit];
X	char x, y, sts;
X
X	/* Freeze InPort registers */
X
X	outb(ioport+ADDR, 7);
X	outb(ioport+DATA, 0x29);
X
X	/* Read mouse status */
X
X	outb(ioport+ADDR, 0);
X	sts = inb(ioport+DATA);
X
X	/* Check if any movement detected */
X
X	if (sts & 0x40)
X		{
X		outb(ioport+ADDR, 1);
X		x = inb(ioport+DATA);
X		outb(ioport+ADDR, 2);
X		y = inb(ioport+DATA);
X		if (y == -128)
X			y = 127;
X		else
X			y = -y;
X		}
X	else
X		{
X		x = 0;
X		y = 0;
X		}
X
X	/* Unfreeze InPort Registers (re-enables interrupts) */
X
X	outb(ioport+ADDR, 7);
X	outb(ioport+DATA, 0x09);
X
X	/* Update accumulated movements */
X
X	sc->x += x;
X	sc->y += y;
X
X	/* Inclusive OR status changes, but always save only last state */
X
X	sc->status |= sts & BUTCHNGMASK;
X	sc->status = (sc->status & ~BUTSTATMASK) | (sts & BUTSTATMASK);
X
X	/* If device in use and any change occurred ... */
X
X	if (sc->state & OPEN && sts & 0x78 && sc->inq.count < (MSBSZ-5))
X		{
X		sts &= BUTSTATMASK;
X		sc->inq.queue[sc->inq.last++] = 0x80 | (sts ^ BUTSTATMASK);
X		sc->inq.queue[sc->inq.last++ % MSBSZ] = x;
X		sc->inq.queue[sc->inq.last++ % MSBSZ] = y;
X		sc->inq.queue[sc->inq.last++ % MSBSZ] = 0;
X		sc->inq.queue[sc->inq.last++ % MSBSZ] = 0;
X		sc->inq.last = sc->inq.last % MSBSZ;
X		sc->inq.count += 5;
X
X		if (sc->state & ASLP)
X			{
X			sc->state &= ~ASLP;
X			wakeup(sc);
X			}
X		if (sc->rsel)
X			{
X			selwakeup(sc->rsel, 0);
X			sc->rsel = NULL;
X			}
X		}
X	}
X
Xint bmsselect(dev, rw, p)
X	dev_t dev;
X	int rw;
X	struct proc *p;
X	{
X	int s, ret;
X	struct bms_softc *sc = &bms_softc[BMSUNIT(dev)];
X
X	/* Silly to select for Output */
X
X	if (rw == FWRITE)
X		return(0);
X
X	/* Return true if a mouse event available */
X
X	s = spltty();
X	if (sc->inq.count != 0)
X		ret = 1;
X	else
X		{
X		ret = 0;
X		sc->rsel = p;
X		}
X
X	splx(s);
X	return(ret);
X	}
X
X#endif
END-of-bms.c
echo x - conf.c.diff
sed 's/^X//' >conf.c.diff << 'END-of-conf.c.diff'
X*** conf.c.orig	Sat Oct 17 15:30:58 1992
X--- conf.c	Sat Oct 17 15:34:45 1992
X***************
X*** 165,175 ****
X  #define	com_tty		NULL
X  #endif
X  
X  int	logopen(),logclose(),logread(),logioctl(),logselect();
X  
X  int	ttselect(), seltrue();
X  
X- 
X  struct cdevsw	cdevsw[] =
X  {
X  	{ cnopen,	cnclose,	cnread,		cnwrite,	/*0*/
X--- 165,185 ----
X  #define	com_tty		NULL
X  #endif
X  
X+ #include "bms.h"
X+ #if NBMS > 0
X+ int	bmsopen(),bmsclose(),bmsread(),bmsselect(),bmsioctl();
X+ #else
X+ #define bmsopen		enxio
X+ #define bmsclose	enxio
X+ #define bmsread		enxio
X+ #define bmsselect	enxio
X+ #define bmsioctl	enxio
X+ #endif
X+ 
X  int	logopen(),logclose(),logread(),logioctl(),logselect();
X  
X  int	ttselect(), seltrue();
X  
X  struct cdevsw	cdevsw[] =
X  {
X  	{ cnopen,	cnclose,	cnread,		cnwrite,	/*0*/
X***************
X*** 214,219 ****
X--- 224,232 ----
X  	{ asopen,	asclose,	rawread,	rawwrite,	/*D*/
X  	  asioctl,	enodev,		nullop,		NULL,
X  	  seltrue,	enodev,		asstrategy },
X+ 	{ bmsopen,	bmsclose,	bmsread,	nullop,		/*E*/
X+ 	  bmsioctl,	enodev,		nullop,		NULL,
X+ 	  bmsselect,	enodev,		NULL },
X  };
X  int	nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
END-of-conf.c.diff
echo x - files.i386.diff
sed 's/^X//' >files.i386.diff << 'END-of-files.i386.diff'
X*** files.i386.orig	Sat Oct 17 15:40:39 1992
X--- files.i386	Sat Oct 17 15:40:57 1992
X***************
X*** 21,26 ****
X--- 21,27 ----
X  i386/isa/isa.c		optional isa device-driver
X  i386/isa/com.c		optional com device-driver
X  i386/isa/npx.c		optional npx device-driver
X+ i386/isa/bms.c		optional bms device-driver
X  i386/isa/as.c		optional as device-driver
X  i386/i386/db_disasm.c	optional ddb
X  i386/i386/db_interface.c	optional ddb
END-of-files.i386.diff
echo x - isa.h.diff
sed 's/^X//' >isa.h.diff << 'END-of-isa.h.diff'
X*** isa.h	Thu Feb 20 14:26:12 1992
X--- /usr/src/sys/i386/isa/isa.h	Mon Apr 27 22:13:39 1992
X***************
X*** 76,82 ****
X  #define IO_WD1		0x1f0		/* Primary Fixed Disk Controller */
X  #define IO_GAME		0x200		/* Game Controller */
X  
X! 					/* 0x208 - 0x277 Open */
X  
X  #define IO_LPT2		0x278		/* Parallel Port #2 */
X  
X--- 76,87 ----
X  #define IO_WD1		0x1f0		/* Primary Fixed Disk Controller */
X  #define IO_GAME		0x200		/* Game Controller */
X  
X! 					/* 0x208 - 0x237 Open */
X! 
X! #define IO_BMS2		0x238		/* secondary InPort Bus Mouse */
X! #define IO_BMS1		0x23c		/* primary InPort Bus Mouse */
X! 
X! 					/* 0x240 - 0x277 Open */
X  
X  #define IO_LPT2		0x278		/* Parallel Port #2 */
X  
END-of-isa.h.diff
echo x - mouse.h
sed 's/^X//' >mouse.h << 'END-of-mouse.h'
X/*-
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
Xstruct mouseinfo {
X	unsigned char status;
X	char xmotion, ymotion;
X	};
X
X#define BUTSTATMASK	0x07	/* Any mouse button down if any bit set */
X#define BUTCHNGMASK	0x38	/* Any mouse button changed if any bit set */
X
X#define BUT3STAT	0x01	/* Button 3 down if set */
X#define BUT2STAT	0x02	/* Button 2 down if set */
X#define BUT1STAT	0x04	/* Button 1 down if set */
X#define BUT3CHNG	0x08	/* Button 3 changed if set */
X#define BUT2CHNG	0x10	/* Button 2 changed if set */
X#define BUT1CHNG	0x20	/* Button 1 changed if set */
X#define MOVEMENT	0x40	/* Mouse movement detected */
X
X/* Ioctl definitions */
X
X#define MOUSEIOC        ('M'<<8)
X#define MOUSEIOCREAD	(MOUSEIOC|60)
END-of-mouse.h
echo x - testmse.c
sed 's/^X//' >testmse.c << 'END-of-testmse.c'
X#include <stdio.h>
X#include <fcntl.h>
X#include <sys/types.h>
X#include <sys/time.h>
X
X/*
X * A simple test program for the bus mouse driver.
X */
Xmain() {
X	int mfd, i, j;
X	fd_set readfd;
X	char buf[1024];
X	extern int errno;
X
X	mfd = open("/dev/mouse", O_RDONLY);
X	if (mfd < 0) {
X		fprintf(stderr, "Mouse open err=%d\n", errno);
X		exit(1);
X	}
X
X	/*
X	 * Test reading the mouse.
X	 */
X	printf("Mouse read test: jiggle mousey please\n");
X	for (j = 0; j < 20; j++) {
X		if (read(mfd, buf, 5) != 5) {
X			fprintf(stderr, "Mouse read err=%d\n", errno);
X			exit(1);
X		}
X		printf("mse: but=0x%x dx=%d dy=%d\n",buf[0] & 0x7, buf[1], buf[2]);
X	}
X	printf("Got 20 mouse inputs\n");
X
X	/*
X	 * Now test the select syscall for the mouse and stdin.
X	 */
X	printf("Mouse select test: type keys and wiggle mouse please\n");
X	for (j = 0; j < 50; j++) {
X		FD_ZERO(&readfd);
X		FD_SET(0, &readfd);	/* stdin */
X		FD_SET(mfd, &readfd);	/* and mouse */
X		i = select(mfd + 1, &readfd, (fd_set *)0, (fd_set *)0,
X			(struct timeval *)0);
X		if (i <= 0) {
X			fprintf(stderr, "Select syscall err=%d\n", errno);
X			exit(1);
X		}
X		if (FD_ISSET(0, &readfd)) {
X			if ((i = read(0, buf, 1024)) <= 0) {
X				fprintf(stderr, "Stdin read err=%d\n", errno);
X				exit(1);
X			}
X			buf[i] = '\0';
X			printf("kbd: Got %s\n", buf);
X		}
X		if (FD_ISSET(mfd, &readfd)) {
X			if (read(mfd, buf, 5) != 5) {
X				fprintf(stderr, "Mouse read err=%d\n", errno);
X				exit(1);
X			}
X			printf("mse: but=0x%x dx=%d dy=%d\n",buf[0] & 0x7, buf[1], buf[2]);
X		}
X	}
X	printf("Test done, bye\n");
X}
END-of-testmse.c
exit