summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:56 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 16:48:56 +0000
commitdfee8a2321bf8c77a14ffbc4a74e11dff7fdb54c (patch)
tree18b0f7dcaf0ee5b4cf2edd51abe0e618abef61f6
-rw-r--r--man/penmount.man39
-rw-r--r--src/xf86PM.c758
-rw-r--r--src/xf86PM.h98
3 files changed, 895 insertions, 0 deletions
diff --git a/man/penmount.man b/man/penmount.man
new file mode 100644
index 0000000..a51ac80
--- /dev/null
+++ b/man/penmount.man
@@ -0,0 +1,39 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/penmount/penmount.man,v 1.3 2001/08/17 13:27:57 dawes Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH PENMOUNT __drivermansuffix__ __vendorversion__
+.SH NAME
+penmount \- PenMount input driver
+.SH SYNOPSIS
+.B "Section \*qInputDevice\*q"
+.br
+.BI " Identifier \*q" idevname \*q
+.br
+.B " Driver \*qpenmount\*q"
+.br
+.BI " Option \*qDevice\*q \*q" devpath \*q
+.br
+\ \ ...
+.br
+.B EndSection
+.SH DESCRIPTION
+.B penmount
+is an XFree86 input driver for PenMount devices...
+.PP
+The
+.B penmount
+driver functions as a pointer input device, and may be used as the
+X server's core pointer.
+THIS MAN PAGE NEEDS TO BE FILLED IN.
+.SH SUPPORTED HARDWARE
+What is supported...
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(__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
+Config details...
+.SH "SEE ALSO"
+XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__).
+.SH AUTHORS
+Authors include...
diff --git a/src/xf86PM.c b/src/xf86PM.c
new file mode 100644
index 0000000..2e89b90
--- /dev/null
+++ b/src/xf86PM.c
@@ -0,0 +1,758 @@
+/*
+ * Copyright (c) 1999 Machine Vision Holdings Incorporated
+ * Author: David Woodhouse <David.Woodhouse@mvhi.com>
+ * CoAuthor: Mayk Langer <langer@vsys.de>
+ *
+ * Template driver used: Copyright (c) 1998 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, cpy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/input/penmount/xf86PM.c,v 1.3 2001/11/26 16:25:53 dawes Exp $ */
+
+#define _PENMOUNT_C_
+
+#include <misc.h>
+#include <xf86.h>
+#define NEED_XF86_TYPES
+#include <xf86_ansic.h>
+#include <xf86_OSproc.h>
+#include <xf86Xinput.h>
+#include <xisb.h>
+#include <exevents.h>
+
+#include "xf86PM.h"
+
+InputDriverRec PENMOUNT = {
+ 1,
+ "penmount",
+ NULL,
+ PenMountPreInit,
+ /*PenMountUnInit*/NULL,
+ NULL,
+ 0
+};
+
+
+
+#ifdef XFree86LOADER
+
+static XF86ModuleVersionInfo VersionRec =
+{
+ "penmount",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_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 */
+};
+
+
+static const char *reqSymbols[] = {
+ "AddEnabledDevice",
+ "ErrorF",
+ "InitButtonClassDeviceStruct",
+ "InitProximityClassDeviceStruct",
+ "InitValuatorAxisStruct",
+ "InitValuatorClassDeviceStruct",
+ "InitPtrFeedbackClassDeviceStruct",
+ "RemoveEnabledDevice",
+ "Xcalloc",
+ "Xfree",
+ "XisbBlockDuration",
+ "XisbFree",
+ "XisbNew",
+ "XisbRead",
+ "XisbTrace",
+ "screenInfo",
+ "xf86AddInputDriver",
+ "xf86AllocateInput",
+ "xf86CloseSerial",
+ "xf86CollectInputOptions",
+ "xf86ErrorFVerb",
+ "xf86FindOptionValue",
+ "xf86GetMotionEvents",
+ "xf86GetVerbosity",
+ "xf86MotionHistoryAllocate",
+ "xf86NameCmp",
+ "xf86OpenSerial",
+ "xf86OptionListCreate",
+ "xf86OptionListMerge",
+ "xf86OptionListReport",
+ "xf86PostButtonEvent",
+ "xf86PostMotionEvent",
+ "xf86PostProximityEvent",
+ "xf86ProcessCommonOptions",
+ "xf86ScaleAxis",
+ "xf86SetIntOption",
+ "xf86SetStrOption",
+ "xf86XInputSetScreen",
+ "xf86XInputSetSendCoreEvents",
+ NULL
+};
+
+
+static pointer
+PenMountSetupProc( pointer module,
+ pointer options,
+ int *errmaj,
+ int *errmin )
+{
+ xf86LoaderReqSymLists(reqSymbols, NULL);
+ xf86AddInputDriver(&PENMOUNT, module, 0);
+ return (pointer) 1;
+}
+
+XF86ModuleData penmountModuleData = { &VersionRec, PenMountSetupProc, NULL };
+
+
+#endif /* XFree86LOADER */
+
+
+/*
+ * Be sure to set vmin appropriately for your device's protocol. You want to
+ * read a full packet before returning
+ */
+static const char *default_options[] =
+{
+ /* "Device", "/dev/ttyS1",*/
+ "BaudRate", "19200",
+ "StopBits", "1",
+ "DataBits", "8",
+ "Parity", "None",
+ "Vmin", "3",
+ "Vtime", "1",
+ "FlowControl", "None",
+ NULL,
+};
+
+
+/*****************************************************************************
+ * Function Definitions
+ ****************************************************************************/
+
+
+
+static InputInfoPtr
+PenMountPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
+{
+ InputInfoPtr pInfo;
+ PenMountPrivatePtr priv = xcalloc (1, sizeof (PenMountPrivateRec));
+ char *s;
+
+ if (!priv)
+ return NULL;
+
+ if (!(pInfo = xf86AllocateInput(drv, 0))) {
+ xfree(priv);
+ return NULL;
+ }
+
+ priv->min_x = 0;
+ priv->max_x = 1024;
+ priv->min_y = 768;
+ priv->max_y = 0;
+ priv->screen_num = 0;
+ priv->screen_width = -1;
+ priv->screen_height = -1;
+ priv->lex_mode = PenMount_byte0;
+ priv->swap_xy = 0;
+ priv->button_down = FALSE;
+ priv->button_number = 1;
+ priv->proximity = FALSE;
+ priv->chip = CHIP_UNKNOWN;
+ priv->pen_down = 0;
+
+ pInfo->type_name = XI_TOUCHSCREEN;
+ pInfo->device_control = DeviceControl;
+ pInfo->read_input = ReadInput;
+ pInfo->control_proc = ControlProc;
+ pInfo->close_proc = CloseProc;
+ pInfo->switch_mode = SwitchMode;
+ pInfo->conversion_proc = ConvertProc;
+ pInfo->dev = NULL;
+ pInfo->private = priv;
+ pInfo->private_flags = 0;
+ pInfo->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
+ pInfo->conf_idev = dev;
+
+ xf86CollectInputOptions(pInfo, default_options, NULL);
+
+ xf86OptionListReport( pInfo->options );
+
+ pInfo->fd = xf86OpenSerial (pInfo->options);
+ if (pInfo->fd == -1)
+ {
+ ErrorF ("PenMount driver unable to open device\n");
+ goto SetupProc_fail;
+ }
+ xf86CloseSerial(pInfo->fd);
+ /*
+ * Process the options for your device like this
+ */
+ priv->min_x = xf86SetIntOption( pInfo->options, "MinX", 0 );
+ priv->max_x = xf86SetIntOption( pInfo->options, "MaxX", 1024 );
+ priv->min_y = xf86SetIntOption( pInfo->options, "MinY", 768 );
+ priv->max_y = xf86SetIntOption( pInfo->options, "MaxY", 0 );
+ priv->screen_num = xf86SetIntOption( pInfo->options, "ScreenNumber", 0 );
+ priv->button_number = xf86SetIntOption( pInfo->options, "ButtonNumber", 1 );
+ priv->swap_xy = xf86SetIntOption( pInfo->options, "SwapXY", 0 );
+ priv->buffer = NULL;
+ s = xf86FindOptionValue (pInfo->options, "ReportingMode");
+ if ((s) && (xf86NameCmp (s, "raw") == 0))
+ priv->reporting_mode = TS_Raw;
+ else
+ priv->reporting_mode = TS_Scaled;
+
+ priv->proximity = FALSE;
+ priv->button_down = FALSE;
+ priv->lex_mode = PenMount_byte0;
+
+ if (QueryHardware (priv) != Success)
+ {
+ ErrorF ("Unable to query/initialize PenMount hardware.\n");
+ goto SetupProc_fail;
+ }
+
+ /* this results in an xstrdup that must be freed later */
+ pInfo->name = xf86SetStrOption( pInfo->options, "DeviceName", "PenMount");
+ xf86ProcessCommonOptions(pInfo, pInfo->options);
+
+ pInfo->flags |= XI86_CONFIGURED;
+ return (pInfo);
+
+ SetupProc_fail:
+ if ((pInfo) && (pInfo->fd))
+ xf86CloseSerial (pInfo->fd);
+ if ((pInfo) && (pInfo->name))
+ xfree (pInfo->name);
+
+ if ((priv) && (priv->buffer))
+ XisbFree (priv->buffer);
+ if (priv)
+ xfree (priv);
+ return (pInfo);
+}
+
+static Bool
+DeviceControl (DeviceIntPtr dev, int mode)
+{
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ PenMountPrivatePtr priv = (PenMountPrivatePtr) (pInfo->private);
+ unsigned char map[] =
+ {0, 1};
+
+ switch (mode)
+ {
+ case DEVICE_INIT:
+ /*
+ * these have to be here instead of in the SetupProc, because when the
+ * SetupProc is run at server startup, screenInfo is not setup yet
+ */
+ priv->screen_width = screenInfo.screens[priv->screen_num]->width;
+ priv->screen_height = screenInfo.screens[priv->screen_num]->height;
+
+ /*
+ * Device reports button press for 1 button.
+ */
+ if (InitButtonClassDeviceStruct (dev, 1, map) == FALSE)
+ {
+ ErrorF ("Unable to allocate PenMount ButtonClassDeviceStruct\n");
+ return !Success;
+ }
+
+ /*
+ * Device reports motions on 2 axes in absolute coordinates.
+ * Axes min and max values are reported in raw coordinates.
+ */
+ if (InitValuatorClassDeviceStruct (dev, 2, xf86GetMotionEvents,
+ pInfo->history_size, Absolute) == FALSE)
+ {
+ ErrorF ("Unable to allocate PenMount ValuatorClassDeviceStruct\n");
+ return !Success;
+ }
+ else
+ {
+ InitValuatorAxisStruct (dev, 0, priv->min_x, priv->max_x,
+ 9500,
+ 0 /* min_res */ ,
+ 9500 /* max_res */ );
+ InitValuatorAxisStruct (dev, 1, priv->min_y, priv->max_y,
+ 10500,
+ 0 /* min_res */ ,
+ 10500 /* max_res */ );
+ }
+
+ if (InitProximityClassDeviceStruct (dev) == FALSE)
+ {
+ ErrorF ("unable to allocate PenMount ProximityClassDeviceStruct\n");
+ return !Success;
+ }
+
+ if (InitPtrFeedbackClassDeviceStruct(dev, PenMountPtrCtrl) == FALSE)
+ {
+ ErrorF ("unable to allocate PenMount PtrFeedbackClassDeviceStruct\n");
+ return !Success;
+ }
+
+ /*
+ * Allocate the motion events buffer.
+ */
+ xf86MotionHistoryAllocate (pInfo);
+ return (Success);
+
+ case DEVICE_ON:
+ pInfo->fd = xf86OpenSerial(pInfo->options);
+ if (pInfo->fd == -1)
+ {
+ xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
+ return (!Success);
+ }
+ else
+ {
+ priv->buffer = XisbNew(pInfo->fd, 64);
+ if (!priv->buffer)
+ {
+ xf86CloseSerial(pInfo->fd);
+ pInfo->fd = -1;
+ return (!Success);
+ }
+/* if (isatty (pInfo->fd)) check if DMC8910 is found */
+ {
+/* echo Success Code */
+ unsigned char buf[5] = { 'D', 'G', 0x02, 0x80, 0x00 };
+
+ XisbBlockDuration (priv->buffer, 500000);
+ if ( PenMountSendPacket(priv, buf, 5) == Success )
+ {
+ /* wait for right response */
+ priv->lex_mode = PenMount_Response0;
+ if (PenMountGetPacket (priv) == Success )
+ {
+ if (( priv->packet[0] == 0xff ) &&
+ ( priv->packet[1] == 0x70 ) )
+ {
+ priv->chip = DMC8910;
+ /* disable DMC8910 */
+ buf[2] = 0x0b;
+ buf[3] = 0x00;
+ buf[4] = 0x00;
+ PenMountSendPacket(priv,buf,5);
+ priv->lex_mode = PenMount_Response0;
+ PenMountGetPacket(priv);
+ /* set screen width */
+ buf[2] = 0x02;
+ buf[3] = (priv->screen_width & 0x0fff) >> 8;
+ buf[4] = priv->screen_width & 0xff;
+ PenMountSendPacket(priv,buf,5);
+ priv->lex_mode = PenMount_Response0;
+ PenMountGetPacket(priv);
+ /* set screen height */
+ buf[2] = 0x02;
+ buf[3] = (priv->screen_height & 0x0fff) >> 8;
+ buf[4] = priv->screen_height & 0xff;
+ buf[3] |= 0x10;
+ PenMountSendPacket(priv,buf,5);
+ priv->lex_mode = PenMount_Response0;
+ PenMountGetPacket(priv);
+ /* enable DMC8910 */
+ buf[2] = 0x0a;
+ buf[3] = 0x01;
+ buf[4] = 0x00;
+ PenMountSendPacket(priv,buf,5);
+ priv->lex_mode = PenMount_Response0;
+ PenMountGetPacket(priv);
+ }
+ }
+ }
+ }
+ }
+
+ XisbBlockDuration (priv->buffer, -1);
+ priv->lex_mode = PenMount_byte0;
+
+ xf86FlushInput(pInfo->fd);
+ AddEnabledDevice (pInfo->fd);
+ dev->public.on = TRUE;
+ return (Success);
+
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ if (pInfo->fd != -1)
+ {
+ RemoveEnabledDevice (pInfo->fd);
+ if (priv->buffer)
+ {
+ XisbFree(priv->buffer);
+ priv->buffer = NULL;
+ }
+ xf86CloseSerial(pInfo->fd);
+ }
+ dev->public.on = FALSE;
+ return (Success);
+ default:
+ return (BadValue);
+ }
+
+}
+
+
+/*
+ * The ReadInput function will have to be tailored to your device
+ */
+static void
+ReadInput (InputInfoPtr pInfo)
+{
+ PenMountPrivatePtr priv = (PenMountPrivatePtr) (pInfo->private);
+ int x,y;
+ unsigned char opck[ PENMOUNT_PACKET_SIZE ];
+
+ /*
+ * set blocking to -1 on the first call because we know there is data to
+ * read. Xisb automatically clears it after one successful read so that
+ * succeeding reads are preceeded buy a select with a 0 timeout to prevent
+ * read from blocking indefinately.
+ */
+ XisbBlockDuration (priv->buffer, -1);
+ while (1)
+ {
+ if ( priv->chip != DMC8910 )
+ {
+ if ( PenMountGetPacket (priv) != Success)
+ break;
+ if (( priv->packet[0] & 0x0C ) != 0x0C )
+ break;
+ if (priv->swap_xy) {
+ y = priv->packet[1];
+ y |= (priv->packet[0] & 0x10) ? 0x100 : 0;
+ y |= (priv->packet[0] & 0x40) ? 0x200 : 0;
+ x = priv->packet[2];
+ x |= (priv->packet[0] & 0x20) ? 0x100 : 0;
+ x |= (priv->packet[0] & 0x80) ? 0x200 : 0;
+ } else {
+ x = priv->packet[1];
+ x |= (priv->packet[0] & 0x10) ? 0x100 : 0;
+ x |= (priv->packet[0] & 0x40) ? 0x200 : 0;
+ y = priv->packet[2];
+ y |= (priv->packet[0] & 0x20) ? 0x100 : 0;
+ y |= (priv->packet[0] & 0x80) ? 0x200 : 0;
+ }
+ }
+ else
+ {
+ memcpy(opck,priv->packet,5);
+ if ( PenMountGetPacket (priv) != Success )
+ break;
+ if (( priv->packet[1] == 0xfd ) && ( priv->packet[2] == 0xfd ))
+ {
+ priv->pen_down = 1;
+ continue;
+ }
+ if (( priv->packet[1] == 0xfe ) && ( priv->packet[2] == 0xfe ))
+ {
+ memcpy(priv->packet,opck,5);
+ if ( !priv->pen_down )
+ continue;
+ priv->pen_down = 0;
+ }
+ if ( priv->swap_xy)
+ {
+ y = priv->packet[1]*256+priv->packet[2];
+ x = priv->packet[3]*256+priv->packet[4];
+ }
+ else
+ {
+ x = priv->packet[1]*256+priv->packet[2];
+ y = priv->packet[3]*256+priv->packet[4];
+ }
+ priv->packet[0] = priv->pen_down ? 0x01 : 0x00;
+ }
+
+ if (priv->reporting_mode == TS_Scaled)
+ {
+ x = xf86ScaleAxis (x, 0, priv->screen_width, priv->min_x,
+ priv->max_x);
+ y = xf86ScaleAxis (y, 0, priv->screen_height, priv->min_y,
+ priv->max_y);
+ }
+
+ xf86XInputSetScreen (pInfo, priv->screen_num, x, y);
+
+ if ((priv->proximity == FALSE) && (priv->packet[0] & 0x01))
+ {
+ priv->proximity = TRUE;
+ xf86PostProximityEvent (pInfo->dev, 1, 0, 2, x, y);
+ }
+
+ /*
+ * Send events.
+ *
+ * We *must* generate a motion before a button change if pointer
+ * location has changed as DIX assumes this. This is why we always
+ * emit a motion, regardless of the kind of packet processed.
+ */
+
+ xf86PostMotionEvent (pInfo->dev, TRUE, 0, 2, x, y);
+
+ /*
+ * Emit a button press or release.
+ */
+ if ((priv->button_down == FALSE) && (priv->packet[0] & 0x01))
+
+ {
+ xf86PostButtonEvent (pInfo->dev, TRUE,
+ priv->button_number, 1, 0, 2, x, y);
+ priv->button_down = TRUE;
+ }
+ if ((priv->button_down == TRUE) && !(priv->packet[0] & 0x01))
+ {
+ xf86PostButtonEvent (pInfo->dev, TRUE,
+ priv->button_number, 0, 0, 2, x, y);
+ priv->button_down = FALSE;
+ }
+ /*
+ * the untouch should always come after the button release
+ */
+ if ((priv->proximity == TRUE) && !(priv->packet[0] & 0x01))
+ {
+ priv->proximity = FALSE;
+ xf86PostProximityEvent (pInfo->dev, 0, 0, 2, x, y);
+ }
+ }
+}
+
+/*
+ * The ControlProc function may need to be tailored for your device
+ */
+static int
+ControlProc (InputInfoPtr pInfo, xDeviceCtl * control)
+{
+ xDeviceTSCalibrationCtl *c = (xDeviceTSCalibrationCtl *) control;
+ PenMountPrivatePtr priv = (PenMountPrivatePtr) (pInfo->private);
+
+ priv->min_x = c->min_x;
+ priv->max_x = c->max_x;
+ priv->min_y = c->min_y;
+ priv->max_y = c->max_y;
+
+ return (Success);
+}
+
+/*
+ * the CloseProc should not need to be tailored to your device
+ */
+static void
+CloseProc (InputInfoPtr pInfo)
+{
+
+}
+
+/*
+ * The SwitchMode function may need to be tailored for your device
+ */
+static int
+SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode)
+{
+ InputInfoPtr pInfo = dev->public.devicePrivate;
+ PenMountPrivatePtr priv = (PenMountPrivatePtr) (pInfo->private);
+
+
+ if ((mode == TS_Raw) || (mode == TS_Scaled))
+ {
+ priv->reporting_mode = mode;
+ return (Success);
+ }
+ else if ((mode == SendCoreEvents) || (mode == DontSendCoreEvents))
+ {
+ xf86XInputSetSendCoreEvents (pInfo, (mode == SendCoreEvents));
+ return (Success);
+ }
+ else
+ return (!Success);
+}
+
+/*
+ * The ConvertProc function may need to be tailored for your device.
+ * This function converts the device's valuator outputs to x and y coordinates
+ * to simulate mouse events.
+ */
+static Bool
+ConvertProc (InputInfoPtr pInfo,
+ int first,
+ int num,
+ int v0,
+ int v1,
+ int v2,
+ int v3,
+ int v4,
+ int v5,
+ int *x,
+ int *y)
+{
+ PenMountPrivatePtr priv = (PenMountPrivatePtr) (pInfo->private);
+
+ if (priv->reporting_mode == TS_Raw)
+ {
+ *x = xf86ScaleAxis (v0, 0, priv->screen_width, priv->min_x,
+ priv->max_x);
+ *y = xf86ScaleAxis (v1, 0, priv->screen_height, priv->min_y,
+ priv->max_y);
+ }
+ else
+ {
+ *x = v0;
+ *y = v1;
+ }
+ return (TRUE);
+}
+
+/*
+ * the QueryHardware fuction should be tailored to your device to
+ * verify the device is attached and functional and perform any
+ * needed initialization.
+ */
+static Bool
+QueryHardware (PenMountPrivatePtr priv)
+{
+ /* Maybe once we get the hardware to actually respond correctly to its
+ configuration 'packets' */
+
+ return (Success);
+}
+
+/*
+ * This function should be renamed for your device and tailored to handle
+ * your device's protocol.
+ */
+static Bool
+PenMountGetPacket (PenMountPrivatePtr priv)
+{
+ int count = 0;
+ int c;
+
+ while ((c = XisbRead (priv->buffer)) >= 0)
+ {
+ /*
+ * fail after 500 bytes so the server doesn't hang forever if a
+ * device sends bad data.
+ */
+ if (count++ > 500)
+ return (!Success);
+
+ switch (priv->lex_mode)
+ {
+ case PenMount_byte0:
+ if ( priv->chip != DMC8910 )
+ {
+ if (!(c & 0x08) )
+ return (!Success);
+ }
+ else
+ {
+ if ( c != 0xff )
+ return (!Success);
+ }
+ priv->packet[0] = (unsigned char) c;
+ priv->lex_mode = PenMount_byte1;
+ break;
+
+ case PenMount_byte1:
+ priv->packet[1] = (unsigned char) c;
+ priv->lex_mode = PenMount_byte2;
+ break;
+
+ case PenMount_byte2:
+ priv->packet[2] = (unsigned char) c;
+ priv->lex_mode = PenMount_byte0;
+ if ( priv->chip != DMC8910 )
+ return (Success);
+ if (( priv->packet[2] == 0xfe ) && ( priv->packet[1] == 0xfe ))
+ return (Success);
+ if (( priv->packet[2] == 0xfd ) && ( priv->packet[1] == 0xfd ))
+ return (Success);
+ priv->lex_mode = PenMount_byte3;
+ break;
+
+ case PenMount_byte3:
+ priv->packet[3] = (unsigned char) c;
+ priv->lex_mode = PenMount_byte4;
+ break;
+
+ case PenMount_byte4:
+ priv->packet[4] = (unsigned char) c;
+ priv->lex_mode = PenMount_byte0;
+ return (Success);
+ break;
+
+ case PenMount_Response0:
+ if ( c == 0xff )
+ priv->lex_mode = PenMount_Response1;
+ priv->packet[0] = (unsigned char) c;
+ break;
+
+ case PenMount_Response1:
+ priv->packet[1] = (unsigned char) c;
+ priv->lex_mode = PenMount_Response2;
+ break;
+ case PenMount_Response2:
+ priv->packet[2] = (unsigned char) c;
+ priv->lex_mode = PenMount_byte0;
+ return (Success);
+ break;
+ }
+ }
+ return (!Success);
+}
+
+static Bool
+PenMountSendPacket (PenMountPrivatePtr priv, unsigned char *buf, int len)
+{
+ int count = 0;
+
+ while ( len > 0 )
+ {
+ if ( XisbWrite(priv->buffer, buf, 1) == 1 )
+ {
+ buf++;
+ len--;
+ continue;
+ }
+ if ( count++ > 500 )
+ break;
+ }
+ return (len ? !Success : Success);
+}
+
+static void
+PenMountPtrCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
+{
+ /* I have no clue what this does, except that registering it stops the
+ X server segfaulting in ProcGetPointerMapping()
+ Ho Hum.
+ */
+}
diff --git a/src/xf86PM.h b/src/xf86PM.h
new file mode 100644
index 0000000..93757d9
--- /dev/null
+++ b/src/xf86PM.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1999 Machine Vision Holdings Incorporated
+ * Author: David Woodhouse <David.Woodhouse@mvhi.com>
+ *
+ * Template driver used: Copyright (c) 1998 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/input/penmount/xf86PM.h,v 1.1 2000/08/01 18:59:58 dawes Exp $ */
+
+#ifndef _PENMOUNT_H_
+#define _PENMOUNT_H_
+
+/******************************************************************************
+ * Definitions
+ * structs, typedefs, #defines, enums
+ *****************************************************************************/
+
+#define PENMOUNT_PACKET_SIZE 5
+
+typedef enum
+{
+ PenMount_byte0, PenMount_byte1, PenMount_byte2, PenMount_byte3, PenMount_byte4,
+ PenMount_Response0, PenMount_Response1, PenMount_Response2
+}
+PenMountState;
+
+
+typedef struct _PenMountPrivateRec
+{
+ int min_x; /* Minimum x reported by calibration */
+ int max_x; /* Maximum x */
+ int min_y; /* Minimum y reported by calibration */
+ int max_y; /* Maximum y */
+ Bool button_down; /* is the "button" currently down */
+ int button_number; /* which button to report */
+ int reporting_mode; /* TS_Raw or TS_Scaled */
+
+ int screen_num; /* Screen associated with the device */
+ int screen_width; /* Width of the associated X screen */
+ int screen_height; /* Height of the screen */
+ int proximity;
+ int swap_xy;
+ XISBuffer *buffer;
+ unsigned char packet[PENMOUNT_PACKET_SIZE]; /* packet being/just read */
+ PenMountState lex_mode;
+ char chip;
+ char pen_down;
+}
+PenMountPrivateRec, *PenMountPrivatePtr;
+
+#define CHIP_UNKNOWN 0
+#define DMC8910 1
+
+
+/******************************************************************************
+ * Declarations
+ *****************************************************************************/
+
+static Bool DeviceControl (DeviceIntPtr, int);
+static void ReadInput (InputInfoPtr);
+static int ControlProc (InputInfoPtr, xDeviceCtl *);
+static void CloseProc (InputInfoPtr);
+static int SwitchMode (ClientPtr, DeviceIntPtr, int);
+static Bool ConvertProc (InputInfoPtr, int, int, int, int, int, int, int, int, int *, int *);
+static Bool QueryHardware (PenMountPrivatePtr);
+static Bool PenMountGetPacket (PenMountPrivatePtr priv);
+static Bool PenMountSendPacket (PenMountPrivatePtr priv, unsigned char *buf, int len );
+
+static InputInfoPtr
+PenMountPreInit(InputDriverPtr drv, IDevPtr dev, int flags);
+
+static void
+PenMountPtrCtrl(DeviceIntPtr device, PtrCtrl *ctrl);
+
+
+#endif /* _PENMOUNT_H_ */