summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa/mse.c
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/i386/isa/mse.c
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/i386/isa/mse.c')
-rw-r--r--sys/i386/isa/mse.c225
1 files changed, 205 insertions, 20 deletions
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);
}
OpenPOWER on IntegriCloud