summaryrefslogtreecommitdiff
path: root/driver/xf86-input-digitaledge/src/DigitalEdge.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/xf86-input-digitaledge/src/DigitalEdge.c')
-rw-r--r--driver/xf86-input-digitaledge/src/DigitalEdge.c1427
1 files changed, 1427 insertions, 0 deletions
diff --git a/driver/xf86-input-digitaledge/src/DigitalEdge.c b/driver/xf86-input-digitaledge/src/DigitalEdge.c
new file mode 100644
index 000000000..5dee41ba2
--- /dev/null
+++ b/driver/xf86-input-digitaledge/src/DigitalEdge.c
@@ -0,0 +1,1427 @@
+/*
+ * Copyright 1996 by Steven Lang <tiger@tyger.org>
+ *
+ * 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 Steven Lang not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. Steven Lang makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * STEVEN LANG DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL STEVEN LANG 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 ACTIONS, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Steve Harris <steve@totl.net>, 2000-02-23
+ * Southampton, UK
+ *
+ * Based on the xf86Summa driver, exensively hacked. Most of the bad
+ * indenting is not my fault, dammit!
+ *
+ * Probably buggy as hell, no idea what the initialisation strings are,
+ * no idea how to ack it. If the tablet stops responding power cycle it.
+ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/input/digitaledge/DigitalEdge.c,v 1.8 2003/09/24 03:16:58 dawes Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86Version.h"
+
+#if XF86_VERSION_CURRENT >= XF86_VERSION_NUMERIC(3,9,0,0,0)
+#define XFREE86_V4 1
+#endif
+
+/* post 3.9 headers */
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+#include "misc.h"
+#include "xf86.h"
+#define NEED_XF86_TYPES
+#if !defined(DGUX)
+#include "xisb.h"
+#endif
+#include "xf86_OSproc.h"
+#include "xf86Xinput.h"
+#include "exevents.h" /* Needed for InitValuator/Proximity stuff */
+#include <X11/keysym.h>
+#include "mipointer.h"
+
+#ifdef XFree86LOADER
+#include "xf86Module.h"
+#endif
+
+#define wait_for_fd(fd) xf86WaitForInput((fd), 1000)
+#define tcflush(fd, n) xf86FlushInput((fd))
+#undef read
+#define read(a,b,c) xf86ReadSerial((a),(b),(c))
+#undef write
+#define write(a,b,c) xf86WriteSerial((a),(char*)(b),(c))
+#undef close
+#define close(a) xf86CloseSerial((a))
+#define XCONFIG_PROBED "(==)"
+#define XCONFIG_GIVEN "(**)"
+#define xf86Verbose 1
+#undef PRIVATE
+#define PRIVATE(x) XI_PRIVATE(x)
+
+/*
+ * 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", "9600",
+ "DataBits", "8",
+ "StopBits", "1",
+ "Parity", "Odd",
+ "FlowControl", "Xoff",
+ "VTime", "10",
+ "VMin", "1",
+ NULL
+};
+
+static InputDriverPtr dedgeDrv;
+
+/*
+** Debugging macros
+*/
+#ifdef DBG
+#undef DBG
+#endif
+#ifdef DEBUG
+#undef DEBUG
+#endif
+
+static int debug_level = 10;
+#define DEBUG 1
+#if DEBUG
+#define DBG(lvl, f) {if ((lvl) <= debug_level) f;}
+#else
+#define DBG(lvl, f)
+#endif
+
+/*
+** Device records
+*/
+#define ABSOLUTE_FLAG 1
+#define STYLUS_FLAG 2
+#define COMPATIBLE_FLAG 4
+
+typedef struct {
+ char *dedgeDevice; /* device file name */
+ int dedgeInc; /* increment between transmits */
+ int dedgeButTrans; /* button translation flags */
+ int dedgeOldX; /* previous X position */
+ int dedgeOldY; /* previous Y position */
+ int dedgeOldProximity; /* previous proximity */
+ int dedgeOldPush; /* previous buttons state */
+ int dedgeOldBarrel; /* previous buttons state */
+ int dedgeOldPressure; /* previous pen pressure */
+ int dedgeMaxX; /* max X value */
+ int dedgeMaxY; /* max Y value */
+ int dedgeXSize; /* active area X size */
+ int dedgeXOffset; /* active area X offset */
+ int dedgeYSize; /* active area Y size */
+ int dedgeYOffset; /* active area Y offset */
+ int dedgeRes; /* resolution in lines per inch */
+ int dedgeClickThresh; /* Click threshold in arbitary units */
+ int flags; /* various flags */
+ int dedgeIndex; /* number of bytes read */
+ unsigned char dedgeData[7]; /* data read on the device */
+} DigitalEdgeDeviceRec, *DigitalEdgeDevicePtr;
+
+/*
+** Configuration data
+*/
+#define DEDGE_SECTION_NAME "DigitalEdge"
+
+#ifndef XFREE86_V4
+
+#define PORT 1
+#define DEVICENAME 2
+#define THE_MODE 3
+#define CURSOR 4
+#define INCREMENT 5
+#define BORDER 6
+#define DEBUG_LEVEL 7
+#define HISTORY_SIZE 8
+#define ALWAYS_CORE 9
+#define ACTIVE_AREA 10
+#define ACTIVE_OFFSET 11
+#define COMPATIBLE 12
+#define CLICK_THRESHOLD 13
+
+#if !defined(sun) || defined(i386)
+static SymTabRec SumTab[] = {
+ {ENDSUBSECTION, "endsubsection"},
+ {PORT, "port"},
+ {DEVICENAME, "devicename"},
+ {THE_MODE, "mode"},
+ {CURSOR, "cursor"},
+ {INCREMENT, "increment"},
+ {BORDER, "border"},
+ {DEBUG_LEVEL, "debuglevel"},
+ {HISTORY_SIZE, "historysize"},
+ {ALWAYS_CORE, "alwayscore"},
+ {ACTIVE_AREA, "activearea"},
+ {ACTIVE_OFFSET, "activeoffset"},
+ {COMPATIBLE, "compatible"},
+ {CLICK_THRESHOLD, "clickthreshold"},
+ {-1, ""}
+};
+
+#define RELATIVE 1
+#define ABSOLUTE 2
+
+static SymTabRec SumModeTabRec[] = {
+ {RELATIVE, "relative"},
+ {ABSOLUTE, "absolute"},
+ {-1, ""}
+};
+
+#define PUCK 1
+#define STYLUS 2
+
+static SymTabRec SumPointTabRec[] = {
+ {PUCK, "puck"},
+ {STYLUS, "stylus"},
+ {-1, ""}
+};
+
+#endif
+#endif /* Pre 3.9 headers */
+
+/*
+** Contants and macro
+*/
+#define BUFFER_SIZE 256 /* size of reception buffer */
+#define XI_NAME "DIGITALEDGE" /* X device name for the stylus */
+
+#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))
+
+#define SS_TABID0 "0" /* Tablet ID 0 */
+#define SS_FIRMID "z?" /* Request firmware ID string */
+#define SS_CONFIG "a" /* Send configuration (max coords) */
+
+#define SS_ABSOLUTE 'F' /* Absolute mode */
+#define SS_RELATIVE 'E' /* Relative mode */
+
+#define SS_UPPER_ORIGIN "b" /* Origin upper left */
+#define SS_500LPI "h" /* 500 lines per inch */
+
+#define SS_PROMPT_MODE "B" /* Prompt mode */
+#define SS_STREAM_MODE "@" /* Stream mode */
+#define SS_INCREMENT 'I' /* Set increment */
+#define SS_BINARY_FMT "zb" /* Binary reporting */
+
+#define SS_PROMPT "P" /* Prompt for current position */
+
+static const char *ss_initstr =
+ SS_TABID0 SS_UPPER_ORIGIN SS_BINARY_FMT SS_STREAM_MODE;
+
+#define PHASING_BIT 0x80
+#define PROXIMITY_BIT 0x01
+#define TABID_BIT 0x20
+#define XSIGN_BIT 0x10
+#define YSIGN_BIT 0x08
+#define BUTTON_BITS 0x02
+#define COORD_BITS 0x7f
+
+/*
+** External declarations
+*/
+
+#ifndef XFREE86_V4
+
+#if defined(sun) && !defined(i386)
+#define ENQUEUE suneqEnqueue
+#else
+#define ENQUEUE xf86eqEnqueue
+
+extern void xf86eqEnqueue(
+ xEventPtr /*e */
+ );
+#endif
+
+extern void miPointerDeltaCursor(
+ int /*dx */ ,
+ int /*dy */ ,
+ unsigned long /*time */
+ );
+
+#if !defined(sun) || defined(i386)
+/*
+** xf86SumConfig
+** Reads the DigitalEdge section from the XF86Config file
+*/
+static Bool
+xf86SumConfig(LocalDevicePtr * array, int inx, int max, LexPtr val)
+{
+ LocalDevicePtr dev = array[inx];
+ DigitalEdgeDevicePtr priv = (DigitalEdgeDevicePtr) (dev->private);
+ int token;
+ int mtoken;
+
+ DBG(1, ErrorF("xf86SumConfig\n"));
+
+ while ((token = xf86GetToken(SumTab)) != ENDSUBSECTION) {
+ switch (token) {
+ case DEVICENAME:
+ if (xf86GetToken(NULL) != STRING)
+ xf86ConfigError("Option string expected");
+ else {
+ dev->name = strdup(val->str);
+ if (xf86Verbose)
+ ErrorF("%s DigitalEdge X device name is %s\n",
+ XCONFIG_GIVEN, dev->name);
+ }
+ break;
+
+ case PORT:
+ if (xf86GetToken(NULL) != STRING)
+ xf86ConfigError("Option string expected");
+ else {
+ priv->dedgeDevice = strdup(val->str);
+ if (xf86Verbose)
+ ErrorF("%s DigitalEdge port is %s\n", XCONFIG_GIVEN,
+ priv->dedgeDevice);
+ }
+ break;
+
+ case THE_MODE:
+ mtoken = xf86GetToken(SumModeTabRec);
+ if ((mtoken == EOF) || (mtoken == STRING)
+ || (mtoken ==
+ NUMBER)) xf86ConfigError("Mode type token expected");
+ else {
+ switch (mtoken) {
+ case ABSOLUTE:
+ priv->flags |= ABSOLUTE_FLAG;
+ break;
+ case RELATIVE:
+ priv->flags &= ~ABSOLUTE_FLAG;
+ break;
+ default:
+ xf86ConfigError("Illegal Mode type");
+ break;
+ }
+ }
+ break;
+
+ case CURSOR:
+ mtoken = xf86GetToken(SumPointTabRec);
+ if ((mtoken == EOF) || (mtoken == STRING)
+ || (mtoken ==
+ NUMBER)) xf86ConfigError("Cursor token expected");
+ else {
+ switch (mtoken) {
+ case STYLUS:
+ priv->flags |= STYLUS_FLAG;
+ break;
+ case PUCK:
+ priv->flags &= ~STYLUS_FLAG;
+ break;
+ default:
+ xf86ConfigError("Illegal cursor type");
+ break;
+ }
+ }
+ break;
+
+ case INCREMENT:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->dedgeInc = val->num;
+ if (xf86Verbose)
+ ErrorF("%s DigitalEdge increment value is %d\n",
+ XCONFIG_GIVEN, priv->dedgeInc);
+ break;
+
+ case CLICK_THRESHOLD:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->dedgeClickThresh = val->num;
+ if (xf86Verbose)
+ ErrorF("%s DigitalEdge click threshold is %d\n",
+ XCONFIG_GIVEN, priv->dedgeClickThresh);
+ break;
+
+ case DEBUG_LEVEL:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ debug_level = val->num;
+ if (xf86Verbose) {
+#if DEBUG
+ ErrorF("%s DigitalEdge debug level sets to %d\n",
+ XCONFIG_GIVEN, debug_level);
+#else
+ ErrorF("%s DigitalEdge debug level not sets to %d because"
+ " debugging is not compiled\n", XCONFIG_GIVEN,
+ debug_level);
+#endif
+ }
+ break;
+
+ case HISTORY_SIZE:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ dev->history_size = val->num;
+ if (xf86Verbose)
+ ErrorF("%s DigitalEdge Motion history size is %d\n",
+ XCONFIG_GIVEN, dev->history_size);
+ break;
+ case COMPATIBLE:
+ priv->flags |= COMPATIBLE_FLAG;
+ if (xf86Verbose)
+ ErrorF
+ ("DigitalEdge compatible - will not query firmware ID\n");
+ break;
+
+ case ALWAYS_CORE:
+ xf86AlwaysCore(dev, TRUE);
+ if (xf86Verbose)
+ ErrorF("%s DigitalEdge device always stays core pointer\n",
+ XCONFIG_GIVEN);
+ break;
+
+ case ACTIVE_AREA:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->dedgeXSize = val->num;
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->dedgeYSize = val->num;
+ ErrorF("%s DigitalEdge active area set to %d.%1dx%d.%1d"
+ " inches\n", XCONFIG_GIVEN, priv->dedgeXSize / 10,
+ priv->dedgeXSize % 10, priv->dedgeYSize / 10,
+ priv->dedgeYSize % 10);
+ break;
+
+ case ACTIVE_OFFSET:
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->dedgeXOffset = val->num;
+ if (xf86GetToken(NULL) != NUMBER)
+ xf86ConfigError("Option number expected");
+ priv->dedgeYOffset = val->num;
+ if (xf86Verbose)
+ ErrorF
+ ("%s DigitalEdge active area offset set to %d.%1dx%d.%1d"
+ " inches\n", XCONFIG_GIVEN, priv->dedgeXOffset / 10,
+ priv->dedgeXOffset % 10, priv->dedgeYOffset / 10,
+ priv->dedgeYOffset % 10);
+ break;
+
+ case EOF:
+ FatalError("Unexpected EOF (missing EndSubSection)");
+ break;
+
+ default:
+ xf86ConfigError("DigitalEdge subsection keyword expected");
+ break;
+ }
+ }
+
+ DBG(1, ErrorF("xf86SumConfig name=%s\n", priv->dedgeDevice));
+
+ return Success;
+}
+#endif
+#endif /* pre 3.9 headers */
+
+/*
+** xf86SumConvert
+** Convert valuators to X and Y.
+*/
+static Bool
+xf86SumConvert(LocalDevicePtr local,
+ int first,
+ int num,
+ int v0,
+ int v1, int v2, int v3, int v4, int v5, int *x, int *y)
+{
+ if (first != 0 || num == 1)
+ return FALSE;
+
+ *x = v0 * screenInfo.screens[0]->width / 2430;
+ *y = v1 * screenInfo.screens[0]->height / 1950;
+
+ DBG(6, ErrorF("Adjusted coords x=%d y=%d\n", *x, *y));
+
+ return TRUE;
+}
+
+/*
+** xf86SumReverseConvert
+** Convert X and Y to valuators.
+*/
+static Bool
+xf86SumReverseConvert(LocalDevicePtr local, int x, int y, int *valuators)
+{
+ DigitalEdgeDevicePtr priv = (DigitalEdgeDevicePtr) local->private;
+
+ valuators[0] = ((x * 2430) / screenInfo.screens[0]->width) + priv->dedgeXOffset;
+ valuators[1] = ((y * 1950) / screenInfo.screens[0]->height) + priv->dedgeYOffset;
+
+
+ DBG(6,
+ ErrorF("Adjusted valuators v0=%d v1=%d\n", valuators[0],
+ valuators[1]));
+
+ return TRUE;
+}
+
+/*
+** xf86SumReadInput
+** Reads from the DigitalEdge and posts any new events to the server.
+*/
+static void xf86SumReadInput(LocalDevicePtr local)
+{
+ DigitalEdgeDevicePtr priv = (DigitalEdgeDevicePtr) local->private;
+ int len, loop;
+ int is_absolute;
+ int x, y, push, barrel, prox, pressure;
+ DeviceIntPtr device;
+ unsigned char buffer[BUFFER_SIZE];
+
+ DBG(7, ErrorF("xf86SumReadInput BEGIN device=%s fd=%d\n",
+ priv->dedgeDevice, local->fd));
+
+ SYSCALL(len = read(local->fd, buffer, sizeof(buffer)));
+
+ if (len <= 0) {
+ Error("error reading DigitalEdge device");
+ return;
+ }
+
+ for (loop = 0; loop < len; loop++) {
+
+/* Format of 5 bytes data packet for DigitalEdge Tablets
+ Byte 1
+ bit 7 Phasing bit always 1
+ bit 6 Proximity bit
+ bit 5 Tablet ID
+ bit 4 X sign (Always 1 for absolute)
+ bit 3 Y sign (Always 1 for absolute)
+ bit 2-0 Button status
+
+ Byte 2
+ bit 7 Always 0
+ bits 6-0 = X6 - X0
+
+ Byte 3 (Absolute mode only)
+ bit 7 Always 0
+ bits 6-0 = X13 - X7
+
+ Byte 4
+ bit 7 Always 0
+ bits 6-0 = Y6 - Y0
+
+ Byte 5 (Absolute mode only)
+ bit 7 Always 0
+ bits 6-0 = Y13 - Y7
+*/
+
+ if ((priv->dedgeIndex == 0) && !(buffer[loop] & PHASING_BIT)) { /* magic bit is not OK */
+ DBG(6,
+ ErrorF("xf86SumReadInput bad magic number 0x%x\n",
+ buffer[loop]));;
+ continue;
+ }
+
+ priv->dedgeData[priv->dedgeIndex++] = buffer[loop];
+
+ if (priv->dedgeIndex == 7) {
+/* the packet is OK */
+/* reset char count for next read */
+ priv->dedgeIndex = 0;
+
+ if (priv->flags & ABSOLUTE_FLAG) {
+ x = (int) priv->dedgeData[1] + ((int) priv->dedgeData[2] << 7);
+ y = 1950 - ((int) priv->dedgeData[3] + ((int) priv->dedgeData[4] << 7));
+ } else {
+ x =
+ priv->dedgeData[0] & XSIGN_BIT ? priv->
+ dedgeData[1] : -priv->dedgeData[1];
+ y =
+ priv->dedgeData[0] & YSIGN_BIT ? priv->
+ dedgeData[2] : -priv->dedgeData[2];
+ }
+ prox = (priv->dedgeData[0] & PROXIMITY_BIT) ? 1 : 0;
+
+ pressure = priv->dedgeData[6] + (priv->dedgeData[5] >> 4) * 128;
+ push = pressure > priv->dedgeClickThresh?1:0;
+ if ((priv->dedgeOldPressure) < priv->dedgeClickThresh && pressure == 1022) {
+ push = 0;
+ } else {
+ priv->dedgeOldPressure = pressure;
+ }
+ if (priv->dedgeData[0] & BUTTON_BITS) {
+ barrel = 1;
+ } else {
+ barrel = 0;
+ }
+
+ device = local->dev;
+
+ DBG(6, ErrorF("prox=%s\tx=%d\ty=%d\tbarrel=%d\tpressure=%d\n",
+ prox ? "true" : "false", x, y, barrel,
+ pressure));
+
+ is_absolute = (priv->flags & ABSOLUTE_FLAG);
+
+/* coordonates are ready we can send events */
+ if (prox) {
+ if (!(priv->dedgeOldProximity))
+ xf86PostProximityEvent(device, 1, 0, 3, x, y, pressure);
+
+ if (
+ (is_absolute
+ && ((priv->dedgeOldX != x) || (priv->dedgeOldY != y)))
+ || (!is_absolute && (x || y))) {
+ if (is_absolute || priv->dedgeOldProximity) {
+ xf86PostMotionEvent(device, is_absolute, 0, 3, x,
+ y, pressure);
+ }
+ }
+ if (priv->dedgeOldPush != push) {
+ int delta;
+
+ delta = push - priv->dedgeOldPush;
+
+ if (priv->dedgeOldPush != push) {
+ DBG(6,
+ ErrorF("xf86SumReadInput push delta=%d\n", delta));
+ xf86PostButtonEvent(device, is_absolute, 1,
+ (delta > 0), 0, 3, x, y, pressure);
+ }
+ }
+
+ if (priv->dedgeOldBarrel != barrel) {
+ int delta;
+
+ delta = barrel - priv->dedgeOldBarrel;
+
+ if (priv->dedgeOldBarrel != barrel) {
+ DBG(6,
+ ErrorF("xf86SumReadInput barrel delta=%d\n", delta));
+ xf86PostButtonEvent(device, is_absolute, 2,
+ (delta > 0), 0, 3, x, y, pressure);
+ }
+ }
+
+ priv->dedgeOldPush = push;
+ priv->dedgeOldBarrel = barrel;
+ priv->dedgeOldX = x;
+ priv->dedgeOldY = y;
+ priv->dedgeOldProximity = prox;
+
+ } else { /* !PROXIMITY */
+/* Any changes in buttons are ignored when !proximity */
+ if (priv->dedgeOldProximity)
+ xf86PostProximityEvent(device, 0, 0, 3, x, y, pressure);
+ priv->dedgeOldProximity = 0;
+ }
+ }
+ }
+ DBG(7, ErrorF("xf86Sum(priv->dedgeData[0] & BUTTON_BITS)iReadInput END device=%p priv=%p\n",
+ (void *)local->dev, (void *)priv));
+}
+
+/*
+** xf86SumControlProc
+** It really does do something. Honest!
+*/
+static void xf86SumControlProc(DeviceIntPtr device, PtrCtrl * ctrl)
+{
+ DBG(2, ErrorF("xf86SumControlProc\n"));
+}
+
+#if 0
+/*
+** xf86SumWriteAndRead
+** Write data, and get the response.
+*/
+static char *xf86SumWriteAndRead(int fd, char *data, char *buffer, int len,
+ int cr_term)
+{
+ int err, numread = 0;
+#ifndef XFREE86_V4
+ fd_set readfds;
+ struct timeval timeout;
+#endif
+
+ SYSCALL(err = write(fd, data, strlen(data)));
+ if (err == -1) {
+ Error("DigitalEdge write");
+ return NULL;
+ }
+#ifndef XFREE86_V4
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+#endif
+ while (numread < len) {
+#ifndef XFREE86_V4
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 200000;
+
+ SYSCALL(err = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout));
+#else
+ err = xf86WaitForInput(fd, 1000);
+#endif
+ if (err == -1) {
+ Error("DigitalEdge select");
+ return NULL;
+ }
+ if (!err) {
+ ErrorF
+ ("Timeout while reading DigitalEdge tablet. No tablet connected ???\n");
+ return NULL;
+ }
+
+ SYSCALL(err = read(fd, buffer + numread++, 1));
+ if (err == -1) {
+ Error("DigitalEdge read");
+ return NULL;
+ }
+ if (!err) {
+ --numread;
+ break;
+ }
+ if (cr_term && buffer[numread - 1] == '\r') {
+ buffer[numread - 1] = 0;
+ break;
+ }
+ }
+ buffer[numread] = 0;
+ return buffer;
+}
+#endif
+
+/*
+** xf86SumOpen
+** Open and initialize the tablet, as well as probe for any needed data.
+*/
+static Bool xf86SumOpen(LocalDevicePtr local)
+{
+#ifndef XFREE86_V4
+ struct termios termios_tty;
+ struct timeval timeout;
+#endif
+ char buffer[256];
+ int err, idx;
+ DigitalEdgeDevicePtr priv = (DigitalEdgeDevicePtr) local->private;
+
+ DBG(1, ErrorF("opening %s\n", priv->dedgeDevice));
+
+#ifdef XFREE86_V4
+ local->fd = xf86OpenSerial(local->options);
+#else
+ SYSCALL(local->fd = open(priv->dedgeDevice, O_RDWR | O_NDELAY, 0));
+#endif
+ if (local->fd == -1) {
+ Error(priv->dedgeDevice);
+ return !Success;
+ }
+ DBG(2, ErrorF("%s opened as fd %d\n", priv->dedgeDevice, local->fd));
+
+#ifndef XFREE86_V4
+#ifdef POSIX_TTY
+ err = tcgetattr(local->fd, &termios_tty);
+ if (err == -1) {
+ Error("DigitalEdge tcgetattr");
+ return !Success;
+ }
+ termios_tty.c_iflag = IXOFF;
+ termios_tty.c_cflag =
+ B9600 | CS8 | CREAD | CLOCAL | HUPCL | PARENB | PARODD;
+ termios_tty.c_lflag = 0;
+
+/* I wonder what these all do, anyway */
+ termios_tty.c_cc[VINTR] = 0;
+ termios_tty.c_cc[VQUIT] = 0;
+ termios_tty.c_cc[VERASE] = 0;
+#ifdef VWERASE
+ termios_tty.c_cc[VWERASE] = 0;
+#endif
+#ifdef VREPRINT
+ termios_tty.c_cc[VREPRINT] = 0;
+#endif
+ termios_tty.c_cc[VKILL] = 0;
+ termios_tty.c_cc[VEOF] = 0;
+ termios_tty.c_cc[VEOL] = 0;
+#ifdef VEOL2
+ termios_tty.c_cc[VEOL2] = 0;
+#endif
+ termios_tty.c_cc[VSUSP] = 0;
+#ifdef VDISCARD
+ termios_tty.c_cc[VDISCARD] = 0;
+#endif
+#ifdef VLNEXT
+ termios_tty.c_cc[VLNEXT] = 0;
+#endif
+
+ termios_tty.c_cc[VMIN] = 1;
+ termios_tty.c_cc[VTIME] = 10;
+
+ err = tcsetattr(local->fd, TCSANOW, &termios_tty);
+ if (err == -1) {
+ Error("DigitalEdge tcsetattr TCSANOW");
+ return !Success;
+ }
+#else
+ Code for someone
+ else
+ to write to handle OSs without POSIX tty functions
+#endif
+#endif
+ DBG(1, ErrorF("initializing DigitalEdge tablet\n"));
+
+/* Send reset (NULL) to the tablet */
+ SYSCALL(err = write(local->fd, "", 1));
+ if (err == -1) {
+ Error("DigitalEdge write");
+ return !Success;
+ }
+
+/* wait 200 mSecs, just in case */
+#ifndef XFREE86_V4
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 200000;
+ SYSCALL(err = select(0, NULL, NULL, NULL, &timeout));
+#else
+ err = xf86WaitForInput(-1, 200);
+#endif
+ if (err == -1) {
+ Error("DigitalEdge select");
+ return !Success;
+ }
+
+/* Put it in prompt mode so it doens't say anything before we're ready */
+ SYSCALL(err =
+ write(local->fd, SS_PROMPT_MODE, strlen(SS_PROMPT_MODE)));
+ if (err == -1) {
+ Error("DigitalEdge write");
+ return !Success;
+ }
+/* Clear any pending input */
+#ifndef XFREE86_V4
+ tcflush(local->fd, TCIFLUSH);
+#else
+ xf86FlushInput(local->fd);
+#endif
+
+ if (priv->dedgeXOffset > 0 && priv->dedgeYOffset > 0) {
+ if (priv->dedgeXSize * 50 < priv->dedgeMaxX - priv->dedgeXOffset &&
+ priv->dedgeYSize * 50 < priv->dedgeMaxY - priv->dedgeYOffset) {
+ priv->dedgeXOffset *= 50;
+ priv->dedgeYOffset *= 50;
+ } else {
+ ErrorF("%s DigitalEdge offset sets active area off tablet, "
+ "centering\n", XCONFIG_PROBED);
+ priv->dedgeXOffset = (priv->dedgeMaxX - priv->dedgeXSize) / 2;
+ priv->dedgeYOffset = (priv->dedgeMaxY - priv->dedgeYSize) / 2;
+ }
+ } else {
+ priv->dedgeXOffset = (priv->dedgeMaxX - priv->dedgeXSize) / 2;
+ priv->dedgeYOffset = (priv->dedgeMaxY - priv->dedgeYSize) / 2;
+ }
+
+ if (priv->dedgeInc > 95)
+ priv->dedgeInc = 95;
+ if (priv->dedgeInc < 1) {
+/* Make a guess as to the best increment value given video mode */
+ if (priv->dedgeXSize / screenInfo.screens[0]->width <
+ priv->dedgeYSize / screenInfo.screens[0]->height)
+ priv->dedgeInc = priv->dedgeXSize / screenInfo.screens[0]->width;
+ else
+ priv->dedgeInc = priv->dedgeYSize / screenInfo.screens[0]->height;
+ if (priv->dedgeInc < 1)
+ priv->dedgeInc = 1;
+ if (xf86Verbose)
+ ErrorF("%s Using increment value of %d\n", XCONFIG_PROBED,
+ priv->dedgeInc);
+ }
+
+/* Sets up the tablet mode to increment, stream, and such */
+ for (idx = 0; ss_initstr[idx]; idx++) {
+ buffer[idx] = ss_initstr[idx];
+ }
+ buffer[idx++] = SS_INCREMENT;
+ buffer[idx++] = 32 + priv->dedgeInc;
+ buffer[idx++] =
+ (priv->flags & ABSOLUTE_FLAG) ? SS_ABSOLUTE : SS_RELATIVE;
+ buffer[idx] = 0;
+
+ SYSCALL(err = write(local->fd, buffer, idx));
+ if (err == -1) {
+ Error("DigitalEdge write");
+ return !Success;
+ }
+
+ if (err <= 0) {
+ SYSCALL(close(local->fd));
+ return !Success;
+ }
+
+ if (priv->dedgeClickThresh <= 0) {
+ /* Make up a value */
+ priv->dedgeClickThresh = 700;
+ }
+
+ return Success;
+}
+
+/*
+** xf86SumOpenDevice
+** Opens and initializes the device driver stuff or dedgepthin.
+*/
+static int xf86SumOpenDevice(DeviceIntPtr pSum)
+{
+ LocalDevicePtr local = (LocalDevicePtr) pSum->public.devicePrivate;
+ DigitalEdgeDevicePtr priv = (DigitalEdgeDevicePtr) PRIVATE(pSum);
+
+ if (xf86SumOpen(local) != Success) {
+ if (local->fd >= 0) {
+ SYSCALL(close(local->fd));
+ }
+ local->fd = -1;
+ }
+
+/* Set the real values */
+ InitValuatorAxisStruct(pSum, 0, 0, /* min val */
+ 2430, /* max val */
+ 500, /* resolution */
+ 0, /* min_res */
+ 500); /* max_res */
+ InitValuatorAxisStruct(pSum, 1, 0, /* min val */
+ 1950, /* max val */
+ 500, /* resolution */
+ 0, /* min_res */
+ 500); /* max_res */
+ InitValuatorAxisStruct(pSum, 2, priv->dedgeClickThresh, /* min val */
+ 1022, /* max val */
+ 500, /* resolution */
+ 0, /* min_res */
+ 500); /* max_res */
+ return (local->fd != -1);
+}
+
+/*
+** xf86SumProc
+** Handle requests to do stuff to the driver.
+*/
+static int xf86SumProc(DeviceIntPtr pSum, int what)
+{
+ CARD8 map[25];
+ int nbaxes;
+ int nbbuttons;
+ int loop;
+ LocalDevicePtr local = (LocalDevicePtr) pSum->public.devicePrivate;
+ DigitalEdgeDevicePtr priv = (DigitalEdgeDevicePtr) PRIVATE(pSum);
+
+ DBG(2,
+ ErrorF("BEGIN xf86SumProc dev=%p priv=%p what=%d\n", (void *)pSum,
+ (void *)priv, what));
+
+ switch (what) {
+ case DEVICE_INIT:
+ DBG(1, ErrorF("xf86SumProc pSum=%p what=INIT\n", (void *)pSum));
+
+ nbaxes = 3; /* X, Y, pressure */
+ nbbuttons = (priv->flags & STYLUS_FLAG) ? 2 : 4;
+
+ for (loop = 1; loop <= nbbuttons; loop++)
+ map[loop] = loop;
+
+ if (InitButtonClassDeviceStruct(pSum, nbbuttons, map) == FALSE) {
+ ErrorF("unable to allocate Button class device\n");
+ return !Success;
+ }
+
+ if (InitFocusClassDeviceStruct(pSum) == FALSE) {
+ ErrorF("unable to init Focus class device\n");
+ return !Success;
+ }
+
+ if (InitPtrFeedbackClassDeviceStruct(pSum, xf86SumControlProc) ==
+ FALSE) {
+ ErrorF("unable to init ptr feedback\n");
+ return !Success;
+ }
+
+ if (InitProximityClassDeviceStruct(pSum) == FALSE) {
+ ErrorF("unable to init proximity class device\n");
+ return !Success;
+ }
+
+ if (InitValuatorClassDeviceStruct(pSum,
+ nbaxes,
+ xf86GetMotionEvents,
+ local->history_size,
+ (priv->flags & ABSOLUTE_FLAG) ?
+ Absolute : Relative) == FALSE) {
+ ErrorF("unable to allocate Valuator class device\n");
+ return !Success;
+ }
+/* allocate the motion history buffer if needed */
+ xf86MotionHistoryAllocate(local);
+#ifndef XFREE86_V4
+ AssignTypeAndName(pSum, local->atom, local->name);
+#endif
+
+/* open the device to gather informations */
+ xf86SumOpenDevice(pSum);
+ break;
+
+ case DEVICE_ON:
+ DBG(1, ErrorF("xf86SumProc pSum=%p what=ON\n", (void *)pSum));
+
+ if ((local->fd < 0) && (!xf86SumOpenDevice(pSum))) {
+ return !Success;
+ }
+ SYSCALL(write(local->fd, SS_PROMPT, strlen(SS_PROMPT)));
+#ifdef XFREE86_V4
+ xf86AddEnabledDevice(local);
+#else
+ AddEnabledDevice(local->fd);
+#endif
+ pSum->public.on = TRUE;
+ break;
+
+ case DEVICE_OFF:
+ DBG(1, ErrorF("xf86SumProc pSum=%p what=%s\n", (void *)pSum,
+ (what == DEVICE_CLOSE) ? "CLOSE" : "OFF"));
+ if (local->fd >= 0)
+#ifdef XFREE86_V4
+ xf86RemoveEnabledDevice(local);
+#else
+ RemoveEnabledDevice(local->fd);
+#endif
+ pSum->public.on = FALSE;
+ break;
+
+ case DEVICE_CLOSE:
+ DBG(1, ErrorF("xf86SumProc pSum=%p what=%s\n", (void *)pSum,
+ (what == DEVICE_CLOSE) ? "CLOSE" : "OFF"));
+ SYSCALL(close(local->fd));
+ local->fd = -1;
+ break;
+
+ default:
+ ErrorF("unsupported mode=%d\n", what);
+ return !Success;
+ break;
+ }
+ DBG(2, ErrorF("END xf86SumProc Success what=%d dev=%p priv=%p\n",
+ what, (void *)pSum, (void *)priv));
+ return Success;
+}
+
+/*
+** xf86SumClose
+** It... Uh... Closes the physical device?
+*/
+static void xf86SumClose(LocalDevicePtr local)
+{
+ if (local->fd >= 0) {
+ SYSCALL(close(local->fd));
+ }
+ local->fd = -1;
+}
+
+/*
+** xf86SumChangeControl
+** When I figure out what it does, it will do it.
+*/
+static int xf86SumChangeControl(LocalDevicePtr local, xDeviceCtl * control)
+{
+ xDeviceResolutionCtl *res;
+
+ res = (xDeviceResolutionCtl *) control;
+
+ if ((control->control != DEVICE_RESOLUTION)
+ || (res->num_valuators < 1)) return (BadMatch);
+
+ return (Success);
+}
+
+/*
+** xf86SumSwitchMode
+** Switches the mode. For now just absolute or relative, hopefully
+** more on the way.
+*/
+static int xf86SumSwitchMode(ClientPtr client, DeviceIntPtr dev, int mode)
+{
+ LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
+ DigitalEdgeDevicePtr priv = (DigitalEdgeDevicePtr) (local->private);
+ char newmode;
+
+ DBG(3, ErrorF("xf86SumSwitchMode dev=%p mode=%d\n", (void *)dev, mode));
+
+ switch (mode) {
+ case Absolute:
+ priv->flags |= ABSOLUTE_FLAG;
+ newmode = SS_ABSOLUTE;
+ break;
+
+ case Relative:
+ priv->flags &= ~ABSOLUTE_FLAG;
+ newmode = SS_RELATIVE;
+ break;
+
+ default:
+ DBG(1, ErrorF("xf86SumSwitchMode dev=%p invalid mode=%d\n",
+ (void *)dev, mode));
+ return BadMatch;
+ }
+ SYSCALL(write(local->fd, &newmode, 1));
+ return Success;
+}
+
+/*
+** xf86SumAllocate
+** Allocates the device structures for the DigitalEdge.
+*/
+static LocalDevicePtr xf86SumAllocate(void)
+{
+#ifdef XFREE86_V4
+ LocalDevicePtr local = xf86AllocateInput(dedgeDrv, 0);
+#else
+ LocalDevicePtr local = (LocalDevicePtr) xalloc(sizeof(LocalDeviceRec));
+#endif
+ DigitalEdgeDevicePtr priv = (DigitalEdgeDevicePtr) xalloc(sizeof(DigitalEdgeDeviceRec));
+#if defined (sun) && !defined(i386)
+ char *dev_name = getenv("DEDGESKETCH_DEV");
+#endif
+
+ local->name = XI_NAME;
+ local->type_name = "DigitalEdge Tablet";
+ local->flags = 0; /*XI86_NO_OPEN_ON_INIT; */
+#ifndef XFREE86_V4
+#if !defined(sun) || defined(i386)
+ local->device_config = xf86SumConfig;
+#endif
+#endif
+ local->device_control = xf86SumProc;
+ local->read_input = xf86SumReadInput;
+ local->control_proc = xf86SumChangeControl;
+ local->close_proc = xf86SumClose;
+ local->switch_mode = xf86SumSwitchMode;
+ local->conversion_proc = xf86SumConvert;
+ local->reverse_conversion_proc = xf86SumReverseConvert;
+ local->fd = -1;
+ local->atom = 0;
+ local->dev = NULL;
+ local->private = priv;
+ local->private_flags = 0;
+ local->history_size = 0;
+
+#if defined(sun) && !defined(i386)
+ if (dev_name) {
+ priv->dedgeDevice = (char *) xalloc(strlen(dev_name) + 1);
+ strcpy(priv->dedgeDevice, dev_name);
+ ErrorF("xf86SumOpen port changed to '%s'\n", priv->dedgeDevice);
+ } else {
+ priv->dedgeDevice = "";
+ }
+#else
+ priv->dedgeDevice = ""; /* device file name */
+#endif
+ priv->dedgeInc = -1; /* re-transmit position on increment */
+ priv->dedgeOldX = -1; /* previous X position */
+ priv->dedgeOldY = -1; /* previous Y position */
+ priv->dedgeOldProximity = 0; /* previous proximity */
+ priv->dedgeOldPush = 0; /* previous buttons state */
+ priv->dedgeOldBarrel = 0; /* previous buttons state */
+ priv->dedgeMaxX = -1; /* max X value */
+ priv->dedgeMaxY = -1; /* max Y value */
+ priv->dedgeXSize = -1; /* active area X */
+ priv->dedgeXOffset = -1; /* active area X offset */
+ priv->dedgeYSize = -1; /* active area Y */
+ priv->dedgeYOffset = -1; /* active area U offset */
+ priv->flags = 0; /* various flags */
+ priv->dedgeIndex = 0; /* number of bytes read */
+
+ return local;
+}
+
+#ifndef XFREE86_V4
+
+/*
+** DigitalEdge device association
+** Device section name and allocation function.
+*/
+DeviceAssocRec dedgemasketch_assoc = {
+ DEDGE_SECTION_NAME, /* config_section_name */
+ xf86SumAllocate /* device_allocate */
+};
+
+#ifdef DYNAMIC_MODULE
+/*
+** init_module
+** Entry point for dynamic module.
+*/
+int
+#ifndef DLSYM_BUG
+init_module(unsigned long server_version)
+#else
+init_xf86DigitalEdge(unsigned long server_version)
+#endif
+{
+ xf86AddDeviceAssoc(&dedgemasketch_assoc);
+
+ if (server_version != XF86_VERSION_CURRENT) {
+ ErrorF("Warning: DigitalEdgeKetch module compiled for version%s\n",
+ XF86_VERSION);
+ return 0;
+ } else {
+ return 1;
+ }
+}
+#endif
+
+#else
+
+/*
+ * xf86SumUninit --
+ *
+ * called when the driver is unloaded.
+ */
+static void
+xf86SumUninit(InputDriverPtr drv,
+ LocalDevicePtr local,
+ int flags)
+{
+ DigitalEdgeDevicePtr priv = (DigitalEdgeDevicePtr) local->private;
+
+ DBG(1, ErrorF("xf86DedgeUninit\n"));
+
+ xf86SumProc(local->dev, DEVICE_OFF);
+
+ xfree (priv);
+ xf86DeleteInput(local, 0);
+}
+
+
+/*
+ * xf86SumInit --
+ *
+ * called when the module subsection is found in XF86Config
+ */
+static InputInfoPtr
+xf86SumInit(InputDriverPtr drv,
+ IDevPtr dev,
+ int flags)
+{
+ LocalDevicePtr local = NULL;
+ DigitalEdgeDevicePtr priv = NULL;
+ char *s;
+
+ dedgeDrv = drv;
+
+ local = xf86SumAllocate();
+ local->conf_idev = dev;
+
+ xf86CollectInputOptions(local, default_options, NULL);
+ xf86OptionListReport( local->options );
+
+ if (local)
+ priv = (DigitalEdgeDevicePtr) local->private;
+
+ if (!local || !priv) {
+ goto SetupProc_fail;
+ }
+
+ local->name = dev->identifier;
+
+ /* Serial Device is mandatory */
+ priv->dedgeDevice = xf86FindOptionValue(local->options, "Device");
+
+ if (!priv->dedgeDevice) {
+ xf86Msg (X_ERROR, "%s: No Device specified.\n", dev->identifier);
+ goto SetupProc_fail;
+ }
+
+ /* Process the common options. */
+ xf86ProcessCommonOptions(local, local->options);
+
+ /* Optional configuration */
+
+ xf86Msg(X_CONFIG, "%s serial device is %s\n", dev->identifier,
+ priv->dedgeDevice);
+
+ debug_level = xf86SetIntOption(local->options, "DebugLevel", 0);
+ if (debug_level > 0) {
+ xf86Msg(X_CONFIG, "Summa: debug level set to %d\n", debug_level);
+ }
+
+
+
+ s = xf86FindOptionValue(local->options, "Mode");
+
+ if (s && (xf86NameCmp(s, "absolute") == 0)) {
+ priv->flags = priv->flags | ABSOLUTE_FLAG;
+ }
+ else if (s && (xf86NameCmp(s, "relative") == 0)) {
+ priv->flags = priv->flags & ~ABSOLUTE_FLAG;
+ }
+ else if (s) {
+ xf86Msg(X_ERROR, "%s: invalid Mode (should be absolute or relative). "
+ "Using default.\n", dev->identifier);
+ }
+ xf86Msg(X_CONFIG, "%s is in %s mode\n", local->name,
+ (priv->flags & ABSOLUTE_FLAG) ? "absolute" : "relative");
+
+
+ s = xf86FindOptionValue(local->options, "Cursor");
+
+ if (s && (xf86NameCmp(s, "stylus") == 0)) {
+ priv->flags = priv->flags | STYLUS_FLAG;
+ }
+ else if (s && (xf86NameCmp(s, "puck") == 0)) {
+ priv->flags = priv->flags & ~STYLUS_FLAG;
+ }
+ else if (s) {
+ xf86Msg(X_ERROR, "%s: invalid Cursor (should be stylus or puck). "
+ "Using default.\n", dev->identifier);
+ }
+ xf86Msg(X_CONFIG, "%s is in cursor-mode %s\n", local->name,
+ (priv->flags & STYLUS_FLAG) ? "cursor" : "puck");
+
+ priv->dedgeInc = xf86SetIntOption(local->options, "increment", 0);
+ if (priv->dedgeInc != 0) {
+ xf86Msg(X_CONFIG, "%s: Increment = %d\n",
+ dev->identifier, priv->dedgeInc);
+ }
+
+ priv->dedgeClickThresh = xf86SetIntOption(local->options,
+ "clickthreshold", 0);
+ if (priv->dedgeClickThresh != 0) {
+ xf86Msg(X_CONFIG, "%s: click threshold is %d\n",
+ dev->identifier, priv->dedgeClickThresh);
+ }
+
+ priv->dedgeXSize = xf86SetIntOption(local->options, "XSize", 0);
+ if (priv->dedgeXSize != 0) {
+ xf86Msg(X_CONFIG, "%s: XSize = %d\n",
+ dev->identifier, priv->dedgeXSize);
+ }
+
+ priv->dedgeYSize = xf86SetIntOption(local->options, "YSize", 0);
+ if (priv->dedgeYSize != 0) {
+ xf86Msg(X_CONFIG, "%s: YSize = %d\n",
+ dev->identifier, priv->dedgeYSize);
+ }
+
+ priv->dedgeXOffset = xf86SetIntOption(local->options, "XOffset", 0);
+ if (priv->dedgeXOffset != 0) {
+ xf86Msg(X_CONFIG, "%s: XOffset = %d\n",
+ dev->identifier, priv->dedgeXOffset);
+ }
+
+ priv->dedgeYOffset = xf86SetIntOption(local->options, "YOffset", 0);
+ if (priv->dedgeYOffset != 0) {
+ xf86Msg(X_CONFIG, "%s: YOffset = %d\n",
+ dev->identifier, priv->dedgeYOffset);
+ }
+
+
+
+ /* mark the device configured */
+ local->flags |= XI86_POINTER_CAPABLE | XI86_CONFIGURED;
+
+ /* return the LocalDevice */
+ return local;
+
+ SetupProc_fail:
+ if (priv)
+ xfree(priv);
+ return local;
+}
+
+_X_EXPORT InputDriverRec DIGITALEDGE = {
+ 1, /* driver version */
+ "digitaledge", /* driver name */
+ NULL, /* identify */
+ xf86SumInit, /* pre-init */
+ xf86SumUninit, /* un-init */
+ NULL, /* module */
+ 0 /* ref count */
+};
+
+
+/*
+ ***************************************************************************
+ *
+ * Dynamic loading functions
+ *
+ ***************************************************************************
+ */
+#ifdef XFree86LOADER
+/*
+ * xf86SumUnplug --
+ *
+ * called when the module subsection is found in XF86Config
+ */
+static void
+xf86SumUnplug(pointer p)
+{
+}
+
+/*
+ * xf86SumPlug --
+ *
+ * called when the module subsection is found in XF86Config
+ */
+static pointer
+xf86SumPlug(pointer module,
+ pointer options,
+ int *errmaj,
+ int *errmin)
+{
+ xf86AddInputDriver(&DIGITALEDGE, module, 0);
+
+ return module;
+}
+
+static XF86ModuleVersionInfo xf86SumVersionRec =
+{
+ "digitaledge",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XORG_VERSION_CURRENT,
+ PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
+ ABI_CLASS_XINPUT,
+ ABI_XINPUT_VERSION,
+ MOD_CLASS_XINPUT,
+ {0, 0, 0, 0} /* signature, to be patched into the file by */
+ /* a tool */
+};
+
+_X_EXPORT XF86ModuleData digitaledgeModuleData = {
+ &xf86SumVersionRec,
+ xf86SumPlug,
+ xf86SumUnplug
+};
+
+#endif /* XFree86LOADER */
+#endif /* XFREE86_V4 */
+
+/* end of xf86DigitalEdge.c */