xserver/hw/xorg/input/mouse Imakefile, NONE, 1.1 Makefile.am, NONE, 1.1 mouse.c, NONE, 1.1 mouse.h, NONE, 1.1 mouse.man, NONE, 1.1 mousePriv.h, NONE, 1.1 pnp.c, NONE, 1.1

Daniel Stone xserver-commit at pdx.freedesktop.org
Tue May 4 01:44:02 EST 2004


Committed by: daniel

Update of /cvs/xserver/xserver/hw/xorg/input/mouse
In directory pdx:/tmp/cvs-serv16821/input/mouse

Added Files:
	Imakefile Makefile.am mouse.c mouse.h mouse.man mousePriv.h 
	pnp.c 
Log Message:
Adding the original drivers/fbdev and input/mouse directories.

* drivers/fbdev/fbdev.c:
Disable shadowfb support for the time being - the miext APIs are different.


--- NEW FILE: Imakefile ---
XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/input/mouse/Imakefile,v 1.4 2000/03/03 01:05:50 dawes Exp $

#define IHaveModules
#include <Server.tmpl>

SRCS = mouse.c pnp.c
OBJS = mouse.o pnp.o

DRIVER = mouse

INCLUDES = -I. -I$(XF86COMSRC) -I$(XF86SRC)/loader -I$(XF86OSSRC) \
	   -I$(SERVERSRC)/mi -I$(SERVERSRC)/include -I$(XINCLUDESRC) \
	   -I$(EXTINCSRC)

DEFINES = -DPNP_MOUSE

#if MakeHasPosixVariableSubstitutions
SubdirLibraryRule($(OBJS))
#endif

ModuleObjectRule()

ObjectModuleTarget($(DRIVER),$(OBJS))

InstallObjectModule($(DRIVER),$(MODULEDIR),input)

#if !defined(XF86DriverSDK)
InstallModuleManPage($(DRIVER))
#endif

DependTarget()

InstallDriverSDKObjectModule($(DRIVER),$(DRIVERSDKMODULEDIR),input)

--- NEW FILE: Makefile.am ---
AM_CFLAGS = $(XORG_CFLAGS) -DPNP_MOUSE

INCLUDES = $(XORG_INCS) \
	   -I$(top_srcdir)/mi \
	   -I$(top_srcdir)/fb \
	   -I$(top_srcdir)/hw/xorg/fbdevhw \
           -I$(top_srcdir)/hw/xorg/loader \
	   -I$(top_srcdir)/hw/xorg/ddc \
           -I$(top_srcdir)/hw/xorg/rac \
	   -I$(top_srcdir)/hw/xorg/vbe \
	   -I$(top_srcdir)/hw/xorg/int10 \
           -I$(top_srcdir)/hw/xorg/i2c \
	   -I$(top_srcdir)/hw/xorg/parser \
	   -I$(top_srcdir)/hw/xorg/shadowfb \
	   -I$(top_srcdir)/hw/xorg/vgahw \
           -I$(top_srcdir)/hw/xorg/Xi \
	   -I$(top_srcdir)/hw/xorg/xaa \
	   -I$(top_srcdir)/hw/xorg/ramdac \
	   -I$(top_srcdir)/os

lib_LIBRARIES = libmouse.a

libmouse_a_SOURCES = mouse.c pnp.c

--- NEW FILE: mouse.c ---
/* $XdotOrg: xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c,v 1.1.4.2.4.4 2004/04/06 20:47:50 eich Exp $ */
/* $XFree86: xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c,v 1.79 2003/11/03 05:11:48 tsi Exp $ */
/*
 *
 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
 * Copyright 1993 by David Dawes <dawes at xfree86.org>
 * Copyright 2002 by SuSE Linux AG, Author: Egbert Eich
 * Copyright 1994-2002 by The XFree86 Project, Inc.
 * Copyright 2002 by Paul Elliott
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the names of copyright holders not be
 * used in advertising or publicity pertaining to distribution of the
 * software without specific, written prior permission.  The copyright holders
 * make no representations about the suitability of this
 * software for any purpose.  It is provided "as is" without express or
[...3552 lines suppressed...]
    MODINFOSTRING2,
    XORG_VERSION_CURRENT,
    1, 0, 0,
    ABI_CLASS_XINPUT,
    ABI_XINPUT_VERSION,
    MOD_CLASS_XINPUT,
    {0, 0, 0, 0}		/* signature, to be patched into the file by */
				/* a tool */
};

XF86ModuleData mouseModuleData = {&xf86MouseVersionRec,
				  xf86MousePlug,
				  xf86MouseUnplug};

/*
  Look at hitachi device stuff.
*/
#endif /* XFree86LOADER */



--- NEW FILE: mouse.h ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/input/mouse/mouse.h,v 1.13 2003/11/03 05:11:49 tsi Exp $ */

/*
 * Copyright (c) 1997-1999 by The XFree86 Project, Inc.
 */

#ifndef MOUSE_H_
#define MOUSE_H_

#include "xf86OSmouse.h"

const char * xf86MouseProtocolIDToName(MouseProtocolID id);
MouseProtocolID xf86MouseProtocolNameToID(const char *name);

#endif

