3 * xserver-xorg-input-evdev
5 * Contact: Sung-Jin Park <sj76.park@samsung.com>
6 * Sangjin LEE <lsj119@samsung.com>
7 * Jeonghyun Kang <jhyuni.kang@samsung.com>
9 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
10 * Copyright © 2004-2008 Red Hat, Inc.
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
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.
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)
38 #ifdef _F_EVDEV_SUPPORT_SMARTRC_
44 #include <evdev-properties.h>
46 #include <sys/types.h>
53 #include <xf86Xinput.h>
54 #include <X11/Xatom.h>
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"
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)
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
70 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
71 static InputInfoPtr pSmartRCKbdDeviceInfo = NULL;
73 extern int block_motion_device;
90 enum scroll_direction_state
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);
102 static int EvdevRCProcessEvent(InputInfoPtr pInfo, struct input_event *ev);
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);
114 typedef struct _tagRCState
122 }RCState, *RCStatePtr;
127 EvdevRCBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
129 InputInfoPtr pInfo = (InputInfoPtr)data;
132 RemoveBlockAndWakeupHandlers(EvdevRCBlockHandler,
133 (WakeupHandlerProcPtr)NoopDDA,
136 ErrorF("15 RCBlock Handler Called, [%d] is_touch_on: %d\n", pInfo->dev->id, rcstate.is_touch_on);
138 if (rcstate.is_touch_on == TRUE)
140 rc = XIChangeDeviceProperty(pInfo->dev, rcstate.atomTouchOn, XA_INTEGER, 8,
141 PropModeReplace, 1, &rcstate.is_touch_on, TRUE);
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);
149 rc = XIDeleteDeviceProperty(pInfo->dev, rcstate.atomTouchOn, TRUE);
153 xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, (int)rcstate.atomTouchOn);
158 EvdevRCBlockHandlerFor2014(pointer data, OSTimePtr pTimeout, pointer pRead)
160 InputInfoPtr pInfo = (InputInfoPtr)data;
163 RemoveBlockAndWakeupHandlers(EvdevRCBlockHandlerFor2014,
164 (WakeupHandlerProcPtr)NoopDDA,
167 ErrorF("14 RCBlock Handler Called, [%d] is_touch_on: %d\n", pInfo->dev->id, rcstate.is_touch_on);
169 if (rcstate.is_touch_on == TRUE)
171 rc = XIChangeDeviceProperty(pInfo->dev, rcstate.atomTouchOn, XA_INTEGER, 8,
172 PropModeReplace, 1, &rcstate.is_touch_on, TRUE);
175 rc = XIDeleteDeviceProperty(pInfo->dev, rcstate.atomTouchOn, TRUE);
179 xf86IDrvMsg(pInfo, X_ERROR, "[%s] Failed to change device property (id:%d, prop=%d)\n", __FUNCTION__, pInfo->dev->id, (int)rcstate.atomTouchOn);
183 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
184 static int EvdevRCProcessEvent(InputInfoPtr *ppInfo, struct input_event *ev)
186 static int EvdevRCProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
189 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
190 InputInfoPtr pInfo = *ppInfo;
192 EvdevPtr pEvdev = pInfo->private;
194 // Start of Coord Cal
195 static int mismatchX = 0, mismatchY = 0;
197 if( rcstate.isSmartRC_15 == TRUE && ev->type == EV_ABS )
199 if(ev->code == ABS_X)
201 int calX = ev->value - pInfo->dev->spriteInfo->sprite->hot.x;
216 if(ev->code == ABS_Y)
218 int calY = ev->value - pInfo->dev->spriteInfo->sprite->hot.y;
236 if (pEvdev->rel_move_ack == 3 || block_motion_device == 1)
238 if (ev->type == EV_REL || ev->type == EV_ABS)
242 if (ev->type == EV_KEY && ev->code == BTN_LEFT)
244 ev->code = KEY_ENTER;
248 if (ev->type == EV_KEY && ev->code == BTN_EXTRA)
252 rcstate.move_state = ABS_MOVE_END;
253 rcstate.is_touch_on = FALSE;
254 rcstate.isSmartRC_15 = FALSE;
256 else if (ev->value == 1)
258 rcstate.move_state = ABS_MOVE_ON;
259 rcstate.is_touch_on = TRUE;
260 rcstate.isSmartRC_15 = TRUE;
263 RegisterBlockAndWakeupHandlers(EvdevRCBlockHandler ,(WakeupHandlerProcPtr) NoopDDA, pInfo);
266 else if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_SYN)
268 rcstate.move_state = ABS_MOVE_START;
272 if (ev->type == EV_KEY && ev->code == BTN_SIDE)
276 rcstate.move_state = ABS_MOVE_END;
277 rcstate.is_touch_on = FALSE;
279 else if (ev->value == 1)
281 rcstate.move_state = ABS_MOVE_ON;
282 rcstate.is_touch_on = TRUE;
285 RegisterBlockAndWakeupHandlers(EvdevRCBlockHandlerFor2014 ,(WakeupHandlerProcPtr) NoopDDA, pInfo);
288 else if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_SYN)
290 rcstate.move_state = ABS_MOVE_START;
293 switch (pEvdev->rc_state)
296 res = EvdevRCProcessNormalState(pInfo, ev);
298 case RC_STATE_DR_KEY:
299 res = EvdevRCProcessDRKeyState(pInfo, ev);
301 case RC_STATE_AIR_TOUCH:
302 res = EvdevRCProcessAirTouchState(pInfo, ev, 1);
308 if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
311 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
313 if (pEvdev->rc_state == RC_STATE_DR_KEY)
315 if(pSmartRCKbdDeviceInfo) *ppInfo = pSmartRCKbdDeviceInfo;
322 int EvdevRCProcessNormalState(InputInfoPtr pInfo, struct input_event *ev)
324 EvdevPtr pEvdev = pInfo->private;
327 if (ev->type == EV_REL || ev->type == EV_ABS)
330 if (ev->type == EV_KEY)
332 if (IF_KEY_CODE_TOUCH && ev->value == 1)
334 pEvdev->rc_state = RC_STATE_AIR_TOUCH;
335 res = EvdevRCProcessAirTouchState(pInfo, ev, 1);
337 else if ( (ev->code == KEY_UP || ev->code == KEY_LEFT || ev->code == KEY_DOWN || ev->code == KEY_RIGHT || ev->code == KEY_ENTER)
340 pEvdev->rc_state = RC_STATE_DR_KEY;
341 res = EvdevRCProcessDRKeyState(pInfo, ev);
343 else if (IF_KEY_CODE_TOUCH && ev->value == 0)
356 int EvdevRCProcessDRKeyState(InputInfoPtr pInfo, struct input_event *ev)
358 EvdevPtr pEvdev = pInfo->private;
360 static int pressed_flag = 0;
361 static BOOL extra_pressed = FALSE;
362 static int last_key = -1;
364 if (ev->type == EV_KEY && ev->code == BTN_LEFT)
366 ev->code = KEY_ENTER;
369 if (ev->type == EV_KEY && IF_NOT_KEY_CODE_TOUCH)
371 if ( (last_key >= 0) && (ev->code != last_key))
375 if (ev->value == 1) {
386 else if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
388 if (pressed_flag == 0)
390 res = EvdevRCProcessAirTouchState(pInfo, ev, 0);
391 extra_pressed = FALSE;
393 else if (ev->value == 1)
395 extra_pressed = TRUE;
399 extra_pressed = FALSE;
402 if (extra_pressed == TRUE && (ev->type == EV_REL || ev->type == EV_ABS))
407 if ((pressed_flag==0) && block_motion_device == 0)
409 if (rcstate.isSmartRC_15 == TRUE)
411 pEvdev->rc_state = RC_STATE_AIR_TOUCH;
412 res = EvdevRCProcessAirTouchState(pInfo, ev, 0);
417 // calculate distance to change air touch mode(2014 smartRC)
418 if(EvdevRCIsBoundary(ev, 150))
420 pEvdev->rc_state = RC_STATE_AIR_TOUCH;
421 res = EvdevRCProcessAirTouchState(pInfo, ev, 0);
427 if (ev->type == EV_REL || ev->type == EV_ABS)
438 int EvdevRCProcessAirTouchState(InputInfoPtr pInfo, struct input_event *ev, int check_boundary)
440 EvdevPtr pEvdev = pInfo->private;
445 if( calculateDistance && EvdevRCIsBoundary(ev, INITIAL_CURSOR_DISTANCE_TO_MOVE))
447 rc = XIChangeDeviceProperty(pInfo->dev, atomDistanceMoved, XA_INTEGER, 8,
448 PropModeReplace, 1, &pEvdev->rel_move_status, TRUE);
450 ErrorF("[EvdevRCProcessAirTouchState] Failed to change atomDistanceMoved\n");
454 if (ev->type == EV_KEY && (IF_NOT_KEY_CODE_TOUCH && ev->code != BTN_LEFT))
457 if (ev->type == EV_REL && (ev->code == REL_HWHEEL || ev->code == REL_WHEEL))
463 if (ev->type == EV_ABS || (ev->type == EV_KEY && IF_KEY_CODE_TOUCH) || ev->type == EV_SYN)
465 EvdevRCWheelScroll(pInfo, ev);
468 if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH && ev->value == 0)
470 temp_res = EvdevRCIsBoundary(ev, 0);
471 if (pEvdev->rc_state != RC_STATE_DR_KEY)
472 pEvdev->rc_state = STATE_NORMAL;
477 else if (check_boundary && ev->type == EV_REL)
479 if (!EvdevRCIsBoundary(ev, 0))
483 if (block_motion_device == 0)
484 pEvdev->rc_state = RC_STATE_AIR_TOUCH;
493 void EvdevRCWheelScroll(InputInfoPtr pInfo, struct input_event *ev)
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;
503 static int velo_y_count=0, velo_x_count = 0;
505 static int wheel_direction_flag = SCROLL_NONE;
507 if (ev->type == EV_REL || ev->type == EV_SYN)
509 if (ev->type == EV_KEY && IF_NOT_KEY_CODE_TOUCH)
512 if (ev->type == EV_KEY)
513 wheel_direction_flag = SCROLL_NONE;
515 if (rcstate.move_state == ABS_MOVE_ON && ev->type == EV_ABS)
518 if (ev->code == ABS_X)
520 before_x = ev->value;
521 before_x_time = ev->time.tv_sec;
522 before_x_utime = ev->time.tv_usec;
524 if ((before_x < 150) || (350 < before_x))
526 wheel_direction_flag = SCROLL_HORIZEN;
530 else if (ev->code == ABS_Y)
532 before_y = ev->value;
533 before_y_time = ev->time.tv_sec;
534 before_y_utime = ev->time.tv_usec;
536 if ((before_y < 150) || (350 < before_y))
538 wheel_direction_flag = SCROLL_VERTICAL;
544 if (ev->type == EV_ABS && ev->code == ABS_X && wheel_direction_flag != SCROLL_VERTICAL)
546 time_diff = (ev->time.tv_sec - before_x_time) * 1000 + (ev->time.tv_usec - before_x_utime)/1000;
549 ErrorF("before and current events had same event time...\n");
553 velo_x = (float)((ABS(before_x - ev->value)) / time_diff);
557 velo_x_count = velo_x_count + (int)velo_x;
560 if (velo_x_count > 2)
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;
567 EvdevRCSendEvent(pInfo, EV_REL, REL_HWHEEL, ((before_x - ev->value) < 0)? -velo_x_count: velo_x_count);
571 before_x = ev->value;
572 before_x_time = ev->time.tv_sec;
573 before_x_utime = ev->time.tv_usec;
575 else if (ev->type == EV_ABS && ev->code == ABS_Y && wheel_direction_flag != SCROLL_HORIZEN)
577 time_diff = (ev->time.tv_sec - before_y_time) * 1000 + (ev->time.tv_usec - before_y_utime)/1000;
580 ErrorF("before and current events had same event time...\n");
583 velo_y = (float)((ABS(before_y - ev->value)) / time_diff);
587 velo_y_count = velo_y_count + (int)velo_y;
590 if (velo_y_count > 2)
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;
597 EvdevRCSendEvent(pInfo, EV_REL, REL_WHEEL, ((before_y - ev->value) < 0)? -velo_y_count: velo_y_count);
601 before_y = ev->value;
602 before_y_time = ev->time.tv_sec;
603 before_y_utime = ev->time.tv_usec;
607 int EvdevRCIsSwipe(struct input_event *ev)
610 static int base_point_x = -1;
611 static int base_point_y = -1;
613 if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
619 if (ev->type == EV_ABS)
621 if (ev->code == ABS_X)
623 if (base_point_x == -1)
625 base_point_x = ev->value;
627 else if (ABS(base_point_x - ev->value) > 300)
632 else if (ev->code == ABS_Y)
634 if (base_point_y == -1)
636 base_point_y = ev->value;
638 else if (ABS(base_point_y - ev->value) > 300)
648 void EvdevRCSendEvent(InputInfoPtr pInfo, int type, int code, int value)
650 EvdevPtr pEvdev = pInfo->private;
651 struct input_event ev;
657 pEvdev->origin_input_process(pInfo, &ev);
661 EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
664 InputInfoPtr pInfo = dev->public.devicePrivate;
665 EvdevPtr pEvdev = pInfo->private;
667 if (atom == atomCalculateDistance )
673 int EvdevRCIsBoundary(struct input_event *ev, int rc_range)
675 static int x_diff=0, y_diff = 0;
678 if (ev->type == EV_KEY && IF_KEY_CODE_TOUCH)
683 if (ev->type == EV_REL)
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;
691 if ((ABS(x_diff) > rc_range) || (ABS(y_diff) > rc_range))
698 void EvdevRCInit(DeviceIntPtr device)
703 pInfo = device->public.devicePrivate;
704 pEvdev = pInfo->private;
706 if (pEvdev->flags & EVDEV_SMART_RC)
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);
717 #ifdef _F_SMART_RC_CHG_KBD_SRC_DEV_
720 if (!strncmp(pEvdev->name, AIR_TOUCH_MOUSE, strlen(AIR_TOUCH_MOUSE))) pSmartRCKbdDeviceInfo = pInfo;
723 XIRegisterPropertyHandler(device, EvdevSetProperty, NULL, NULL);
726 #endif //_F_EVDEV_SUPPORT_SMARTRC_