summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/xfree86/input/citron
diff options
context:
space:
mode:
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/input/citron')
-rw-r--r--xc/programs/Xserver/hw/xfree86/input/citron/Imakefile31
-rw-r--r--xc/programs/Xserver/hw/xfree86/input/citron/citron.c2421
-rw-r--r--xc/programs/Xserver/hw/xfree86/input/citron/citron.cpp631
-rw-r--r--xc/programs/Xserver/hw/xfree86/input/citron/citron.h522
4 files changed, 3605 insertions, 0 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/input/citron/Imakefile b/xc/programs/Xserver/hw/xfree86/input/citron/Imakefile
new file mode 100644
index 000000000..6e0fcc6e9
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/input/citron/Imakefile
@@ -0,0 +1,31 @@
+XCOMM $XFree86: xc/programs/Xserver/hw/xfree86/input/citron/Imakefile,v 1.1 2000/11/02 02:51:20 dawes Exp $
+
+#define IHaveModules
+#include <Server.tmpl>
+
+SRCS = citron.c
+OBJS = citron.o
+
+DRIVER = citron
+
+INCLUDES = -I. -I$(XF86COMSRC) -I$(XF86SRC)/loader -I$(XF86OSSRC) \
+ -I$(SERVERSRC)/include -I$(SERVERSRC)/mi -I$(XINCLUDESRC) -I$(EXTINCSRC)
+
+#if MakeHasPosixVariableSubstitutions
+SubdirLibraryRule($(OBJS))
+#endif
+
+ModuleObjectRule()
+
+ObjectModuleTarget($(DRIVER),$(OBJS))
+
+InstallObjectModule($(DRIVER),$(MODULEDIR),input)
+
+#if !defined(XF86DriverSDK)
+CppManTarget($(DRIVER),)
+InstallModuleManPage($(DRIVER))
+#endif
+
+DependTarget()
+
+InstallDriverSDKObjectModule($(DRIVER),$(DRIVERSDKMODULEDIR),input)
diff --git a/xc/programs/Xserver/hw/xfree86/input/citron/citron.c b/xc/programs/Xserver/hw/xfree86/input/citron/citron.c
new file mode 100644
index 000000000..517c87500
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/input/citron/citron.c
@@ -0,0 +1,2421 @@
+/*
+ * 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/citron/citron.c,v 1.4 2000/11/03 13:13:31 tsi Exp $ */
+
+/*
+ * Based, in part, on code with the following copyright notice:
+ *
+ * Copyright 1999-2000 by Thomas Thanner, Citron GmbH, Germany. <support@citron.de>
+ * Copyright 1999-2000 by Peter Kunzmann, Citron GmbH, Germany. <support@citron.de>
+ *
+ * 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 Thomas Thanner and Citron GmbH not be used in advertising or
+ * publicity pertaining to distribution of the software without specific, written
+ * prior permission. Thomas Thanner and Citron GmbH makes no representations about
+ * the suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * THOMAS THANNER AND CITRON GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL THOMAS THANNER OR CITRON GMBH BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RSULTING 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.
+ *
+ */
+
+/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ * Citron specific extensions:
+ *
+ * 1) Configuration file entries:
+ * a) "SleepTime" Touch idle time in seconds before sleep mode
+ * (reduced scanning) is entered.
+ * 0 = immediately; 65535=never;
+ * default=65535
+ * b) "ActivePWM" PWM duty cycle during regular operation.
+ * default=255
+ * c) "SleepPWM" PWM duty cycle during sleep mode.
+ * default=255
+ * d) "ClickMode" Button click emulation mode;
+ * 1 = Enter Mode
+ * 2 = Dual Touch Mode
+ * 3 = Dual Exit Mode
+ * 4 = Z-Press Mode
+ * 5 = Z-Press Exit Mode
+ * default = 1
+ *
+ * 2) Additional modes in SetMode() function:
+ * (These modes are only activated if the CIT_MODE_EXT macro is defined
+ * at compile time. Until now the mode values are not defined, yet)
+ * a) ClickMode_Enter set the button click emulation mode to 1
+ * b) ClickMode_Dual set the button click emulation mode to 2
+ * c) ClickMode_DualExit set the button click emulation mode to 3
+ * d) ClickMode_ZPress set the button click emulation mode to 4
+ * e) ClickMode_ZPressExit set the button click emulation mode to 5
+ *
+ *!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
+/*
+ ---------------------------------------------------------------------------
+ Revision history:
+
+ Ver Date Description of changes Name
+ ---------------------------------------------------------------------------
+ 2.03 17.09.00 Reconnect when getting breaks changed, changes
+ when powering off the system and reconnecting
+ parser for commands from "xcit" added
+ "cit_ParseCommand" to set the variables not
+ only on the touch side but also in the priv rec pk
+ 2.04 19.10.00 reconnect enhanced pk
+ ============================================================================
+
+*/
+
+
+#define _citron_C_
+#define PK 0
+#define INITT 0 /* Initialisation of touch in first loop */
+
+/* ODD version number enables the debug macros */
+/* EVEN version number is for release */
+#define CITOUCH_VERSION 0x204
+char version[]="Touch Driver V2.04 (c) 1999-2000 Citron GmbH";
+
+
+
+/*****************************************************************************
+ * Standard Headers
+ ****************************************************************************/
+
+#include <misc.h>
+#include <xf86.h>
+#define NEED_XF86_TYPES
+/*#include <xf86Version.h>*/
+#include <xf86_ansic.h>
+/* #define XF86_OS_PRIVS for xf86SoundKbdBell */
+#include <xf86_OSproc.h>
+#include <xf86Optrec.h>
+#include <xf86Xinput.h>
+#include <xisb.h>
+#include <exevents.h> /* Needed for InitValuator/Proximity stuff*/
+
+
+/* I have to explicit declare this function, because I get an error if I compile */
+/* with "#define XF86_OS_PRIVS". I also have to put a "SYMVAR(xf86SoundKbdBell)" */
+/* statement into the "/loader/xf86sym.c file" to be able to access this function (PK) */
+extern void xf86SoundKbdBell(int loudness, int pitch, int duration);
+
+/* #define CI_TIM */ /* Enable timer */
+#define CIT_BEEP /* enable beep feature */
+
+/*****************************************************************************
+ * Local Headers
+ ****************************************************************************/
+#include "citron.h"
+
+/*****************************************************************************
+ * Variables without includable headers
+ ****************************************************************************/
+
+/*****************************************************************************
+ * defines
+ ****************************************************************************/
+#define CIT_DEF_MIN_X 0
+#define CIT_DEF_MAX_X 0xFFFF
+#define CIT_DEF_MIN_Y 0
+#define CIT_DEF_MAX_Y 0xFFFF
+
+#define CIT_BUFFER_SIZE 1024
+
+
+
+/******************************************************************************
+ * debugging macro
+ *****************************************************************************/
+#ifdef DBG
+#undef DBG
+#endif
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+static int debug_level = 0;
+#if CITOUCH_VERSION & 0x0001
+#define DEBUG
+#endif
+#ifdef DEBUG
+#define DBG(lvl, f) {if ((lvl) <= debug_level) f;}
+#else
+#define DBG(lvl, f)
+#endif
+
+/* Debugging levels for various routines */
+#define PP 5 /* cit_ProcessPacket */
+#define RI 6 /* cit_ReadInput */
+#define GP 6 /* cit_GetPacket */
+#define DDS 5 /* DDS package */
+#define DC 5 /* cit_DriverComm */
+
+#define XFREE86_V4
+
+#ifdef XFREE86_V4
+#define WAIT(t) \
+ err = xf86WaitForInput(-1, ((t) * 1000)); \
+ if (err == -1) { \
+ ErrorF("Citron select error\n"); \
+ return !Success; \
+ }
+#else
+#define WAIT(t) \
+ timeout.tv_sec = 0; \
+ timeout.tv_usec = (t) * 1000; \
+ SYSCALL(err = select(0, NULL, NULL, NULL, &timeout)); \
+ if (err == -1) { \
+ ErrorF("Citron select error : %s\n", strerror(errno)); \
+ return !Success; \
+ }
+#endif
+
+
+
+
+/*****************************************************************************
+ * Local Variables
+ ****************************************************************************/
+
+
+static InputInfoPtr CitronPreInit(InputDriverPtr drv, IDevPtr dev, int flags);
+
+
+InputDriverRec CITRON = {
+ 1,
+ "citron",
+ NULL,
+ CitronPreInit,
+ /*CitronUnInit*/ NULL,
+ NULL,
+ 0
+};
+
+#ifdef XFree86LOADER
+
+
+/*
+ ***************************************************************************
+ *
+ * Dynamic loading functions
+ *
+ ***************************************************************************
+ */
+
+
+static XF86ModuleVersionInfo VersionRec =
+{
+ "citron", /* name of module */
+ MODULEVENDORSTRING, /* vendor specific string */
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT, /* Module-specific current version */
+ 0, /* Module-specific major version */
+ 1, /* Module-specific minor version */
+ 1, /* Module-specific patch level */
+ ABI_CLASS_XINPUT,
+ ABI_XINPUT_VERSION,
+ MOD_CLASS_XINPUT,
+ {0, 0, 0, 0} /* signature of the version info structure */
+};
+
+
+/* ************************************************************************
+ * [SetupProc] --
+ *
+ * called when the module subsection is found in XF86Config
+ *
+ * ************************************************************************/
+
+static pointer
+SetupProc( pointer module,
+ pointer options,
+ int *errmaj,
+ int *errmin )
+{
+/* xf86LoaderReqSymLists(reqSymbols, NULL); */
+ xf86AddInputDriver(&CITRON, module, 0);
+ DBG(5, ErrorF ("%sSetupProc called\n", CI_INFO));
+
+ return (pointer) 1;
+}
+
+/*****************************************************************************
+ * [TearDownProc]
+ ****************************************************************************/
+static void
+TearDownProc (pointer p)
+{
+ DBG(5, ErrorF ("%sTearDownProc Called\n", CI_INFO));
+}
+
+
+XF86ModuleData citronModuleData = { &VersionRec, SetupProc, TearDownProc};
+
+#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[] =
+{
+
+ "BaudRate", "19200",
+ "StopBits", "1",
+ "DataBits", "8",
+ "Parity", "None",
+ "Vmin", "3",
+ "Vtime", "1",
+ "FlowControl", "None",
+ "ClearDTR", ""
+};
+
+
+/*****************************************************************************
+ * Function Definitions
+ ****************************************************************************/
+
+
+
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* [xf86CitronFeedback] */
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+/* Online driver parameter change */
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+static void
+cit_SendtoTouch(DeviceIntPtr dev)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ cit_PrivatePtr priv = (cit_PrivatePtr)(local->private);
+ int i,j;
+ unsigned char buf[MAX_BYTES_TO_TRANSFER*2+2];
+
+ DBG(DDS, ErrorF("%scit_SendtoTouch(numbytes=0x%02X, data[0]=%02x, data[1]=%02x, data[2]=%02x, data[3]=%02x, ...)\n", CI_INFO, priv->dds.numbytes,
+ priv->dds.data[0], priv->dds.data[1], priv->dds.data[2], priv->dds.data[3],));
+
+ j=0;
+ buf[j++] = CTS_STX; /* transmit start of packet */
+
+ for(i=0; i<priv->dds.numbytes; i++)
+ {
+ if (priv->dds.data[i] >= CTS_CTRLMIN && priv->dds.data[i] <= CTS_CTRLMAX)
+ { /* data has to be encoded */
+ buf[j++] = CTS_ESC;
+ buf[j++] = priv->dds.data[i] | CTS_ENCODE;
+ }
+ else buf[j++] = priv->dds.data[i];
+ }
+ buf[j++] = CTS_ETX; /* end of packet */
+
+ XisbWrite(priv->buffer, buf, j);
+
+
+ for(i=0; i<j; i++)
+ {
+ if(i%16 == 0) DBG(DDS, ErrorF("\n"));
+ DBG(DDS, ErrorF("%02x ",buf[i]));
+ }
+
+
+ DBG(DDS, ErrorF("\n"));
+}
+
+
+static void
+cit_ParseCommand(DeviceIntPtr dev)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ cit_PrivatePtr priv = (cit_PrivatePtr)(local->private);
+ int i;
+
+ DBG(DDS, ErrorF("%scit_ParseCommand(numbytes=0x%02X, data= ", CI_INFO, priv->dds.numbytes));
+
+ for(i=0; i<priv->dds.numbytes; i++)
+ DBG(DDS, ErrorF("%02x ", priv->dds.data[i]));
+
+ DBG(DDS,ErrorF("\n"));
+
+ switch(priv->dds.data[0]&0xff)
+ {
+ case C_SETPWM:
+ priv->pwm_active = priv->dds.data[1];
+ priv->pwm_sleep = priv->dds.data[2];
+ DBG(DDS, ErrorF("%scit_ParseCommand(PWM Active:%d PWM Sleep:%d \n", CI_INFO, priv->pwm_active, priv->pwm_sleep));
+ break;
+
+ case C_SETSLEEPMODE:
+ if(priv->dds.data[1] == 0)
+ {
+ priv->sleep_time_act = priv->dds.data[2] | (priv->dds.data[3] << 8);
+ }
+ DBG(DDS, ErrorF("%scit_ParseCommand(Sleep Time act:%d \n", CI_INFO, priv->sleep_time_act));
+ break;
+
+ case C_SETDOZEMODE:
+ if(priv->dds.data[1] == 0)
+ {
+ priv->doze_time_act = priv->dds.data[2] | (priv->dds.data[3] << 8);
+ }
+ DBG(DDS, ErrorF("%scit_ParseCommand(Doze Time act:%d \n", CI_INFO, priv->doze_time_act));
+ break;
+
+ case C_SETAREAPRESSURE:
+ priv->button_threshold = priv->dds.data[1];
+ DBG(DDS, ErrorF("%scit_ParseCommand(Button Threshold:%d \n", CI_INFO, priv->button_threshold));
+ break;
+ }
+}
+
+
+
+static void
+cit_DriverComm(DeviceIntPtr dev)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ cit_PrivatePtr priv = (cit_PrivatePtr)(local->private);
+ int i;
+ unsigned short tmp;
+
+ DBG(DC, ErrorF("%scit_DriverComm(numbytes=0x%02X, data[1]=%02x, ...)\n", CI_INFO, priv->dds.numbytes, priv->dds.data[1]));
+
+ i=1;
+ switch(priv->dds.data[i++]) /* command word */
+ {
+ case D_SETCLICKMODE:
+ priv->click_mode = priv->dds.data[i++];
+ ErrorF("%sClick Mode: %d\n", CI_INFO, priv->click_mode);
+ break;
+
+ case D_BEEP:
+ priv->beep = priv->dds.data[i++];
+ ErrorF("%sBeep: %s\n", CI_INFO, (priv->beep > 0) ? "activated":"not activated");
+ break;
+
+ case D_SETBEEP:
+ priv->press_vol = priv->dds.data[i++];
+ ErrorF("%sBeep Pressure Volume: %d\n", CI_INFO, priv->press_vol);
+ tmp = priv->dds.data[i++];
+ tmp += priv->dds.data[i++] << 8;
+ priv->press_pitch = tmp;
+ ErrorF("%sBeep Pressure Pitch: %d\n", CI_INFO, priv->press_pitch);
+ priv->press_dur = priv->dds.data[i++];
+ ErrorF("%sBeep Pressure Duration: %d\n", CI_INFO, priv->press_dur);
+ priv->rel_vol = priv->dds.data[i++];
+ ErrorF("%sBeep Release Volume: %d\n", CI_INFO, priv->rel_vol);
+ tmp = priv->dds.data[i++];
+ tmp += priv->dds.data[i++] << 8;
+ priv->rel_pitch = tmp;
+ ErrorF("%sBeep Release Pitch: %d\n", CI_INFO, priv->rel_pitch);
+ priv->rel_dur = priv->dds.data[i++];
+ ErrorF("%sBeep Release Duration: %d\n", CI_INFO, priv->rel_dur);
+ break;
+
+ default:
+ ErrorF("%sNot known command: %d\n", CI_WARNING, priv->dds.data[1]);
+
+ }
+}
+
+
+static void
+xf86CitronPrint (int nr, LedCtrl *ctrl)
+{
+ DBG(8, ErrorF("%s------------------------------------------\n", CI_INFO));
+ DBG(8, ErrorF("%sxf86CitronFeedback%d(dev, ctrl)\n", CI_INFO, nr));
+ DBG(8, ErrorF("%s ctrl->led_values.......:%d [0x%08lX]\n", CI_INFO, ctrl->led_values, ctrl->led_values));
+ DBG(8, ErrorF("%s ctrl->led_mask.........:%d [0x%08lX]\n", CI_INFO, ctrl->led_mask, ctrl->led_mask));
+ DBG(8, ErrorF("%s ctrl->id...............:%d\n", CI_INFO, ctrl->id));
+}
+
+
+static void
+xf86CitronFeedback0 (DeviceIntPtr dev, LedCtrl *ctrl)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ cit_PrivatePtr priv = (cit_PrivatePtr)(local->private);
+ COMMAND *cmd;
+
+ DBG(DDS, ErrorF("%sEntering xf86CitronFeedback0()...\n",CI_INFO));
+
+ cmd = (COMMAND *)&ctrl->led_values;
+
+ DBG(DDS, ErrorF("%scmd->packet = %d\n", CI_INFO, cmd->packet));
+
+
+ if(cmd->packet == 0) /* test if first packet has come (with number of bytes in first byte) */
+ {
+ if(cmd->par[0] == 0) /* test if something is to do at all */
+ return;
+ priv->dds.curbyte = 2;
+ priv->dds.numbytes = cmd->par[0];
+ priv->dds.data[0] = cmd->par[1];
+ priv->dds.data[1] = cmd->par[2];
+ priv->dds.packet = 1;
+ }
+ else
+ {
+ if(priv->dds.packet == cmd->packet)
+ {
+ priv->dds.data[priv->dds.packet*3-1] = cmd->par[0];
+ priv->dds.data[priv->dds.packet*3] = cmd->par[1];
+ priv->dds.data[priv->dds.packet*3+1] = cmd->par[2];
+ priv->dds.packet++;
+ priv->dds.curbyte += 3;
+ }
+ else
+ DBG(DDS, ErrorF("%sPacket error: should be %d is %d\n", CI_WARNING, priv->dds.packet, cmd->packet));
+
+ }
+ DBG(DDS, ErrorF("%snumbytes = %d curbyte=%d\n", CI_INFO, priv->dds.numbytes, priv->dds.curbyte));
+ if(priv->dds.curbyte >= priv->dds.numbytes)
+ {
+ if(priv->dds.data[0] == DRIVCOMM)
+ cit_DriverComm(dev); /* process command in the driver */
+ else
+ {
+ cit_ParseCommand(dev); /* First parse command and set parameters in priv rec */
+ cit_SendtoTouch(dev); /* send message to the touch and execute command there */
+ }
+ }
+
+ DBG(DDS, ErrorF("%s 1 led_values = %08x\n", CI_INFO, ctrl->led_values));
+ ctrl->led_values = 0x12345678;
+ DBG(DDS, ErrorF("%s 2 led_values = %08x\n", CI_INFO, ctrl->led_values));
+
+}
+
+
+static void
+xf86CitronFeedback1 (DeviceIntPtr dev, LedCtrl *ctrl)
+{
+ static int test = 0;
+ xf86CitronPrint (1, ctrl);
+ ctrl->led_values = 0x8765432;
+ ctrl->led_mask = test++;
+}
+
+static void
+xf86CitronFeedback2 (DeviceIntPtr dev, LedCtrl *ctrl)
+{
+ xf86CitronPrint (2, ctrl);
+ ctrl->led_values = (unsigned long)GetTimeInMillis();
+ ctrl->led_mask = (unsigned long)GetTimeInMillis()&0xff;
+}
+
+
+
+#if(PK)
+/* Hexdump a number of Words */
+/* len is number of words to dump */
+static void hexdump (void *ioaddr, int len)
+{
+ int i;
+ unsigned long *ptr = (unsigned long *)ioaddr;
+
+ ErrorF(" ADDR 0-3 4-7 8-B C-F\n");
+ ErrorF("---------+-----+----+----+----+----+----+----+----\n");
+
+ while (len > 0)
+ {
+ ErrorF ("%08X: ", (unsigned long)ptr);
+
+ for (i=0;i < ( (len>4)?4:len);i++)
+ ErrorF (" %08x", *ptr++);
+ ErrorF ("\n");
+ len -= 8;
+ }
+
+ ErrorF("---------+-----+----+----+----+----+----+----+----\n");
+}
+#endif
+
+#ifdef CIT_TIM
+/*****************************************************************************
+ * [cit_StartTimer]
+ ****************************************************************************/
+
+static void
+cit_StartTimer(cit_PrivatePtr priv)
+{
+ priv->timer_ptr = TimerSet(priv->timer_ptr, 0, priv->timer_val1,
+ priv->timer_callback, (pointer)priv);
+ DBG(5, ErrorF ("%scit_StartTimer called PTR=%08x\n", CI_INFO, priv->timer_ptr));
+}
+
+
+/*****************************************************************************
+ * [cit_CloseTimer]
+ ****************************************************************************/
+static void
+cit_CloseTimer(cit_PrivatePtr priv)
+{
+
+ DBG(5, ErrorF ("%scit_CloseTimer called PTR=%08x\n", CI_INFO, priv->timer_ptr));
+ if(priv->timer_ptr)
+ {
+ TimerFree(priv->timer_ptr);
+ priv->timer_ptr = NULL;
+ }
+ else
+ DBG(5, ErrorF ("%scit_CloseTimer: Nothing to close\n", CI_WARNING));
+}
+
+
+
+/*****************************************************************************
+ * [cit_DualTouchTimer]
+ ****************************************************************************/
+static CARD32
+cit_DualTouchTimer(OsTimerPtr timer, CARD32 now, pointer arg)
+{
+ cit_PrivatePtr priv = (cit_PrivatePtr) arg;
+ int sigstate;
+
+ DBG(5, ErrorF ("%scit_DualTouchTimer called %d\n", CI_INFO, GetTimeInMillis()));
+
+ priv->packet[0] = R_EXIT; /* build a exit message */
+ priv->packet[1] = LOBYTE(priv->raw_x);
+ priv->packet[2] = HIBYTE(priv->raw_x);
+ priv->packet[3] = LOBYTE(priv->raw_y);
+ priv->packet[4] = HIBYTE(priv->raw_y);
+ priv->packeti = 5;
+ priv->fake_exit = TRUE;
+ sigstate = xf86BlockSIGIO ();
+
+
+ priv->local->read_input(priv->local); /* faking up an exit message */
+ xf86UnblockSIGIO (sigstate);
+
+ DBG(3, ErrorF ("%scit_DualTouchTimer: Faking Exit Message Sent\n", CI_INFO));
+
+ return (0); /* stop timer */
+}
+
+#endif
+
+/*****************************************************************************
+ * [CitronPreInit]
+ ****************************************************************************/
+static InputInfoPtr
+CitronPreInit (InputDriverPtr drv, IDevPtr dev, int flags)
+{
+ LocalDevicePtr local = xf86AllocateInput(drv, 0);
+ cit_PrivatePtr priv = (cit_PrivatePtr) xcalloc (1, sizeof (cit_PrivateRec));
+ char *s;
+#if(INITT)
+ int errmaj, errmin;
+#endif
+
+ ErrorF ("%sCitronPreInit called - xcalloc=%d\n", CI_INFO, sizeof(cit_PrivateRec));
+/* DBG(2, ErrorF("\txf86Verbose=%d\n", xf86Verbose));*/
+ if ((!local) || (!priv))
+ {
+ ErrorF("%s\t- unable to allocate structures!\n", CI_ERROR);
+ goto SetupProc_fail;
+ }
+
+
+ /* this results in an xf86strdup that must be freed later */
+ local->name = xf86SetStrOption(local->options, "DeviceName", "CiTouch");
+ ErrorF("%sDevice name: %s\n", CI_INFO, local->name);
+
+ local->type_name = XI_TOUCHSCREEN;
+
+ /*
+ * Standard setup for the local device record
+ */
+ 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->history_size = xf86SetIntOption(local->options, "HistorySize", 0);
+ local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS;
+ local->conf_idev = dev;
+
+ xf86CollectInputOptions(local, default_options, NULL);
+
+/* xf86OptionListReport(local->options); */
+
+
+
+ debug_level = xf86SetIntOption(local->options, "DebugLevel", 0);
+ if(debug_level)
+ {
+#ifdef DEBUG
+ ErrorF("%sDebug level set to %d\n", CI_CONFIG, debug_level);
+#else
+ ErrorF("%sDebug not available\n", CI_INFO);
+#endif
+ }
+
+
+#if(INITT)
+
+
+ DBG(5, ErrorF ("%sOpenSerial will be called\n", CI_INFO));
+
+ local->fd = xf86OpenSerial (local->options);
+ if (local->fd == -1)
+ {
+ ErrorF ("%s\t- unable to open device %s\n", CI_ERROR, xf86FindOptionValue (local->options, "Device"));
+ goto SetupProc_fail;
+ }
+
+ DBG(6, ErrorF("%s\t+ %s opened successfully.\n", CI_INFO, xf86FindOptionValue (local->options, "Device")));
+#endif
+
+ /*
+ * Process the options for the IRT
+ */
+ priv->screen_num = xf86SetIntOption(local->options, "ScreenNumber", 0);
+ ErrorF("%sAssociated screen: %d\n", CI_CONFIG, priv->screen_num);
+ priv->min_x = xf86SetIntOption(local->options, "MinX", CIT_DEF_MIN_X);
+ ErrorF("%sMinimum x position: %d\n", CI_CONFIG, priv->min_x);
+ priv->max_x = xf86SetIntOption(local->options, "MaxX", CIT_DEF_MAX_X);
+ ErrorF("%sMaximum x position: %d\n", CI_CONFIG, priv->max_x);
+ priv->min_y = xf86SetIntOption(local->options, "MinY", CIT_DEF_MIN_Y);
+ ErrorF("%sMinimum y position: %d\n", CI_CONFIG, priv->min_y);
+ priv->max_y = xf86SetIntOption(local->options, "MaxY", CIT_DEF_MAX_Y);
+ ErrorF("%sMaximum y position: %d\n", CI_CONFIG, priv->max_y);
+ priv->button_number = xf86SetIntOption(local->options, "ButtonNumber", 1);
+ ErrorF("%sButton Number: %d\n", CI_CONFIG, priv->button_number);
+ priv->button_threshold = xf86SetIntOption(local->options, "ButtonThreshold", 10);
+ ErrorF("%sButton Threshold: %d\n", CI_CONFIG, priv->button_threshold);
+ priv->sleep_mode = xf86SetIntOption(local->options, "SleepMode", 0);
+ ErrorF("%sSleep Mode: %d\n", CI_CONFIG, priv->sleep_mode);
+ priv->sleep_time_act = xf86SetIntOption(local->options, "SleepTime", 65535);
+ ErrorF("%sSleep Time: %d\n", CI_CONFIG, priv->sleep_time_act);
+ priv->sleep_time_scan = xf86SetIntOption(local->options, "SleepScan", 65535);
+ ErrorF("%sSleep Scan: %d\n", CI_CONFIG, priv->sleep_time_scan);
+ priv->pwm_active = xf86SetIntOption(local->options, "PWMActive", 255);
+ ErrorF("%sPWM Active: %d\n", CI_CONFIG, priv->pwm_active);
+ priv->pwm_sleep = xf86SetIntOption(local->options, "PWMSleep", 255);
+ ErrorF("%sPWM Sleep: %d\n", CI_CONFIG, priv->pwm_sleep);
+ priv->click_mode = xf86SetIntOption(local->options, "ClickMode", NO_CLICK_MODE);
+ ErrorF("%sClick Mode: %d\n", CI_CONFIG, priv->click_mode);
+ priv->origin = xf86SetIntOption(local->options, "Origin", 0);
+ ErrorF("%sOrigin: %d\n", CI_CONFIG, priv->origin);
+ priv->doze_mode = xf86SetIntOption(local->options, "DozeMode", 0);
+ ErrorF("%sDoze Mode: %d\n", CI_CONFIG, priv->doze_mode);
+ priv->doze_time_act = xf86SetIntOption(local->options, "DozeTime", 10);
+ ErrorF("%sDoze Time: %d\n", CI_CONFIG, priv->doze_time_act);
+ priv->doze_time_scan = xf86SetIntOption(local->options, "DozeScan", 25);
+ ErrorF("%sDoze Scan: %d\n", CI_CONFIG, priv->doze_time_scan);
+ priv->delta_x = xf86SetIntOption(local->options, "DeltaX", 0) & 0xff;
+ ErrorF("%sDelta X: %d\n", CI_CONFIG, priv->delta_x);
+ priv->delta_y = xf86SetIntOption(local->options, "DeltaY", 0) & 0xff;
+ ErrorF("%sDelta Y: %d\n", CI_CONFIG, priv->delta_y);
+ priv->beep = xf86SetIntOption(local->options, "Beep", 0);
+ ErrorF("%sBeep: %s\n", CI_CONFIG, (priv->beep > 0) ? "activated":"not activated");
+ priv->press_vol = xf86SetIntOption(local->options, "PressVol", 100);
+ ErrorF("%sBeep Pressure Volume: %d\n", CI_CONFIG, priv->press_vol);
+ priv->press_pitch = xf86SetIntOption(local->options, "PressPitch", 880);
+ ErrorF("%sBeep Pressure Pitch: %d\n", CI_CONFIG, priv->press_pitch);
+ priv->press_dur = xf86SetIntOption(local->options, "PressDur", 15) & 0xff;
+ ErrorF("%sBeep Pressure Duration: %d\n", CI_CONFIG, priv->press_dur);
+ priv->rel_vol = xf86SetIntOption(local->options, "ReleaseVol", 100);
+ ErrorF("%sBeep Release Volume: %d\n", CI_CONFIG, priv->rel_vol);
+ priv->rel_pitch = xf86SetIntOption(local->options, "ReleasePitch", 1200);
+ ErrorF("%sBeep Release Pitch: %d\n", CI_CONFIG, priv->rel_pitch);
+ priv->rel_dur = xf86SetIntOption(local->options, "ReleaseDur", 10) & 0xff;
+ ErrorF("%sBeep Release Duration: %d\n", CI_CONFIG, priv->rel_dur);
+ priv->beam_timeout = xf86SetIntOption(local->options, "BeamTimeout", 30) & 0xffff;
+ ErrorF("%sBeam Timeout: %d\n", CI_CONFIG, priv->beam_timeout);
+ priv->touch_time = xf86SetIntOption(local->options, "TouchTime", 0) & 0xff;
+ ErrorF("%sTouch Time: %d\n", CI_CONFIG, priv->touch_time);
+ priv->enter_count = xf86SetIntOption(local->options, "EnterCount", 3);
+ ErrorF("%sEnter Count: %d\n", CI_CONFIG, priv->enter_count);
+ priv->max_dual_count = xf86SetIntOption(local->options, "DualCount", MAX_DUAL_TOUCH_COUNT);
+ ErrorF("%sDual Count: %d\n", CI_CONFIG, priv->max_dual_count);
+
+/* trace the min and max values */
+ priv->raw_min_x = CIT_DEF_MAX_X;
+ priv->raw_max_x = 0;
+ priv->raw_min_y = CIT_DEF_MAX_Y;
+ priv->raw_max_y = 0;
+
+#ifdef CIT_TIM
+/* preset timer values */
+ priv->timer_ptr = NULL;
+ priv->timer_val1 = 0;
+ priv->timer_val2 = 0;
+ priv->timer_callback = NULL;
+#endif
+
+ priv->fake_exit = FALSE;
+ priv->enter_touched = 0; /* preset */
+ priv->local = local; /* save local device pointer */
+
+ DBG(6, ErrorF("%s\t+ options read\n", CI_INFO));
+ s = xf86FindOptionValue (local->options, "ReportingMode");
+ if ((s) && (xf86NameCmp (s, "raw") == 0))
+ priv->reporting_mode = TS_Raw;
+ else
+ priv->reporting_mode = TS_Scaled;
+
+#if(INITT)
+ /*
+ * Create an X Input Serial Buffer, because IRT is connected to a serial port
+ */
+ priv->buffer = XisbNew (local->fd, CIT_BUFFER_SIZE);
+#endif
+ priv->proximity = FALSE;
+ priv->button_down = FALSE;
+ priv->dual_touch_count = 0;
+ priv->dual_flg = 0;
+ priv->state = 0;
+ priv->lex_mode = cit_idle;
+ priv->last_x = 0;
+ priv->last_y = 0;
+ priv->query_state = 0; /* first query */
+
+
+#if(INITT)
+ DBG (8, XisbTrace (priv->buffer, 1));
+
+
+ /*
+ * Verify that the IRT is attached and functional
+ */
+ if (QueryHardware (local, &errmaj, &errmin) != Success)
+ {
+ ErrorF ("%s\t- Unable to query/initialize Citron hardware.\n", CI_INFO);
+ goto SetupProc_fail;
+ }
+#endif
+
+ xf86ProcessCommonOptions(local, local->options);
+ local->flags |= XI86_CONFIGURED;
+#if(PK)
+ if (xf86FindOption (local->options, "DemandLoaded"))
+ {
+ DBG (5, ErrorF ("%s\tCitron module was demand loaded\n", CI_INFO));
+ xf86AddLocalDevice (local, TRUE);
+ }
+ else
+ xf86AddLocalDevice (local, FALSE);
+#endif
+
+ if (local->fd >= 0)
+ {
+ RemoveEnabledDevice (local->fd);
+#if(INITT)
+ if (priv->buffer)
+ {
+ XisbFree(priv->buffer);
+ priv->buffer = NULL;
+ }
+ xf86CloseSerial(local->fd);
+#endif
+ }
+
+
+ /* return the LocalDevice */
+ DBG(5, ErrorF ("%sCitronPreInit success\n", CI_INFO));
+ return (local);
+
+
+ /*
+ * If something went wrong, cleanup and return NULL
+ */
+ SetupProc_fail:
+#if(INITT)
+ if ((local) && (local->fd))
+ xf86CloseSerial (local->fd);
+#endif
+ if ((local) && (local->name))
+ xfree (local->name);
+ if (local)
+ xfree (local);
+#if(INITT)
+ if ((priv) && (priv->buffer))
+ XisbFree (priv->buffer);
+#endif
+ if (priv)
+ xfree (priv);
+ ErrorF ("%sCitronPreInit returning NULL\n", CI_ERROR);
+ return (NULL);
+}
+
+
+
+/*****************************************************************************
+ * [DeviceControl]
+ ****************************************************************************/
+static Bool
+DeviceControl (DeviceIntPtr dev, int mode)
+{
+ Bool RetVal;
+
+ DBG(5, ErrorF ("%sDeviceControl called; mode = %d\n", CI_INFO, mode));
+ switch (mode)
+ {
+ case DEVICE_INIT:
+ DBG(6, ErrorF ("%s\tINIT\n", CI_INFO));
+ DeviceInit (dev);
+ RetVal = Success;
+ break;
+ case DEVICE_ON:
+ DBG(6, ErrorF ("%s\tON\n", CI_INFO));
+ RetVal = DeviceOn (dev);
+ break;
+ case DEVICE_OFF:
+ DBG(6, ErrorF ("%s\tOFF\n", CI_INFO));
+ RetVal = DeviceOff (dev);
+ break;
+ case DEVICE_CLOSE:
+ DBG(6, ErrorF ("%s\tCLOSE\n", CI_INFO));
+ RetVal = DeviceClose (dev);
+ break;
+ default:
+ ErrorF ("%sDeviceControl Mode (%d) not found\n", CI_ERROR, mode);
+ RetVal = BadValue;
+ }
+ return(RetVal);
+}
+
+/*****************************************************************************
+ * [DeviceOn]
+ ****************************************************************************/
+static Bool
+DeviceOn (DeviceIntPtr dev)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
+ int errmaj, errmin;
+
+ DBG(5, ErrorF ("%sDeviceOn called\n", CI_INFO));
+
+ local->fd = xf86OpenSerial(local->options);
+ if (local->fd == -1)
+ {
+ xf86Msg(X_WARNING, "%s%s: cannot open input device\n", CI_ERROR, local->name);
+ goto DeviceOn_fail;
+ }
+ priv->buffer = XisbNew (local->fd, CIT_BUFFER_SIZE);
+ if (!priv->buffer)
+ goto DeviceOn_fail;
+
+ xf86FlushInput(local->fd);
+
+ if (QueryHardware (local, &errmaj, &errmin) != Success)
+ {
+ ErrorF ("%s\t- Unable to query/initialize Citron hardware.\n", CI_ERROR);
+ goto DeviceOn_fail;
+ }
+
+ AddEnabledDevice (local->fd);
+ dev->public.on = TRUE;
+ return (Success);
+
+ /*
+ * If something went wrong, cleanup
+ */
+ DeviceOn_fail:
+ if ((local) && (local->fd))
+ xf86CloseSerial (local->fd);
+
+ if ((local) && (local->name))
+ xfree (local->name);
+ if (local)
+ {
+ xfree (local);
+ local = NULL;
+ }
+ if ((priv) && (priv->buffer))
+ XisbFree (priv->buffer);
+ if (priv)
+ {
+ xfree (priv);
+ priv = NULL;
+ }
+ ErrorF ("%sDeviceOn failed\n", CI_ERROR);
+ return (!Success);
+
+
+
+}
+
+/*****************************************************************************
+ * [DeviceOff]
+ ****************************************************************************/
+static Bool
+DeviceOff (DeviceIntPtr dev)
+{
+ DBG(5, ErrorF ("%sDeviceOff called\n", CI_INFO));
+ return DeviceClose(dev);
+}
+
+/*****************************************************************************
+ * [DeviceClose]
+ ****************************************************************************/
+static Bool
+DeviceClose (DeviceIntPtr dev)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
+ int c;
+
+ DBG(5, ErrorF ("%sDeviceClose called\n",CI_INFO));
+
+ cit_Flush(priv->buffer);
+
+ cit_SendCommand(priv->buffer, C_SOFTRESET, 0);
+#ifdef CIT_TIM
+ cit_CloseTimer(priv); /* Close timer if started */
+#endif
+ XisbTrace(priv->buffer, 1); /* trace on */
+ XisbBlockDuration (priv->buffer, 500000);
+ c = XisbRead (priv->buffer);
+ if(c == CTS_NAK)
+ {
+ DBG(6, ErrorF ("%sTouch Reset executed\n",CI_INFO));
+ }
+ else
+ {
+ DBG(6, ErrorF ("%sTouch Reset not executed\n",CI_ERROR));
+ }
+
+
+/* Now free all allocated memory */
+ if (local->fd >= 0)
+ {
+ RemoveEnabledDevice (local->fd);
+ if (priv->buffer)
+ {
+ XisbFree(priv->buffer);
+ priv->buffer = NULL;
+ }
+ xf86CloseSerial(local->fd);
+ local->fd = 0;
+ }
+
+ dev->public.on = FALSE;
+ ErrorF("%sx-range = [%d..%d]\n", CI_INFO, priv->raw_min_x, priv->raw_max_x);
+ ErrorF("%sy-range = [%d..%d]\n", CI_INFO, priv->raw_min_y, priv->raw_max_y);
+
+ return (Success);
+}
+
+
+/*****************************************************************************
+ * [DeviceInit]
+ ****************************************************************************/
+static Bool
+DeviceInit (DeviceIntPtr dev)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
+
+ unsigned char map[] =
+ {0, 1};
+
+ DBG (5, ErrorF("%sDeviceInit called\n", CI_INFO));
+ /*
+ * these have to be here instead of in the SetupProc, because when the
+ * SetupProc is run and 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;
+
+ DBG (5, ErrorF("%sScreen Number: %d Screen Width: %d Screen Height: %d\n", CI_INFO,
+ priv->screen_num, priv->screen_width, priv->screen_height));
+
+ /*
+ * Device reports button press for up to 1 button.
+ */
+ if (InitButtonClassDeviceStruct (dev, 1, map) == FALSE)
+ {
+ ErrorF ("%sUnable to allocate Citron touchscreen ButtonClassDeviceStruct\n", CI_ERROR);
+ return !Success;
+ }
+
+ /*
+ * Device reports motions on 2 axes in absolute coordinates.
+ * Axes min and max values are reported in raw coordinates.
+ * Resolution is computed roughly by the difference between
+ * max and min values scaled from the approximate size of the
+ * screen to fit one meter.
+ * Device may reports touch pressure on the 3rd axis.
+ */
+ if (InitValuatorClassDeviceStruct (dev, 2, xf86GetMotionEvents,
+ local->history_size, Absolute) == FALSE)
+ {
+ ErrorF ("%sUnable to allocate Citron touchscreen ValuatorClassDeviceStruct\n", CI_ERROR);
+ return !Success;
+ }
+ else
+ {
+ InitValuatorAxisStruct (dev, 0, priv->min_x, priv->max_x,
+ CIT_DEF_MAX_X,
+ CIT_DEF_MIN_X /* min_res */ ,
+ CIT_DEF_MAX_X /* max_res */ );
+ InitValuatorAxisStruct (dev, 1, priv->min_y, priv->max_y,
+ CIT_DEF_MAX_Y,
+ CIT_DEF_MIN_Y /* min_res */ ,
+ CIT_DEF_MAX_Y /* max_res */ );
+ }
+
+ if (InitProximityClassDeviceStruct (dev) == FALSE)
+ {
+ ErrorF ("%sUnable to allocate Citron touchscreen ProximityClassDeviceStruct\n", CI_ERROR);
+ return !Success;
+ }
+
+
+ /*
+ * Use the LedFeedbackClass to set some driver parameters
+ */
+
+ /* ID=0 --> Return driver version (RO) */
+
+ if (InitLedFeedbackClassDeviceStruct(dev, xf86CitronFeedback0) == FALSE)
+ {
+ ErrorF("Unable to allocate CITRON touchscreen LedFeedbackClassDeviceStruct, id=0\n");
+ return !Success;
+ }
+ /* ID=1 --> ENTER_COUNT */
+ if (InitLedFeedbackClassDeviceStruct(dev, xf86CitronFeedback1) == FALSE)
+ {
+ ErrorF("Unable to allocate CITRON touchscreen LedFeedbackClassDeviceStruct, id=1\n");
+ return !Success;
+ }
+
+ /* ID=2 --> */
+ if (InitLedFeedbackClassDeviceStruct(dev, xf86CitronFeedback2) == FALSE)
+ {
+ ErrorF("Unable to allocate CITRON touchscreen LedFeedbackClassDeviceStruct, id=2\n");
+ return !Success;
+ }
+
+
+ /*
+ * Allocate the motion events buffer.
+ */
+ xf86MotionHistoryAllocate (local);
+ return (Success);
+}
+
+/*****************************************************************************
+ * [ReadInput]
+ ****************************************************************************/
+static void
+ReadInput (LocalDevicePtr local)
+{
+ int x, y;
+ cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
+
+ DBG(RI, ErrorF("%sReadInput called\n", CI_INFO));
+
+ /*
+ * 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 by a select with a 0 timeout to prevent
+ * read from blocking indefinately.
+ */
+ if(!priv->fake_exit)
+ {
+ XisbBlockDuration (priv->buffer, -1);
+ DBG(RI, ErrorF("%sXisbBlockDuration = -1\n", CI_INFO));
+ }
+ while (
+#ifdef CIT_TIM
+ priv->fake_exit ||
+#endif
+ (cit_GetPacket (priv) == Success))
+ {
+ cit_ProcessPacket(priv);
+
+
+
+ if (priv->reporting_mode == TS_Scaled)
+ {
+ x = xf86ScaleAxis (priv->raw_x, 0, priv->screen_width, priv->min_x,
+ priv->max_x);
+ y = xf86ScaleAxis (priv->raw_y, 0, priv->screen_height, priv->min_y,
+ priv->max_y);
+ DBG(RI, ErrorF("%s\tscaled coordinates: (%d, %d)\n", CI_INFO, x, y));
+ }
+ else
+ {
+ x = priv->raw_x;
+ y = priv->raw_y;
+ }
+
+ xf86XInputSetScreen (local, priv->screen_num, x, y);
+
+ if ((priv->proximity == FALSE) && (priv->state & CIT_TOUCHED))
+ {
+ priv->proximity = TRUE;
+ xf86PostProximityEvent (local->dev, 1, 0, 2, x, y);
+ DBG(RI, ErrorF("%s\tproximity(TRUE, x=%d, y=%d)\n", CI_INFO, 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.
+ * First test if coordinates have changed a predefined amount of pixels
+ */
+
+ if ( ((x >= (priv->last_x + priv->delta_x)) ||
+ (x <= (priv->last_x - priv->delta_x)) ||
+ (y >= (priv->last_y + priv->delta_y)) ||
+ (y <= (priv->last_y - priv->delta_y))) ||
+ ( ((x < priv->delta_x) ||
+ (x > (priv->screen_width - priv->delta_x))) ||
+ ((y < priv->delta_x) ||
+ (y > (priv->screen_height - priv->delta_y)))) )
+ {
+ xf86PostMotionEvent (local->dev, TRUE, 0, 2, x, y);
+ DBG(RI, ErrorF("%s\tPostMotionEvent(x=%d, y=%d, last_x=%d, last_y=%d)\n", CI_INFO,
+ x, y, priv->last_x, priv->last_y));
+
+ priv->last_x = x; /* save cooked data */
+ priv->last_y = y;
+ }
+
+ /*
+ * Emit a button press or release.
+ */
+
+ if ((priv->button_down == FALSE) && (priv->state & CIT_BUTTON))
+ {
+ if(priv->enter_touched < priv->enter_count)
+ priv->enter_touched++;
+
+ if(priv->enter_touched == priv->enter_count)
+ {
+ priv->enter_touched++; /* increment count one more time to prevent further enter events */
+ xf86PostButtonEvent (local->dev, TRUE,
+ priv->button_number, 1, 0, 2, x, y);
+ cit_Beep(priv, 1);
+
+ DBG(RI, ErrorF("%s\tPostButtonEvent(DOWN, x=%d, y=%d)\n", CI_INFO, x, y));
+
+ priv->button_down = TRUE;
+ }
+ }
+
+ if ((priv->button_down == TRUE) && !(priv->state & CIT_BUTTON))
+ {
+ xf86PostButtonEvent (local->dev, TRUE,
+ priv->button_number, 0, 0, 2, x, y);
+ cit_Beep(priv, 0);
+ priv->enter_touched = 0; /* reset coordinate report counter */
+ DBG(RI, ErrorF("%s\tPostButtonEvent(UP, x=%d, y=%d)\n", CI_INFO, x, y));
+ priv->button_down = FALSE;
+ }
+ /*
+ * the untouch should always come after the button release
+ */
+ if ((priv->proximity == TRUE) && !(priv->state & CIT_TOUCHED))
+ {
+ priv->proximity = FALSE;
+ xf86PostProximityEvent (local->dev, 0, 0, 2, x, y);
+ DBG(RI, ErrorF("%s\tproximity(FALSE, x=%d, y=%d)\n", CI_INFO, x, y));
+ }
+
+
+ DBG (RI, ErrorF ("%sTouchScreen: x(%d), y(%d), %s\n",
+ CI_INFO, x, y,
+ (priv->state == CIT_TOUCHED) ? "Touched" : "Released"));
+
+#ifdef CIT_TIM
+ if(priv->fake_exit)
+ {
+ priv->fake_exit = FALSE; /* do not sent any further faked exit messages */
+ return;
+ }
+#endif
+ }
+ DBG(RI, ErrorF("%sExit ReadInput\n", CI_INFO));
+}
+
+/*****************************************************************************
+ * [ControlProc]
+ ****************************************************************************/
+static int
+ControlProc (LocalDevicePtr local, xDeviceCtl * control)
+{
+ xDeviceTSCalibrationCtl *c = (xDeviceTSCalibrationCtl *) control;
+ cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
+
+ DBG(5, ErrorF("%sControlProc called\n", CI_INFO));
+
+ 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);
+}
+
+/*****************************************************************************
+ * [CloseProc]
+ ****************************************************************************/
+static void
+CloseProc (LocalDevicePtr local)
+{
+ DBG(5, ErrorF("%sCloseProc called\n", CI_INFO));
+}
+
+/*****************************************************************************
+ * [SwitchMode]
+ ****************************************************************************/
+static int
+SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
+ DBG(5, ErrorF("%sSwitchMode called; mode = %d\n", CI_INFO, mode));
+ if ((mode == TS_Raw) || (mode == TS_Scaled))
+ {
+ priv->reporting_mode = mode;
+ DBG(6, ErrorF("%s\treporting mode = %s\n", CI_INFO, mode==TS_Raw?"raw":"scaled"));
+ return (Success);
+ }
+ else if ((mode == SendCoreEvents) || (mode == DontSendCoreEvents))
+ {
+ xf86XInputSetSendCoreEvents (local, (mode == SendCoreEvents));
+ DBG(6, ErrorF("%s\tmode = %sSend Core Events\n", CI_INFO, mode==DontSendCoreEvents?"Don\'t ":""));
+ return (Success);
+ }
+#ifdef CIT_MODE_EXT
+ else if (mode == ClickMode_Enter)
+ {
+ priv->click_mode = CM_ENTER;
+ DBG(6, ErrorF("%s\tset click mode to ENTER\n", CI_INFO));
+ return (Success);
+ }
+ else if (mode == ClickMode_Dual)
+ {
+ priv->click_mode = CM_DUAL;
+ DBG(6, ErrorF("%s\tset click mode to DUAL TOUCH\n", CI_INFO));
+ return (Success);
+ }
+ else if (mode == ClickMode_ZPress)
+ {
+ priv->click_mode = CM_ZPRESS;
+ DBG(6, ErrorF("%s\tset click mode to Z-Press\n", CI_INFO));
+ return (Success);
+ }
+#endif
+ else
+ {
+ ErrorF("%sUnknown mode for Citron Touchscreen Switchmode Function: 0x%02x!\n", CI_ERROR, mode);
+ return (!Success);
+ }
+}
+
+/*****************************************************************************
+ * [ConvertProc]
+ ****************************************************************************/
+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)
+{
+ cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
+
+ DBG(5, ErrorF("%sConvertProc called(first=%d, num=%d, v0=%d, v1=%d, v2=%d, v3=%d\n",
+ CI_INFO, first, num, v0, v1, v2, v3));
+ 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;
+ }
+ DBG(6, ErrorF("%s\t+ x=%d, y=%d\n",CI_INFO, *x, *y));
+ return (TRUE);
+}
+
+/*****************************************************************************
+ * [QueryHardware]
+ ****************************************************************************/
+static Bool
+QueryHardware (LocalDevicePtr local, int *errmaj, int *errmin)
+{
+ cit_PrivatePtr priv = (cit_PrivatePtr) (local->private);
+ unsigned char x;
+ int i, cnt;
+ int err; /* for WAIT */
+ int init = FALSE;
+
+ /* Reset the IRT from any mode and wait for end of warmstart */
+ DBG(5, ErrorF("%sQueryHardware called\n", CI_INFO));
+
+/* Will not work with XFree86 4.0 */
+/* xf86SerialSendBreak (local->fd, 2); */
+ cit_Flush(priv->buffer);
+
+/* Test if touch is already initialized */
+ cit_SendCommand(priv->buffer, C_GETORIGIN, 0);
+
+ /* wait max. 0.5 seconds for acknowledge */
+ DBG(6, ErrorF("%s\t* waiting for acknowledge\n", CI_INFO));
+/* WAIT(50); */
+ XisbBlockDuration (priv->buffer, 500000);
+ cnt = 0;
+ err = FALSE;
+
+ while ((i=XisbRead(priv->buffer)) != -1)
+ {
+ DBG(7, ErrorF("%s\t* 0x%02X received - cnt %d\n",CI_INFO, i, cnt));
+ {
+ switch (cnt)
+ {
+
+ case 0:
+ if ((unsigned char)i != CTS_STX)
+ init = TRUE;
+ break;
+
+ case 1:
+ if ((unsigned char)i != (CMD_REP_CONV & C_GETORIGIN))
+ init = TRUE;
+ break;
+
+ case 2:
+ if ((unsigned char)i > 3)
+ init = TRUE;
+ break;
+
+ case 3:
+ if ((unsigned char)i != CTS_ETX)
+ init = TRUE;
+ break;
+ }
+ }
+ cnt++;
+ if(init)
+ break;
+ }
+ /* Touch is physically not connected or sio problem or break */
+ cit_Flush(priv->buffer); /* flush the buffer and wait for break */
+ if(cnt < 3)
+ {
+ WAIT(150);
+ /* if we have 0 in the buffer I assume we got a break */
+ if (XisbRead(priv->buffer) == 0)
+ {
+
+ DBG(6, ErrorF("%s+ BREAK detected - cnt=%d\n", CI_INFO, cnt));
+ init = TRUE;
+ }
+ else /* if nothing is in the buffer I assume the touch is not connected */
+ {
+ ErrorF("%sTouch not connected - please connect - cnt=%d\n", CI_ERROR, cnt);
+ return(Success); /* If success is returned we can later connect */
+ } /* the touch again when it was reconnected without */
+ } /* restarting X */
+
+ /* if init is true, we have to (re)initialize the touch */
+ if (init)
+ {
+ ErrorF("%sTouch not initialized yet\n",CI_INFO);
+
+ /*
+ * IRT signals end of startup by sending BREAKS with 100 ms length.
+ * wait a maximum of 2 seconds for at least 2 consecutive breaks
+ * to be sure the IRT is really initialized
+ */
+ cit_Flush(priv->buffer); /* clear the buffer and wait for break */
+ DBG(6, ErrorF("%s\t* waiting for BREAKS...\n", CI_INFO));
+ for (i=0, cnt=0; (i<20) && (cnt<2); i++)
+ {
+/* millisleep (105); */
+ WAIT(120); /* wait a little bit longer than 100 ms */
+ DBG(7, ErrorF("%s\t (loop %d)\n", CI_INFO, i));
+ if (XisbRead(priv->buffer) == 0)
+ {
+ cnt++;
+ DBG(6, ErrorF("%s\t+ BREAK %d detected\n", CI_INFO, cnt));
+ }
+ else
+ {
+ cnt = 0;
+ }
+ }
+ if (cnt < 2)
+ {
+ ErrorF("%sCannot reset Citron Infrared Touch!\n", CI_ERROR);
+/* *errmaj = LDR_NOHARDWARE; */
+ return (!Success);
+ }
+ /* Now initialize IRT to CTS Protocol */
+ DBG(6, ErrorF("%s\t* initializing to CTS mode\n", CI_INFO));
+ x = 0x0d;
+ for (i=0; i<2; i++)
+ {
+ XisbWrite(priv->buffer, &x, 1);
+/* millisleep (50); */
+ WAIT(50);
+ }
+ x = MODE_D;
+ XisbWrite(priv->buffer, &x, 1);
+
+ /* wait max. 0.5 seconds for acknowledge */
+ DBG(6, ErrorF("%s\t* waiting for acknowledge\n", CI_INFO));
+ XisbBlockDuration (priv->buffer, 500000);
+ cnt = 0;
+ while ((i=XisbRead(priv->buffer)) != -1)
+ {
+ DBG(7, ErrorF("%s\t* 0x%02X received - waiting for CTS_XON\n",CI_INFO, i));
+ if ((unsigned char)i == CTS_XON)
+ break;
+ if(cnt++ > 100) return (Success); /* emergency stop */
+ }
+ if ((unsigned char)i != CTS_XON)
+ {
+ ErrorF("%sNo acknowledge from Citron Infrared Touch!\n", CI_ERROR);
+/* *errmaj = LDR_NOHARDWARE; */
+ return (!Success);
+ }
+ }
+ /* now we have the touch connected, do the initialization stuff */
+ DBG(6, ErrorF("%s\t+ Touch connected!\n",CI_INFO));
+ cit_Flush(priv->buffer);
+
+ DBG(6, ErrorF("%s\t+ requesting pressure sensors report\n",CI_INFO));
+ if (cit_GetPressureSensors(priv)!=Success)
+ {
+ ErrorF("%sNo pressure sensors report received from Citron Touchscreen!\n",CI_ERROR);
+ }
+
+ DBG(5, ErrorF("%s ClickMode is %d\n",CI_INFO, priv->click_mode));
+ if(priv->click_mode == NO_CLICK_MODE) /* no click mode set in XF86Config */
+ {
+ priv->click_mode = (priv->pressure_sensors > 0) ? CM_ZPRESS : CM_ENTER;
+ DBG(5, ErrorF("%sClickMode set to %d\n",CI_INFO, priv->click_mode));
+ }
+
+ cit_SendCommand(priv->buffer, C_SETAREAFLAGS, 1, AOF_ADDEXIT
+ | AOF_ADDCOORD
+ | AOF_ACTIVE
+ | AOF_ADDPRESS);
+
+ cit_SendCommand(priv->buffer, C_SETAREAMODE, 1, AOM_CONT);
+
+ cit_SendCommand(priv->buffer, C_SETCONTTIME, 1, 20);
+
+ cit_SendCommand(priv->buffer, C_SETDUALTOUCHING, 1, DT_ERROR);
+
+ cit_SendCommand(priv->buffer, C_SETAREAPRESSURE, 1, LOBYTE(priv->button_threshold));
+
+ cit_SendCommand(priv->buffer, C_SETRESOLUTION, 4,
+ LOBYTE(CIT_DEF_MAX_X),
+ HIBYTE(CIT_DEF_MAX_X),
+ LOBYTE(CIT_DEF_MAX_Y),
+ HIBYTE(CIT_DEF_MAX_Y));
+
+ cit_SendCommand(priv->buffer, C_SETPWM, 2,
+ LOBYTE(priv->pwm_active),
+ LOBYTE(priv->pwm_sleep));
+
+ cit_SendCommand(priv->buffer, C_SETBEAMTIMEOUT, 2,
+ LOBYTE(priv->beam_timeout),
+ HIBYTE(priv->beam_timeout));
+
+ cit_SendCommand(priv->buffer, C_SETORIGIN, 1, LOBYTE(priv->origin));
+ cit_SendCommand(priv->buffer, C_SETTOUCHTIME, 1, LOBYTE(priv->touch_time));
+
+ cit_SendCommand(priv->buffer, C_SETSLEEPMODE, 5,
+ LOBYTE(priv->sleep_mode),
+ LOBYTE(priv->sleep_time_act),
+ HIBYTE(priv->sleep_time_act),
+ LOBYTE(priv->sleep_time_scan),
+ HIBYTE(priv->sleep_time_scan));
+
+ cit_SendCommand(priv->buffer, C_SETDOZEMODE, 5,
+ LOBYTE(priv->doze_mode),
+ LOBYTE(priv->doze_time_act),
+ HIBYTE(priv->doze_time_act),
+ LOBYTE(priv->doze_time_scan),
+ HIBYTE(priv->doze_time_scan));
+
+ cit_SendCommand(priv->buffer, C_SETTRANSMISSION, 1, TM_TRANSMIT);
+ cit_SendCommand(priv->buffer, C_SETSCANNING, 1, 1);
+
+
+ if(priv->query_state == 0) /* do error reporting only 1 time */
+ {
+ priv->query_state++;
+
+ DBG(6, ErrorF("%s\t+ requesting initial errors report\n",CI_INFO));
+ if (cit_GetInitialErrors(priv)!=Success)
+ {
+ ErrorF("%sNo initial error report received from Citron Touchscreen!\n",CI_ERROR);
+ *errmaj = LDR_NOHARDWARE;
+ return (!Success);
+ }
+ DBG(6, ErrorF("\t+ requesting defective beams report\n"));
+ if (cit_GetDefectiveBeams(priv)!=Success)
+ {
+ ErrorF("%sNo defective beams report received from Citron Touchscreen!\n",CI_ERROR);
+ *errmaj = LDR_NOHARDWARE;
+ return (!Success);
+ }
+ DBG(6, ErrorF("\t+ requesting touch revisions\n"));
+ if (cit_GetDesignator(priv)!=Success)
+ {
+ ErrorF("%sNo designator received from Citron Touchscreen!\n",CI_ERROR);
+ *errmaj = LDR_NOHARDWARE;
+ return (!Success);
+ }
+ if (cit_GetRevision(priv, GR_SYSMGR)!=Success)
+ {
+ ErrorF("%sNo system manager module revision received from Citron Touchscreen!\n",CI_ERROR);
+ *errmaj = LDR_NOHARDWARE;
+ return (!Success);
+ }
+ if (cit_GetRevision(priv, GR_HARDWARE)!=Success)
+ {
+ ErrorF("%sNo hardware module revision received from Citron Touchscreen!\n",CI_ERROR);
+ *errmaj = LDR_NOHARDWARE;
+ return (!Success);
+ }
+ if (cit_GetRevision(priv, GR_PROCESS)!=Success)
+ {
+ ErrorF("%sNo process module revision received from Citron Touchscreen!\n",CI_ERROR);
+ *errmaj = LDR_NOHARDWARE;
+ return (!Success);
+ }
+ if (cit_GetRevision(priv, GR_PROTOCOL)!=Success)
+ {
+ ErrorF("%sNo protocol module revision received from Citron Touchscreen!\n",CI_ERROR);
+ *errmaj = LDR_NOHARDWARE;
+ return (!Success);
+ }
+ if (cit_GetRevision(priv, GR_HWPARAM)!=Success)
+ {
+ ErrorF("%sNo hardware parameter module revision received from Citron Touchscreen!\n",CI_ERROR);
+ *errmaj = LDR_NOHARDWARE;
+ return (!Success);
+ }
+ }
+
+ DBG(6, ErrorF("%s\t+ Touch initialized - %d\n",CI_INFO, priv->query_state));
+
+ return (Success);
+}
+
+
+/*****************************************************************************
+ * [cit_GetPacket]
+ ****************************************************************************/
+static Bool
+cit_GetPacket (cit_PrivatePtr priv)
+{
+ int c;
+ int errmaj, errmin;
+
+ DBG(GP, ErrorF("%scit_GetPacket called\n", CI_INFO));
+ DBG(GP, ErrorF("%s\t* initial lex_mode =%d (%s)\n", CI_INFO, priv->lex_mode,
+ priv->lex_mode==cit_idle ?"idle":
+ priv->lex_mode==cit_getID ?"getID":
+ priv->lex_mode==cit_collect ?"collect":
+ priv->lex_mode==cit_escape ?"escape":
+ "???"));
+ while ((c = XisbRead (priv->buffer)) >= 0)
+ {
+#if(0)
+ DBG(GP, ErrorF("%s c=%d\n",CI_INFO, c));
+#endif
+ if (c == CTS_STX)
+ {
+ DBG(GP, ErrorF("%s\t+ STX detected\n", CI_INFO));
+ /* start of report received */
+ if (priv->lex_mode != cit_idle)
+ DBG(7, ErrorF("%s\t- no ETX received before this STX!\n", CI_WARNING));
+ priv->lex_mode = cit_getID;
+ DBG(GP, ErrorF("%s\t+ new lex_mode == getID\n", CI_INFO));
+ }
+ else if (c == CTS_ETX)
+ {
+ DBG(GP, ErrorF("%s\t+ ETX detected\n", CI_INFO));
+ /* end of command received */
+ /* always IDLE after report completion */
+ DBG(GP, ErrorF("%s\t+ new lex_mode == idle\n", CI_INFO));
+ if (priv->lex_mode == cit_collect)
+ {
+ DBG(GP, ErrorF("%s\t+ Good report received\n", CI_INFO));
+ priv->lex_mode = cit_idle;
+ return (Success);
+ }
+ DBG(GP, ErrorF("%s\t- unexpected ETX received!\n", CI_WARNING));
+ priv->lex_mode = cit_idle;
+ }
+ else if (c == CTS_ESC)
+ {
+ DBG(GP, ErrorF("%s\t+ escape detected\n", CI_INFO));
+ /* next character is encoded */
+ if (priv->lex_mode != cit_collect)
+ {
+ DBG(GP, ErrorF("%s\t- unexpected control character received\n", CI_WARNING));
+ }
+ else
+ {
+ priv->lex_mode = cit_escape;
+ DBG(GP, ErrorF("%s\t+ new lex_mode == escape\n", CI_INFO));
+ }
+ }
+ else if ((c < CTS_CTRLMIN) || (c > CTS_CTRLMAX))
+ {
+ /* regular report data received */
+ if (priv->lex_mode == cit_getID)
+ { /* receive report ID */
+ priv->packeti = 0;
+ priv->packet[priv->packeti++] = (unsigned char)c;
+ priv->lex_mode = cit_collect;
+ DBG(GP, ErrorF("%s\t+ identifier captured, new lex_mode == collect\n", CI_INFO));
+ }
+ else if ((priv->lex_mode == cit_collect) || (priv->lex_mode == cit_escape))
+ { /* receive command data */
+ if (priv->lex_mode == cit_escape)
+ { /* decode encoded data byte */
+ c &= CTS_DECODE; /* decode data */
+ priv->lex_mode = cit_collect;
+ DBG(GP, ErrorF("%s\t+ decoded character = 0x%02X\n", CI_INFO, c));
+ DBG(GP, ErrorF("%s\t+ new lex_mode = collect\n", CI_INFO));
+ }
+ if (priv->packeti < CTS_PACKET_SIZE)
+ { /* add data bytes to buffer */
+ priv->packet[priv->packeti++] = (unsigned char)c;
+ }
+ else
+ {
+ DBG(GP, ErrorF("%s\t- command buffer overrun\n", CI_ERROR));
+ /* let's reinitialize the touch - maybe it sends breaks */
+ cit_Flush(priv->buffer);
+
+ }
+ }
+ else
+ {
+ /* this happens e.g. when the touch sends breaks, so we try to reconnect */
+ DBG(GP, ErrorF("%s\t- unexpected non control received!\n", CI_WARNING));
+ DBG(GP, ErrorF("%s\t- Device not connected - trying to reconnect ...\n", CI_WARNING));
+ if (QueryHardware (priv->local, &errmaj, &errmin) != Success)
+ ErrorF ("%s\t- Unable to query/initialize Citron Touch hardware.\n", CI_ERROR);
+ else
+ ErrorF ("%s\t- Citron Touch reconnected\n", CI_INFO);
+
+ }
+ }
+ else if (c != CTS_XON && c != CTS_XOFF)
+ {
+ DBG(GP, ErrorF("%s\t- unhandled control character received!\n", CI_WARNING));
+ }
+ }
+ DBG(GP, ErrorF("%scit_GetPacket exit !Success\n", CI_INFO));
+ return (!Success);
+}
+
+
+/*****************************************************************************
+ * [cit_Flush]
+ ****************************************************************************/
+static void
+cit_Flush (XISBuffer *b)
+{
+ DBG(7, ErrorF("%scit_Flush called\n", CI_INFO));
+ XisbBlockDuration(b, 0);
+ while (XisbRead(b) > 0);
+}
+
+
+
+/*****************************************************************************
+ * [cit_Beep]
+ ****************************************************************************/
+static void
+cit_Beep(cit_PrivatePtr priv, int press)
+{
+#ifdef CIT_BEEP
+ if(priv->beep == 0)
+ return;
+
+ /* ring release bell */
+ if(press == 0)
+
+ /* [0]: volume, [1]: pitch, [2]: duration */
+ /* formula is: ((1193190 / freq) & 0xffff) | */
+ /* (((unsigned long)duration * loudness / 50) << 16)) */
+ /* .. whatever the inventor wants to intend by it, I don't know (PK) */
+
+ xf86SoundKbdBell(priv->rel_vol, priv->rel_pitch, priv->rel_dur);
+
+ else
+ /* ring press bell */
+ xf86SoundKbdBell(priv->press_vol,priv->press_pitch, priv->press_dur);
+
+ DBG(7, ErrorF("%scit_Beep called - %s\n", CI_INFO, (press == 0) ? "release" : "press"));
+#endif
+}
+
+
+/*****************************************************************************
+ * [cit_SendCommand]
+ ****************************************************************************/
+static void
+cit_SendCommand (XISBuffer *b, unsigned char cmd, int cnt, ...)
+{
+ va_list ap;
+ unsigned char data, x;
+
+ va_start(ap, cnt);
+
+ DBG(7, ErrorF("%scit_SendCommand(cmd=0x%02X, cnt=%d, ...)\n", CI_INFO, cmd, cnt));
+ x = CTS_STX;
+ XisbWrite(b, &x, 1); /* transmit start of packet */
+ XisbWrite(b, &cmd, 1); /* transmit command code */
+ x = CTS_ESC;
+ while (cnt-- > 0)
+ { /* encode and transmit optional parameters */
+ data = va_arg(ap, int);
+ if (data >= CTS_CTRLMIN && data <= CTS_CTRLMAX)
+ { /* data has to be encoded */
+ data |= CTS_ENCODE;
+ XisbWrite(b, &x, 1); /* mark coded data */
+ }
+ XisbWrite(b, &data, 1); /* transmit data */
+ }
+ x = CTS_ETX;
+ XisbWrite(b, &x, 1); /* transmit end of packet */
+ va_end(ap);
+}
+
+
+/*****************************************************************************
+ * [cit_GetInitialErrors]
+ ****************************************************************************/
+static Bool cit_GetInitialErrors(cit_PrivatePtr priv)
+{
+ unsigned long errors;
+ int i;
+ Bool res;
+
+ cit_Flush(priv->buffer);
+ cit_SendCommand(priv->buffer, C_GETERRORS, 1, GE_INITIAL);
+ /*
+ touch responds within 1 millisecond,
+ but it takes some time, until the command is sent!
+ */
+ for (i=0; i<5; i++)
+ {
+ XisbBlockDuration(priv->buffer, 500000);
+ res = cit_GetPacket(priv);
+ if ((res == Success) || (priv->lex_mode == cit_idle));
+ break;
+ }
+ if (res != Success)
+ {
+ DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
+ return (!Success);
+ }
+ /* examine packet */
+ if (priv->packeti != 6)
+ {
+ DBG(5, ErrorF("%sWrong packet length (expected 6, received %d bytes)\n", CI_NOTICE, priv->packeti));
+ return (!Success);
+ }
+ if (priv->packet[0] != (C_GETERRORS & CMD_REP_CONV))
+ {
+ DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ (C_GETERRORS & CMD_REP_CONV), priv->packet[0]));
+ return (!Success);
+ }
+ if (priv->packet[1] != GE_INITIAL)
+ {
+ DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ GE_INITIAL, priv->packet[1]));
+ return (!Success);
+ }
+ /* this is our packet! check contents */
+ errors = 0x00000001UL * (unsigned long)priv->packet[2]
+ + 0x00000100UL * (unsigned long)priv->packet[3]
+ + 0x00010000UL * (unsigned long)priv->packet[4]
+ + 0x10000000UL * (unsigned long)priv->packet[5];
+ DBG(6, ErrorF("%sinitial errors = 0x%08lX\n", CI_NOTICE, errors));
+ if (errors == 0x00000000UL)
+ {
+ ErrorF("%sNo initialization errors detected.\n", CI_INFO);
+ }
+ if (errors & IE_SMCHKSUM)
+ {
+ ErrorF("%sSystem Manager Module checksum error!\n", CI_ERROR);
+ }
+ if (errors & IE_SMINIT)
+ {
+ ErrorF("%sSystem Manager Module initialization error!\n", CI_ERROR);
+ }
+ if (errors & IE_HWCHKSUM)
+ {
+ ErrorF("%sHardware Module checksum error!\n", CI_ERROR);
+ }
+ if (errors & IE_HWINIT)
+ {
+ ErrorF("%sHardware Module initialization error!\n", CI_ERROR);
+ }
+ if (errors & IE_HW_BEAMS)
+ {
+ ErrorF("%s broken beams during initialization detected!\n", CI_ERROR);
+ }
+ if (errors & IE_HW_PSU)
+ {
+ ErrorF("%s force sensors not operating!\n", CI_ERROR);
+ }
+ if (errors & IE_HW_CPU)
+ {
+ ErrorF("%s CPU integrity test failed!\n", CI_ERROR);
+ }
+ if (errors & IE_HW_IRAM)
+ {
+ ErrorF("%s internal RAM error!\n", CI_ERROR);
+ }
+ if (errors & IE_HW_XRAM)
+ {
+ ErrorF("%s external SRAM error!\n", CI_ERROR);
+ }
+ if (errors & IE_PCCHKSUM)
+ {
+ ErrorF("%sProcess Module checksum error!\n", CI_ERROR);
+ }
+ if (errors & IE_PCINIT)
+ {
+ ErrorF("%sProcess Module initialization error!\n", CI_ERROR);
+ }
+ if (errors & IE_PTCHKSUM)
+ {
+ ErrorF("%sProtocol Module checksum error!\n", CI_ERROR);
+ }
+ if (errors & IE_PTINIT)
+ {
+ ErrorF("%sProtocol Module initialization error!\n", CI_ERROR);
+ }
+ if (errors & IE_BICHK)
+ {
+ ErrorF("%sBurnIn Module checksum error!\n", CI_ERROR);
+ }
+ if (errors & IE_BIINIT)
+ {
+ ErrorF("%sBurnIn Module initialization error!\n", CI_ERROR);
+ }
+ if (errors & IE_FPGACHK)
+ {
+ ErrorF("%sFPGA configuration checksum error!\n", CI_ERROR);
+ }
+ if (errors & IE_HWPCHK)
+ {
+ ErrorF("%sHardware Parameter checksum error!\n", CI_ERROR);
+ }
+ return (Success);
+}
+
+
+/*****************************************************************************
+ * [cit_GetDefectiveBeams]
+ ****************************************************************************/
+static Bool cit_GetDefectiveBeams(cit_PrivatePtr priv)
+{
+ unsigned nx, ny;
+ int i;
+ Bool res;
+
+ cit_Flush(priv->buffer);
+ cit_SendCommand(priv->buffer, C_GETERRORS, 1, GE_DEFECTBEAMS);
+ /*
+ touch responds within 1 millisecond,
+ but it takes some time, until the command is sent!
+ */
+ for (i=0; i<5; i++)
+ {
+ XisbBlockDuration(priv->buffer, 500000);
+ res = cit_GetPacket(priv);
+ if ((res == Success) || (priv->lex_mode == cit_idle));
+ break;
+ }
+ if (res != Success)
+ {
+ DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
+ return (!Success);
+ }
+ /* examine packet */
+ if (priv->packeti < 6)
+ {
+ DBG(5, ErrorF("%sWrong packet length (expected >= 6, received %d bytes)\n", CI_NOTICE, priv->packeti));
+ return (!Success);
+ }
+ if (priv->packet[0] != (C_GETERRORS & CMD_REP_CONV))
+ {
+ DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ (C_GETERRORS & CMD_REP_CONV), priv->packet[0]));
+ return (!Success);
+ }
+ if (priv->packet[1] != GE_DEFECTBEAMS)
+ {
+ DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ GE_DEFECTBEAMS, priv->packet[1]));
+ return (!Success);
+ }
+ /* this is our packet! check contents */
+ nx = 0x0001U * (unsigned)priv->packet[2]
+ + 0x0100U * (unsigned)priv->packet[3];
+
+ ny = 0x0001U * (unsigned)priv->packet[4]
+ + 0x0100U * (unsigned)priv->packet[5];
+ /* list defective X-beams */
+ if (nx > 0)
+ {
+ ErrorF("%s%u defective X-Beams detected:\n", CI_ERROR, nx);
+ for (i=0; i<nx; i++)
+ {
+ ErrorF("%s\tX%02u\n", CI_ERROR, (unsigned)priv->packet[6+i]);
+ }
+ }
+ else
+ {
+ ErrorF("%sNo defective X-beams detected.\n", CI_INFO);
+ }
+
+ /* list defective Y-beams */
+ if (ny > 0)
+ {
+ ErrorF("%s%u defective Y-Beams detected:\n", CI_ERROR, ny);
+ for (i=0; i<ny; i++)
+ {
+ ErrorF("%s\tY%02u\n", CI_ERROR, (unsigned)priv->packet[6+nx+i]);
+ }
+ }
+ else
+ {
+ ErrorF("%sNo defective Y-beams detected.\n", CI_INFO);
+ }
+ return (Success);
+}
+
+
+/*****************************************************************************
+ * [cit_GetDesignator]
+ ****************************************************************************/
+static Bool cit_GetDesignator(cit_PrivatePtr priv)
+{
+ int i,n;
+ Bool res;
+
+ cit_Flush(priv->buffer);
+ cit_SendCommand(priv->buffer, C_GETREVISIONS, 1, GR_DESIGNATOR);
+ /*
+ touch responds within 1 millisecond,
+ but it takes some time, until the command is sent and received!
+ */
+ for (i=0; i<5; i++)
+ {
+ XisbBlockDuration(priv->buffer, 500000);
+ res = cit_GetPacket(priv);
+ if ((res == Success) || (priv->lex_mode == cit_idle));
+ break;
+ }
+ if (res != Success)
+ {
+ DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
+ return (!Success);
+ }
+ /* examine packet */
+ if (priv->packeti < 2+CTS_DESIGNATOR_LEN+CTS_ASSY_LEN)
+ {
+ DBG(5, ErrorF("%sWrong packet length (expected >= %d, received %d bytes)\n", CI_NOTICE,
+ 2+CTS_DESIGNATOR_LEN+CTS_ASSY_LEN,
+ priv->packeti));
+ return (!Success);
+ }
+ if (priv->packet[0] != (C_GETREVISIONS & CMD_REP_CONV))
+ {
+ DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ (C_GETREVISIONS & CMD_REP_CONV), priv->packet[0]));
+ return (!Success);
+ }
+ if (priv->packet[1] != GR_DESIGNATOR)
+ {
+ DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ GR_DESIGNATOR, priv->packet[1]));
+ return (!Success);
+ }
+ /* this is our packet! check contents */
+ ErrorF("%sDesignator \"", CI_INFO);
+ i = 2;
+ n = 0;
+ while (n++ < CTS_DESIGNATOR_LEN && priv->packet[i]!=0)
+ {
+ ErrorF("%c", priv->packet[i++]);
+ }
+ ErrorF("\"\n%sAssembly \"", CI_INFO);
+ i = 2 + CTS_DESIGNATOR_LEN;
+ n = 0;
+ while (n++ < CTS_ASSY_LEN && priv->packet[i]!=0)
+ {
+ ErrorF("%c", priv->packet[i++]);
+ }
+ ErrorF("\"\n");
+ return (Success);
+}
+
+
+/*****************************************************************************
+ * [cit_GetRevision]
+ ****************************************************************************/
+static Bool cit_GetRevision(cit_PrivatePtr priv, int selection)
+{
+ int i,n;
+ Bool res;
+
+ cit_Flush(priv->buffer);
+ cit_SendCommand(priv->buffer, C_GETREVISIONS, 1, (unsigned char)selection);
+ /*
+ touch responds within 1 millisecond,
+ but it takes some time, until the command is sent and received!
+ */
+ XisbBlockDuration(priv->buffer, 500000);
+ while (((res = cit_GetPacket(priv)) != Success) && (priv->lex_mode != cit_idle));
+ if (res != Success)
+ {
+ DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
+ return (!Success);
+ }
+ /* examine packet */
+ if (priv->packeti < 2)
+ {
+ DBG(5, ErrorF("%sWrong packet length (expected >= %d, received %d bytes)\n", CI_NOTICE,
+ 2, priv->packeti));
+ return (!Success);
+ }
+ if (priv->packet[0] != (C_GETREVISIONS & CMD_REP_CONV))
+ {
+ DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ (C_GETREVISIONS & CMD_REP_CONV), priv->packet[0]));
+ return (!Success);
+ }
+ if (priv->packet[1] != selection)
+ {
+ DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ selection, priv->packet[1]));
+ return (!Success);
+ }
+ /* this is our packet! check contents */
+ DBG(5, ErrorF("%s%s module revision ", CI_INFO,
+ selection == GR_SYSMGR ? "SysMgr " :
+ selection == GR_HARDWARE ? "Hardware" :
+ selection == GR_PROCESS ? "Process " :
+ selection == GR_PROTOCOL ? "Protocol" :
+ selection == GR_HWPARAM ? "HWParam " :
+ "???"));
+ i = 2;
+ n = 0;
+ DBG(5, ErrorF("\""));
+ while (n < priv->packeti && priv->packet[i]!=0)
+ {
+ DBG(5, ErrorF("%c", priv->packet[i]));
+ i++;
+ }
+ DBG(5, ErrorF("\"\n"));
+ return (Success);
+}
+
+
+/*****************************************************************************
+ * [cit_ProcessPacket]
+ ****************************************************************************/
+static void cit_ProcessPacket(cit_PrivatePtr priv)
+{
+ int i;
+
+ DBG(PP, ErrorF("%scit_ProcessPacket called\n", CI_INFO));
+ DBG(PP, ErrorF("%s\t+ enter state = 0x%04X, dual touch count=%d\n", CI_INFO, priv->state, priv->dual_touch_count));
+ /* examine message identifier */
+
+ priv->dual_flg = TRUE; /* Dual Touch Error occurred */
+#ifdef CIT_TIM
+ priv->timer_val1 = 1000; /* Timer delay [ms]*/
+ priv->timer_callback = (OsTimerCallback)cit_DualTouchTimer; /* timer callback routine */
+ cit_StartTimer(priv);
+#endif
+
+ switch (priv->packet[0])
+ {
+ case R_COORD: /* new touch coordinates received */
+ if (priv->packeti < 5)
+ {
+ DBG(PP, ErrorF("%s\t- coordinate message packet too short (%d bytes)\n", CI_ERROR, priv->packeti));
+ break;
+ }
+
+
+ if (priv->dual_touch_count > 0)
+ priv->dual_touch_count--;
+
+ priv->raw_x = 0x0001U * priv->packet[1]
+ + 0x0100U * priv->packet[2];
+ priv->raw_y = 0x0001U * priv->packet[3]
+ + 0x0100U * priv->packet[4];
+
+ priv->raw_min_x = min(priv->raw_min_x, priv->raw_x);
+ priv->raw_max_x = max(priv->raw_max_x, priv->raw_x);
+ priv->raw_min_y = min(priv->raw_min_y, priv->raw_y);
+ priv->raw_max_y = max(priv->raw_max_y, priv->raw_y);
+
+ priv->state |= CIT_TOUCHED;
+
+ DBG(PP, ErrorF("%s\t+ COORD message raw (%d,%d)\n", CI_INFO, priv->raw_x, priv->raw_y));
+ break;
+
+ case R_EXIT: /* touch area no longer interrupted */
+ if (priv->packeti < 5)
+ {
+ DBG(PP, ErrorF("%s\t- exit message packet too short (%d bytes)\n", CI_ERROR, priv->packeti));
+ break;
+ }
+
+ priv->state &= ~(CIT_TOUCHED | CIT_PRESSED);
+ priv->dual_touch_count = 0;
+ priv->raw_x = 0x0001U * priv->packet[1]
+ + 0x0100U * priv->packet[2];
+ priv->raw_y = 0x0001U * priv->packet[3]
+ + 0x0100U * priv->packet[4];
+#ifdef CIT_TIM
+ cit_CloseTimer(priv); /* close timer if exit message was received */
+#endif
+ DBG(PP, ErrorF("%s\t+ EXIT message (%d,%d)\n", CI_INFO, priv->raw_x, priv->raw_y));
+ break;
+
+ case R_DUALTOUCHERROR:
+ if (priv->dual_touch_count < priv->max_dual_count)
+ priv->dual_touch_count++;
+ DBG(PP, ErrorF("%s\t+ DUAL TOUCH ERROR message received\n", CI_INFO));
+ break;
+
+ case R_PRESSURE: /* pressure message received */
+ if (priv->packeti < 2)
+ {
+ DBG(PP, ErrorF("%s\t- pressure message packet too short (%d bytes)\n", CI_ERROR, priv->packeti));
+ break;
+ }
+ priv->state |= CIT_TOUCHED;
+ if (priv->packet[1] == PRESS_EXCEED)
+ priv->state |= CIT_PRESSED;
+ else if(priv->packet[1] == PRESS_BELOW)
+ {
+ priv->state &= ~CIT_PRESSED;
+ }
+ else
+ DBG(PP, ErrorF("%sPressure Message Error\n", CI_ERROR));
+
+ DBG(PP, ErrorF("%s\t+ pressure %s message\n", CI_INFO, priv->packet[1] ? "enter":"exit"));
+ break;
+
+ default:
+ DBG(PP, ErrorF("%s\t* unhandled message:", CI_ERROR));
+ for (i=0; i<priv->packeti; i++)
+ {
+ DBG(PP, ErrorF(" 0x%02X", priv->packet[i]));
+ }
+ DBG(PP, ErrorF("\n"));
+ }
+ /* generate button state */
+ switch (priv->click_mode)
+ {
+ case CM_ZPRESS:
+ DBG(PP, ErrorF("%s\t+ ZPress, button ", CI_INFO));
+ if (priv->state & CIT_PRESSED)
+ {
+ priv->state |= CIT_BUTTON;
+ DBG(PP, ErrorF("down"));
+ }
+ else
+ {
+ priv->state &= ~CIT_BUTTON;
+ DBG(PP, ErrorF("up"));
+ }
+
+ break;
+
+ case CM_ZPRESSEXIT:
+ DBG(PP, ErrorF("%s\t+ ZPressExit, button ", CI_INFO));
+ if (priv->state & CIT_PRESSED)
+ {
+ priv->state |= CIT_BUTTON;
+ DBG(PP, ErrorF("down"));
+ }
+ else if (!(priv->state & CIT_TOUCHED))
+ {
+ priv->state &= ~CIT_BUTTON;
+ DBG(PP, ErrorF("up"));
+ }
+ break;
+
+ case CM_DUAL:
+ DBG(PP, ErrorF("%s\t+ Dual Touch, button ", CI_INFO));
+ if ((priv->dual_touch_count == priv->max_dual_count) && (priv->state & CIT_TOUCHED))
+ {
+ priv->state |= CIT_BUTTON;
+ DBG(PP, ErrorF("down"));
+ }
+ else if (priv->dual_touch_count == 0)
+ {
+ priv->state &= ~CIT_BUTTON;
+ DBG(PP, ErrorF("up"));
+ }
+ break;
+
+ case CM_DUALEXIT:
+ DBG(PP, ErrorF("%s\t+ Dual Exit, button ", CI_INFO));
+ if ((priv->dual_touch_count == priv->max_dual_count) && (priv->state & CIT_TOUCHED))
+ {
+ priv->dual_flg = TRUE;
+ priv->state |= CIT_BUTTON;
+ DBG(PP, ErrorF("down"));
+ }
+ else if (!(priv->state & CIT_TOUCHED))
+ {
+ priv->state &= ~CIT_BUTTON;
+ DBG(PP, ErrorF("up"));
+ }
+ break;
+
+ default: /* default to enter mode */
+ DBG(PP, ErrorF("%s\t+ Enter Mode, button ", CI_INFO));
+ if (priv->state & CIT_TOUCHED)
+ {
+ priv->state |= CIT_BUTTON;
+ DBG(PP, ErrorF("down"));
+ }
+ else
+ {
+ priv->state &= ~CIT_BUTTON;
+ DBG(PP, ErrorF("up"));
+ }
+ break;
+ }
+ DBG(PP, ErrorF("\n"));
+ DBG(PP, ErrorF("%s\t+ Click Mode=%d\n", CI_INFO, priv->click_mode));
+ DBG(PP+1, ErrorF("%s\t+ exit state = 0x%04X, dual touch count=%d\n", CI_INFO, priv->state, priv->dual_touch_count));
+ DBG(PP+1, ErrorF("%s\t raw_x=%d, raw_y=%d\n", CI_INFO, priv->raw_x, priv->raw_y));
+}
+
+
+
+/*****************************************************************************
+ * [cit_GetPressureSensors]
+ ****************************************************************************/
+static Bool cit_GetPressureSensors(cit_PrivatePtr priv)
+{
+ int i;
+ Bool res;
+
+ cit_Flush(priv->buffer);
+ cit_SendCommand(priv->buffer, C_GETHARDWARE, 1, GH_SENSORCOUNT);
+ /*
+ touch responds within 1 millisecond,
+ but it takes some time, until the command is sent and received!
+ */
+ for (i=0; i<5; i++)
+ {
+ XisbBlockDuration(priv->buffer, 500000);
+ res = cit_GetPacket(priv);
+ if ((res == Success) || (priv->lex_mode == cit_idle));
+ break;
+ }
+ if (res != Success)
+ {
+ DBG(5, ErrorF("%sNo packet received!\n", CI_NOTICE));
+ return (!Success);
+ }
+ /* examine packet */
+ if (priv->packeti < 2+CTS_SENSORCOUNT_LEN)
+ {
+ DBG(5, ErrorF("%sWrong packet length (expected >= %d, received %d bytes)\n", CI_NOTICE,
+ 2+CTS_SENSORCOUNT_LEN,
+ priv->packeti));
+ return (!Success);
+ }
+ if (priv->packet[0] != (C_GETHARDWARE & CMD_REP_CONV))
+ {
+ DBG(5, ErrorF("%sWrong packet identifier (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ (C_GETHARDWARE & CMD_REP_CONV), priv->packet[0]));
+ return (!Success);
+ }
+ if (priv->packet[1] != GH_SENSORCOUNT)
+ {
+ DBG(5, ErrorF("%sWrong packet selector (expected 0x%02X, received 0x%02X)\n", CI_NOTICE,
+ GH_SENSORCOUNT, priv->packet[1]));
+ return (!Success);
+ }
+ /* this is our packet! check contents */
+ ErrorF("%sPressureSensors: \"%d\"\n", CI_INFO, priv->packet[2]);
+ priv->pressure_sensors = priv->packet[2];
+ return (Success);
+}
+
+
diff --git a/xc/programs/Xserver/hw/xfree86/input/citron/citron.cpp b/xc/programs/Xserver/hw/xfree86/input/citron/citron.cpp
new file mode 100644
index 000000000..444eae0dc
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/input/citron/citron.cpp
@@ -0,0 +1,631 @@
+.\" Copyright (c) 2000 Peter Kunzmann <support@@citron.de>
+.\"
+.\" This is free documentation; you can redistribute it and/or
+.\" modify it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2 of
+.\" the License, or (at your option) any later version.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" $XFree86: xc/programs/Xserver/hw/xfree86/input/citron/citron.cpp,v 1.1 2000/11/02 02:51:21 dawes Exp $
+.\"
+.TH CITRON 4 "Version 4.0.1" "XFREE86"
+.SH NAME
+citron \- Citron Infrared Touch Driver (CiTouch)
+.SH SYNOPSIS
+.B "Section ""InputDevice"""
+.br
+.BI " Identifier """ idevname """"
+.br
+.B " Driver ""citron"""
+.br
+.BI " Option ""Device"" """ devpath """"
+.br
+\ \ ...
+.br
+.B EndSection
+.SH DESCRIPTION
+.B citron
+is a XFree86 input driver for
+.I Citron Infrared Touch
+devices.
+.PP
+The
+.B citron
+driver acts as a pointer input device, and may be used as the
+X server's core pointer. It is connected via a "RS232" with the host.
+.SH SUPPORTED HARDWARE
+At the moment the following touches are supported. They are also
+available as
+.I ZPress
+touches.
+
+.B IRT6I5-V2.x
+ 6.5 inch Infrared Touch
+
+.B IRT10I4-V4.x
+ 10.4 inch Infrared Touch
+
+.B IRT12I1-V2.x
+ 12.1 inch Infrared Touch
+
+.B IRT15I1-V1.x
+ 15.1 inch Infrared Touch
+
+.SH CONFIGURATION DETAILS
+Please refer to XF86Config(5x) 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.
+For better understanding please read also the
+.B CTS
+and various
+.B IRT
+manuals which are available in "pdf" format from Citron web page
+.B www.citron.de
+or directly from Citron.
+
+.PP
+.PP
+The following driver
+.B Options
+are supported:
+.TP 7
+.BI "Option ""Device"" """ devpath """
+Specify the device path for the citron touch. Valid devices are:
+.PP
+.RS 12
+/dev/ttyS0, /dev/ttyS1, ....
+This option is mandatory.
+.RE
+.PP
+.RS 7
+It's important to specify the right device Note: com1 -> /dev/ttyS0, com2 -> /dev/ttyS1 ....
+
+.RE
+.TP 7
+.BI "Option ""ScreenNumber"" """ "screennumber" """
+sets the
+.I screennumber
+for the
+.I citron
+InputDevice.
+.PP
+.RS 7
+.I Default:
+ScreenNumber: "0"
+
+.RE
+.TP 7
+.BI "Option ""MinX, MinY"" """ value """
+These are the minimum X and Y values for the
+.I citron
+input device.
+.PP
+.RS 7
+Note: MinX, MinY must be less than MaxX, MaxY.
+.PP
+.I Range:
+"0" - "65535"
+.PP
+.I Default:
+MinX: "0" MinY: "0"
+
+
+.RE
+.TP 7
+.BI "Option ""MaxX, MaxY"" """ value """
+These are the maximum X and Y values for the
+.I citron
+input device.
+.PP
+.RS 7
+Note: MaxX, MaxY must be greater than MinX, MinY.
+.PP
+.I Range:
+"0" - "65535"
+.PP
+.I Default:
+MaxX: "65535" MaxY: "65535"
+
+
+.RE
+.TP 7
+.BI "Option ""ButtonNumber"" """ value """
+This value is responsible for the
+.I button number
+that is returned within the xf86PostButton event message
+.PP
+.RS 7
+.I Range:
+"0" - "255"
+.PP
+.I Default:
+"1"
+
+.RE
+.TP 7
+.BI "Option ""ButtonThreshold"" """ value """
+This value is responsible for the
+.I button threshold.
+It changes the pressure sensitivity of the touch. A higher number
+corresponds to a higher pressure.
+.PP
+.RS 7
+Note: This feature is only available with pressure sensitive hardware.
+.PP
+.I Range:
+"0" - "255"
+.PP
+.I Default:
+"20"
+
+.RE
+.TP 7
+.B Sleep-Mode
+If the IRT is in
+.I Doze-Mode
+and Touch Zone is not interrupted for another
+certain span of time, the so-called
+.I Sleep-Mode
+is activated. The
+.I Sleep-Mode
+decreases the scan rate of the beams even further than
+the
+.I Doze-Mode
+does (see below). This way the life expectancy of the beams is
+prolonged and the power consumption of the IRT is reduced.
+As soon as an interruption of the Touch Zone is detected, the
+.I Sleep-Mode
+is deactivated and the Touch Zone will again be scanned with
+the maximum speed. With the Sleep-Mode activated,
+depending on the set scan rate the IRT's response time can be
+considerably longer as in normal operation. If, for example,
+a scan rate of 500 ms / scan is set, it may last up to a half
+of a second until the IRT detects the interruption and deactivates
+the
+.I Sleep-Mode.
+
+.PP
+.RE
+.TP 7
+.BI "Option ""SleepMode"" """ mode """
+This value is responsible for the
+.I sleep-mode
+of the touch.
+.RS 7
+Determines the behaviour of the Sleep-Mode.
+
+.B 0x00
+ No message at either activation or deactivation
+
+.B 0x01
+ Message at activation
+
+.B 0x02
+ Message at deactivation
+
+.B 0x03
+ Message at activation and deactivation
+
+.B 0x10
+GP_OUT output set according to the Sleep-Mode status
+
+.I Values:
+"0" "1" "2" "3" "16"
+
+.I Default:
+"0"
+
+.RE
+.TP 7
+.BI "Option ""SleepTime"" """ time """
+This value is responsible for the
+.I sleep-time
+of the touch. It is the activation time in seconds
+("0" = immediately activated, "65535" = always deactivated).
+.RS 7
+.PP
+.I Range:
+"0" - "65535" [s]
+.PP
+.I Default:
+"65535" => deactivated
+
+.RE
+.TP 7
+.BI "Option ""SleepScan"" """ scan """
+This value is responsible for the
+.I scan-time
+of the touch. This is the time interval between two scan operations
+while in Sleep-Mode. The time interval is set in steps
+of milliseconds.
+.RS 7
+.PP
+.I Range:
+"0" - "65535" [ms]
+.PP
+.I Default:
+"500"
+
+.RE
+.TP 7
+.BI "Option ""PWMActive"" """ value """
+This value determines the mark-to-space ratio of the
+.I PWM
+output while in normal operation (sleep-mode not active).
+Higher values result in longer pulse widths. This output
+signal can be used in conjunction with the
+.I Citron AWBI
+to do backlight-dimming via the touch.
+.RS 7
+.PP
+.I Range:
+"0" - "255"
+.PP
+.I Default:
+"255" (max. brightness)
+
+
+.RE
+.TP 7
+.BI "Option ""PWMSleep"" """ value """
+This value determines the mark-to-space ratio of the
+.I PWM
+output while in sleep-mode (->
+.I SleepMode, SleepScan, SleepTime
+) operation (sleep-mode active).
+Higher values result in longer pulse widths.
+.RS 7
+.PP
+.I Range:
+"0" - "255"
+.PP
+.I Default:
+"255" (max. brightness)
+
+.RE
+.TP 7
+.BI "Option ""ClickMode"" """ mode """
+With mode one can select between 5
+.I ClickModes
+
+.I """1"" = ClickMode Enter
+
+With this mode every interruption of the infrared beams will
+activate a ButtonPress event and after the interruption a
+ButtonRelease event will be sent.
+
+.I """2"" = ClickMode Dual
+
+With this mode every interruption will sent a Proximity event and
+every second interruption a ButtonPress event. With the release of
+the interruption (while one interruption is still active) a
+ButtonRelease event will be sent.
+
+.I """3"" = ClickMode Dual Exit
+
+With this mode every interruption will sent a ProximityIn event and
+every second interruption a ButtonPress event. With the release of
+the interruption (while one interruption is still active) no
+ButtonRelease event will be sent. Only if all interruptions are released
+a ButtonRelease followed by a ProximityOut event will be sent.
+
+.I """4"" = ClickMode ZPress
+
+With this mode every interruption will sent a ProximityIn event. Only if
+a certain pressure is exceeded a ButtonPress event will occur. If the
+pressure falls below a certain limit a ButtonRelease event will be sent.
+After also the interruption is released a ProximityOut event is generated.
+
+.I """5"" = ClickMode ZPress Exit
+
+This mode is similat to "Clickmode Dual Exit".
+The first interruption of the beams will sent a ProximityIn event. Only if
+a certain pressure is exceeded a ButtonPress event will occur. If the
+pressure falls below a certain limit no ButtonRelease event will be sent.
+After the interruption is also released a ButtonRelease followed by
+a ProximityOut event is generated.
+.RS 7
+.PP
+.I Range:
+"1" - "5"
+.PP
+.I Default:
+"1" (ClickMode Enter)
+
+.RE
+.TP 7
+.BI "Option ""Origin"" """ value """
+This value sets the coordinates origin to one of the four corners of
+the screen.
+The following values are accepted:
+"0" TOPLEFT: Origin set to the left-hand side top corner.
+"1" TOPRIGHT: Origin set to the right-hand side top corner.
+"2" BOTTOMRIGHT: Origin set to the right-hand side bottom corner.
+"3" BOTTOMLEFT: Origin set to the left-hand side bottom corner.
+.RS 7
+.PP
+.I Range:
+"0" - "3"
+.PP
+.I Default:
+"0" (TOPLEFT)
+
+.RE
+.TP 7
+.B "Doze-Mode"
+If for a certain span of time the Touch Zone is not interrupted,
+the so-called Doze-Mode is automatically activated. The activated
+Doze-Mode slightly decreases the scan rate of the beams. This way
+the power consumption of the IRT is reduced. As soon as an
+interruption of the Touch Zone is detected, the Doze-Mode
+is deactivated and the Touch Zone will again be scanned with
+the maximum speed.
+
+.RE
+.TP 7
+.BI "Option ""DozeMode"" """ mode """
+This value is responsible for the
+.I doze-mode
+of the touch.
+.RS 7
+.PP
+Determines the behaviour of the Doze-Mode.
+.PP
+0x00 No message at either activation or deactivation
+
+0x01 Message at activation
+
+0x02 Message at deactivation
+
+0x03 Message at activation and deactivation
+
+0x10 GP_OUT output set according to the Doze-Mode status
+
+If the GP_OUT output is already controlled by the
+.I Sleep-Mode
+it is no longer available as an output port anymore.
+.PP
+.I Values:
+"0" "1" "2" "3" "16"
+.PP
+.I Default:
+"0"
+
+
+
+.RE
+.TP 7
+.BI "Option ""DozeTime"" """ time """
+This value is responsible for the
+.I doze-time
+of the touch. It is the activation time in seconds
+("0" = immediately activated, "65535" = always deactivated).
+.RS 7
+.PP
+.I Range:
+"0" - "65535" [s]
+.PP
+.I Default:
+"65535" => deactivated
+
+
+.RE
+.TP 7
+.BI "Option ""DozeScan"" """ scan """
+This value is responsible for the
+.I scan-time
+of the touch. This is the time interval between two scan operations
+while in Doze-Mode. The time interval is set in steps
+of milliseconds.
+.RS 7
+.PP
+.I Range:
+"0" - "65535" [ms]
+.PP
+.I Default:
+"500"
+
+.RE
+.TP 7
+.BI "Option ""DeltaX"" """ value """
+This value determines a virtual area at the left and right
+side of the current cursor position where the cursor didn't move.
+Within this area no "MotionNotify" event will be sent.
+.RS 7
+.PP
+.I Range:
+"0" - "255"
+.PP
+.I Default:
+"0" (no deltaX)
+
+
+.RE
+.TP 7
+.BI "Option ""DeltaY"" """ value """
+This value determines a virtual area at the top and bottom
+of the current cursor position where the cursor didn't move.
+Within this area no "MotionNotify" event will be sent.
+.RS 7
+.PP
+.I Range:
+"0" - "255"
+.PP
+.I Default:
+"0" (no deltaY)
+
+.RE
+.TP 7
+.BI "Option ""Beep"" """ value """
+This value determines if a "ButtonPress" and/or a "ButtonRelease"
+event should sound the buzzer. "0" deactivates the buzzer while
+every other value will activate it.
+.RS 7
+.PP
+.I Range:
+"0" - "1"
+.PP
+.I Default:
+"0" (deactivated)
+
+.RE
+.TP 7
+.BI "Option ""PressVol"" """ value """
+This value determines the volume of the buzzer (0-100%)
+when a "ButtonPress" event is sent.
+.RS 7
+.PP
+.I Range:
+"0" - "100"
+.PP
+.I Default:
+"100"
+
+
+.RE
+.TP 7
+.BI "Option ""PressPitch"" """ value """
+This value determines the pitch of the tone
+when a "ButtonPress" event is sent.
+.RS 7
+.PP
+.I Range:
+"0" - "3000"
+.PP
+.I Default:
+"880"
+
+
+
+.RE
+.TP 7
+.BI "Option ""PressDur"" """ value """
+This value determines the duration of the tone in ms
+when a "ButtonPress" event is sent.
+.RS 7
+.PP
+.I Range:
+"0" - "255"
+.PP
+.I Default:
+"15"
+
+.RE
+.TP 7
+.BI "Option ""ReleaseVol"" """ value """
+This value determines the volume of the buzzer (0-100%)
+when a "ButtonRelease" event is sent.
+.RS 7
+.PP
+.I Range:
+"0" - "100"
+.PP
+.I Default:
+"100"
+
+
+.RE
+.TP 7
+.BI "Option ""ReleasePitch"" """ value """
+This value determines the pitch of the tone when
+when a "ButtonRelease" event is sent.
+.RS 7
+.PP
+.I Range:
+"0" - "3000"
+.PP
+.I Default:
+"1200"
+
+
+
+.RE
+.TP 7
+.BI "Option ""ReleseDur"" """ value """
+This value determines the duration of the tone in ms when
+when a "ButtonRelease" event is sent.
+.RS 7
+.PP
+.I Range:
+"0" - "255"
+.PP
+.I Default:
+"10"
+
+
+
+.RE
+.TP 7
+.BI "Option ""BeamTimeout"" """ value """
+Determines the time span in seconds, that has to elapse before a beam is
+considered defective, blanked-out and excluded from the coordinates
+evaluation.
+.RS 7
+.PP
+.I Range:
+"0" - "65535"
+.PP
+.I Default:
+"30" (30 seconds)
+
+
+
+
+.RE
+.TP 7
+.BI "Option ""TouchTime"" """ value """
+Determines the minimum time span in steps of 10ms for a valid
+interruption. In order for an interruption to be
+reported to the host computer as valid, it needs to remain at
+the same spot for at least the time span declared here.
+.RS 7
+.PP
+.I Range:
+"0" - "255"
+.PP
+.I Default:
+"0" (=6,5 ms)
+
+
+.RE
+.TP 7
+.BI "Option ""EnterCount"" """ count """
+Number of skipped "enter reports". Reports are sent approx.
+every 20ms.
+.RS 7
+.PP
+.I Range:
+"0" - "31"
+.PP
+.I Default:
+"3" (3 skipped messages = 60ms)
+
+
+.RE
+.TP 7
+.BI "Option ""DualCount"" """ count """
+Number of skipped "dual touch error". Reports are sent approx.
+every 20ms. This option is only available for "ZPress" and
+"ZPress Exit" modes.
+.RS 7
+.PP
+.I Range:
+"0" - "31"
+.PP
+.I Default:
+"2" (2 skipped messages = 40ms)
+
+
+.SH "SEE ALSO"
+XFree86(1), XF86Config(5x), xf86config(1), Xserver(1), X(1).
+.SH AUTHORS
+2000 - written by Citron GmbH (support@citron.de)
diff --git a/xc/programs/Xserver/hw/xfree86/input/citron/citron.h b/xc/programs/Xserver/hw/xfree86/input/citron/citron.h
new file mode 100644
index 000000000..b43d45ce6
--- /dev/null
+++ b/xc/programs/Xserver/hw/xfree86/input/citron/citron.h
@@ -0,0 +1,522 @@
+/*
+ * 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/citron/citron.h,v 1.1 2000/11/02 02:51:21 dawes Exp $ */
+
+/*
+ * Based, in part, on code with the following copyright notice:
+ *
+ * Copyright 1999-2000 by Thomas Thanner, Citron GmbH, Germany. <support@citron.de>
+ *
+ * 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 Thomas Thanner and Citron GmbH not be used in advertising or
+ * publicity pertaining to distribution of the software without specific, written
+ * prior permission. Thomas Thanner and Citron GmbH makes no representations about
+ * the suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * THOMAS THANNER AND CITRON GMBH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL THOMAS THANNER OR CITRON GMBH 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.
+ *
+ */
+
+#ifndef _citron_H_
+#define _citron_H_
+
+/******************************************************************************
+ * Definitions
+ * structs, typedefs, #defines, enums
+ *****************************************************************************/
+
+/* CTS (Citron Touch Software) protocol constants */
+#define CTS_CTRLMIN 0x10 /* Lower end of the control character range */
+#define CTS_XON 0x11 /* Start serial transmission character */
+#define CTS_STX 0x12 /* Start of message delimiter */
+#define CTS_XOFF 0x13 /* Stop serial transmission character */
+#define CTS_ETX 0x14 /* End of message delimiter */
+#define CTS_NAK 0x15 /* Not Acknowledge, send by the IRT just before it resets itself */
+#define CTS_ESC 0x16 /* Escape character to encode non control characters with a value inside the control character range */
+#define CTS_CTRLMAX 0x16 /* Upper end of the control character range */
+
+#define CTS_ENCODE 0x40 /* Use this constant to encode non control character with a value inside the control character range */
+#define CTS_DECODE (~0x40) /* Use this constant to decode previously encoded characters. These characters are marked by a leading CTS_ESC. */
+
+#define CTS_MSG_MIN 0x18 /* First usable character for message and report identifiers */
+#define CTS_MSG_MAX 0x7F /* Last usable character for message and report identifiers */
+
+#define CTS_DESIGNATOR_LEN 32 /* Length of the designator part in the HardwareRevision report */
+#define CTS_ASSY_LEN 16 /* Length of the ASSY part in the HardwareRevision report */
+#define CTS_OEMSTRING_LEN 256 /* Length of the OEM string */
+#define CTS_FPGA_LEN 28 /* Length of the FPGA version string */
+#define CTS_SENSORCOUNT_LEN 1 /* Length of sensorcount report */
+
+#define CTS_MAX_HWASSY 32 /* Maximum number of hardware codeable assy numbers */
+
+#define CTS_MAX_POLYEDGE 64 /* Maximum number of polygonal area edges */
+
+#define CMD_REP_CONV 0x7f /* Use this bit mask to convert a command into a report identifier */
+
+#define CTS_PACKET_SIZE (1+CTS_OEMSTRING_LEN)
+
+/* Area operating modes */
+#define AOM_OFF 0x00 /* No coordinate messages will be generated by this area */
+#define AOM_ENTER 0x01 /* Only the area entry point will be reported in a coordinate message */
+#define AOM_TRACK 0x02 /* Every movement inside the area will be reported in a coordinate message */
+#define AOM_CONT 0x03 /* If the area is touched, coordinate messages will be created in fixed time intervals */
+
+/* Modification flags for the area operating mode */
+#define AOF_ADDEXIT 0x01 /* Exit messages will be generated for this area */
+#define AOF_ADDCOORD 0x02 /* The coordinate of the touch point will be reported in addition to the area number */
+#define AOF_ADDPRESS 0x04 /* Pressure messages will be generated for this area */
+#define AOF_PRESSALWAYS 0x08 /* This area requires a permanent pressure to generate coordinate messages */
+#define AOF_PRESSENTER 0x10 /* This area requires only pressure to generate the first coordinate message. */
+#define AOF_PRESSLOCAL 0x20 /* This area has a locally defined pressure sensitivity, If this flag is not set, the pressure sensivity of area0 is used. */
+#define AOF_EXTENDED 0x40 /* This area must be leaved, before any other area will generate coordinate messages */
+#define AOF_ACTIVE 0x80 /* This area is active. Only active areas will generate messages. */
+
+/* group ClearArea command parameter values */
+#define CA_ALL 0x00 /* Clear all areas on all pages */
+#define CA_PAGE 0x01 /* Clear all areas of a certain page */
+#define CA_AREA 0x02 /* Clear a single area, however area0 cannot be cleared. area0 will only be reset to its power up default state. */
+
+/* SetTransmission command parameter values */
+#define TM_TRANSMIT 0x01 /* Enable the transmission of messages (report will be transmitted always) */
+#define TM_NONE 0x00 /* Disable transmission of messages and disable the XON/XOFF protocol */
+#define TM_RXDFLOW 0x10 /* Enable the XON/XOFF protocol for the transmitter (IRT will send XON/XOFF to the host) */
+#define TM_TXDFLOW 0x20 /* Enable the XON/XOFF protocol for the receiver (host will sned XON/XOFF to the IRT) */
+
+/* Sleep- and Doze-Mode command parameters */
+#define TS_QUIET 0x00 /* Disable the generation of TouchSaver messages */
+#define TS_ACTIMSG 0x01 /* Enable the generation of messages on sleep- or doze-mode activation */
+#define TS_PASIMSG 0x02 /* Enable the generation of messages on sleep- or doze-mode deactivation */
+#define TS_SETOUT 0x10 /* The /GP_OUT output of the IRT will reflect the sleep- or doze-mode state, if this flag is set. */
+#define TS_ACTIVE 0x80 /* This is a read only flag to decode the current sleep- or doze-mode state in SleepModeState and DozeModeState reports. */
+
+/* SetDualTouching command parameters */
+#define DT_IGNORE 0x00 /* Multiple touches are ignored, no DualTouchError messages will be generated */
+#define DT_ERROR 0x01 /* Multiple touches will be reported by a DualTouchError message */
+#define DT_COORD 0x02 /* The coordinate of the second touch point will be reported in a separate coordinate message. More than 2 touch points will be reported by DualTouchError messages. */
+
+/* SetOrigin command parameters */
+#define OR_TOPLEFT 0x00 /* The coordinate origin is in the top left corner of the touch */
+#define OR_TOPRIGHT 0x01 /* The coordinate origin is in the top right corner of the touch */
+#define OR_BOTTOMRIGHT 0x02 /* The coordinate origin is in the bottom right corner of the touch */
+#define OR_BOTTOMLEFT 0x03 /* The coordinate origin is in the bottom left corner of the touch */
+
+/* GetSignalValues command parameters */
+#define GS_NOREPORT 0x00 /* Don't report the signal values */
+#define GS_SIGNAL 0x01 /* Report the beam values as used for coordinate generation */
+#define GS_REFERENCE 0x02 /* Report the reference beam values */
+#define GS_BROKEN 0x03 /* Report the results of the broken/not broken beam detection */
+#define GS_RESCAN 0x80 /* Add this flag to rescan the touch before generating the SignalValues report */
+
+/* GetPressureValues command parameters */
+#define GP_NOREPORT 0x00 /* Don't report the pressure values */
+#define GP_SIGNAL 0x01 /* Report the signals of the active pressure sensors */
+#define GP_REFERENCE 0x02 /* Report the signals of the calibration sensors */
+#define GP_INTERNAL 0x04 /* Report the internal state of the pressure sensitive unit */
+
+/* SetPort/GetPort command parameters */
+#define GP_OCOUT0 0x01 /* Get/Set the /OC_OUT0 port of the IRT */
+#define GP_BIJMP 0x02 /* Get the state of the BurnIn jumper on the IRT */
+#define GP_OCSSAVER 0x04 /* Get/Set the /OC_SSAVER port of the IRT */
+#define GP_OCIN0 0x08 /* Get the state of the /OC_IN0 port of the IRT */
+
+/* GetRevisions command parameters */
+#define GR_SYSMGR 0x01 /* Get the version number of the System Manager module */
+#define GR_HARDWARE 0x02 /* Get the version number of the Hardware module */
+#define GR_PROCESS 0x04 /* Get the version number of the Process module */
+#define GR_PROTOCOL 0x08 /* Get the version number of the Protocol module */
+#define GR_HWPARAM 0x10 /* Get the version number of the Hardware Parameters module */
+#define GR_DESIGNATOR 0x20 /* Get the IRT designator and ASSY number */
+#define GR_BURNIN 0x40 /* Get the version number of the Burn-In module */
+#define GR_FPGA 0x80 /* Get the version number of the FPGA module */
+
+/* GetErrors command parameters */
+#define GE_INITIAL 0x01 /* Report the errors detected during IRT startup */
+#define GE_DEFECTBEAMS 0x02 /* Report the beams that are marked defect and are therefore excluded from the coordinate calculations */
+#define GE_COMMUNICATION 0x04 /* Report communication errors on the serial link */
+#define GE_COMMAND 0x08 /* Report command errors (invalid parameters, unknown commands, ...) */
+#define GE_CLEAR 0x80 /* Add this flag to clear the errors after reporting */
+
+/* GetHardware command parameters */
+#define GH_BEAMCOUNT 0x01 /* Report the number of x and y beams */
+#define GH_SENSORCOUNT 0x02 /* Report the number of pressure sensors */
+#define GH_PERIPHERALS 0x04 /* Report a bit vector that identifies all assembled peripherals on the IRT */
+
+/* GetHWVersion command parameters */
+#define HV_SSNO 0x01 /* Report the silicon serial number */
+#define HV_ASSY 0x02 /* Report the hard wired assembly number */
+#define HV_FPGA 0x04 /* Report the FPGA version string */
+
+/* InitialError decoding bit masks */
+#define IE_SMCHKSUM 0x00000001UL /* The system manager module has a checksum error */
+#define IE_SMINIT 0x00000002UL /* The system manager module reported an error during initialisation */
+#define IE_HWCHKSUM 0x00000004UL /* The hardware module has a checksum error */
+#define IE_HWINIT 0x00000008UL /* The hardware module reported an error during initialisation */
+#define IE_PCCHKSUM 0x00000010UL /* The process module has a checksum error */
+#define IE_PCINIT 0x00000020UL /* The process module reported an error during initialisation */
+#define IE_PTCHKSUM 0x00000040UL /* The protocol module has a checksum error */
+#define IE_PTINIT 0x00000080UL /* The protocol module reported an error during initialisation */
+#define IE_HW_BEAMS 0x00000100UL /* There were broken beams during hardware initialisation */
+#define IE_HW_PSU 0x00000200UL /* There pressure sensitive unit could not be initialised */
+#define IE_HW_CPU 0x00000400UL /* There was an error in the CPU core detected during startup */
+#define IE_HW_IRAM 0x00000800UL /* There was an error in the initial internal ram check */
+#define IE_HW_XRAM 0x00001000UL /* There was an error in the initial external ram check */
+#define IE_BICHK 0x00002000UL /* The burnin module has a checksum error */
+#define IE_BIINIT 0x00004000UL /* The burnin module reported an error during initialisation */
+#define IE_FPGACHK 0x00008000UL /* The fpga module has a checksum error */
+#define IE_HWPCHK 0x00010000UL /* The hardware parameter module has a checksum error */
+
+/* CommunicationError decoding bit masks */
+#define CE_DC2GTDC4 0x00000001UL /* There were more CTS_STX received than CTS_ETX */
+#define CE_DC4GTDC2 0x00000002UL /* There were more CTS_ETX received than CTS_STX */
+#define CE_UNXNONCTRL 0x00000004UL /* Non control character received outside a CTS_STX/CTS_ETX sequence */
+#define CE_UNXCONTROL 0x00000008UL /* Unexpected control character received */
+#define CE_OVERFLOW 0x00000010UL /* The hardware receiver buffer had an overflow */
+#define CE_FRAMING 0x00000020UL /* There were characters with framing errors received */
+#define CE_PARITY 0x00000040UL /* There were characters with invalid parity received */
+#define CE_XOFFTO 0x00000080UL /* No XON was received within the defined timeout after a XOFF */
+#define CE_CMDOVER 0x00000100UL /* The command buffer had an overflow */
+#define CE_RCVROVER 0x00000200UL /* The receiver ring buffer had an overflow */
+
+/* CommandError decoding bit masks */
+#define CE_UNKNOWN 0x00000001UL /* Unknown command received */
+#define CE_PARAMCNT 0x00000002UL /* Too much or too less parameters received */
+#define CE_RANGE 0x00000004UL /* One or more parameters were out of range */
+
+/* Peripheral indentification bit masks */
+#define PERI_OCOUT0 0x00000001UL /* The /OC_OUT0 port is available */
+#define PERI_BURNIN 0x00000002UL /* The BurnIn jumper is available */
+#define PERI_GP_OUT 0x00000004UL /* The /GP_OUT port is available */
+#define PERI_OCPWM 0x00000008UL /* The /OC_PWM port is available */
+#define PERI_SPEAKER 0x00000010UL /* The speaker port is available */
+#define PERI_GP_IN 0x00000020UL /* The /GP_IN port is available */
+#define PERI_RUNLED 0x00000040UL /* The red blinking indication LED is available */
+
+/* SaveSetup/ReadSetup command parameters */
+#define SUP_SERIAL 0x01 /* Save/Read the serial port setup */
+#define SUP_MACRO 0x02 /* Save/Read the macro definitions */
+#define SUP_AREAS 0x04 /* Save/Read the area definitions */
+#define SUP_PERI 0x08 /* Save/Read the peripheral settings */
+#define SUP_COORD 0x10 /* Save/Read the coordinate settings */
+
+/* IRT initialisation modes for <f cts_Connect> */
+
+#define MODE_A 0x7b /* Initialise the IRT to AFE-Mode A emulation */
+#define MODE_B 0x3c /* Initialise the IRT to Carroll emulation */
+#define MODE_C 0x6f /* Another entry point for Mode-D (for backwards compatibility) */
+#define MODE_D 0x81 /* Initialise the IRT to the CTS protocol */
+
+/* Command is for the driver */
+#define DRIVCOMM 0x00 /* Command for driver */
+
+/* Command Identifiers for the driver */
+#define D_SETCLICKMODE 0x00
+#define D_BEEP 0x01
+#define D_SETBEEP 0x02
+
+
+/* Message identifiers */
+#define R_DUALTOUCHERROR 0x18 /* Invalid multiple touches are detected */
+#define R_COORD 0x19 /* Regular coordinate report */
+#define R_EXIT 0x1a /* An area was leaved */
+#define R_PRESSURE 0x1b /* An area was pressed or released */
+#define PRESS_BELOW 0x00 /* Pressure below a certain threshold */
+#define PRESS_EXCEED 0x01 /* Pressure higher than a certain threshold */
+
+#define R_SLEEPMODE 0x1c /* The sleep-mode was activated or deactivated */
+#define R_DOZEMODE 0x1d /* The doze-mode was activated or deactivated */
+
+/* Special report identifiers */
+#define R_POLYAREADEF 0x2a
+#define R_IDLE 0x34
+#define R_SCANTIMING 0x56
+
+/* Command identifiers */
+#define C_SOFTRESET 0x80
+#define C_RESETCTS 0x81
+#define C_SAVESETUP 0x83
+#define C_DESTROYSETUP 0x84
+#define C_SETSCANTIMING 0x85
+#define C_GETSCANTIMING 0x86
+
+#define C_CLEARAREA 0xa0
+#define C_DEFINEAREA 0xa1
+#define C_GETAREADEF 0xa2
+#define C_GETAREAPAGE 0xa3
+#define C_GETFREEAREASPACE 0xa4
+#define C_SELECTAREAPAGE 0xa5
+#define C_SETAREASTATE 0xa6
+#define C_SETAREAMODE 0xa7
+#define C_SETAREAFLAGS 0xa8
+#define C_SETAREAPRESSURE 0xa9
+#define C_DEFINEPOLYAREA 0xaa
+
+#define C_GETERRORS 0xb0
+#define C_GETHARDWARE 0xb1
+#define C_GETREVISIONS 0xb2
+#define C_GETSETUP 0xb3
+#define C_GETSINGLEMESSAGE 0xb4
+#define C_GETSINGLESCAN 0xb5
+#define C_GETSIGNALVALUES 0xb6
+#define C_GETPRESSUREVALUES 0xb7
+#define C_GETOEMSTRING 0xb8
+#define C_GETHWVERSIONS 0xb9
+#define C_BIGETFIRSTSESSION 0xba
+#define C_BIGETNEXTSESSION 0xbb
+#define C_BIGETRECORD 0xbc
+#define C_BIERASEDATA 0xbd
+#define C_BIGETTICKUNIT 0xbe
+
+#define C_GETBEAMMINMAX 0xc0
+#define C_GETBEAMTIMEOUT 0xc1
+#define C_GETCONTTIME 0xc2
+#define C_GETDUALTOUCHING 0xc3
+#define C_GETORIGIN 0xc4
+#define C_GETRESOLUTION 0xc5
+#define C_GETSCANNING 0xc6
+#define C_GETTRANSMISSION 0xc7
+#define C_SETBEAMMINMAX 0xc8
+#define C_SETBEAMTIMEOUT 0xc9
+#define C_SETCONTTIME 0xca
+#define C_SETDUALTOUCHING 0xcb
+#define C_SETORIGIN 0xcc
+#define C_SETRESOLUTION 0xcd
+#define C_SETSCANNING 0xce
+#define C_SETTRANSMISSION 0xcf
+
+#define C_GETTOUCHTIME 0xd0
+#define C_SETTOUCHTIME 0xd1
+
+#define C_CLEARMACRO 0xe0
+#define C_ENDMACRORECORD 0xe1
+#define C_EXECMACRO 0xe2
+#define C_GETFREEMACROSPACE 0xe3
+#define C_STARTMACRORECORD 0xe5
+
+#define C_GETPORT 0xf0
+#define C_GETPWM 0xf1
+#define C_GETSOUND 0xf2
+#define C_GETSLEEPMODE 0xf3
+#define C_SETPORT 0xf4
+#define C_SETPWM 0xf5
+#define C_SETSOUND 0xf6
+#define C_SETSLEEPMODE 0xf7
+#define C_GETDOZEMODE 0xf8
+#define C_SETDOZEMODE 0xf9
+
+/* touch states */
+#define CIT_TOUCHED 0x01
+#define CIT_PRESSED 0x02
+#define CIT_BUTTON 0x04
+
+/* click modes */
+#define CM_ENTER 1
+#define CM_DUAL 2
+#define CM_DUALEXIT 3
+#define CM_ZPRESS 4
+#define CM_ZPRESSEXIT 5
+
+#define MAX_DUAL_TOUCH_COUNT 2
+
+#define NO_CLICK_MODE 255 /* no click mode set in xf86Config */
+
+/* command structure for Feedback Functions */
+typedef struct {
+ unsigned char par[3]; /* byte parameter */
+ char packet; /* packet number 00 - 7F */
+} COMMAND;
+
+
+/* Data exchange with driver (Driver Data Structure) */
+#define MAX_BYTES_TO_TRANSFER 0x20
+#define LAST_PACKET 0x7f
+
+typedef struct {
+ short curbyte; /* current byte number */
+ short numbytes; /* number of bytes to transmit */
+ short packet; /* packet number */
+ unsigned char data[MAX_BYTES_TO_TRANSFER]; /* pointer to data area */
+} CitronDDS;
+
+
+
+
+/*****************************************************************************
+ * X-Header
+ ****************************************************************************/
+
+#define X_CITOUCH " CiTouch: "
+const char *CI_PROBED = {"(--)" X_CITOUCH}; /* Value was probed */
+const char *CI_CONFIG = {"(**)" X_CITOUCH}; /* Value was given in the config file */
+const char *CI_DEFAULT = {"(==)" X_CITOUCH}; /* Value is a default */
+const char *CI_CMDLINE = {"(++)" X_CITOUCH}; /* Value was given on the command line */
+const char *CI_NOTICE = {"(!!)" X_CITOUCH}; /* Notice */
+const char *CI_INFO = {"(II)" X_CITOUCH}; /* Informational message */
+const char *CI_WARNING = {"(WW)" X_CITOUCH}; /* Warning message */
+const char *CI_ERROR = {"(EE)" X_CITOUCH}; /* Error message */
+const char *CI_UNKNOWN = {"(?\?)" X_CITOUCH}; /* Unknown message */
+
+
+
+/*****************************************************************************
+ * macros
+ ****************************************************************************/
+#define millisleep(ms) xf86usleep((ms) * 1000)
+
+#define HIBYTE(x) ( (unsigned char) ( (x) >> 8 ) )
+#define LOBYTE(x) ( (unsigned char) ( (x) & 0xff ) )
+
+
+/*****************************************************************************
+ * typedefs
+ ****************************************************************************/
+typedef enum
+{
+ cit_idle, cit_getID, cit_collect, cit_escape
+}
+cit_State; /* Citron Infrared Touch Driver State */
+
+typedef struct _cit_privateRec
+{
+ 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 */
+ int button_threshold; /* Z > button threshold = button click */
+ int axes;
+ int dual_touch_count; /* counter for dual touch error events */
+ int click_mode; /* one of the CM_ constants */
+ 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 packeti; /* index into packet */
+ int raw_x; /* Raw Coordinates */
+ int raw_y;
+ int sleep_mode; /* sleep mode: 0x00=no message, 0x01=m at activation, 0x02=m at deactivation, */
+ /* 0x03= message at act. + deact., 0x10= GP_OUT set */
+ int sleep_time_act; /* time until touchsaver gets activate */
+ int sleep_time_scan; /* time interval between two scans */
+ int pwm_sleep; /* PWM duty cycle during touch saver mode */
+ int pwm_active; /* PWM duty cycle during regular operation */
+ int state;
+/* additional parameters */
+ int last_x; /* last cooked data */
+ int last_y;
+ int doze_mode; /* doze mode: 0x00=no message, 0x01=m at activation, 0x02=m at deactivation, */
+ /* 0x03= message at act. + deact., 0x10= GP_OUT set */
+ int doze_time_act; /* time until touchsaver gets activate */
+ int doze_time_scan; /* time interval between scans */
+ int origin; /* Coordinates origin */
+ int delta_x; /* Delta x - if coordinate changed less than delta x no motion event */
+ int delta_y;
+ int beep; /* 0= no beep, 1=beep enabled */
+ int press_vol; /* volume of beep (press event) */
+ int press_pitch; /* pitch of beep (press event) */
+ int press_dur; /* length of beep in 10ms (press event) */
+ int rel_vol; /* volume of beep (release event) */
+ int rel_pitch; /* pitch of beep (release event) */
+ int rel_dur; /* length of beep in 10ms (release event) */
+ int beam_timeout; /* Beam timeout 0= no beam timeout */
+ int touch_time; /* minimum time span for a valid interruption */
+ int enter_touched; /* button is down due to an enter event */
+ int enter_count; /* number of jumed coord reports before a ButtonPress event is sent */
+ int max_dual_count; /* number of jumed dualtouch error reports before a ButtonPress event is sent */
+ int dual_flg; /* Flag set if dualtouch error report is received , reset by counter */
+ int raw_min_x; /* min x,y max x,y value accumulated over the whole session */
+ int query_state; /* test if query was already started */
+ int raw_max_x;
+ int raw_min_y;
+ int raw_max_y;
+ int pressure_sensors; /* number of pressure sensors */
+ OsTimerPtr timer_ptr; /* Timer for general purposes */
+ CARD32 timer_val1; /* Timer 1st delay */
+ CARD32 timer_val2; /* Timer second delay */
+ OsTimerCallback timer_callback; /* timer callback routine */
+ int fake_exit; /* tell the ReadInput function there is a exit message (from timer) */
+/* end additional parameters */
+ LocalDevicePtr local; /* Pointer to local device */
+ Bool button_down; /* is the "button" currently down */
+ Bool proximity;
+ cit_State lex_mode;
+ XISBuffer *buffer;
+ unsigned char packet[CTS_PACKET_SIZE]; /* packet being/just read */
+ CitronDDS dds; /* Structure for Byte transfer to the driver via LedFeedbackControl */
+}
+cit_PrivateRec, *cit_PrivatePtr;
+
+/******************************************************************************
+ * Declarations
+ *****************************************************************************/
+/*extern void ModuleInit (pointer *, INT32 *);*/
+static MODULESETUPPROTO (SetupProc);
+static void TearDownProc (pointer p);
+/*static void *SetupProc (XF86OptionPtr, int *, int *);*/
+static Bool DeviceControl (DeviceIntPtr def, int mode);
+static Bool DeviceOn (DeviceIntPtr);
+static Bool DeviceOff (DeviceIntPtr);
+static Bool DeviceClose (DeviceIntPtr);
+static Bool DeviceInit (DeviceIntPtr);
+static void ReadInput (LocalDevicePtr);
+static int ControlProc (LocalDevicePtr, xDeviceCtl *);
+static void CloseProc (LocalDevicePtr);
+static int SwitchMode (ClientPtr, DeviceIntPtr, int);
+static Bool ConvertProc (LocalDevicePtr, int, int, int, int, int, int, int, int, int *, int *);
+static Bool QueryHardware (LocalDevicePtr, int *, int *);
+static Bool cit_GetPacket (cit_PrivatePtr);
+static void cit_Flush(XISBuffer *);
+static void cit_SendCommand(XISBuffer *, unsigned char, int, ...);
+static Bool cit_GetInitialErrors(cit_PrivatePtr);
+static Bool cit_GetDefectiveBeams(cit_PrivatePtr);
+static Bool cit_GetDesignator(cit_PrivatePtr);
+static Bool cit_GetPressureSensors(cit_PrivatePtr);
+static Bool cit_GetRevision(cit_PrivatePtr, int);
+static void cit_ProcessPacket(cit_PrivatePtr);
+static void cit_Beep(cit_PrivatePtr priv, int press);
+#ifdef CIT_TIM
+static void cit_StartTimer(cit_PrivatePtr priv);
+static void cit_CloseTimer(cit_PrivatePtr priv);
+static CARD32 cit_DualTouchTimer(OsTimerPtr timer, CARD32 now, pointer arg);
+#endif
+
+
+
+/*
+ * DO NOT PUT ANYTHING AFTER THIS ENDIF
+ */
+#endif