--- NEW FILE: mouse.man ---
.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/mouse/mouse.man,v 1.6 2003/04/03 22:18:31 dawes Exp $ 
.\" shorthand for double quote that works everywhere.
.ds q \N'34'
.TH MOUSE __drivermansuffix__ __vendorversion__
.SH NAME
mouse \- Mouse input driver
.SH SYNOPSIS
.nf
.B "Section \*qInputDevice\*q"
.BI "  Identifier \*q" idevname \*q
.B  "  Driver \*qmouse\*q"
.BI "  Option \*qProtocol\*q \*q" protoname \*q
.BI "  Option \*qDevice\*q   \*q" devpath \*q
\ \ ...
.B EndSection
.fi
.SH DESCRIPTION
.B mouse 
is an __xservername__ input driver for mice.  The driver supports most available
mouse types and interfaces.  USB mice are only supported on some OSs,
and the level of support for PS/2 mice depends on the OS.
.PP
The
.B mouse
driver functions as a pointer input device, and may be used as the
X server's core pointer.  Multiple mice are supported by multiple
instances of this driver.
.SH SUPPORTED HARDWARE
There is a detailed list of hardware that the
.B mouse
driver supports in the
.I README.mouse
document.  This can be found
in __projectroot__/lib/X11/doc/, or online at
http://www.xfree86.org/current/mouse.html.
.SH CONFIGURATION DETAILS
Please refer to __xconfigfile__(__filemansuffix__) for general configuration
details and for options that can be used with all input drivers.  This
section only covers configuration details specific to this driver.
.PP
The driver can auto-detect the mouse type on some platforms  On some
platforms this is limited to plug and play serial mice, and on some the
auto-detection works for any mouse that the OS's kernel driver supports.
On others, it is always necessary to specify the mouse protocol in the
config file.  The
.I README.mouse
document contains some detailed information about this.
.PP
The following driver
.B Options
are supported:
.TP 7
.BI "Option \*qProtocol\*q \*q" string \*q
Specify the mouse protocol.  Valid protocol types include:
.PP
.RS 12
Auto, Microsoft, MouseSystems, MMSeries, Logitech, MouseMan, MMHitTab,
GlidePoint, IntelliMouse, ThinkingMouse, ValuMouseScroll, AceCad, PS/2, ImPS/2,
ExplorerPS/2, ThinkingMousePS/2, MouseManPlusPS/2, GlidePointPS/2,
NetMousePS/2, NetScrollPS/2, BusMouse, SysMouse, WSMouse, USB, Xqueue.
.RE
.PP
.RS 7
Not all protocols are supported on all platforms.  The "Auto" platform
specifies that protocol auto-detection should be attempted.  There is no
default protocol setting, and specifying this option is mandatory.
.RE
.TP 7
.BI "Option \*qDevice\*q \*q" string \*q
Specifies the device through which the mouse can be accessed.  A common
setting is "/dev/mouse", which is often a symbolic link to the real
device.  This option is mandatory, and there is no default setting.
.TP 7
.BI "Option \*qButtons\*q \*q" integer \*q
Specifies the number of mouse buttons.  In cases where the number of buttons
cannot be auto-detected, the default value is 3.
.TP 7
.BI "Option \*qEmulate3Buttons\*q \*q" boolean \*q
Enable/disable the emulation of the third (middle) mouse button for mice
which only have two physical buttons.  The third button is emulated by
pressing both buttons simultaneously.  Default: off
.TP 7
.BI "Option \*qEmulate3Timeout\*q \*q" integer \*q
Sets the timeout (in milliseconds) that the driver waits before deciding
if two buttons where pressed "simultaneously" when 3 button emulation is
enabled.  Default: 50.
.TP 7
.BI "Option \*qChordMiddle\*q \*q" boolean \*q
Enable/disable handling of mice that send left+right events when the middle
button is used.  Default: off.
.TP 7
.BI "Option \*qEmulateWheel\*q \*q" boolean \*q
Enable/disable "wheel" emulation.  Wheel emulation means emulating button
press/release events when the mouse is moved while a specific real button
is pressed.  Wheel button events (typically buttons 4 and 5) are
usually used for scrolling.  Wheel emulation is useful for getting wheel-like
behaviour with trackballs.  It can also be useful for mice with 4 or
more buttons but no wheel.  See the description of the
.BR EmulateWheelButton ,
.BR EmulateWheelInertia ,
.BR XAxisMapping ,
and
.B YAxisMapping
options below.  Default: off.
.TP 7
.BI "Option \*qEmulateWheelButton\*q \*q" integer \*q
Specifies which button must be held down to enable wheel emulation mode.
While this button is down, X and/or Y pointer movement will generate button
press/release events as specified for the
.B XAxisMapping
and
.B YAxisMapping
settings.  Default: 4.
.TP 7
.BI "Option \*qEmulateWheelInertia\*q \*q" integer \*q
Specifies how far (in pixels) the pointer must move to generate button
press/release events in wheel emulation mode.  Default: 50.
.TP 7
.BI "Option \*qXAxisMapping\*q \*q" "N1 N2" \*q
Specifies which buttons are mapped to motion in the X direction in wheel
emulation mode.  Button number
.I N1
is mapped to the negative X axis motion and button number
.I N2
is mapped to the positive X axis motion.  Default: no mapping.
.TP 7
.BI "Option \*qYAxisMapping\*q \*q" "N1 N2" \*q
Specifies which buttons are mapped to motion in the Y direction in wheel
emulation mode.  Button number
.I N1
is mapped to the negative Y axis motion and button number
.I N2
is mapped to the positive Y axis motion.  Default: "4 5".
.TP 7
.BI "Option \*qZAxisMapping\*q \*qX\*q"
.TP 7
.BI "Option \*qZAxisMapping\*q \*qY\*q"
.TP 7
.BI "Option \*qZAxisMapping\*q \*q" "N1 N2" \*q
.TP 7
.BI "Option \*qZAxisMapping\*q \*q" "N1 N2 N3 N4" \*q
Set the mapping for the Z axis (wheel) motion to buttons or another axis
.RB ( X
or
.BR Y ).
Button number
.I N1
is mapped to the negative Z axis motion and button number
.I N2
is mapped to the positive Z axis motion.  For mice with two wheels,
four button numbers can be specified, with the negative and positive motion
of the second wheel mapped respectively to buttons number
.I N3
and
.IR N4 .
Default: no mapping.
.TP 7
.BI "Option \*qFlipXY\*q \*q" boolean \*q
Enable/disable swapping the X and Y axes.  This transformation is applied
after the
.BR InvX ,
.B InvY
and
.BR AngleOffset
transformations.  Default: off.
.TP 7
.BI "Option \*qInvX\*q \*q" boolean \*q
Invert the X axis.  Default: off.
.TP 7
.BI "Option \*qInvY\*q \*q" boolean \*q
Invert the Y axis.  Default: off.
.TP 7
.BI "Option \*qAngleOffset\*q \*q" integer \*q
Specify a clockwise angular offset (in degrees) to apply to the pointer
motion.  This transformation is applied before the
.BR FlipXY ,
.B InvX
and
.B InvY
transformations.  Default: 0.
.TP 7
.BI "Option \*qSampleRate\*q \*q" integer \*q
Sets the number of motion/button events the mouse sends per second.  Setting
this is only supported for some mice, including some Logitech mice and
some PS/2 mice on some platforms.  Default: whatever the mouse is
already set to.
.TP 7
.BI "Option \*qResolution\*q \*q" integer \*q
Sets the resolution of the device in counts per inch.  Setting this is
only supported for some mice, including some PS/2 mice on some platforms.
Default: whatever the mouse is already set to.
.TP 7
.BI "Option \*qDragLockButtons\*q \*q" "L1 B2 L3 B4" \*q
Sets \*qdrag lock buttons\*q that simulate holding a button down, so
that low dexterity people do not have to hold a button down at the
same time they move a mouse cursor. Button numbers occur in pairs,
with the lock button number occurring first, followed by the button
number that is the target of the lock button.
.TP 7
.BI "Option \*qDragLockButtons\*q \*q" "M1" \*q
Sets a \*qmaster drag lock button\*q that acts as a \*qMeta Key\*q
indicating that the next button pressed is to be 
\*qdrag locked\*q.
.TP 7
.BI "Option \*qClearDTR\*q \*q" boolean \*q
Enable/disable clearing the DTR line on the serial port used by the mouse.
Some dual-protocol mice require the DTR line to be cleared to operate
in the non-default protocol.  This option is for serial mice only.
Default: off.
.TP 7
.BI "Option \*qClearRTS\*q \*q" boolean \*q
Enable/disable clearing the RTS line on the serial port used by the mouse.
Some dual-protocol mice require the RTS line to be cleared to operate
in the non-default protocol.  This option is for serial mice only.
Default: off.
.TP 7
.BI "Option \*qBaudRate\*q \*q" integer \*q
Set the baud rate to use for communicating with a serial mouse.  This
option should rarely be required because the default is correct for almost
all situations.  Valid values include: 300, 1200, 2400, 4800, 9600, 19200.
Default: 1200.
.PP
There are some other options that may be used to control various parameters
for serial port communication, but they are not documented here because
the driver sets them correctly for each mouse protocol type.
.SH "SEE ALSO"
__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__),
README.mouse.

