📄 xf86onetouch.c
字号:
/* * Copyright 2000-2003 by Alessandro Rubini <rubini@linux.it> * somehow based on xf86Summa.c: * Copyright 1996 by Steven Lang <tiger@tyger.org> * * This work is sponsored by Automata S.p.A, Cannon group. * It is also based on previous work of mine sponsored by Gunze-USA. * * 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 the authors not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. The authors make no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * THE AUTHORS DISCLAIM 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. *//* $XFree86: <I think this string is added by official archiving> */static const char identification[] = "$Identification: What? $";#include <xf86Version.h>#if XF86_VERSION_MAJOR > 3#define XFREE86_V4#else#error "Versions of X less than 4 are not supported by this module"#endif#include <fcntl.h>#ifndef XFree86LOADER#include <unistd.h>#include <errno.h>#endif#include <misc.h>#include <xf86.h>#define NEED_XF86_TYPES#if !defined(DGUX)#include <xf86_ansic.h>#include <xisb.h>#endif#include <xf86_OSproc.h>#include <xf86Xinput.h>#include <exevents.h> /* Needed for InitValuator/Proximity stuff */#include <keysym.h>#include <mipointer.h>#ifdef XFree86LOADER#include <xf86Module.h>#endif#include "calib-math.h"#undef memset#define memset xf86memset#undef sleep#define sleep(t) xf86WaitForInput(-1, 1000 * (t))#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", "StopBits", "1", "DataBits", "8", "Parity", "None", "Vmin", "1", "Vtime", "10", "FlowControl", "None", NULL};static InputDriverPtr gnzDrv;#if defined(__QNX__) || defined(__QNXNTO__)#define POSIX_TTY#endif#include "onetouch.h" /* Definitions for the led meanings *//*** Debugging macros*/#ifdef DBG#undef DBG#endif#ifdef DEBUG#undef DEBUG#endifstatic int debug_level = 0;#define DEBUG 1#if DEBUG#define DBG(lvl, f) {if ((lvl) <= debug_level) f;}#else#define DBG(lvl, f)#endif/*** Device records*/#define ONETOUCH_MAXPHYSCOORD 1023#define ONETOUCH_MAXCOORD (64*1024-1) /* oversampled, synthetic value */#define FLAG_PRE_TAPPING 1 /* this is motion, despite being pen-down */#define FLAG_WAS_UP 2 /* last event was a pen-up event */#define ONETOUCH_DEFAULT_TAPPING_DELAY 0 /* off */#define ONETOUCH_DEFAULT_JITTER_DELAY 50 /* milli Seconds *//* * Prototype for a callback to handle delayed release event. * This is handy for integrating out the on/off jitter that * the Onetouch device tends to produce during a user drag (Chris Howe) */static CARD32 touchButtonTimer(OsTimerPtr timer, CARD32 now, pointer arg); typedef struct { char *onetDevice; /* device file name */ int flags; /* various flags */ int onetBaud; /* 9600 or 19200 */ int onetDlen; /* data length (3 or 11) */ int onetAvgX; /* previous X position */ int onetAvgY; /* previous Y position */ int onetSmooth; /* how smooth the motion is */ int onetPrevButton; /* previous button state */ int onetBytes; /* number of bytes read */ int onetButton; /* 0 (default), 1, 2, -1, -2 for "once" */ unsigned char onetData[16]; /* data read on the device */ double onetCalib[6]; /* Calibration parameters */ char *onetConfig; /* filename for configuration */ int onetJitterDelay; /* time to delay before issuing a buttonup */ int onetTappingDelay; /* longer hops are not considered ticks */ long onetUpSec; /* when did pen-up happen */ long onetUpUsec; /* when did pen-up happen */ LedCtrl *onetLeds; OsTimerPtr timer;} OnetouchDeviceRec, *OnetouchDevicePtr;#define ONETOUCH_SERIAL_DLEN 11#define ONETOUCH_PS2_DLEN 3/*** Configuration data*/#define ONETOUCH_SECTION_NAME "Onetouch"#define ONETOUCH_DEFAULT_CFGFILE "/etc/onetouch.calib"/*** Contants and macro*/#define BUFFER_SIZE 120 /* size of reception buffer */#define XI_NAME "ONETOUCH" /* X device name for the touch screen */#define MSGID "xf86Onetouch: "#define SYSCALL(call) while(((call) == -1) && (errno == EINTR))/*** xf86OnetouchConvert** Convert valuators to X and Y. Since calibration data has already been used,** this only requires downscaling to screen size*/static Boolxf86OnetouchConvert(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 / (ONETOUCH_MAXCOORD); *y = v1 * screenInfo.screens[0]->height / (ONETOUCH_MAXCOORD); if (*x < 0) *x = 0; if (*y < 0) *y = 0; if (*x > screenInfo.screens[0]->width-1) *x = screenInfo.screens[0]->width-1; if (*y > screenInfo.screens[0]->height-1) *y = screenInfo.screens[0]->height-1; DBG(6, ErrorF("Adjusted coords x=%d y=%d\n", *x, *y)); return TRUE;}/*** xf86OnetouchReadInput** Reads from the touch screen, uses calibration data** and posts any new events to the server.*/static voidxf86OnetouchReadInput(LocalDevicePtr local){ OnetouchDevicePtr priv = (OnetouchDevicePtr) local->private; unsigned char * pkt = priv->onetData; int len, loop; int x, y, button; double * calib = priv->onetCalib; DeviceIntPtr device; unsigned char buffer[BUFFER_SIZE]; static int oldbytes; /* bytes left over on the buffer */ static unsigned char up_packet[] = "\xff\xfe\xfe"; #define up_size 3 long sec, usec; DBG(7, ErrorF("xf86OnetouchReadInput BEGIN device=%s fd=%d (bytes %i)\n", priv->onetDevice, local->fd, priv->onetBytes)); oldbytes = priv->onetBytes; priv->onetBytes = 0; memcpy(buffer, pkt, oldbytes); SYSCALL(len = read(local->fd, buffer+oldbytes, sizeof(buffer)-oldbytes)); if (len <= 0) { Error("error reading Onetouch touch screen device"); return; } len += oldbytes; /* * Serial protocol: * 0xff, <lowx>, <highx>, <lowy>, <highy> (5b) * 0xff, 0xfe, 0xfe (3b) == release */ for (loop = 0; loop < len; ) { /* resync, in case we lost something */ if (buffer[loop] != 0xff) { loop++; if (loop == len) { oldbytes = 0; return; } } /* check if not enough data for a packet */ if ( len-loop < 3 || (strncmp(buffer+loop, up_packet, up_size) && len-loop < 5)) { DBG(6, ErrorF("short (%i) %02x %02x %02x\n", len-loop, buffer[loop], buffer[loop+1],buffer[loop+2])); if (loop) memcpy(priv->onetData, buffer+loop, len-loop); priv->onetBytes = len-loop; return; } /* handle the 3-byte packet */ if (len-loop >= 3 && !strncmp(buffer+loop, up_packet, up_size)) { /* If there is further data, ignore this up event */ if (len-loop > 4 && buffer[loop+3] == 0xff) { loop += 3; continue; } /* * The user has let go of the touchpad, but we dont know * if this is a bounce or a real button up event. Set up * a timer to fire off the button up event unless something * else happens (Chris Howe) */ xf86getsecs(&priv->onetUpSec, &priv->onetUpUsec); /* tap info */ if (priv->onetJitterDelay) { priv->timer = TimerSet( priv->timer, 0, priv->onetJitterDelay /* delay */, touchButtonTimer, local); } loop += 3; continue; } /* * everything from here onwards is about the 5-byte packet */ x = buffer[loop+1] + (buffer[loop+2]<<8); y = buffer[loop+3] + (buffer[loop+4]<<8); /* calibration leads to values that span 16 bits like before */ x = (int)(calib[0]*(double)x + calib[1]*(double)y + calib[2]); y = (int)(calib[3]*(double)x + calib[4]*(double)y + calib[5]); button = 1; /* smooth it down, unless first touch */ if (!(priv->flags & FLAG_WAS_UP)) { x = (priv->onetAvgX * priv->onetSmooth + x)/(priv->onetSmooth+1); y = (priv->onetAvgY * priv->onetSmooth + y)/(priv->onetSmooth+1); } /* FIXME: this isn't coordinated with debouncing */ if (!button) priv->flags |= FLAG_WAS_UP; else priv->flags &= ~FLAG_WAS_UP; DBG(6, ErrorF("Cooked: %5i, %5i (%i)\n", x, y, !!button)); /* Now send events */ device = local->dev; if ( (priv->onetAvgX != x) || (priv->onetAvgY != y) ) { xf86PostMotionEvent(device, 1 /* absolute */, 0, 2, x, y); } /* * If we were in an up state and now we are in a down state * consider sending a button down event. */ if (!priv->onetPrevButton) { if( priv->timer ) { /* * Uh-oh. We have detected a bounce. Cancel the timer * and do not send a button event. */ TimerFree( priv->timer ); priv->timer = NULL; } else { int deltams = 0; /* No timer: real touchdown. Is this pre-tap? */ xf86getsecs(&sec, &usec); deltams = (sec - priv->onetUpSec) * 1000 + (usec - priv->onetUpUsec) / 1000; if (!priv->onetTappingDelay || (deltams < priv->onetTappingDelay)) { int b = priv->onetButton; if (b < 0) b = -b; xf86PostButtonEvent(device, 1 /* absolute */, b+1 /* button, 0 is b1 etc */, 1 /* isdown */, 0, 2, x, y); DBG(1, ErrorF("Post button %i\n", b+1)); } else { priv->flags |= FLAG_PRE_TAPPING; DBG(1, ErrorF("Pre-tapping\n")); } } } /* remember data */ priv->onetPrevButton = button; priv->onetAvgX = x; priv->onetAvgY = y; loop += 5; } priv->onetBytes = len - loop; memcpy(priv->onetData, buffer+loop, len-loop); return;}/* send a button event after a delay */static CARD32touchButtonTimer(OsTimerPtr timer, CARD32 now, pointer arg){ LocalDevicePtr local = (LocalDevicePtr) arg; OnetouchDevicePtr priv = (OnetouchDevicePtr)(local->private); int sigstate; int b = priv->onetButton; if (b < 0) b = -b; sigstate = xf86BlockSIGIO(); xf86PostButtonEvent(local->dev, 1 /* absolute */, b+1 /* button */, 0 /* isdown */, 0, 2, priv->onetAvgX, priv->onetAvgY); xf86UnblockSIGIO(sigstate); if (priv->onetButton < 0) { /* "once" done, reset it */ priv->onetLeds->led_values = 0; priv->onetButton = 0; } priv->onetPrevButton = 0; priv->flags &= ~FLAG_PRE_TAPPING; DBG(1, ErrorF("Post delayed button-up %i\n", b+1)); priv->timer = NULL; return(0);}/*** xf86OnetouchControlProc** This is called for each device control that is defined at init time.** It currently isn't use, but I plan to make tapping, smoothness and** on/off available as integer device controls.*/static voidxf86OnetouchControlProc(DeviceIntPtr device, PtrCtrl *ctrl){ DBG(2, ErrorF("xf86OnetouchControlProc\n"));}/* Read the configuration file or revert to default (identity) cfg */static int xf86OnetouchReadCalib(OnetouchDevicePtr priv, int activate){ int i, err = 1; static int numbers[10]; FILE *f; double precision; /* unused by now */ f = fopen(priv->onetConfig, "r"); if (f) { char s[80]; fgets(s, 80, f); /* discard the comment */ for (i=0; i<10; i++) err = fscanf(f, "%i", numbers+i); err = (err == 1) ? 0 : 1; /* 1 means ok, 0 or -1 means error */ fclose(f); } if (err) ErrorF(MSGID "Calibration data absent or invalid, using defaults\n"); if (!err) { /* ok, we now have the 10 raw values, convert them */ err = official_5p_calibration( 1<<16, 1<<16, /* 64k range */ numbers, priv->onetCalib, &precision); } if (err || !activate) { /* LED_UNCALIBRATE passes through here, to avoid duplication */ memset(priv->onetCalib, 0, 6 * sizeof(double)); priv->onetCalib[0] = 1.0; /* X = 1*x + 0*y + 0 */ priv->onetCalib[4] = 1.0; /* Y = 0*x + 1*y + 0 */ return 0; } ErrorF(MSGID "Calibration data valid\n"); ErrorF(MSGID "Calibration: X = %f x + %f y + %f\n", priv->onetCalib[0], priv->onetCalib[1], priv->onetCalib[2]); ErrorF(MSGID "Calibration: Y = %f x + %f y + %f\n", priv->onetCalib[3], priv->onetCalib[4], priv->onetCalib[5]); return 0;}/* * This feedback function is used to get commands from a client application */static void xf86OnetouchLeds(DeviceIntPtr dev, LedCtrl *ctrl){ LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate; OnetouchDevicePtr priv = (OnetouchDevicePtr)local->private; int cmd; if (!priv->onetLeds) { /* fist time */ priv->onetLeds = ctrl; ctrl->led_mask = ~0; } DBG(9, ErrorF(MSGID "ledfeedback %x %x\n", ctrl->led_values, ctrl->led_mask)); cmd = ctrl->led_values & ctrl->led_mask; if (cmd & OTLED_UNCALIBRATE) { /* remove calibration, used before making a new calibration */ xf86OnetouchReadCalib(priv, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -