diff options
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/input/citron')
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/input/citron/Imakefile | 31 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/input/citron/citron.c | 2421 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/input/citron/citron.cpp | 631 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/input/citron/citron.h | 522 |
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 |