--- NEW FILE: mousePriv.h ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/input/mouse/mousePriv.h,v 1.11 2003/11/03 05:11:49 tsi Exp $ */
/*
 * Copyright (c) 1997-1999 by The XFree86 Project, Inc.
 */

#ifndef _X_MOUSEPRIV_H
#define _X_MOUSEPRIV_H

#if 0
# define MOUSEINITDEBUG
# define MOUSEDATADEBUG
#endif

#include "mouse.h"
#include "xf86Xinput.h"                                                                                              
/* Private interface for the mouse driver. */

typedef enum  {
    AUTOPROBE_H_NOPROTO,
    AUTOPROBE_H_GOOD,
    AUTOPROBE_H_AUTODETECT,
    AUTOPROBE_H_VALIDATE1,
    AUTOPROBE_H_VALIDATE2,
    AUTOPROBE_H_SETPROTO,
    AUTOPROBE_NOPROTO,
    AUTOPROBE_COLLECT,
    AUTOPROBE_CREATE_PROTOLIST,
    AUTOPROBE_GOOD,
    AUTOPROBE_AUTODETECT,
    AUTOPROBE_VALIDATE1,
    AUTOPROBE_VALIDATE2,
    AUTOPROBE_SWITCHSERIAL,
    AUTOPROBE_SWITCH_PROTOCOL
} mseAutoProbeStates;

typedef struct {
    const char *	name;
    int			class;
    const char **	defaults;
    MouseProtocolID	id;
} MouseProtocolRec, *MouseProtocolPtr;

#define NUM_MSE_AUTOPROBE_BYTES 24  /* multiple of 3,4 and 6 byte packages */
#define NUM_MSE_AUTOPROBE_TOTAL 64
#define NUM_AUTOPROBE_PROTOS 17


