tizen 2.4 release
[adaptation/xorg/driver/xserver-xorg-input-evdev.git] / src / smartRC.c
1 /*
2  *
3  * xserver-xorg-input-evdev
4  *
5  * Contact: Sung-Jin Park <sj76.park@samsung.com>
6  *          Sangjin LEE <lsj119@samsung.com>
7  *          Jeonghyun Kang <jhyuni.kang@samsung.com>
8  *
9  * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
10  * Copyright © 2004-2008 Red Hat, Inc.
11  *
12  * Permission to use, copy, modify, distribute, and sell this software
13  * and its documentation for any purpose is hereby granted without
14  * fee, provided that the above copyright notice appear in all copies
15  * and that both that copyright notice and this permission notice
16  * appear in supporting documentation, and that the name of Red Hat
17  * not be used in advertising or publicity pertaining to distribution
18  * of the software without specific, written prior permission.  Red
19  * Hat makes no representations about the suitability of this software
20  * for any purpose.  It is provided "as is" without express or implied
21  * warranty.
22  *
23  * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
24  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
25  * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
26  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
27  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
28  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
29  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30  *
31  * Authors:
32  *      Kristian Høgsberg (krh@redhat.com)
33  *      Adam Jackson (ajax@redhat.com)
34  *      Peter Hutterer (peter.hutterer@redhat.com)
35  *      Oliver McFadden (oliver.mcfadden@nokia.com)
36  */
37
38 #ifdef _F_EVDEV_SUPPORT_SMARTRC_
39  #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42
43 #include <evdev.h>
44 #include <evdev-properties.h>
45 #include <errno.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <fcntl.h>
49 #include <unistd.h>
50
51 #include <exevents.h>
52 #include <xf86.h>
53 #include <xf86Xinput.h>
54 #include <X11/Xatom.h>
55
56 #define ABS(x) (((x) < 0) ? -(x) : (x))
57 #define XI_PROP_TOUCH_ON "Evdev SmartRC Moved"
58 #define XI_PROP_SMARTRC_DISCANCE_MOVED "Evdev SmartRC Distance Moved"
59 #define XI_PROP_START_CALCULATE_DISTANCE "Start Calcualting Distance"
60
61 #define IF_KEY_CODE_TOUCH (ev->code == BTN_EXTRA || ev->code == BTN_SIDE)
62 #define IF_NOT_KEY_CODE_TOUCH (ev->code != BTN_EXTRA && ev->code != BTN_SIDE)
63
64 static Atom atomDistanceMoved;
65 static Atom atomCalculateDistance;
66 static Atom prop_move_start;
67 static int calculateDistance=0;
68 #define INITIAL_CURSOR_DISTANCE_TO_MOVE 0
69
70 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
71 static InputInfoPtr pSmartRCKbdDeviceInfo = NULL;
72 #endif
73 extern int block_motion_device;
74
75 enum device_state
76 {
77     STATE_NONE=0,
78     STATE_NORMAL,
79     RC_STATE_DR_KEY,
80     RC_STATE_AIR_TOUCH
81 };
82
83 enum abs_move_state
84 {
85     ABS_MOVE_END=0,
86     ABS_MOVE_ON,
87     ABS_MOVE_START
88 };
89
90 enum scroll_direction_state
91 {
92     SCROLL_NONE=0,
93     SCROLL_VERTICAL,
94     SCROLL_HORIZEN
95 };
96
97 static void EvdevRCBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead);
98 static void EvdevRCBlockHandlerFor2014(pointer data, OSTimePtr pTimeout, pointer pRead);
99 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
100 static int EvdevRCProcessEvent(InputInfoPtr *ppInfo, struct input_event *ev);
101 #else
102 static int EvdevRCProcessEvent(InputInfoPtr pInfo, struct input_event *ev);
103 #endif
104 int EvdevRCProcessNormalState(InputInfoPtr pInfo, struct input_event *ev);
105 int EvdevRCProcessDRKeyState(InputInfoPtr pInfo, struct input_event *ev);
106 void EvdevRCWheelScroll(InputInfoPtr pInfo, struct input_event *ev);
107 int EvdevRCProcessAirTouchState(InputInfoPtr pInfo, struct input_event *ev, int check_boundary);
108 int EvdevRCIsSwipe(struct input_event *ev);
109 void EvdevRCSendEvent(InputInfoPtr pInfo, int type, int code, int value);
110 int EvdevRCIsBoundary(struct input_event *ev, int rc_range);
111 static int EvdevSetProperty(DeviceIntPtr dev, Atom atom,
112                             XIPropertyValuePtr val, BOOL checkonly);
113
114 typedef struct _tagRCState
115 {
116     int velocity;
117     int velo_time;
118     int move_state;
119     BOOL is_touch_on;
120     BOOL isSmartRC_15;
121     Atom atomTouchOn;
122 }RCState, *RCStatePtr;
123
124 RCState rcstate;
125
126 static void
127 EvdevRCBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
128 {
129     InputInfoPtr pInfo = (InputInfoPtr)data;
130     int rc;
131
132     RemoveBlockAndWakeupHandlers(EvdevRCBlockHandler,
133                                  (WakeupHandlerProcPtr)NoopDDA,
134                                  data);
135
136     ErrorF("15 RCBlock Handler Called, [%d] is_touch_on: %d\n", pInfo->dev->id, rcstate.is_touch_on);
137
138     if (rcstate.is_touch_on == TRUE)
139     {
140         rc = XIChangeDeviceProperty(pInfo->dev, rcstate.atomTouchOn, XA_INTEGER, 8,
141                                 PropModeReplace, 1, &rcstate.is_touch_on, TRUE);
142
143         // In case of 2015 smartRC, cursor is enable when touch on device.  (prop_move_start is set to "1")
144         if (block_motion_device == 0)
145            rc = XIChangeDeviceProperty(pInfo->dev, prop_move_start, XA_INTEGER, 8,
146                  PropModeReplace, 1, &rcstate.is_touch_on, TRUE);
147     }
148     else
149         rc = XIDeleteDeviceProperty(pInfo->dev, rcstate.atomTouchOn, TRUE);
150
151     if (rc != Success)
152     {
153         xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, (int)rcstate.atomTouchOn);
154     }
155 }
156
157 static void
158 EvdevRCBlockHandlerFor2014(pointer data, OSTimePtr pTimeout, pointer pRead)
159 {
160     InputInfoPtr pInfo = (InputInfoPtr)data;
161     int rc;
162
163     RemoveBlockAndWakeupHandlers(EvdevRCBlockHandlerFor2014,
164                                  (WakeupHandlerProcPtr)NoopDDA,
165                                  data);
166
167     ErrorF("14 RCBlock Handler Called, [%d] is_touch_on: %d\n", pInfo->dev->id, rcstate.is_touch_on);
168
169     if (rcstate.is_touch_on == TRUE)
170     {
171         rc = XIChangeDeviceProperty(pInfo->dev, rcstate.atomTouchOn, XA_INTEGER, 8,
172                     PropModeReplace, 1, &rcstate.is_touch_on, TRUE);
173     }
174     else
175         rc = XIDeleteDeviceProperty(pInfo->dev, rcstate.atomTouchOn, TRUE);
176
177     if (rc != Success)
178     {
179         xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, (int)rcstate.atomTouchOn);
180     }
181 }
182
183 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
184 static int EvdevRCProcessEvent(InputInfoPtr *ppInfo, struct input_event *ev)
185 #else
186 static int EvdevRCProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
187 #endif
188 {
189 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
190     InputInfoPtr pInfo = *ppInfo;
191 #endif
192     EvdevPtr pEvdev = pInfo->private;
193     int res = 0;
194     // Start of Coord Cal
195     static int mismatchX = 0, mismatchY = 0;
196
197     if( rcstate.isSmartRC_15 == TRUE && ev->type == EV_ABS )
198     {
199        if(ev->code == ABS_X)
200        {
201           int calX = ev->value - pInfo->dev->spriteInfo->sprite->hot.x;
202           if(calX == 0)
203           {
204              mismatchX = 0;
205              return 0;
206           }
207           if(++mismatchX < 10)
208           {
209              return 0;
210           }
211           mismatchX = 0;
212           ev->type = EV_REL;
213           ev->code = REL_X;
214           ev->value = calX;
215        }
216        if(ev->code == ABS_Y)
217        {
218           int calY = ev->value - pInfo->dev->spriteInfo->sprite->hot.y;
219           if(calY == 0)
220           {
221              mismatchY = 0;
222              return 0;
223           }
224           if(++mismatchY < 10)
225           {
226              return 0;
227           }
228           mismatchY = 0;
229           ev->type = EV_REL;
230           ev->code = REL_Y;
231           ev->value = calY;
232        }
233     }
234     // End of Coord Cal
235
236     if (pEvdev->rel_move_ack == 3 || block_motion_device == 1)
237     {
238             if (ev->type == EV_REL || ev->type == EV_ABS)
239             {
240                     return res;
241             }
242             if (ev->type == EV_KEY && ev->code == BTN_LEFT)
243             {
244                     ev->code = KEY_ENTER;
245             }
246     }
247     
248     if (ev->type == EV_KEY && ev->code == BTN_EXTRA)
249     {
250         if (ev->value == 0)
251         {
252             rcstate.move_state = ABS_MOVE_END;
253             rcstate.is_touch_on = FALSE;
254             rcstate.isSmartRC_15 = FALSE;
255         }
256         else if (ev->value == 1)
257         {
258             rcstate.move_state = ABS_MOVE_ON;
259             rcstate.is_touch_on = TRUE;
260             rcstate.isSmartRC_15 = TRUE;
261         }
262                 OsBlockSIGIO();
263         RegisterBlockAndWakeupHandlers(EvdevRCBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, pInfo);
264                 OsReleaseSIGIO(); 
265     }
266     else if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_SYN)
267     {
268         rcstate.move_state = ABS_MOVE_START;
269     }
270
271
272     if (ev->type == EV_KEY && ev->code == BTN_SIDE)
273     {
274         if (ev->value == 0)
275         {
276             rcstate.move_state = ABS_MOVE_END;
277             rcstate.is_touch_on = FALSE;
278         }
279         else if (ev->value == 1)
280         {
281             rcstate.move_state = ABS_MOVE_ON;
282             rcstate.is_touch_on = TRUE;
283         }
284         OsBlockSIGIO();
285         RegisterBlockAndWakeupHandlers(EvdevRCBlockHandlerFor2014 ,(WakeupHandlerProcPtr) NoopDDA, pInfo);
286         OsReleaseSIGIO(); 
287     }
288     else if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_SYN)
289     {
290         rcstate.move_state = ABS_MOVE_START;
291     }
292
293     switch (pEvdev->rc_state)
294     {
295         case STATE_NORMAL:
296             res = EvdevRCProcessNormalState(pInfo, ev);
297             break;
298         case RC_STATE_DR_KEY:
299             res = EvdevRCProcessDRKeyState(pInfo, ev);
300             break;
301         case RC_STATE_AIR_TOUCH:
302             res = EvdevRCProcessAirTouchState(pInfo, ev, 1);
303             break;
304         default:
305             break;
306     }
307
308     if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
309         return 0;
310     else 
311 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
312     {
313         if (pEvdev->rc_state == RC_STATE_DR_KEY)
314         {
315             if(pSmartRCKbdDeviceInfo) *ppInfo = pSmartRCKbdDeviceInfo;
316         }
317     }
318 #endif
319     return res;
320 }
321
322 int EvdevRCProcessNormalState(InputInfoPtr pInfo, struct input_event *ev)
323 {
324     EvdevPtr pEvdev = pInfo->private;
325     int res = 0;
326
327     if (ev->type == EV_REL || ev->type == EV_ABS)
328         return res;
329
330     if (ev->type == EV_KEY)
331     {
332         if (IF_KEY_CODE_TOUCH && ev->value == 1)
333         {
334             pEvdev->rc_state = RC_STATE_AIR_TOUCH;
335             res = EvdevRCProcessAirTouchState(pInfo, ev, 1);
336         }
337         else if ( (ev->code == KEY_UP || ev->code == KEY_LEFT || ev->code == KEY_DOWN || ev->code == KEY_RIGHT || ev->code == KEY_ENTER)
338             && (ev->value == 1))
339         {
340             pEvdev->rc_state = RC_STATE_DR_KEY;
341             res = EvdevRCProcessDRKeyState(pInfo, ev);
342         }
343         else if (IF_KEY_CODE_TOUCH && ev->value == 0)
344         {
345             return res;
346         }
347         else
348             res = 1;
349     }
350     else
351         res = 1;
352
353     return res;
354 }
355
356 int EvdevRCProcessDRKeyState(InputInfoPtr pInfo, struct input_event *ev)
357 {
358     EvdevPtr pEvdev = pInfo->private;
359     int res = 0;
360     static int pressed_flag = 0;
361     static BOOL extra_pressed = FALSE;
362     static int last_key = -1;
363
364     if (ev->type == EV_KEY && ev->code == BTN_LEFT)
365     {
366         ev->code = KEY_ENTER;
367     }
368
369     if (ev->type == EV_KEY && IF_NOT_KEY_CODE_TOUCH)
370     {
371         if ( (last_key >= 0) && (ev->code != last_key))
372         {
373             return res;
374         }
375         if (ev->value == 1) {
376             pressed_flag++;
377             last_key = ev->code;
378         }
379         else {
380             pressed_flag--;
381             last_key = -1;
382             if (pressed_flag<0)
383                 pressed_flag = 0;
384         }
385     }
386     else if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
387     {
388         if (pressed_flag == 0)
389         {
390             res = EvdevRCProcessAirTouchState(pInfo, ev, 0);
391             extra_pressed = FALSE;
392         }
393         else if (ev->value == 1)
394         {
395             extra_pressed = TRUE;
396         }
397         else
398         {
399             extra_pressed = FALSE;
400         }
401     }
402     if (extra_pressed == TRUE && (ev->type == EV_REL || ev->type == EV_ABS))
403     {
404        return res;
405     }
406
407     if ((pressed_flag==0) && block_motion_device == 0)
408     {
409        if (rcstate.isSmartRC_15 == TRUE)
410        {
411           pEvdev->rc_state = RC_STATE_AIR_TOUCH;
412           res = EvdevRCProcessAirTouchState(pInfo, ev, 0);
413           return res;
414        }
415        else
416        {
417           // calculate distance to change air touch mode(2014 smartRC)
418           if(EvdevRCIsBoundary(ev, 150))
419           {
420              pEvdev->rc_state = RC_STATE_AIR_TOUCH;
421              res = EvdevRCProcessAirTouchState(pInfo, ev, 0);
422              return res;
423           }
424        }
425     }
426
427     if (ev->type == EV_REL || ev->type == EV_ABS)
428     {
429         return res;
430     }
431     else
432         res = 1;
433
434     return res;
435
436 }
437
438 int EvdevRCProcessAirTouchState(InputInfoPtr pInfo, struct input_event *ev, int check_boundary)
439 {
440     EvdevPtr pEvdev = pInfo->private;
441     int res = 0;
442     int rc;
443     int temp_res;
444
445     if( calculateDistance && EvdevRCIsBoundary(ev, INITIAL_CURSOR_DISTANCE_TO_MOVE))
446     {
447         rc = XIChangeDeviceProperty(pInfo->dev, atomDistanceMoved, XA_INTEGER, 8,
448             PropModeReplace, 1, &pEvdev->rel_move_status, TRUE);
449         if (rc != Success)
450             ErrorF("[EvdevRCProcessAirTouchState] Failed to change atomDistanceMoved\n");
451         calculateDistance=0;
452     }
453
454     if (ev->type == EV_KEY && (IF_NOT_KEY_CODE_TOUCH && ev->code != BTN_LEFT))
455         return res;
456
457     if (ev->type == EV_REL && (ev->code == REL_HWHEEL || ev->code == REL_WHEEL))
458     {
459         res = 1;
460         return res;
461     }
462
463     if (ev->type == EV_ABS || (ev->type == EV_KEY && IF_KEY_CODE_TOUCH) || ev->type == EV_SYN)
464     {
465         EvdevRCWheelScroll(pInfo, ev);
466     }
467
468     if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH && ev->value == 0)
469     {
470         temp_res = EvdevRCIsBoundary(ev, 0);
471         if (pEvdev->rc_state != RC_STATE_DR_KEY)
472             pEvdev->rc_state = STATE_NORMAL;
473         if (temp_res == 1)
474             res = temp_res;
475             return res;
476     }
477     else if (check_boundary && ev->type == EV_REL)
478     {
479         if (!EvdevRCIsBoundary(ev, 0))
480             return res;
481         else
482         {
483             if (block_motion_device == 0)
484                 pEvdev->rc_state = RC_STATE_AIR_TOUCH;
485         }
486     }
487
488     res = 1;
489
490     return res;
491 }
492
493 void EvdevRCWheelScroll(InputInfoPtr pInfo, struct input_event *ev)
494 {
495     static int before_x=-1, before_y=-1;
496     static int before_x_utime = -1, before_y_utime = -1;
497     static int before_x_time = -1, before_y_time = -1;
498
499     int time_diff = 0;
500     float velo_x=0;
501
502     float velo_y = 0;
503     static int velo_y_count=0, velo_x_count = 0;
504
505     static int wheel_direction_flag = SCROLL_NONE;
506
507     if (ev->type == EV_REL || ev->type == EV_SYN)
508         return;
509     if (ev->type == EV_KEY && IF_NOT_KEY_CODE_TOUCH)
510         return;
511
512     if (ev->type == EV_KEY)
513         wheel_direction_flag = SCROLL_NONE;
514
515     if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_ABS)
516     {
517         velo_y_count=0;
518         if (ev->code == ABS_X)
519         {
520             before_x = ev->value;
521             before_x_time = ev->time.tv_sec;
522             before_x_utime = ev->time.tv_usec;
523
524             if ((before_x < 150) || (350 < before_x))
525             {
526                 wheel_direction_flag = SCROLL_HORIZEN;
527             }
528             return;
529         }
530         else if (ev->code == ABS_Y)
531         {
532             before_y = ev->value;
533             before_y_time = ev->time.tv_sec;
534             before_y_utime = ev->time.tv_usec;
535
536             if ((before_y < 150) || (350 < before_y))
537             {
538                 wheel_direction_flag = SCROLL_VERTICAL;
539             }
540             return;
541         }
542     }
543
544     if (ev->type == EV_ABS && ev->code == ABS_X && wheel_direction_flag != SCROLL_VERTICAL)
545     {
546         time_diff = (ev->time.tv_sec - before_x_time) * 1000 + (ev->time.tv_usec - before_x_utime)/1000;
547         if (time_diff == 0)
548         {
549             ErrorF("before and current events had same event time...\n");
550             return;
551         }
552
553         velo_x = (float)((ABS(before_x - ev->value)) / time_diff);
554
555         if (velo_x > 1)
556         {
557             velo_x_count = velo_x_count + (int)velo_x;
558         }
559
560         if (velo_x_count > 2)
561         {
562             wheel_direction_flag = SCROLL_HORIZEN;
563             velo_x_count = (velo_x_count / 4);
564             if (velo_x_count > 2)
565                 velo_x_count = velo_x_count * 2;
566
567             EvdevRCSendEvent(pInfo, EV_REL, REL_HWHEEL, ((before_x - ev->value) < 0)? -velo_x_count: velo_x_count);
568             velo_x_count = 0;
569         }
570
571         before_x = ev->value;
572         before_x_time = ev->time.tv_sec;
573         before_x_utime = ev->time.tv_usec;
574     }
575     else if (ev->type == EV_ABS && ev->code == ABS_Y && wheel_direction_flag != SCROLL_HORIZEN)
576     {
577         time_diff = (ev->time.tv_sec - before_y_time) * 1000 + (ev->time.tv_usec - before_y_utime)/1000;
578         if (time_diff == 0)
579         {
580             ErrorF("before and current events had same event time...\n");
581             return;
582         }
583         velo_y = (float)((ABS(before_y - ev->value)) / time_diff);
584
585         if (velo_y > 1)
586         {
587             velo_y_count = velo_y_count + (int)velo_y;
588         }
589
590         if (velo_y_count > 2)
591         {
592             wheel_direction_flag = SCROLL_VERTICAL;
593             velo_y_count = (velo_y_count / 4);
594             if (velo_y_count > 2)
595                 velo_y_count = velo_y_count * 2;
596
597             EvdevRCSendEvent(pInfo, EV_REL, REL_WHEEL, ((before_y - ev->value) < 0)? -velo_y_count: velo_y_count);
598             velo_y_count = 0;
599         }
600
601         before_y = ev->value;
602         before_y_time = ev->time.tv_sec;
603         before_y_utime = ev->time.tv_usec;
604     }
605 }
606
607 int EvdevRCIsSwipe(struct input_event *ev)
608 {
609     int res = 0;
610     static int base_point_x = -1;
611     static int base_point_y = -1;
612
613     if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
614     {
615             base_point_x = -1;
616             base_point_y = -1;
617     }
618
619     if (ev->type == EV_ABS)
620     {
621         if (ev->code == ABS_X)
622         {
623             if (base_point_x == -1)
624             {
625                 base_point_x = ev->value;
626             }
627             else if (ABS(base_point_x - ev->value) > 300)
628             {
629                 res = 1;
630             }
631         }
632         else if (ev->code == ABS_Y)
633         {
634             if (base_point_y == -1)
635             {
636                 base_point_y = ev->value;
637             }
638             else if (ABS(base_point_y - ev->value) > 300)
639             {
640                 res = 1;
641             }
642         }
643     }
644
645     return res;
646 }
647
648 void EvdevRCSendEvent(InputInfoPtr pInfo, int type, int code, int value)
649 {
650     EvdevPtr pEvdev = pInfo->private;
651     struct input_event ev;
652
653     ev.type = type;
654     ev.code = code;
655     ev.value = value;
656
657     pEvdev->origin_input_process(pInfo, &ev);
658 }
659
660 static int
661 EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
662                  BOOL checkonly)
663 {
664     InputInfoPtr pInfo  = dev->public.devicePrivate;
665     EvdevPtr     pEvdev = pInfo->private;
666  
667     if (atom == atomCalculateDistance )
668     {
669         calculateDistance=1;
670     }
671     return 0;
672 }
673 int EvdevRCIsBoundary(struct input_event *ev, int rc_range)
674 {
675     static int x_diff=0, y_diff = 0;
676     int res = 0;
677
678     if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
679     {
680         x_diff = y_diff = 0;
681     }
682
683     if (ev->type == EV_REL)
684     {
685         if (ev->code == REL_X)
686             x_diff = x_diff + ev->value;
687         if (ev->code == REL_Y)
688             y_diff = y_diff + ev->value;
689     }
690
691     if ((ABS(x_diff) > rc_range) || (ABS(y_diff) > rc_range))
692     {
693         res = 1;
694     }
695     return res;
696 }
697
698 void EvdevRCInit(DeviceIntPtr device)
699 {
700     InputInfoPtr pInfo;
701     EvdevPtr pEvdev;
702
703     pInfo = device->public.devicePrivate;
704     pEvdev = pInfo->private;
705
706     if (pEvdev->flags & EVDEV_SMART_RC)
707     {
708         ErrorF("[%s] id: %d, smart rc... hook \n", __FUNCTION__, device->id);
709         pEvdev->extra_input_process = EvdevRCProcessEvent;
710         pEvdev->rc_state = STATE_NORMAL;
711         rcstate.velocity = 3;
712         rcstate.atomTouchOn = MakeAtom(XI_PROP_TOUCH_ON, strlen(XI_PROP_TOUCH_ON), TRUE);
713         atomDistanceMoved = MakeAtom(XI_PROP_SMARTRC_DISCANCE_MOVED,strlen(XI_PROP_SMARTRC_DISCANCE_MOVED), TRUE);
714         atomCalculateDistance= MakeAtom(XI_PROP_START_CALCULATE_DISTANCE,strlen(XI_PROP_START_CALCULATE_DISTANCE), TRUE);
715         prop_move_start = MakeAtom(XI_PROP_REL_MOVE_STATUS, strlen(XI_PROP_REL_MOVE_STATUS), TRUE);
716     }
717 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
718     else
719     {
720         if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE))) pSmartRCKbdDeviceInfo = pInfo;
721     }
722 #endif
723     XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
724     return;
725 }
726 #endif //_F_EVDEV_SUPPORT_SMARTRC_