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
commitf680e23cbef4224c8c3c1b2f36719e7f54d60eee (patch)
tree2d26b1d7af150da69472f4f5ba1088846f6a2862
-rw-r--r--man/microtouch.man36
-rw-r--r--src/microtouch.c989
-rw-r--r--src/microtouch.h144
3 files changed, 1169 insertions, 0 deletions
diff --git a/man/microtouch.man b/man/microtouch.man
new file mode 100644
index 0000000..af1a467
--- /dev/null
+++ b/man/microtouch.man
@@ -0,0 +1,36 @@
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/microtouch/microtouch.man,v 1.2 2001/01/27 18:20:58 dawes Exp $
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH MICROTOUCH __drivermansuffix__ __vendorversion__
+.SH NAME
+microtouch \- MicroTouch input driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qInputDevice\*q"
+.BI " Identifier \*q" idevname \*q
+.B " Driver \*qmicrotouch\*q"
+.BI " Option \*qDevice\*q \*q" devpath \*q
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B microtouch
+is an XFree86 input driver for MicroTouch devices...
+.PP
+The
+.B microtouch
+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/microtouch.c b/src/microtouch.c
new file mode 100644
index 0000000..e17ca99
--- /dev/null
+++ b/src/microtouch.c
@@ -0,0 +1,989 @@
+/*
+ * 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.
+ *
+ */
+/*
+ * Based, in part, on code with the following copyright notice:
+ *
+ * Copyright 1996 by Patrick Lecoanet, France. <lecoanet@cenaath.cena.dgac.fr>
+ *
+ * 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 Patrick Lecoanet not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Patrick Lecoanet makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * PATRICK LECOANET DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL PATRICK LECOANET 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.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/input/microtouch/microtouch.c,v 1.12 2000/08/11 19:10:45 dawes Exp $ */
+
+#define _microtouch_C_
+/*****************************************************************************
+ * Standard Headers
+ ****************************************************************************/
+
+#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> /* Needed for InitValuator/Proximity stuff */
+
+/*****************************************************************************
+ * Local Headers
+ ****************************************************************************/
+#include "microtouch.h"
+
+/*****************************************************************************
+ * Variables without includable headers
+ ****************************************************************************/
+
+/*****************************************************************************
+ * Local Variables
+ ****************************************************************************/
+
+static InputInfoPtr
+MuTouchPreInit(InputDriverPtr drv, IDevPtr dev, int flags);
+
+
+InputDriverRec MICROTOUCH = {
+ 1,
+ "microtouch",
+ NULL,
+ MuTouchPreInit,
+ /*MuTouchUnInit*/ NULL,
+ NULL,
+ 0
+};
+
+#ifdef XFree86LOADER
+
+static XF86ModuleVersionInfo VersionRec =
+{
+ "microtouch",
+ 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",
+ "RemoveEnabledDevice",
+ "Xcalloc",
+ "Xfree",
+ "XisbBlockDuration",
+ "XisbFree",
+ "XisbNew",
+ "XisbRead",
+ "XisbTrace",
+ "XisbWrite",
+ "screenInfo",
+ "xf86AddInputDriver",
+ "xf86AllocateInput",
+ "xf86CloseSerial",
+ "xf86CollectInputOptions",
+ "xf86ErrorF",
+ "xf86ErrorFVerb",
+ "xf86FindOptionValue",
+ "xf86FlushInput",
+ "xf86GetMotionEvents",
+ "xf86GetVerbosity",
+ "xf86LoaderReqSymLists",
+ "xf86MotionHistoryAllocate",
+ "xf86Msg",
+ "xf86NameCmp",
+ "xf86OpenSerial",
+ "xf86OptionListCreate",
+ "xf86OptionListFree",
+ "xf86OptionListReport",
+ "xf86PostButtonEvent",
+ "xf86PostMotionEvent",
+ "xf86PostProximityEvent",
+ "xf86ProcessCommonOptions",
+ "xf86ScaleAxis",
+ "xf86SetIntOption",
+ "xf86SetSerial",
+ "xf86SetStrOption",
+ "xf86XInputSetScreen",
+ "xf86XInputSetSendCoreEvents",
+ "xf86memset",
+ "xf86sscanf",
+ "xf86strcmp",
+ "xf86strlen",
+ "xf86strncmp",
+ "xf86strncpy",
+ NULL
+};
+
+static pointer
+SetupProc( pointer module,
+ pointer options,
+ int *errmaj,
+ int *errmin )
+{
+ xf86LoaderReqSymLists(reqSymbols, NULL);
+ xf86AddInputDriver(&MICROTOUCH, module, 0);
+ return (pointer) 1;
+}
+
+XF86ModuleData microtouchModuleData = {&VersionRec, &SetupProc, NULL };
+
+#endif /* XFree86LOADER */
+
+
+static const char *default_options[] =
+{
+ "BaudRate", "9600",
+ "StopBits", "1",
+ "DataBits", "8",
+ "Parity", "None",
+ "Vmin", "5",
+ "Vtime", "1",
+ "FlowControl", "None"
+};
+static const char *fallback_options[] =
+{
+ "BaudRate", "9600",
+ "StopBits", "2",
+ "DataBits", "7",
+ "Parity", "None",
+ "Vmin", "1",
+ "Vtime", "1",
+ "FlowControl", "None"
+};
+
+
+/*****************************************************************************
+ * Function Definitions
+ ****************************************************************************/
+
+
+
+static InputInfoPtr
+MuTouchPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
+{
+ LocalDevicePtr local;
+ MuTPrivatePtr priv;
+
+ char *s;
+
+ priv = xcalloc (1, sizeof (MuTPrivateRec));
+ if (!priv)
+ return NULL;
+
+ local = xf86AllocateInput(drv, 0);
+ if (!local) {
+ xfree(priv);
+ return NULL;
+ }
+
+ local->type_name = XI_TOUCHSCREEN;
+ local->device_control = DeviceControl;
+ local->read_input = ReadInput;
+ local->control_proc = ControlProc;
+ local->close_proc = CloseProc;
+ local->switch_mode = SwitchMode;
+ local->conversion_proc = ConvertProc;
+ local->dev = NULL;
+ local->private = priv;
+ local->private_flags = 0;
+ local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
+ local->conf_idev = dev;
+
+ xf86CollectInputOptions(local, default_options, NULL);
+
+ xf86OptionListReport(local->options);
+
+ local->fd = xf86OpenSerial (local->options);
+ if (local->fd == -1)
+ {
+ ErrorF ("MicroTouch driver unable to open device\n");
+ goto SetupProc_fail;
+ }
+ xf86ErrorFVerb( 6, "tty port opened successfully\n" );
+
+ priv->min_x = xf86SetIntOption( local->options, "MinX", 0 );
+ priv->max_x = xf86SetIntOption( local->options, "MaxX", 1000 );
+ priv->min_y = xf86SetIntOption( local->options, "MinY", 0 );
+ priv->max_y = xf86SetIntOption( local->options, "MaxY", 1000 );
+ priv->screen_num = xf86SetIntOption( local->options, "ScreenNumber", 0 );
+ priv->button_number = xf86SetIntOption( local->options, "ButtonNumber", 1 );
+
+ s = xf86FindOptionValue (local->options, "ReportingMode");
+ if ((s) && (xf86NameCmp (s, "raw") == 0))
+ priv->reporting_mode = TS_Raw;
+ else
+ priv->reporting_mode = TS_Scaled;
+
+ priv->buffer = XisbNew (local->fd, 200);
+ priv->proximity = FALSE;
+ priv->button_down = FALSE;
+
+ DBG (9, XisbTrace (priv->buffer, 1));
+
+ MuTNewPacket (priv);
+ if (QueryHardware(local) != Success)
+ {
+ ErrorF ("Unable to query/initialize MicroTouch hardware.\n");
+ goto SetupProc_fail;
+ }
+
+ local->history_size = xf86SetIntOption( local->options, "HistorySize", 0 );
+
+
+ /* prepare to process touch packets */
+ MuTNewPacket (priv);
+
+ /* this results in an xstrdup that must be freed later */
+ local->name = xf86SetStrOption( local->options, "DeviceName", "MicroTouch TouchScreen" );
+ xf86ProcessCommonOptions(local, local->options);
+ local->flags |= XI86_CONFIGURED;
+
+ if (local->fd != -1)
+ {
+ RemoveEnabledDevice (local->fd);
+ if (priv->buffer)
+ {
+ XisbFree(priv->buffer);
+ priv->buffer = NULL;
+ }
+ xf86CloseSerial(local->fd);
+ }
+ RemoveEnabledDevice (local->fd);
+ local->fd = -1;
+ return (local);
+
+ SetupProc_fail:
+ if ((local) && (local->fd))
+ xf86CloseSerial (local->fd);
+ if ((local) && (local->name))
+ xfree (local->name);
+
+ if ((priv) && (priv->buffer))
+ XisbFree (priv->buffer);
+ if (priv)
+ xfree (priv);
+ return (local);
+}
+
+static Bool
+DeviceControl (DeviceIntPtr dev,
+ int mode)
+{
+ Bool RetValue;
+
+ switch (mode)
+ {
+ case DEVICE_INIT:
+ DeviceInit (dev);
+ RetValue = Success;
+ break;
+ case DEVICE_ON:
+ RetValue = DeviceOn( dev );
+ break;
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ RetValue = DeviceOff( dev );
+ break;
+ default:
+ RetValue = BadValue;
+ }
+
+ return( RetValue );
+}
+
+static Bool
+DeviceOn (DeviceIntPtr dev)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ MuTPrivatePtr priv = (MuTPrivatePtr) (local->private);
+
+ local->fd = xf86OpenSerial(local->options);
+ if (local->fd == -1)
+ {
+ xf86Msg(X_WARNING, "%s: cannot open input device\n", local->name);
+ return (!Success);
+ }
+
+ priv->buffer = XisbNew(local->fd, 64);
+ if (!priv->buffer)
+ {
+ xf86CloseSerial(local->fd);
+ local->fd = -1;
+ return (!Success);
+ }
+
+ xf86FlushInput(local->fd);
+ AddEnabledDevice (local->fd);
+ dev->public.on = TRUE;
+ return (Success);
+}
+
+static Bool
+DeviceOff (DeviceIntPtr dev)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ MuTPrivatePtr priv = (MuTPrivatePtr) (local->private);
+
+ if (local->fd != -1)
+ {
+ RemoveEnabledDevice (local->fd);
+ if (priv->buffer)
+ {
+ XisbFree(priv->buffer);
+ priv->buffer = NULL;
+}
+ xf86CloseSerial(local->fd);
+ }
+
+ RemoveEnabledDevice (local->fd);
+ dev->public.on = FALSE;
+ return (Success);
+}
+
+static Bool
+DeviceInit (DeviceIntPtr dev)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ MuTPrivatePtr priv = (MuTPrivatePtr) (local->private);
+ unsigned char map[] =
+ {0, 1};
+
+ /*
+ * 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 MicroTouch touchscreen 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,
+ local->history_size, Absolute) == FALSE)
+ {
+ ErrorF ("Unable to allocate MicroTouch touchscreen 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 MicroTouch touchscreen ProximityClassDeviceStruct\n");
+ return !Success;
+ }
+
+ /*
+ * Allocate the motion events buffer.
+ */
+ xf86MotionHistoryAllocate (local);
+ return (Success);
+}
+
+#define WORD_ASSEMBLY(byte1, byte2) (((byte2) << 7) | (byte1))
+
+static void
+ReadInput (LocalDevicePtr local)
+{
+ int x, y;
+ int type;
+ MuTPrivatePtr priv = (MuTPrivatePtr) (local->private);
+
+ /*
+ * 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 (MuTGetPacket (priv) == Success)
+ {
+ type = priv->packet[0];
+ x = WORD_ASSEMBLY (priv->packet[1], priv->packet[2]);
+ y = WORD_ASSEMBLY (priv->packet[3], priv->packet[4]);
+
+ 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 (local, priv->screen_num, x, y);
+
+ if ((priv->proximity == FALSE) && (type & MuT_CONTACT))
+ {
+ priv->proximity = TRUE;
+ xf86PostProximityEvent (local->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 (local->dev, TRUE, 0, 2, x, y);
+
+ /*
+ * Emit a button press or release.
+ */
+ if ((priv->button_down == FALSE) && (type & MuT_CONTACT))
+
+ {
+ xf86PostButtonEvent (local->dev, TRUE,
+ priv->button_number, 1, 0, 2, x, y);
+ priv->button_down = TRUE;
+ }
+ if ((priv->button_down == TRUE) && !(type & MuT_CONTACT))
+ {
+ xf86PostButtonEvent (local->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) && !(type & MuT_CONTACT))
+
+ {
+ priv->proximity = FALSE;
+ xf86PostProximityEvent (local->dev, 0, 0, 2, x, y);
+ }
+
+ xf86ErrorFVerb( 3, "TouchScreen: x(%d), y(%d), %d %d %s\n",
+ x, y, type, type & MuT_CONTACT,
+ (type & MuT_CONTACT) ? "Press" : "Release" );
+ }
+}
+
+static int
+ControlProc (LocalDevicePtr local, xDeviceCtl * control)
+{
+ xDeviceTSCalibrationCtl *c = (xDeviceTSCalibrationCtl *) control;
+ MuTPrivatePtr priv = (MuTPrivatePtr) (local->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);
+}
+
+static void
+CloseProc (LocalDevicePtr local)
+{
+}
+
+static int
+SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ MuTPrivatePtr priv = (MuTPrivatePtr) (local->private);
+ if ((mode == TS_Raw) || (mode == TS_Scaled))
+ {
+ priv->reporting_mode = mode;
+ return (Success);
+ }
+ else if ((mode == SendCoreEvents) || (mode == DontSendCoreEvents))
+ {
+ xf86XInputSetSendCoreEvents (local, (mode == SendCoreEvents));
+ return (Success);
+ }
+ else
+ return (!Success);
+}
+
+static Bool
+ConvertProc (LocalDevicePtr local,
+ int first,
+ int num,
+ int v0,
+ int v1,
+ int v2,
+ int v3,
+ int v4,
+ int v5,
+ int *x,
+ int *y)
+{
+ MuTPrivatePtr priv = (MuTPrivatePtr) (local->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);
+}
+
+static Bool
+xf86MuTSendCommand (unsigned char *type, MuTPrivatePtr priv)
+{
+ int r;
+ int retries = MuT_RETRIES;
+
+ while (retries--)
+ {
+ if (xf86MuTSendPacket (type, strlen ( (char *)type), priv) != Success)
+ continue;
+ r = xf86MuTWaitReply ( (unsigned char *)MuT_OK, priv);
+ if (r == ACK)
+ return (TRUE);
+ else if (r == NACK)
+ return (FALSE);
+ }
+ return (FALSE);
+}
+
+/*
+ * The microtouch SMT3 factory default is 72N, but the recommended operating
+ * mode is 81N. This code first tries 81N, but if that fails it switches to
+ * 72N and puts the controller in 81N before proceeding
+ */
+static Bool
+QueryHardware (LocalDevicePtr local)
+{
+ MuTPrivatePtr priv = (MuTPrivatePtr) local->private;
+ pointer fallback;
+ Bool ret = Success;
+ int cs7 = FALSE;
+
+ fallback = xf86OptionListCreate (fallback_options,
+ (sizeof (fallback_options) / sizeof (fallback_options[0])), 0);
+
+ priv->cs7flag = TRUE;
+ if (!xf86MuTSendCommand ( (unsigned char *)MuT_RESET, priv))
+ {
+ xf86ErrorFVerb( 5,
+ "Switching Com Parameters to CS7, 2 stop bits, no parity\n" );
+ xf86SetSerial (priv->buffer->fd, fallback);
+ cs7 = TRUE;
+ if (!xf86MuTSendCommand ( (unsigned char *)MuT_RESET, priv))
+ {
+ ret = !Success;
+ goto done;
+ }
+ }
+ if (!xf86MuTSendCommand ( (unsigned char *)MuT_ABDISABLE, priv))
+ {
+ ret = !Success;
+ goto done;
+ }
+ if (!xf86MuTSendCommand ( (unsigned char *)MuT_SETRATE, priv))
+ {
+ ret = !Success;
+ goto done;
+ }
+ if (cs7)
+ {
+ xf86ErrorFVerb( 5,
+ "Switching Com Parameters back to CS8, 1 stop bit, no parity\n" );
+ xf86SetSerial (priv->buffer->fd, local->options);
+ }
+ priv->cs7flag = FALSE;
+ if (!xf86MuTSendCommand ( (unsigned char *)MuT_FORMAT_TABLET, priv))
+ {
+ ret = !Success;
+ goto done;
+ }
+ if (!xf86MuTSendCommand ( (unsigned char *)MuT_MODE_STREAM, priv))
+ {
+ ret = !Success;
+ goto done;
+ }
+ if (!xf86MuTSendCommand ( (unsigned char *)MuT_PARAM_LOCK, priv))
+ {
+ ret = !Success;
+ goto done;
+ }
+ if( 1 ) /* Was: if (xf86Verbose), but can't do that in 3.9N... */
+ {
+ if (xf86MuTSendPacket ( (unsigned char *)MuT_OUTPUT_IDENT, strlen (MuT_OUTPUT_IDENT),
+ priv) == Success)
+ {
+ if (MuTGetPacket (priv) == Success)
+ xf86MuTPrintIdent (priv->packet);
+ }
+
+ /* some microtouch controllers support one command, some support the
+ * * other. If the first one get's a NACK, try the second. They both
+ * * return the same packet. */
+ if (xf86MuTSendPacket ( (unsigned char *)MuT_UNIT_VERIFY, strlen (MuT_UNIT_VERIFY),
+ priv) == Success)
+ {
+ if ((MuTGetPacket (priv) == Success) &&
+ (strcmp ( (char *)&(priv->packet[1]), MuT_ERROR) == 0))
+ {
+ if (xf86MuTSendPacket ( (unsigned char *)MuT_UNIT_TYPE,
+ strlen (MuT_UNIT_TYPE), priv) == Success)
+ {
+ if ((MuTGetPacket (priv) != Success))
+ {
+ ret = !Success;
+ goto done;
+ }
+ }
+ }
+ ret = xf86MuTPrintHwStatus (priv->packet);
+ }
+ }
+
+ done:
+ xf86OptionListFree (fallback);
+
+ return (ret);
+}
+
+static void
+MuTNewPacket (MuTPrivatePtr priv)
+{
+ priv->lex_mode = microtouch_normal;
+ priv->packeti = 0;
+ priv->binary_pkt = FALSE;
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86MuTSendPacket --
+ * Emit a variable length packet to the controller.
+ * The function expects a valid buffer containing the
+ * command to be sent to the controller. The command
+ * size is in len
+ * The buffer is filled with the leading and trailing
+ * character before sending.
+ *
+ ***************************************************************************
+ */
+static Bool
+xf86MuTSendPacket (unsigned char *type, int len, MuTPrivatePtr priv)
+{
+ int result;
+ unsigned char req[MuT_PACKET_SIZE];
+
+ memset (req, 0, MuT_PACKET_SIZE);
+ strncpy ((char *) &req[1], (char *)type, strlen ( (char *)type));
+ req[0] = MuT_LEAD_BYTE;
+ req[len + 1] = MuT_TRAIL_BYTE;
+
+ result = XisbWrite (priv->buffer, req, len + 2);
+ if (result != len + 2)
+ {
+ xf86ErrorFVerb( 5, "System error while sending to MicroTouch touchscreen.\n" );
+ return !Success;
+ }
+ else
+ return Success;
+}
+
+/*
+ ***************************************************************************
+ * 0 ACK
+ * -1 NACK
+ * -2 timeout
+ * -3 wrong packet type
+ ***************************************************************************
+ */
+static int
+xf86MuTWaitReply (unsigned char *type, MuTPrivatePtr priv)
+{
+ Bool ok;
+ int wrong, empty;
+
+ wrong = MuT_MAX_WRONG_PACKETS;
+ empty = MuT_MAX_EMPTY_PACKETS;
+ do
+ {
+ ok = !Success;
+
+ /*
+ * Wait half a second for the reply. The fuse counts down each
+ * timeout and each wrong packet.
+ */
+ xf86ErrorFVerb( 4, "Waiting %d ms for data from port\n", MuT_MAX_WAIT / 1000 );
+ MuTNewPacket (priv);
+ XisbBlockDuration (priv->buffer, MuT_MAX_WAIT);
+ ok = MuTGetPacket (priv);
+ /*
+ * type is a NULL terminated string of 0 - 2 characters. An empty
+ * string for type indicates that any reply type is acceptable.
+ */
+ if (ok != Success)
+ {
+ xf86ErrorFVerb( 4, "Recieved empty packet.\n" );
+ empty--;
+ continue;
+ }
+ if (ok == Success)
+ {
+ /*
+ * this bit of weirdness attempts to detect an ACK from the
+ * controller when it is in 7bit mode and the computer is in 8bit
+ * mode. If we see this pattern and send a NACK here the next
+ * level up will switch to 7 bit mode and try again
+ */
+ if (priv->cs7flag && (priv->packet[1] == MuT_OK7) &&
+ (priv->packet[2] == '\0'))
+ {
+ xf86ErrorFVerb( 4, "Detected the 7 bit ACK in 8bit mode.\n" );
+ return (NACK);
+ }
+ if (strcmp ( (char *)&(priv->packet[1]), (char *)type) == 0)
+ {
+ xf86ErrorFVerb( 5, "\t\tgot an ACK\n" );
+ return (ACK);
+ }
+ else if (strcmp ( (char *)&(priv->packet[1]), MuT_ERROR) == 0)
+ {
+ xf86ErrorFVerb( 5, "\t\tgot a NACK\n" );
+ return (NACK);
+ }
+ else
+ {
+ xf86ErrorFVerb( 2, "Wrong reply received\n" );
+ ok = !Success;
+ wrong--;
+ }
+ }
+ }
+ while (ok != Success && wrong && empty);
+
+ if (wrong)
+ return (TIMEOUT);
+ else
+ return (WRONG_PACKET);
+}
+
+static Bool
+MuTGetPacket (MuTPrivatePtr priv)
+{
+ int count = 0;
+ int c;
+
+ while ((c = XisbRead (priv->buffer)) >= 0)
+ {
+ if (count++ > 100)
+ {
+ MuTNewPacket (priv);
+ return (!Success);
+ }
+
+ switch (priv->lex_mode)
+ {
+ case microtouch_normal:
+ if ((c == MuT_LEAD_BYTE) ||
+ (priv->cs7flag && ((c & 0x7f) == MuT_LEAD_BYTE)))
+ {
+ xf86ErrorFVerb( 8, "Saw MuT_LEAD_BYTE\n" );
+ priv->packet[priv->packeti++] = (unsigned char) c;
+ priv->lex_mode = microtouch_body;
+ }
+ /*
+ * binary touch packets do not have LEAD_BYTE or TRAIL_BYTE
+ * Instead, only the first byte has the 8th bit set.
+ */
+ if (c & 0x80)
+ {
+ xf86ErrorFVerb( 8, "Saw BINARY start\n" );
+ priv->packet[priv->packeti++] = (unsigned char) c;
+ priv->lex_mode = mtouch_binary;
+ priv->bin_byte = 0;
+ }
+ break;
+
+ case mtouch_binary:
+ priv->packet[priv->packeti++] = (unsigned char) c;
+ priv->bin_byte++;
+ if (priv->bin_byte == 4)
+ {
+ xf86ErrorFVerb( 8, "got a good BINARY packet\n" );
+ MuTNewPacket (priv);
+ priv->binary_pkt = TRUE;
+ return (Success);
+ }
+ break;
+
+ case microtouch_body:
+ /*
+ * apparently a new packet can start in the middle of another
+ * packet if they host sends something at the right time to
+ * trigger it.
+ */
+ if ((c == MuT_LEAD_BYTE) ||
+ (priv->cs7flag && ((c & 0x7f) == MuT_LEAD_BYTE)))
+ {
+ priv->packeti = 0;
+ }
+ if ((c == MuT_TRAIL_BYTE) ||
+ (priv->cs7flag && ((c & 0x7f) == MuT_TRAIL_BYTE)))
+ {
+ /* null terminate the packet */
+ priv->packet[priv->packeti++] = '\0';
+ xf86ErrorFVerb( 8, "got a good packet\n" );
+ MuTNewPacket (priv);
+ return (Success);
+ }
+ else
+ priv->packet[priv->packeti++] = (unsigned char) c;
+ break;
+
+ }
+ }
+ return (!Success);
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86MuTPrintIdent --
+ * Print type of touchscreen and features on controller board.
+ *
+ ***************************************************************************
+ */
+static void
+xf86MuTPrintIdent (unsigned char *packet)
+{
+ int vers, rev;
+
+ if (strlen ( (char *)packet) < 6)
+ return;
+ xf86Msg( X_PROBED, " MicroTouch touchscreen is " );
+ if (strncmp ((char *) &packet[1], MuT_TOUCH_PEN_IDENT, 2) == 0)
+ xf86ErrorF( "a TouchPen.\n" );
+ else if (strncmp ((char *) &packet[1], MuT_SMT3_IDENT, 2) == 0)
+ xf86ErrorF( "a Serial/SMT3.\n" );
+ else if (strncmp ((char *) &packet[1], MuT_GENERAL_IDENT, 2) == 0)
+ xf86ErrorF( "an SMT2, SMT3V or SMT3RV.\n" );
+ else
+ xf86ErrorF( "Unknown Type %c%c.\n", packet[1], packet[2] );
+ sscanf ((char *) &packet[3], "%2d%2d", &vers, &rev);
+ xf86Msg( X_PROBED, " MicroTouch controller firmware revision is %d.%d.\n", vers, rev);
+}
+
+/*
+ ***************************************************************************
+ *
+ * xf86MuTPrintHwStatus --
+ * Print status of hardware. That is if the controller report errors,
+ * decode and display them.
+ *
+ ***************************************************************************
+ */
+static Bool
+xf86MuTPrintHwStatus (unsigned char *packet)
+{
+ int i;
+ int err;
+
+ for (i = 3; i < 7; i++)
+ {
+ if (packet[i] == 'R')
+ {
+ xf86Msg( X_PROBED,
+ " MicroTouch controller is a resistive type.\n" );
+ }
+
+ }
+ if (packet[7] == '1')
+ {
+ xf86Msg( X_PROBED,
+ " MicroTouch controller reports the following errors:\n" );
+ err = packet[8];
+ if (err & 0x01)
+ xf86ErrorF( "\tReserved\n" );
+ if (err & 0x02)
+ xf86ErrorF( "\tROM error. Firmware checksum verification error.\n" );
+ if (err & 0x04)
+ xf86ErrorF( "\tPWM error. Unable to establish PWM operating range at power-up.\n" );
+ if (err & 0x08)
+ xf86ErrorF( "\tNOVRAM error. The operating parameters in the controller NOVRAM are invalid.\n" );
+ if (err & 0x10)
+ xf86ErrorF( "\tHWD error. The controller hardware failed.\n" );
+ if (err & 0x20)
+ xf86ErrorF( "\tReserved\n" );
+ if (err & 0x40)
+ xf86ErrorF( "\tCable NOVRAM error. The linearization data in the cable NOVRAM is invalid.\n" );
+ if (err & 0x80)
+ xf86ErrorF( "\tNOVRAM2 error. The linearization data in the controller NOVRAM is invalid.\n" );
+ return (!Success);
+ }
+
+ return (Success);
+}
diff --git a/src/microtouch.h b/src/microtouch.h
new file mode 100644
index 0000000..696b12e
--- /dev/null
+++ b/src/microtouch.h
@@ -0,0 +1,144 @@
+/*
+ * 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/microtouch/microtouch.h,v 1.4 2000/03/03 20:36:41 dawes Exp $ */
+
+#ifndef _microtouch_H_
+#define _microtouch_H_
+
+/******************************************************************************
+ * Definitions
+ * structs, typedefs, #defines, enums
+ *****************************************************************************/
+#define MuT_REPORT_SIZE 5 /* Size of a report packet. */
+#define MuT_BUFFER_SIZE 256 /* Size of input buffer. */
+#define MuT_PACKET_SIZE 10 /* Maximum size of a command/reply
+ * *including* */
+#define MuT_MAX_WRONG_PACKETS 20 /* Number of wrong packets to accept
+ * before giving up when looking for a
+ * specific packet type */
+#define MuT_MAX_EMPTY_PACKETS 5 /* Number of empty reads to accept before
+ * giving up when looking for a reply */
+#define MuT_RETRIES 3
+#define MuT_MAX_WAIT 100000 /* Max wait time for a reply
+ * (microsec) */
+
+ /* the leading and trailing bytes. */
+#define MuT_LEAD_BYTE 0x01 /* First byte of a command/reply packet.
+ * */
+#define MuT_TRAIL_BYTE 0x0D /* Last byte of a command/reply packet.
+ * */
+
+/*
+ * Commands.
+ */
+#define MuT_RESET "R" /* Reset the controller. */
+#define MuT_OUTPUT_IDENT "OI" /* Ask some infos about the firmware. */
+#define MuT_UNIT_TYPE "UT" /* Ask some more infos about the *
+ * firmware. */
+#define MuT_UNIT_VERIFY "UV" /* Ask some more infos about the *
+ * firmware. some hardware only supports
+ * * this version */
+#define MuT_ABDISABLE "AD" /* disable auto baud detection */
+#define MuT_SETRATE "PN812" /* set com parameters to
+ * 8,1,none,9600 */
+#define MuT_FORMAT_TABLET "FT" /* Report events using tablet format. */
+#define MuT_FINGER_ONLY "FO" /* Always send reports. */
+#define MuT_MODE_STREAM "MS" /* Receive reports in stream mode */
+#define MuT_PARAM_LOCK "PL" /* write settings to nvram */
+
+#define MuT_OK "0" /* Report success. */
+#define MuT_OK7 0xb0 /* 7bit Report success as seen in 8bit mode */
+#define MuT_ERROR "1" /* Report error. */
+#define MuT_ANY "" /* Accept any reply */
+
+#define MuT_TOUCH_PEN_IDENT "P5"
+#define MuT_SMT3_IDENT "Q1"
+#define MuT_GENERAL_IDENT "A3"
+
+#define MuT_CONTACT 0x40 /* Report touch/untouch with touchscreen. */
+
+#define ACK 0
+#define NACK -1
+#define TIMEOUT -2
+#define WRONG_PACKET -3
+
+typedef enum
+{
+ microtouch_normal, microtouch_body, mtouch_binary
+}
+MuTState;
+
+typedef struct _MuTPrivateRec
+{
+ 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 proximity; /* is the stylus in proximity */
+ 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 */
+ XISBuffer *buffer;
+ unsigned char packet[MuT_BUFFER_SIZE]; /* packet being/just read */
+ int packeti; /* index into packet */
+ Bool cs7flag;
+ Bool binary_pkt; /* indicates packet was a binary touch */
+
+ MuTState lex_mode;
+ int bin_byte; /* bytes recieved in binary packet */
+}
+MuTPrivateRec, *MuTPrivatePtr;
+
+/******************************************************************************
+ * Declarations
+ *****************************************************************************/
+/*int DumpOpts (XF86OptionPtr opts); */
+static Bool DeviceControl (DeviceIntPtr dev, int mode);
+static Bool DeviceOn (DeviceIntPtr dev);
+static Bool DeviceOff (DeviceIntPtr dev);
+static Bool DeviceInit (DeviceIntPtr dev);
+static void ReadInput (LocalDevicePtr local);
+static int ControlProc (LocalDevicePtr local, xDeviceCtl * control);
+static void CloseProc (LocalDevicePtr local);
+static int SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode);
+static Bool ConvertProc (LocalDevicePtr local, int first, int num, int v0, int v1, int v2, int v3, int v4, int v5, int *x, int *y);
+static Bool xf86MuTSendCommand (unsigned char *type, MuTPrivatePtr priv);
+static Bool QueryHardware (LocalDevicePtr local);
+static void MuTNewPacket (MuTPrivatePtr priv);
+static Bool xf86MuTSendPacket (unsigned char *type, int len, MuTPrivatePtr priv);
+static int xf86MuTWaitReply (unsigned char *type, MuTPrivatePtr priv);
+static Bool MuTGetPacket (MuTPrivatePtr priv);
+static void xf86MuTPrintIdent (unsigned char *packet);
+static Bool xf86MuTPrintHwStatus (unsigned char *packet);
+/*
+ * DO NOT PUT ANYTHING AFTER THIS ENDIF
+ */
+#endif