Return to BSD News archive
Newsgroups: comp.unix.bsd Path: sserve!manuel!munnari.oz.au!uunet!haven.umd.edu!wam.umd.edu!fcawth From: fcawth@wam.umd.edu (Alfred B. Cawthorne) Subject: [386bsd] bus mouse driver Message-ID: <1992Sep7.152230.22199@wam.umd.edu> Originator: fcawth@rac2.wam.umd.edu Sender: usenet@wam.umd.edu (USENET News system) Nntp-Posting-Host: rac2.wam.umd.edu Organization: University of Maryland at College Park Date: Mon, 7 Sep 1992 15:22:30 GMT Lines: 390 Here is the second version of my logitech bus mouse driver. I use it with X386 with good results. It requires no modification of the X386 code so you can use it with the binaries that are floating around. Please send any fixes, etc... to fcawth@delphi.umd.edu Fred. cut here.--------------- # 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 # mse.c # mse.h # tst.c # echo x - README sed 's/^X//' >README << 'END-of-README' XThis is a simple bus mouse driver I wrote so I could use my logitech bus Xmouse with X386. The standard disclaimer applies to this code. USE AT XYOUR OWN RISK!!! This is not a finished product, and I don't have lots of time Xto make it really nice. I just wanted to use my mouse with X386! X XVersion 0.1: First attempt, non interrupt driven. This version worked ok, but X certain operations (like moving the scrollbar) were slow because the mouse X port did not get read fast enough. X XVersion 0.2: Still not as nice as I'd like it, but it works much better than X the first version. A buffer was added which stores mouse values when the X mouse card interrupts. I am not sure why, but buttons need to be posted X twice to be recognized correctly by X386. I noticed that I would have to X move my cheapo serial mouse for the buttons to get recognized, so I suspect X that this is a feature of X386. The buffering in this version is very X primative. X XFuture: Write a nifty circular queue for the mouse data, and don't reset X after each read. X XInstallation Instructions: X X1. copy the files mse.c and mse.h into the /sys/i386/isa directory. X X2. add the line: Xdevice mse0 at isa? port 0x23c irq9 vector mseintr Xto your system's config file. X(Note: the port's address can be changed in the mse.h file) X X3. add the line: Xi386/isa/mse.c optional mse device-driver Xto /sys/i386/conf/files.i386 X X4. add this to /sys/i386/i386/conf.c X X#include "mse.h" X#if NMSE >0 Xint mseioctl(),mseopen(),mseclose(),mseread(),msewrite(); X#else Xdefine mseiocntl enxio Xdefine mseclose enxio Xdefine mseread enxio Xdefine msewrite enxio Xdefine mseopen enxio X#endif X X5. change an entry in the cdevsw array (conf.c) to read: X X { mseopen, mseclose, mseread, msewrite, X mseioctl, nullop, nullop, NULL, X seltrue, enodev, enodev }, X X(Note that the position of this determines the major device # of the driver) X( a hex number to the right of each entry is given so you don't even have to X count ) X6. Make the driver special file: Xmknod /dev/mouse c <major> 0 X X7. To use it with X386, add the line: XBusMouse "/dev/mouse" Xto the Xconfig file and comment out all the serial mouse related stuff. X XNow, it should work. I included a test program I used when writing this. X XSend any questions or comments to fcawth@delphi.umd.edu. END-of-README echo x - mse.c sed 's/^X//' >mse.c << 'END-of-mse.c' X/* 386bsd logitech Bus Mouse driver Fred Cawthorne 8/25/92 */ X/* This is a BETA release (at best) as it is my first attempt at programming */ X/* a bsd device driver. It is intended to be a simple but usable bus mouse */ X/* driver. I have tested this with the binary X386 release from agate, and */ X/* it seems to work fine. This driver gives the user two ways of accessing */ X/* the mouse. IOCTLS probabally involve less overhead than READ's but the */ X/* mseread routine was included for compatibility with X386. */ X/* Please send any improvements, suggestions, etc to fcawth@delphi.umd.edu */ X X X/* Version 0.2 Interrupt driven version */ X/* Permission is given to copy, modify, and use this code in any way you see */ X/* fit. I assume no responsibility for the problems this code could cause. */ X/* The only thing I know is that it works for me, it may or not work for you.*/ X X X#include "mse.h" X X#include "param.h" X#include "ioctl.h" X#include "conf.h" X#include "uio.h" X#include "kernel.h" X X#include "i386/isa/isa_device.h" Xstatic char mse_buffer[193]; Xstatic int mse_bufptr; Xint mseprobe(), mseattach(), msestart(), mseparam(); Xstruct isa_driver msedriver = { X mseprobe, mseattach, "mse" X}; X Xmseprobe(dev) Xstruct isa_device *dev; X{ X/*hack for now, if your bus mouse doesn't like this, find out what its sig. is*/ X/* we need a good way of finding out if it is really there but I don't have */ X/* any hardware documentation for the mouse */ Xif (inb(SIGNATURE_PORT)==0) X return(1); Xelse return(0); X} X X Xint Xmseattach(isdp) Xstruct isa_device *isdp; X{ X outb (CONTROL,0); X/* outb(CONTROL, MOUSEDEFAULT); X outb(PORTC, PORTC_DISABLE_INTERRUPTS); */ Xprintf (" sig=%d",inb(SIGNATURE_PORT)); Xreturn (1); X} X Xmseopen(dev_t dev, int flag, int mode, struct proc *p) X{ X outb(CONTROL, MOUSEDEFAULT); Xmse_bufptr=0; X outb(PORTC, PORTC_ENABLE_INTERRUPTS); X Xreturn(0); X} X Xmseclose(dev, flag, mode, p) X dev_t dev; X int flag, mode; X struct proc *p; X{ X outb(CONTROL, 0); X outb(PORTC, PORTC_DISABLE_INTERRUPTS); Xreturn(0); X} X Xmseintr(unit) X{ Xstruct mousedat mouse_dat; Xint i; Xstatic int oldbut; Xstatic int buttonpress = 0; X Xoutb(PORTC, PORTC_DISABLE_INTERRUPTS); X outb(PORTC, READ_X_LOW); X mouse_dat.deltax = inb(PORTA) & 0xf; X outb(PORTC, READ_X_HIGH); X mouse_dat.deltax |= (inb(PORTA) & 0xf) << 4; X X outb(PORTC, READ_Y_LOW ); X mouse_dat.deltay = inb(PORTA) & 0xf; X outb(PORTC, READ_Y_HIGH); X i = inb(PORTA); Xoutb(PORTC, PORTC_DISABLE_INTERRUPTS); X mouse_dat.deltay |= (i & 0xf) << 4; X mouse_dat.buttons = (i >> 5)|0x80; X if((char)(mouse_dat.deltay)==(-128)) (char)mouse_dat.deltay++; X if ((char)(mouse_dat.deltay)!=0) mouse_dat.deltay=-mouse_dat.deltay; X if((char)(mouse_dat.deltax)==(-128)) (char)mouse_dat.deltax++; Xif ((mouse_dat.deltax!=0)||(mouse_dat.deltay!=0)||(mouse_dat.buttons!=oldbut)) X{ Xif (buttonpress>1 ) { Xoldbut=mouse_dat.buttons; Xbuttonpress=0; } Xelse { Xbuttonpress++; Xoldbut=0; } X Xmse_buffer[mse_bufptr++]=(char)mouse_dat.buttons; Xmse_buffer[mse_bufptr++]=(char)mouse_dat.deltax; Xmse_buffer[mse_bufptr++]=(char)mouse_dat.deltay; Xif (mse_bufptr>191) mse_bufptr=(189); X/*printf ("mse_bufptr=%d\n",mse_bufptr++); Xprintf ("MOUSEINTR called dx=%d dy=%d but=%d\n",mouse_dat.deltax,mouse_dat.deltay,mouse_dat.buttons); X*/ X} Xoutb(PORTC,PORTC_ENABLE_INTERRUPTS); X X} Xmseioctl(dev, cmd, data, flag) X dev_t dev; X int cmd,flag; X struct mousedat* data; X{ int i; Xregister struct mousedat mouse_dat; X switch(cmd) { X case MIOGETDATA:outb(PORTC, READ_X_LOW); X mouse_dat.deltax = inb(PORTA) & 0xf; X outb(PORTC, READ_X_HIGH); X mouse_dat.deltax |= (inb(PORTA) & 0xf) << 4; X X outb(PORTC, READ_Y_LOW ); X mouse_dat.deltay = inb(PORTA) & 0xf; X outb(PORTC, READ_Y_HIGH); X i = inb(PORTA); X mouse_dat.deltay |= (i & 0xf) << 4; X mouse_dat.buttons = i >> 5; X(struct mousedat *)data->buttons=(7-(mouse_dat.buttons)); X(struct mousedat *)data->deltax=mouse_dat.deltax; X(struct mousedat *)data->deltay=mouse_dat.deltay; Xreturn(0); X break; X X default: return(EFAULT); X break; X } Xreturn(0); X} X Xmsestart(tp) X register struct mousedat *tp; X{ X} X Xmseread (dev,uio,flag) X struct uio *uio; X dev_t dev; Xint flag; X X{ Xint ptr; Xif (mse_bufptr!=0) Xfor (ptr=0; ptr<mse_bufptr; ptr++ ) { X/*printf ("mse_buffer[%d]=%d,",ptr,mse_buffer[ptr]); */ Xif ((uio->uio_resid)>3) { X ureadc((char)mse_buffer[ptr++],uio); X ureadc((char)mse_buffer[ptr++],uio); X ureadc((char)mse_buffer[ptr],uio); X } X} Xmse_bufptr=0; Xreturn(0); X} X Xmsewrite(dev,uio,flag) Xdev_t dev; Xstruct uio *uio; X{} X END-of-mse.c echo x - mse.h sed 's/^X//' >mse.h << 'END-of-mse.h' X/* mouse.h: header file for Logitech Bus Mouse driver */ X X#ifndef MOUSE_H X#define MOUSE_H X X/* #define USE_INTS /* Should the driver use interrupts? */ X X#define PORTA 0x23c /* 1100 */ X#define SIGNATURE_PORT 0x23d /* 1101 */ X#define PORTC 0x23e /* 1110 */ X#define CONTROL 0x23f /* 1111 */ X X#define SETMODE 0x80 /* 1xxx xxxx */ X /* Group A */ X#define M_AMODE0 0x00 /* x00x xxxx */ X#define M_AMODE1 0x20 /* x01x xxxx */ X#define M_AMODE2 0x40 /* x10x xxxx */ X#define M_AIN 0x10 /* xxx1 xxxx */ X#define M_AOUT 0x00 /* xxx0 xxxx */ X#define M_CUIN 0x08 /* xxxx 1xxx */ X#define M_CUOUT 0x00 /* xxxx 0xxx */ X /* Group B */ X#define M_BMODE0 0x00 /* xxxx x0xx */ X#define M_BMODE1 0x04 /* xxxx x1xx */ X#define M_BIN 0x02 /* xxxx xx1x */ X#define M_BOUT 0x00 /* xxxx xx0x */ X#define M_CLIN 0x01 /* xxxx xxx1 */ X#define M_CLOUT 0x00 /* xxxx xxx0 */ X X#define MOUSEDEFAULT (SETMODE|M_AMODE0|M_AIN) /* 1001 0000 */ X X#define READ_X_LOW 0x80 /* 1000 0000 */ X#define READ_X_HIGH 0xa0 /* 1010 0000 */ X#define READ_Y_LOW 0xc0 /* 1100 0000 */ X#define READ_Y_HIGH 0xe0 /* 1110 0000 */ X X#define PORTC_ENABLE_INTERRUPTS 0x80 /* 1000 0000 */ X#define PORTC_DISABLE_INTERRUPTS 0x10 /* 0000 0000 */ X Xstruct mousedat { X unsigned char buttons; X char deltax,deltay; X}; X X/* IOCTLS */ X#define MIOGETDATA ((sizeof(struct mousedat*)<<16)|('M'<<8) | 0x01 |0x40000000) /* get mouse data */ X X#endif X END-of-mse.h echo x - tst.c sed 's/^X//' >tst.c << 'END-of-tst.c' X X/* X Test program for Mouse Driver X DON'T use this while you are using the mouse under X windows or it will X get confused... X*/ X X#include <sys/file.h> X#include <sys/ioctl.h> X#include <sys/types.h> X#include "mse.h" X Xint mousefd; X X Xmain() X{ X struct mousedat new,old; X int xpos, ypos; X X old.deltax = old.deltay = old.buttons = 1; X X if ((mousefd = open("/dev/mouse",O_RDWR,0)) == -1) { X perror("open of mouse device"); X exit(1); X } Xwhile (1) readmouse(&new); X Xold.buttons=0; X xpos = ypos = 1; X while (old.buttons != 7) { /* press all 3 buttons to quit */ X readmouse(&new); X if ((new.deltax!=0)||(new.deltay!=0)||(new.buttons!=old.buttons)){ X xpos += new.deltax; ypos += new.deltay; X printf("X=%03d Y=%03d Buttons=%c%c%c\n", xpos, ypos, X new.buttons & 4 ? '*' : ' ', X new.buttons & 2 ? '*' : ' ', X new.buttons & 1 ? '*' : ' ' ); X old.buttons=new.buttons; X old.deltax=new.deltax; X old.deltay=new.deltay; X } X } X} X Xreadmouse( md ) Xregister struct mousedat *md; X{ Xint i; Xchar buf[1024]; Xint len = 10; X/* if ((ioctl(mousefd,MIOGETDATA,md)) == -1) { X perror("IOCTL failed on /dev/mouse"); X exit(2); X } */ X/* some printfs to see if everything's OK */ X X/*printf ("deltax=%d deltay=%d buttons=%d \n",md->deltax,md->deltay,md->buttons); */ Xlen=read(mousefd,&buf,64); Xfor (i=0; i<len ; i++) Xprintf ("len=%d buf[%d]=%d \n",len,i,buf[i]); Xsleep(1); X} X END-of-tst.c exit