/* * Copyright 2004 by Kenan Esau , Baltmannsweiler, * Germany. * * 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 names of copyright holders not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. The copyright holders * make no representations about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. * * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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. * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #define _evdev_touch_C_ /***************************************************************************** * Standard Headers ****************************************************************************/ #define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) #include #include #include #define NEED_XF86_TYPES #include #include #include #include #include #include /***************************************************************************** * Local Headers ****************************************************************************/ #include "libtouch.h" #include "evtouch.h" /***************************************************************************** * Variables without includable headers ****************************************************************************/ /***************************************************************************** * Local Variables ****************************************************************************/ static InputInfoPtr EVTouchPreInit(InputDriverPtr drv, IDevPtr dev, int flags); static int debug_level = 0; InputDriverRec EVTOUCH = { 1, "evtouch", NULL, EVTouchPreInit, /*EVTouchUnInit*/ NULL, NULL, 0 }; #ifdef XFree86LOADER ModuleInfoRec EVTouchInfo = { 1, "EVTOUCH", NULL, 0, NULL /*EVTouchAvailableOptions*/, }; static XF86ModuleVersionInfo VersionRec = { "evtouch", "Kenan Esau", MODINFOSTRING1, MODINFOSTRING2, XF86_VERSION_CURRENT, 0, 8, 3, ABI_CLASS_XINPUT, ABI_XINPUT_VERSION, MOD_CLASS_XINPUT, {0, 0, 0, 0} /* signature, to be patched into the file by * a tool */ }; static pointer Plug( pointer module, pointer options, int *errmaj, int *errmin ) { xf86AddModuleInfo(&EVTouchInfo, module); xf86AddInputDriver(&EVTOUCH, module, 0); return module; } static void Unplug(pointer p) { DBGOUT(1, "EVTouch: Unplug\n"); } XF86ModuleData evtouchModuleData = {&VersionRec, Plug, Unplug }; #endif /* XFree86LOADER */ static const char *default_options[] = { "BaudRate", "9600", "StopBits", "1", "DataBits", "8", "Parity", "None", "Vmin", "5", "Vtime", "1", "FlowControl", "None" }; static void ControlProc(DeviceIntPtr device, PtrCtrl *ctrl); /***************************************************************************** * Function Definitions ****************************************************************************/ static CARD32 emulate3Timer(OsTimerPtr timer, CARD32 now, pointer _local) { int sigstate; DBGOUT(2,"EVTouch: %s\n", __FUNCTION__); LocalDevicePtr local = (LocalDevicePtr)_local; EVTouchPrivatePtr priv = (EVTouchPrivatePtr) local->private; sigstate = xf86BlockSIGIO(); xf86PostMotionEvent(local->dev, TRUE, 0, 2, priv->cur_x, priv->cur_y); /* * Emit a button press -- release is handled in EVTouchLBRBEvent */ if ( ( priv->touch_flags & LB_STAT ) && !( priv->touch_flags & RB_STAT ) ) { DBGOUT(2, "EVTouch: Left Press\n"); xf86PostButtonEvent (local->dev, TRUE, 1, 1, 0, 2, priv->cur_x, priv->cur_y); } if ( ( priv->touch_flags & RB_STAT ) && !( priv->touch_flags & LB_STAT ) ) { DBGOUT(2, "EVTouch: Right Press\n"); xf86PostButtonEvent (local->dev, TRUE, 3, 1, 0, 2, priv->cur_x, priv->cur_y); } /* Handling "middle" button press */ if ( ( priv->touch_flags & RB_STAT ) && ( priv->touch_flags & LB_STAT ) ) { DBGOUT(2, "EVTouch: Middle Press\n"); xf86PostButtonEvent (local->dev, TRUE, 2, 1, 0, 2, priv->cur_x, priv->cur_y); } priv->emulate3_timer_expired = TRUE; xf86UnblockSIGIO(sigstate); return 0; } void EVTouchProcessAbs(EVTouchPrivatePtr priv) { struct input_event *ev; /* packet being/just read */ ev = &priv->ev; priv->old_x = priv->cur_x; priv->old_y = priv->cur_y; if (ev->code == ABS_X) { priv->cur_x = ev->value; libtouchSetXPos(priv->libtouch, priv->cur_x); } if (ev->code == ABS_Y) { priv->cur_y = ev->value; libtouchSetYPos(priv->libtouch, priv->cur_y); } if (ev->code == ABS_WHEEL) { LocalDevicePtr local = priv->local; if (ev->value > 0) { for (; ev->value > 0; ev->value--) { xf86PostButtonEvent (local->dev, TRUE, 4, 1, 0, 2, priv->cur_x, priv->cur_y); xf86PostButtonEvent (local->dev, TRUE, 4, 0, 0, 2, priv->cur_x, priv->cur_y); } } else if (ev->value < 0) { for (ev->value = -ev->value; ev->value > 0; ev->value--) { xf86PostButtonEvent (local->dev, TRUE, 5, 1, 0, 2, priv->cur_x, priv->cur_y); xf86PostButtonEvent (local->dev, TRUE, 5, 0, 0, 2, priv->cur_x, priv->cur_y); } } } } void EVTouchProcessRel(EVTouchPrivatePtr priv) { struct input_event *ev; /* packet being/just read */ ev = &priv->ev; priv->old_x = priv->cur_x; priv->old_y = priv->cur_y; if ( ev->code == REL_X ) { priv->cur_x += ev->value; if (priv->cur_x > priv->max_x) priv->cur_x = priv->max_x; if (priv->cur_x < priv->min_x) priv->cur_x = priv->min_x; return; } if ( ev->code == REL_Y ) { priv->cur_y += ev->value; if (priv->cur_y > priv->max_y) priv->cur_y = priv->max_y; if (priv->cur_y < priv->min_y) priv->cur_y = priv->min_y; return; } libtouchSetPos(priv->libtouch, priv->cur_x, priv->cur_y); } void EVTouchLBRBEvent(EVTouchPrivatePtr priv) { struct input_event *ev; /* packet being/just read */ LocalDevicePtr local = priv->local; static OsTimerPtr emulate3_timer = NULL; int btn = 0; ev = &priv->ev; DBGOUT(2, "EVTouch: %s\n", __FUNCTION__); if (priv->emulate3) { if ( (ev->value==1) && (emulate3_timer==NULL) ) emulate3_timer = TimerSet(emulate3_timer, 0, priv->emulate3_timeout, emulate3Timer, local); if ( (ev->value == 1) && (ev->code == BTN_LEFT) ) priv->touch_flags |= LB_STAT; if ( (ev->value == 1) && (ev->code == BTN_RIGHT) ) priv->touch_flags |= RB_STAT; if ( (ev->value == 0) && (priv->touch_flags & RB_STAT) && (priv->touch_flags & LB_STAT) ) { DBGOUT(2, "EVTouch: Middle Release\n"); priv->touch_flags &= ~LB_STAT; priv->touch_flags &= ~RB_STAT; btn = 2; } else if ( (ev->value == 0) && (ev->code == BTN_LEFT) && (priv->touch_flags & LB_STAT) ) { DBGOUT(2, "EVTouch: Left Release\n"); priv->touch_flags &= ~LB_STAT; btn = 1; } else if ( (ev->value == 0) && (ev->code == BTN_RIGHT) && (priv->touch_flags & RB_STAT) ) { DBGOUT(2, "EVTouch: Right Release\n"); priv->touch_flags &= ~RB_STAT; btn = 3; } if (ev->value == 0) { TimerFree(emulate3_timer); emulate3_timer=NULL; priv->emulate3_timer_expired = FALSE; xf86PostButtonEvent(local->dev, TRUE, btn, ev->value, 0, 2, priv->cur_x, priv->cur_y); } } else { if (ev->code == BTN_LEFT) { xf86PostButtonEvent(local->dev, TRUE, 1, ev->value, 0, 2, priv->cur_x, priv->cur_y); } if (ev->code == BTN_MIDDLE) { xf86PostButtonEvent(local->dev, TRUE, 2, ev->value, 0, 2, priv->cur_x, priv->cur_y); } if (ev->code == BTN_RIGHT) { xf86PostButtonEvent (local->dev, TRUE, 3, ev->value, 0, 2, priv->cur_x, priv->cur_y); } } } void EVTouchProcessKey(EVTouchPrivatePtr priv) { struct input_event *ev; /* packet being/just read */ DBGOUT(2, "EVTouch: %s\n", __FUNCTION__); ev = &priv->ev; if ( (ev->code == BTN_LEFT) || (ev->code == BTN_RIGHT) || (ev->code == BTN_MIDDLE) ) { /* give lb and rb-events some special treatment (emulate3 or not, ...) */ EVTouchLBRBEvent(priv); return; } #ifdef _0_ switch (ev->code) { case BTN_SIDE: break; case BTN_EXTRA: break; case BTN_FORWARD: break; case BTN_BACK: break; case BTN_TASK: break; default: return; } xf86PostButtonEvent(local->dev, TRUE, btn, ev->value, 0, 2, priv->cur_x, priv->cur_y); #endif return; } static Bool DeviceOn (DeviceIntPtr dev) { LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private); local->fd = xf86OpenSerial(local->options); DBGOUT(2, "EVTouch: Device ON\n"); if (local->fd == -1) { xf86Msg(X_WARNING, "%s: cannot open input device\n", local->name); return (!Success); } priv->buffer = XisbNew(local->fd, 64); if (!priv->buffer) { xf86CloseSerial(local->fd); local->fd = -1; return (!Success); } xf86FlushInput(local->fd); #ifndef XFREE86_V4 xf86AddEnabledDevice(local); #else AddEnabledDevice(local->fd); #endif dev->public.on = TRUE; return (Success); } static Bool DeviceOff (DeviceIntPtr dev) { LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private); DBGOUT(2, "EVTouch: Device OFF\n"); if (local->fd != -1) { xf86RemoveEnabledDevice (local); if (priv->buffer) { XisbFree(priv->buffer); priv->buffer = NULL; } xf86CloseSerial(local->fd); } xf86RemoveEnabledDevice (local); dev->public.on = FALSE; if ( (priv->calibrate) && (priv->fifo>0) ){ SYSCALL(close (priv->fifo)); } return (Success); } static Bool DeviceInit (DeviceIntPtr dev) { LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private); unsigned char map[] = {0, 1, 2, 3, 4, 5}; /* * these have to be here instead of in the SetupProc, because when the * SetupProc is run at server startup, screenInfo is not setup yet */ ScrnInfoPtr pScrn = xf86Screens[priv->screen_num]; priv->phys_width = pScrn->currentMode->HDisplay; /* physical screen resolution */ priv->phys_height = pScrn->currentMode->VDisplay; priv->screen_width = pScrn->virtualX; /* It's the virtual screen size ! */ priv->screen_height = pScrn->virtualY; priv->pViewPort_X0 = &(pScrn->frameX0); /* initialize the pointers to the viewport coords */ if ( (priv->screen_width != priv->phys_width) || (priv->screen_height != priv->phys_height) ) priv->virtual = 1; else priv->virtual = 0; priv->pViewPort_Y0 = &(pScrn->frameY0); priv->pViewPort_X1 = &(pScrn->frameX1); priv->pViewPort_Y1 = &(pScrn->frameY1); DBGOUT(2, "EVTouch: DeviceInit\n"); DBGOUT(2, "EVTouch: Display X,Y: %d %d\n", priv->phys_width, priv->phys_height); DBGOUT(2, "EVTouch: Virtual X,Y: %d %d\n", priv->screen_width, priv->screen_height); DBGOUT(2, "EVTouch: DriverName, Rev.: %s %d\n", pScrn->driverName, pScrn->driverVersion); DBGOUT(2, "EVTouch: Viewport X0,Y0: %d %d\n", *priv->pViewPort_X0, *priv->pViewPort_Y0); DBGOUT(2, "EVTouch: Viewport X1,Y1: %d %d\n", *priv->pViewPort_X1, *priv->pViewPort_Y1); DBGOUT(2, "EVTouch: MaxValue H,V: %d %d\n", pScrn->maxHValue, pScrn->maxVValue); priv->screen_width = screenInfo.screens[priv->screen_num]->width; priv->screen_height = screenInfo.screens[priv->screen_num]->height; if (InitPtrFeedbackClassDeviceStruct((DeviceIntPtr) dev, ControlProc) == FALSE) { ErrorF("Unable to init ptr feedback for EVTouch\n"); return !Success; } /* * Device reports button press for 5 buttons. */ if (InitButtonClassDeviceStruct (dev, 5, map) == FALSE) { ErrorF("Unable to allocate EVTouch touchscreen ButtonClassDeviceStruct\n"); return !Success; } if (InitFocusClassDeviceStruct(dev) == FALSE) { ErrorF("Unable to allocate EVTouch touchscreen FocusClassDeviceStruct\n"); return !Success; } /* * Device reports motions on 2 axes in absolute coordinates. * Axes min and max values are reported in raw coordinates. */ if (InitValuatorClassDeviceStruct(dev, 2, xf86GetMotionEvents, local->history_size, Absolute) == FALSE) { ErrorF ("Unable to allocate EVTouch touchscreen ValuatorClassDeviceStruct\n"); return !Success; } else { InitValuatorAxisStruct (dev, 0, priv->min_x, priv->max_x, 1024, EV_AXIS_MIN_RES /* min_res */ , EV_AXIS_MAX_RES /* max_res */ ); InitValuatorAxisStruct (dev, 1, priv->min_y, priv->max_y, 1024, EV_AXIS_MIN_RES /* min_res */ , EV_AXIS_MAX_RES /* max_res */ ); } /* Initial position of pointer on screen: Centered */ priv->cur_x=(priv->max_x - priv->min_x)/2; priv->cur_y=(priv->max_y - priv->min_y)/2; libtouchSetPos(priv->libtouch, priv->cur_x, priv->cur_y); if (InitProximityClassDeviceStruct (dev) == FALSE) { ErrorF ("Unable to allocate EVTouch touchscreen ProximityClassDeviceStruct\n"); return !Success; } /* * Allocate the motion events buffer. */ xf86MotionHistoryAllocate (local); return (Success); } static Bool DeviceControl (DeviceIntPtr dev, int mode) { Bool RetValue; switch (mode) { case DEVICE_INIT: DeviceInit(dev); RetValue = Success; break; case DEVICE_ON: RetValue = DeviceOn(dev); break; case DEVICE_OFF: case DEVICE_CLOSE: RetValue = DeviceOff(dev); break; default: RetValue = BadValue; } return( RetValue ); } static void EVTouchNewPacket (EVTouchPrivatePtr priv) { xf86memset(&priv->ev, 0, sizeof(struct input_event)); priv->packeti = 0; priv->binary_pkt = FALSE; } static unsigned char EVTouchRead(EVTouchPrivatePtr priv) { unsigned char c; XisbBlockDuration (priv->buffer, EV_TIMEOUT); c = XisbRead(priv->buffer); return (c); } static Bool EVTouchGetPacket (EVTouchPrivatePtr priv) { static int count = 0; int c; CARD32 now; if (count==0) EVTouchNewPacket(priv); while ((c = XisbRead(priv->buffer)) >= 0) { if (count == 0) { now = GetTimeInMillis(); libtouchSetTime(priv->libtouch, now); } ((char *)&priv->ev)[count] = c; count ++; if (sizeof(priv->ev) == count) { count = 0; EVTouchDumpPacketToLog(priv); return Success; } } return (!Success); } static void ReadInput (LocalDevicePtr local) { struct input_event *ev; /* packet being/just read */ EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private); /* * 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 buy a select with a 0 timeout to prevent * read from blocking infinately. */ XisbBlockDuration (priv->buffer, -1); while (EVTouchGetPacket (priv) == Success) { ev = &priv->ev; xf86XInputSetScreen(local, priv->screen_num, priv->cur_x, priv->cur_y); xf86PostProximityEvent(local->dev, 1, 0, 2, priv->cur_x, priv->cur_y); priv->old_x = priv->cur_x; priv->old_y = priv->cur_y; switch (ev->type) { case EV_ABS: EVTouchProcessAbs(priv); break; case EV_REL: EVTouchProcessRel(priv); break; case EV_KEY: if (priv->ev.code == BTN_TOUCH) { if (priv->ev.value == 1) { priv->touch_flags |= TOUCHED; DBGOUT(2, "EVTouch: TOUCHED\n"); } else { priv->touch_flags &= ~TOUCHED; DBGOUT(2, "EVTouch: UNTOUCHED\n"); } } break; case EV_SYN: if ( priv->touch_flags & TOUCHED ) libtouchTriggerSM(priv->libtouch, PEN_TOUCHED); else libtouchTriggerSM(priv->libtouch, PEN_UNTOUCHED); break; } DBGOUT( 2, "EVTouch: setting (x/y)=(%d/%d)\n", priv->cur_x, priv->cur_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. */ xf86PostMotionEvent (local->dev, TRUE, 0, 2, priv->cur_x, priv->cur_y); if (ev->type == EV_KEY) EVTouchProcessKey(priv); } } static void ControlProc(DeviceIntPtr device, PtrCtrl *ctrl) { DBGOUT(2, "EVTouch: ControlProc\n"); } static void CloseProc (LocalDevicePtr local) { xf86ErrorFVerb(2, "CLOSEPROC\n" ); } static int SwitchMode (ClientPtr client, DeviceIntPtr dev, int mode) { LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate; EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private); if ((mode == TS_Raw) || (mode == TS_Scaled)) { priv->reporting_mode = mode; return (Success); } else if ((mode == SendCoreEvents) || (mode == DontSendCoreEvents)) { xf86XInputSetSendCoreEvents (local, (mode == SendCoreEvents)); return (Success); } else return (!Success); } 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 ) { /* correction factors depending on current position of pointer */ float cx[3]; float cy[3]; float dx = 0, dy = 0; int max_x, max_y; int xc, yc; int screen_width = 0; int screen_height = 0; #ifdef EVDBG int i = 0; #endif EVTouchPrivatePtr priv = (EVTouchPrivatePtr) (local->private); DBGOUT(2, "FIRST: v0=%d v1=%d\n", v0, v1); /*correction of raw coordinates*/ if ( (priv->fifo>0) && (priv->calibrate) ){ DBGOUT(2, "writing to FIFO\n"); SYSCALL(write (priv->fifo, &v0, sizeof(v0))); SYSCALL(write (priv->fifo, &v1, sizeof(v1))); } if (!priv->calibrate) { xc = v0 - priv->min_x; yc = v1 - priv->min_y; max_x = priv->max_x - priv->min_x; max_y = priv->max_y - priv->min_y; if (priv->rotate == EV_ROTATE_NONE) { screen_width = priv->phys_width; screen_height = priv->phys_height; } else { screen_width = priv->phys_height; screen_height = priv->phys_width; } if (xc < (max_x / 2)) { /* left */ if (yc>(max_y / 2)) { /* upper */ cx[1] = ((float) xc / (max_x / 2) ); cx[0] = (float) 1 - cx[1]; cy[0] = ((float) (yc-(max_y/2)) / (max_y/2) ); cy[1] = (float) 1 - cy[0]; dx = ((float) (cx[1] * cy[0] * priv->diff[1][0]) + (float)(cx[0] * cy[0] * priv->diff[0][0]) + (float)(cx[1] * cy[1] * priv->diff[4][0]) + (float)(cx[0] * cy[1] * priv->diff[3][0])); dy = ((float) (cx[1] * cy[0] * priv->diff[1][1]) + (float)(cx[0] * cy[0] * priv->diff[0][1]) + (float)(cx[1] * cy[1] * priv->diff[4][1]) + (float)(cx[0] * cy[1] * priv->diff[3][1])); } else { /* lower */ cx[1] = ((float) xc / (max_x/2) ); cx[0] = (float) 1 - cx[1]; cy[0] = ((float) yc / (max_y/2) ); cy[1] = (float) 1 - cy[0]; dx = ((float) (cx[1] * cy[0] * priv->diff[4][0]) + (float)(cx[0] * cy[0] * priv->diff[3][0]) + (float)(cx[1] * cy[1] * priv->diff[7][0]) + (float)(cx[0] * cy[1] * priv->diff[6][0])); dy = ((float) (cx[1] * cy[0] * priv->diff[4][1]) + (float)(cx[0] * cy[0] * priv->diff[3][1]) + (float)(cx[1] * cy[1] * priv->diff[7][1]) + (float)(cx[0] * cy[1] * priv->diff[6][1])); } } else { /* right */ if (yc>(max_y/2)) { /* upper */ cx[1] = ((float) (xc-(max_x/2)) / (max_x/2) ); cx[0] = (float)1 - cx[1]; cy[0] = ((float) (yc-(max_y/2)) / (max_y/2) ); cy[1] = (float)1 - cy[0]; dx = ((float) (cx[1] * cy[0] * priv->diff[2][0]) + (float)(cx[0] * cy[0] * priv->diff[1][0]) + (float)(cx[1] * cy[1] * priv->diff[5][0]) + (float)(cx[0] * cy[1] * priv->diff[4][0])); dy = ((float) (cx[1] * cy[0] * priv->diff[2][1]) + (float)(cx[0] * cy[0] * priv->diff[1][1]) + (float)(cx[1] * cy[1] * priv->diff[5][1]) + (float)(cx[0] * cy[1] * priv->diff[4][1])); DBGOUT(2, "TEST: dx=%f dy=%f\n", dx, dy); } else { /* lower */ cx[1] = ((float) (xc-(max_x/2)) / (max_x/2) ); cx[0] = (float) 1 - cx[1]; cy[0] = ((float) yc / (max_y/2) ); cy[1] = (float) 1 - cy[0]; dx = ((float) (cx[1] * cy[0] * priv->diff[5][0]) + (float)(cx[0] * cy[0] * priv->diff[4][0]) + (float)(cx[1] * cy[1] * priv->diff[8][0]) + (float)(cx[0] * cy[1] * priv->diff[7][0])); dy = ((float) (cx[1] * cy[0] * priv->diff[5][1]) + (float)(cx[0] * cy[0] * priv->diff[4][1]) + (float)(cx[1] * cy[1] * priv->diff[8][1]) + (float)(cx[0] * cy[1] * priv->diff[7][1])); } } #ifdef EVDBG for (i=0; i<3; i++) xf86ErrorFVerb(2, "cx[%d]=%f cy[%d]=%f\n", i, cx[i] ,i, cy[i]); DBGOUT(2, "ViewPort_X0=%d ViewPort_Y0=%d\n", *(priv->pViewPort_X0), *(priv->pViewPort_Y0)); DBGOUT(2, "dx=%f dy=%f\n", dx, dy); #endif xc = ( ((float)xc / max_x) * screen_width ) + dx; yc = ( ((float)yc / max_y) * screen_height) + dy; if (priv->swap_y == TRUE) yc = screen_height - yc; /* ususally we DON'T swap x -- but if swap_x is 1 => go on and swap */ if (priv->swap_x == TRUE) xc = screen_width - xc; /* rotation mixes x and y up a bit */ if (priv->rotate == EV_ROTATE_CW) { v0 = yc; v1 = screen_width - xc; } else if (priv->rotate == EV_ROTATE_CCW) { v0 = screen_height - yc; v1 = xc; } else { v0 = xc; v1 = yc; } } DBGOUT(2, "FINAL: v0=%d v1=%d\n", v0, v1); *x = v0; *y = v1; return (TRUE); } static Bool QueryHardware (LocalDevicePtr local) { xf86ErrorFVerb(2, "QUERY HARDWARE\n" ); return Success; } static InputInfoPtr EVTouchPreInit(InputDriverPtr drv, IDevPtr dev, int flags) { /* LocalDevicePtr local; */ InputInfoPtr local; EVTouchPrivatePtr priv; int i = 0; char *s; char tmp_str[8]; int timeo = 0; priv = xcalloc (1, sizeof (EVTouchPrivateRec)); if (!priv) return NULL; local = xf86AllocateInput(drv, 0); if (!local) { xfree(priv); return NULL; } local->name = dev->identifier; local->type_name = XI_TOUCHSCREEN; local->device_control = DeviceControl; local->read_input = ReadInput; local->control_proc = NULL; /* ControlProc; */ local->close_proc = CloseProc; local->switch_mode = SwitchMode; local->conversion_proc = ConvertProc; local->reverse_conversion_proc = NULL; local->fd = -1; local->dev = NULL; local->private = priv; priv->local = local; local->private_flags = 0; local->flags = XI86_POINTER_CAPABLE | XI86_SEND_DRAG_EVENTS; local->conf_idev = dev; xf86CollectInputOptions(local, default_options, NULL); xf86OptionListReport(local->options); local->fd = xf86OpenSerial (local->options); if (local->fd == -1) { ErrorF ("EVTouch driver unable to open device\n"); goto SetupProc_fail; } xf86ErrorFVerb( 3, "evdev device opened successfully\n" ); priv->libtouch = xcalloc(1, sizeof(LibTouchRec)); libtouchInit(priv->libtouch, local); priv->calibrate = xf86SetIntOption(local->options, "Calibrate", 0); priv->min_x = xf86SetIntOption(local->options, "MinX", 0 ); priv->max_x = xf86SetIntOption(local->options, "MaxX", EV_SCREEN_WIDTH ); priv->min_y = xf86SetIntOption(local->options, "MinY", 0 ); priv->max_y = xf86SetIntOption(local->options, "MaxY", EV_SCREEN_HEIGHT ); priv->screen_num = xf86SetIntOption(local->options, "ScreenNumber", 0 ); priv->button_number = xf86SetIntOption(local->options, "ButtonNumber", 2 ); priv->emulate3 = xf86SetBoolOption(local->options, "Emulate3Buttons", TRUE); priv->emulate3_timeout = xf86SetIntOption(local->options, "Emulate3Timeout", 50); priv->buttonless = xf86SetBoolOption(local->options, "ButtonlessDevice", FALSE); debug_level = xf86SetIntOption(local->options, "DebugLevel", 0); libtouchSetDebugLevel(debug_level); timeo = xf86SetIntOption(local->options, "TapTimer", 90); libtouchSetTapTimeo(priv->libtouch, timeo); timeo = xf86SetIntOption(local->options, "LongtouchTimer", 160); libtouchSetLongtouchTimeo(priv->libtouch, timeo); libtouchSetMoveLimit(priv->libtouch, xf86SetIntOption( local->options, "MoveLimit", 180 )); priv->rotate = EV_ROTATE_NONE; s = xf86FindOptionValue(local->options, "Rotate"); if (s) { if (xf86NameCmp(s, "CW") == 0) { priv->rotate = EV_ROTATE_CW; } else if (xf86NameCmp(s, "CCW") == 0 ) { priv->rotate = EV_ROTATE_CCW; } } if (priv->rotate == EV_ROTATE_NONE) { priv->max_rel_x = priv->max_x; priv->max_rel_y = priv->max_y; priv->min_rel_x = priv->min_x; priv->min_rel_y = priv->min_y; } else { priv->max_rel_x = priv->max_y; priv->max_rel_y = priv->max_x; priv->min_rel_x = priv->min_y; priv->min_rel_y = priv->min_x; } priv->swap_y = xf86SetBoolOption(local->options, "SwapY", FALSE); priv->swap_x = xf86SetBoolOption(local->options, "SwapX", FALSE); /* get calibration parameters from XF86Config */ for (i=0; i<9; i++){ sprintf(tmp_str, "x%d", i); priv->diff[i][0] = xf86SetIntOption( local->options, tmp_str, 0 ); sprintf(tmp_str, "y%d", i); priv->diff[i][1] = xf86SetIntOption( local->options, tmp_str, 0 ); DBGOUT(2, "(diff[%d][0]/diff[%d][1])=(%d/%d)\n", i, i, priv->diff[i][0], priv->diff[i][1]); } xf86AlwaysCore(local, TRUE); s = xf86FindOptionValue (local->options, "ReportingMode"); if ((s) && (xf86NameCmp (s, "raw") == 0)) priv->reporting_mode = TS_Raw; else priv->reporting_mode = TS_Scaled; priv->buffer = XisbNew (local->fd, 200); priv->touch_flags = 0; DBG (9, XisbTrace (priv->buffer, 1)); if (QueryHardware(local) != Success) { ErrorF ("Unable to query/initialize EVTouch hardware.\n"); goto SetupProc_fail; } local->history_size = xf86SetIntOption( local->options, "HistorySize", 0 ); /* prepare to process touch packets */ EVTouchNewPacket (priv); /* if started in calibration-mode: - open named pipe */ if (priv->calibrate) { SYSCALL(priv->fifo=open("/tmp/ev_calibrate", O_RDWR, 0)); if (priv->fifo < 0) xf86ErrorFVerb(2, "open FIFO FAILED\n"); } /* this results in an xstrdup that must be freed later */ local->name = xf86SetStrOption( local->options, "DeviceName", "EVTouch TouchScreen" ); xf86ProcessCommonOptions(local, local->options); local->flags |= XI86_CONFIGURED; if (local->fd != -1) { if (priv->buffer) { XisbFree(priv->buffer); priv->buffer = NULL; } xf86CloseSerial(local->fd); } local->fd = -1; return (local); SetupProc_fail: if ((local) && (local->fd)) xf86CloseSerial (local->fd); if ((local) && (local->name)) xfree (local->name); if ((priv) && (priv->buffer)) XisbFree (priv->buffer); if (priv) xfree (priv); return (local); }