diff options
Diffstat (limited to 'driver/xf86-input-digitaledge/src/DigitalEdge.c')
-rw-r--r-- | driver/xf86-input-digitaledge/src/DigitalEdge.c | 1427 |
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 */ |