From: jk7744.park Date: Sat, 24 Oct 2015 06:30:40 +0000 (+0900) Subject: tizen 2.4 release X-Git-Tag: accepted/tizen/2.4/mobile/20151029.042018^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Faccepted%2Ftizen_2.4_mobile;p=adaptation%2Fxorg%2Fdriver%2Fxserver-xorg-input-evdev.git tizen 2.4 release --- diff --git a/configure.ac b/configure.ac index dff2bcf..e08a1cd 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ # Initialize Autoconf AC_PREREQ([2.60]) AC_INIT([xf86-input-evdev], - [2.7.0], + [2.7.3], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xf86-input-evdev]) AC_CONFIG_SRCDIR([Makefile.am]) @@ -39,15 +39,14 @@ AC_DISABLE_STATIC AC_PROG_LIBTOOL # Initialize X.Org macros 1.8 or later for MAN_SUBSTS set by XORG_MANPAGE_SECTIONS -m4_ifndef([XORG_MACROS_VERSION], +m4_ifndef([XORG_MACROS_VERSION], [m4_fatal([must install xorg-macros 1.8 or later before running autoconf/autogen])]) XORG_MACROS_VERSION(1.8) XORG_DEFAULT_OPTIONS # Obtain compiler/linker options from server and required extensions -PKG_CHECK_MODULES(XORG, [xorg-server >= 1.10] xproto inputproto) +PKG_CHECK_MODULES(XORG, [xorg-server >= 1.10] inputproto) PKG_CHECK_MODULES(UDEV, libudev) - PKG_CHECK_MODULES(XI22, [inputproto >= 2.1.99.3] [xorg-server >= 1.11.99.901], HAVE_XI22="yes", HAVE_XI22="no") if test "x$HAVE_XI22" = xyes; then @@ -58,6 +57,11 @@ if test "x$HAVE_XI22" = xyes && test "x$HAVE_MTDEV" = xyes; then AC_DEFINE(MULTITOUCH, 1, [XI2.2 available]) fi +# Checks for ttrace header files +PKG_CHECK_MODULES(TTRACE, + [ttrace], + AC_DEFINE(ENABLE_TTRACE, 1, [ttrace available])); + # Define a configure option for an alternate input module directory AC_ARG_WITH(xorg-module-dir, AC_HELP_STRING([--with-xorg-module-dir=DIR], diff --git a/include/evdev-properties.h b/include/evdev-properties.h index c9ebacf..6695a29 100755 --- a/include/evdev-properties.h +++ b/include/evdev-properties.h @@ -96,4 +96,14 @@ #define EVDEV_PROP_TOUCH_TRANSFORM_MATRIX "Evdev Touch Transform Matrix" #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */ +#ifdef _F_SUPPORT_ROTATION_ANGLE_ +/* Real/fake Rotation angle of a touch device */ +/* CARD8, value range 0-3 : 0(0), 1 (90), 3(180), 2(270) */ +#define EVDEV_PROP_ROTATION_ANGLE "Evdev Rotation Angle" + +/* File descriptor value of rotation device node to control TSP rotation origin */ +/* CARD32, value will be between file descriptors range */ +#define EVDEV_PROP_ROTATION_NODE "Evdev Rotation Node" +#endif /* #ifdef _F_SUPPORT_ROTATION_ANGLE_ */ + #endif diff --git a/packaging/xorg-x11-drv-evdev.spec b/packaging/xorg-x11-drv-evdev.spec index 0a884ac..2ce2402 100644 --- a/packaging/xorg-x11-drv-evdev.spec +++ b/packaging/xorg-x11-drv-evdev.spec @@ -1,7 +1,7 @@ #sbs-git:slp/pkgs/xorg/driver/xserver-xorg-input-evdev xserver-xorg-input-evdev 2.3.2 1bd95071427e460187b090bc5ff5a2d880fe156a Name: xorg-x11-drv-evdev Summary: Xorg X11 evdev input driver -Version: 2.7.6.11 +Version: 2.7.6.19 Release: 3 Group: System/X Hardware Support License: MIT @@ -10,18 +10,12 @@ Source0: %{name}-%{version}.tar.gz #Requires: xorg-server Requires: xorg-x11-server-Xorg BuildRequires: pkgconfig(xorg-macros) -BuildRequires: xorg-x11-server-devel -#BuildRequires: pkgconfig(xorg-server) +BuildRequires: pkgconfig(xorg-server) BuildRequires: pkgconfig(xkbfile) -BuildRequires: pkgconfig(xproto) BuildRequires: pkgconfig(inputproto) -BuildRequires: pkgconfig(xrandr) -BuildRequires: pkgconfig(randrproto) -BuildRequires: pkgconfig(xextproto) -BuildRequires: pkgconfig(resourceproto) BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(mtdev) -BuildRequires: model-build-features +BuildRequires: pkgconfig(ttrace) Requires: libudev Requires: mtdev @@ -48,13 +42,17 @@ This package contains xorg evdev development files export CFLAGS+=" -D_ENV_MOBILE_" %else %if "%{?tizen_profile_name}" == "wearable" -export CFLAGS+=" -D_ENV_WEARABLE_" -%if "%{?model_build_feature_formfactor}" == "circle" -export CFLAGS+=" -D_F_EVDEV_SUPPORT_ROTARY_" +export CFLAGS+=" -D_ENV_WEARABLE_ -D_F_SUPPORT_ROTATION_ANGLE_ -D_F_EVDEV_SUPPORT_ROTARY_" +%else +%if "%{?tizen_profile_name}" == "tv" +export CFLAGS+=" -D_ENV_TV_ -D_F_PROXY_DEVICE_ENABLED_ -D_F_EVDEV_SUPPORT_SMARTRC_" +export CFLAGS+=" -D_F_PICTURE_OFF_MODE_ENABLE_ -D_F_DONOT_SEND_RMA_BTN_RELEASE_ -D_F_PROXY_DEVICE_CHANGE_SOURCE_ID" +export CFLAGS+=" -D_F_BLOCK_MOTION_DEVICE_ -D_F_BOOST_PULSE_ -D_F_REMAP_KEYS_ -D_F_SMART_RC_CHG_KBD_SRC_DEV_ " %endif %endif %endif %reconfigure --disable-static CFLAGS="$CFLAGS -Wall -g -D_F_EVDEV_CONFINE_REGION_ -D_F_ENABLE_DEVICE_TYPE_PROP_ -D_F_GESTURE_EXTENSION_ -D_F_TOUCH_TRANSFORM_MATRIX_ -D_F_ENABLE_REL_MOVE_STATUS_PROP_ -D_F_EVDEV_SUPPORT_GAMEPAD -D_F_USE_DEFAULT_XKB_RULES_ " + make %{?jobs:-j%jobs} %install diff --git a/src/Makefile.am b/src/Makefile.am index c5e21fc..b446b33 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,12 +25,12 @@ # _ladir passes a dummy rpath to libtool so the thing will actually link # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. -AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS) +AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS) $(TTRACE_CPPFLAGS) AM_CPPFLAGS =-I$(top_srcdir)/include @DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la -@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version -@DRIVER_NAME@_drv_la_LIBADD = $(MTDEV_LIBS) +@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version $(TTRACE_LIBS) +@DRIVER_NAME@_drv_la_LIBADD = $(MTDEV_LIBS) $(UDEV_LIBS) @DRIVER_NAME@_drv_ladir = @inputdir@ @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \ @@ -40,4 +40,6 @@ AM_CPPFLAGS =-I$(top_srcdir)/include emuWheel.c \ draglock.c \ apple.c \ - rotary.c + rotary.c \ + smartRC.c \ + proxyDev.c diff --git a/src/emuWheel.c b/src/emuWheel.c index ae894fa..db989c5 100644 --- a/src/emuWheel.c +++ b/src/emuWheel.c @@ -51,7 +51,6 @@ static Atom prop_wheel_timeout = 0; static Atom prop_wheel_button = 0; /* Local Funciton Prototypes */ -static BOOL EvdevWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char *axis_name); static int EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value); /* Filter mouse button events */ @@ -197,7 +196,8 @@ EvdevWheelEmuInertia(InputInfoPtr pInfo, WheelAxisPtr axis, int value) /* Handle button mapping here to avoid code duplication, returns true if a button mapping was found. */ static BOOL -EvdevWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char* axis_name) +EvdevWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, + const char *axis_name) { EvdevPtr pEvdev = (EvdevPtr)pInfo->private; char *option_string; diff --git a/src/evdev.c b/src/evdev.c old mode 100755 new mode 100644 index 90f6443..04d681f --- a/src/evdev.c +++ b/src/evdev.c @@ -52,6 +52,9 @@ #include #include +#ifdef _F_PROXY_DEVICE_ENABLED_ +#include +#endif //_F_PROXY_DEVICE_ENABLED_ #include #include #include @@ -90,6 +93,11 @@ #define MAXDEVICES MAX_DEVICES #endif +#ifdef _F_PICTURE_OFF_MODE_ENABLE_ +#define XI_PROP_PICTURE_OFF_MODE "PICTURE_OFF_MODE" +static Atom atomPictureOffMode; +#endif //_F_PICTURE_OFF_MODE_ENABLE_ + #define ArrayLength(a) (sizeof(a) / (sizeof((a)[0]))) #define MIN_KEYCODE 8 @@ -133,6 +141,8 @@ static int proximity_bits[] = { BTN_TOOL_LENS, }; +extern char * strcasestr(const char *haystack, const char *needle); + static int EvdevOn(DeviceIntPtr); static int EvdevCache(InputInfoPtr pInfo); static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl); @@ -140,6 +150,7 @@ static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode); static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab); static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]); static int EvdevOpenDevice(InputInfoPtr pInfo); +static void EvdevCloseDevice(InputInfoPtr pInfo); static void EvdevInitAxesLabels(EvdevPtr pEvdev, int mode, int natoms, Atom *atoms); static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms); @@ -154,6 +165,9 @@ static BOOL EvdevMTStatusGet(InputInfoPtr pInfo, MTSyncType sync); #ifdef _F_TOUCH_TRANSFORM_MATRIX_ static void EvdevSetTransformMatrix(InputInfoPtr pInfo, int num_transform, float *tmatrix); #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */ +#ifdef _F_SUPPORT_ROTATION_ANGLE_ +static void EvdevSetRotationAngle(EvdevPtr pEvdev, int angle); +#endif /* _F_SUPPORT_ROTATION_ANGLE_ */ #ifdef _F_EVDEV_CONFINE_REGION_ Bool IsMaster(DeviceIntPtr dev); DeviceIntPtr GetPairedDevice(DeviceIntPtr dev); @@ -163,12 +177,20 @@ static void EvdevHookPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, C static void EvdevHookPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox); static void EvdevSetCursorLimits(InputInfoPtr pInfo, int region[6], int isSet); static void EvdevSetConfineRegion(InputInfoPtr pInfo, int num_item, int region[6]); + +#ifdef MULTITOUCH +static int num_slots(EvdevPtr pEvdev); +#endif + +static Atom prop_confine_region = 0; +#endif /* _F_EVDEV_CONFINE_REGION_ */ #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ static CARD32 EvdevRelativeMoveTimer(OsTimerPtr timer, CARD32 time, pointer arg); #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */ +#ifdef _F_DONOT_SEND_RMA_BTN_RELEASE_ +static BOOL isButtonPressed = FALSE; +#endif //_F_DONOT_SEND_RMA_BTN_RELEASE_ -static Atom prop_confine_region = 0; -#endif /* _F_EVDEV_CONFINE_REGION_ */ static Atom prop_product_id; static Atom prop_invert; static Atom prop_calibration; @@ -184,6 +206,18 @@ static Atom prop_device_type; static Atom prop_relative_move_status; static Atom prop_relative_move_ack; #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */ + +#ifdef _F_BLOCK_MOTION_DEVICE_ +static Atom prop_block_motion_status; /* Atom to block motion device */ +int block_motion_device = 0; /* Variable to set/unset of motion device */ +#endif //_F_BLOCK_MOTION_DEVICE_ +#ifdef _F_PICTURE_OFF_MODE_ENABLE_ +int pictureOffMode; +#endif //_F_PICTURE_OFF_MODE_ENABLE_ +#ifdef _F_BOOST_PULSE_ +static int fd_boostpulse = 0; +#endif //_F_BOOST_PULSE_ + #ifdef _F_TOUCH_TRANSFORM_MATRIX_ static Atom prop_transform; #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */ @@ -192,6 +226,32 @@ static Atom prop_transform; static Atom prop_xkb_rules = None; #endif //_F_USE_DEFAULT_XKB_RULES_ +#ifdef _F_SUPPORT_ROTATION_ANGLE_ +static Atom prop_rotation_angle = 0; +static Atom prop_rotation_node = 0; +#endif //_F_SUPPORT_ROTATION_ANGLE_ + +#ifdef _F_PROXY_DEVICE_ENABLED_ +static Atom prop_use_proxy_slave_device; +static InputInfoPtr pCreatorInfo = NULL; +static InputInfoPtr pProxyDeviceInfo = NULL; +#define PROXY_DEV_NAME "HWKeys" +#define OPT_TYPE_VAL "ProxyDev" + +static int EvdevSetProxyDevice(DeviceIntPtr dev, int val); +static InputOption *EvdevOptionDupConvert(pointer original); +static void EvdevFreeInputOpts(InputOption* opts); +static void EvdevReplaceOption(InputOption *opts,const char* key, char * value); +static InputInfoPtr EvdevCreateProxyDevice(InputInfoPtr pInfo); +static void EvdevProxydevReadInput(InputInfoPtr pInfo); +static void MakeClassesChangedEvent(DeviceChangedEvent *dce, DeviceIntPtr master, DeviceIntPtr slave, int flags); +#ifndef _F_PROXY_DEVICE_CHANGE_SOURCE_ID +static void EvdevPostDevChangeEvent(InputInfoPtr pInfo); +#else /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */ +static void EvdevCheckDevChange(EvdevPtr pEvdev, int deviceid); +#endif /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */ +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ + /* All devices the evdev driver has allocated and knows about. * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK) * cannot be used by evdev, leaving us with a space of 2 at the end. */ @@ -218,9 +278,11 @@ addRemap(EvdevPtr ev,uint16_t code,uint8_t value) if (!ev->keyremap) { ev->keyremap=(EvdevKeyRemapPtr)calloc(sizeof(EvdevKeyRemap),1); + if (!ev->keyremap) return; } if (!ev->keyremap->sl[slice]) { ev->keyremap->sl[slice]=(EvdevKeyRemapSlice*)calloc(sizeof(EvdevKeyRemapSlice),1); + if (!ev->keyremap->sl[slice]) return; } ev->keyremap->sl[slice]->cd[offs]=value; } @@ -453,7 +515,7 @@ SetRemapOption(InputInfoPtr pInfo,const char* name) c=s; while (sscanf(c," %li = %li %n",&code,&value,&consumed) > 1) { c+=consumed; - if (code < 0 || code > 65535L) { + if (code > 65535L) { xf86Msg(X_ERROR,"%s: input code %ld out of range for option \"event_key_remap\", ignoring.\n",pInfo->name,code); continue; } @@ -469,10 +531,11 @@ SetRemapOption(InputInfoPtr pInfo,const char* name) xf86Msg(X_ERROR, "%s: invalid input for option \"event_key_remap\" starting at '%s', ignoring.\n", pInfo->name, c); } + free(s); } #endif //_F_REMAP_KEYS_ -static EventQueuePtr +static EvdevEventQueuePtr EvdevNextInQueue(InputInfoPtr pInfo) { EvdevPtr pEvdev = pInfo->private; @@ -495,13 +558,18 @@ EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) #else //_F_REMAP_KEYS_ int code = ev->code + MIN_KEYCODE; #endif //_F_REMAP_KEYS_ - EventQueuePtr pQueue; + EvdevEventQueuePtr pQueue; /* Filter all repeated events from device. We'll do softrepeat in the server, but only since 1.6 */ if (value == 2) return; +#ifdef _F_BOOST_PULSE_ + if (fd_boostpulse && value == 1) + write(fd_boostpulse, (void *) "1", 1); +#endif //_F_BOOST_PULSE_ + if ((pQueue = EvdevNextInQueue(pInfo))) { pQueue->type = EV_QUEUE_KEY; @@ -513,7 +581,12 @@ EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value) void EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value) { - EventQueuePtr pQueue; + EvdevEventQueuePtr pQueue; + +#ifdef _F_BOOST_PULSE_ + if (fd_boostpulse && value == 1) + write(fd_boostpulse, (void *) "1", 1); +#endif //_F_BOOST_PULSE_ if ((pQueue = EvdevNextInQueue(pInfo))) { @@ -526,7 +599,7 @@ EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value) void EvdevQueueProximityEvent(InputInfoPtr pInfo, int value) { - EventQueuePtr pQueue; + EvdevEventQueuePtr pQueue; if ((pQueue = EvdevNextInQueue(pInfo))) { pQueue->type = EV_QUEUE_PROXIMITY; @@ -540,7 +613,7 @@ void EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask, uint16_t evtype) { - EventQueuePtr pQueue; + EvdevEventQueuePtr pQueue; if ((pQueue = EvdevNextInQueue(pInfo))) { pQueue->type = EV_QUEUE_TOUCH; @@ -1192,8 +1265,34 @@ EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev) if (EvdevMBEmuFilterEvent(pInfo, button, value)) return; - if (button) - EvdevQueueButtonEvent(pInfo, button, value); + if (button) { +#ifdef _F_PICTURE_OFF_MODE_ENABLE_ + if((pictureOffMode == 1) && (button == 1)) { + if(value == 0) { + /* Send right button press and release instead of left button press/release */ + button = 3; + EvdevQueueButtonEvent(pInfo, button, 1); + EvdevQueueButtonEvent(pInfo, button, 0); + } else ; /* Do nothing Ignore the left button press event */ + } + else { + /* When button is pressed, cancel timer for cursor hide*/ + if(value == 1) { + isButtonPressed = TRUE; + } else { + isButtonPressed = FALSE; + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + TimerCancel(pEvdev->rel_move_timer); + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, EVDEV_RMS_TIMEOUT, EvdevRelativeMoveTimer, pInfo); + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + } + EvdevQueueButtonEvent(pInfo, button, value); + } +#else //_F_PICTURE_OFF_MODE_ENABLE_ + EvdevQueueButtonEvent(pInfo, button, value); +#endif //_F_PICTURE_OFF_MODE_ENABLE_ + } else EvdevQueueKbdEvent(pInfo, ev, value); } @@ -1208,6 +1307,8 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevPtr pEvdev = pInfo->private; int map; + TTRACE_BEGIN("XORG:EVDEV:PROCESS_REL_MOTION"); + /* Get the signed value, earlier kernels had this as unsigned */ value = ev->value; @@ -1231,12 +1332,16 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev) #endif default: /* Ignore EV_REL events if we never set up for them. */ - if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS)) + if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS)) { + TTRACE_END(); return; + } /* Handle mouse wheel emulation */ - if (EvdevWheelEmuFilterMotion(pInfo, ev)) + if (EvdevWheelEmuFilterMotion(pInfo, ev)) { + TTRACE_END(); return; + } pEvdev->rel_queued = 1; pEvdev->delta[ev->code] += value; @@ -1244,6 +1349,7 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev) valuator_mask_set(pEvdev->vals, map, value); break; } + TTRACE_END(); } #ifdef MULTITOUCH @@ -1267,7 +1373,6 @@ EvdevProcessTouch(InputInfoPtr pInfo) else type = XI_TouchUpdate; - EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_mask, type); pEvdev->slot_state = SLOTSTATE_EMPTY; @@ -1278,8 +1383,15 @@ EvdevProcessTouch(InputInfoPtr pInfo) static int num_slots(EvdevPtr pEvdev) { - int value = pEvdev->absinfo[ABS_MT_SLOT].maximum - - pEvdev->absinfo[ABS_MT_SLOT].minimum + 1; + int value = 0; + + if (pEvdev->mtdev) { + value = pEvdev->mtdev->caps.slot.maximum + 1; + } + else { + value= pEvdev->absinfo[ABS_MT_SLOT].maximum - + pEvdev->absinfo[ABS_MT_SLOT].minimum + 1; + } /* If we don't know how many slots there are, assume at least 10 */ return value > 1 ? value : 10; @@ -1345,25 +1457,27 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevPtr pEvdev = pInfo->private; int map; + TTRACE_BEGIN("XORG:EVDEV:PROCESS_ABS_MOTION"); + /* Get the signed value, earlier kernels had this as unsigned */ value = ev->value; #ifdef _F_EVDEV_SUPPORT_GAMEPAD if(pEvdev->flags & EVDEV_GAMEPAD) { EvdevMappingGamepadAbsToKey(pInfo, ev); - return; + goto out; } #endif//_F_EVDEV_SUPPORT_GAMEPAD /* Ignore EV_ABS events if we never set up for them. */ if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)) - return; + goto out; if (ev->code > ABS_MAX) - return; + goto out; if (EvdevWheelEmuFilterMotion(pInfo, ev)) - return; + goto out; if (ev->code >= ABS_MT_SLOT) { EvdevProcessTouchEvent(pInfo, ev); @@ -1374,12 +1488,14 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev) if(map < 0) { xf86IDrvMsg(pInfo, X_INFO, "[EvdevProcessAbsoluteMotionEvent] Invalid valuator (=%d), value=%d\nThis is going to be skipped.", map, value); - return; + goto out; } valuator_mask_set(pEvdev->vals, map, value); pEvdev->abs_queued = 1; } +out: + TTRACE_END(); } /** @@ -1391,20 +1507,24 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev) int value, i; EvdevPtr pEvdev = pInfo->private; + TTRACE_BEGIN("XORG:EVDEV:PROCESS_KEY_MOTION"); + /* Get the signed value, earlier kernels had this as unsigned */ value = ev->value; /* don't repeat mouse buttons */ - if (ev->code >= BTN_MOUSE && ev->code < KEY_OK) - if (value == 2) - return; - + if (ev->code >= BTN_MOUSE && ev->code < KEY_OK) { + if (value == 2) { + goto out; + } + } #ifdef _F_EVDEV_SUPPORT_GAMEPAD if(pEvdev->flags & EVDEV_GAMEPAD) { EvdevMappingGamepadKeyToKey(pInfo, ev); - if (ev->code == 0) - return; + if (ev->code == 0) { + goto out; + } } #endif//_F_EVDEV_SUPPORT_GAMEPAD @@ -1414,7 +1534,7 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev) if (ev->code == proximity_bits[i]) { EvdevProcessProximityEvent(pInfo, ev); - return; + goto out; } } @@ -1436,6 +1556,8 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevProcessButtonEvent(pInfo, ev); break; } +out: + TTRACE_END(); } #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ @@ -1449,20 +1571,27 @@ EvdevRelativeMoveTimer(OsTimerPtr timer, CARD32 time, pointer arg) else return 0; if(!pEvdev) return 0; + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); if(pEvdev->rel_move_timer) TimerCancel(pEvdev->rel_move_timer); - pEvdev->rel_move_timer = NULL; - - pEvdev->rel_move_status = 0; - pEvdev->rel_move_ack = 0; - int rc = XIDeleteDeviceProperty(pInfo->dev, prop_relative_move_status, TRUE); - - if (rc != Success) + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); +#ifdef _F_DONOT_SEND_RMA_BTN_RELEASE_ + if(!isButtonPressed) { - xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to delete device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, prop_relative_move_status); - } +#endif //_F_DONOT_SEND_RMA_BTN_RELEASE_ + pEvdev->rel_move_status = 0; + if (pEvdev->rel_move_ack != 2) + pEvdev->rel_move_ack = 0; + int rc = XIDeleteDeviceProperty(pInfo->dev, prop_relative_move_status, TRUE); - ErrorF("[%s] pEvdev->rel_move_status=%d\n", __FUNCTION__, pEvdev->rel_move_status); + if (rc != Success) + { if (pEvdev->rel_move_ack != 2) + pEvdev->rel_move_ack = 0; + xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to delete device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, prop_relative_move_status); + } +#ifdef _F_DONOT_SEND_RMA_BTN_RELEASE_ + } +#endif //_F_DONOT_SEND_RMA_BTN_RELEASE_ return 0; } @@ -1550,7 +1679,11 @@ EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int first_v, { EvdevPtr pEvdev = pInfo->private; +#ifdef _F_BLOCK_MOTION_DEVICE_ + if (pEvdev->rel_queued && (block_motion_device ==0)) { +#else //_F_BLOCK_MOTION_DEVICE_ if (pEvdev->rel_queued) { +#endif //_F_BLOCK_MOTION_DEVICE_ #ifdef _F_EVDEV_SUPPORT_ROTARY_ if (pEvdev->flags & EVDEV_OFM) { pEvdev->extra_rel_post_ofm(pInfo, num_v, first_v, v); @@ -1573,9 +1706,11 @@ EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int first_v, RegisterBlockAndWakeupHandlers(EvdevBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, pInfo); } + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); TimerCancel(pEvdev->rel_move_timer); - pEvdev->rel_move_timer = NULL; - pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, 15000, EvdevRelativeMoveTimer, pInfo); + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, EVDEV_RMS_TIMEOUT, EvdevRelativeMoveTimer, pInfo); + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */ xf86PostMotionEventM(pInfo->dev, Relative, pEvdev->vals); } @@ -1599,7 +1734,11 @@ EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int num_v, int first_v, * pEvdev->in_proximity is initialized to 1 so devices that don't use * this scheme still just work. */ +#ifdef _F_BLOCK_MOTION_DEVICE_ + if (pEvdev->abs_queued && pEvdev->in_proximity && block_motion_device == 0 ) { +#else //_F_BLOCK_MOTION_DEVICE_ if (pEvdev->abs_queued && pEvdev->in_proximity) { +#endif //_F_BLOCK_MOTION_DEVICE_ xf86PostMotionEventM(pInfo->dev, Absolute, pEvdev->vals); } } @@ -1649,6 +1788,21 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v, EvdevPtr pEvdev = pInfo->private; +#ifdef _F_PROXY_DEVICE_ENABLED_ +#ifdef _F_PROXY_DEVICE_CHANGE_SOURCE_ID + if(!(pInfo->dev)) + { + return; + } + + EvdevCheckDevChange(pEvdev, pInfo->dev->id); +#else + if(pEvdev->proxy_device){ + EvdevPostDevChangeEvent(pEvdev->proxy_device); + } +#endif +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ + for (i = 0; i < pEvdev->num_queue; i++) { switch (pEvdev->queue[i].type) { case EV_QUEUE_KEY: @@ -1669,6 +1823,7 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v, } else xf86PostButtonEvent(pInfo->dev, Relative, pEvdev->queue[i].detail.key, pEvdev->queue[i].val, 0, 0); + break; case EV_QUEUE_PROXIMITY: break; @@ -1710,12 +1865,12 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v, if ((XI_TouchBegin == event_type) && (slot_idx == 0)) { - if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_BEGIN)) - { - sync_value = MTOUCH_FRAME_SYNC_BEGIN; - EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN); - } - } + if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_BEGIN)) + { + sync_value = MTOUCH_FRAME_SYNC_BEGIN; + EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_BEGIN); + } + } xf86PostTouchEvent(pInfo->dev, slot_idx, event_type, 0, @@ -1723,10 +1878,14 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v, if ((sync_value < 0) && (XI_TouchEnd == event_type)) { - if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_END)) - { - EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_END); - } + if (EvdevMTStatusGet(pInfo, MTOUCH_FRAME_SYNC_END)) + { + EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_END); + } + else + { + EvdevMTSync(pInfo, MTOUCH_FRAME_SYNC_UPDATE); + } } } #else /* #ifdef _F_GESTURE_EXTENSION_ */ @@ -1751,6 +1910,7 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) int num_v = 0, first_v = 0; int v[MAX_VALUATORS] = {}; EvdevPtr pEvdev = pInfo->private; + TTRACE_BEGIN("XORG:EVDEV:PROCESS_SYNC_MOTION"); EvdevProcessProximityState(pInfo); @@ -1766,7 +1926,7 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) memset(pEvdev->delta, 0, sizeof(pEvdev->delta)); for (i = 0; i < ArrayLength(pEvdev->queue); i++) { - EventQueuePtr queue = &pEvdev->queue[i]; + EvdevEventQueuePtr queue = &pEvdev->queue[i]; queue->detail.key = 0; queue->type = 0; queue->val = 0; @@ -1780,6 +1940,7 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) pEvdev->rel_queued = 0; pEvdev->prox_queued = 0; + TTRACE_END(); } /** @@ -1789,6 +1950,34 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) static void EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev) { + TTRACE_BEGIN("XORG:EVDEV:PROCESS_EVENT"); + + EvdevPtr pEvdev = pInfo->private; + int result = 0; + +#ifdef _F_EVDEV_SUPPORT_SMARTRC_ + if (pEvdev->extra_input_process) { +#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_ + result = pEvdev->extra_input_process(&pInfo, ev); +#else + result = pEvdev->extra_input_process(pInfo, ev); +#endif + if (!result) { + return; + } + } +#endif //_F_EVDEV_SUPPORT_SMARTRC_ + +#ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ + if (pEvdev->rel_move_ack == 2) { + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + TimerCancel(pEvdev->rel_move_timer); + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + pEvdev->rel_move_status = 0; + + return; + } +#endif//_F_ENABLE_REL_MOVE_STATUS_PROP_ switch (ev->type) { case EV_REL: EvdevProcessRelativeMotionEvent(pInfo, ev); @@ -1803,6 +1992,7 @@ EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev) EvdevProcessSyncEvent(pInfo, ev); break; } + TTRACE_END(); } #undef ABS_X_VALUE @@ -1812,7 +2002,9 @@ EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev) static void EvdevFreeMasks(EvdevPtr pEvdev) { +#ifdef MULTITOUCH int i; +#endif valuator_mask_free(&pEvdev->vals); valuator_mask_free(&pEvdev->old_vals); @@ -1840,6 +2032,8 @@ EvdevReadInput(InputInfoPtr pInfo) struct input_event ev[NUM_EVENTS]; int i, len = sizeof(ev); + TTRACE_BEGIN("XORG:EVDEV:READ_INPUT"); + while (len == sizeof(ev)) { #ifdef MULTITOUCH @@ -1859,9 +2053,8 @@ EvdevReadInput(InputInfoPtr pInfo) EvdevMBEmuFinalize(pInfo); Evdev3BEmuFinalize(pInfo); xf86RemoveEnabledDevice(pInfo); - close(pInfo->fd); - pInfo->fd = -1; - } else if (errno != EAGAIN) + } + else if (errno != EAGAIN) { /* We use X_NONE here because it doesn't alloc */ xf86MsgVerb(X_NONE, 0, "%s: Read error: %s\n", pInfo->name, @@ -1881,6 +2074,7 @@ EvdevReadInput(InputInfoPtr pInfo) for (i = 0; i < len/sizeof(ev[0]); i++) EvdevProcessEvent(pInfo, &ev[i]); } + TTRACE_END(); } static void @@ -2124,6 +2318,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) } #ifdef MULTITOUCH if (num_mt_axes_total > 0) { + pEvdev->num_mt_vals = num_mt_axes_total; pEvdev->mt_mask = valuator_mask_new(num_mt_axes_total); if (!pEvdev->mt_mask) { xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n", @@ -2164,7 +2359,9 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) i = 0; for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) { +#ifdef MULTITOUCH int j; +#endif int mapping; pEvdev->axis_map[axis] = -1; if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) || @@ -2203,8 +2400,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device) int mode = pEvdev->flags & EVDEV_TOUCHPAD ? XIDependentTouch : XIDirectTouch; - if (pEvdev->mtdev && pEvdev->mtdev->caps.slot.maximum > 0) - num_touches = pEvdev->mtdev->caps.slot.maximum; + num_touches = num_slots(pEvdev); if (!InitTouchClassDeviceStruct(device, num_touches, mode, num_mt_axes_total)) { @@ -2423,7 +2619,7 @@ EvdevAddRelValuatorClass(DeviceIntPtr device) else if (axis == REL_DIAL) SetScrollValuator(device, axnum, SCROLL_TYPE_VERTICAL, -1.0, SCROLL_FLAG_NONE); else if (axis == REL_HWHEEL) - SetScrollValuator(device, axnum, SCROLL_TYPE_HORIZONTAL, -1.0, SCROLL_FLAG_NONE); + SetScrollValuator(device, axnum, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE); #endif } @@ -2487,12 +2683,12 @@ EvdevInitButtonMapping(InputInfoPtr pInfo) /* Check for user-defined button mapping */ if ((mapping = xf86CheckStrOption(pInfo->options, "ButtonMapping", NULL))) { - char *map, *s = " "; + char *map, *s = NULL; int btn = 0; xf86IDrvMsg(pInfo, X_CONFIG, "ButtonMapping '%s'\n", mapping); map = mapping; - while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS) + do { btn = strtol(map, &s, 10); @@ -2506,7 +2702,7 @@ EvdevInitButtonMapping(InputInfoPtr pInfo) pEvdev->btnmap[nbuttons++] = btn; map = s; - } + } while (s && *s != '\0' && nbuttons < EVDEV_MAXBUTTONS); free(mapping); } @@ -2634,6 +2830,7 @@ EvdevInit(DeviceIntPtr device) pInfo = device->public.devicePrivate; pEvdev = pInfo->private; + TTRACE_BEGIN("XORG:EVDEV:INIT"); /* clear all axis_map entries */ for(i = 0; i < max(ABS_CNT,REL_CNT); i++) @@ -2676,7 +2873,15 @@ EvdevInit(DeviceIntPtr device) * unregister is when the device dies. In which case we don't have to * unregister anyway */ EvdevInitProperty(device); +#ifdef _F_PROXY_DEVICE_ENABLED_ + if (!strncmp(pInfo->name, PROXY_DEV_NAME, sizeof(PROXY_DEV_NAME))) { + EvdevProxyInit(device); + } + else + XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL); +#else //_F_PROXY_DEVICE_ENABLED_ XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL); +#endif //_F_PROXY_DEVICE_ENABLED_ EvdevMBEmuInitProperty(device); Evdev3BEmuInitProperty(device); EvdevWheelEmuInitProperty(device); @@ -2685,6 +2890,11 @@ EvdevInit(DeviceIntPtr device) #ifdef _F_EVDEV_SUPPORT_ROTARY_ EvdevRotaryInit(device); #endif //_F_EVDEV_SUPPORT_ROTARY_ +#ifdef _F_EVDEV_SUPPORT_SMARTRC_ + EvdevRCInit(device); +#endif //_F_EVDEV_SUPPORT_SMARTRC_ + + TTRACE_END(); return Success; } @@ -2698,13 +2908,28 @@ EvdevOn(DeviceIntPtr device) InputInfoPtr pInfo; EvdevPtr pEvdev; int rc = Success; + ErrorF("[EvdevOn][id:%d] find device (%s)\n", device->id, device->name); + TTRACE_BEGIN("XORG:EVDEV:ON"); pInfo = device->public.devicePrivate; pEvdev = pInfo->private; + +#ifdef _F_PROXY_DEVICE_ENABLED_ + /*Check if its proxy device.. in that case just set flag and return..*/ + if(pEvdev->b_proxy_device) + { + pEvdev->flags |= EVDEV_INITIALIZED; + device->public.on = TRUE; + return Success; + } +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ + /* after PreInit fd is still open */ rc = EvdevOpenDevice(pInfo); - if (rc != Success) + if (rc != Success) { + TTRACE_END(); return rc; + } EvdevGrabDevice(pInfo, 1, 0); @@ -2715,6 +2940,7 @@ EvdevOn(DeviceIntPtr device) pEvdev->flags |= EVDEV_INITIALIZED; device->public.on = TRUE; + TTRACE_END(); return Success; } @@ -2740,6 +2966,24 @@ EvdevProc(DeviceIntPtr device, int what) return EvdevOn(device); case DEVICE_OFF: +#ifdef _F_PROXY_DEVICE_ENABLED_ + if(pEvdev->b_proxy_device) + { + if (pEvdev->flags & EVDEV_INITIALIZED) + { + pEvdev->min_maj = 0; + pEvdev->flags &= ~EVDEV_INITIALIZED; + device->public.on = FALSE; + } + if (pInfo->fd != -1) + { + xf86RemoveEnabledDevice(pInfo); + close(pInfo->fd); + pInfo->fd = -1; + } + return Success; + } +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ if (pEvdev->flags & EVDEV_INITIALIZED) { EvdevMBEmuFinalize(pInfo); @@ -2749,15 +2993,15 @@ EvdevProc(DeviceIntPtr device, int what) { EvdevGrabDevice(pInfo, 0, 1); xf86RemoveEnabledDevice(pInfo); - close(pInfo->fd); - pInfo->fd = -1; + EvdevCloseDevice(pInfo); } #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ if (pEvdev->rel_move_timer) { + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); TimerCancel(pEvdev->rel_move_timer); - pEvdev->rel_move_timer = NULL; + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); pEvdev->rel_move_status = 0; pEvdev->rel_move_ack = 0; ErrorF("[%s][dev:%d] DEVICE_OFF (rel_move_status=%d, rel_move_prop_set=%d)\n", __FUNCTION__, pInfo->dev->id, pEvdev->rel_move_status, @@ -2776,10 +3020,7 @@ EvdevProc(DeviceIntPtr device, int what) EvdevSetConfineRegion(pInfo, 1, ®ion[0]); #endif /* _F_EVDEV_CONFINE_REGION_ */ xf86IDrvMsg(pInfo, X_INFO, "Close\n"); - if (pInfo->fd != -1) { - close(pInfo->fd); - pInfo->fd = -1; - } + EvdevCloseDevice(pInfo); EvdevFreeMasks(pEvdev); EvdevRemoveDevice(pInfo); #ifdef _F_REMAP_KEYS_ @@ -2829,7 +3070,13 @@ EvdevCache(InputInfoPtr pInfo) goto error; } - strcpy(pEvdev->name, name); + len = strlen(name); + if (len < sizeof(pEvdev->name)) { + strncpy(pEvdev->name, name, len+1); + } else { + strncpy(pEvdev->name, name, sizeof(pEvdev->name)-1); + xf86DrvMsg(pInfo, X_WARNING, "Device's name(%s) is too long. Restrict name to inside of buffer size\n", pEvdev->name); + } len = ioctl(pInfo->fd, EVIOCGBIT(0, sizeof(bitmask)), bitmask); if (len < 0) { @@ -3079,7 +3326,26 @@ EvdevProbe(InputInfoPtr pInfo) } } #endif - +#ifdef _F_EVDEV_SUPPORT_SMARTRC_ + if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_EXTRA)) + { + xf86IDrvMsg(pInfo, X_PROBED, "Found extra button\n"); + if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE))) + { + xf86IDrvMsg(pInfo, X_PROBED, "... regarding smart rc\n"); + pEvdev->flags |= EVDEV_SMART_RC; + } + } + if (EvdevBitIsSet(pEvdev->key_bitmask, BTN_SIDE)) + { + xf86IDrvMsg(pInfo, X_PROBED, "Found extra button\n"); + if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE))) + { + xf86IDrvMsg(pInfo, X_PROBED, "... regarding smart rc\n"); + pEvdev->flags |= EVDEV_SMART_RC; + } + } +#endif //_F_EVDEV_SUPPORT_SMARTRC_ if (ignore_abs && has_abs_axes) { xf86IDrvMsg(pInfo, X_INFO, "Absolute axes present but ignored.\n"); @@ -3182,6 +3448,9 @@ EvdevProbe(InputInfoPtr pInfo) xf86IDrvMsg(pInfo, X_INFO, "Configuring as touchscreen\n"); pInfo->type_name = XI_TOUCHSCREEN; } else { + if (!EvdevBitIsSet(pEvdev->rel_bitmask, REL_X) || + !EvdevBitIsSet(pEvdev->rel_bitmask, REL_Y)) + EvdevForceXY(pInfo, Relative); xf86IDrvMsg(pInfo, X_INFO, "Configuring as mouse\n"); pInfo->type_name = XI_MOUSE; } @@ -3216,7 +3485,16 @@ EvdevProbe(InputInfoPtr pInfo) pEvdev->flags |= EVDEV_HALLIC; } #endif //_F_EVDEV_SUPPORT_ROTARY_ +#ifdef _F_EVDEV_SUPPORT_SMARTRC_ + if (pEvdev->flags & EVDEV_SMART_RC) { + xf86IDrvMsg(pInfo, X_INFO, "Configuring as smart rc\n"); + pInfo->type_name = XI_MOUSE; + EvdevSetBit(pEvdev->rel_bitmask, REL_WHEEL); + EvdevSetBit(pEvdev->rel_bitmask, REL_HWHEEL); + } + pEvdev->origin_input_process = EvdevProcessEvent; +#endif //_F_EVDEV_SUPPORT_SMARTRC_ if (rc) xf86IDrvMsg(pInfo, X_WARNING, "Don't know how to use device\n"); @@ -3273,21 +3551,49 @@ EvdevOpenDevice(InputInfoPtr pInfo) } } +#ifdef MULTITOUCH + if (!pEvdev->mtdev) { /* after PreInit mtdev is still valid */ + pEvdev->mtdev = mtdev_new_open(pInfo->fd); + if (!pEvdev->mtdev) { + xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name); + EvdevCloseDevice(pInfo); + return FALSE; + } + } + if (pEvdev->mtdev) + pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value; +#endif /* Check major/minor of device node to avoid adding duplicate devices. */ pEvdev->min_maj = EvdevGetMajorMinor(pInfo); if (EvdevIsDuplicate(pInfo)) { xf86IDrvMsg(pInfo, X_WARNING, "device file is duplicate. Ignoring.\n"); + EvdevCloseDevice(pInfo); + return BadMatch; + } + + return Success; +} + +static void +EvdevCloseDevice(InputInfoPtr pInfo) +{ + EvdevPtr pEvdev = pInfo->private; + if (pInfo->fd >= 0) + { close(pInfo->fd); + pInfo->fd = -1; + } + #ifdef MULTITOUCH + if (pEvdev->mtdev) + { mtdev_close_delete(pEvdev->mtdev); pEvdev->mtdev = NULL; -#endif - return BadMatch; } +#endif - return Success; } #ifdef _F_EVDEV_CONFINE_REGION_ @@ -3584,6 +3890,41 @@ EvdevSetTransformMatrix(InputInfoPtr pInfo, int num_transform, float *tmatrix) } #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */ +#ifdef _F_SUPPORT_ROTATION_ANGLE_ +static void +EvdevSetRotationAngle(EvdevPtr pEvdev, int angle) +{ + if(pEvdev->rotation_node <= 0) + { + xf86Msg(X_INFO, "[%s] Rotation node doesn't exist. Ignored. (angle=%d)\n", __FUNCTION__, angle); + return; + } + + if(pEvdev->rotation_angle != angle) + { + { + int nwrite = 0; + char buf; + + buf = (char)(angle + '0'); + + nwrite = write(pEvdev->rotation_node, &buf, sizeof(buf)); + + if(nwrite <= 0) + xf86Msg(X_ERROR, "[%s] Failed to write angle(=%d) on rotation_node. (errno=%d)\n", __FUNCTION__, angle, errno); + else + xf86Msg(X_ERROR, "[%s] Succeed to write angle(=%d) on rotation_node.\n", __FUNCTION__, angle); + } + + pEvdev->rotation_angle = angle; + } + else + { + xf86Msg(X_INFO, "[%s] Rotation angle has not been changed. Ignored. (angle=%d)\n", __FUNCTION__, angle); + } +} +#endif// _F_SUPPORT_ROTATION_ANGLE_ + static void EvdevUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) { @@ -3599,6 +3940,8 @@ EvdevUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) /* Release string allocated in EvdevOpenDevice. */ free(pEvdev->device); pEvdev->device = NULL; + free(pEvdev); + pEvdev = NULL; } xf86DeleteInput(pInfo, flags); } @@ -3614,17 +3957,64 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) const char *str; #endif /* #ifdef _F_TOUCH_TRANSFORM_MATRIX_ */ +#ifdef _F_PROXY_DEVICE_ENABLED_ + char *type; +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ + +#ifdef _F_BOOST_PULSE_ + if(fd_boostpulse == NULL) + fd_boostpulse = open("sys/kernel/hmp/boostpulse", O_RDWR); +#endif //_F_BOOST_PULSE_ + if (!(pEvdev = calloc(sizeof(EvdevRec), 1))) { xf86IDrvMsg(pInfo, X_ERROR, "Failed to allocate memory for private member of pInfo !\n"); goto error; } + TTRACE_END(); + pInfo->private = pEvdev; pInfo->type_name = "UNKNOWN"; pInfo->device_control = EvdevProc; pInfo->read_input = EvdevReadInput; pInfo->switch_mode = EvdevSwitchMode; +#ifdef _F_EVDEV_SUPPORT_SMARTRC_ + pEvdev->extra_input_process = NULL; + pEvdev->rc_state = 0; + pEvdev->proxy_enabled = xf86SetBoolOption(pInfo->options, "ProxyDeviceEnabled", FALSE); +#endif //_F_EVDEV_SUPPORT_SMARTRC_ + +#ifdef _F_PROXY_DEVICE_ENABLED_ + /* If Type == ProxyDev, this is a proxy device */ + type = xf86CheckStrOption(pInfo->options, "Type", NULL); + + xf86Msg(X_INFO, "%s: Evdev Type %s found\n", pInfo->name, type); + + if (type != NULL && strcmp(type, OPT_TYPE_VAL) == 0) + { + EvdevPtr pCreatorEvdev; + free(type); + if (!pCreatorInfo){ + return Success; + } + pCreatorEvdev = pCreatorInfo->private; + xf86Msg(X_INFO, "%s: Evdev proxy device found\n", pInfo->name); + memcpy(pEvdev, pCreatorEvdev, sizeof(EvdevRec)); + pInfo->read_input = EvdevProxydevReadInput; + pInfo->type_name = pCreatorInfo->type_name; + pEvdev->b_proxy_device = TRUE; + pEvdev->proxy_device = NULL; + return Success; + } + else + { + free(type); + pEvdev->b_proxy_device = FALSE; + pEvdev->proxy_device = NULL; + } +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ + #ifdef _F_EVDEV_SUPPORT_ROTARY_ pEvdev->extra_rel_post_hallic= NULL; pEvdev->extra_rel_post_ofm= NULL; @@ -3637,6 +4027,9 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) #ifdef MULTITOUCH pEvdev->cur_slot = -1; #endif +#ifdef MULTI_PASSIVE_GRAB_ + pEvdev->activatedkeylist = NULL; +#endif //MULTI_PASSIVE_GRAB_ /* * We initialize pEvdev->in_proximity to 1 so that device that doesn't use @@ -3728,6 +4121,7 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) else { xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name); + TTRACE_END(); return FALSE; } } @@ -3788,6 +4182,21 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ pEvdev->rel_move_timer = NULL; + if (pEvdev->flags & EVDEV_RELATIVE_EVENTS) + { +#ifdef _F_PROXY_DEVICE_ENABLED_ + if (!pEvdev->b_proxy_device) + { +#endif //_F_PROXY_DEVICE_ENABLED_ + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + pEvdev->rel_move_timer = TimerSet(pEvdev->rel_move_timer, 0, EVDEV_RMS_TIMEOUT, EvdevRelativeMoveTimer, pInfo); + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + TimerCancel(pEvdev->rel_move_timer); + ErrorF("[EvdevPreinit] Device: %s has relative events create RMS timer(%p)\n", pInfo->name, pEvdev->rel_move_timer); +#ifdef _F_PROXY_DEVICE_ENABLED_ + } +#endif //_F_PROXY_DEVICE_ENABLED_ + } pEvdev->rel_move_prop_set = 0; pEvdev->rel_move_status = 0; #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */ @@ -3827,11 +4236,31 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) pEvdev->keycode_btnPlay = xf86SetIntOption(pInfo->options, "GamePad_ButtonPlay", 0); #endif//_F_EVDEV_SUPPORT_GAMEPAD +#ifdef _F_SUPPORT_ROTATION_ANGLE_ + pEvdev->rotation_angle = xf86SetIntOption(pInfo->options, "RotationAngle", 0); + + str = xf86CheckStrOption(pInfo->options, "RotationNode", NULL); + if (str) + { + do { + pEvdev->rotation_node = open(str, O_WRONLY, 0); + } while (pEvdev->rotation_node < 0 && errno == EINTR); + } + else xf86Msg(X_INFO, "%s: No rotation node exists..\n", pInfo->name); + + if (pEvdev->rotation_node < 0) { + xf86Msg(X_ERROR, "Unable to open evdevmultitouch rotation_node\"%s\".\n", str); + xf86Msg(X_ERROR, "Input rotation will be done inside evdevmultitouch driver.\n"); + pEvdev->rotation_node = 0; + } +#endif// _F_SUPPORT_ROTATION_ANGLE_ + + TTRACE_END(); return Success; error: - if ((pInfo) && (pInfo->fd >= 0)) - close(pInfo->fd); + EvdevCloseDevice(pInfo); + TTRACE_END(); return rc; } @@ -4184,9 +4613,14 @@ EvdevInitProperty(DeviceIntPtr dev) #ifdef _F_EVDEV_CONFINE_REGION_ int region[6] = { 0, }; #endif /* _F_EVDEV_CONFINE_REGION_ */ +#ifdef _F_PROXY_DEVICE_ENABLED_ + int slave_proxy; +#endif /* _F_PROXY_DEVICE_ENABLED_ */ CARD32 product[2]; - +#ifdef _F_PICTURE_OFF_MODE_ENABLE_ + atomPictureOffMode = MakeAtom(XI_PROP_PICTURE_OFF_MODE,strlen(XI_PROP_PICTURE_OFF_MODE), TRUE); +#endif //_F_PICTURE_OFF_MODE_ENABLE_ prop_product_id = MakeAtom(XI_PROP_PRODUCT_ID, strlen(XI_PROP_PRODUCT_ID), TRUE); product[0] = pEvdev->id_vendor; product[1] = pEvdev->id_product; @@ -4201,30 +4635,31 @@ EvdevInitProperty(DeviceIntPtr dev) device_node = strdup(pEvdev->device); prop_device = MakeAtom(XI_PROP_DEVICE_NODE, strlen(XI_PROP_DEVICE_NODE), TRUE); - rc = XIChangeDeviceProperty(dev, prop_device, XA_STRING, 8, - PropModeReplace, - (device_node?strlen(device_node):0), device_node, - FALSE); - free(device_node); - - if (rc != Success) - return; + if (device_node) + { + rc = XIChangeDeviceProperty(dev, prop_device, XA_STRING, 8, + PropModeReplace, + strlen(device_node), device_node, + FALSE); + free(device_node); - XISetDevicePropertyDeletable(dev, prop_device, FALSE); + if (rc == Success) + XISetDevicePropertyDeletable(dev, prop_device, FALSE); + } #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ /* Device node property */ device_type = strdup(pInfo->type_name); prop_device_type = MakeAtom(XI_PROP_DEVICE_TYPE, strlen(XI_PROP_DEVICE_TYPE), TRUE); - rc = XIChangeDeviceProperty(dev, prop_device_type, XA_STRING, 8, - PropModeReplace, - (device_type?strlen(device_type):0), device_type, - FALSE); - free(device_type); - - if (rc != Success) - return; + if (device_type) + { + rc = XIChangeDeviceProperty(dev, prop_device_type, XA_STRING, 8, + PropModeReplace, + strlen(device_type), device_type, + FALSE); + free(device_type); + } #endif /* #ifdef _F_ENABLE_DEVICE_TYPE_PROP_ */ #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ @@ -4235,7 +4670,10 @@ EvdevInitProperty(DeviceIntPtr dev) strlen(XI_PROP_REL_MOVE_STATUS), TRUE); prop_relative_move_ack = MakeAtom(XI_PROP_REL_MOVE_ACK, strlen(XI_PROP_REL_MOVE_ACK), TRUE); - +#ifdef _F_BLOCK_MOTION_DEVICE_ + prop_block_motion_status = MakeAtom(XI_PROP_BLOCK_MOTION_DEVICE, + strlen(XI_PROP_BLOCK_MOTION_DEVICE), TRUE); +#endif //_F_BLOCK_MOTION_DEVICE_ ErrorF("[%s] prop_relative_move_status = %d, prop_relative_move_ack = %d\n", __FUNCTION__, prop_relative_move_status, prop_relative_move_ack); #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */ @@ -4336,7 +4774,8 @@ EvdevInitProperty(DeviceIntPtr dev) if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP))) { int mode; - Atom atoms[pEvdev->num_vals]; + int num_axes = pEvdev->num_vals + pEvdev->num_mt_vals; + Atom atoms[num_axes]; if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) mode = Absolute; @@ -4347,9 +4786,9 @@ EvdevInitProperty(DeviceIntPtr dev) mode = Absolute; } - EvdevInitAxesLabels(pEvdev, mode, pEvdev->num_vals, atoms); + EvdevInitAxesLabels(pEvdev, mode, num_axes, atoms); XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32, - PropModeReplace, pEvdev->num_vals, atoms, FALSE); + PropModeReplace, num_axes, atoms, FALSE); XISetDevicePropertyDeletable(dev, prop_axis_label, FALSE); } /* Button labelling */ @@ -4361,7 +4800,51 @@ EvdevInitProperty(DeviceIntPtr dev) PropModeReplace, pEvdev->num_buttons, atoms, FALSE); XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE); } - } +#ifdef _F_SUPPORT_ROTATION_ANGLE_ + if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS) { + int rotation_angle; + prop_rotation_angle = MakeAtom(EVDEV_PROP_ROTATION_ANGLE, + strlen(EVDEV_PROP_ROTATION_ANGLE), TRUE); + + rotation_angle = pEvdev->rotation_angle; + rc = XIChangeDeviceProperty(dev, prop_rotation_angle, XA_INTEGER, 8, + PropModeReplace, 1, &rotation_angle, TRUE); + if (rc != Success) + return; + + XISetDevicePropertyDeletable(dev, prop_rotation_angle, FALSE); + + int rotation_node; + prop_rotation_node = MakeAtom(EVDEV_PROP_ROTATION_NODE, + strlen(EVDEV_PROP_ROTATION_NODE), TRUE); + + rotation_node = pEvdev->rotation_node; + rc = XIChangeDeviceProperty(dev, prop_rotation_node, XA_INTEGER, 32, + PropModeReplace, 1, &rotation_node, FALSE); + if (rc != Success) + return; + + XISetDevicePropertyDeletable(dev, prop_rotation_node, FALSE); + } +#endif //_F_SUPPORT_ROTATION_ANGLE_ + +#ifdef _F_PROXY_DEVICE_ENABLED_ + slave_proxy = 0; + prop_use_proxy_slave_device = MakeAtom(XI_PROP_USE_PROXY_SLAVE_DEVICE, strlen(XI_PROP_USE_PROXY_SLAVE_DEVICE), TRUE); + XIChangeDeviceProperty(dev, prop_use_proxy_slave_device, XA_INTEGER, 8, + PropModeReplace, 1, &slave_proxy, FALSE); + XISetDevicePropertyDeletable(dev, prop_use_proxy_slave_device, FALSE); + pEvdev->proxy_device = NULL; +#endif // _F_PROXY_DEVICE_ENABLED_ + } +#ifdef _F_PROXY_DEVICE_ENABLED_ + slave_proxy = 0; + prop_use_proxy_slave_device = MakeAtom(XI_PROP_USE_PROXY_SLAVE_DEVICE, strlen(XI_PROP_USE_PROXY_SLAVE_DEVICE), TRUE); + XIChangeDeviceProperty(dev, prop_use_proxy_slave_device, XA_INTEGER, 8, + PropModeReplace, 1, &slave_proxy, FALSE); + XISetDevicePropertyDeletable(dev, prop_use_proxy_slave_device, FALSE); + pEvdev->proxy_device = NULL; +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ } static int @@ -4436,16 +4919,334 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ else if (atom == prop_relative_move_ack) { + int data; + if (val->format != 8 || val->type != XA_INTEGER) return BadMatch; if (val->size != 1) return BadMatch; - if (!checkonly) - pEvdev->rel_move_ack = 1; + if (!checkonly) { + data = *((CARD8*)val->data); + pEvdev->rel_move_ack = data; + } + + if ((pEvdev->rel_move_ack == 2) || (pEvdev->rel_move_ack == 3)) + { + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + TimerCancel(pEvdev->rel_move_timer); + if (pEvdev->rel_move_timer == NULL) ErrorF("[%s:%d] pEvdev->rel_move_timer: %p\n", __FUNCTION__, __LINE__, pEvdev->rel_move_timer); + pEvdev->rel_move_status = 0; + } } #endif /* _F_ENABLE_REL_MOVE_STATUS_PROP_ */ +#ifdef _F_GESTURE_EXTENSION_ + else if (atom == XIGetKnownProperty(XI_PROP_ENABLED)) + { + if (val->format != 8 || val->type != XA_INTEGER) + return BadMatch; + + if (val->size != 1) + return BadMatch; + + if (!checkonly && strcasestr(dev->name, "touchscreen")) + { + DeviceIntPtr device; + for (device = inputInfo.devices; device; device = device->next) + { + if(!strncmp(device->name, GESTURE_DEV_NAME, sizeof(GESTURE_DEV_NAME)-1)) + { + InputInfoPtr gestureInfo = device->public.devicePrivate; + ErrorF("[EvdevSetProperty][id:%d] find device (%s)\n", device->id, device->name); + gestureInfo->device_control(device, DEVICE_READY); + break; + } + } + } + } +#endif //_F_GESTURE_EXTENSION_ + +#ifdef _F_SUPPORT_ROTATION_ANGLE_ + else if (atom == prop_rotation_angle) + { + int data; + char cdata; + if (val->format != 8 || val->type != XA_INTEGER || val->size != 1) + return BadMatch; + + if (!checkonly) + { + cdata = *((char*)val->data); + data = (int)cdata; + + EvdevSetRotationAngle(pEvdev, data); + } + } +#endif //_F_SUPPORT_ROTATION_ANGLE_ + +#ifdef _F_PROXY_DEVICE_ENABLED_ + else if (atom == prop_use_proxy_slave_device) + { + int data; + + if (val->format != 8 || val->type != XA_INTEGER) + return BadMatch; + if (val->size != 1) + return BadMatch; + if (!pEvdev->proxy_enabled) + return Success; + + if (!checkonly) { + data = *((CARD8*)val->data); + EvdevSetProxyDevice(dev,data); + } + } +#endif // #ifdef _F_PROXY_DEVICE_ENABLED_ +#ifdef _F_BLOCK_MOTION_DEVICE_ + else if (atom == prop_block_motion_status ) + { + int data; + + if (!checkonly) { + data = *((CARD8*)val->data); + block_motion_device = data; + } + } + else if ((atom == atomPictureOffMode)) + { + int data; + data = *((CARD8*)val->data); + pictureOffMode = data; + } +#endif //_F_BLOCK_MOTION_DEVICE_ return Success; } + +#ifdef _F_PROXY_DEVICE_ENABLED_ + +static int EvdevSetProxyDevice(DeviceIntPtr dev, int val) +{ + InputInfoPtr pInfo = dev->public.devicePrivate; + EvdevPtr pEvdev = pInfo->private; + if(0 == val) { + pEvdev->proxy_device = NULL; + } else { + if(NULL == pProxyDeviceInfo) { + pProxyDeviceInfo = EvdevCreateProxyDevice(pInfo); + } + pEvdev->proxy_device = pProxyDeviceInfo; + } + return 1; +} + +/* Duplicate xf86 options and convert them to InputOption */ +static InputOption *EvdevOptionDupConvert(pointer original) +{ + InputOption *iopts = NULL, *new; + InputInfoRec dummy; + + memset(&dummy, 0, sizeof(dummy)); + dummy.options = xf86OptionListDuplicate(original); + + while(dummy.options) + { + if (xf86NameCmp(xf86OptionName(dummy.options), "config_info") == 0) { + /*should not copy config_info as its used by hotplugging layer*/ + dummy.options = xf86NextOption(dummy.options); + continue; + } + new = calloc(1, sizeof(struct _InputOption)); + if (!new) return iopts; + + new->opt_name = xf86OptionName(dummy.options); + new->opt_val = xf86OptionValue(dummy.options); + new->list.next = iopts; + iopts = new; + dummy.options = xf86NextOption(dummy.options); + } + + return iopts; +} + +static void EvdevFreeInputOpts(InputOption* opts) +{ + InputOption *tmp = opts; + while(opts) + { + tmp = opts->list.next; + free(opts->opt_name); + free(opts->opt_val); + free(opts); + opts = tmp; + } +} + +static void EvdevReplaceOption(InputOption *opts,const char* key, char * value) +{ + while(opts) + { + if (xf86NameCmp(opts->opt_name, key) == 0) + { + free(opts->opt_val); + opts->opt_val = strdup(value); + } + opts = opts->list.next; + } +} + + +/* +* @return 0 if successful, 1 if failure pProxyDeviceInfo +*/ +static InputInfoPtr +EvdevCreateProxyDevice(InputInfoPtr pInfo) { + InputInfoPtr pProxyDev; + + DeviceIntPtr dev; /* dummy */ + InputOption *input_options = NULL; + char* name; + char str_OPT_TYPE_VAL[sizeof(OPT_TYPE_VAL)]; + char str_dev_null[sizeof("/dev/null")]; + + pInfo->options = xf86AddNewOption(pInfo->options, "Type", "core"); + pInfo->options = xf86AddNewOption(pInfo->options, "SendCoreEvents", "on"); + + /* Create new device */ + input_options = EvdevOptionDupConvert(pInfo->options); + snprintf(str_OPT_TYPE_VAL, sizeof(OPT_TYPE_VAL), OPT_TYPE_VAL); + EvdevReplaceOption(input_options, "type",str_OPT_TYPE_VAL); + + name = malloc( (strlen(PROXY_DEV_NAME) + 1)*sizeof(char)); + + if( !name ) + { + EvdevFreeInputOpts(input_options); + xf86DrvMsg(-1, X_ERROR, "[X11][%s] Failed to allocate memory !\n", __FUNCTION__); + return NULL; + } + + snprintf(name, strlen(PROXY_DEV_NAME)+1, PROXY_DEV_NAME); + snprintf(str_dev_null, sizeof("/dev/null"), "/dev/null"); + EvdevReplaceOption(input_options, "name",name); + EvdevReplaceOption(input_options, "Device",str_dev_null); + EvdevReplaceOption(input_options, "Path",str_dev_null); + + pCreatorInfo = pInfo; + NewInputDeviceRequest(input_options, NULL, &dev); + pProxyDev = dev->public.devicePrivate; + pCreatorInfo = NULL; + + EvdevFreeInputOpts(input_options); + + free(name); + return pProxyDev; +} + +static void +EvdevProxydevReadInput(InputInfoPtr pInfo) +{ + +} + +static void +MakeClassesChangedEvent(DeviceChangedEvent *dce, + DeviceIntPtr master, DeviceIntPtr slave, int flags) +{ + int i; + CARD32 ms = GetTimeInMillis(); + + memset(dce, 0, sizeof(DeviceChangedEvent)); + dce->deviceid = slave->id; + dce->masterid = master ? master->id : 0; + dce->header = ET_Internal; + dce->length = sizeof(DeviceChangedEvent); + dce->type = ET_DeviceChanged; + dce->time = ms; + dce->flags = flags; + dce->sourceid = slave->id; + + if (slave->button) { + dce->buttons.num_buttons = slave->button->numButtons; + for (i = 0; i < dce->buttons.num_buttons; i++) + dce->buttons.names[i] = slave->button->labels[i]; + } + if (slave->valuator) { + dce->num_valuators = slave->valuator->numAxes; + for (i = 0; i < dce->num_valuators; i++) { + dce->valuators[i].min = slave->valuator->axes[i].min_value; + dce->valuators[i].max = slave->valuator->axes[i].max_value; + dce->valuators[i].resolution = slave->valuator->axes[i].resolution; + dce->valuators[i].mode = slave->valuator->axes[i].mode; + dce->valuators[i].name = slave->valuator->axes[i].label; + dce->valuators[i].scroll = slave->valuator->axes[i].scroll; + } + } + if (slave->key) { + dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code; + dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code; + } +} +#ifndef _F_PROXY_DEVICE_CHANGE_SOURCE_ID +static void EvdevPostDevChangeEvent(InputInfoPtr pInfo) +{ + DeviceChangedEvent event; + DeviceIntPtr master = inputInfo.keyboard; + DeviceIntPtr dummyDevice = pInfo->dev; + int flag; + + if(master->last.slave == dummyDevice) { + return; + } + + flag = DEVCHANGE_KEYBOARD_EVENT | DEVCHANGE_SLAVE_SWITCH; + + MakeClassesChangedEvent(&event,master,dummyDevice,flag); + + master->last.slave = dummyDevice; + + mieqEnqueue (dummyDevice, (InternalEvent*)&event); +} +#else /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */ +static void EvdevCheckDevChange(EvdevPtr pEvdev, int deviceid) +{ + DeviceChangedEvent event; + DeviceIntPtr master; + DeviceIntPtr dummyDevice; + int flag; + if(!pProxyDeviceInfo || !pEvdev) return; + + //if proxydevice is created but is not used by the current device, + //reset the sourcedid of keyclass of the proxy device to its own id + //and return.. + if(pProxyDeviceInfo && !pEvdev->proxy_device) { + pProxyDeviceInfo->dev->key->sourceid = pProxyDeviceInfo->dev->id; + return; + } + + master = inputInfo.keyboard; + dummyDevice = pProxyDeviceInfo->dev; + + //if nothing has changed.. return + //the first check is for differentiating between attached slaves and the second + //differentiates between the floating slaves represented by the proxy device + if(master->last.slave == dummyDevice && + pProxyDeviceInfo->dev->key->sourceid == deviceid) { + return; + } + + flag = DEVCHANGE_KEYBOARD_EVENT | DEVCHANGE_SLAVE_SWITCH; + + MakeClassesChangedEvent(&event,master,dummyDevice,flag); + + master->last.slave = dummyDevice; + + //setting the source id of the device key class to the id of the actual slave it represents. + //clients can query the same to know which device the actual events are coming from + pProxyDeviceInfo->dev->key->sourceid = deviceid; + + mieqEnqueue (dummyDevice, (InternalEvent*)&event); +} +#endif /* _F_PROXY_DEVICE_CHANGE_SOURCE_ID */ +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ diff --git a/src/evdev.h b/src/evdev.h old mode 100755 new mode 100644 index 3dd3953..2fe2c77 --- a/src/evdev.h +++ b/src/evdev.h @@ -47,6 +47,16 @@ #include #endif +#ifdef ENABLE_TTRACE +#include + +#define TTRACE_BEGIN(NAME) traceBegin(TTRACE_TAG_INPUT, NAME) +#define TTRACE_END() traceEnd(TTRACE_TAG_INPUT) +#else //ENABLE_TTRACE +#define TTRACE_BEGIN(NAME) +#define TTRACE_END() +#endif //ENABLE_TTRACE + #ifdef _F_GESTURE_EXTENSION_ typedef enum _MTSyncType { @@ -59,6 +69,11 @@ typedef enum _MTSyncType enum EventType { +#ifdef _F_PROXY_DEVICE_ENABLED_ + ET_Motion = 6, + ET_DeviceChanged = 17, + ET_RawMotion = 24, +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ ET_MTSync = 0x7E, ET_Internal = 0xFF /* First byte */ }; @@ -76,6 +91,46 @@ struct _AnyEvent int y; }; +#ifdef _F_PROXY_DEVICE_ENABLED_ + +#define DEVCHANGE_SLAVE_SWITCH 0x2 +#define DEVCHANGE_KEYBOARD_EVENT 0x8 + +struct _DeviceChangedEvent { + unsigned char header; /**< Always ET_Internal */ + enum EventType type; /**< ET_DeviceChanged */ + int length; /**< Length in bytes */ + Time time; /**< Time in ms */ + int deviceid; /**< Device whose capabilities have changed */ + int flags; /**< Mask of ::HAS_NEW_SLAVE, + ::POINTER_EVENT, ::KEYBOARD_EVENT */ + int masterid; /**< MD when event was generated */ + int sourceid; /**< The device that caused the change */ + + struct { + int num_buttons; /**< Number of buttons */ + Atom names[MAX_BUTTONS];/**< Button names */ + } buttons; + + int num_valuators; /**< Number of axes */ + struct { + uint32_t min; /**< Minimum value */ + uint32_t max; /**< Maximum value */ + double value; /**< Current value */ + /* FIXME: frac parts of min/max */ + uint32_t resolution; /**< Resolution counts/m */ + uint8_t mode; /**< Relative or Absolute */ + Atom name; /**< Axis name */ + ScrollInfo scroll; /**< Smooth scrolling info */ + } valuators[MAX_VALUATORS]; + + struct { + int min_keycode; + int max_keycode; + } keys; +}; +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ + union _InternalEvent { struct { unsigned char header; /**< Always ET_Internal */ @@ -84,7 +139,16 @@ union _InternalEvent { Time time; /**< Time in ms. */ } any; AnyEvent any_event; +#ifdef _F_PROXY_DEVICE_ENABLED_ + DeviceChangedEvent changed_event; +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ }; + +#define GESTURE_DEV_NAME "Gesture" +/* Gesture driver will query devices information + * if a gesture driver's control function is called using DEVICE_READY*/ +#define DEVICE_READY 11 + #endif /* #ifdef _F_GESTURE_EXTENSION_ */ #ifndef EV_CNT /* linux 2.6.23 kernels and earlier lack _CNT defines */ @@ -113,6 +177,12 @@ union _InternalEvent { #define EVDEV_PRESS 1 #define EVDEV_RELEASE 0 +#ifdef _ENV_TV_ +#define EVDEV_RMS_TIMEOUT 5000 +#else +#define EVDEV_RMS_TIMEOUT 15000 +#endif //_ENV_TV_ + /* evdev flags */ #define EVDEV_KEYBOARD_EVENTS (1 << 0) #define EVDEV_BUTTON_EVENTS (1 << 1) @@ -143,6 +213,11 @@ union _InternalEvent { #define DEFAULT_HW_ROTARY_MAX 4360 #endif //_F_EVDEV_SUPPORT_ROTARY_ +#ifdef _F_EVDEV_SUPPORT_SMARTRC_ +#define EVDEV_SMART_RC (1 << 16) /* air touch mouse is special remote controller for smart tv */ +#define AIR_TOUCH_MOUSE "Advanced Touch REMOTE" +#endif //_F_EVDEV_SUPPORT_SMARTRC_ + #ifndef MAX_VALUATORS #define MAX_VALUATORS 36 #endif @@ -159,6 +234,18 @@ union _InternalEvent { #define XI_PROP_REL_MOVE_STATUS "Relative Move Status" #define XI_PROP_REL_MOVE_ACK "Relative Move Acknowledge" #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */ +#ifdef _F_BLOCK_MOTION_DEVICE_ +#define XI_PROP_BLOCK_MOTION_DEVICE "Block Motion Device" /*Atom to block motion device */ +#endif //_F_BLOCK_MOTION_DEVICE_ +#ifdef _F_PICTURE_OFF_MODE_ENABLE_ +#define XI_PROP_PICTURE_OFF_MODE "PICTURE_OFF_MODE" /* Atom to check picture off mode */ +#endif //_F_PICTURE_OFF_MODE_ENABLE_ + +#ifdef _F_PROXY_DEVICE_ENABLED_ +#define XI_PROP_USE_PROXY_SLAVE_DEVICE "Use Proxy Slave Device" +#endif /* #ifdef _F_PROXY_DEVICE_ENABLED_ */ + +#define XI_PROP_UNGRAB_DEVICE "Ungrab Device" #define LONG_BITS (sizeof(long) * 8) @@ -191,6 +278,14 @@ typedef struct { int traveled_distance; } WheelAxis, *WheelAxisPtr; +#ifdef _F_MULTI_PASSIVE_GRAB_ +typedef struct _ActivatedKeyList +{ + CARD8 keycode; + struct xorg_list list; +} ActivatedKeyList; +#endif //_F_MULTI_PASSIVE_GRAB_ + /* Event queue used to defer keyboard/button events until EV_SYN time. */ typedef struct { enum { @@ -211,7 +306,7 @@ typedef struct { #ifdef MULTITOUCH ValuatorMask *touchMask; #endif -} EventQueueRec, *EventQueuePtr; +} EvdevEventQueueRec, *EvdevEventQueuePtr; #ifdef _F_REMAP_KEYS_ typedef struct { @@ -223,6 +318,10 @@ typedef struct { #endif //_F_REMAP_KEYS_ typedef struct { +#ifdef _F_MULTI_PASSIVE_GRAB_ + ActivatedKeyList *activatedkeylist; +#endif //_F_MULTI_PASSIVE_GRAB_ + unsigned short id_vendor; unsigned short id_product; @@ -230,6 +329,7 @@ typedef struct { int grabDevice; /* grab the event device? */ int num_vals; /* number of valuators */ + int num_mt_vals; /* number of multitouch valuators */ int axis_map[max(ABS_CNT, REL_CNT)]; /* Map evdev to index */ ValuatorMask *vals; /* new values coming in */ ValuatorMask *old_vals; /* old values for calculating relative motion */ @@ -324,7 +424,7 @@ typedef struct { #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ BOOL rel_move_status; BOOL rel_move_prop_set; - BOOL rel_move_ack; + int rel_move_ack; OsTimerPtr rel_move_timer; #endif /* #ifdef _F_ENABLE_REL_MOVE_STATUS_PROP_ */ Bool block_handler_registered; @@ -371,12 +471,17 @@ typedef struct { BOOL use_default_xkb_rmlvo; #endif//_F_USE_DEFAULT_XKB_RULES_ +#ifdef _F_SUPPORT_ROTATION_ANGLE_ + int rotation_angle; + int rotation_node; +#endif// _F_SUPPORT_ROTATION_ANGLE_ + /* minor/major number */ dev_t min_maj; /* Event queue used to defer keyboard/button events until EV_SYN time. */ int num_queue; - EventQueueRec queue[EVDEV_MAXQUEUE]; + EvdevEventQueueRec queue[EVDEV_MAXQUEUE]; enum fkeymode fkeymode; @@ -385,6 +490,21 @@ typedef struct { void (*extra_rel_post_hallic) (InputInfoPtr pInfo, int num_v, int first_v, int v[MAX_VALUATORS]); int HW_Calibration; #endif //_F_EVDEV_SUPPORT_ROTARY_ +#ifdef _F_EVDEV_SUPPORT_SMARTRC_ + int rc_state; +#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_ + int (*extra_input_process) (InputInfoPtr *ppInfo, struct input_event *ev); +#else + int (*extra_input_process) (InputInfoPtr pInfo, struct input_event *ev); +#endif + void (*origin_input_process) (InputInfoPtr pInfo, struct input_event *ev); +#endif //_F_EVDEV_SUPPORT_SMARTRC_ + +#ifdef _F_PROXY_DEVICE_ENABLED_ + Bool proxy_enabled; + Bool b_proxy_device; + InputInfoPtr proxy_device; +#endif //_F_PROXY_DEVICE_ENABLED_ } EvdevRec, *EvdevPtr; /* Event posting functions */ @@ -445,7 +565,13 @@ static void EvdevMappingGamepadKeyToKey(InputInfoPtr pInfo, struct input_event static int EvdevIsGamePad(InputInfoPtr pInfo); #endif//_F_EVDEV_SUPPORT_GAMEPAD static void EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev); -#endif #ifdef _F_USE_DEFAULT_XKB_RULES_ void EvdevGetXkbRules(DeviceIntPtr device, XkbRMLVOSet * rmlvo); -#endif //_F_USE_DEFAULT_XKB_RULES_ \ No newline at end of file +#endif //_F_USE_DEFAULT_XKB_RULES_ +#ifdef _F_EVDEV_SUPPORT_SMARTRC_ +void EvdevRCInit(DeviceIntPtr device); +#endif //_F_EVDEV_SUPPORT_SMARTRC_ +#ifdef _F_PROXY_DEVICE_ENABLED_ +void EvdevProxyInit(DeviceIntPtr device); +#endif //_F_PROXY_DEVICE_ENABLED_ +#endif \ No newline at end of file diff --git a/src/proxyDev.c b/src/proxyDev.c new file mode 100644 index 0000000..148d615 --- /dev/null +++ b/src/proxyDev.c @@ -0,0 +1,303 @@ +/* + * + * xserver-xorg-input-evdev + * + * Contact: Sung-Jin Park + * Sangjin LEE + * Jeonghyun Kang + * + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright © 2004-2008 Red Hat, Inc. + * + * 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 Red Hat + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. Red + * Hat makes 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 THE AUTHORS 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. + * + * Authors: + * Kristian Høgsberg (krh@redhat.com) + * Adam Jackson (ajax@redhat.com) + * Peter Hutterer (peter.hutterer@redhat.com) + * Oliver McFadden (oliver.mcfadden@nokia.com) + */ + +#ifdef _F_PROXY_DEVICE_ENABLED_ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "evdev.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +struct _DeviceEvent { + unsigned char header; /**< Always ET_Internal */ + enum EventType type; /**< One of EventType */ + int length; /**< Length in bytes */ + Time time; /**< Time in ms */ + int deviceid; /**< Device to post this event for */ + int sourceid; /**< The physical source device */ + union { + uint32_t button; /**< Button number (also used in pointer emulating + touch events) */ + uint32_t key; /**< Key code */ + } detail; + uint32_t touchid; /**< Touch ID (client_id) */ + int16_t root_x; /**< Pos relative to root window in integral data */ + float root_x_frac; /**< Pos relative to root window in frac part */ + int16_t root_y; /**< Pos relative to root window in integral part */ + float root_y_frac; /**< Pos relative to root window in frac part */ + uint8_t buttons[(MAX_BUTTONS + 7) / 8]; /**< Button mask */ + struct { + uint8_t mask[(MAX_VALUATORS + 7) / 8];/**< Valuator mask */ + uint8_t mode[(MAX_VALUATORS + 7) / 8];/**< Valuator mode (Abs or Rel)*/ + double data[MAX_VALUATORS]; /**< Valuator data */ + } valuators; + struct { + uint32_t base; /**< XKB base modifiers */ + uint32_t latched; /**< XKB latched modifiers */ + uint32_t locked; /**< XKB locked modifiers */ + uint32_t effective;/**< XKB effective modifiers */ + } mods; + struct { + uint8_t base; /**< XKB base group */ + uint8_t latched; /**< XKB latched group */ + uint8_t locked; /**< XKB locked group */ + uint8_t effective;/**< XKB effective group */ + } group; + Window root; /**< Root window of the event */ + int corestate; /**< Core key/button state BEFORE the event */ + int key_repeat; /**< Internally-generated key repeat event */ + uint32_t flags; /**< Flags to be copied into the generated event */ + uint32_t resource; /**< Touch event resource, only for TOUCH_REPLAYING */ +}; + +typedef struct _barrierBoundary { + unsigned int x1; + unsigned int y1; + unsigned int x2; + unsigned int y2; +} barrierBoundary; + +typedef enum _barrierState { + BARRIER_NONE, + BARRIER_INSIDE, + BARRIER_OUTSIDE +} barrierState; + +#define prop_MLS_Barrier_Boundary "MLS_Barrier_Boundary" +#define prop_MLS_Barrier_Hit "MLS_Barrier_Hit" + +static void EvdevProxyBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead); +void EvdevProxySetBarrierBoundary(int num, unsigned int val[4], barrierBoundary *boundary); +barrierState EvdevProxyLocationManager(int x, int y, barrierBoundary boundary); +void EvdevProxyProcessMotion(int screen_num, InternalEvent *ev, DeviceIntPtr device); +void EvdevProxyProcessRawMotion(int screen_num, InternalEvent *ev, DeviceIntPtr device); +static int EvdevProxySetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly); +static int EvdevProxyDeleteProperty(DeviceIntPtr dev, Atom atom); + +DeviceIntPtr proxyDev; + +/* MLS Barrier */ +barrierBoundary BarrierBoundary; +barrierState BarrierState; +Atom atom_MLS_Barrier_Boundary; +Atom atom_MLS_Barrier_Hit; + +/* Ungrab device */ +static Atom prop_ungrab_device; + +int last_id; +#define VCP_ID 2 + +static void +EvdevProxyBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) +{ + InputInfoPtr pInfo = (InputInfoPtr)data; + int rc = 0; + + RemoveBlockAndWakeupHandlers(EvdevProxyBlockHandler, + (WakeupHandlerProcPtr)NoopDDA, + data); + + if (BarrierState != BARRIER_NONE) + rc = XIChangeDeviceProperty(pInfo->dev, atom_MLS_Barrier_Hit, XA_INTEGER, 32, + PropModeReplace, 1, &BarrierState, TRUE); + + if (rc != Success) + { + xf86IDrvMsg(pInfo, X_ERROR, "[%s:%d] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, __LINE__, pInfo->dev->id, atom_MLS_Barrier_Hit); + } +} + +void EvdevProxySetBarrierBoundary(int num, unsigned int val[4], barrierBoundary *boundary) +{ + if (num == 0) { + if (BarrierState != BARRIER_NONE) ErrorF("[%s:%d] Unset MLS Barrier Boundary\n", __FUNCTION__, __LINE__); + boundary->x1 = 0; + boundary->x2 = 0; + boundary->y1 = 0; + boundary->y2 = 0; + BarrierState = BARRIER_NONE; + } + else { + ErrorF("[%s:%d] Set MLS Barrier Boundary (%d, %d) (%d, %d)\n", __FUNCTION__, __LINE__, val[0], val[1], val[2], val[3]); + boundary->x1 = val[0]; + boundary->x2 = val[2]; + boundary->y1 = val[1]; + boundary->y2 = val[3]; + } +} + +barrierState EvdevProxyLocationManager(int x, int y, barrierBoundary boundary) +{ + if ((boundary.x1+boundary.y1+boundary.x2+boundary.y2) <= 0 ) { + return BARRIER_NONE; + } + else if ( (boundary.x1 <= x && x <=boundary.x2) + && (boundary.y1 <= y && y <=boundary.y2) ) { + return BARRIER_INSIDE; + } + return BARRIER_OUTSIDE; +} + +void EvdevProxyProcessRawMotion(int screen_num, InternalEvent * ev,DeviceIntPtr device) +{ + if (device->id != VCP_ID) + last_id = device->id; + device->public.processInputProc(ev, device); +} + +void EvdevProxyProcessMotion(int screen_num, InternalEvent * ev,DeviceIntPtr device) +{ + DeviceEvent *dev = &(ev->changed_event); + barrierState prevBarrierState = BarrierState; + if (!dev) { + ErrorF("[%s:%d] It is not a device event\n", __FUNCTION__, __LINE__); + goto process_event; + } + if (last_id != device->id) { + last_id = 0; + goto process_event; + } + + BarrierState = EvdevProxyLocationManager(dev->root_x, dev->root_y, BarrierBoundary); + if (BarrierState == BARRIER_NONE) + goto process_event; + else if (prevBarrierState == BarrierState) + goto process_event; + else if (prevBarrierState == BARRIER_INSIDE) { + ErrorF("[%s:%d] Pointer in to barrier from outside\n", __FUNCTION__, __LINE__); + OsBlockSIGIO(); + RegisterBlockAndWakeupHandlers(EvdevProxyBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, (InputInfoPtr)(proxyDev->public.devicePrivate)); + OsReleaseSIGIO(); + } + else if (prevBarrierState == BARRIER_OUTSIDE) { + ErrorF("[%s:%d] Pointer out to barrier from inside\n", __FUNCTION__, __LINE__); + OsBlockSIGIO(); + RegisterBlockAndWakeupHandlers(EvdevProxyBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, (InputInfoPtr)(proxyDev->public.devicePrivate)); + OsReleaseSIGIO(); + } + else if (prevBarrierState == BARRIER_NONE && BarrierState == BARRIER_INSIDE) { + ErrorF("[%s:%d] Pointer move start from inside\n", __FUNCTION__, __LINE__); + OsBlockSIGIO(); + RegisterBlockAndWakeupHandlers(EvdevProxyBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, (InputInfoPtr)(proxyDev->public.devicePrivate)); + OsReleaseSIGIO(); + } + last_id = 0; +process_event: + device->public.processInputProc(ev, device); +} + +void EvdevProxyInit(DeviceIntPtr device) +{ + InputInfoPtr pInfo = device->public.devicePrivate;; + EvdevPtr pEvdev = pInfo->private; + + XIRegisterPropertyHandler(device, EvdevProxySetProperty, NULL, EvdevProxyDeleteProperty); + mieqSetHandler(ET_Motion, EvdevProxyProcessMotion); + mieqSetHandler(ET_RawMotion, EvdevProxyProcessRawMotion); + + proxyDev = device; + + BarrierBoundary.x1 = 0; + BarrierBoundary.y1 = 0; + BarrierBoundary.x2 = 0; + BarrierBoundary.y2 = 0; + BarrierState = BARRIER_NONE; + + last_id = 0; + + atom_MLS_Barrier_Boundary = MakeAtom(prop_MLS_Barrier_Boundary, strlen(prop_MLS_Barrier_Boundary), TRUE); + atom_MLS_Barrier_Hit = MakeAtom(prop_MLS_Barrier_Hit, strlen(prop_MLS_Barrier_Hit), TRUE); + prop_ungrab_device = MakeAtom(XI_PROP_UNGRAB_DEVICE, strlen(XI_PROP_UNGRAB_DEVICE), TRUE); +} + +static int +EvdevProxySetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, + BOOL checkonly) +{ + if (atom == atom_MLS_Barrier_Boundary) { + if (val->format != 32 || val->type != XA_INTEGER) + return BadMatch; + if (val->size != 4 && val->size != 0) + return BadMatch; + + if (!checkonly) { + EvdevProxySetBarrierBoundary(val->size, val->data, &BarrierBoundary); + } + } + + else if (atom == prop_ungrab_device ) + { + int data; + DeviceIntPtr master = inputInfo.pointer; + + if(!checkonly) { + data = *((CARD8*)val->data); + if (data == 1 && master->deviceGrab.grab) { + ErrorF("[%s:%d] ungrab master pointer device(%d) in device (%d)\n", __FUNCTION__, __LINE__, master->id, dev->id); + (*master->deviceGrab.DeactivateGrab) (master); + } + } + } + + return Success; +} + +static int +EvdevProxyDeleteProperty(DeviceIntPtr dev, Atom atom) +{ + if (atom == atom_MLS_Barrier_Boundary) { + EvdevProxySetBarrierBoundary(0, NULL, &BarrierBoundary); + } + + return Success; +} +#endif //_F_PROXY_DEVICE_ENABLED_ diff --git a/src/rotary.c b/src/rotary.c old mode 100755 new mode 100644 diff --git a/src/smartRC.c b/src/smartRC.c new file mode 100644 index 0000000..d69ca9f --- /dev/null +++ b/src/smartRC.c @@ -0,0 +1,726 @@ +/* + * + * xserver-xorg-input-evdev + * + * Contact: Sung-Jin Park + * Sangjin LEE + * Jeonghyun Kang + * + * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright © 2004-2008 Red Hat, Inc. + * + * 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 Red Hat + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. Red + * Hat makes 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 THE AUTHORS 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. + * + * Authors: + * Kristian Høgsberg (krh@redhat.com) + * Adam Jackson (ajax@redhat.com) + * Peter Hutterer (peter.hutterer@redhat.com) + * Oliver McFadden (oliver.mcfadden@nokia.com) + */ + +#ifdef _F_EVDEV_SUPPORT_SMARTRC_ + #ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define ABS(x) (((x) < 0) ? -(x) : (x)) +#define XI_PROP_TOUCH_ON "Evdev SmartRC Moved" +#define XI_PROP_SMARTRC_DISCANCE_MOVED "Evdev SmartRC Distance Moved" +#define XI_PROP_START_CALCULATE_DISTANCE "Start Calcualting Distance" + +#define IF_KEY_CODE_TOUCH (ev->code == BTN_EXTRA || ev->code == BTN_SIDE) +#define IF_NOT_KEY_CODE_TOUCH (ev->code != BTN_EXTRA && ev->code != BTN_SIDE) + +static Atom atomDistanceMoved; +static Atom atomCalculateDistance; +static Atom prop_move_start; +static int calculateDistance=0; +#define INITIAL_CURSOR_DISTANCE_TO_MOVE 0 + +#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_ +static InputInfoPtr pSmartRCKbdDeviceInfo = NULL; +#endif +extern int block_motion_device; + +enum device_state +{ + STATE_NONE=0, + STATE_NORMAL, + RC_STATE_DR_KEY, + RC_STATE_AIR_TOUCH +}; + +enum abs_move_state +{ + ABS_MOVE_END=0, + ABS_MOVE_ON, + ABS_MOVE_START +}; + +enum scroll_direction_state +{ + SCROLL_NONE=0, + SCROLL_VERTICAL, + SCROLL_HORIZEN +}; + +static void EvdevRCBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead); +static void EvdevRCBlockHandlerFor2014(pointer data, OSTimePtr pTimeout, pointer pRead); +#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_ +static int EvdevRCProcessEvent(InputInfoPtr *ppInfo, struct input_event *ev); +#else +static int EvdevRCProcessEvent(InputInfoPtr pInfo, struct input_event *ev); +#endif +int EvdevRCProcessNormalState(InputInfoPtr pInfo, struct input_event *ev); +int EvdevRCProcessDRKeyState(InputInfoPtr pInfo, struct input_event *ev); +void EvdevRCWheelScroll(InputInfoPtr pInfo, struct input_event *ev); +int EvdevRCProcessAirTouchState(InputInfoPtr pInfo, struct input_event *ev, int check_boundary); +int EvdevRCIsSwipe(struct input_event *ev); +void EvdevRCSendEvent(InputInfoPtr pInfo, int type, int code, int value); +int EvdevRCIsBoundary(struct input_event *ev, int rc_range); +static int EvdevSetProperty(DeviceIntPtr dev, Atom atom, + XIPropertyValuePtr val, BOOL checkonly); + +typedef struct _tagRCState +{ + int velocity; + int velo_time; + int move_state; + BOOL is_touch_on; + BOOL isSmartRC_15; + Atom atomTouchOn; +}RCState, *RCStatePtr; + +RCState rcstate; + +static void +EvdevRCBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) +{ + InputInfoPtr pInfo = (InputInfoPtr)data; + int rc; + + RemoveBlockAndWakeupHandlers(EvdevRCBlockHandler, + (WakeupHandlerProcPtr)NoopDDA, + data); + + ErrorF("15 RCBlock Handler Called, [%d] is_touch_on: %d\n", pInfo->dev->id, rcstate.is_touch_on); + + if (rcstate.is_touch_on == TRUE) + { + rc = XIChangeDeviceProperty(pInfo->dev, rcstate.atomTouchOn, XA_INTEGER, 8, + PropModeReplace, 1, &rcstate.is_touch_on, TRUE); + + // In case of 2015 smartRC, cursor is enable when touch on device. (prop_move_start is set to "1") + if (block_motion_device == 0) + rc = XIChangeDeviceProperty(pInfo->dev, prop_move_start, XA_INTEGER, 8, + PropModeReplace, 1, &rcstate.is_touch_on, TRUE); + } + else + rc = XIDeleteDeviceProperty(pInfo->dev, rcstate.atomTouchOn, TRUE); + + if (rc != Success) + { + xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, (int)rcstate.atomTouchOn); + } +} + +static void +EvdevRCBlockHandlerFor2014(pointer data, OSTimePtr pTimeout, pointer pRead) +{ + InputInfoPtr pInfo = (InputInfoPtr)data; + int rc; + + RemoveBlockAndWakeupHandlers(EvdevRCBlockHandlerFor2014, + (WakeupHandlerProcPtr)NoopDDA, + data); + + ErrorF("14 RCBlock Handler Called, [%d] is_touch_on: %d\n", pInfo->dev->id, rcstate.is_touch_on); + + if (rcstate.is_touch_on == TRUE) + { + rc = XIChangeDeviceProperty(pInfo->dev, rcstate.atomTouchOn, XA_INTEGER, 8, + PropModeReplace, 1, &rcstate.is_touch_on, TRUE); + } + else + rc = XIDeleteDeviceProperty(pInfo->dev, rcstate.atomTouchOn, TRUE); + + if (rc != Success) + { + xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, (int)rcstate.atomTouchOn); + } +} + +#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_ +static int EvdevRCProcessEvent(InputInfoPtr *ppInfo, struct input_event *ev) +#else +static int EvdevRCProcessEvent(InputInfoPtr pInfo, struct input_event *ev) +#endif +{ +#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_ + InputInfoPtr pInfo = *ppInfo; +#endif + EvdevPtr pEvdev = pInfo->private; + int res = 0; + // Start of Coord Cal + static int mismatchX = 0, mismatchY = 0; + + if( rcstate.isSmartRC_15 == TRUE && ev->type == EV_ABS ) + { + if(ev->code == ABS_X) + { + int calX = ev->value - pInfo->dev->spriteInfo->sprite->hot.x; + if(calX == 0) + { + mismatchX = 0; + return 0; + } + if(++mismatchX < 10) + { + return 0; + } + mismatchX = 0; + ev->type = EV_REL; + ev->code = REL_X; + ev->value = calX; + } + if(ev->code == ABS_Y) + { + int calY = ev->value - pInfo->dev->spriteInfo->sprite->hot.y; + if(calY == 0) + { + mismatchY = 0; + return 0; + } + if(++mismatchY < 10) + { + return 0; + } + mismatchY = 0; + ev->type = EV_REL; + ev->code = REL_Y; + ev->value = calY; + } + } + // End of Coord Cal + + if (pEvdev->rel_move_ack == 3 || block_motion_device == 1) + { + if (ev->type == EV_REL || ev->type == EV_ABS) + { + return res; + } + if (ev->type == EV_KEY && ev->code == BTN_LEFT) + { + ev->code = KEY_ENTER; + } + } + + if (ev->type == EV_KEY && ev->code == BTN_EXTRA) + { + if (ev->value == 0) + { + rcstate.move_state = ABS_MOVE_END; + rcstate.is_touch_on = FALSE; + rcstate.isSmartRC_15 = FALSE; + } + else if (ev->value == 1) + { + rcstate.move_state = ABS_MOVE_ON; + rcstate.is_touch_on = TRUE; + rcstate.isSmartRC_15 = TRUE; + } + OsBlockSIGIO(); + RegisterBlockAndWakeupHandlers(EvdevRCBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, pInfo); + OsReleaseSIGIO(); + } + else if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_SYN) + { + rcstate.move_state = ABS_MOVE_START; + } + + + if (ev->type == EV_KEY && ev->code == BTN_SIDE) + { + if (ev->value == 0) + { + rcstate.move_state = ABS_MOVE_END; + rcstate.is_touch_on = FALSE; + } + else if (ev->value == 1) + { + rcstate.move_state = ABS_MOVE_ON; + rcstate.is_touch_on = TRUE; + } + OsBlockSIGIO(); + RegisterBlockAndWakeupHandlers(EvdevRCBlockHandlerFor2014 ,(WakeupHandlerProcPtr) NoopDDA, pInfo); + OsReleaseSIGIO(); + } + else if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_SYN) + { + rcstate.move_state = ABS_MOVE_START; + } + + switch (pEvdev->rc_state) + { + case STATE_NORMAL: + res = EvdevRCProcessNormalState(pInfo, ev); + break; + case RC_STATE_DR_KEY: + res = EvdevRCProcessDRKeyState(pInfo, ev); + break; + case RC_STATE_AIR_TOUCH: + res = EvdevRCProcessAirTouchState(pInfo, ev, 1); + break; + default: + break; + } + + if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH) + return 0; + else +#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_ + { + if (pEvdev->rc_state == RC_STATE_DR_KEY) + { + if(pSmartRCKbdDeviceInfo) *ppInfo = pSmartRCKbdDeviceInfo; + } + } +#endif + return res; +} + +int EvdevRCProcessNormalState(InputInfoPtr pInfo, struct input_event *ev) +{ + EvdevPtr pEvdev = pInfo->private; + int res = 0; + + if (ev->type == EV_REL || ev->type == EV_ABS) + return res; + + if (ev->type == EV_KEY) + { + if (IF_KEY_CODE_TOUCH && ev->value == 1) + { + pEvdev->rc_state = RC_STATE_AIR_TOUCH; + res = EvdevRCProcessAirTouchState(pInfo, ev, 1); + } + else if ( (ev->code == KEY_UP || ev->code == KEY_LEFT || ev->code == KEY_DOWN || ev->code == KEY_RIGHT || ev->code == KEY_ENTER) + && (ev->value == 1)) + { + pEvdev->rc_state = RC_STATE_DR_KEY; + res = EvdevRCProcessDRKeyState(pInfo, ev); + } + else if (IF_KEY_CODE_TOUCH && ev->value == 0) + { + return res; + } + else + res = 1; + } + else + res = 1; + + return res; +} + +int EvdevRCProcessDRKeyState(InputInfoPtr pInfo, struct input_event *ev) +{ + EvdevPtr pEvdev = pInfo->private; + int res = 0; + static int pressed_flag = 0; + static BOOL extra_pressed = FALSE; + static int last_key = -1; + + if (ev->type == EV_KEY && ev->code == BTN_LEFT) + { + ev->code = KEY_ENTER; + } + + if (ev->type == EV_KEY && IF_NOT_KEY_CODE_TOUCH) + { + if ( (last_key >= 0) && (ev->code != last_key)) + { + return res; + } + if (ev->value == 1) { + pressed_flag++; + last_key = ev->code; + } + else { + pressed_flag--; + last_key = -1; + if (pressed_flag<0) + pressed_flag = 0; + } + } + else if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH) + { + if (pressed_flag == 0) + { + res = EvdevRCProcessAirTouchState(pInfo, ev, 0); + extra_pressed = FALSE; + } + else if (ev->value == 1) + { + extra_pressed = TRUE; + } + else + { + extra_pressed = FALSE; + } + } + if (extra_pressed == TRUE && (ev->type == EV_REL || ev->type == EV_ABS)) + { + return res; + } + + if ((pressed_flag==0) && block_motion_device == 0) + { + if (rcstate.isSmartRC_15 == TRUE) + { + pEvdev->rc_state = RC_STATE_AIR_TOUCH; + res = EvdevRCProcessAirTouchState(pInfo, ev, 0); + return res; + } + else + { + // calculate distance to change air touch mode(2014 smartRC) + if(EvdevRCIsBoundary(ev, 150)) + { + pEvdev->rc_state = RC_STATE_AIR_TOUCH; + res = EvdevRCProcessAirTouchState(pInfo, ev, 0); + return res; + } + } + } + + if (ev->type == EV_REL || ev->type == EV_ABS) + { + return res; + } + else + res = 1; + + return res; + +} + +int EvdevRCProcessAirTouchState(InputInfoPtr pInfo, struct input_event *ev, int check_boundary) +{ + EvdevPtr pEvdev = pInfo->private; + int res = 0; + int rc; + int temp_res; + + if( calculateDistance && EvdevRCIsBoundary(ev, INITIAL_CURSOR_DISTANCE_TO_MOVE)) + { + rc = XIChangeDeviceProperty(pInfo->dev, atomDistanceMoved, XA_INTEGER, 8, + PropModeReplace, 1, &pEvdev->rel_move_status, TRUE); + if (rc != Success) + ErrorF("[EvdevRCProcessAirTouchState] Failed to change atomDistanceMoved\n"); + calculateDistance=0; + } + + if (ev->type == EV_KEY && (IF_NOT_KEY_CODE_TOUCH && ev->code != BTN_LEFT)) + return res; + + if (ev->type == EV_REL && (ev->code == REL_HWHEEL || ev->code == REL_WHEEL)) + { + res = 1; + return res; + } + + if (ev->type == EV_ABS || (ev->type == EV_KEY && IF_KEY_CODE_TOUCH) || ev->type == EV_SYN) + { + EvdevRCWheelScroll(pInfo, ev); + } + + if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH && ev->value == 0) + { + temp_res = EvdevRCIsBoundary(ev, 0); + if (pEvdev->rc_state != RC_STATE_DR_KEY) + pEvdev->rc_state = STATE_NORMAL; + if (temp_res == 1) + res = temp_res; + return res; + } + else if (check_boundary && ev->type == EV_REL) + { + if (!EvdevRCIsBoundary(ev, 0)) + return res; + else + { + if (block_motion_device == 0) + pEvdev->rc_state = RC_STATE_AIR_TOUCH; + } + } + + res = 1; + + return res; +} + +void EvdevRCWheelScroll(InputInfoPtr pInfo, struct input_event *ev) +{ + static int before_x=-1, before_y=-1; + static int before_x_utime = -1, before_y_utime = -1; + static int before_x_time = -1, before_y_time = -1; + + int time_diff = 0; + float velo_x=0; + + float velo_y = 0; + static int velo_y_count=0, velo_x_count = 0; + + static int wheel_direction_flag = SCROLL_NONE; + + if (ev->type == EV_REL || ev->type == EV_SYN) + return; + if (ev->type == EV_KEY && IF_NOT_KEY_CODE_TOUCH) + return; + + if (ev->type == EV_KEY) + wheel_direction_flag = SCROLL_NONE; + + if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_ABS) + { + velo_y_count=0; + if (ev->code == ABS_X) + { + before_x = ev->value; + before_x_time = ev->time.tv_sec; + before_x_utime = ev->time.tv_usec; + + if ((before_x < 150) || (350 < before_x)) + { + wheel_direction_flag = SCROLL_HORIZEN; + } + return; + } + else if (ev->code == ABS_Y) + { + before_y = ev->value; + before_y_time = ev->time.tv_sec; + before_y_utime = ev->time.tv_usec; + + if ((before_y < 150) || (350 < before_y)) + { + wheel_direction_flag = SCROLL_VERTICAL; + } + return; + } + } + + if (ev->type == EV_ABS && ev->code == ABS_X && wheel_direction_flag != SCROLL_VERTICAL) + { + time_diff = (ev->time.tv_sec - before_x_time) * 1000 + (ev->time.tv_usec - before_x_utime)/1000; + if (time_diff == 0) + { + ErrorF("before and current events had same event time...\n"); + return; + } + + velo_x = (float)((ABS(before_x - ev->value)) / time_diff); + + if (velo_x > 1) + { + velo_x_count = velo_x_count + (int)velo_x; + } + + if (velo_x_count > 2) + { + wheel_direction_flag = SCROLL_HORIZEN; + velo_x_count = (velo_x_count / 4); + if (velo_x_count > 2) + velo_x_count = velo_x_count * 2; + + EvdevRCSendEvent(pInfo, EV_REL, REL_HWHEEL, ((before_x - ev->value) < 0)? -velo_x_count: velo_x_count); + velo_x_count = 0; + } + + before_x = ev->value; + before_x_time = ev->time.tv_sec; + before_x_utime = ev->time.tv_usec; + } + else if (ev->type == EV_ABS && ev->code == ABS_Y && wheel_direction_flag != SCROLL_HORIZEN) + { + time_diff = (ev->time.tv_sec - before_y_time) * 1000 + (ev->time.tv_usec - before_y_utime)/1000; + if (time_diff == 0) + { + ErrorF("before and current events had same event time...\n"); + return; + } + velo_y = (float)((ABS(before_y - ev->value)) / time_diff); + + if (velo_y > 1) + { + velo_y_count = velo_y_count + (int)velo_y; + } + + if (velo_y_count > 2) + { + wheel_direction_flag = SCROLL_VERTICAL; + velo_y_count = (velo_y_count / 4); + if (velo_y_count > 2) + velo_y_count = velo_y_count * 2; + + EvdevRCSendEvent(pInfo, EV_REL, REL_WHEEL, ((before_y - ev->value) < 0)? -velo_y_count: velo_y_count); + velo_y_count = 0; + } + + before_y = ev->value; + before_y_time = ev->time.tv_sec; + before_y_utime = ev->time.tv_usec; + } +} + +int EvdevRCIsSwipe(struct input_event *ev) +{ + int res = 0; + static int base_point_x = -1; + static int base_point_y = -1; + + if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH) + { + base_point_x = -1; + base_point_y = -1; + } + + if (ev->type == EV_ABS) + { + if (ev->code == ABS_X) + { + if (base_point_x == -1) + { + base_point_x = ev->value; + } + else if (ABS(base_point_x - ev->value) > 300) + { + res = 1; + } + } + else if (ev->code == ABS_Y) + { + if (base_point_y == -1) + { + base_point_y = ev->value; + } + else if (ABS(base_point_y - ev->value) > 300) + { + res = 1; + } + } + } + + return res; +} + +void EvdevRCSendEvent(InputInfoPtr pInfo, int type, int code, int value) +{ + EvdevPtr pEvdev = pInfo->private; + struct input_event ev; + + ev.type = type; + ev.code = code; + ev.value = value; + + pEvdev->origin_input_process(pInfo, &ev); +} + +static int +EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, + BOOL checkonly) +{ + InputInfoPtr pInfo = dev->public.devicePrivate; + EvdevPtr pEvdev = pInfo->private; + + if (atom == atomCalculateDistance ) + { + calculateDistance=1; + } + return 0; +} +int EvdevRCIsBoundary(struct input_event *ev, int rc_range) +{ + static int x_diff=0, y_diff = 0; + int res = 0; + + if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH) + { + x_diff = y_diff = 0; + } + + if (ev->type == EV_REL) + { + if (ev->code == REL_X) + x_diff = x_diff + ev->value; + if (ev->code == REL_Y) + y_diff = y_diff + ev->value; + } + + if ((ABS(x_diff) > rc_range) || (ABS(y_diff) > rc_range)) + { + res = 1; + } + return res; +} + +void EvdevRCInit(DeviceIntPtr device) +{ + InputInfoPtr pInfo; + EvdevPtr pEvdev; + + pInfo = device->public.devicePrivate; + pEvdev = pInfo->private; + + if (pEvdev->flags & EVDEV_SMART_RC) + { + ErrorF("[%s] id: %d, smart rc... hook \n", __FUNCTION__, device->id); + pEvdev->extra_input_process = EvdevRCProcessEvent; + pEvdev->rc_state = STATE_NORMAL; + rcstate.velocity = 3; + rcstate.atomTouchOn = MakeAtom(XI_PROP_TOUCH_ON, strlen(XI_PROP_TOUCH_ON), TRUE); + atomDistanceMoved = MakeAtom(XI_PROP_SMARTRC_DISCANCE_MOVED,strlen(XI_PROP_SMARTRC_DISCANCE_MOVED), TRUE); + atomCalculateDistance= MakeAtom(XI_PROP_START_CALCULATE_DISTANCE,strlen(XI_PROP_START_CALCULATE_DISTANCE), TRUE); + prop_move_start = MakeAtom(XI_PROP_REL_MOVE_STATUS, strlen(XI_PROP_REL_MOVE_STATUS), TRUE); + } +#ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_ + else + { + if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE))) pSmartRCKbdDeviceInfo = pInfo; + } +#endif + XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL); + return; +} +#endif //_F_EVDEV_SUPPORT_SMARTRC_ \ No newline at end of file