typedef struct {
    int		current;
    Bool	inReset;
    CARD32	lastEvent;
    CARD32	expires;
    Bool	soft;
    int		goodCount;
    int		badCount;
    int		protocolID;
    int		count;
    char	data[NUM_MSE_AUTOPROBE_TOTAL];
    mseAutoProbeStates autoState;
    MouseProtocolID protoList[NUM_AUTOPROBE_PROTOS];
    int		serialDefaultsNum;
    int		prevDx, prevDy;
    int		accDx, accDy;
    int		acc;
    CARD32	pnpLast;
    Bool	disablePnPauto;
} mousePrivRec, *mousePrivPtr;

/* mouse proto flags */
#define MPF_NONE		0x00
#define MPF_SAFE		0x01

/* pnp.c */
MouseProtocolID MouseGetPnpProtocol(InputInfoPtr pInfo);
Bool ps2Reset(InputInfoPtr pInfo);
Bool ps2EnableDataReporting(InputInfoPtr pInfo);
Bool ps2SendPacket(InputInfoPtr pInfo, unsigned char *bytes, int len);
int ps2GetDeviceID(InputInfoPtr pInfo);

#endif /* _X_MOUSE_H */

--- NEW FILE: pnp.c ---
/* $XFree86: xc/programs/Xserver/hw/xfree86/input/mouse/pnp.c,v 1.20tsi Exp $ */
/*
 * Copyright 1998 by Kazutaka YOKOTA <yokota at zodiac.mech.utsunomiya-u.ac.jp>
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Kazutaka YOKOTA not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Kazutaka YOKOTA makes no representations
 * about the suitability of this software for any purpose.  It is provided
 * "as is" without express or implied warranty.
 *
 * KAZUTAKA YOKOTA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL KAZUTAKA YOKOTA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#define NEED_EVENTS
#include <X11/X.h>
#include <X11/Xproto.h>
#include "inputstr.h"
#include "scrnintstr.h"
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86Xinput.h"
#include "xf86_OSproc.h"
#include "xf86OSmouse.h"
#include "xf86_ansic.h"
#include "mouse.h"
#include "mousePriv.h"

#ifdef MOUSEINITDEBUG
# define DEBUG
# define EXTMOUSEDEBUG
#endif

/* serial PnP ID string */
typedef struct {
    int revision;	/* PnP revision, 100 for 1.00 */
    char *eisaid;	/* EISA ID including mfr ID and product ID */
    char *serial;	/* serial No, optional */
    char *class;	/* device class, optional */
    char *compat;	/* list of compatible drivers, optional */
    char *description;	/* product description, optional */
    int neisaid;	/* length of the above fields... */
    int nserial;
    int nclass;
    int ncompat;
    int ndescription;
} pnpid_t;

/* symbol table entry */
typedef struct {
    char *name;
    MouseProtocolID val;
} symtab_t;

/* PnP EISA/product IDs */
static symtab_t pnpprod[] = {
    { "KML0001",  PROT_THINKING },	/* Kensignton ThinkingMouse */
    { "MSH0001",  PROT_IMSERIAL },	/* MS IntelliMouse */
    { "MSH0004",  PROT_IMSERIAL },	/* MS IntelliMouse TrackBall */
    { "KYEEZ00",  PROT_MS },		/* Genius EZScroll */
    { "KYE0001",  PROT_MS },		/* Genius PnP Mouse */
    { "KYE0002",  PROT_MS },		/* MouseSystem (Genius?) SmartScroll */
    { "KYE0003",  PROT_IMSERIAL },	/* Genius NetMouse */
    { "LGI800C",  PROT_IMSERIAL },	/* Logitech MouseMan (4 button model) */
    { "LGI8033",  PROT_IMSERIAL },	/* Logitech Cordless MouseMan Wheel */
    { "LGI8050",  PROT_IMSERIAL },	/* Logitech MouseMan+ */
    { "LGI8051",  PROT_IMSERIAL },	/* Logitech FirstMouse+ */
    { "LGI8001",  PROT_LOGIMAN },	/* Logitech serial */
    { "A4W0005",  PROT_IMSERIAL },	/* A4 Tech 4D/4D+ Mouse */
    { "PEC9802",  PROT_IMSERIAL },	/* 8D Scroll Mouse */

    { "PNP0F00",  PROT_BM },		/* MS bus */
    { "PNP0F01",  PROT_MS },		/* MS serial */
    { "PNP0F02",  PROT_BM },		/* MS InPort */
    { "PNP0F03",  PROT_PS2 },		/* MS PS/2 */
    /*
     * EzScroll returns PNP0F04 in the compatible device field; but it
     * doesn't look compatible... XXX
     */
    { "PNP0F04",  PROT_MSC },		/* MouseSystems */ 
    { "PNP0F05",  PROT_MSC },		/* MouseSystems */ 
#ifdef notyet
    { "PNP0F06",  PROT_??? },		/* Genius Mouse */ 
    { "PNP0F07",  PROT_??? },		/* Genius Mouse */ 
#endif
    { "PNP0F08",  PROT_LOGIMAN },	/* Logitech serial */
    { "PNP0F09",  PROT_MS },		/* MS BallPoint serial */
    { "PNP0F0A",  PROT_MS },		/* MS PnP serial */
    { "PNP0F0B",  PROT_MS },		/* MS PnP BallPoint serial */
    { "PNP0F0C",  PROT_MS },		/* MS serial comatible */
    { "PNP0F0D",  PROT_BM },		/* MS InPort comatible */
    { "PNP0F0E",  PROT_PS2 },		/* MS PS/2 comatible */
    { "PNP0F0F",  PROT_MS },		/* MS BallPoint comatible */
#ifdef notyet
    { "PNP0F10",  PROT_??? },		/* TI QuickPort */
#endif
    { "PNP0F11",  PROT_BM },		/* MS bus comatible */
    { "PNP0F12",  PROT_PS2 },		/* Logitech PS/2 */
    { "PNP0F13",  PROT_PS2 },		/* PS/2 */
#ifdef notyet
    { "PNP0F14",  PROT_??? },		/* MS Kids Mouse */
#endif
    { "PNP0F15",  PROT_BM },		/* Logitech bus */ 
#ifdef notyet
    { "PNP0F16",  PROT_??? },		/* Logitech SWIFT */
#endif
    { "PNP0F17",  PROT_LOGIMAN },	/* Logitech serial compat */
    { "PNP0F18",  PROT_BM },		/* Logitech bus compatible */
    { "PNP0F19",  PROT_PS2 },		/* Logitech PS/2 compatible */
#ifdef notyet
    { "PNP0F1A",  PROT_??? },		/* Logitech SWIFT compatible */
    { "PNP0F1B",  PROT_??? },		/* HP Omnibook */
    { "PNP0F1C",  PROT_??? },		/* Compaq LTE TrackBall PS/2 */
    { "PNP0F1D",  PROT_??? },		/* Compaq LTE TrackBall serial */
    { "PNP0F1E",  PROT_??? },		/* MS Kids Trackball */
#endif
    { NULL,	  PROT_UNKNOWN },
};

