tizen 2.4 release accepted/tizen_2.4_mobile tizen_2.4 accepted/tizen/2.4/mobile/20151029.042018 submit/tizen_2.4/20151028.062431 tizen_2.4_mobile_release
authorjk7744.park <jk7744.park@samsung.com>
Sat, 24 Oct 2015 06:30:40 +0000 (15:30 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Sat, 24 Oct 2015 06:30:40 +0000 (15:30 +0900)
configure.ac
include/evdev-properties.h
packaging/xorg-x11-drv-evdev.spec
src/Makefile.am
src/emuWheel.c
src/evdev.c [changed mode: 0755->0644]
src/evdev.h [changed mode: 0755->0644]
src/proxyDev.c [new file with mode: 0644]
src/rotary.c [changed mode: 0755->0644]
src/smartRC.c [new file with mode: 0644]

index dff2bcf..e08a1cd 100644 (file)
@@ -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],
index c9ebacf..6695a29 100755 (executable)
 #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
index 0a884ac..2ce2402 100644 (file)
@@ -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
index c5e21fc..b446b33 100644 (file)
 # _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
index ae894fa..db989c5 100644 (file)
@@ -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;
old mode 100755 (executable)
new mode 100644 (file)
index 90f6443..04d681f
@@ -52,6 +52,9 @@
 
 #include <xf86.h>
 #include <xf86Xinput.h>
+#ifdef _F_PROXY_DEVICE_ENABLED_
+#include <xorg/optionstr.h>
+#endif //_F_PROXY_DEVICE_ENABLED_
 #include <exevents.h>
 #include <xorgVersion.h>
 #include <xkbsrv.h>
 #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, &region[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_ */
old mode 100755 (executable)
new mode 100644 (file)
index 3dd3953..2fe2c77
 #include <mtdev.h>
 #endif
 
+#ifdef ENABLE_TTRACE
+#include <ttrace.h>
+
+#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 <axis> 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 (file)
index 0000000..148d615
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ *
+ * xserver-xorg-input-evdev
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ *          Sangjin LEE <lsj119@samsung.com>
+ *          Jeonghyun Kang <jhyuni.kang@samsung.com>
+ *
+ * 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 <evdev-properties.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <exevents.h>
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <X11/Xatom.h>
+#include <xorg/optionstr.h>
+
+#include <xorg/mi.h>
+
+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_
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/src/smartRC.c b/src/smartRC.c
new file mode 100644 (file)
index 0000000..d69ca9f
--- /dev/null
@@ -0,0 +1,726 @@
+/*
+ *
+ * xserver-xorg-input-evdev
+ *
+ * Contact: Sung-Jin Park <sj76.park@samsung.com>
+ *          Sangjin LEE <lsj119@samsung.com>
+ *          Jeonghyun Kang <jhyuni.kang@samsung.com>
+ *
+ * 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 <evdev.h>
+#include <evdev-properties.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <exevents.h>
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <X11/Xatom.h>
+
+#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