summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoryokota <yokota@FreeBSD.org>1997-12-07 08:09:19 +0000
committeryokota <yokota@FreeBSD.org>1997-12-07 08:09:19 +0000
commit14e5988fe7a4f1b8e66d0c9737ef2977af92f4e6 (patch)
tree8588079ed8400cfd44b8ff3350d61fc9cc86df32 /sys
parent86f898b9574f12a3edac943f45088ed254f4387b (diff)
downloadFreeBSD-src-14e5988fe7a4f1b8e66d0c9737ef2977af92f4e6.zip
FreeBSD-src-14e5988fe7a4f1b8e66d0c9737ef2977af92f4e6.tar.gz
- Add support for the following mice to psm/moused/sysmouse:
MS IntelliMouse, Kensington Thinking Mouse, Genius NetScroll, Genius NetMouse, Genius NetMouse Pro, ALPS GlidePoint, ASCII MieMouse, Logitech MouseMan+, FirstMouse+ - The `psm' driver is made to recognize various models of PS/2 mice and enable their extra features so that their additional buttons and wheel/roller are recognized. The name of the detected model will be printed at boot time. - A set of new ioctl functions are added to the `psm', `mse' and `sysmouse' drivers so that the userland program (such as the X server) can query device information and change driver settings. - The wheel/roller movement is handled as the `Z' axis movement by the mouse drivers and the moused daemon. The Z axis movement may be mapped to another axis movement or buttons. - The mouse drivers support a new, standard mouse data format, MOUSE_PROTO_SYSMOUSE format which can encode x, y, and x axis movement and up to 10 buttons. /sys/i386/include/mouse.h - Added some fields to `mousestatus_t' to store Z axis movement and flag bits. - Added the field `model' to `mousehw_t' to store mouse model code. Defined model codes. - Extended `mousemode_t'. - Added new protocols and some constants for them. - Added new ioctl functions and structures. - Removed obsolete ioctl definitions. /sys/i386/include/console.h - Added `dz' field to the structure `mouse_data' to pass Z axis movement to `syscons/sysmouse'. - Removed LEFT_BUTTON, MIDDLE_BUTTON and RIGHT_BUTTON. Use button bits defined in `mouse.h' instead. /sys/i386/isa/psm.c - Added a set of functions to detect various mice which have additional features (wheel and buttons) unavailable in the standard PS/2 mouse. - Refined existing ioctl functions and added new ones. Most important of all is MOUSE_SETLEVEL which manipulates the output level of the driver. While the output level remains zero, the output from the `psm' driver is in the standard PS/2 mouse format (three bytes long). When the level is set to one, the `psm' driver will send data in the extended format. At the level two the driver uses the format which is native to the connected mouse is used. (Meaning that the output from the device is passed to the caller as is, unmodified.) The `psm' driver will pass such extended data format as is to the caller if the output level is two, but emulates the standard format if the output level is zero. - Added kernel configuration flags to set initial resolution (PSM_CONFIG_RESOLUTION) and acceleration (PSM_CONFIG_ACCEL). - Removed the compile options PSM_ACCEL, PSM_CHECKSYNC and PSM_EMULATION. Acceleration ratio is now specified by the kernel configuration flags stated above. Sync check logic is refined and now standard. The sync check can be turned off by the new kernel configuration flags PSM_CONFIG_NOCHECKSYNC (0x100). PSM_EMULATION has been of little use. - Summer clean up :-) Removed unused code and obsolete comments. /sys/i386/isa/mse.c - Created mseioctl() to deal with ioctl functions MOUSE_XXXX. Most importantly, the MOUSE_SETLEVEL ioctl will change the output format from the 5 byte format to the new, extended format so that the caller can take advantage of Z axis movement and additional buttons. - Use constants defined in `mouse.h' rather than magic numbers. /sys/i386/isa/syscons.c - Changed scioctl() to reflect the new `console.h' and some of the new ioctls defined in `mouse.h'. Most importantly, the MOUSE_SETLEVEL ioctl will change the `sysmouse' output format from the MouseSystems 5 byte format to the new, extended format so that the caller can take advantage of Z axis movement and additional buttons. - Added support for double/triple click actions of the left button and single click action of the right button in the virtual console. The left button double click will select a word under the mouse pointer. The triple click will select a line and the single click of the right button will extend the selected region to the current position of the mouse pointer. This will make the cut/paste support more compatible with xterm. /sys/i386/isa/kbdio.h - Added PSM_INTELLI_ID.
Diffstat (limited to 'sys')
-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