static const char *pnpSerial[] = {
	"BaudRate",	"1200",
	"DataBits",	"7",
	"StopBits",	"1",
	"Parity",	"None",
	"FlowControl",	"None",
	"VTime",	"0",
	"VMin",		"1",
	NULL
};

static int pnpgets(InputInfoPtr, char *, Bool *prePNP);
static int pnpparse(InputInfoPtr, pnpid_t *, char *, int);
static MouseProtocolID prepnpparse(InputInfoPtr pInfo, char *buf);
static symtab_t *pnpproto(pnpid_t *);
static symtab_t *gettoken(symtab_t *, char *, int);
static MouseProtocolID getPs2ProtocolPnP(InputInfoPtr pInfo);
static MouseProtocolID probePs2ProtocolPnP(InputInfoPtr pInfo);

static MouseProtocolID
MouseGetSerialPnpProtocol(InputInfoPtr pInfo)
{
    char buf[256];	/* PnP ID string may be up to 256 bytes long */
    pnpid_t pnpid;
    symtab_t *t;
    int len;
    Bool prePNP;

    if ((len = pnpgets(pInfo, buf, &prePNP)) > 0) 
    {
	if (!prePNP) {
	    if (pnpparse(pInfo, &pnpid, buf, len) &&
		(t = pnpproto(&pnpid)) != NULL) {
		xf86MsgVerb(X_INFO, 2, "%s: PnP-detected protocol ID: %d\n",
			    pInfo->name, t->val);
		return (t->val);
	    }
	} else
	    return prepnpparse(pInfo,buf);
    }
    return PROT_UNKNOWN;
}

MouseProtocolID
MouseGetPnpProtocol(InputInfoPtr pInfo)
{
    MouseDevPtr  pMse = pInfo->private;
    mousePrivPtr mPriv = (mousePrivPtr)pMse->mousePriv;
    MouseProtocolID val;
    CARD32 last;
    
    if ((val = MouseGetSerialPnpProtocol(pInfo)) != PROT_UNKNOWN) {
	if (val == MouseGetSerialPnpProtocol(pInfo))
	    return val;
    }

#if 1
    last = mPriv->pnpLast;
    mPriv->pnpLast = currentTime.milliseconds;

    if (last) {
	if (last - currentTime.milliseconds < 100
	    || (mPriv->disablePnPauto
		&& (last - currentTime.milliseconds < 10000))) {
#ifdef EXTMOUSEDEBUG
	    xf86ErrorF("Mouse: Disabling PnP\n");
#endif
	    mPriv->disablePnPauto = TRUE;
	    return PROT_UNKNOWN;
	} 
    }
    
#ifdef EXTMOUSEDEBUG
    if (mPriv->disablePnPauto)
	xf86ErrorF("Mouse: Enabling PnP\n");
#endif
    mPriv->disablePnPauto = FALSE;

    if (mPriv->soft)
	return getPs2ProtocolPnP(pInfo);
    else
	return probePs2ProtocolPnP(pInfo);
#else
    return PROT_UNKNOWN;
#endif
}

/*
 * Try to elicit a PnP ID as described in 
 * Microsoft, Hayes: "Plug and Play External COM Device Specification, 
 * rev 1.00", 1995.
 *
 * The routine does not fully implement the COM Enumerator as per Section
 * 2.1 of the document.  In particular, we don't have idle state in which
 * the driver software monitors the com port for dynamic connection or 
 * removal of a device at the port, because `moused' simply quits if no 
 * device is found.
 *
 * In addition, as PnP COM device enumeration procedure slightly has 
 * changed since its first publication, devices which follow earlier
 * revisions of the above spec. may fail to respond if the rev 1.0 
 * procedure is used. XXX
 */
