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