diff options
-rw-r--r-- | sys/alpha/include/console.h | 15 | ||||
-rw-r--r-- | sys/alpha/include/mouse.h | 177 | ||||
-rw-r--r-- | sys/dev/mse/mse.c | 225 | ||||
-rw-r--r-- | sys/dev/syscons/syscons.c | 484 | ||||
-rw-r--r-- | sys/i386/include/console.h | 15 | ||||
-rw-r--r-- | sys/i386/include/mouse.h | 177 | ||||
-rw-r--r-- | sys/i386/isa/kbdio.h | 3 | ||||
-rw-r--r-- | sys/i386/isa/mse.c | 225 | ||||
-rw-r--r-- | sys/i386/isa/psm.c | 1683 | ||||
-rw-r--r-- | sys/i386/isa/syscons.c | 484 | ||||
-rw-r--r-- | sys/isa/kbdio.h | 3 | ||||
-rw-r--r-- | sys/isa/syscons.c | 484 | ||||
-rw-r--r-- | sys/sys/mouse.h | 177 |
13 files changed, 3184 insertions, 968 deletions
diff --git a/sys/alpha/include/console.h b/sys/alpha/include/console.h index cbeb2c4..539a61d 100644 --- a/sys/alpha/include/console.h +++ b/sys/alpha/include/console.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: console.h,v 1.31 1997/09/04 09:05:17 kato Exp $ + * $Id: console.h,v 1.32 1997/10/01 20:46:25 sos Exp $ */ #ifndef _MACHINE_CONSOLE_H_ @@ -108,13 +108,10 @@ struct vt_mode { short frsig; /* not implemented yet SOS */ }; -#define RIGHT_BUTTON 0x01 -#define MIDDLE_BUTTON 0x02 -#define LEFT_BUTTON 0x04 - struct mouse_data { int x; int y; + int z; int buttons; }; @@ -123,6 +120,11 @@ struct mouse_mode { int signal; }; +struct mouse_event { + int id; /* one based */ + int value; +}; + #define MOUSE_SHOW 0x01 #define MOUSE_HIDE 0x02 #define MOUSE_MOVEABS 0x03 @@ -130,12 +132,15 @@ struct mouse_mode { #define MOUSE_GETINFO 0x05 #define MOUSE_MODE 0x06 #define MOUSE_ACTION 0x07 +#define MOUSE_MOTION_EVENT 0x08 +#define MOUSE_BUTTON_EVENT 0x09 struct mouse_info { int operation; union { struct mouse_data data; struct mouse_mode mode; + struct mouse_event event; }u; }; diff --git a/sys/alpha/include/mouse.h b/sys/alpha/include/mouse.h index 86f4528..d0eecef 100644 --- a/sys/alpha/include/mouse.h +++ b/sys/alpha/include/mouse.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 1992, 1993 Erik Forsberg. + * Copyright (c) 1996, 1997 Kazutaka YOKOTA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -19,7 +20,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: mouse.h,v 1.7 1997/02/22 09:34:50 peter Exp $ + * $Id: mouse.h,v 1.8 1997/10/19 10:44:02 yokota Exp $ */ #ifndef _MACHINE_MOUSE_H_ @@ -28,45 +29,33 @@ #include <sys/types.h> #include <sys/ioccom.h> -/* - * NOTE: MOUSEIOC, MOUSEIOCREAD, and mouseinfo are now obsolete, - * but will stay for compatibility reasons. But, remember, - * the MOUSEIOCREAD ioctl command doesn't work and never worked before. - * Some day we shall get rid of these... - */ +/* ioctls */ +#define MOUSE_GETSTATUS _IOR('M', 0, mousestatus_t) +#define MOUSE_GETHWINFO _IOR('M', 1, mousehw_t) +#define MOUSE_GETMODE _IOR('M', 2, mousemode_t) +#define MOUSE_SETMODE _IOW('M', 3, mousemode_t) +#define MOUSE_GETLEVEL _IOR('M', 4, int) +#define MOUSE_SETLEVEL _IOW('M', 5, int) +#define MOUSE_GETVARS _IOR('M', 6, mousevar_t) +#define MOUSE_SETVARS _IOW('M', 7, mousevar_t) +#define MOUSE_READSTATE _IOWR('M', 8, mousedata_t) +#define MOUSE_READDATA _IOWR('M', 9, mousedata_t) -#define MOUSEIOC ('M'<<8) -#define MOUSEIOCREAD (MOUSEIOC|60) - -typedef struct mouseinfo { - unsigned char status; - char xmotion; - char ymotion; -} mouseinfo_t; -/* status */ -#define BUTSTATMASK 0x07 /* Any mouse button down if any bit set */ -#define BUTCHNGMASK 0x38 /* Any mouse button changed if any bit set */ -#define BUT3STAT 0x01 /* Button 3 down if set */ -#define BUT2STAT 0x02 /* Button 2 down if set */ -#define BUT1STAT 0x04 /* Button 1 down if set */ -#define BUT3CHNG 0x08 /* Button 3 changed if set */ -#define BUT2CHNG 0x10 /* Button 2 changed if set */ -#define BUT1CHNG 0x20 /* Button 1 changed if set */ -#define MOVEMENT 0x40 /* Mouse movement detected */ - -#define MOUSE_GETSTATE _IOR('M',0,mousestatus_t) -#define MOUSE_GETHWINFO _IOR('M',1,mousehw_t) -#define MOUSE_GETMODE _IOR('M',2,mousemode_t) -#define MOUSE_SETMODE _IOW('M',3,mousemode_t) - -/* new ioctls */ +#if notyet +#define MOUSE_SETRESOLUTION _IOW('M', 10, int) +#define MOUSE_SETSCALING _IOW('M', 11, int) +#define MOUSE_SETRATE _IOW('M', 12, int) +#define MOUSE_GETHWID _IOR('M', 13, int) +#endif /* mouse status block */ typedef struct mousestatus { + int flags; /* state change flags */ int button; /* button status */ int obutton; /* previous button status */ int dx; /* x movement */ int dy; /* y movement */ + int dz; /* z movement */ } mousestatus_t; /* button */ @@ -78,23 +67,34 @@ typedef struct mousestatus { #define MOUSE_BUTTON6DOWN 0x0020 #define MOUSE_BUTTON7DOWN 0x0040 #define MOUSE_BUTTON8DOWN 0x0080 -#define MOUSE_STDBUTTONS 0x0007 /* buttons 1-3 */ -#define MOUSE_EXTBUTTONS 0x00f8 /* the others */ +#define MOUSE_MAXBUTTON 31 +#define MOUSE_STDBUTTONS 0x0007 /* buttons 1-3 */ +#define MOUSE_EXTBUTTONS 0x7ffffff8 /* the others (28 of them!) */ +#define MOUSE_BUTTONS (MOUSE_STDBUTTONS | MOUSE_EXTBUTTONS) + +/* flags */ +#define MOUSE_STDBUTTONSCHANGED MOUSE_STDBUTTONS +#define MOUSE_EXTBUTTONSCHANGED MOUSE_EXTBUTTONS +#define MOUSE_BUTTONSCHANGED MOUSE_BUTTONS +#define MOUSE_POSCHANGED 0x80000000 typedef struct mousehw { - int buttons; + int buttons; /* -1 if unknown */ int iftype; /* MOUSE_IF_XXX */ int type; /* mouse/track ball/pad... */ + int model; /* I/F dependent model ID: MOUSE_MODEL_XXX */ int hwid; /* I/F dependent hardware ID * for the PS/2 mouse, it will be PSM_XXX_ID */ } mousehw_t; /* iftype */ +#define MOUSE_IF_UNKNOWN (-1) #define MOUSE_IF_SERIAL 0 #define MOUSE_IF_BUS 1 #define MOUSE_IF_INPORT 2 #define MOUSE_IF_PS2 3 +#define MOUSE_IF_SYSMOUSE 4 /* type */ #define MOUSE_UNKNOWN (-1) /* should be treated as a mouse */ @@ -103,24 +103,67 @@ typedef struct mousehw { #define MOUSE_STICK 2 #define MOUSE_PAD 3 +/* model */ +#define MOUSE_MODEL_UNKNOWN (-1) +#define MOUSE_MODEL_GENERIC 0 +#define MOUSE_MODEL_GLIDEPOINT 1 +#define MOUSE_MODEL_NETSCROLL 2 +#define MOUSE_MODEL_NET 3 +#define MOUSE_MODEL_INTELLI 4 +#define MOUSE_MODEL_THINK 5 +#define MOUSE_MODEL_EASYSCROLL 6 +#define MOUSE_MODEL_MOUSEMANPLUS 7 + typedef struct mousemode { int protocol; /* MOUSE_PROTO_XXX */ int rate; /* report rate (per sec), -1 if unknown */ - int resolution; /* 1:low, 2:medium low, 3:medium high - * 4:high, 0: default, -1 if unknown - */ + int resolution; /* MOUSE_RES_XXX, -1 if unknown */ int accelfactor; /* accelation factor (must be 1 or greater) */ + int level; /* driver operation level */ + int packetsize; /* the length of the data packet */ + unsigned char syncmask[2]; /* sync. data bits in the header byte */ } mousemode_t; /* protocol */ +#define MOUSE_PROTO_UNKNOWN (-1) #define MOUSE_PROTO_MS 0 /* Microsoft Serial, 3 bytes */ #define MOUSE_PROTO_MSC 1 /* Mouse Systems, 5 bytes */ #define MOUSE_PROTO_LOGI 2 /* Logitech, 3 bytes */ #define MOUSE_PROTO_MM 3 /* MM series, 3 bytes */ #define MOUSE_PROTO_LOGIMOUSEMAN 4 /* Logitech MouseMan 3/4 bytes */ #define MOUSE_PROTO_BUS 5 /* MS/Logitech bus mouse */ -#define MOUSE_PROTO_INPORT 6 /* MS/ATI inport mouse */ +#define MOUSE_PROTO_INPORT 6 /* MS/ATI InPort mouse */ #define MOUSE_PROTO_PS2 7 /* PS/2 mouse, 3 bytes */ +#define MOUSE_PROTO_HITTAB 8 /* Hitachi Tablet 3 bytes */ +#define MOUSE_PROTO_GLIDEPOINT 9 /* ALPS GlidePoint, 3/4 bytes */ +#define MOUSE_PROTO_INTELLI 10 /* MS IntelliMouse, 4 bytes */ +#define MOUSE_PROTO_THINK 11 /* Kensignton Thinking Mouse, 3/4 bytes */ +#define MOUSE_PROTO_SYSMOUSE 12 /* /dev/sysmouse */ + +#define MOUSE_RES_UNKNOWN (-1) +#define MOUSE_RES_DEFAULT 0 +#define MOUSE_RES_LOW (-2) +#define MOUSE_RES_MEDIUMLOW (-3) +#define MOUSE_RES_MEDIUMHIGH (-4) +#define MOUSE_RES_HIGH (-5) + +typedef struct mousedata { + int len; /* # of data in the buffer */ + int buf[16]; /* data buffer */ +} mousedata_t; + +#if (defined(MOUSE_GETVARS)) + +typedef struct mousevar { + int var[16]; +} mousevar_t; + +/* magic numbers in var[0] */ +#define MOUSE_VARS_PS2_SIG 0x00325350 /* 'PS2' */ +#define MOUSE_VARS_BUS_SIG 0x00535542 /* 'BUS' */ +#define MOUSE_VARS_INPORT_SIG 0x00504e49 /* 'INP' */ + +#endif /* MOUSE_GETVARS */ /* Microsoft Serial mouse data packet */ #define MOUSE_MSS_PACKETSIZE 3 @@ -132,7 +175,19 @@ typedef struct mousemode { #define MOUSE_MSS_BUTTON3DOWN 0x10 /* right */ /* Logitech MouseMan data packet (M+ protocol) */ -#define MOUSE_LMAN_BUTTON2DOWN 0x20 /* middle button, in the 4th byte */ +#define MOUSE_LMAN_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ + +/* ALPS GlidePoint extention (variant of M+ protocol) */ +#define MOUSE_ALPS_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ +#define MOUSE_ALPS_TAP 0x10 /* `tapping' action, the 4th byte */ + +/* Kinsington Thinking Mouse extention (variant of M+ protocol) */ +#define MOUSE_THINK_BUTTON2DOWN 0x20 /* lower-left button, the 4th byte */ +#define MOUSE_THINK_BUTTON4DOWN 0x10 /* lower-right button, the 4th byte */ + +/* MS IntelliMouse (variant of MS Serial) */ +#define MOUSE_INTELLI_PACKETSIZE 4 +#define MOUSE_INTELLI_BUTTON2DOWN 0x10 /* middle button the 4th byte */ /* Mouse Systems Corp. mouse data packet */ #define MOUSE_MSC_PACKETSIZE 5 @@ -156,18 +211,50 @@ typedef struct mousemode { /* PS/2 mouse data packet */ #define MOUSE_PS2_PACKETSIZE 3 -#define MOUSE_PS2_SYNCMASK 0x08 /* 0x0c for 2 button mouse */ -#define MOUSE_PS2_SYNC 0x08 /* 0x0c for 2 button mouse */ +#define MOUSE_PS2_SYNCMASK 0xc8 +#define MOUSE_PS2_SYNC 0x08 #define MOUSE_PS2_BUTTONS 0x07 /* 0x03 for 2 button mouse */ #define MOUSE_PS2_BUTTON1DOWN 0x01 /* left */ #define MOUSE_PS2_BUTTON2DOWN 0x04 /* middle */ #define MOUSE_PS2_BUTTON3DOWN 0x02 /* right */ -#define MOUSE_PS2_BUTTON4UP 0x08 /* GlidePoint tapping feature - * Yes! this is the same bit as SYNC! - */ +#define MOUSE_PS2_TAP MOUSE_PS2_SYNC /* GlidePoint (PS/2) `tapping' + * Yes! this is the same bit + * as SYNC! + */ +#define MOUSE_PS2PLUS_BUTTON4DOWN 0x10 /* 4th button on MouseMan+ */ + #define MOUSE_PS2_XNEG 0x10 #define MOUSE_PS2_YNEG 0x20 #define MOUSE_PS2_XOVERFLOW 0x40 #define MOUSE_PS2_YOVERFLOW 0x80 +#define MOUSE_PS2PLUS_ZNEG 0x08 /* MouseMan+ negative wheel movement */ + +/* sysmouse extended data packet */ +/* + * /dev/sysmouse sends data in two formats, depending on the protocol + * level. At the level 0, format is exactly the same as MousSystems' + * five byte packet. At the level 1, the first five bytes are the same + * as at the level 0. There are additional three bytes which shows + * `dz' and the states of additional buttons. `dz' is expressed as the + * sum of the byte 5 and 6 which contain signed seven bit values. + * The states of the button 4 though 10 are in the bit 0 though 6 in + * the byte 7 respectively: 1 indicates the button is up. + */ +#define MOUSE_SYS_PACKETSIZE 8 +#define MOUSE_SYS_SYNCMASK 0xf8 +#define MOUSE_SYS_SYNC 0x80 +#define MOUSE_SYS_BUTTON1UP 0x04 /* left, 1st byte */ +#define MOUSE_SYS_BUTTON2UP 0x02 /* middle, 1st byte */ +#define MOUSE_SYS_BUTTON3UP 0x01 /* right, 1st byte */ +#define MOUSE_SYS_BUTTON4UP 0x0001 /* 7th byte */ +#define MOUSE_SYS_BUTTON5UP 0x0002 +#define MOUSE_SYS_BUTTON6UP 0x0004 +#define MOUSE_SYS_BUTTON7UP 0x0008 +#define MOUSE_SYS_BUTTON8UP 0x0010 +#define MOUSE_SYS_BUTTON9UP 0x0020 +#define MOUSE_SYS_BUTTON10UP 0x0040 +#define MOUSE_SYS_MAXBUTTON 10 +#define MOUSE_SYS_STDBUTTONS 0x07 +#define MOUSE_SYS_EXTBUTTONS 0x7f /* the others */ #endif /* _MACHINE_MOUSE_H_ */ diff --git a/sys/dev/mse/mse.c b/sys/dev/mse/mse.c index 8403d45..01b285b 100644 --- a/sys/dev/mse/mse.c +++ b/sys/dev/mse/mse.c @@ -11,7 +11,7 @@ * this software for any purpose. It is provided "as is" * without express or implied warranty. * - * $Id: mse.c,v 1.34 1997/09/14 03:19:10 peter Exp $ + * $Id: mse.c,v 1.35 1997/11/18 11:30:10 bde Exp $ */ /* * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and @@ -58,9 +58,14 @@ #endif /*DEVFS*/ #include <machine/clock.h> +#include <machine/mouse.h> #include <i386/isa/isa_device.h> +/* driver configuration flags (config) */ +#define MSE_CONFIG_ACCEL 0x00f0 /* acceleration factor */ +#define MSE_CONFIG_FLAGS (MSE_CONFIG_ACCEL) + static int mseprobe(struct isa_device *); static int mseattach(struct isa_device *); @@ -71,12 +76,13 @@ struct isa_driver msedriver = { static d_open_t mseopen; static d_close_t mseclose; static d_read_t mseread; +static d_ioctl_t mseioctl; static d_poll_t msepoll; #define CDEV_MAJOR 27 static struct cdevsw mse_cdevsw = { mseopen, mseclose, mseread, nowrite, /*27*/ - noioc, nostop, nullreset, nodevtotty,/* mse */ + mseioctl, nostop, nullreset, nodevtotty,/* mse */ msepoll, nommap, NULL, "mse", NULL, -1 }; @@ -84,7 +90,6 @@ static struct cdevsw mse_cdevsw = * Software control structure for mouse. The sc_enablemouse(), * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). */ -#define PROTOBYTES 5 static struct mse_softc { int sc_flags; int sc_mousetype; @@ -98,7 +103,10 @@ static struct mse_softc { int sc_obuttons; int sc_buttons; int sc_bytesread; - u_char sc_bytes[PROTOBYTES]; + u_char sc_bytes[MOUSE_SYS_PACKETSIZE]; + mousehw_t hw; + mousemode_t mode; + mousestatus_t status; #ifdef DEVFS void *devfs_token; void *n_devfs_token; @@ -198,9 +206,19 @@ static struct mse_types { /* Disable interrupts routine */ void (*m_get) __P((u_int port, int *dx, int *dy, int *but)); /* and get mouse status */ + mousehw_t m_hw; /* buttons iftype type model hwid */ + mousemode_t m_mode; /* proto rate res accel level size mask */ } mse_types[] = { - { MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati }, - { MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi }, + { MSE_ATIINPORT, + mse_probeati, mse_enableati, mse_disableati, mse_getati, + { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, + { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, + { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, + { MSE_LOGITECH, + mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi, + { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, + { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, + { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, { 0, }, }; @@ -221,6 +239,8 @@ mseprobe(idp) sc->sc_enablemouse = mse_types[i].m_enable; sc->sc_disablemouse = mse_types[i].m_disable; sc->sc_getmouse = mse_types[i].m_get; + sc->hw = mse_types[i].m_hw; + sc->mode = mse_types[i].m_mode; return (1); } i++; @@ -236,6 +256,7 @@ mseattach(idp) struct mse_softc *sc = &mse_sc[unit]; sc->sc_port = idp->id_iobase; + sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4; #ifdef DEVFS sc->devfs_token = devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0, @@ -268,9 +289,13 @@ mseopen(dev, flags, fmt, p) if (sc->sc_flags & MSESC_OPEN) return (EBUSY); sc->sc_flags |= MSESC_OPEN; - sc->sc_obuttons = sc->sc_buttons = 0x7; + sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS; sc->sc_deltax = sc->sc_deltay = 0; - sc->sc_bytesread = PROTOBYTES; + sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; + sc->mode.level = 0; + sc->status.flags = 0; + sc->status.button = sc->status.obutton = 0; + sc->status.dx = sc->status.dy = sc->status.dz = 0; /* * Initialize mouse interface and enable interrupts. @@ -320,7 +345,7 @@ mseread(dev, uio, ioflag) * packet. */ s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ - if (sc->sc_bytesread >= PROTOBYTES) { + if (sc->sc_bytesread >= sc->mode.packetsize) { while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && (sc->sc_obuttons ^ sc->sc_buttons) == 0) { if (MSE_NBLOCKIO(dev)) { @@ -340,7 +365,8 @@ mseread(dev, uio, ioflag) * For some reason X386 expects 5 bytes but never uses * the fourth or fifth? */ - sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8); + sc->sc_bytes[0] = sc->mode.syncmask[1] + | (sc->sc_buttons & ~sc->mode.syncmask[0]); if (sc->sc_deltax > 127) sc->sc_deltax = 127; if (sc->sc_deltax < -127) @@ -353,12 +379,14 @@ mseread(dev, uio, ioflag) sc->sc_bytes[1] = sc->sc_deltax; sc->sc_bytes[2] = sc->sc_deltay; sc->sc_bytes[3] = sc->sc_bytes[4] = 0; + sc->sc_bytes[5] = sc->sc_bytes[6] = 0; + sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS; sc->sc_obuttons = sc->sc_buttons; sc->sc_deltax = sc->sc_deltay = 0; sc->sc_bytesread = 0; } splx(s); - xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread); + xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread); if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) return (error); sc->sc_bytesread += xfer; @@ -366,6 +394,123 @@ mseread(dev, uio, ioflag) } /* + * mseioctl: process ioctl commands. + */ +static int +mseioctl(dev, cmd, addr, flag, p) + dev_t dev; + int cmd; + caddr_t addr; + int flag; + struct proc *p; +{ + register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; + mousestatus_t status; + int err = 0; + int s; + + switch (cmd) { + + case MOUSE_GETHWINFO: + s = spltty(); + *(mousehw_t *)addr = sc->hw; + if (sc->mode.level == 0) + ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC; + splx(s); + break; + + case MOUSE_GETMODE: + s = spltty(); + *(mousemode_t *)addr = sc->mode; + switch (sc->mode.level) { + case 0: + break; + case 1: + ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE; + ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK; + ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC; + break; + } + splx(s); + break; + + case MOUSE_SETMODE: + switch (((mousemode_t *)addr)->level) { + case 0: + case 1: + break; + default: + return (EINVAL); + } + if (((mousemode_t *)addr)->accelfactor < -1) + return (EINVAL); + else if (((mousemode_t *)addr)->accelfactor >= 0) + sc->mode.accelfactor = + ((mousemode_t *)addr)->accelfactor; + sc->mode.level = ((mousemode_t *)addr)->level; + switch (sc->mode.level) { + case 0: + sc->sc_bytesread = sc->mode.packetsize + = MOUSE_MSC_PACKETSIZE; + break; + case 1: + sc->sc_bytesread = sc->mode.packetsize + = MOUSE_SYS_PACKETSIZE; + break; + } + break; + + case MOUSE_GETLEVEL: + *(int *)addr = sc->mode.level; + break; + + case MOUSE_SETLEVEL: + switch (*(int *)addr) { + case 0: + sc->mode.level = *(int *)addr; + sc->sc_bytesread = sc->mode.packetsize + = MOUSE_MSC_PACKETSIZE; + break; + case 1: + sc->mode.level = *(int *)addr; + sc->sc_bytesread = sc->mode.packetsize + = MOUSE_SYS_PACKETSIZE; + break; + default: + return (EINVAL); + } + break; + + case MOUSE_GETSTATUS: + s = spltty(); + status = sc->status; + sc->status.flags = 0; + sc->status.obutton = sc->status.button; + sc->status.button = 0; + sc->status.dx = 0; + sc->status.dy = 0; + sc->status.dz = 0; + splx(s); + *(mousestatus_t *)addr = status; + break; + + case MOUSE_READSTATE: + case MOUSE_READDATA: + return (ENODEV); + +#if (defined(MOUSE_GETVARS)) + case MOUSE_GETVARS: + case MOUSE_SETVARS: + return (ENODEV); +#endif + + default: + return (ENOTTY); + } + return (err); +} + +/* * msepoll: check for mouse input to be processed. */ static int @@ -380,8 +525,8 @@ msepoll(dev, events, p) s = spltty(); if (events & (POLLIN | POLLRDNORM)) - if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 || - sc->sc_deltay != 0 || + if (sc->sc_bytesread != sc->mode.packetsize || + sc->sc_deltax != 0 || sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) revents |= events & (POLLIN | POLLRDNORM); else { @@ -403,7 +548,23 @@ void mseintr(unit) int unit; { + /* + * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP) + * into `mousestatus' button bits (MOUSE_BUTTON?DOWN). + */ + static int butmap[8] = { + 0, + MOUSE_BUTTON3DOWN, + MOUSE_BUTTON2DOWN, + MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, + MOUSE_BUTTON1DOWN, + MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, + MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, + MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN + }; register struct mse_softc *sc = &mse_sc[unit]; + int dx, dy, but; + int sign; #ifdef DEBUG static int mse_intrcnt = 0; @@ -413,7 +574,31 @@ mseintr(unit) if ((sc->sc_flags & MSESC_OPEN) == 0) return; - (*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons); + (*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but); + if (sc->mode.accelfactor > 0) { + sign = (dx < 0); + dx = dx * dx / sc->mode.accelfactor; + if (dx == 0) + dx = 1; + if (sign) + dx = -dx; + sign = (dy < 0); + dy = dy * dy / sc->mode.accelfactor; + if (dy == 0) + dy = 1; + if (sign) + dy = -dy; + } + sc->sc_deltax += dx; + sc->sc_deltay += dy; + sc->sc_buttons = but; + + but = butmap[~but & MOUSE_MSC_BUTTONS]; + sc->status.dx += dx; + sc->status.dy += dy; + sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0) + | (sc->status.button ^ but); + sc->status.button = but; /* * If mouse state has changed, wake up anyone wanting to know. @@ -497,7 +682,7 @@ mse_getlogi(port, dx, dy, but) outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); x = inb(port + MSE_PORTA); - *but = (x >> 5) & 0x7; + *but = (x >> 5) & MOUSE_MSC_BUTTONS; x &= 0xf; outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); x |= (inb(port + MSE_PORTA) << 4); @@ -505,8 +690,8 @@ mse_getlogi(port, dx, dy, but) y = (inb(port + MSE_PORTA) & 0xf); outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); y |= (inb(port + MSE_PORTA) << 4); - *dx += x; - *dy += y; + *dx = x; + *dy = y; outb(port + MSE_PORTC, MSE_INTREN); } @@ -569,13 +754,13 @@ mse_getati(port, dx, dy, but) outb(port + MSE_PORTA, MSE_INPORT_MODE); outb(port + MSE_PORTB, MSE_INPORT_HOLD); outb(port + MSE_PORTA, MSE_INPORT_STATUS); - *but = ~(inb(port + MSE_PORTB) & 0x7); + *but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS; outb(port + MSE_PORTA, MSE_INPORT_DX); byte = inb(port + MSE_PORTB); - *dx += byte; + *dx = byte; outb(port + MSE_PORTA, MSE_INPORT_DY); byte = inb(port + MSE_PORTB); - *dy += byte; + *dy = byte; outb(port + MSE_PORTA, MSE_INPORT_MODE); outb(port + MSE_PORTB, MSE_INPORT_INTREN); } diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 9e6353c..56feb74 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.240 1997/11/25 12:44:44 sos Exp $ + * $Id: syscons.c,v 1.241 1997/12/06 13:23:26 bde Exp $ */ #include "sc.h" @@ -49,6 +49,7 @@ #include <machine/clock.h> #include <machine/cons.h> #include <machine/console.h> +#include <machine/mouse.h> #include <machine/md_var.h> #include <machine/psl.h> #include <machine/frame.h> @@ -153,6 +154,8 @@ static char vgaregs[MODE_PARAM_SIZE]; static char vgaregs2[MODE_PARAM_SIZE]; static int rows_offset = 1; static char *cut_buffer; +static int mouse_level = 0; /* sysmouse protocol level */ +static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; static u_short mouse_and_mask[16] = { 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, @@ -249,8 +252,14 @@ static void set_font_mode(u_char *buf); static void set_normal_mode(u_char *buf); static void set_destructive_cursor(scr_stat *scp); static void set_mouse_pos(scr_stat *scp); +static int skip_spc_right(scr_stat *scp, u_short *p); +static int skip_spc_left(scr_stat *scp, u_short *p); +static void mouse_cut(scr_stat *scp); static void mouse_cut_start(scr_stat *scp); static void mouse_cut_end(scr_stat *scp); +static void mouse_cut_word(scr_stat *scp); +static void mouse_cut_line(scr_stat *scp); +static void mouse_cut_extend(scr_stat *scp); static void mouse_paste(scr_stat *scp); static void draw_mouse_image(scr_stat *scp); static void remove_mouse_image(scr_stat *scp); @@ -785,6 +794,8 @@ scopen(dev_t dev, int flag, int mode, struct proc *p) scparam(tp, &tp->t_termios); ttsetwater(tp); (*linesw[tp->t_line].l_modem)(tp, 1); + if (minor(dev) == SC_MOUSE) + mouse_level = 0; /* XXX */ } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) @@ -925,11 +936,12 @@ int scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) { int error; - u_int i = 0; + u_int i; struct tty *tp; scr_stat *scp; u_short *usp; char *mp; + int s; tp = scdevtotty(dev); if (!tp) @@ -1047,10 +1059,22 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) case CONS_MOUSECTL: /* control mouse arrow */ { + /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ + static butmap[8] = { + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP + | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON1UP, + 0, + }; mouse_info_t *mouse = (mouse_info_t*)data; if (!crtc_vga) - return ENXIO; + return ENODEV; switch (mouse->operation) { case MOUSE_MODE: @@ -1100,26 +1124,55 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) case MOUSE_GETINFO: mouse->u.data.x = scp->mouse_xpos; mouse->u.data.y = scp->mouse_ypos; + mouse->u.data.z = 0; mouse->u.data.buttons = scp->mouse_buttons; break; case MOUSE_ACTION: + case MOUSE_MOTION_EVENT: /* this should maybe only be settable from /dev/consolectl SOS */ /* send out mouse event on /dev/sysmouse */ + + mouse_status.dx += mouse->u.data.x; + mouse_status.dy += mouse->u.data.y; + mouse_status.dz += mouse->u.data.z; + if (mouse->operation == MOUSE_ACTION) + mouse_status.button = mouse->u.data.buttons; + mouse_status.flags |= + ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? + MOUSE_POSCHANGED : 0) + | (mouse_status.obutton ^ mouse_status.button); + if (cur_console->status & MOUSE_ENABLED) cur_console->status |= MOUSE_VISIBLE; + if ((MOUSE_TTY)->t_state & TS_ISOPEN) { - u_char buf[5]; + u_char buf[MOUSE_SYS_PACKETSIZE]; int j; - buf[0] = 0x80 | ((~mouse->u.data.buttons) & 0x07); - buf[1] = (mouse->u.data.x & 0x1fe >> 1); - buf[3] = (mouse->u.data.x & 0x1ff) - buf[1]; - buf[2] = -(mouse->u.data.y & 0x1fe >> 1); - buf[4] = -(mouse->u.data.y & 0x1ff) - buf[2]; - for (j=0; j<5; j++) + /* the first five bytes are compatible with MouseSystems' */ + buf[0] = MOUSE_MSC_SYNC + | butmap[mouse_status.button & MOUSE_STDBUTTONS]; + j = imax(imin(mouse->u.data.x, 255), -256); + buf[1] = j >> 1; + buf[3] = j - buf[1]; + j = -imax(imin(mouse->u.data.y, 255), -256); + buf[2] = j >> 1; + buf[4] = j - buf[2]; + for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++) + (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); + if (mouse_level >= 1) { /* extended part */ + j = imax(imin(mouse->u.data.z, 127), -128); + buf[5] = (j >> 1) & 0x7f; + buf[6] = (j - (j >> 1)) & 0x7f; + /* buttons 4-10 */ + buf[7] = (~mouse_status.button >> 3) & 0x7f; + for (j = MOUSE_MSC_PACKETSIZE; + j < MOUSE_SYS_PACKETSIZE; j++) (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); + } } + if (cur_console->mouse_signal) { cur_console->mouse_buttons = mouse->u.data.buttons; /* has controlling process died? */ @@ -1132,26 +1185,117 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) else psignal(cur_console->mouse_proc, cur_console->mouse_signal); } - else { + else if (mouse->operation == MOUSE_ACTION) { /* process button presses */ - if (cur_console->mouse_buttons != mouse->u.data.buttons) { + if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && + !(cur_console->status & UNKNOWN_MODE)) { cur_console->mouse_buttons = mouse->u.data.buttons; - if (!(cur_console->status & UNKNOWN_MODE)) { - if (cur_console->mouse_buttons & LEFT_BUTTON) - mouse_cut_start(cur_console); - else - mouse_cut_end(cur_console); - if (cur_console->mouse_buttons & RIGHT_BUTTON || - cur_console->mouse_buttons & MIDDLE_BUTTON) - mouse_paste(cur_console); - } + if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) + mouse_cut_start(cur_console); + else + mouse_cut_end(cur_console); + if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN || + cur_console->mouse_buttons & MOUSE_BUTTON3DOWN) + mouse_paste(cur_console); } } + if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { - cur_console->mouse_xpos += mouse->u.data.x; - cur_console->mouse_ypos += mouse->u.data.y; + cur_console->mouse_xpos += mouse->u.data.x; + cur_console->mouse_ypos += mouse->u.data.y; set_mouse_pos(cur_console); } + + break; + + case MOUSE_BUTTON_EVENT: + if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) + return EINVAL; + if (mouse->u.event.value < 0) + return EINVAL; + + if (mouse->u.event.value > 0) { + cur_console->mouse_buttons |= mouse->u.event.id; + mouse_status.button |= mouse->u.event.id; + } else { + cur_console->mouse_buttons &= ~mouse->u.event.id; + mouse_status.button &= ~mouse->u.event.id; + } + mouse_status.flags |= + ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? + MOUSE_POSCHANGED : 0) + | (mouse_status.obutton ^ mouse_status.button); + + if (cur_console->status & MOUSE_ENABLED) + cur_console->status |= MOUSE_VISIBLE; + + if ((MOUSE_TTY)->t_state & TS_ISOPEN) { + u_char buf[8]; + int i; + + buf[0] = MOUSE_MSC_SYNC + | butmap[mouse_status.button & MOUSE_STDBUTTONS]; + buf[7] = (~mouse_status.button >> 3) & 0x7f; + buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; + for (i = 0; + i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE + : MOUSE_MSC_PACKETSIZE); i++) + (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); + } + + if (cur_console->mouse_signal) { + if (cur_console->mouse_proc && + (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ + cur_console->mouse_signal = 0; + cur_console->mouse_proc = NULL; + cur_console->mouse_pid = 0; + } + else + psignal(cur_console->mouse_proc, cur_console->mouse_signal); + break; + } + + if (cur_console->status & UNKNOWN_MODE) + break; + + switch (mouse->u.event.id) { + case MOUSE_BUTTON1DOWN: + switch (mouse->u.event.value % 4) { + case 0: /* up */ + mouse_cut_end(cur_console); + break; + case 1: + mouse_cut_start(cur_console); + break; + case 2: + mouse_cut_word(cur_console); + break; + case 3: + mouse_cut_line(cur_console); + break; + } + break; + case MOUSE_BUTTON2DOWN: + switch (mouse->u.event.value) { + case 0: /* up */ + break; + default: + mouse_paste(cur_console); + break; + } + break; + case MOUSE_BUTTON3DOWN: + switch (mouse->u.event.value) { + case 0: /* up */ + if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)) + mouse_cut_end(cur_console); + break; + default: + mouse_cut_extend(cur_console); + break; + } + break; + } break; default: @@ -1162,6 +1306,107 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) return 0; } + /* MOUSE_XXX: /dev/sysmouse ioctls */ + case MOUSE_GETHWINFO: /* get device information */ + { + mousehw_t *hw = (mousehw_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + hw->buttons = 10; /* XXX unknown */ + hw->iftype = MOUSE_IF_SYSMOUSE; + hw->type = MOUSE_MOUSE; + hw->model = MOUSE_MODEL_GENERIC; + hw->hwid = 0; + return 0; + } + + case MOUSE_GETMODE: /* get protocol/mode */ + { + mousemode_t *mode = (mousemode_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + mode->level = mouse_level; + switch (mode->level) { + case 0: + /* at this level, sysmouse emulates MouseSystems protocol */ + mode->protocol = MOUSE_PROTO_MSC; + mode->rate = -1; /* unknown */ + mode->resolution = -1; /* unknown */ + mode->accelfactor = 0; /* disabled */ + mode->packetsize = MOUSE_MSC_PACKETSIZE; + mode->syncmask[0] = MOUSE_MSC_SYNCMASK; + mode->syncmask[1] = MOUSE_MSC_SYNC; + break; + + case 1: + /* at this level, sysmouse uses its own protocol */ + mode->protocol = MOUSE_PROTO_SYSMOUSE; + mode->rate = -1; + mode->resolution = -1; + mode->accelfactor = 0; + mode->packetsize = MOUSE_SYS_PACKETSIZE; + mode->syncmask[0] = MOUSE_SYS_SYNCMASK; + mode->syncmask[1] = MOUSE_SYS_SYNC; + break; + } + return 0; + } + + case MOUSE_SETMODE: /* set protocol/mode */ + { + mousemode_t *mode = (mousemode_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + if ((mode->level < 0) || (mode->level > 1)) + return EINVAL; + mouse_level = mode->level; + return 0; + } + + case MOUSE_GETLEVEL: /* get operation level */ + if (tp != MOUSE_TTY) + return ENOTTY; + *(int *)data = mouse_level; + return 0; + + case MOUSE_SETLEVEL: /* set operation level */ + if (tp != MOUSE_TTY) + return ENOTTY; + if ((*(int *)data < 0) || (*(int *)data > 1)) + return EINVAL; + mouse_level = *(int *)data; + return 0; + + case MOUSE_GETSTATUS: /* get accumulated mouse events */ + if (tp != MOUSE_TTY) + return ENOTTY; + s = spltty(); + *(mousestatus_t *)data = mouse_status; + mouse_status.flags = 0; + mouse_status.obutton = mouse_status.button; + mouse_status.dx = 0; + mouse_status.dy = 0; + mouse_status.dz = 0; + splx(s); + return 0; + +#if notyet + case MOUSE_GETVARS: /* get internal mouse variables */ + case MOUSE_SETVARS: /* set internal mouse variables */ + if (tp != MOUSE_TTY) + return ENOTTY; + return ENODEV; +#endif + + case MOUSE_READSTATE: /* read status from the device */ + case MOUSE_READDATA: /* read data from the device */ + if (tp != MOUSE_TTY) + return ENOTTY; + return ENODEV; + case CONS_GETINFO: /* get current (virtual) console info */ { vid_info_t *ptr = (vid_info_t*)data; @@ -1210,6 +1455,8 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) if (scp->history != NULL) i = imax(scp->history_size / scp->xsize - imax(SC_HISTORY_SIZE, scp->ysize), 0); + else + i = 0; switch (cmd & 0xff) { case M_VGA_C80x60: case M_VGA_M80x60: if (!(fonts_loaded & FONT_8)) @@ -4106,28 +4353,86 @@ set_mouse_pos(scr_stat *scp) scp->mouse_pos = scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); - if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) { - u_short *ptr; - int i = 0; - - mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); - mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); - scp->mouse_cut_end = scp->mouse_pos; - for (ptr = (scp->mouse_cut_start > scp->mouse_cut_end - ? scp->mouse_cut_end : scp->mouse_cut_start); - ptr <= (scp->mouse_cut_start > scp->mouse_cut_end - ? scp->mouse_cut_start : scp->mouse_cut_end); - ptr++) { - cut_buffer[i++] = *ptr & 0xff; - if (((ptr - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { - cut_buffer[i++] = '\n'; - } - } - cut_buffer[i] = 0x00; - } + if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) + mouse_cut(scp); } } +#define isspace(c) (((c) & 0xff) == ' ') + +static int +skip_spc_right(scr_stat *scp, u_short *p) +{ + int i; + + for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { + if (!isspace(*p)) + break; + ++p; + } + return i; +} + +static int +skip_spc_left(scr_stat *scp, u_short *p) +{ + int i; + + for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { + if (!isspace(*p)) + break; + --p; + } + return i; +} + +static void +mouse_cut(scr_stat *scp) +{ + u_short *end; + u_short *p; + int i = 0; + int j = 0; + + scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? + scp->mouse_pos + 1 : scp->mouse_pos; + end = (scp->mouse_cut_start > scp->mouse_cut_end) ? + scp->mouse_cut_start : scp->mouse_cut_end; + for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? + scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { + cut_buffer[i] = *p & 0xff; + /* remember the position of the last non-space char */ + if (!isspace(cut_buffer[i++])) + j = i; + /* trim trailing blank when crossing lines */ + if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { + cut_buffer[j++] = '\n'; + i = j; + } + } + cut_buffer[i] = '\0'; + + /* scan towards the end of the last line */ + --p; + for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { + if (!isspace(*p)) + break; + ++p; + } + /* if there is nothing but blank chars, trim them, but mark towards eol */ + if (i >= scp->xsize) { + if (scp->mouse_cut_start > scp->mouse_cut_end) + scp->mouse_cut_start = p; + else + scp->mouse_cut_end = p; + cut_buffer[j++] = '\n'; + cut_buffer[j] = '\0'; + } + + mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); + mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); +} + static void mouse_cut_start(scr_stat *scp) { @@ -4135,14 +4440,24 @@ mouse_cut_start(scr_stat *scp) if (scp->status & MOUSE_VISIBLE) { if (scp->mouse_pos == scp->mouse_cut_start && - scp->mouse_cut_start == scp->mouse_cut_end) { - cut_buffer[0] = 0x00; + scp->mouse_cut_start == scp->mouse_cut_end - 1) { + cut_buffer[0] = '\0'; remove_cutmarking(scp); - } - else { - scp->mouse_cut_start = scp->mouse_cut_end = scp->mouse_pos; + } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { + /* if the pointer is on trailing blank chars, mark towards eol */ + i = skip_spc_left(scp, scp->mouse_pos) + 1; + scp->mouse_cut_start = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; + scp->mouse_cut_end = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; + cut_buffer[0] = '\n'; + cut_buffer[1] = '\0'; + scp->status |= MOUSE_CUTTING; + } else { + scp->mouse_cut_start = scp->mouse_pos; + scp->mouse_cut_end = scp->mouse_cut_start + 1; cut_buffer[0] = *scp->mouse_cut_start & 0xff; - cut_buffer[1] = 0x00; + cut_buffer[1] = '\0'; scp->status |= MOUSE_CUTTING; } mark_all(scp); @@ -4164,6 +4479,77 @@ mouse_cut_end(scr_stat *scp) } static void +mouse_cut_word(scr_stat *scp) +{ + u_short *p; + u_short *sol; + u_short *eol; + int i; + + /* + * Because we don't have locale information in the kernel, + * we only distinguish space char and non-space chars. Punctuation + * chars, symbols and other regular chars are all treated alike. + */ + if (scp->status & MOUSE_VISIBLE) { + sol = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; + eol = sol + scp->xsize; + if (isspace(*scp->mouse_pos)) { + for (p = scp->mouse_pos; p >= sol; --p) + if (!isspace(*p)) + break; + scp->mouse_cut_start = ++p; + for (p = scp->mouse_pos; p < eol; ++p) + if (!isspace(*p)) + break; + scp->mouse_cut_end = p; + } else { + for (p = scp->mouse_pos; p >= sol; --p) + if (isspace(*p)) + break; + scp->mouse_cut_start = ++p; + for (p = scp->mouse_pos; p < eol; ++p) + if (isspace(*p)) + break; + scp->mouse_cut_end = p; + } + for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) + cut_buffer[i++] = *p & 0xff; + cut_buffer[i] = '\0'; + scp->status |= MOUSE_CUTTING; + } +} + +static void +mouse_cut_line(scr_stat *scp) +{ + u_short *p; + int i; + + if (scp->status & MOUSE_VISIBLE) { + scp->mouse_cut_start = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; + scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; + for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) + cut_buffer[i++] = *p & 0xff; + cut_buffer[i++] = '\n'; + cut_buffer[i] = '\0'; + scp->status |= MOUSE_CUTTING; + } +} + +static void +mouse_cut_extend(scr_stat *scp) +{ + if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) + && (scp->mouse_cut_start != NULL)) { + mouse_cut(scp); + scp->status |= MOUSE_CUTTING; + } +} + +static void mouse_paste(scr_stat *scp) { if (scp->status & MOUSE_VISIBLE) { @@ -4273,7 +4659,7 @@ draw_cutmarking(scr_stat *scp) /* are we outside the selected area ? */ if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? scp->mouse_cut_end : scp->mouse_cut_start) || - ptr > (scp->mouse_cut_start > scp->mouse_cut_end ? + ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? scp->mouse_cut_start : scp->mouse_cut_end)) { if (ptr != scp->cursor_pos) nch = (och & 0xff) | (*ptr & 0xff00); diff --git a/sys/i386/include/console.h b/sys/i386/include/console.h index cbeb2c4..539a61d 100644 --- a/sys/i386/include/console.h +++ b/sys/i386/include/console.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: console.h,v 1.31 1997/09/04 09:05:17 kato Exp $ + * $Id: console.h,v 1.32 1997/10/01 20:46:25 sos Exp $ */ #ifndef _MACHINE_CONSOLE_H_ @@ -108,13 +108,10 @@ struct vt_mode { short frsig; /* not implemented yet SOS */ }; -#define RIGHT_BUTTON 0x01 -#define MIDDLE_BUTTON 0x02 -#define LEFT_BUTTON 0x04 - struct mouse_data { int x; int y; + int z; int buttons; }; @@ -123,6 +120,11 @@ struct mouse_mode { int signal; }; +struct mouse_event { + int id; /* one based */ + int value; +}; + #define MOUSE_SHOW 0x01 #define MOUSE_HIDE 0x02 #define MOUSE_MOVEABS 0x03 @@ -130,12 +132,15 @@ struct mouse_mode { #define MOUSE_GETINFO 0x05 #define MOUSE_MODE 0x06 #define MOUSE_ACTION 0x07 +#define MOUSE_MOTION_EVENT 0x08 +#define MOUSE_BUTTON_EVENT 0x09 struct mouse_info { int operation; union { struct mouse_data data; struct mouse_mode mode; + struct mouse_event event; }u; }; diff --git a/sys/i386/include/mouse.h b/sys/i386/include/mouse.h index 86f4528..d0eecef 100644 --- a/sys/i386/include/mouse.h +++ b/sys/i386/include/mouse.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 1992, 1993 Erik Forsberg. + * Copyright (c) 1996, 1997 Kazutaka YOKOTA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -19,7 +20,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: mouse.h,v 1.7 1997/02/22 09:34:50 peter Exp $ + * $Id: mouse.h,v 1.8 1997/10/19 10:44:02 yokota Exp $ */ #ifndef _MACHINE_MOUSE_H_ @@ -28,45 +29,33 @@ #include <sys/types.h> #include <sys/ioccom.h> -/* - * NOTE: MOUSEIOC, MOUSEIOCREAD, and mouseinfo are now obsolete, - * but will stay for compatibility reasons. But, remember, - * the MOUSEIOCREAD ioctl command doesn't work and never worked before. - * Some day we shall get rid of these... - */ +/* ioctls */ +#define MOUSE_GETSTATUS _IOR('M', 0, mousestatus_t) +#define MOUSE_GETHWINFO _IOR('M', 1, mousehw_t) +#define MOUSE_GETMODE _IOR('M', 2, mousemode_t) +#define MOUSE_SETMODE _IOW('M', 3, mousemode_t) +#define MOUSE_GETLEVEL _IOR('M', 4, int) +#define MOUSE_SETLEVEL _IOW('M', 5, int) +#define MOUSE_GETVARS _IOR('M', 6, mousevar_t) +#define MOUSE_SETVARS _IOW('M', 7, mousevar_t) +#define MOUSE_READSTATE _IOWR('M', 8, mousedata_t) +#define MOUSE_READDATA _IOWR('M', 9, mousedata_t) -#define MOUSEIOC ('M'<<8) -#define MOUSEIOCREAD (MOUSEIOC|60) - -typedef struct mouseinfo { - unsigned char status; - char xmotion; - char ymotion; -} mouseinfo_t; -/* status */ -#define BUTSTATMASK 0x07 /* Any mouse button down if any bit set */ -#define BUTCHNGMASK 0x38 /* Any mouse button changed if any bit set */ -#define BUT3STAT 0x01 /* Button 3 down if set */ -#define BUT2STAT 0x02 /* Button 2 down if set */ -#define BUT1STAT 0x04 /* Button 1 down if set */ -#define BUT3CHNG 0x08 /* Button 3 changed if set */ -#define BUT2CHNG 0x10 /* Button 2 changed if set */ -#define BUT1CHNG 0x20 /* Button 1 changed if set */ -#define MOVEMENT 0x40 /* Mouse movement detected */ - -#define MOUSE_GETSTATE _IOR('M',0,mousestatus_t) -#define MOUSE_GETHWINFO _IOR('M',1,mousehw_t) -#define MOUSE_GETMODE _IOR('M',2,mousemode_t) -#define MOUSE_SETMODE _IOW('M',3,mousemode_t) - -/* new ioctls */ +#if notyet +#define MOUSE_SETRESOLUTION _IOW('M', 10, int) +#define MOUSE_SETSCALING _IOW('M', 11, int) +#define MOUSE_SETRATE _IOW('M', 12, int) +#define MOUSE_GETHWID _IOR('M', 13, int) +#endif /* mouse status block */ typedef struct mousestatus { + int flags; /* state change flags */ int button; /* button status */ int obutton; /* previous button status */ int dx; /* x movement */ int dy; /* y movement */ + int dz; /* z movement */ } mousestatus_t; /* button */ @@ -78,23 +67,34 @@ typedef struct mousestatus { #define MOUSE_BUTTON6DOWN 0x0020 #define MOUSE_BUTTON7DOWN 0x0040 #define MOUSE_BUTTON8DOWN 0x0080 -#define MOUSE_STDBUTTONS 0x0007 /* buttons 1-3 */ -#define MOUSE_EXTBUTTONS 0x00f8 /* the others */ +#define MOUSE_MAXBUTTON 31 +#define MOUSE_STDBUTTONS 0x0007 /* buttons 1-3 */ +#define MOUSE_EXTBUTTONS 0x7ffffff8 /* the others (28 of them!) */ +#define MOUSE_BUTTONS (MOUSE_STDBUTTONS | MOUSE_EXTBUTTONS) + +/* flags */ +#define MOUSE_STDBUTTONSCHANGED MOUSE_STDBUTTONS +#define MOUSE_EXTBUTTONSCHANGED MOUSE_EXTBUTTONS +#define MOUSE_BUTTONSCHANGED MOUSE_BUTTONS +#define MOUSE_POSCHANGED 0x80000000 typedef struct mousehw { - int buttons; + int buttons; /* -1 if unknown */ int iftype; /* MOUSE_IF_XXX */ int type; /* mouse/track ball/pad... */ + int model; /* I/F dependent model ID: MOUSE_MODEL_XXX */ int hwid; /* I/F dependent hardware ID * for the PS/2 mouse, it will be PSM_XXX_ID */ } mousehw_t; /* iftype */ +#define MOUSE_IF_UNKNOWN (-1) #define MOUSE_IF_SERIAL 0 #define MOUSE_IF_BUS 1 #define MOUSE_IF_INPORT 2 #define MOUSE_IF_PS2 3 +#define MOUSE_IF_SYSMOUSE 4 /* type */ #define MOUSE_UNKNOWN (-1) /* should be treated as a mouse */ @@ -103,24 +103,67 @@ typedef struct mousehw { #define MOUSE_STICK 2 #define MOUSE_PAD 3 +/* model */ +#define MOUSE_MODEL_UNKNOWN (-1) +#define MOUSE_MODEL_GENERIC 0 +#define MOUSE_MODEL_GLIDEPOINT 1 +#define MOUSE_MODEL_NETSCROLL 2 +#define MOUSE_MODEL_NET 3 +#define MOUSE_MODEL_INTELLI 4 +#define MOUSE_MODEL_THINK 5 +#define MOUSE_MODEL_EASYSCROLL 6 +#define MOUSE_MODEL_MOUSEMANPLUS 7 + typedef struct mousemode { int protocol; /* MOUSE_PROTO_XXX */ int rate; /* report rate (per sec), -1 if unknown */ - int resolution; /* 1:low, 2:medium low, 3:medium high - * 4:high, 0: default, -1 if unknown - */ + int resolution; /* MOUSE_RES_XXX, -1 if unknown */ int accelfactor; /* accelation factor (must be 1 or greater) */ + int level; /* driver operation level */ + int packetsize; /* the length of the data packet */ + unsigned char syncmask[2]; /* sync. data bits in the header byte */ } mousemode_t; /* protocol */ +#define MOUSE_PROTO_UNKNOWN (-1) #define MOUSE_PROTO_MS 0 /* Microsoft Serial, 3 bytes */ #define MOUSE_PROTO_MSC 1 /* Mouse Systems, 5 bytes */ #define MOUSE_PROTO_LOGI 2 /* Logitech, 3 bytes */ #define MOUSE_PROTO_MM 3 /* MM series, 3 bytes */ #define MOUSE_PROTO_LOGIMOUSEMAN 4 /* Logitech MouseMan 3/4 bytes */ #define MOUSE_PROTO_BUS 5 /* MS/Logitech bus mouse */ -#define MOUSE_PROTO_INPORT 6 /* MS/ATI inport mouse */ +#define MOUSE_PROTO_INPORT 6 /* MS/ATI InPort mouse */ #define MOUSE_PROTO_PS2 7 /* PS/2 mouse, 3 bytes */ +#define MOUSE_PROTO_HITTAB 8 /* Hitachi Tablet 3 bytes */ +#define MOUSE_PROTO_GLIDEPOINT 9 /* ALPS GlidePoint, 3/4 bytes */ +#define MOUSE_PROTO_INTELLI 10 /* MS IntelliMouse, 4 bytes */ +#define MOUSE_PROTO_THINK 11 /* Kensignton Thinking Mouse, 3/4 bytes */ +#define MOUSE_PROTO_SYSMOUSE 12 /* /dev/sysmouse */ + +#define MOUSE_RES_UNKNOWN (-1) +#define MOUSE_RES_DEFAULT 0 +#define MOUSE_RES_LOW (-2) +#define MOUSE_RES_MEDIUMLOW (-3) +#define MOUSE_RES_MEDIUMHIGH (-4) +#define MOUSE_RES_HIGH (-5) + +typedef struct mousedata { + int len; /* # of data in the buffer */ + int buf[16]; /* data buffer */ +} mousedata_t; + +#if (defined(MOUSE_GETVARS)) + +typedef struct mousevar { + int var[16]; +} mousevar_t; + +/* magic numbers in var[0] */ +#define MOUSE_VARS_PS2_SIG 0x00325350 /* 'PS2' */ +#define MOUSE_VARS_BUS_SIG 0x00535542 /* 'BUS' */ +#define MOUSE_VARS_INPORT_SIG 0x00504e49 /* 'INP' */ + +#endif /* MOUSE_GETVARS */ /* Microsoft Serial mouse data packet */ #define MOUSE_MSS_PACKETSIZE 3 @@ -132,7 +175,19 @@ typedef struct mousemode { #define MOUSE_MSS_BUTTON3DOWN 0x10 /* right */ /* Logitech MouseMan data packet (M+ protocol) */ -#define MOUSE_LMAN_BUTTON2DOWN 0x20 /* middle button, in the 4th byte */ +#define MOUSE_LMAN_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ + +/* ALPS GlidePoint extention (variant of M+ protocol) */ +#define MOUSE_ALPS_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ +#define MOUSE_ALPS_TAP 0x10 /* `tapping' action, the 4th byte */ + +/* Kinsington Thinking Mouse extention (variant of M+ protocol) */ +#define MOUSE_THINK_BUTTON2DOWN 0x20 /* lower-left button, the 4th byte */ +#define MOUSE_THINK_BUTTON4DOWN 0x10 /* lower-right button, the 4th byte */ + +/* MS IntelliMouse (variant of MS Serial) */ +#define MOUSE_INTELLI_PACKETSIZE 4 +#define MOUSE_INTELLI_BUTTON2DOWN 0x10 /* middle button the 4th byte */ /* Mouse Systems Corp. mouse data packet */ #define MOUSE_MSC_PACKETSIZE 5 @@ -156,18 +211,50 @@ typedef struct mousemode { /* PS/2 mouse data packet */ #define MOUSE_PS2_PACKETSIZE 3 -#define MOUSE_PS2_SYNCMASK 0x08 /* 0x0c for 2 button mouse */ -#define MOUSE_PS2_SYNC 0x08 /* 0x0c for 2 button mouse */ +#define MOUSE_PS2_SYNCMASK 0xc8 +#define MOUSE_PS2_SYNC 0x08 #define MOUSE_PS2_BUTTONS 0x07 /* 0x03 for 2 button mouse */ #define MOUSE_PS2_BUTTON1DOWN 0x01 /* left */ #define MOUSE_PS2_BUTTON2DOWN 0x04 /* middle */ #define MOUSE_PS2_BUTTON3DOWN 0x02 /* right */ -#define MOUSE_PS2_BUTTON4UP 0x08 /* GlidePoint tapping feature - * Yes! this is the same bit as SYNC! - */ +#define MOUSE_PS2_TAP MOUSE_PS2_SYNC /* GlidePoint (PS/2) `tapping' + * Yes! this is the same bit + * as SYNC! + */ +#define MOUSE_PS2PLUS_BUTTON4DOWN 0x10 /* 4th button on MouseMan+ */ + #define MOUSE_PS2_XNEG 0x10 #define MOUSE_PS2_YNEG 0x20 #define MOUSE_PS2_XOVERFLOW 0x40 #define MOUSE_PS2_YOVERFLOW 0x80 +#define MOUSE_PS2PLUS_ZNEG 0x08 /* MouseMan+ negative wheel movement */ + +/* sysmouse extended data packet */ +/* + * /dev/sysmouse sends data in two formats, depending on the protocol + * level. At the level 0, format is exactly the same as MousSystems' + * five byte packet. At the level 1, the first five bytes are the same + * as at the level 0. There are additional three bytes which shows + * `dz' and the states of additional buttons. `dz' is expressed as the + * sum of the byte 5 and 6 which contain signed seven bit values. + * The states of the button 4 though 10 are in the bit 0 though 6 in + * the byte 7 respectively: 1 indicates the button is up. + */ +#define MOUSE_SYS_PACKETSIZE 8 +#define MOUSE_SYS_SYNCMASK 0xf8 +#define MOUSE_SYS_SYNC 0x80 +#define MOUSE_SYS_BUTTON1UP 0x04 /* left, 1st byte */ +#define MOUSE_SYS_BUTTON2UP 0x02 /* middle, 1st byte */ +#define MOUSE_SYS_BUTTON3UP 0x01 /* right, 1st byte */ +#define MOUSE_SYS_BUTTON4UP 0x0001 /* 7th byte */ +#define MOUSE_SYS_BUTTON5UP 0x0002 +#define MOUSE_SYS_BUTTON6UP 0x0004 +#define MOUSE_SYS_BUTTON7UP 0x0008 +#define MOUSE_SYS_BUTTON8UP 0x0010 +#define MOUSE_SYS_BUTTON9UP 0x0020 +#define MOUSE_SYS_BUTTON10UP 0x0040 +#define MOUSE_SYS_MAXBUTTON 10 +#define MOUSE_SYS_STDBUTTONS 0x07 +#define MOUSE_SYS_EXTBUTTONS 0x7f /* the others */ #endif /* _MACHINE_MOUSE_H_ */ diff --git a/sys/i386/isa/kbdio.h b/sys/i386/isa/kbdio.h index a25edc5..b9bbe0a 100644 --- a/sys/i386/isa/kbdio.h +++ b/sys/i386/isa/kbdio.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: kbdio.h,v 1.6 1997/02/22 09:36:47 peter Exp $ */ #ifndef _I386_ISA_KBDIO_H_ @@ -148,6 +148,7 @@ /* aux device ID */ #define PSM_MOUSE_ID 0 #define PSM_BALLPOINT_ID 2 +#define PSM_INTELLI_ID 3 #ifdef KERNEL diff --git a/sys/i386/isa/mse.c b/sys/i386/isa/mse.c index 8403d45..01b285b 100644 --- a/sys/i386/isa/mse.c +++ b/sys/i386/isa/mse.c @@ -11,7 +11,7 @@ * this software for any purpose. It is provided "as is" * without express or implied warranty. * - * $Id: mse.c,v 1.34 1997/09/14 03:19:10 peter Exp $ + * $Id: mse.c,v 1.35 1997/11/18 11:30:10 bde Exp $ */ /* * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and @@ -58,9 +58,14 @@ #endif /*DEVFS*/ #include <machine/clock.h> +#include <machine/mouse.h> #include <i386/isa/isa_device.h> +/* driver configuration flags (config) */ +#define MSE_CONFIG_ACCEL 0x00f0 /* acceleration factor */ +#define MSE_CONFIG_FLAGS (MSE_CONFIG_ACCEL) + static int mseprobe(struct isa_device *); static int mseattach(struct isa_device *); @@ -71,12 +76,13 @@ struct isa_driver msedriver = { static d_open_t mseopen; static d_close_t mseclose; static d_read_t mseread; +static d_ioctl_t mseioctl; static d_poll_t msepoll; #define CDEV_MAJOR 27 static struct cdevsw mse_cdevsw = { mseopen, mseclose, mseread, nowrite, /*27*/ - noioc, nostop, nullreset, nodevtotty,/* mse */ + mseioctl, nostop, nullreset, nodevtotty,/* mse */ msepoll, nommap, NULL, "mse", NULL, -1 }; @@ -84,7 +90,6 @@ static struct cdevsw mse_cdevsw = * Software control structure for mouse. The sc_enablemouse(), * sc_disablemouse() and sc_getmouse() routines must be called spl'd(). */ -#define PROTOBYTES 5 static struct mse_softc { int sc_flags; int sc_mousetype; @@ -98,7 +103,10 @@ static struct mse_softc { int sc_obuttons; int sc_buttons; int sc_bytesread; - u_char sc_bytes[PROTOBYTES]; + u_char sc_bytes[MOUSE_SYS_PACKETSIZE]; + mousehw_t hw; + mousemode_t mode; + mousestatus_t status; #ifdef DEVFS void *devfs_token; void *n_devfs_token; @@ -198,9 +206,19 @@ static struct mse_types { /* Disable interrupts routine */ void (*m_get) __P((u_int port, int *dx, int *dy, int *but)); /* and get mouse status */ + mousehw_t m_hw; /* buttons iftype type model hwid */ + mousemode_t m_mode; /* proto rate res accel level size mask */ } mse_types[] = { - { MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati }, - { MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi }, + { MSE_ATIINPORT, + mse_probeati, mse_enableati, mse_disableati, mse_getati, + { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, + { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, + { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, + { MSE_LOGITECH, + mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi, + { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, }, + { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, + { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, }, { 0, }, }; @@ -221,6 +239,8 @@ mseprobe(idp) sc->sc_enablemouse = mse_types[i].m_enable; sc->sc_disablemouse = mse_types[i].m_disable; sc->sc_getmouse = mse_types[i].m_get; + sc->hw = mse_types[i].m_hw; + sc->mode = mse_types[i].m_mode; return (1); } i++; @@ -236,6 +256,7 @@ mseattach(idp) struct mse_softc *sc = &mse_sc[unit]; sc->sc_port = idp->id_iobase; + sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4; #ifdef DEVFS sc->devfs_token = devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0, @@ -268,9 +289,13 @@ mseopen(dev, flags, fmt, p) if (sc->sc_flags & MSESC_OPEN) return (EBUSY); sc->sc_flags |= MSESC_OPEN; - sc->sc_obuttons = sc->sc_buttons = 0x7; + sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS; sc->sc_deltax = sc->sc_deltay = 0; - sc->sc_bytesread = PROTOBYTES; + sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE; + sc->mode.level = 0; + sc->status.flags = 0; + sc->status.button = sc->status.obutton = 0; + sc->status.dx = sc->status.dy = sc->status.dz = 0; /* * Initialize mouse interface and enable interrupts. @@ -320,7 +345,7 @@ mseread(dev, uio, ioflag) * packet. */ s = spltty(); /* XXX Should be its own spl, but where is imlXX() */ - if (sc->sc_bytesread >= PROTOBYTES) { + if (sc->sc_bytesread >= sc->mode.packetsize) { while (sc->sc_deltax == 0 && sc->sc_deltay == 0 && (sc->sc_obuttons ^ sc->sc_buttons) == 0) { if (MSE_NBLOCKIO(dev)) { @@ -340,7 +365,8 @@ mseread(dev, uio, ioflag) * For some reason X386 expects 5 bytes but never uses * the fourth or fifth? */ - sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8); + sc->sc_bytes[0] = sc->mode.syncmask[1] + | (sc->sc_buttons & ~sc->mode.syncmask[0]); if (sc->sc_deltax > 127) sc->sc_deltax = 127; if (sc->sc_deltax < -127) @@ -353,12 +379,14 @@ mseread(dev, uio, ioflag) sc->sc_bytes[1] = sc->sc_deltax; sc->sc_bytes[2] = sc->sc_deltay; sc->sc_bytes[3] = sc->sc_bytes[4] = 0; + sc->sc_bytes[5] = sc->sc_bytes[6] = 0; + sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS; sc->sc_obuttons = sc->sc_buttons; sc->sc_deltax = sc->sc_deltay = 0; sc->sc_bytesread = 0; } splx(s); - xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread); + xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread); if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio)) return (error); sc->sc_bytesread += xfer; @@ -366,6 +394,123 @@ mseread(dev, uio, ioflag) } /* + * mseioctl: process ioctl commands. + */ +static int +mseioctl(dev, cmd, addr, flag, p) + dev_t dev; + int cmd; + caddr_t addr; + int flag; + struct proc *p; +{ + register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)]; + mousestatus_t status; + int err = 0; + int s; + + switch (cmd) { + + case MOUSE_GETHWINFO: + s = spltty(); + *(mousehw_t *)addr = sc->hw; + if (sc->mode.level == 0) + ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC; + splx(s); + break; + + case MOUSE_GETMODE: + s = spltty(); + *(mousemode_t *)addr = sc->mode; + switch (sc->mode.level) { + case 0: + break; + case 1: + ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE; + ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK; + ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC; + break; + } + splx(s); + break; + + case MOUSE_SETMODE: + switch (((mousemode_t *)addr)->level) { + case 0: + case 1: + break; + default: + return (EINVAL); + } + if (((mousemode_t *)addr)->accelfactor < -1) + return (EINVAL); + else if (((mousemode_t *)addr)->accelfactor >= 0) + sc->mode.accelfactor = + ((mousemode_t *)addr)->accelfactor; + sc->mode.level = ((mousemode_t *)addr)->level; + switch (sc->mode.level) { + case 0: + sc->sc_bytesread = sc->mode.packetsize + = MOUSE_MSC_PACKETSIZE; + break; + case 1: + sc->sc_bytesread = sc->mode.packetsize + = MOUSE_SYS_PACKETSIZE; + break; + } + break; + + case MOUSE_GETLEVEL: + *(int *)addr = sc->mode.level; + break; + + case MOUSE_SETLEVEL: + switch (*(int *)addr) { + case 0: + sc->mode.level = *(int *)addr; + sc->sc_bytesread = sc->mode.packetsize + = MOUSE_MSC_PACKETSIZE; + break; + case 1: + sc->mode.level = *(int *)addr; + sc->sc_bytesread = sc->mode.packetsize + = MOUSE_SYS_PACKETSIZE; + break; + default: + return (EINVAL); + } + break; + + case MOUSE_GETSTATUS: + s = spltty(); + status = sc->status; + sc->status.flags = 0; + sc->status.obutton = sc->status.button; + sc->status.button = 0; + sc->status.dx = 0; + sc->status.dy = 0; + sc->status.dz = 0; + splx(s); + *(mousestatus_t *)addr = status; + break; + + case MOUSE_READSTATE: + case MOUSE_READDATA: + return (ENODEV); + +#if (defined(MOUSE_GETVARS)) + case MOUSE_GETVARS: + case MOUSE_SETVARS: + return (ENODEV); +#endif + + default: + return (ENOTTY); + } + return (err); +} + +/* * msepoll: check for mouse input to be processed. */ static int @@ -380,8 +525,8 @@ msepoll(dev, events, p) s = spltty(); if (events & (POLLIN | POLLRDNORM)) - if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 || - sc->sc_deltay != 0 || + if (sc->sc_bytesread != sc->mode.packetsize || + sc->sc_deltax != 0 || sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) revents |= events & (POLLIN | POLLRDNORM); else { @@ -403,7 +548,23 @@ void mseintr(unit) int unit; { + /* + * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP) + * into `mousestatus' button bits (MOUSE_BUTTON?DOWN). + */ + static int butmap[8] = { + 0, + MOUSE_BUTTON3DOWN, + MOUSE_BUTTON2DOWN, + MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, + MOUSE_BUTTON1DOWN, + MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, + MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, + MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN + }; register struct mse_softc *sc = &mse_sc[unit]; + int dx, dy, but; + int sign; #ifdef DEBUG static int mse_intrcnt = 0; @@ -413,7 +574,31 @@ mseintr(unit) if ((sc->sc_flags & MSESC_OPEN) == 0) return; - (*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons); + (*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but); + if (sc->mode.accelfactor > 0) { + sign = (dx < 0); + dx = dx * dx / sc->mode.accelfactor; + if (dx == 0) + dx = 1; + if (sign) + dx = -dx; + sign = (dy < 0); + dy = dy * dy / sc->mode.accelfactor; + if (dy == 0) + dy = 1; + if (sign) + dy = -dy; + } + sc->sc_deltax += dx; + sc->sc_deltay += dy; + sc->sc_buttons = but; + + but = butmap[~but & MOUSE_MSC_BUTTONS]; + sc->status.dx += dx; + sc->status.dy += dy; + sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0) + | (sc->status.button ^ but); + sc->status.button = but; /* * If mouse state has changed, wake up anyone wanting to know. @@ -497,7 +682,7 @@ mse_getlogi(port, dx, dy, but) outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW); x = inb(port + MSE_PORTA); - *but = (x >> 5) & 0x7; + *but = (x >> 5) & MOUSE_MSC_BUTTONS; x &= 0xf; outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH); x |= (inb(port + MSE_PORTA) << 4); @@ -505,8 +690,8 @@ mse_getlogi(port, dx, dy, but) y = (inb(port + MSE_PORTA) & 0xf); outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH); y |= (inb(port + MSE_PORTA) << 4); - *dx += x; - *dy += y; + *dx = x; + *dy = y; outb(port + MSE_PORTC, MSE_INTREN); } @@ -569,13 +754,13 @@ mse_getati(port, dx, dy, but) outb(port + MSE_PORTA, MSE_INPORT_MODE); outb(port + MSE_PORTB, MSE_INPORT_HOLD); outb(port + MSE_PORTA, MSE_INPORT_STATUS); - *but = ~(inb(port + MSE_PORTB) & 0x7); + *but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS; outb(port + MSE_PORTA, MSE_INPORT_DX); byte = inb(port + MSE_PORTB); - *dx += byte; + *dx = byte; outb(port + MSE_PORTA, MSE_INPORT_DY); byte = inb(port + MSE_PORTB); - *dy += byte; + *dy = byte; outb(port + MSE_PORTA, MSE_INPORT_MODE); outb(port + MSE_PORTB, MSE_INPORT_INTREN); } diff --git a/sys/i386/isa/psm.c b/sys/i386/isa/psm.c index f7e2fc7..d839a82 100644 --- a/sys/i386/isa/psm.c +++ b/sys/i386/isa/psm.c @@ -1,5 +1,6 @@ /*- * Copyright (c) 1992, 1993 Erik Forsberg. + * Copyright (c) 1996, 1997 Kazutaka YOKOTA. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -19,7 +20,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: psm.c,v 1.45 1997/11/18 12:21:32 bde Exp $ + * $Id: psm.c,v 1.46 1997/11/21 11:36:21 yokota Exp $ */ /* @@ -48,13 +49,16 @@ * * Hardware access routines and probe logic rewritten by * Kazutaka Yokota <yokota@zodiac.mech.utsunomiya-u.ac.jp> - * - 3 October 1996. - * - 14 October 1996. - * - 22 October 1996. + * - 3, 14, 22 October 1996. * - 12 November 1996. IOCTLs and rearranging `psmread', `psmioctl'... - * - 14 November 1996. Uses `kbdio.c'. - * - 30 November 1996. More fixes. + * - 14, 30 November 1996. Uses `kbdio.c'. * - 13 December 1996. Uses queuing version of `kbdio.c'. + * - January/February 1997. Tweaked probe logic for + * HiNote UltraII/Latitude/Armada laptops. + * - 30 July 1997. Added APM support. + * - 5 March 1997. Defined driver configuration flags (PSM_CONFIG_XXX). + * Improved sync check logic. + * Vender specific support routines. */ #include "psm.h" @@ -83,7 +87,7 @@ #include <i386/isa/kbdio.h> /* - * driver specific options: the following options may be set by + * Driver specific options: the following options may be set by * `options' statements in the kernel configuration file. */ @@ -92,15 +96,7 @@ #define PSM_DEBUG 0 /* logging: 0: none, 1: brief, 2: verbose */ #endif -/* #define PSM_CHECKSYNC if defined, check the header data byte */ - /* features */ -#ifndef PSM_ACCEL -#define PSM_ACCEL 0 /* must be one or greater; acceleration will be - * disabled if zero */ -#endif - -/* #define PSM_EMULATION enables protocol emulation */ /* #define PSM_HOOKAPM hook the APM resume event */ /* #define PSM_RESETAFTERSUSPEND reset the device at the resume event */ @@ -115,50 +111,56 @@ /* end of driver specific options */ +/* input queue */ +#define PSM_BUFSIZE 960 +#define PSM_SMALLBUFSIZE 240 + +/* operation levels */ +#define PSM_LEVEL_BASE 0 +#define PSM_LEVEL_STANDARD 1 +#define PSM_LEVEL_NATIVE 2 +#define PSM_LEVEL_MIN PSM_LEVEL_BASE +#define PSM_LEVEL_MAX PSM_LEVEL_NATIVE + /* some macros */ #define PSM_UNIT(dev) (minor(dev) >> 1) #define PSM_NBLOCKIO(dev) (minor(dev) & 1) #define PSM_MKMINOR(unit,block) (((unit) << 1) | ((block) ? 0:1)) #ifndef max -#define max(x,y) ((x) > (y) ? (x) : (y)) +#define max(x,y) ((x) > (y) ? (x) : (y)) #endif #ifndef min -#define min(x,y) ((x) < (y) ? (x) : (y)) +#define min(x,y) ((x) < (y) ? (x) : (y)) #endif /* ring buffer */ -#define PSM_BUFSIZE 256 - typedef struct ringbuf { - int count; - int head; - int tail; - mousestatus_t buf[PSM_BUFSIZE]; + int count; /* # of valid elements in the buffer */ + int head; /* head pointer */ + int tail; /* tail poiner */ + unsigned char buf[PSM_BUFSIZE]; } ringbuf_t; /* driver control block */ -typedef int (*packetfunc_t) __P((unsigned char *, int *, int, mousestatus_t *)); - static struct psm_softc { /* Driver status information */ struct selinfo rsel; /* Process selecting for Input */ unsigned char state; /* Mouse driver state */ - KBDC kbdc; - int addr; /* I/O port address */ - mousehw_t hw; /* hardware information */ - mousemode_t mode; /* operation mode */ - mousemode_t dflt_mode; /* default operation mode */ - ringbuf_t queue; /* mouse status queue */ - packetfunc_t mkpacket; /* func. to turn queued data into output format */ - unsigned char ipacket[MOUSE_PS2_PACKETSIZE];/* interim input buffer */ - unsigned char opacket[PSM_BUFSIZE]; /* output buffer */ - int inputbytes; /* # of bytes in the input buffer */ - int outputbytes; /* # of bytes in the output buffer */ - int outputhead; /* points the head of the output buffer */ - int button; /* the latest button state */ + int config; /* driver configuration flags */ + int flags; /* other flags */ + KBDC kbdc; /* handle to access the keyboard controller */ + int addr; /* I/O port address */ + mousehw_t hw; /* hardware information */ + mousemode_t mode; /* operation mode */ + mousemode_t dflt_mode; /* default operation mode */ + mousestatus_t status; /* accumulated mouse movement */ + ringbuf_t queue; /* mouse status queue */ + unsigned char ipacket[16]; /* interim input buffer */ + int inputbytes; /* # of bytes in the input buffer */ + int button; /* the latest button state */ #ifdef DEVFS - void *devfs_token; - void *n_devfs_token; + void *devfs_token; + void *n_devfs_token; #endif #ifdef PSM_HOOKAPM struct apmhook resumehook; @@ -166,9 +168,32 @@ static struct psm_softc { /* Driver status information */ } *psm_softc[NPSM]; /* driver state flags (state) */ -#define PSM_VALID 0x80 -#define PSM_OPEN 1 /* Device is open */ -#define PSM_ASLP 2 /* Waiting for mouse data */ +#define PSM_VALID 0x80 +#define PSM_OPEN 1 /* Device is open */ +#define PSM_ASLP 2 /* Waiting for mouse data */ + +/* driver configuration flags (config) */ +#define PSM_CONFIG_RESOLUTION 0x000f /* resolution */ +#define PSM_CONFIG_ACCEL 0x00f0 /* acceleration factor */ +#define PSM_CONFIG_NOCHECKSYNC 0x0100 /* disable sync. test */ + +#define PSM_CONFIG_FLAGS (PSM_CONFIG_RESOLUTION \ + | PSM_CONFIG_ACCEL \ + | PSM_CONFIG_NOCHECKSYNC) + +/* other flags (flags) */ +/* + * Pass mouse data packet to the user land program `as is', even if + * the mouse has vender-specific enhanced features and uses non-standard + * packet format. Otherwise manipulate the mouse data packet so that + * it can be recognized by the programs which can only understand + * the standard packet format. +*/ +#define PSM_FLAGS_NATIVEMODE 0x0200 + +/* packet formatting function */ +typedef int packetfunc_t __P((struct psm_softc *, unsigned char *, + int *, int, mousestatus_t *)); /* function prototypes */ static int psmprobe __P((struct isa_device *)); @@ -186,10 +211,10 @@ static d_poll_t psmpoll; static int enable_aux_dev __P((KBDC)); static int disable_aux_dev __P((KBDC)); -static int get_mouse_status __P((KBDC, int *)); +static int get_mouse_status __P((KBDC, int *, int, int)); static int get_aux_id __P((KBDC)); static int set_mouse_sampling_rate __P((KBDC, int)); -static int set_mouse_scaling __P((KBDC)); +static int set_mouse_scaling __P((KBDC, int)); static int set_mouse_resolution __P((KBDC, int)); static int set_mouse_mode __P((KBDC)); static int get_mouse_buttons __P((KBDC)); @@ -198,11 +223,41 @@ static void recover_from_error __P((KBDC)); static int restore_controller __P((KBDC, int)); static int reinitialize __P((int, mousemode_t *)); static int doopen __P((int, int)); -static int mkms __P((unsigned char *, int *, int, mousestatus_t *)); -static int mkman __P((unsigned char *, int *, int, mousestatus_t *)); -static int mkmsc __P((unsigned char *, int *, int, mousestatus_t *)); -static int mkmm __P((unsigned char *, int *, int, mousestatus_t *)); -static int mkps2 __P((unsigned char *, int *, int, mousestatus_t *)); +static char *model_name(int); + +/* vender specific features */ +typedef int probefunc_t __P((struct psm_softc *)); + +static int mouse_id_proc1 __P((KBDC, int, int, int *)); +static probefunc_t enable_groller; +static probefunc_t enable_gmouse; +static probefunc_t enable_aglide; +static probefunc_t enable_kmouse; +static probefunc_t enable_msintelli; +static probefunc_t enable_mmanplus; +static int tame_mouse __P((struct psm_softc *, mousestatus_t *, unsigned char *)); + +static struct { + int model; + unsigned char syncmask; + int packetsize; + probefunc_t *probefunc; +} vendertype[] = { + { MOUSE_MODEL_NET, /* Genius NetMouse */ + 0xc8, MOUSE_INTELLI_PACKETSIZE, enable_gmouse, }, + { MOUSE_MODEL_NETSCROLL, /* Genius NetScroll */ + 0xc8, 6, enable_groller, }, + { MOUSE_MODEL_GLIDEPOINT, /* ALPS GlidePoint */ + 0xc0, MOUSE_PS2_PACKETSIZE, enable_aglide, }, + { MOUSE_MODEL_MOUSEMANPLUS, /* Logitech MouseMan+ */ + 0x08, MOUSE_PS2_PACKETSIZE, enable_mmanplus, }, + { MOUSE_MODEL_THINK, /* Kensignton ThinkingMouse */ + 0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse, }, + { MOUSE_MODEL_INTELLI, /* Microsoft IntelliMouse */ + 0xc8, MOUSE_INTELLI_PACKETSIZE, enable_msintelli, }, + { MOUSE_MODEL_GENERIC, + 0xc8, MOUSE_PS2_PACKETSIZE, NULL, }, +}; /* device driver declarateion */ struct isa_driver psmdriver = { psmprobe, psmattach, "psm", FALSE }; @@ -243,22 +298,41 @@ disable_aux_dev(KBDC kbdc) } static int -get_mouse_status(KBDC kbdc, int *status) +get_mouse_status(KBDC kbdc, int *status, int flag, int len) { + int cmd; int res; + int i; + switch (flag) { + case 0: + default: + cmd = PSMC_SEND_DEV_STATUS; + break; + case 1: + cmd = PSMC_SEND_DEV_DATA; + break; + } empty_aux_buffer(kbdc, 5); - res = send_aux_command(kbdc, PSMC_SEND_DEV_STATUS); + res = send_aux_command(kbdc, cmd); if (verbose >= 2) - log(LOG_DEBUG, "psm: SEND_AUX_STATUS return code:%04x\n", res); + log(LOG_DEBUG, "psm: SEND_AUX_DEV_%s return code:%04x\n", + (flag == 1) ? "DATA" : "STATUS", res); if (res != PSM_ACK) - return FALSE; + return 0; - status[0] = read_aux_data(kbdc); - status[1] = read_aux_data(kbdc); - status[2] = read_aux_data(kbdc); + for (i = 0; i < len; ++i) { + status[i] = read_aux_data(kbdc); + if (status[i] < 0) + break; + } - return TRUE; + if (verbose) { + log(LOG_DEBUG, "psm: %s %02x %02x %02x\n", + (flag == 1) ? "data" : "status", status[0], status[1], status[2]); + } + + return i; } static int @@ -297,13 +371,23 @@ set_mouse_sampling_rate(KBDC kbdc, int rate) } static int -set_mouse_scaling(KBDC kbdc) +set_mouse_scaling(KBDC kbdc, int scale) { int res; - res = send_aux_command(kbdc, PSMC_SET_SCALING11); + switch (scale) { + case 1: + default: + scale = PSMC_SET_SCALING11; + break; + case 2: + scale = PSMC_SET_SCALING21; + break; + } + res = send_aux_command(kbdc, scale); if (verbose >= 2) - log(LOG_DEBUG, "psm: SET_SCALING11 return code:%04x\n", res); + log(LOG_DEBUG, "psm: SET_SCALING%s return code:%04x\n", + (scale == PSMC_SET_SCALING21) ? "21" : "11", res); return (res == PSM_ACK); } @@ -344,29 +428,27 @@ get_mouse_buttons(KBDC kbdc) int status[3]; /* - * NOTE: a special sequence to obtain Logitech-Mouse-specific + * NOTE: a special sequence to obtain Logitech Mouse specific * information: set resolution to 25 ppi, set scaling to 1:1, set * scaling to 1:1, set scaling to 1:1. Then the second byte of the * mouse status bytes is the number of available buttons. + * Some manufactures also support this sequence. */ if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW) return c; - if (set_mouse_scaling(kbdc) && set_mouse_scaling(kbdc) - && set_mouse_scaling(kbdc) && get_mouse_status(kbdc, status)) { - if (verbose) { - log(LOG_DEBUG, "psm: status %02x %02x %02x (get_mouse_buttons)\n", - status[0], status[1], status[2]); - } + if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1) + && set_mouse_scaling(kbdc, 1) + && (get_mouse_status(kbdc, status, 0, 3) >= 3)) { if (status[1] != 0) return status[1]; } return c; } +/* misc subroutines */ /* - * FIXME:XXX - * someday, I will get the list of valid pointing devices and - * their IDs... + * Someday, I will get the complete list of valid pointing devices and + * their IDs... XXX */ static int is_a_mouse(int id) @@ -375,6 +457,7 @@ is_a_mouse(int id) static int valid_ids[] = { PSM_MOUSE_ID, /* mouse */ PSM_BALLPOINT_ID, /* ballpoint device */ + PSM_INTELLI_ID, /* Intellimouse */ -1 /* end of table */ }; int i; @@ -388,6 +471,31 @@ is_a_mouse(int id) #endif } +static char * +model_name(int model) +{ + static struct { + int model_code; + char *model_name; + } models[] = { + { MOUSE_MODEL_NETSCROLL, "NetScroll Mouse" }, + { MOUSE_MODEL_NET, "NetMouse" }, + { MOUSE_MODEL_GLIDEPOINT, "GlidePoint" }, + { MOUSE_MODEL_THINK, "ThinkingMouse" }, + { MOUSE_MODEL_INTELLI, "IntelliMouse" }, + { MOUSE_MODEL_MOUSEMANPLUS, "MouseMan+" }, + { MOUSE_MODEL_GENERIC, "Generic PS/2 mouse" }, + { MOUSE_MODEL_UNKNOWN, NULL }, + }; + int i; + + for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i) { + if (models[i].model_code == model) + return models[i].model_name; + } + return "Unknown"; +} + static void recover_from_error(KBDC kbdc) { @@ -418,6 +526,8 @@ recover_from_error(KBDC kbdc) static int restore_controller(KBDC kbdc, int command_byte) { + empty_both_buffers(kbdc, 10); + if (!set_controller_command_byte(kbdc, 0xff, command_byte)) { log(LOG_ERR, "psm: failed to restore the keyboard controller " "command byte.\n"); @@ -437,6 +547,7 @@ restore_controller(KBDC kbdc, int command_byte) static int reinitialize(int unit, mousemode_t *mode) { + struct psm_softc *sc = psm_softc[unit]; KBDC kbdc = psm_softc[unit]->kbdc; int stat[3]; int i; @@ -453,7 +564,7 @@ reinitialize(int unit, mousemode_t *mode) default: /* error */ recover_from_error(kbdc); log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n", - unit,i); + unit, i); return FALSE; } @@ -477,25 +588,45 @@ reinitialize(int unit, mousemode_t *mode) } empty_both_buffers(kbdc, 10); /* remove stray data if any */ + /* FIXME: hardware ID, mouse buttons? */ + + /* other parameters */ + for (i = 0; vendertype[i].probefunc != NULL; ++i) { + if ((*vendertype[i].probefunc)(sc)) { + if (verbose >= 2) + log(LOG_ERR, "psm%d: found %s\n", + unit, model_name(vendertype[i].model)); + break; + } + } + + sc->hw.model = vendertype[i].model; + sc->mode.packetsize = vendertype[i].packetsize; + /* set mouse parameters */ if (mode != (mousemode_t *)NULL) { if (mode->rate > 0) mode->rate = set_mouse_sampling_rate(kbdc, mode->rate); if (mode->resolution >= 0) mode->resolution = set_mouse_resolution(kbdc, mode->resolution); - set_mouse_scaling(kbdc); + set_mouse_scaling(kbdc, 1); set_mouse_mode(kbdc); } - /* just check the status of the mouse */ - i = get_mouse_status(kbdc, stat); - if (!i) { - log(LOG_DEBUG, "psm%d: failed to get status.\n", unit); - } else if (verbose) { - log(LOG_DEBUG, "psm%d: status %02x %02x %02x\n", unit, - stat[0], stat[1], stat[2]); + /* request a data packet and extract sync. bits */ + if (get_mouse_status(kbdc, stat, 1, 3) < 3) { + log(LOG_DEBUG, "psm%d: failed to get data (reinitialize).\n", unit); + sc->mode.syncmask[0] = 0; + } else { + sc->mode.syncmask[1] = stat[0] & sc->mode.syncmask[0]; /* syncbits */ + /* the NetScroll Mouse will send three more bytes... Ignore them */ + empty_aux_buffer(kbdc, 5); } + /* just check the status of the mouse */ + if (get_mouse_status(kbdc, stat, 0, 3) < 3) + log(LOG_DEBUG, "psm%d: failed to get status (reinitialize).\n", unit); + return TRUE; } @@ -519,22 +650,21 @@ doopen(int unit, int command_byte) * it again. But it will take long time and it's not a good * idea to disable the keyboard that long... */ - if (!reinitialize(unit, &sc->mode)) { - if (!enable_aux_dev(sc->kbdc)) - recover_from_error(sc->kbdc); + if (!reinitialize(unit, &sc->mode) || !enable_aux_dev(sc->kbdc)) { + recover_from_error(sc->kbdc); #else { #endif restore_controller(sc->kbdc, command_byte); /* mark this device is no longer available */ sc->state &= ~PSM_VALID; - log(LOG_ERR, "psm%d: failed to enable the device (doopen).\n", + log(LOG_ERR, "psm%d: failed to enable the device (doopen).\n", unit); return (EIO); } } - if (!get_mouse_status(sc->kbdc, stat)) + if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n", unit); /* enable the aux port and interrupt */ @@ -581,11 +711,16 @@ psmprobe(struct isa_device *dvp) sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); if (sc == NULL) - return (0); + return (0); bzero(sc, sizeof *sc); +#if 0 + kbdc_debug(TRUE); +#endif sc->addr = dvp->id_iobase; sc->kbdc = kbdc_open(sc->addr); + sc->config = dvp->id_flags & PSM_CONFIG_FLAGS; + sc->flags = 0; if (bootverbose) ++verbose; @@ -600,33 +735,7 @@ psmprobe(struct isa_device *dvp) /* * NOTE: two bits in the command byte controls the operation of the * aux port (mouse port): the aux port disable bit (bit 5) and the aux - * port interrupt (IRQ 12) enable bit (bit 2). When this probe routine - * is called, there are following possibilities about the presence of - * the aux port and the PS/2 mouse. - * - * Case 1: aux port disabled (bit 5:1), aux int. disabled (bit 2:0) The - * aux port most certainly exists. A device may or may not be - * connected to the port. No driver is probably installed yet. - * - * Case 2: aux port enabled (bit 5:0), aux int. disabled (bit 2:0) Three - * possibile situations here: - * - * Case 2a: The aux port does not exist, therefore, is not explicitly - * disabled. Case 2b: The aux port exists. A device and a driver may - * exist, using the device in the polling(remote) mode. Case 2c: The - * aux port exists. A device may exist, but someone who knows nothing - * about the aux port has set the command byte this way. - * - * Case 3: aux port disabled (bit 5:1), aux int. enabled (bit 2:1) The - * aux port exists, but someone is controlloing the device and - * temporalily disabled the port. - * - * Case 4: aux port enabled (bit 5:0), aux int. enabled (bit 2:1) The aux - * port exists, a device is attached to the port, and someone is - * controlling the device. Some BIOS set the bits this way after boot. - * - * All in all, it is no use examing the bits for detecting the presence - * of the port and the mouse device. + * port interrupt (IRQ 12) enable bit (bit 2). */ /* discard anything left after the keyboard initialization */ @@ -721,10 +830,7 @@ psmprobe(struct isa_device *dvp) } /* save the default values after reset */ - if (get_mouse_status(sc->kbdc, stat)) { - if (verbose) - printf("psm%d: status after reset %02x %02x %02x\n", - unit, stat[0], stat[1], stat[2]); + if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) { sc->dflt_mode.rate = sc->mode.rate = stat[2]; sc->dflt_mode.resolution = sc->mode.resolution = stat[1]; } else { @@ -748,6 +854,7 @@ psmprobe(struct isa_device *dvp) sc->hw.type = MOUSE_TRACKBALL; break; case PSM_MOUSE_ID: + case PSM_INTELLI_ID: sc->hw.type = MOUSE_MOUSE; break; default: @@ -758,21 +865,48 @@ psmprobe(struct isa_device *dvp) /* # of buttons */ sc->hw.buttons = get_mouse_buttons(sc->kbdc); + /* other parameters */ + for (i = 0; vendertype[i].probefunc != NULL; ++i) { + if ((*vendertype[i].probefunc)(sc)) { + if (verbose >= 2) + printf("psm%d: found %s\n", + unit, model_name(vendertype[i].model)); + break; + } + } + + sc->hw.model = vendertype[i].model; + + sc->dflt_mode.level = PSM_LEVEL_BASE; + sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE; + sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4; + if (sc->config & PSM_CONFIG_NOCHECKSYNC) + sc->dflt_mode.syncmask[0] = 0; + else + sc->dflt_mode.syncmask[0] = vendertype[i].syncmask; + sc->dflt_mode.syncmask[1] = 0; /* syncbits */ + sc->mode = sc->dflt_mode; + sc->mode.packetsize = vendertype[i].packetsize; + /* set mouse parameters */ - /* FIXME:XXX should we set them in `psmattach()' rather than here? */ - /* FIXME:XXX I don't know if these parameters are reasonable */ i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS); if (verbose >= 2) - log(LOG_DEBUG, "psm%d: SET_DEFAULTS return code:%04x\n", - unit, i); -#ifdef PSM_MSCKLUDGE - set_mouse_resolution(sc->kbdc, PSMD_RES_HIGH); -#endif + printf("psm%d: SET_DEFAULTS return code:%04x\n", unit, i); + if (sc->config & PSM_CONFIG_RESOLUTION) { + sc->mode.resolution + = set_mouse_resolution(sc->kbdc, + (sc->config & PSM_CONFIG_RESOLUTION) - 1); + } -#if 0 - set_mouse_scaling(sc->kbdc); /* 1:1 scaling */ - set_mouse_mode(sc->kbdc); /* stream mode */ -#endif + /* request a data packet and extract sync. bits */ + if (get_mouse_status(sc->kbdc, stat, 1, 3) < 3) { + printf("psm%d: failed to get data.\n", unit); + sc->mode.syncmask[0] = 0; + } else { + sc->mode.syncmask[1] = stat[0] & sc->mode.syncmask[0]; /* syncbits */ + /* the NetScroll Mouse will send three more bytes... Ignore them */ + empty_aux_buffer(sc->kbdc, 5); + } /* just check the status of the mouse */ /* @@ -780,13 +914,16 @@ psmprobe(struct isa_device *dvp) * there, which hung the controller unless there is data transmission * after ACK from the mouse. */ - i = get_mouse_status(sc->kbdc, stat); - if (!i) { - log(LOG_DEBUG, "psm%d: failed to get status.\n", unit); - } else if (verbose) { - log(LOG_DEBUG, "psm%d: status %02x %02x %02x\n", - unit, stat[0], stat[1], stat[2]); - } + if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) { + printf("psm%d: failed to get status.\n", unit); + } else { + /* + * When in its native mode, some mice operate with different + * default parameters than in the PS/2 compatible mode. + */ + sc->dflt_mode.rate = sc->mode.rate = stat[2]; + sc->dflt_mode.resolution = sc->mode.resolution = stat[1]; + } /* disable the aux port for now... */ if (!set_controller_command_byte(sc->kbdc, @@ -818,11 +955,6 @@ psmattach(struct isa_device *dvp) if (sc == NULL) /* shouldn't happen */ return (0); - /* initial operation mode */ - sc->dflt_mode.accelfactor = sc->mode.accelfactor = PSM_ACCEL; - sc->dflt_mode.protocol = sc->mode.protocol = MOUSE_PROTO_PS2; - sc->mkpacket = mkps2; - /* Setup initial state */ sc->state = PSM_VALID; @@ -846,11 +978,17 @@ psmattach(struct isa_device *dvp) printf("psm%d: APM hooks installed.\n", unit); #endif /* PSM_HOOKAPM */ - if (verbose) - printf("psm%d: device ID %d, %d buttons\n", - unit, sc->hw.hwid, sc->hw.buttons); - else - printf("psm%d: device ID %d\n", unit, sc->hw.hwid); + if (!verbose) { + printf("psm%d: model %s, device ID %d\n", + unit, model_name(sc->hw.model), sc->hw.hwid); + } else { + printf("psm%d: model %s, device ID %d, %d buttons\n", + unit, model_name(sc->hw.model), sc->hw.hwid, sc->hw.buttons); + printf("psm%d: config:%08x, flags:%08x, packet size:%d\n", + unit, sc->config, sc->flags, sc->mode.packetsize); + printf("psm%d: syncmask:%02x, syncbits:%02x\n", + unit, sc->mode.syncmask[0], sc->mode.syncmask[1]); + } if (bootverbose) --verbose; @@ -884,17 +1022,24 @@ psmopen(dev_t dev, int flag, int fmt, struct proc *p) /* Initialize state */ sc->rsel.si_flags = 0; sc->rsel.si_pid = 0; + sc->mode.level = sc->dflt_mode.level; + sc->mode.protocol = sc->dflt_mode.protocol; /* flush the event queue */ sc->queue.count = 0; sc->queue.head = 0; sc->queue.tail = 0; + sc->status.flags = 0; + sc->status.button = 0; + sc->status.obutton = 0; + sc->status.dx = 0; + sc->status.dy = 0; + sc->status.dz = 0; sc->button = 0; - /* empty input/output buffers */ + /* empty input buffer */ + bzero(sc->ipacket, sizeof(sc->ipacket)); sc->inputbytes = 0; - sc->outputbytes = 0; - sc->outputhead = 0; /* don't let timeout routines in the keyboard driver to poll the kbdc */ if (!kbdc_lock(sc->kbdc, TRUE)) @@ -942,7 +1087,6 @@ psmclose(dev_t dev, int flag, int fmt, struct proc *p) struct psm_softc *sc = psm_softc[PSM_UNIT(dev)]; int stat[3]; int command_byte; - int ret; int s; /* don't let timeout routines in the keyboard driver to poll the kbdc */ @@ -978,24 +1122,21 @@ psmclose(dev_t dev, int flag, int fmt, struct proc *p) empty_aux_buffer(sc->kbdc, 10); /* disable the aux device, port and interrupt */ - if (!disable_aux_dev(sc->kbdc)) { - /* MOUSE ERROR; - * NOTE: we don't return error and continue, pretending - * we have successfully disabled the device. It's OK because - * the interrupt routine will discard any data from the mouse - * hereafter. - */ - log(LOG_ERR, "psm%d: failed to disable the device (psmclose).\n", - PSM_UNIT(dev)); - } + if (sc->state & PSM_VALID) { + if (!disable_aux_dev(sc->kbdc)) { + /* MOUSE ERROR; + * NOTE: we don't return error and continue, pretending + * we have successfully disabled the device. It's OK because + * the interrupt routine will discard any data from the mouse + * hereafter. + */ + log(LOG_ERR, "psm%d: failed to disable the device (psmclose).\n", + PSM_UNIT(dev)); + } - ret = get_mouse_status(sc->kbdc, stat); - if (!ret) { - log(LOG_DEBUG, "psm%d: failed to get status (psmclose).\n", - PSM_UNIT(dev)); - } else if (verbose >= 2) { - log(LOG_DEBUG, "psm%d: status %02x %02x %02x (psmclose)\n", - PSM_UNIT(dev), stat[0], stat[1], stat[2]); + if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) + log(LOG_DEBUG, "psm%d: failed to get status (psmclose).\n", + PSM_UNIT(dev)); } if (!set_controller_command_byte(sc->kbdc, @@ -1013,287 +1154,193 @@ psmclose(dev_t dev, int flag, int fmt, struct proc *p) empty_aux_buffer(sc->kbdc, 10); /* close is almost always successful */ - sc->state &= ~(PSM_OPEN | PSM_ASLP); + sc->state &= ~PSM_OPEN; kbdc_lock(sc->kbdc, FALSE); return (0); } -#ifdef PSM_EMULATION -static int -mkms(unsigned char *buf, int *len, int maxlen, register mousestatus_t *status) -{ - static int butmap[] = { - 0, MOUSE_MSS_BUTTON1DOWN, - 0, MOUSE_MSS_BUTTON1DOWN , - MOUSE_MSS_BUTTON3DOWN, MOUSE_MSS_BUTTON1DOWN | MOUSE_MSS_BUTTON3DOWN, - MOUSE_MSS_BUTTON3DOWN, MOUSE_MSS_BUTTON1DOWN | MOUSE_MSS_BUTTON3DOWN, - }; - unsigned char delta; - - if (maxlen - *len < MOUSE_MSS_PACKETSIZE) - return FALSE; - - buf[0] = MOUSE_MSS_SYNC | butmap[status->button & MOUSE_STDBUTTONS]; - - if (status->dx < -128) - delta = 0x80; /* -128 */ - else - if (status->dx > 127) - delta = 0x7f; /* 127 */ - else - delta = (unsigned char) status->dx; - buf[0] |= (delta & 0xc0) >> 6; /* bit 6-7 */ - buf[1] = delta & 0x3f; /* bit 0-5 */ - - if (status->dy < -128) - delta = 0x80; /* -128 */ - else - if (status->dy > 127) - delta = 0x7f; /* 127 */ - else - delta = (unsigned char) status->dy; - buf[0] |= (delta & 0xc0) >> 4; /* bit 6-7 */ - buf[2] = delta & 0x3f; /* bit 0-5 */ - - *len += MOUSE_MSS_PACKETSIZE; - - return TRUE; -} - -static int -mkman(unsigned char *buf, int *len, int maxlen, register mousestatus_t *status) -{ - static int butmap[] = { - 0, MOUSE_MSS_BUTTON1DOWN, - 0, MOUSE_MSS_BUTTON1DOWN, - MOUSE_MSS_BUTTON3DOWN, MOUSE_MSS_BUTTON1DOWN | MOUSE_MSS_BUTTON3DOWN, - MOUSE_MSS_BUTTON3DOWN, MOUSE_MSS_BUTTON1DOWN | MOUSE_MSS_BUTTON3DOWN, - }; - unsigned char delta; - int l; - - l = ((status->button ^ status->obutton) & MOUSE_BUTTON2DOWN) ? - MOUSE_MSS_PACKETSIZE + 1: MOUSE_MSS_PACKETSIZE; - if (maxlen - *len < l) - return FALSE; - - buf[0] = MOUSE_MSS_SYNC | butmap[status->button & MOUSE_STDBUTTONS]; - - if (status->dx < -128) - delta = 0x80; /* -128 */ - else - if (status->dx > 127) - delta = 0x7f; /* 127 */ - else - delta = (unsigned char) status->dx; - buf[0] |= (delta & 0xc0) >> 6; /* bit 6-7 */ - buf[1] = delta & 0x3f; /* bit 0-5 */ - - if (status->dy < -128) - delta = 0x80; /* -128 */ - else - if (status->dy > 127) - delta = 0x7f; /* 127 */ - else - delta = (unsigned char) status->dy; - buf[0] |= (delta & 0xc0) >> 4; /* bit 6-7 */ - buf[2] = delta & 0x3f; /* bit 0-5 */ - - if (l > MOUSE_MSS_PACKETSIZE) - buf[3] = (status->button & MOUSE_BUTTON2DOWN) - ? MOUSE_LMAN_BUTTON2DOWN : 0; - - *len += l; - - return TRUE; -} - static int -mkmsc(unsigned char *buf, int *len, int maxlen, register mousestatus_t *status) +tame_mouse(struct psm_softc *sc, mousestatus_t *status, unsigned char *buf) { - static int butmap[] = { + static unsigned char butmapps2[8] = { 0, - MOUSE_MSC_BUTTON1UP, MOUSE_MSC_BUTTON2UP, - MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, - MOUSE_MSC_BUTTON3UP, - MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, - MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, + MOUSE_PS2_BUTTON1DOWN, + MOUSE_PS2_BUTTON2DOWN, + MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN, + MOUSE_PS2_BUTTON3DOWN, + MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON3DOWN, + MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN, + MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN, + }; + static unsigned char butmapmsc[8] = { MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON1UP, + 0, }; - register int delta; - - if (maxlen - *len < MOUSE_MSC_PACKETSIZE) - return FALSE; - - buf[0] = MOUSE_MSC_SYNC - | (~butmap[status->button & MOUSE_STDBUTTONS] & MOUSE_MSC_BUTTONS); - - /* data bytes cannot be between 80h (-128) and 87h (-120). - * values we can return is 255 (0ffh) through -251 (10fh = 87h*2 + 1). - */ - if (status->dx < -251) - delta = -251; - else - if (status->dx > 255) - delta = 255; - else - delta = status->dx; - buf[1] = delta/2; - buf[3] = delta - buf[1]; - - if (status->dy < -251) - delta = -251; - else - if (status->dy > 255) - delta = 255; - else - delta = status->dy; - buf[2] = delta/2; - buf[4] = delta - buf[2]; - - *len += MOUSE_MSC_PACKETSIZE; + int mapped; + int i; - return TRUE; + if (sc->mode.level == PSM_LEVEL_BASE) { + mapped = status->button & ~MOUSE_BUTTON4DOWN; + if (status->button & MOUSE_BUTTON4DOWN) + mapped |= MOUSE_BUTTON1DOWN; + status->button = mapped; + buf[0] = MOUSE_PS2_SYNC | butmapps2[mapped & MOUSE_STDBUTTONS]; + i = max(min(status->dx, 255), -256); + if (i < 0) + buf[0] |= MOUSE_PS2_XNEG; + buf[1] = i; + i = max(min(status->dy, 255), -256); + if (i < 0) + buf[0] |= MOUSE_PS2_YNEG; + buf[2] = i; + return MOUSE_PS2_PACKETSIZE; + } else if (sc->mode.level == PSM_LEVEL_STANDARD) { + buf[0] = MOUSE_MSC_SYNC | butmapmsc[status->button & MOUSE_STDBUTTONS]; + i = max(min(status->dx, 255), -256); + buf[1] = i >> 1; + buf[3] = i - buf[1]; + i = max(min(status->dy, 255), -256); + buf[2] = i >> 1; + buf[4] = i - buf[2]; + i = max(min(status->dz, 127), -128); + buf[5] = (i >> 1) & 0x7f; + buf[6] = (i - (i >> 1)) & 0x7f; + buf[7] = (~status->button >> 3) & 0x7f; + return MOUSE_SYS_PACKETSIZE; + } + return sc->inputbytes;; } static int -mkmm(unsigned char *buf, int *len, int maxlen, register mousestatus_t *status) +psmread(dev_t dev, struct uio *uio, int flag) { - static int butmap[] = { - 0, - MOUSE_MM_BUTTON1DOWN, MOUSE_MM_BUTTON2DOWN, - MOUSE_MM_BUTTON1DOWN | MOUSE_MM_BUTTON2DOWN, - MOUSE_MM_BUTTON3DOWN, - MOUSE_MM_BUTTON1DOWN | MOUSE_MM_BUTTON3DOWN, - MOUSE_MM_BUTTON2DOWN | MOUSE_MM_BUTTON3DOWN, - MOUSE_MM_BUTTON1DOWN | MOUSE_MM_BUTTON2DOWN | MOUSE_MM_BUTTON3DOWN, - }; - int delta; - - if (maxlen - *len < MOUSE_MM_PACKETSIZE) - return FALSE; + register struct psm_softc *sc = psm_softc[PSM_UNIT(dev)]; + unsigned char buf[PSM_SMALLBUFSIZE]; + int error = 0; + int s; + int l; - buf[0] = MOUSE_MM_SYNC - | butmap[status->button & MOUSE_STDBUTTONS] - | ((status->dx > 0) ? MOUSE_MM_XPOSITIVE : 0) - | ((status->dy > 0) ? MOUSE_MM_YPOSITIVE : 0); + if ((sc->state & PSM_VALID) == 0) + return EIO; - delta = (status->dx < 0) ? -status->dx : status->dx; - buf[1] = min(delta, 127); - delta = (status->dy < 0) ? -status->dy : status->dy; - buf[2] = min(delta, 127); + /* block until mouse activity occured */ + s = spltty(); + while (sc->queue.count <= 0) { + if (PSM_NBLOCKIO(dev)) { + splx(s); + return EWOULDBLOCK; + } + sc->state |= PSM_ASLP; + error = tsleep((caddr_t) sc, PZERO | PCATCH, "psmrea", 0); + sc->state &= ~PSM_ASLP; + if (error) { + splx(s); + return error; + } else if ((sc->state & PSM_VALID) == 0) { + /* the device disappeared! */ + splx(s); + return EIO; + } + } + splx(s); - *len += MOUSE_MM_PACKETSIZE; + /* copy data to the user land */ + while ((sc->queue.count > 0) && (uio->uio_resid > 0)) { + s = spltty(); + l = min(sc->queue.count, uio->uio_resid); + if (l > sizeof(buf)) + l = sizeof(buf); + if (l > sizeof(sc->queue.buf) - sc->queue.head) { + bcopy(&sc->queue.buf[sc->queue.head], &buf[0], + sizeof(sc->queue.buf) - sc->queue.head); + bcopy(&sc->queue.buf[0], + &buf[sizeof(sc->queue.buf) - sc->queue.head], + l - (sizeof(sc->queue.buf) - sc->queue.head)); + } else { + bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l); + } + sc->queue.count -= l; + sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf); + splx(s); + error = uiomove(buf, l, uio); + if (error) + break; + } - return TRUE; + return error; } -#endif /* PSM_EMULATION */ static int -mkps2(unsigned char *buf, int *len, int maxlen, register mousestatus_t *status) +block_mouse_data(struct psm_softc *sc, int *c) { - static int butmap[] = { - 0, - MOUSE_PS2_BUTTON1DOWN, MOUSE_PS2_BUTTON2DOWN, - MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN, - MOUSE_PS2_BUTTON3DOWN, - MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON3DOWN, - MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN, - MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN, - }; - register int delta; - - if (maxlen - *len < MOUSE_PS2_PACKETSIZE) - return FALSE; + int s; - buf[0] = ((status->button & MOUSE_BUTTON4DOWN) ? 0 : MOUSE_PS2_BUTTON4UP) - | butmap[status->button & MOUSE_STDBUTTONS]; - if ((verbose >= 2) && ((buf[0] & MOUSE_PS2_BUTTON4UP) == 0)) - log(LOG_DEBUG, "psm: button 4 down (%04x) (mkps2)\n", buf[0]); + if (!kbdc_lock(sc->kbdc, TRUE)) + return EIO; - if (status->dx < -256) - delta = -256; - else - if (status->dx > 255) - delta = 255; - else - delta = status->dx; - if (delta < 0) - buf[0] |= MOUSE_PS2_XNEG; - buf[1] = delta; - - if (status->dy < -256) - delta = -256; - else - if (status->dy > 255) - delta = 255; - else - delta = status->dy; - if (delta < 0) - buf[0] |= MOUSE_PS2_YNEG; - buf[2] = delta; + s = spltty(); + *c = get_controller_command_byte(sc->kbdc); + if ((*c == -1) + || !set_controller_command_byte(sc->kbdc, + kbdc_get_device_mask(sc->kbdc), + KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT + | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { + /* this is CONTROLLER ERROR */ + splx(s); + kbdc_lock(sc->kbdc, FALSE); + return EIO; + } - *len += MOUSE_PS2_PACKETSIZE; + /* + * The device may be in the middle of status data transmission. + * The transmission will be interrupted, thus, incomplete status + * data must be discarded. Although the aux interrupt is disabled + * at the keyboard controller level, at most one aux interrupt + * may have already been pending and a data byte is in the + * output buffer; throw it away. Note that the second argument + * to `empty_aux_buffer()' is zero, so that the call will just + * flush the internal queue. + * `psmintr()' will be invoked after `splx()' if an interrupt is + * pending; it will see no data and returns immediately. + */ + empty_aux_buffer(sc->kbdc, 0); /* flush the queue */ + read_aux_data_no_wait(sc->kbdc); /* throw away data if any */ + sc->inputbytes = 0; + splx(s); - return TRUE; + return 0; } static int -psmread(dev_t dev, struct uio *uio, int flag) +unblock_mouse_data(struct psm_softc *sc, int c) { - register struct psm_softc *sc = psm_softc[PSM_UNIT(dev)]; - unsigned int length; - int error; - int s; - int i; + int error = 0; - /* block until mouse activity occured */ - s = spltty(); - if ((sc->outputbytes <= 0) && (sc->queue.count <= 0)) { - while (sc->queue.count <= 0) { - if (PSM_NBLOCKIO(dev)) { - splx(s); - return (EWOULDBLOCK); - } - sc->state |= PSM_ASLP; - error = tsleep((caddr_t) sc, PZERO | PCATCH, "psmread", 0); - sc->state &= ~PSM_ASLP; - if (error) { - splx(s); - return (error); - } - } - } + /* + * We may have seen a part of status data during `set_mouse_XXX()'. + * they have been queued; flush it. + */ + empty_aux_buffer(sc->kbdc, 0); - if (sc->outputbytes >= uio->uio_resid) { - /* nothing to be done */ - } else { - if (sc->outputbytes > 0) { - bcopy(&sc->opacket[sc->outputhead], sc->opacket, - sc->outputbytes); - } - sc->outputhead = 0; - for (i = sc->queue.head; sc->queue.count > 0; - i = (i + 1) % PSM_BUFSIZE, --sc->queue.count) { - if (!(*sc->mkpacket) (&sc->opacket[sc->outputbytes], - &sc->outputbytes, PSM_BUFSIZE, &sc->queue.buf[i])) - break; - } - sc->queue.head = i; + /* restore ports and interrupt */ + if (!set_controller_command_byte(sc->kbdc, + kbdc_get_device_mask(sc->kbdc), + c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { + /* CONTROLLER ERROR; this is serious, we may have + * been left with the inaccessible keyboard and + * the disabled mouse interrupt. + */ + error = EIO; } - /* allow interrupts again */ - splx(s); - - /* copy data to user process */ - length = min(sc->outputbytes, uio->uio_resid); - error = uiomove(&sc->opacket[sc->outputhead], length, uio); - if (error) - return (error); - sc->outputhead += length; - sc->outputbytes -= length; - - return (error); + kbdc_lock(sc->kbdc, FALSE); + return error; } static int @@ -1302,7 +1349,11 @@ psmioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p) struct psm_softc *sc = psm_softc[PSM_UNIT(dev)]; mousemode_t mode; mousestatus_t status; - packetfunc_t func; +#if (defined(MOUSE_GETVARS)) + mousevar_t *var; +#endif + mousedata_t *data; + int stat[3]; int command_byte; int error = 0; int s; @@ -1311,166 +1362,233 @@ psmioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p) switch (cmd) { case MOUSE_GETHWINFO: - *(mousehw_t *) addr = sc->hw; + s = spltty(); + *(mousehw_t *)addr = sc->hw; + if (sc->mode.level == PSM_LEVEL_BASE) + ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC; + splx(s); break; case MOUSE_GETMODE: - *(mousemode_t *) addr = sc->mode; - if (sc->mode.resolution >= 0) - ((mousemode_t *) addr)->resolution = sc->mode.resolution + 1; + s = spltty(); + *(mousemode_t *)addr = sc->mode; + ((mousemode_t *)addr)->resolution = + MOUSE_RES_LOW - sc->mode.resolution; + switch (sc->mode.level) { + case PSM_LEVEL_BASE: + ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2; + ((mousemode_t *)addr)->packetsize = MOUSE_PS2_PACKETSIZE; + break; + case PSM_LEVEL_STANDARD: + ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE; + ((mousemode_t *)addr)->packetsize = MOUSE_SYS_PACKETSIZE; + ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK; + ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC; + break; + case PSM_LEVEL_NATIVE: + /* FIXME: this isn't quite correct... XXX */ + ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2; + break; + } + splx(s); break; case MOUSE_SETMODE: - mode = *(mousemode_t *) addr; - if (mode.rate == 0) { + mode = *(mousemode_t *)addr; + /* adjust and validate parameters. */ + if (mode.rate > UCHAR_MAX) + return EINVAL; + if (mode.rate == 0) mode.rate = sc->dflt_mode.rate; - } else if (mode.rate > 0) { - mode.rate = min(mode.rate, PSMD_MAX_RATE); - } else { /* mode.rate < 0 */ - mode.rate = sc->mode.rate; - } - if (mode.resolution == 0) { + else if (mode.rate == -1) + /* don't change the current setting */ + ; + else if (mode.rate < 0) + return EINVAL; + if (mode.resolution >= UCHAR_MAX) + return EINVAL; + if (mode.resolution >= 200) + mode.resolution = MOUSE_RES_HIGH; + else if (mode.resolution >= 100) + mode.resolution = MOUSE_RES_MEDIUMHIGH; + else if (mode.resolution >= 50) + mode.resolution = MOUSE_RES_MEDIUMLOW; + else if (mode.resolution > 0) + mode.resolution = MOUSE_RES_LOW; + if (mode.resolution == MOUSE_RES_DEFAULT) mode.resolution = sc->dflt_mode.resolution; - } else if (mode.resolution > 0) { - mode.resolution = min(mode.resolution - 1, PSMD_MAX_RESOLUTION); - } else { /* mode.resolution < 0 */ - mode.resolution = sc->mode.resolution; - } -#ifdef PSM_EMULATION - switch (mode.protocol) { - case MOUSE_PROTO_MS: - func = mkms; - break; - case MOUSE_PROTO_LOGIMOUSEMAN: - func = mkman; - break; - case MOUSE_PROTO_MSC: - func = mkmsc; - break; - case MOUSE_PROTO_MM: - func = mkmm; - break; - case MOUSE_PROTO_PS2: - func = mkps2; - break; - default: - error = EINVAL; - func = (packetfunc_t) NULL; - break; - } - if (error) - break; -#else - mode.protocol = sc->mode.protocol; -#endif /* PSM_EMULATION */ - if (mode.accelfactor < 0) { - error = EINVAL; - break; - } + else if (mode.resolution == -1) + /* don't change the current setting */ + ; + else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */ + mode.resolution = MOUSE_RES_LOW - mode.resolution; + if (mode.level == -1) + /* don't change the current setting */ + mode.level = sc->mode.level; + else if ((mode.level < PSM_LEVEL_MIN) || (mode.level > PSM_LEVEL_MAX)) + return EINVAL; + if (mode.accelfactor == -1) + /* don't change the current setting */ + mode.accelfactor = sc->mode.accelfactor; + else if (mode.accelfactor < 0) + return EINVAL; /* don't allow anybody to poll the keyboard controller */ - if (!kbdc_lock(sc->kbdc, TRUE)) { - error = EIO; - break; - } - - /* temporalily disable the keyboard */ - s = spltty(); - command_byte = get_controller_command_byte(sc->kbdc); - if ((command_byte == -1) - || !set_controller_command_byte(sc->kbdc, - kbdc_get_device_mask(sc->kbdc), - KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT - | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) { - /* this is CONTROLLER ERROR; I don't know how to recover - * from this error. - */ - kbdc_lock(sc->kbdc, FALSE); - splx(s); - log(LOG_ERR, "psm%d: failed to set the command byte (psmioctl).\n", - PSM_UNIT(dev)); - error = EIO; - break; - } - /* - * The device may be in the middle of status data transmission. - * The transmission will be interrupted, thus, incomplete status - * data must be discarded. Although the aux interrupt is disabled - * at the keyboard controller level, at most one aux interrupt - * may have already been pending and a data byte is in the - * output buffer; throw it away. Note that the second argument - * to `empty_aux_buffer()' is zero, so that the call will just - * flush the internal queue. - * `psmintr()' will be invoked after `splx()' if an interrupt is - * pending; it will see no data and returns immediately. - */ - empty_aux_buffer(sc->kbdc, 0); /* flush the queue */ - read_aux_data_no_wait(sc->kbdc); /* throw away data if any */ - sc->inputbytes = 0; - splx(s); + error = block_mouse_data(sc, &command_byte); + if (error) + return error; + /* set mouse parameters */ if (mode.rate > 0) mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate); if (mode.resolution >= 0) mode.resolution = set_mouse_resolution(sc->kbdc, mode.resolution); - - /* - * We may have seen a part of status data, which is queued, - * during `set_mouse_XXX()'; flush it. - */ - empty_aux_buffer(sc->kbdc, 0); - - /* restore ports and interrupt */ - if (!set_controller_command_byte(sc->kbdc, - kbdc_get_device_mask(sc->kbdc), - command_byte & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) { - /* CONTROLLER ERROR; this is serious, we may have - * been left with the unaccessible keyboard and - * the disabled mouse interrupt. - */ - kbdc_lock(sc->kbdc, FALSE); - log(LOG_ERR, "psm%d: failed to re-enable " - "the aux port and int (psmioctl).\n", PSM_UNIT(dev)); - error = EIO; - break; - } + set_mouse_scaling(sc->kbdc, 1); + get_mouse_status(sc->kbdc, stat, 0, 3); - sc->mode = mode; -#ifdef PSM_EMULATION - sc->mkpacket = func; - sc->outputbytes = 0; - sc->outputhead = 0; -#endif /* PSM_EMULATION */ - kbdc_lock(sc->kbdc, FALSE); + s = spltty(); + sc->mode.rate = mode.rate; + sc->mode.resolution = mode.resolution; + sc->mode.accelfactor = mode.accelfactor; + sc->mode.level = mode.level; + splx(s); + + unblock_mouse_data(sc, command_byte); + break; + case MOUSE_GETLEVEL: + *(int *)addr = sc->mode.level; break; - case MOUSEIOCREAD: /* FIXME:XXX this should go... */ - error = EINVAL; + case MOUSE_SETLEVEL: + if ((*(int *)addr < PSM_LEVEL_MIN) || (*(int *)addr > PSM_LEVEL_MAX)) + return EINVAL; + sc->mode.level = *(int *)addr; break; - case MOUSE_GETSTATE: + case MOUSE_GETSTATUS: s = spltty(); - if (sc->queue.count > 0) { - status = sc->queue.buf[sc->queue.head]; - sc->queue.head = (sc->queue.head + 1) % PSM_BUFSIZE; - --sc->queue.count; - } else { - status.button = status.obutton = sc->button; - status.dx = status.dy = 0; - } + status = sc->status; + sc->status.flags = 0; + sc->status.obutton = sc->status.button; + sc->status.button = 0; + sc->status.dx = 0; + sc->status.dy = 0; + sc->status.dz = 0; splx(s); + *(mousestatus_t *)addr = status; + break; - *(mousestatus_t *) addr = status; +#if (defined(MOUSE_GETVARS)) + case MOUSE_GETVARS: + var = (mousevar_t *)addr; + bzero(var, sizeof(*var)); + s = spltty(); + var->var[0] = MOUSE_VARS_PS2_SIG; + var->var[1] = sc->config; + var->var[2] = sc->flags; + splx(s); break; - default: - error = EINVAL; + case MOUSE_SETVARS: + return ENODEV; +#endif /* MOUSE_GETVARS */ + + case MOUSE_READSTATE: + case MOUSE_READDATA: + data = (mousedata_t *)addr; + if (data->len > sizeof(data->buf)/sizeof(data->buf[0])) + return EINVAL; + + error = block_mouse_data(sc, &command_byte); + if (error) + return error; + if ((data->len = get_mouse_status(sc->kbdc, data->buf, + (cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0) + error = EIO; + unblock_mouse_data(sc, command_byte); + break; + +#if (defined(MOUSE_SETRESOLUTION)) + case MOUSE_SETRESOLUTION: + mode.resolution = *(int *)addr; + if (mode.resolution >= UCHAR_MAX) + return EINVAL; + else if (mode.resolution >= 200) + mode.resolution = MOUSE_RES_HIGH; + else if (mode.resolution >= 100) + mode.resolution = MOUSE_RES_MEDIUMHIGH; + else if (mode.resolution >= 50) + mode.resolution = MOUSE_RES_MEDIUMLOW; + else if (mode.resolution > 0) + mode.resolution = MOUSE_RES_LOW; + if (mode.resolution == MOUSE_RES_DEFAULT) + mode.resolution = sc->dflt_mode.resolution; + else if (mode.resolution == -1) + mode.resolution = sc->mode.resolution; + else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */ + mode.resolution = MOUSE_RES_LOW - mode.resolution; + + error = block_mouse_data(sc, &command_byte); + if (error) + return error; + sc->mode.resolution = set_mouse_resolution(sc->kbdc, mode.resolution); + if (sc->mode.resolution != mode.resolution) + error = EIO; + unblock_mouse_data(sc, command_byte); break; +#endif /* MOUSE_SETRESOLUTION */ + +#if (defined(MOUSE_SETRATE)) + case MOUSE_SETRATE: + mode.rate = *(int *)addr; + if (mode.rate > UCHAR_MAX) + return EINVAL; + if (mode.rate == 0) + mode.rate = sc->dflt_mode.rate; + else if (mode.rate < 0) + mode.rate = sc->mode.rate; + + error = block_mouse_data(sc, &command_byte); + if (error) + return error; + sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate); + if (sc->mode.rate != mode.rate) + error = EIO; + unblock_mouse_data(sc, command_byte); + break; +#endif /* MOUSE_SETRATE */ + +#if (defined(MOUSE_SETSCALING)) + case MOUSE_SETSCALING: + if ((*(int *)addr <= 0) || (*(int *)addr > 2)) + return EINVAL; + + error = block_mouse_data(sc, &command_byte); + if (error) + return error; + if (!set_mouse_scaling(sc->kbdc, *(int *)addr)) + error = EIO; + unblock_mouse_data(sc, command_byte); + break; +#endif /* MOUSE_SETSCALING */ + +#if (defined(MOUSE_GETHWID)) + case MOUSE_GETHWID: + error = block_mouse_data(sc, &command_byte); + if (error) + return error; + sc->hw.hwid = get_aux_id(sc->kbdc); + *(int *)addr = sc->hw.hwid; + unblock_mouse_data(sc, command_byte); + break; +#endif /* MOUSE_GETHWID */ + + default: + return ENOTTY; } - /* Return error code */ - return (error); + return error; } void @@ -1482,7 +1600,8 @@ psmintr(int unit) */ static int butmap[8] = { 0, - MOUSE_BUTTON1DOWN, MOUSE_BUTTON3DOWN, + MOUSE_BUTTON1DOWN, + MOUSE_BUTTON3DOWN, MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, MOUSE_BUTTON2DOWN, MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, @@ -1490,9 +1609,10 @@ psmintr(int unit) MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN }; register struct psm_softc *sc = psm_softc[unit]; - mousestatus_t *ms; + mousestatus_t ms; + int x, y, z; int c; - int x, y; + int l; /* read until there is nothing to read */ while((c = read_aux_data_no_wait(sc->kbdc)) != -1) { @@ -1501,95 +1621,142 @@ psmintr(int unit) if ((sc->state & PSM_OPEN) == 0) continue; - /* - * FIXME: there seems no way to reliably - * re-synchronize with the PS/2 mouse once we are out of sync. Sure, - * there is a sync bit in the first data byte, but the second and the - * third bytes may have these bits on (oh, it's not functioning as - * sync bit then!). There need to be two consequtive bytes with this - * bit off to re-sync. (This can be done if the user clicks buttons - * without moving the mouse?) - */ - if (sc->inputbytes == 0) { -#ifdef PSM_CHECKSYNC - if ((c & MOUSE_PS2_SYNCMASK) == MOUSE_PS2_SYNC) - sc->ipacket[sc->inputbytes++] = c; - else - log(LOG_DEBUG, "psmintr: sync. bit is off (%04x).\n", c); -#else - sc->ipacket[sc->inputbytes++] = c; -#endif /* PSM_CHECKSYNC */ - } else { - sc->ipacket[sc->inputbytes++] = c; - if (sc->inputbytes >= MOUSE_PS2_PACKETSIZE) { - if (sc->queue.count >= PSM_BUFSIZE) { - /* no room in the queue */ - sc->inputbytes = 0; - return; - } -#if 0 - x = (sc->ipacket[0] & MOUSE_PS2_XOVERFLOW) ? - ((sc->ipacket[0] & MOUSE_PS2_XNEG) ? -256 : 255) : - ((sc->ipacket[0] & MOUSE_PS2_XNEG) ? - sc->ipacket[1] - 256 : sc->ipacket[1]); - y = (sc->ipacket[0] & MOUSE_PS2_YOVERFLOW) ? - ((sc->ipacket[0] & MOUSE_PS2_YNEG) ? -256 : 255) : - ((sc->ipacket[0] & MOUSE_PS2_YNEG) ? - sc->ipacket[2] - 256 : sc->ipacket[2]); -#else - /* it seems OK to ignore the OVERFLOW bits... */ - x = (sc->ipacket[0] & MOUSE_PS2_XNEG) ? - sc->ipacket[1] - 256 : sc->ipacket[1]; - y = (sc->ipacket[0] & MOUSE_PS2_YNEG) ? - sc->ipacket[2] - 256 : sc->ipacket[2]; -#endif - if (sc->mode.accelfactor >= 1) { - if (x != 0) { - x = x * x / sc->mode.accelfactor; - if (x == 0) - x = 1; - if (sc->ipacket[0] & MOUSE_PS2_XNEG) - x = -x; - } - if (y != 0) { - y = y * y / sc->mode.accelfactor; - if (y == 0) - y = 1; - if (sc->ipacket[0] & MOUSE_PS2_YNEG) - y = -y; - } - } - - /* - * FIXME:XXX - * we shouldn't store data if no movement and - * no button status change is detected? - */ - ms = &sc->queue.buf[sc->queue.tail]; - ms->dx = x; - ms->dy = y; - ms->obutton = sc->button; /* previous button state */ - sc->button = ms->button = /* latest button state */ - butmap[sc->ipacket[0] & MOUSE_PS2_BUTTONS] - | ((sc->ipacket[0] & MOUSE_PS2_BUTTON4UP) - ? 0 : MOUSE_BUTTON4DOWN); + /* + * Check sync bits. We check for overflow bits and the bit 3 + * for most mice. True, the code doesn't work if overflow + * condition occurs. But we expect it rarely happens... + */ + if ((sc->inputbytes == 0) + && ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1])) { + log(LOG_DEBUG, "psmintr: out of sync (%04x != %04x).\n", + c & sc->mode.syncmask[0], sc->mode.syncmask[1]); + continue; + } + + sc->ipacket[sc->inputbytes++] = c; + if (sc->inputbytes < sc->mode.packetsize) + continue; + #if 0 - if ((verbose >= 2) - && ((sc->ipacket[0] & MOUSE_PS2_BUTTON4UP) == 0)) - log(LOG_DEBUG, "psm%d: button 4 down (%04x) (psmintr)\n", - unit, sc->ipacket[0]); + log(LOG_DEBUG, "psmintr: %02x %02x %02x %02x %02x %02x\n", + sc->ipacket[0], sc->ipacket[1], sc->ipacket[2], + sc->ipacket[3], sc->ipacket[4], sc->ipacket[5]); #endif - sc->queue.tail = (sc->queue.tail + 1) % PSM_BUFSIZE; - ++sc->queue.count; - sc->inputbytes = 0; - - if (sc->state & PSM_ASLP) { - sc->state &= ~PSM_ASLP; - wakeup((caddr_t) sc); - } - selwakeup(&sc->rsel); + + c = sc->ipacket[0]; + + /* + * A kludge for Kensington device! + * The MSB of the horizontal count appears to be stored in + * a strange place. This kludge doesn't affect other mice + * because the bit is the overflow bit which is, in most cases, + * expected to be zero when we reach here. XXX + */ + sc->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0; + + /* ignore the overflow bits... */ + x = (c & MOUSE_PS2_XNEG) ? sc->ipacket[1] - 256 : sc->ipacket[1]; + y = (c & MOUSE_PS2_YNEG) ? sc->ipacket[2] - 256 : sc->ipacket[2]; + z = 0; + ms.obutton = sc->button; /* previous button state */ + ms.button = butmap[c & MOUSE_PS2_BUTTONS]; + + switch (sc->hw.model) { + + case MOUSE_MODEL_INTELLI: + case MOUSE_MODEL_NET: + /* wheel data is in the fourth byte */ + z = (char)sc->ipacket[3]; + break; + + case MOUSE_MODEL_MOUSEMANPLUS: + if ((c & ~MOUSE_PS2_BUTTONS) == 0xc8) { + /* the extended data packet encodes button and wheel events */ + x = y = 0; + z = (sc->ipacket[1] & MOUSE_PS2PLUS_ZNEG) + ? (sc->ipacket[2] & 0x0f) - 16 : (sc->ipacket[2] & 0x0f); + ms.button |= (sc->ipacket[2] & MOUSE_PS2PLUS_BUTTON4DOWN) + ? MOUSE_BUTTON4DOWN : 0; + } else { + /* preserve button states */ + ms.button |= ms.obutton & MOUSE_EXTBUTTONS; + } + break; + + case MOUSE_MODEL_GLIDEPOINT: + /* `tapping' action */ + ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : MOUSE_BUTTON4DOWN; + break; + + case MOUSE_MODEL_NETSCROLL: + /* three addtional bytes encode button and wheel events */ + ms.button |= (sc->ipacket[3] & MOUSE_PS2_BUTTON3DOWN) + ? MOUSE_BUTTON4DOWN : 0; + z = (sc->ipacket[3] & MOUSE_PS2_XNEG) + ? sc->ipacket[4] - 256 : sc->ipacket[4]; + break; + + case MOUSE_MODEL_THINK: + /* the fourth button state in the first byte */ + ms.button |= (c & MOUSE_PS2_TAP) ? MOUSE_BUTTON4DOWN : 0; + break; + + case MOUSE_MODEL_GENERIC: + default: + break; + } + + /* scale values */ + if (sc->mode.accelfactor >= 1) { + if (x != 0) { + x = x * x / sc->mode.accelfactor; + if (x == 0) + x = 1; + if (c & MOUSE_PS2_XNEG) + x = -x; + } + if (y != 0) { + y = y * y / sc->mode.accelfactor; + if (y == 0) + y = 1; + if (c & MOUSE_PS2_YNEG) + y = -y; } } + + ms.dx = x; + ms.dy = y; + ms.dz = z; + ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0) + | (ms.obutton ^ ms.button); + + if (sc->mode.level < PSM_LEVEL_NATIVE) + sc->inputbytes = tame_mouse(sc, &ms, sc->ipacket); + + sc->status.flags |= ms.flags; + sc->status.dx += ms.dx; + sc->status.dy += ms.dy; + sc->status.dz += ms.dz; + sc->status.button = ms.button; + sc->button = ms.button; + + /* queue data */ + if (sc->queue.count + sc->inputbytes < sizeof(sc->queue.buf)) { + l = min(sc->inputbytes, sizeof(sc->queue.buf) - sc->queue.tail); + bcopy(&sc->ipacket[0], &sc->queue.buf[sc->queue.tail], l); + if (sc->inputbytes > l) + bcopy(&sc->ipacket[l], &sc->queue.buf[0], sc->inputbytes - l); + sc->queue.tail = + (sc->queue.tail + sc->inputbytes) % sizeof(sc->queue.buf); + sc->queue.count += sc->inputbytes; + } + sc->inputbytes = 0; + + if (sc->state & PSM_ASLP) { + sc->state &= ~PSM_ASLP; + wakeup((caddr_t) sc); + } + selwakeup(&sc->rsel); } } @@ -1603,7 +1770,7 @@ psmpoll(dev_t dev, int events, struct proc *p) /* Return true if a mouse event available */ s = spltty(); if (events & (POLLIN | POLLRDNORM)) - if ((sc->outputbytes > 0) || (sc->queue.count > 0)) + if (sc->queue.count > 0) revents |= events & (POLLIN | POLLRDNORM); else selrecord(p, &sc->rsel); @@ -1613,6 +1780,254 @@ psmpoll(dev_t dev, int events, struct proc *p) return (revents); } +/* vender/model specific routines */ + +static int mouse_id_proc1(KBDC kbdc, int res, int scale, int *status) +{ + if (set_mouse_resolution(kbdc, res) != res) + return FALSE; + if (set_mouse_scaling(kbdc, scale) + && set_mouse_scaling(kbdc, scale) + && set_mouse_scaling(kbdc, scale) + && (get_mouse_status(kbdc, status, 0, 3) >= 3)) + return TRUE; + return FALSE; +} + +#if notyet +/* Logitech MouseMan Cordless II */ +static int +enable_lcordless(struct psm_softc *sc) +{ + int status[3]; + int ch; + + if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 2, status)) + return FALSE; + if (status[1] == PSMD_RES_HIGH) + return FALSE; + ch = (status[0] & 0x07) - 1; /* channel # */ + if ((ch <= 0) || (ch > 4)) + return FALSE; + /* + * status[1]: always one? + * status[2]: battery status? (0-100) + */ + return TRUE; +} +#endif /* notyet */ + +/* Genius NetScroll Mouse */ +static int +enable_groller(struct psm_softc *sc) +{ + int status[3]; + + /* + * The special sequence to enable the fourth button and the + * roller. Immediately after this sequence check status bytes. + * if the mouse is NetScroll, the second and the third bytes are + * '3' and 'D'. + */ + + /* + * If the mouse is an ordinary PS/2 mouse, the status bytes should + * look like the following. + * + * byte 1 bit 7 always 0 + * bit 6 stream mode (0) + * bit 5 disabled (0) + * bit 4 1:1 scaling (0) + * bit 3 always 0 + * bit 0-2 button status + * byte 2 resolution (PSMD_RES_HIGH) + * byte 3 report rate (?) + */ + + if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status)) + return FALSE; + if ((status[1] != '3') || (status[2] != 'D')) + return FALSE; + /* FIXME!! */ + sc->hw.buttons = get_mouse_buttons(sc->kbdc); + sc->hw.buttons = 4; + return TRUE; +} + +/* Genius NetMouse/NetMouse Pro */ +static int +enable_gmouse(struct psm_softc *sc) +{ + int status[3]; + + /* + * The special sequence to enable the middle, "rubber" button. + * Immediately after this sequence check status bytes. + * if the mouse is NetMouse, NetMouse Pro, or ASCII MIE Mouse, + * the second and the third bytes are '3' and 'U'. + * NOTE: NetMouse reports that it has three buttons although it has + * two buttons and a rubber button. NetMouse Pro and MIE Mouse + * say they have three buttons too and they do have a button on the + * side... + */ + if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status)) + return FALSE; + if ((status[1] != '3') || (status[2] != 'U')) + return FALSE; + return TRUE; +} + +/* ALPS GlidePoint */ +static int +enable_aglide(struct psm_softc *sc) +{ + int status[3]; + + /* + * The special sequence to obtain ALPS GlidePoint specific + * information. Immediately after this sequence, status bytes will + * contain something interesting. + * NOTE: ALPS produces several models of GlidePoint. Some of those + * do not respond to this sequence, thus, cannot be detected this way. + */ + if (!mouse_id_proc1(sc->kbdc, PSMD_RES_LOW, 2, status)) + return FALSE; + if ((status[0] & 0x10) || (status[1] == PSMD_RES_LOW)) + return FALSE; + return TRUE; +} + +/* Kensington ThinkingMouse/Trackball */ +static int +enable_kmouse(struct psm_softc *sc) +{ + static unsigned char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 }; + KBDC kbdc = sc->kbdc; + int status[3]; + int id1; + int id2; + int i; + + id1 = get_aux_id(kbdc); + if (set_mouse_sampling_rate(kbdc, 10) != 10) + return FALSE; + /* + * The device is now in the native mode? It returns a different + * ID value... + */ + id2 = get_aux_id(kbdc); + if ((id1 == id2) || (id2 != 2)) + return FALSE; + + if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW) + return FALSE; +#if PSM_DEBUG >= 2 + /* at this point, resolution is LOW, sampling rate is 10/sec */ + if (get_mouse_status(kbdc, status, 0, 3) < 3) + return FALSE; +#endif + + /* + * The special sequence to enable the third and fourth buttons. + * Otherwise they behave like the first and second buttons. + */ + for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) { + if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) + return FALSE; + } + + /* + * At this point, the device is using default resolution and + * sampling rate for the native mode. + */ + if (get_mouse_status(kbdc, status, 0, 3) < 3) + return FALSE; + if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1])) + return FALSE; + + /* the device appears be enabled by this sequence, diable it for now */ + disable_aux_dev(kbdc); + empty_aux_buffer(kbdc, 5); + + return TRUE; +} + +/* Logitech MouseMan+/FirstMouse+ */ +static int +enable_mmanplus(struct psm_softc *sc) +{ + static char res[] = { + -1, PSMD_RES_LOW, PSMD_RES_HIGH, PSMD_RES_MEDIUM_HIGH, + PSMD_RES_MEDIUM_LOW, -1, PSMD_RES_HIGH, PSMD_RES_MEDIUM_LOW, + PSMD_RES_MEDIUM_HIGH, PSMD_RES_HIGH, + }; + KBDC kbdc = sc->kbdc; + int data[3]; + int i; + + /* the special sequence to enable the fourth button and the roller. */ + for (i = 0; i < sizeof(res)/sizeof(res[0]); ++i) { + if (res[i] < 0) { + if (!set_mouse_scaling(kbdc, 1)) + return FALSE; + } else { + if (set_mouse_resolution(kbdc, res[i]) != res[i]) + return FALSE; + } + } + + if (get_mouse_status(kbdc, data, 1, 3) < 3) + return FALSE; + + /* + * MouseMan+ and FirstMouse+ return following data. + * + * byte 1 0xc8 + * byte 2 ?? (MouseMan+:0xc2, FirstMouse+:0xc6) + * byte 3 model ID? MouseMan+:0x50, FirstMouse+:0x51 + */ + if ((data[0] & ~MOUSE_PS2_BUTTONS) != 0xc8) + return FALSE; + + /* + * MouseMan+ (or FirstMouse+) is now in its native mode, in which + * the wheel and the fourth button events are encoded in the + * special data packet. The mouse may be put in the IntelliMouse mode + * if it is initialized by the IntelliMouse's method. + */ + return TRUE; +} + +/* MS IntelliMouse */ +static int +enable_msintelli(struct psm_softc *sc) +{ + /* + * Logitech MouseMan+ and FirstMouse+ will also respond to this + * probe routine and act like IntelliMouse. + */ + + static unsigned char rate[] = { 200, 100, 80, }; + KBDC kbdc = sc->kbdc; + int id; + int i; + + /* the special sequence to enable the third button and the roller. */ + for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) { + if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i]) + return FALSE; + } + /* the device will give the genuine ID only after the above sequence */ + id = get_aux_id(kbdc); + if (id != PSM_INTELLI_ID) + return FALSE; + + sc->hw.hwid = id; + sc->hw.buttons = 3; + + return TRUE; +} + static int psm_devsw_installed = FALSE; static void diff --git a/sys/i386/isa/syscons.c b/sys/i386/isa/syscons.c index 9e6353c..56feb74 100644 --- a/sys/i386/isa/syscons.c +++ b/sys/i386/isa/syscons.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.240 1997/11/25 12:44:44 sos Exp $ + * $Id: syscons.c,v 1.241 1997/12/06 13:23:26 bde Exp $ */ #include "sc.h" @@ -49,6 +49,7 @@ #include <machine/clock.h> #include <machine/cons.h> #include <machine/console.h> +#include <machine/mouse.h> #include <machine/md_var.h> #include <machine/psl.h> #include <machine/frame.h> @@ -153,6 +154,8 @@ static char vgaregs[MODE_PARAM_SIZE]; static char vgaregs2[MODE_PARAM_SIZE]; static int rows_offset = 1; static char *cut_buffer; +static int mouse_level = 0; /* sysmouse protocol level */ +static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; static u_short mouse_and_mask[16] = { 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, @@ -249,8 +252,14 @@ static void set_font_mode(u_char *buf); static void set_normal_mode(u_char *buf); static void set_destructive_cursor(scr_stat *scp); static void set_mouse_pos(scr_stat *scp); +static int skip_spc_right(scr_stat *scp, u_short *p); +static int skip_spc_left(scr_stat *scp, u_short *p); +static void mouse_cut(scr_stat *scp); static void mouse_cut_start(scr_stat *scp); static void mouse_cut_end(scr_stat *scp); +static void mouse_cut_word(scr_stat *scp); +static void mouse_cut_line(scr_stat *scp); +static void mouse_cut_extend(scr_stat *scp); static void mouse_paste(scr_stat *scp); static void draw_mouse_image(scr_stat *scp); static void remove_mouse_image(scr_stat *scp); @@ -785,6 +794,8 @@ scopen(dev_t dev, int flag, int mode, struct proc *p) scparam(tp, &tp->t_termios); ttsetwater(tp); (*linesw[tp->t_line].l_modem)(tp, 1); + if (minor(dev) == SC_MOUSE) + mouse_level = 0; /* XXX */ } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) @@ -925,11 +936,12 @@ int scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) { int error; - u_int i = 0; + u_int i; struct tty *tp; scr_stat *scp; u_short *usp; char *mp; + int s; tp = scdevtotty(dev); if (!tp) @@ -1047,10 +1059,22 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) case CONS_MOUSECTL: /* control mouse arrow */ { + /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ + static butmap[8] = { + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP + | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON1UP, + 0, + }; mouse_info_t *mouse = (mouse_info_t*)data; if (!crtc_vga) - return ENXIO; + return ENODEV; switch (mouse->operation) { case MOUSE_MODE: @@ -1100,26 +1124,55 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) case MOUSE_GETINFO: mouse->u.data.x = scp->mouse_xpos; mouse->u.data.y = scp->mouse_ypos; + mouse->u.data.z = 0; mouse->u.data.buttons = scp->mouse_buttons; break; case MOUSE_ACTION: + case MOUSE_MOTION_EVENT: /* this should maybe only be settable from /dev/consolectl SOS */ /* send out mouse event on /dev/sysmouse */ + + mouse_status.dx += mouse->u.data.x; + mouse_status.dy += mouse->u.data.y; + mouse_status.dz += mouse->u.data.z; + if (mouse->operation == MOUSE_ACTION) + mouse_status.button = mouse->u.data.buttons; + mouse_status.flags |= + ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? + MOUSE_POSCHANGED : 0) + | (mouse_status.obutton ^ mouse_status.button); + if (cur_console->status & MOUSE_ENABLED) cur_console->status |= MOUSE_VISIBLE; + if ((MOUSE_TTY)->t_state & TS_ISOPEN) { - u_char buf[5]; + u_char buf[MOUSE_SYS_PACKETSIZE]; int j; - buf[0] = 0x80 | ((~mouse->u.data.buttons) & 0x07); - buf[1] = (mouse->u.data.x & 0x1fe >> 1); - buf[3] = (mouse->u.data.x & 0x1ff) - buf[1]; - buf[2] = -(mouse->u.data.y & 0x1fe >> 1); - buf[4] = -(mouse->u.data.y & 0x1ff) - buf[2]; - for (j=0; j<5; j++) + /* the first five bytes are compatible with MouseSystems' */ + buf[0] = MOUSE_MSC_SYNC + | butmap[mouse_status.button & MOUSE_STDBUTTONS]; + j = imax(imin(mouse->u.data.x, 255), -256); + buf[1] = j >> 1; + buf[3] = j - buf[1]; + j = -imax(imin(mouse->u.data.y, 255), -256); + buf[2] = j >> 1; + buf[4] = j - buf[2]; + for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++) + (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); + if (mouse_level >= 1) { /* extended part */ + j = imax(imin(mouse->u.data.z, 127), -128); + buf[5] = (j >> 1) & 0x7f; + buf[6] = (j - (j >> 1)) & 0x7f; + /* buttons 4-10 */ + buf[7] = (~mouse_status.button >> 3) & 0x7f; + for (j = MOUSE_MSC_PACKETSIZE; + j < MOUSE_SYS_PACKETSIZE; j++) (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); + } } + if (cur_console->mouse_signal) { cur_console->mouse_buttons = mouse->u.data.buttons; /* has controlling process died? */ @@ -1132,26 +1185,117 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) else psignal(cur_console->mouse_proc, cur_console->mouse_signal); } - else { + else if (mouse->operation == MOUSE_ACTION) { /* process button presses */ - if (cur_console->mouse_buttons != mouse->u.data.buttons) { + if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && + !(cur_console->status & UNKNOWN_MODE)) { cur_console->mouse_buttons = mouse->u.data.buttons; - if (!(cur_console->status & UNKNOWN_MODE)) { - if (cur_console->mouse_buttons & LEFT_BUTTON) - mouse_cut_start(cur_console); - else - mouse_cut_end(cur_console); - if (cur_console->mouse_buttons & RIGHT_BUTTON || - cur_console->mouse_buttons & MIDDLE_BUTTON) - mouse_paste(cur_console); - } + if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) + mouse_cut_start(cur_console); + else + mouse_cut_end(cur_console); + if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN || + cur_console->mouse_buttons & MOUSE_BUTTON3DOWN) + mouse_paste(cur_console); } } + if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { - cur_console->mouse_xpos += mouse->u.data.x; - cur_console->mouse_ypos += mouse->u.data.y; + cur_console->mouse_xpos += mouse->u.data.x; + cur_console->mouse_ypos += mouse->u.data.y; set_mouse_pos(cur_console); } + + break; + + case MOUSE_BUTTON_EVENT: + if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) + return EINVAL; + if (mouse->u.event.value < 0) + return EINVAL; + + if (mouse->u.event.value > 0) { + cur_console->mouse_buttons |= mouse->u.event.id; + mouse_status.button |= mouse->u.event.id; + } else { + cur_console->mouse_buttons &= ~mouse->u.event.id; + mouse_status.button &= ~mouse->u.event.id; + } + mouse_status.flags |= + ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? + MOUSE_POSCHANGED : 0) + | (mouse_status.obutton ^ mouse_status.button); + + if (cur_console->status & MOUSE_ENABLED) + cur_console->status |= MOUSE_VISIBLE; + + if ((MOUSE_TTY)->t_state & TS_ISOPEN) { + u_char buf[8]; + int i; + + buf[0] = MOUSE_MSC_SYNC + | butmap[mouse_status.button & MOUSE_STDBUTTONS]; + buf[7] = (~mouse_status.button >> 3) & 0x7f; + buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; + for (i = 0; + i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE + : MOUSE_MSC_PACKETSIZE); i++) + (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); + } + + if (cur_console->mouse_signal) { + if (cur_console->mouse_proc && + (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ + cur_console->mouse_signal = 0; + cur_console->mouse_proc = NULL; + cur_console->mouse_pid = 0; + } + else + psignal(cur_console->mouse_proc, cur_console->mouse_signal); + break; + } + + if (cur_console->status & UNKNOWN_MODE) + break; + + switch (mouse->u.event.id) { + case MOUSE_BUTTON1DOWN: + switch (mouse->u.event.value % 4) { + case 0: /* up */ + mouse_cut_end(cur_console); + break; + case 1: + mouse_cut_start(cur_console); + break; + case 2: + mouse_cut_word(cur_console); + break; + case 3: + mouse_cut_line(cur_console); + break; + } + break; + case MOUSE_BUTTON2DOWN: + switch (mouse->u.event.value) { + case 0: /* up */ + break; + default: + mouse_paste(cur_console); + break; + } + break; + case MOUSE_BUTTON3DOWN: + switch (mouse->u.event.value) { + case 0: /* up */ + if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)) + mouse_cut_end(cur_console); + break; + default: + mouse_cut_extend(cur_console); + break; + } + break; + } break; default: @@ -1162,6 +1306,107 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) return 0; } + /* MOUSE_XXX: /dev/sysmouse ioctls */ + case MOUSE_GETHWINFO: /* get device information */ + { + mousehw_t *hw = (mousehw_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + hw->buttons = 10; /* XXX unknown */ + hw->iftype = MOUSE_IF_SYSMOUSE; + hw->type = MOUSE_MOUSE; + hw->model = MOUSE_MODEL_GENERIC; + hw->hwid = 0; + return 0; + } + + case MOUSE_GETMODE: /* get protocol/mode */ + { + mousemode_t *mode = (mousemode_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + mode->level = mouse_level; + switch (mode->level) { + case 0: + /* at this level, sysmouse emulates MouseSystems protocol */ + mode->protocol = MOUSE_PROTO_MSC; + mode->rate = -1; /* unknown */ + mode->resolution = -1; /* unknown */ + mode->accelfactor = 0; /* disabled */ + mode->packetsize = MOUSE_MSC_PACKETSIZE; + mode->syncmask[0] = MOUSE_MSC_SYNCMASK; + mode->syncmask[1] = MOUSE_MSC_SYNC; + break; + + case 1: + /* at this level, sysmouse uses its own protocol */ + mode->protocol = MOUSE_PROTO_SYSMOUSE; + mode->rate = -1; + mode->resolution = -1; + mode->accelfactor = 0; + mode->packetsize = MOUSE_SYS_PACKETSIZE; + mode->syncmask[0] = MOUSE_SYS_SYNCMASK; + mode->syncmask[1] = MOUSE_SYS_SYNC; + break; + } + return 0; + } + + case MOUSE_SETMODE: /* set protocol/mode */ + { + mousemode_t *mode = (mousemode_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + if ((mode->level < 0) || (mode->level > 1)) + return EINVAL; + mouse_level = mode->level; + return 0; + } + + case MOUSE_GETLEVEL: /* get operation level */ + if (tp != MOUSE_TTY) + return ENOTTY; + *(int *)data = mouse_level; + return 0; + + case MOUSE_SETLEVEL: /* set operation level */ + if (tp != MOUSE_TTY) + return ENOTTY; + if ((*(int *)data < 0) || (*(int *)data > 1)) + return EINVAL; + mouse_level = *(int *)data; + return 0; + + case MOUSE_GETSTATUS: /* get accumulated mouse events */ + if (tp != MOUSE_TTY) + return ENOTTY; + s = spltty(); + *(mousestatus_t *)data = mouse_status; + mouse_status.flags = 0; + mouse_status.obutton = mouse_status.button; + mouse_status.dx = 0; + mouse_status.dy = 0; + mouse_status.dz = 0; + splx(s); + return 0; + +#if notyet + case MOUSE_GETVARS: /* get internal mouse variables */ + case MOUSE_SETVARS: /* set internal mouse variables */ + if (tp != MOUSE_TTY) + return ENOTTY; + return ENODEV; +#endif + + case MOUSE_READSTATE: /* read status from the device */ + case MOUSE_READDATA: /* read data from the device */ + if (tp != MOUSE_TTY) + return ENOTTY; + return ENODEV; + case CONS_GETINFO: /* get current (virtual) console info */ { vid_info_t *ptr = (vid_info_t*)data; @@ -1210,6 +1455,8 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) if (scp->history != NULL) i = imax(scp->history_size / scp->xsize - imax(SC_HISTORY_SIZE, scp->ysize), 0); + else + i = 0; switch (cmd & 0xff) { case M_VGA_C80x60: case M_VGA_M80x60: if (!(fonts_loaded & FONT_8)) @@ -4106,28 +4353,86 @@ set_mouse_pos(scr_stat *scp) scp->mouse_pos = scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); - if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) { - u_short *ptr; - int i = 0; - - mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); - mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); - scp->mouse_cut_end = scp->mouse_pos; - for (ptr = (scp->mouse_cut_start > scp->mouse_cut_end - ? scp->mouse_cut_end : scp->mouse_cut_start); - ptr <= (scp->mouse_cut_start > scp->mouse_cut_end - ? scp->mouse_cut_start : scp->mouse_cut_end); - ptr++) { - cut_buffer[i++] = *ptr & 0xff; - if (((ptr - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { - cut_buffer[i++] = '\n'; - } - } - cut_buffer[i] = 0x00; - } + if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) + mouse_cut(scp); } } +#define isspace(c) (((c) & 0xff) == ' ') + +static int +skip_spc_right(scr_stat *scp, u_short *p) +{ + int i; + + for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { + if (!isspace(*p)) + break; + ++p; + } + return i; +} + +static int +skip_spc_left(scr_stat *scp, u_short *p) +{ + int i; + + for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { + if (!isspace(*p)) + break; + --p; + } + return i; +} + +static void +mouse_cut(scr_stat *scp) +{ + u_short *end; + u_short *p; + int i = 0; + int j = 0; + + scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? + scp->mouse_pos + 1 : scp->mouse_pos; + end = (scp->mouse_cut_start > scp->mouse_cut_end) ? + scp->mouse_cut_start : scp->mouse_cut_end; + for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? + scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { + cut_buffer[i] = *p & 0xff; + /* remember the position of the last non-space char */ + if (!isspace(cut_buffer[i++])) + j = i; + /* trim trailing blank when crossing lines */ + if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { + cut_buffer[j++] = '\n'; + i = j; + } + } + cut_buffer[i] = '\0'; + + /* scan towards the end of the last line */ + --p; + for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { + if (!isspace(*p)) + break; + ++p; + } + /* if there is nothing but blank chars, trim them, but mark towards eol */ + if (i >= scp->xsize) { + if (scp->mouse_cut_start > scp->mouse_cut_end) + scp->mouse_cut_start = p; + else + scp->mouse_cut_end = p; + cut_buffer[j++] = '\n'; + cut_buffer[j] = '\0'; + } + + mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); + mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); +} + static void mouse_cut_start(scr_stat *scp) { @@ -4135,14 +4440,24 @@ mouse_cut_start(scr_stat *scp) if (scp->status & MOUSE_VISIBLE) { if (scp->mouse_pos == scp->mouse_cut_start && - scp->mouse_cut_start == scp->mouse_cut_end) { - cut_buffer[0] = 0x00; + scp->mouse_cut_start == scp->mouse_cut_end - 1) { + cut_buffer[0] = '\0'; remove_cutmarking(scp); - } - else { - scp->mouse_cut_start = scp->mouse_cut_end = scp->mouse_pos; + } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { + /* if the pointer is on trailing blank chars, mark towards eol */ + i = skip_spc_left(scp, scp->mouse_pos) + 1; + scp->mouse_cut_start = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; + scp->mouse_cut_end = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; + cut_buffer[0] = '\n'; + cut_buffer[1] = '\0'; + scp->status |= MOUSE_CUTTING; + } else { + scp->mouse_cut_start = scp->mouse_pos; + scp->mouse_cut_end = scp->mouse_cut_start + 1; cut_buffer[0] = *scp->mouse_cut_start & 0xff; - cut_buffer[1] = 0x00; + cut_buffer[1] = '\0'; scp->status |= MOUSE_CUTTING; } mark_all(scp); @@ -4164,6 +4479,77 @@ mouse_cut_end(scr_stat *scp) } static void +mouse_cut_word(scr_stat *scp) +{ + u_short *p; + u_short *sol; + u_short *eol; + int i; + + /* + * Because we don't have locale information in the kernel, + * we only distinguish space char and non-space chars. Punctuation + * chars, symbols and other regular chars are all treated alike. + */ + if (scp->status & MOUSE_VISIBLE) { + sol = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; + eol = sol + scp->xsize; + if (isspace(*scp->mouse_pos)) { + for (p = scp->mouse_pos; p >= sol; --p) + if (!isspace(*p)) + break; + scp->mouse_cut_start = ++p; + for (p = scp->mouse_pos; p < eol; ++p) + if (!isspace(*p)) + break; + scp->mouse_cut_end = p; + } else { + for (p = scp->mouse_pos; p >= sol; --p) + if (isspace(*p)) + break; + scp->mouse_cut_start = ++p; + for (p = scp->mouse_pos; p < eol; ++p) + if (isspace(*p)) + break; + scp->mouse_cut_end = p; + } + for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) + cut_buffer[i++] = *p & 0xff; + cut_buffer[i] = '\0'; + scp->status |= MOUSE_CUTTING; + } +} + +static void +mouse_cut_line(scr_stat *scp) +{ + u_short *p; + int i; + + if (scp->status & MOUSE_VISIBLE) { + scp->mouse_cut_start = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; + scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; + for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) + cut_buffer[i++] = *p & 0xff; + cut_buffer[i++] = '\n'; + cut_buffer[i] = '\0'; + scp->status |= MOUSE_CUTTING; + } +} + +static void +mouse_cut_extend(scr_stat *scp) +{ + if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) + && (scp->mouse_cut_start != NULL)) { + mouse_cut(scp); + scp->status |= MOUSE_CUTTING; + } +} + +static void mouse_paste(scr_stat *scp) { if (scp->status & MOUSE_VISIBLE) { @@ -4273,7 +4659,7 @@ draw_cutmarking(scr_stat *scp) /* are we outside the selected area ? */ if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? scp->mouse_cut_end : scp->mouse_cut_start) || - ptr > (scp->mouse_cut_start > scp->mouse_cut_end ? + ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? scp->mouse_cut_start : scp->mouse_cut_end)) { if (ptr != scp->cursor_pos) nch = (och & 0xff) | (*ptr & 0xff00); diff --git a/sys/isa/kbdio.h b/sys/isa/kbdio.h index a25edc5..b9bbe0a 100644 --- a/sys/isa/kbdio.h +++ b/sys/isa/kbdio.h @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: kbdio.h,v 1.6 1997/02/22 09:36:47 peter Exp $ */ #ifndef _I386_ISA_KBDIO_H_ @@ -148,6 +148,7 @@ /* aux device ID */ #define PSM_MOUSE_ID 0 #define PSM_BALLPOINT_ID 2 +#define PSM_INTELLI_ID 3 #ifdef KERNEL diff --git a/sys/isa/syscons.c b/sys/isa/syscons.c index 9e6353c..56feb74 100644 --- a/sys/isa/syscons.c +++ b/sys/isa/syscons.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.240 1997/11/25 12:44:44 sos Exp $ + * $Id: syscons.c,v 1.241 1997/12/06 13:23:26 bde Exp $ */ #include "sc.h" @@ -49,6 +49,7 @@ #include <machine/clock.h> #include <machine/cons.h> #include <machine/console.h> +#include <machine/mouse.h> #include <machine/md_var.h> #include <machine/psl.h> #include <machine/frame.h> @@ -153,6 +154,8 @@ static char vgaregs[MODE_PARAM_SIZE]; static char vgaregs2[MODE_PARAM_SIZE]; static int rows_offset = 1; static char *cut_buffer; +static int mouse_level = 0; /* sysmouse protocol level */ +static mousestatus_t mouse_status = { 0, 0, 0, 0, 0, 0 }; static u_short mouse_and_mask[16] = { 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, @@ -249,8 +252,14 @@ static void set_font_mode(u_char *buf); static void set_normal_mode(u_char *buf); static void set_destructive_cursor(scr_stat *scp); static void set_mouse_pos(scr_stat *scp); +static int skip_spc_right(scr_stat *scp, u_short *p); +static int skip_spc_left(scr_stat *scp, u_short *p); +static void mouse_cut(scr_stat *scp); static void mouse_cut_start(scr_stat *scp); static void mouse_cut_end(scr_stat *scp); +static void mouse_cut_word(scr_stat *scp); +static void mouse_cut_line(scr_stat *scp); +static void mouse_cut_extend(scr_stat *scp); static void mouse_paste(scr_stat *scp); static void draw_mouse_image(scr_stat *scp); static void remove_mouse_image(scr_stat *scp); @@ -785,6 +794,8 @@ scopen(dev_t dev, int flag, int mode, struct proc *p) scparam(tp, &tp->t_termios); ttsetwater(tp); (*linesw[tp->t_line].l_modem)(tp, 1); + if (minor(dev) == SC_MOUSE) + mouse_level = 0; /* XXX */ } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) @@ -925,11 +936,12 @@ int scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) { int error; - u_int i = 0; + u_int i; struct tty *tp; scr_stat *scp; u_short *usp; char *mp; + int s; tp = scdevtotty(dev); if (!tp) @@ -1047,10 +1059,22 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) case CONS_MOUSECTL: /* control mouse arrow */ { + /* MOUSE_BUTTON?DOWN -> MOUSE_MSC_BUTTON?UP */ + static butmap[8] = { + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP + | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON3UP, + MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON2UP, + MOUSE_MSC_BUTTON1UP, + 0, + }; mouse_info_t *mouse = (mouse_info_t*)data; if (!crtc_vga) - return ENXIO; + return ENODEV; switch (mouse->operation) { case MOUSE_MODE: @@ -1100,26 +1124,55 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) case MOUSE_GETINFO: mouse->u.data.x = scp->mouse_xpos; mouse->u.data.y = scp->mouse_ypos; + mouse->u.data.z = 0; mouse->u.data.buttons = scp->mouse_buttons; break; case MOUSE_ACTION: + case MOUSE_MOTION_EVENT: /* this should maybe only be settable from /dev/consolectl SOS */ /* send out mouse event on /dev/sysmouse */ + + mouse_status.dx += mouse->u.data.x; + mouse_status.dy += mouse->u.data.y; + mouse_status.dz += mouse->u.data.z; + if (mouse->operation == MOUSE_ACTION) + mouse_status.button = mouse->u.data.buttons; + mouse_status.flags |= + ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? + MOUSE_POSCHANGED : 0) + | (mouse_status.obutton ^ mouse_status.button); + if (cur_console->status & MOUSE_ENABLED) cur_console->status |= MOUSE_VISIBLE; + if ((MOUSE_TTY)->t_state & TS_ISOPEN) { - u_char buf[5]; + u_char buf[MOUSE_SYS_PACKETSIZE]; int j; - buf[0] = 0x80 | ((~mouse->u.data.buttons) & 0x07); - buf[1] = (mouse->u.data.x & 0x1fe >> 1); - buf[3] = (mouse->u.data.x & 0x1ff) - buf[1]; - buf[2] = -(mouse->u.data.y & 0x1fe >> 1); - buf[4] = -(mouse->u.data.y & 0x1ff) - buf[2]; - for (j=0; j<5; j++) + /* the first five bytes are compatible with MouseSystems' */ + buf[0] = MOUSE_MSC_SYNC + | butmap[mouse_status.button & MOUSE_STDBUTTONS]; + j = imax(imin(mouse->u.data.x, 255), -256); + buf[1] = j >> 1; + buf[3] = j - buf[1]; + j = -imax(imin(mouse->u.data.y, 255), -256); + buf[2] = j >> 1; + buf[4] = j - buf[2]; + for (j = 0; j < MOUSE_MSC_PACKETSIZE; j++) + (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); + if (mouse_level >= 1) { /* extended part */ + j = imax(imin(mouse->u.data.z, 127), -128); + buf[5] = (j >> 1) & 0x7f; + buf[6] = (j - (j >> 1)) & 0x7f; + /* buttons 4-10 */ + buf[7] = (~mouse_status.button >> 3) & 0x7f; + for (j = MOUSE_MSC_PACKETSIZE; + j < MOUSE_SYS_PACKETSIZE; j++) (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[j],MOUSE_TTY); + } } + if (cur_console->mouse_signal) { cur_console->mouse_buttons = mouse->u.data.buttons; /* has controlling process died? */ @@ -1132,26 +1185,117 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) else psignal(cur_console->mouse_proc, cur_console->mouse_signal); } - else { + else if (mouse->operation == MOUSE_ACTION) { /* process button presses */ - if (cur_console->mouse_buttons != mouse->u.data.buttons) { + if ((cur_console->mouse_buttons ^ mouse->u.data.buttons) && + !(cur_console->status & UNKNOWN_MODE)) { cur_console->mouse_buttons = mouse->u.data.buttons; - if (!(cur_console->status & UNKNOWN_MODE)) { - if (cur_console->mouse_buttons & LEFT_BUTTON) - mouse_cut_start(cur_console); - else - mouse_cut_end(cur_console); - if (cur_console->mouse_buttons & RIGHT_BUTTON || - cur_console->mouse_buttons & MIDDLE_BUTTON) - mouse_paste(cur_console); - } + if (cur_console->mouse_buttons & MOUSE_BUTTON1DOWN) + mouse_cut_start(cur_console); + else + mouse_cut_end(cur_console); + if (cur_console->mouse_buttons & MOUSE_BUTTON2DOWN || + cur_console->mouse_buttons & MOUSE_BUTTON3DOWN) + mouse_paste(cur_console); } } + if (mouse->u.data.x != 0 || mouse->u.data.y != 0) { - cur_console->mouse_xpos += mouse->u.data.x; - cur_console->mouse_ypos += mouse->u.data.y; + cur_console->mouse_xpos += mouse->u.data.x; + cur_console->mouse_ypos += mouse->u.data.y; set_mouse_pos(cur_console); } + + break; + + case MOUSE_BUTTON_EVENT: + if ((mouse->u.event.id & MOUSE_BUTTONS) == 0) + return EINVAL; + if (mouse->u.event.value < 0) + return EINVAL; + + if (mouse->u.event.value > 0) { + cur_console->mouse_buttons |= mouse->u.event.id; + mouse_status.button |= mouse->u.event.id; + } else { + cur_console->mouse_buttons &= ~mouse->u.event.id; + mouse_status.button &= ~mouse->u.event.id; + } + mouse_status.flags |= + ((mouse->u.data.x || mouse->u.data.y || mouse->u.data.z) ? + MOUSE_POSCHANGED : 0) + | (mouse_status.obutton ^ mouse_status.button); + + if (cur_console->status & MOUSE_ENABLED) + cur_console->status |= MOUSE_VISIBLE; + + if ((MOUSE_TTY)->t_state & TS_ISOPEN) { + u_char buf[8]; + int i; + + buf[0] = MOUSE_MSC_SYNC + | butmap[mouse_status.button & MOUSE_STDBUTTONS]; + buf[7] = (~mouse_status.button >> 3) & 0x7f; + buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; + for (i = 0; + i < ((mouse_level >= 1) ? MOUSE_SYS_PACKETSIZE + : MOUSE_MSC_PACKETSIZE); i++) + (*linesw[(MOUSE_TTY)->t_line].l_rint)(buf[i],MOUSE_TTY); + } + + if (cur_console->mouse_signal) { + if (cur_console->mouse_proc && + (cur_console->mouse_proc != pfind(cur_console->mouse_pid))){ + cur_console->mouse_signal = 0; + cur_console->mouse_proc = NULL; + cur_console->mouse_pid = 0; + } + else + psignal(cur_console->mouse_proc, cur_console->mouse_signal); + break; + } + + if (cur_console->status & UNKNOWN_MODE) + break; + + switch (mouse->u.event.id) { + case MOUSE_BUTTON1DOWN: + switch (mouse->u.event.value % 4) { + case 0: /* up */ + mouse_cut_end(cur_console); + break; + case 1: + mouse_cut_start(cur_console); + break; + case 2: + mouse_cut_word(cur_console); + break; + case 3: + mouse_cut_line(cur_console); + break; + } + break; + case MOUSE_BUTTON2DOWN: + switch (mouse->u.event.value) { + case 0: /* up */ + break; + default: + mouse_paste(cur_console); + break; + } + break; + case MOUSE_BUTTON3DOWN: + switch (mouse->u.event.value) { + case 0: /* up */ + if (!(cur_console->mouse_buttons & MOUSE_BUTTON1DOWN)) + mouse_cut_end(cur_console); + break; + default: + mouse_cut_extend(cur_console); + break; + } + break; + } break; default: @@ -1162,6 +1306,107 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) return 0; } + /* MOUSE_XXX: /dev/sysmouse ioctls */ + case MOUSE_GETHWINFO: /* get device information */ + { + mousehw_t *hw = (mousehw_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + hw->buttons = 10; /* XXX unknown */ + hw->iftype = MOUSE_IF_SYSMOUSE; + hw->type = MOUSE_MOUSE; + hw->model = MOUSE_MODEL_GENERIC; + hw->hwid = 0; + return 0; + } + + case MOUSE_GETMODE: /* get protocol/mode */ + { + mousemode_t *mode = (mousemode_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + mode->level = mouse_level; + switch (mode->level) { + case 0: + /* at this level, sysmouse emulates MouseSystems protocol */ + mode->protocol = MOUSE_PROTO_MSC; + mode->rate = -1; /* unknown */ + mode->resolution = -1; /* unknown */ + mode->accelfactor = 0; /* disabled */ + mode->packetsize = MOUSE_MSC_PACKETSIZE; + mode->syncmask[0] = MOUSE_MSC_SYNCMASK; + mode->syncmask[1] = MOUSE_MSC_SYNC; + break; + + case 1: + /* at this level, sysmouse uses its own protocol */ + mode->protocol = MOUSE_PROTO_SYSMOUSE; + mode->rate = -1; + mode->resolution = -1; + mode->accelfactor = 0; + mode->packetsize = MOUSE_SYS_PACKETSIZE; + mode->syncmask[0] = MOUSE_SYS_SYNCMASK; + mode->syncmask[1] = MOUSE_SYS_SYNC; + break; + } + return 0; + } + + case MOUSE_SETMODE: /* set protocol/mode */ + { + mousemode_t *mode = (mousemode_t *)data; + + if (tp != MOUSE_TTY) + return ENOTTY; + if ((mode->level < 0) || (mode->level > 1)) + return EINVAL; + mouse_level = mode->level; + return 0; + } + + case MOUSE_GETLEVEL: /* get operation level */ + if (tp != MOUSE_TTY) + return ENOTTY; + *(int *)data = mouse_level; + return 0; + + case MOUSE_SETLEVEL: /* set operation level */ + if (tp != MOUSE_TTY) + return ENOTTY; + if ((*(int *)data < 0) || (*(int *)data > 1)) + return EINVAL; + mouse_level = *(int *)data; + return 0; + + case MOUSE_GETSTATUS: /* get accumulated mouse events */ + if (tp != MOUSE_TTY) + return ENOTTY; + s = spltty(); + *(mousestatus_t *)data = mouse_status; + mouse_status.flags = 0; + mouse_status.obutton = mouse_status.button; + mouse_status.dx = 0; + mouse_status.dy = 0; + mouse_status.dz = 0; + splx(s); + return 0; + +#if notyet + case MOUSE_GETVARS: /* get internal mouse variables */ + case MOUSE_SETVARS: /* set internal mouse variables */ + if (tp != MOUSE_TTY) + return ENOTTY; + return ENODEV; +#endif + + case MOUSE_READSTATE: /* read status from the device */ + case MOUSE_READDATA: /* read data from the device */ + if (tp != MOUSE_TTY) + return ENOTTY; + return ENODEV; + case CONS_GETINFO: /* get current (virtual) console info */ { vid_info_t *ptr = (vid_info_t*)data; @@ -1210,6 +1455,8 @@ scioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) if (scp->history != NULL) i = imax(scp->history_size / scp->xsize - imax(SC_HISTORY_SIZE, scp->ysize), 0); + else + i = 0; switch (cmd & 0xff) { case M_VGA_C80x60: case M_VGA_M80x60: if (!(fonts_loaded & FONT_8)) @@ -4106,28 +4353,86 @@ set_mouse_pos(scr_stat *scp) scp->mouse_pos = scp->scr_buf + ((scp->mouse_ypos/scp->font_size)*scp->xsize + scp->mouse_xpos/8); - if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) { - u_short *ptr; - int i = 0; - - mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); - mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); - scp->mouse_cut_end = scp->mouse_pos; - for (ptr = (scp->mouse_cut_start > scp->mouse_cut_end - ? scp->mouse_cut_end : scp->mouse_cut_start); - ptr <= (scp->mouse_cut_start > scp->mouse_cut_end - ? scp->mouse_cut_start : scp->mouse_cut_end); - ptr++) { - cut_buffer[i++] = *ptr & 0xff; - if (((ptr - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { - cut_buffer[i++] = '\n'; - } - } - cut_buffer[i] = 0x00; - } + if ((scp->status & MOUSE_VISIBLE) && (scp->status & MOUSE_CUTTING)) + mouse_cut(scp); } } +#define isspace(c) (((c) & 0xff) == ' ') + +static int +skip_spc_right(scr_stat *scp, u_short *p) +{ + int i; + + for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { + if (!isspace(*p)) + break; + ++p; + } + return i; +} + +static int +skip_spc_left(scr_stat *scp, u_short *p) +{ + int i; + + for (i = (p-- - scp->scr_buf) % scp->xsize - 1; i >= 0; --i) { + if (!isspace(*p)) + break; + --p; + } + return i; +} + +static void +mouse_cut(scr_stat *scp) +{ + u_short *end; + u_short *p; + int i = 0; + int j = 0; + + scp->mouse_cut_end = (scp->mouse_pos >= scp->mouse_cut_start) ? + scp->mouse_pos + 1 : scp->mouse_pos; + end = (scp->mouse_cut_start > scp->mouse_cut_end) ? + scp->mouse_cut_start : scp->mouse_cut_end; + for (p = (scp->mouse_cut_start > scp->mouse_cut_end) ? + scp->mouse_cut_end : scp->mouse_cut_start; p < end; ++p) { + cut_buffer[i] = *p & 0xff; + /* remember the position of the last non-space char */ + if (!isspace(cut_buffer[i++])) + j = i; + /* trim trailing blank when crossing lines */ + if (((p - scp->scr_buf) % scp->xsize) == (scp->xsize - 1)) { + cut_buffer[j++] = '\n'; + i = j; + } + } + cut_buffer[i] = '\0'; + + /* scan towards the end of the last line */ + --p; + for (i = (p - scp->scr_buf) % scp->xsize; i < scp->xsize; ++i) { + if (!isspace(*p)) + break; + ++p; + } + /* if there is nothing but blank chars, trim them, but mark towards eol */ + if (i >= scp->xsize) { + if (scp->mouse_cut_start > scp->mouse_cut_end) + scp->mouse_cut_start = p; + else + scp->mouse_cut_end = p; + cut_buffer[j++] = '\n'; + cut_buffer[j] = '\0'; + } + + mark_for_update(scp, scp->mouse_cut_start - scp->scr_buf); + mark_for_update(scp, scp->mouse_cut_end - scp->scr_buf); +} + static void mouse_cut_start(scr_stat *scp) { @@ -4135,14 +4440,24 @@ mouse_cut_start(scr_stat *scp) if (scp->status & MOUSE_VISIBLE) { if (scp->mouse_pos == scp->mouse_cut_start && - scp->mouse_cut_start == scp->mouse_cut_end) { - cut_buffer[0] = 0x00; + scp->mouse_cut_start == scp->mouse_cut_end - 1) { + cut_buffer[0] = '\0'; remove_cutmarking(scp); - } - else { - scp->mouse_cut_start = scp->mouse_cut_end = scp->mouse_pos; + } else if (skip_spc_right(scp, scp->mouse_pos) >= scp->xsize) { + /* if the pointer is on trailing blank chars, mark towards eol */ + i = skip_spc_left(scp, scp->mouse_pos) + 1; + scp->mouse_cut_start = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize + i; + scp->mouse_cut_end = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize + 1) * scp->xsize; + cut_buffer[0] = '\n'; + cut_buffer[1] = '\0'; + scp->status |= MOUSE_CUTTING; + } else { + scp->mouse_cut_start = scp->mouse_pos; + scp->mouse_cut_end = scp->mouse_cut_start + 1; cut_buffer[0] = *scp->mouse_cut_start & 0xff; - cut_buffer[1] = 0x00; + cut_buffer[1] = '\0'; scp->status |= MOUSE_CUTTING; } mark_all(scp); @@ -4164,6 +4479,77 @@ mouse_cut_end(scr_stat *scp) } static void +mouse_cut_word(scr_stat *scp) +{ + u_short *p; + u_short *sol; + u_short *eol; + int i; + + /* + * Because we don't have locale information in the kernel, + * we only distinguish space char and non-space chars. Punctuation + * chars, symbols and other regular chars are all treated alike. + */ + if (scp->status & MOUSE_VISIBLE) { + sol = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; + eol = sol + scp->xsize; + if (isspace(*scp->mouse_pos)) { + for (p = scp->mouse_pos; p >= sol; --p) + if (!isspace(*p)) + break; + scp->mouse_cut_start = ++p; + for (p = scp->mouse_pos; p < eol; ++p) + if (!isspace(*p)) + break; + scp->mouse_cut_end = p; + } else { + for (p = scp->mouse_pos; p >= sol; --p) + if (isspace(*p)) + break; + scp->mouse_cut_start = ++p; + for (p = scp->mouse_pos; p < eol; ++p) + if (isspace(*p)) + break; + scp->mouse_cut_end = p; + } + for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) + cut_buffer[i++] = *p & 0xff; + cut_buffer[i] = '\0'; + scp->status |= MOUSE_CUTTING; + } +} + +static void +mouse_cut_line(scr_stat *scp) +{ + u_short *p; + int i; + + if (scp->status & MOUSE_VISIBLE) { + scp->mouse_cut_start = scp->scr_buf + + ((scp->mouse_pos - scp->scr_buf) / scp->xsize) * scp->xsize; + scp->mouse_cut_end = scp->mouse_cut_start + scp->xsize; + for (i = 0, p = scp->mouse_cut_start; p < scp->mouse_cut_end; ++p) + cut_buffer[i++] = *p & 0xff; + cut_buffer[i++] = '\n'; + cut_buffer[i] = '\0'; + scp->status |= MOUSE_CUTTING; + } +} + +static void +mouse_cut_extend(scr_stat *scp) +{ + if ((scp->status & MOUSE_VISIBLE) && !(scp->status & MOUSE_CUTTING) + && (scp->mouse_cut_start != NULL)) { + mouse_cut(scp); + scp->status |= MOUSE_CUTTING; + } +} + +static void mouse_paste(scr_stat *scp) { if (scp->status & MOUSE_VISIBLE) { @@ -4273,7 +4659,7 @@ draw_cutmarking(scr_stat *scp) /* are we outside the selected area ? */ if ( ptr < (scp->mouse_cut_start > scp->mouse_cut_end ? scp->mouse_cut_end : scp->mouse_cut_start) || - ptr > (scp->mouse_cut_start > scp->mouse_cut_end ? + ptr >= (scp->mouse_cut_start > scp->mouse_cut_end ? scp->mouse_cut_start : scp->mouse_cut_end)) { if (ptr != scp->cursor_pos) nch = (och & 0xff) | (*ptr & 0xff00); diff --git a/sys/sys/mouse.h b/sys/sys/mouse.h index 86f4528..d0eecef 100644 --- a/sys/sys/mouse.h +++ b/sys/sys/mouse.h @@ -1,5 +1,6 @@ /*- * Copyright (c) 1992, 1993 Erik Forsberg. + * Copyright (c) 1996, 1997 Kazutaka YOKOTA * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -19,7 +20,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: mouse.h,v 1.7 1997/02/22 09:34:50 peter Exp $ + * $Id: mouse.h,v 1.8 1997/10/19 10:44:02 yokota Exp $ */ #ifndef _MACHINE_MOUSE_H_ @@ -28,45 +29,33 @@ #include <sys/types.h> #include <sys/ioccom.h> -/* - * NOTE: MOUSEIOC, MOUSEIOCREAD, and mouseinfo are now obsolete, - * but will stay for compatibility reasons. But, remember, - * the MOUSEIOCREAD ioctl command doesn't work and never worked before. - * Some day we shall get rid of these... - */ +/* ioctls */ +#define MOUSE_GETSTATUS _IOR('M', 0, mousestatus_t) +#define MOUSE_GETHWINFO _IOR('M', 1, mousehw_t) +#define MOUSE_GETMODE _IOR('M', 2, mousemode_t) +#define MOUSE_SETMODE _IOW('M', 3, mousemode_t) +#define MOUSE_GETLEVEL _IOR('M', 4, int) +#define MOUSE_SETLEVEL _IOW('M', 5, int) +#define MOUSE_GETVARS _IOR('M', 6, mousevar_t) +#define MOUSE_SETVARS _IOW('M', 7, mousevar_t) +#define MOUSE_READSTATE _IOWR('M', 8, mousedata_t) +#define MOUSE_READDATA _IOWR('M', 9, mousedata_t) -#define MOUSEIOC ('M'<<8) -#define MOUSEIOCREAD (MOUSEIOC|60) - -typedef struct mouseinfo { - unsigned char status; - char xmotion; - char ymotion; -} mouseinfo_t; -/* status */ -#define BUTSTATMASK 0x07 /* Any mouse button down if any bit set */ -#define BUTCHNGMASK 0x38 /* Any mouse button changed if any bit set */ -#define BUT3STAT 0x01 /* Button 3 down if set */ -#define BUT2STAT 0x02 /* Button 2 down if set */ -#define BUT1STAT 0x04 /* Button 1 down if set */ -#define BUT3CHNG 0x08 /* Button 3 changed if set */ -#define BUT2CHNG 0x10 /* Button 2 changed if set */ -#define BUT1CHNG 0x20 /* Button 1 changed if set */ -#define MOVEMENT 0x40 /* Mouse movement detected */ - -#define MOUSE_GETSTATE _IOR('M',0,mousestatus_t) -#define MOUSE_GETHWINFO _IOR('M',1,mousehw_t) -#define MOUSE_GETMODE _IOR('M',2,mousemode_t) -#define MOUSE_SETMODE _IOW('M',3,mousemode_t) - -/* new ioctls */ +#if notyet +#define MOUSE_SETRESOLUTION _IOW('M', 10, int) +#define MOUSE_SETSCALING _IOW('M', 11, int) +#define MOUSE_SETRATE _IOW('M', 12, int) +#define MOUSE_GETHWID _IOR('M', 13, int) +#endif /* mouse status block */ typedef struct mousestatus { + int flags; /* state change flags */ int button; /* button status */ int obutton; /* previous button status */ int dx; /* x movement */ int dy; /* y movement */ + int dz; /* z movement */ } mousestatus_t; /* button */ @@ -78,23 +67,34 @@ typedef struct mousestatus { #define MOUSE_BUTTON6DOWN 0x0020 #define MOUSE_BUTTON7DOWN 0x0040 #define MOUSE_BUTTON8DOWN 0x0080 -#define MOUSE_STDBUTTONS 0x0007 /* buttons 1-3 */ -#define MOUSE_EXTBUTTONS 0x00f8 /* the others */ +#define MOUSE_MAXBUTTON 31 +#define MOUSE_STDBUTTONS 0x0007 /* buttons 1-3 */ +#define MOUSE_EXTBUTTONS 0x7ffffff8 /* the others (28 of them!) */ +#define MOUSE_BUTTONS (MOUSE_STDBUTTONS | MOUSE_EXTBUTTONS) + +/* flags */ +#define MOUSE_STDBUTTONSCHANGED MOUSE_STDBUTTONS +#define MOUSE_EXTBUTTONSCHANGED MOUSE_EXTBUTTONS +#define MOUSE_BUTTONSCHANGED MOUSE_BUTTONS +#define MOUSE_POSCHANGED 0x80000000 typedef struct mousehw { - int buttons; + int buttons; /* -1 if unknown */ int iftype; /* MOUSE_IF_XXX */ int type; /* mouse/track ball/pad... */ + int model; /* I/F dependent model ID: MOUSE_MODEL_XXX */ int hwid; /* I/F dependent hardware ID * for the PS/2 mouse, it will be PSM_XXX_ID */ } mousehw_t; /* iftype */ +#define MOUSE_IF_UNKNOWN (-1) #define MOUSE_IF_SERIAL 0 #define MOUSE_IF_BUS 1 #define MOUSE_IF_INPORT 2 #define MOUSE_IF_PS2 3 +#define MOUSE_IF_SYSMOUSE 4 /* type */ #define MOUSE_UNKNOWN (-1) /* should be treated as a mouse */ @@ -103,24 +103,67 @@ typedef struct mousehw { #define MOUSE_STICK 2 #define MOUSE_PAD 3 +/* model */ +#define MOUSE_MODEL_UNKNOWN (-1) +#define MOUSE_MODEL_GENERIC 0 +#define MOUSE_MODEL_GLIDEPOINT 1 +#define MOUSE_MODEL_NETSCROLL 2 +#define MOUSE_MODEL_NET 3 +#define MOUSE_MODEL_INTELLI 4 +#define MOUSE_MODEL_THINK 5 +#define MOUSE_MODEL_EASYSCROLL 6 +#define MOUSE_MODEL_MOUSEMANPLUS 7 + typedef struct mousemode { int protocol; /* MOUSE_PROTO_XXX */ int rate; /* report rate (per sec), -1 if unknown */ - int resolution; /* 1:low, 2:medium low, 3:medium high - * 4:high, 0: default, -1 if unknown - */ + int resolution; /* MOUSE_RES_XXX, -1 if unknown */ int accelfactor; /* accelation factor (must be 1 or greater) */ + int level; /* driver operation level */ + int packetsize; /* the length of the data packet */ + unsigned char syncmask[2]; /* sync. data bits in the header byte */ } mousemode_t; /* protocol */ +#define MOUSE_PROTO_UNKNOWN (-1) #define MOUSE_PROTO_MS 0 /* Microsoft Serial, 3 bytes */ #define MOUSE_PROTO_MSC 1 /* Mouse Systems, 5 bytes */ #define MOUSE_PROTO_LOGI 2 /* Logitech, 3 bytes */ #define MOUSE_PROTO_MM 3 /* MM series, 3 bytes */ #define MOUSE_PROTO_LOGIMOUSEMAN 4 /* Logitech MouseMan 3/4 bytes */ #define MOUSE_PROTO_BUS 5 /* MS/Logitech bus mouse */ -#define MOUSE_PROTO_INPORT 6 /* MS/ATI inport mouse */ +#define MOUSE_PROTO_INPORT 6 /* MS/ATI InPort mouse */ #define MOUSE_PROTO_PS2 7 /* PS/2 mouse, 3 bytes */ +#define MOUSE_PROTO_HITTAB 8 /* Hitachi Tablet 3 bytes */ +#define MOUSE_PROTO_GLIDEPOINT 9 /* ALPS GlidePoint, 3/4 bytes */ +#define MOUSE_PROTO_INTELLI 10 /* MS IntelliMouse, 4 bytes */ +#define MOUSE_PROTO_THINK 11 /* Kensignton Thinking Mouse, 3/4 bytes */ +#define MOUSE_PROTO_SYSMOUSE 12 /* /dev/sysmouse */ + +#define MOUSE_RES_UNKNOWN (-1) +#define MOUSE_RES_DEFAULT 0 +#define MOUSE_RES_LOW (-2) +#define MOUSE_RES_MEDIUMLOW (-3) +#define MOUSE_RES_MEDIUMHIGH (-4) +#define MOUSE_RES_HIGH (-5) + +typedef struct mousedata { + int len; /* # of data in the buffer */ + int buf[16]; /* data buffer */ +} mousedata_t; + +#if (defined(MOUSE_GETVARS)) + +typedef struct mousevar { + int var[16]; +} mousevar_t; + +/* magic numbers in var[0] */ +#define MOUSE_VARS_PS2_SIG 0x00325350 /* 'PS2' */ +#define MOUSE_VARS_BUS_SIG 0x00535542 /* 'BUS' */ +#define MOUSE_VARS_INPORT_SIG 0x00504e49 /* 'INP' */ + +#endif /* MOUSE_GETVARS */ /* Microsoft Serial mouse data packet */ #define MOUSE_MSS_PACKETSIZE 3 @@ -132,7 +175,19 @@ typedef struct mousemode { #define MOUSE_MSS_BUTTON3DOWN 0x10 /* right */ /* Logitech MouseMan data packet (M+ protocol) */ -#define MOUSE_LMAN_BUTTON2DOWN 0x20 /* middle button, in the 4th byte */ +#define MOUSE_LMAN_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ + +/* ALPS GlidePoint extention (variant of M+ protocol) */ +#define MOUSE_ALPS_BUTTON2DOWN 0x20 /* middle button, the 4th byte */ +#define MOUSE_ALPS_TAP 0x10 /* `tapping' action, the 4th byte */ + +/* Kinsington Thinking Mouse extention (variant of M+ protocol) */ +#define MOUSE_THINK_BUTTON2DOWN 0x20 /* lower-left button, the 4th byte */ +#define MOUSE_THINK_BUTTON4DOWN 0x10 /* lower-right button, the 4th byte */ + +/* MS IntelliMouse (variant of MS Serial) */ +#define MOUSE_INTELLI_PACKETSIZE 4 +#define MOUSE_INTELLI_BUTTON2DOWN 0x10 /* middle button the 4th byte */ /* Mouse Systems Corp. mouse data packet */ #define MOUSE_MSC_PACKETSIZE 5 @@ -156,18 +211,50 @@ typedef struct mousemode { /* PS/2 mouse data packet */ #define MOUSE_PS2_PACKETSIZE 3 -#define MOUSE_PS2_SYNCMASK 0x08 /* 0x0c for 2 button mouse */ -#define MOUSE_PS2_SYNC 0x08 /* 0x0c for 2 button mouse */ +#define MOUSE_PS2_SYNCMASK 0xc8 +#define MOUSE_PS2_SYNC 0x08 #define MOUSE_PS2_BUTTONS 0x07 /* 0x03 for 2 button mouse */ #define MOUSE_PS2_BUTTON1DOWN 0x01 /* left */ #define MOUSE_PS2_BUTTON2DOWN 0x04 /* middle */ #define MOUSE_PS2_BUTTON3DOWN 0x02 /* right */ -#define MOUSE_PS2_BUTTON4UP 0x08 /* GlidePoint tapping feature - * Yes! this is the same bit as SYNC! - */ +#define MOUSE_PS2_TAP MOUSE_PS2_SYNC /* GlidePoint (PS/2) `tapping' + * Yes! this is the same bit + * as SYNC! + */ +#define MOUSE_PS2PLUS_BUTTON4DOWN 0x10 /* 4th button on MouseMan+ */ + #define MOUSE_PS2_XNEG 0x10 #define MOUSE_PS2_YNEG 0x20 #define MOUSE_PS2_XOVERFLOW 0x40 #define MOUSE_PS2_YOVERFLOW 0x80 +#define MOUSE_PS2PLUS_ZNEG 0x08 /* MouseMan+ negative wheel movement */ + +/* sysmouse extended data packet */ +/* + * /dev/sysmouse sends data in two formats, depending on the protocol + * level. At the level 0, format is exactly the same as MousSystems' + * five byte packet. At the level 1, the first five bytes are the same + * as at the level 0. There are additional three bytes which shows + * `dz' and the states of additional buttons. `dz' is expressed as the + * sum of the byte 5 and 6 which contain signed seven bit values. + * The states of the button 4 though 10 are in the bit 0 though 6 in + * the byte 7 respectively: 1 indicates the button is up. + */ +#define MOUSE_SYS_PACKETSIZE 8 +#define MOUSE_SYS_SYNCMASK 0xf8 +#define MOUSE_SYS_SYNC 0x80 +#define MOUSE_SYS_BUTTON1UP 0x04 /* left, 1st byte */ +#define MOUSE_SYS_BUTTON2UP 0x02 /* middle, 1st byte */ +#define MOUSE_SYS_BUTTON3UP 0x01 /* right, 1st byte */ +#define MOUSE_SYS_BUTTON4UP 0x0001 /* 7th byte */ +#define MOUSE_SYS_BUTTON5UP 0x0002 +#define MOUSE_SYS_BUTTON6UP 0x0004 +#define MOUSE_SYS_BUTTON7UP 0x0008 +#define MOUSE_SYS_BUTTON8UP 0x0010 +#define MOUSE_SYS_BUTTON9UP 0x0020 +#define MOUSE_SYS_BUTTON10UP 0x0040 +#define MOUSE_SYS_MAXBUTTON 10 +#define MOUSE_SYS_STDBUTTONS 0x07 +#define MOUSE_SYS_EXTBUTTONS 0x7f /* the others */ #endif /* _MACHINE_MOUSE_H_ */ |