static int
pnpgets(InputInfoPtr pInfo, char *buf, Bool *prePNP)
{
    int i;
    char c;
    pointer pnpOpts;
    
#if 0
    /* 
     * This is the procedure described in rev 1.0 of PnP COM device spec.
     * Unfortunately, some devices which comform to earlier revisions of
     * the spec gets confused and do not return the ID string...
     */

    /* port initialization (2.1.2) */
    if ((i = xf86GetSerialModemState(pInfo->fd)) == -1)
	return 0;
    i |= XF86_M_DTR;		/* DTR = 1 */
    i &= ~XF86_M_RTS;		/* RTS = 0 */
    if (xf86SetSerialModemState(pInfo->fd, i) == -1)
	goto disconnect_idle;
    usleep(200000);
    if ((i = xf86GetSerialModemState(pInfo->fd)) == -1 ||
	(i & XF86_M_DSR) == 0)
	goto disconnect_idle;

    /* port setup, 1st phase (2.1.3) */
    pnpOpts = xf86OptionListCreate(pnpSerial, -1, 1);
    xf86SetSerial(pInfo->fd, pnpOpts);
    i = TIOCM_DTR | TIOCM_RTS;	/* DTR = 0, RTS = 0 */
    xf86SerialModemClearBits(pInfo->fd, i);
    usleep(200000);
    i = TIOCM_DTR;		/* DTR = 1, RTS = 0 */
    xf86SerialModemSetBits(pInfo->fd, i);
    usleep(200000);

    /* wait for response, 1st phase (2.1.4) */
    xf86FlushInput(pInfo->fd);
    i = TIOCM_RTS;		/* DTR = 1, RTS = 1 */
    xf86SerialModemSetBits(pInfo->fd, i);

    /* try to read something */
    if (xf86WaitForInput(pInfo->fd, 200000) <= 0) {

	/* port setup, 2nd phase (2.1.5) */
        i = TIOCM_DTR | TIOCM_RTS;	/* DTR = 0, RTS = 0 */
	xf86SerialModemClearBits(pInfo->fd, i);
        usleep(200000);

	/* wait for respose, 2nd phase (2.1.6) */
	xf86FlushInput(pInfo->fd);
        i = TIOCM_DTR | TIOCM_RTS;	/* DTR = 1, RTS = 1 */
	xf86SerialModemSetBits(pInfo->fd, i);

        /* try to read something */
	if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
	    goto connect_idle;
    }
#else
    /*
     * This is a simplified procedure; it simply toggles RTS.
     */

    if ((i = xf86GetSerialModemState(pInfo->fd)) == -1)
	return 0;
    i |= XF86_M_DTR;		/* DTR = 1 */
    i &= ~XF86_M_RTS;		/* RTS = 0 */
    if (xf86SetSerialModemState(pInfo->fd, i) == -1)
	goto disconnect_idle;
    usleep(200000);

    pnpOpts = xf86OptionListCreate(pnpSerial, -1, 1);
    xf86SetSerial(pInfo->fd, pnpOpts);

    /* wait for respose */
    xf86FlushInput(pInfo->fd);
    i = XF86_M_DTR | XF86_M_RTS;	/* DTR = 1, RTS = 1 */
    xf86SerialModemSetBits(pInfo->fd, i);

    /* try to read something */
    if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
        goto connect_idle;
#endif

    /* collect PnP COM device ID (2.1.7) */
    i = 0;
    *prePNP = FALSE;
    
    usleep(200000);	/* the mouse must send `Begin ID' within 200msec */
    while (xf86ReadSerial(pInfo->fd, &c, 1) == 1) {
	/* we may see "M", or "M3..." before `Begin ID' */
	if (c == 'M') 
	    *prePNP = TRUE;

        if ((c == 0x08) || (c == 0x28)) {	/* Begin ID */
	    *prePNP = FALSE;
	    buf[0] = c;
	    i = 1;
	    break;
        }
	if (*prePNP)
	    buf[i++] = c;
	
	if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
	    break;
    }
    if (i <= 0) {
	/* we haven't seen `Begin ID' in time... */
	goto connect_idle;
    }
    if (*prePNP)
	return i;
    
    ++c;			/* make it `End ID' */
    for (;;) {
	if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
	    break;

	xf86ReadSerial(pInfo->fd, &buf[i], 1);
        if (buf[i++] == c)	/* End ID */
	    break;
	if (i >= 256)
	    break;
    }
    if (buf[i - 1] != c)
	goto connect_idle;
    return i;

    /*
     * According to PnP spec, we should set DTR = 1 and RTS = 0 while 
     * in idle state.  But, `moused' shall set DTR = RTS = 1 and proceed, 
     * assuming there is something at the port even if it didn't 
     * respond to the PnP enumeration procedure.
     */
disconnect_idle:
    i = XF86_M_DTR | XF86_M_RTS;		/* DTR = 1, RTS = 1 */
    xf86SerialModemSetBits(pInfo->fd, i);
connect_idle:
    return 0;
}

