summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/alpha/include/console.h15
-rw-r--r--sys/alpha/include/mouse.h177
-rw-r--r--sys/dev/mse/mse.c225
-rw-r--r--sys/dev/syscons/syscons.c484
-rw-r--r--sys/i386/include/console.h15
-rw-r--r--sys/i386/include/mouse.h177
-rw-r--r--sys/i386/isa/kbdio.h3
-rw-r--r--sys/i386/isa/mse.c225
-rw-r--r--sys/i386/isa/psm.c1683
-rw-r--r--sys/i386/isa/syscons.c484
-rw-r--r--sys/isa/kbdio.h3
-rw-r--r--sys/isa/syscons.c484
-rw-r--r--sys/sys/mouse.h177
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_ */
OpenPOWER on IntegriCloud