diff options
author | yokota <yokota@FreeBSD.org> | 1997-12-07 08:09:19 +0000 |
---|---|---|
committer | yokota <yokota@FreeBSD.org> | 1997-12-07 08:09:19 +0000 |
commit | 14e5988fe7a4f1b8e66d0c9737ef2977af92f4e6 (patch) | |
tree | 8588079ed8400cfd44b8ff3350d61fc9cc86df32 /sys/dev/mse/mse.c | |
parent | 86f898b9574f12a3edac943f45088ed254f4387b (diff) | |
download | FreeBSD-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/dev/mse/mse.c')
-rw-r--r-- | sys/dev/mse/mse.c | 225 |
1 files changed, 205 insertions, 20 deletions
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); } |