static int
pnpparse(InputInfoPtr pInfo, pnpid_t *id, char *buf, int len)
{
    char s[3];
    int offset;
    int sum = 0;
    int i, j;

    id->revision = 0;
    id->eisaid = NULL;
    id->serial = NULL;
    id->class = NULL;
    id->compat = NULL;
    id->description = NULL;
    id->neisaid = 0;
    id->nserial = 0;
    id->nclass = 0;
    id->ncompat = 0;
    id->ndescription = 0;

    offset = 0x28 - buf[0];

    /* calculate checksum */
    for (i = 0; i < len - 3; ++i) {
	sum += buf[i];
	buf[i] += offset;
    }
    sum += buf[len - 1];
    for (; i < len; ++i)
	buf[i] += offset;
    xf86MsgVerb(X_INFO, 2, "%s: PnP ID string: `%*.*s'\n", pInfo->name,
		len, len, buf);

    /* revision */
    buf[1] -= offset;
    buf[2] -= offset;
    id->revision = ((buf[1] & 0x3f) << 6) | (buf[2] & 0x3f);
    xf86MsgVerb(X_INFO, 2, "%s: PnP rev %d.%02d\n", pInfo->name,
		id->revision / 100, id->revision % 100);

    /* EISA vender and product ID */
    id->eisaid = &buf[3];
    id->neisaid = 7;

    /* option strings */
    i = 10;
    if (buf[i] == '\\') {
        /* device serial # */
        for (j = ++i; i < len; ++i) {
            if (buf[i] == '\\')
		break;
        }
	if (i >= len)
	    i -= 3;
	if (i - j == 8) {
            id->serial = &buf[j];
            id->nserial = 8;
	}
    }
    if (buf[i] == '\\') {
        /* PnP class */
        for (j = ++i; i < len; ++i) {
            if (buf[i] == '\\')
		break;
        }
	if (i >= len)
	    i -= 3;
	if (i > j + 1) {
            id->class = &buf[j];
            id->nclass = i - j;
        }
    }
    if (buf[i] == '\\') {
	/* compatible driver */
        for (j = ++i; i < len; ++i) {
            if (buf[i] == '\\')
		break;
        }
	/*
	 * PnP COM spec prior to v0.96 allowed '*' in this field, 
	 * it's not allowed now; just ignore it.
	 */
	if (buf[j] == '*')
	    ++j;
	if (i >= len)
	    i -= 3;
	if (i > j + 1) {
            id->compat = &buf[j];
            id->ncompat = i - j;
        }
    }
    if (buf[i] == '\\') {
	/* product description */
        for (j = ++i; i < len; ++i) {
            if (buf[i] == ';')
		break;
        }
	if (i >= len)
	    i -= 3;
	if (i > j + 1) {
            id->description = &buf[j];
            id->ndescription = i - j;
        }
    }

    /* checksum exists if there are any optional fields */
    if ((id->nserial > 0) || (id->nclass > 0)
	|| (id->ncompat > 0) || (id->ndescription > 0)) {
	xf86MsgVerb(X_INFO, 4, "%s: PnP checksum: 0x%02X\n", pInfo->name, sum);
        sprintf(s, "%02X", sum & 0x0ff);
        if (strncmp(s, &buf[len - 3], 2) != 0) {
#if 0
            /* 
	     * Checksum error!!
	     * I found some mice do not comply with the PnP COM device 
	     * spec regarding checksum... XXX
	     */
	    return FALSE;
#endif
        }
    }

    return TRUE;
}

/* We can only identify MS at the moment */
static MouseProtocolID
prepnpparse(InputInfoPtr pInfo, char *buf)
{
    if (buf[0] == 'M' && buf[1] == '3')
	return PROT_MS;
    return PROT_UNKNOWN;
}


static symtab_t *
pnpproto(pnpid_t *id)
{
    symtab_t *t;
    int i, j;

    if (id->nclass > 0)
	if (strncmp(id->class, "MOUSE", id->nclass) != 0)
	    /* this is not a mouse! */
	    return NULL;

    if (id->neisaid > 0) {
        t = gettoken(pnpprod, id->eisaid, id->neisaid);
	if (t->val != -1)
            return t;
    }

    /*
     * The 'Compatible drivers' field may contain more than one
     * ID separated by ','.
     */
    if (id->ncompat <= 0)
	return NULL;
    for (i = 0; i < id->ncompat; ++i) {
        for (j = i; id->compat[i] != ','; ++i)
            if (i >= id->ncompat)
		break;
        if (i > j) {
            t = gettoken(pnpprod, id->compat + j, i - j);
	    if (t->val != -1)
                return t;
	}
    }

    return NULL;
}

/* name/val mapping */

static symtab_t *
gettoken(tab, s, len)
symtab_t *tab;
char *s;
int len;
{
    int i;

    for (i = 0; tab[i].name != NULL; ++i) {
	if (strncmp(tab[i].name, s, len) == 0)
	    break;
    }
    return &tab[i];
}

/******************* PS/2 PnP probing ****************/

static int
readMouse(InputInfoPtr pInfo, unsigned char *u)
{

    if (xf86WaitForInput(pInfo->fd, 200000) <= 0)
	return FALSE;

    xf86ReadSerial(pInfo->fd, u, 1);
    return TRUE;
}

static void
ps2DisableWrapMode(InputInfoPtr pInfo)
{
    unsigned char reset_wrap_mode[] = { 0xEC };
    ps2SendPacket(pInfo, reset_wrap_mode, sizeof(reset_wrap_mode));
}

Bool
ps2SendPacket(InputInfoPtr pInfo, unsigned char *bytes, int len)
{
    unsigned char c;
    int i,j;
    
#ifdef DEBUG
    xf86ErrorF("Ps/2 data package:");
    for (i = 0; i < len; i++)
	xf86ErrorF(" %x", *(bytes + i));
    xf86ErrorF("\n");
#endif

    for (i = 0; i < len; i++) {
	for (j = 0; j < 10; j++) {
	    xf86WriteSerial(pInfo->fd, bytes + i, 1);
	    usleep(10000);
	    if (!readMouse(pInfo,&c)) {
#ifdef DEBUG
		xf86ErrorF("sending 0x%x to PS/2 unsuccessful\n",*(bytes + i));
#endif
		return FALSE;
	    }
#ifdef DEBUG
	    xf86ErrorF("Recieved: 0x%x\n",c);
#endif
	    if (c == 0xFA) /* ACK */
		break;

	    if (c == 0xFE) /* resend */
		continue;
	    

	    if (c == 0xFC) /* error */
		return FALSE;

	    /* Some mice accidently enter wrap mode during init */
	    if (c == *(bytes + i)    /* wrap mode */
		&& (*(bytes + i) != 0xEC)) /* avoid recursion */
		ps2DisableWrapMode(pInfo);

	    return FALSE;
	}
	if (j == 10)
	    return FALSE;
    }
    
    return TRUE;
}
    
static Bool
ps2DisableDataReporting(InputInfoPtr pInfo)
{
    unsigned char packet[] = { 0xF5 };
    return ps2SendPacket(pInfo, packet, sizeof(packet));
}

Bool
ps2EnableDataReporting(InputInfoPtr pInfo)
{
    unsigned char packet[] = { 0xF4 };
    return ps2SendPacket(pInfo, packet, sizeof(packet));
}

int
ps2GetDeviceID(InputInfoPtr pInfo)
{
    unsigned char u;
    unsigned char packet[] = { 0xf2 };

    usleep(30000);
    xf86FlushInput(pInfo->fd);
    if (!ps2SendPacket(pInfo, packet, sizeof(packet))) 
	return -1;
    while (1) {
	if (!readMouse(pInfo,&u))
	    return -1;
	if (u != 0xFA)
	    break;
    }
#ifdef DEBUG
    xf86ErrorF("Obtained Mouse Type: %x\n",u);
#endif
    return (int) u;
}

Bool
ps2Reset(InputInfoPtr pInfo)
{
    unsigned char u;
    unsigned char packet[] = { 0xff };
    unsigned char reply[] = { 0xaa, 0x00 };
    unsigned int i;
#ifdef DEBUG
   xf86ErrorF("PS/2 Mouse reset\n");
#endif
    if (!ps2SendPacket(pInfo, packet, sizeof(packet))) 
	return FALSE;
    /* we need a little delay here */
    xf86WaitForInput(pInfo->fd, 500000);
    for (i = 0; i < sizeof(reply) ; i++) {
	if (!readMouse(pInfo,&u)) {
	    goto EXIT;
	}
	if (u != reply[i]) 
	    goto EXIT;
    }
    return TRUE;
    
 EXIT:
    xf86FlushInput(pInfo->fd);
    return FALSE;
}

static MouseProtocolID
probePs2ProtocolPnP(InputInfoPtr pInfo)
{
    unsigned char u;
    MouseProtocolID ret = PROT_UNKNOWN;

    xf86FlushInput(pInfo->fd);

    ps2DisableDataReporting(pInfo);
    
    if (ps2Reset(pInfo)) { /* Reset PS2 device */
  	unsigned char seq[] = { 243, 200, 243, 100, 243, 80 }; 
	/* Try to identify Intelli Mouse */
	if (ps2SendPacket(pInfo, seq, sizeof(seq))) {
	    u = ps2GetDeviceID(pInfo);
	    if (u == 0x03) {
		/* found IntelliMouse now try IntelliExplorer */
		unsigned char seq[] = { 243, 200, 243, 200, 243, 80 };
		if (ps2SendPacket(pInfo,seq,sizeof(seq))) {
		    u = ps2GetDeviceID(pInfo);
		    if (u == 0x04)
			ret =  PROT_EXPPS2;
		    else 
			ret = PROT_IMPS2;
		} 
	    } else if (ps2Reset(pInfo))  /* reset again to find sane state */
		ret = PROT_PS2;
	}
    
	if (ret != PROT_UNKNOWN) 
	    ps2EnableDataReporting(pInfo);
    }
    return ret;
}

static struct ps2protos {
    int Id; 
    MouseProtocolID protoID;
} ps2 [] = {
    { 0x0, PROT_PS2 },
    { 0x3, PROT_IMPS2 },
    { 0x4, PROT_EXPPS2 },
    { -1 , PROT_UNKNOWN }
};


static MouseProtocolID
getPs2ProtocolPnP(InputInfoPtr pInfo)
{
    int Id;
    int i;
    MouseProtocolID proto;
    int count = 4;

    xf86FlushInput(pInfo->fd);

    while (--count)
	if (ps2DisableDataReporting(pInfo))
	    break;
    
    if (!count) {
	proto = PROT_UNKNOWN;
	goto EXIT;
    }
    
    if ((Id = ps2GetDeviceID(pInfo)) == -1) {
	proto = PROT_UNKNOWN;
	goto EXIT;
    }

    if (-1 == ps2EnableDataReporting(pInfo)) {
	proto = PROT_UNKNOWN;
	goto EXIT;
    }

    for (i = 0; ps2[i].protoID != PROT_UNKNOWN; i++) {
	if (ps2[i].Id == Id) {
	    xf86MsgVerb(X_PROBED,2,"Found PS/2 proto ID %x\n",Id);
	    proto =  ps2[i].protoID;
	    goto EXIT;
	}
    }
    
    proto = PROT_UNKNOWN;
    xf86Msg(X_ERROR,"Found unknown PS/2 proto ID %x\n",Id);
    
 EXIT:
    xf86FlushInput(pInfo->fd);
    return proto;
}





More information about the xserver-commit mailing list