2 * Copyright © 2012 Jonas Ådahl
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32 #include <linux/input.h>
33 #include <sys/timerfd.h>
37 #include "libinput-private.h"
40 #define DEFAULT_CONSTANT_ACCEL_NUMERATOR 50
41 #define DEFAULT_MIN_ACCEL_FACTOR 0.16
42 #define DEFAULT_MAX_ACCEL_FACTOR 1.0
43 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
45 #define DEFAULT_TOUCHPAD_SINGLE_TAP_BUTTON BTN_LEFT
46 #define DEFAULT_TOUCHPAD_SINGLE_TAP_TIMEOUT 100
49 TOUCHPAD_MODEL_UNKNOWN = 0,
50 TOUCHPAD_MODEL_SYNAPTICS,
52 TOUCHPAD_MODEL_APPLETOUCH,
53 TOUCHPAD_MODEL_ELANTECH
57 TOUCHPAD_EVENT_NONE = 0,
58 TOUCHPAD_EVENT_ABSOLUTE_ANY = (1 << 0),
59 TOUCHPAD_EVENT_ABSOLUTE_X = (1 << 1),
60 TOUCHPAD_EVENT_ABSOLUTE_Y = (1 << 2),
61 TOUCHPAD_EVENT_REPORT = (1 << 3)
64 struct touchpad_model_spec {
67 enum touchpad_model model;
70 static struct touchpad_model_spec touchpad_spec_table[] = {
71 {0x0002, 0x0007, TOUCHPAD_MODEL_SYNAPTICS},
72 {0x0002, 0x0008, TOUCHPAD_MODEL_ALPS},
73 {0x05ac, 0x0000, TOUCHPAD_MODEL_APPLETOUCH},
74 {0x0002, 0x000e, TOUCHPAD_MODEL_ELANTECH},
75 {0x0000, 0x0000, TOUCHPAD_MODEL_UNKNOWN}
79 TOUCHPAD_STATE_NONE = 0,
80 TOUCHPAD_STATE_TOUCH = (1 << 0),
81 TOUCHPAD_STATE_MOVE = (1 << 1)
84 #define TOUCHPAD_HISTORY_LENGTH 4
86 struct touchpad_motion {
91 enum touchpad_fingers_state {
92 TOUCHPAD_FINGERS_ONE = (1 << 0),
93 TOUCHPAD_FINGERS_TWO = (1 << 1),
94 TOUCHPAD_FINGERS_THREE = (1 << 2)
112 struct touchpad_dispatch {
113 struct evdev_dispatch base;
114 struct evdev_device *device;
116 enum touchpad_model model;
119 int last_finger_state;
121 double constant_accel_factor;
122 double min_accel_factor;
123 double max_accel_factor;
125 unsigned int event_mask;
126 unsigned int event_mask_filter;
134 enum fsm_event *events;
137 enum fsm_state state;
140 struct libinput_fd_handle *fd_handle;
162 struct touchpad_motion motion_history[TOUCHPAD_HISTORY_LENGTH];
164 unsigned int motion_count;
166 struct motion_filter *filter;
169 static enum touchpad_model
170 get_touchpad_model(struct evdev_device *device)
175 if (ioctl(device->fd, EVIOCGID, &id) < 0)
176 return TOUCHPAD_MODEL_UNKNOWN;
178 for (i = 0; i < ARRAY_LENGTH(touchpad_spec_table); i++)
179 if (touchpad_spec_table[i].vendor == id.vendor &&
180 (!touchpad_spec_table[i].product ||
181 touchpad_spec_table[i].product == id.product))
182 return touchpad_spec_table[i].model;
184 return TOUCHPAD_MODEL_UNKNOWN;
188 configure_touchpad_pressure(struct touchpad_dispatch *touchpad,
189 int32_t pressure_min, int32_t pressure_max)
191 int32_t range = pressure_max - pressure_min + 1;
193 touchpad->has_pressure = 1;
195 /* Magic numbers from xf86-input-synaptics */
196 switch (touchpad->model) {
197 case TOUCHPAD_MODEL_ELANTECH:
198 touchpad->pressure.touch_low = pressure_min + 1;
199 touchpad->pressure.touch_high = pressure_min + 1;
202 touchpad->pressure.touch_low =
203 pressure_min + range * (25.0/256.0);
204 touchpad->pressure.touch_high =
205 pressure_min + range * (30.0/256.0);
210 touchpad_profile(struct motion_filter *filter,
215 struct touchpad_dispatch *touchpad =
216 (struct touchpad_dispatch *) data;
220 accel_factor = velocity * touchpad->constant_accel_factor;
222 if (accel_factor > touchpad->max_accel_factor)
223 accel_factor = touchpad->max_accel_factor;
224 else if (accel_factor < touchpad->min_accel_factor)
225 accel_factor = touchpad->min_accel_factor;
230 static inline struct touchpad_motion *
231 motion_history_offset(struct touchpad_dispatch *touchpad, int offset)
234 (touchpad->motion_index - offset + TOUCHPAD_HISTORY_LENGTH) %
235 TOUCHPAD_HISTORY_LENGTH;
237 return &touchpad->motion_history[offset_index];
241 estimate_delta(int x0, int x1, int x2, int x3)
243 return (x0 + x1 - x2 - x3) / 4;
247 hysteresis(int in, int center, int margin)
249 int diff = in - center;
250 if (abs(diff) <= margin)
254 return center + diff - margin;
255 else if (diff < -margin)
256 return center + diff + margin;
257 return center + diff;
261 touchpad_get_delta(struct touchpad_dispatch *touchpad, double *dx, double *dy)
263 *dx = estimate_delta(motion_history_offset(touchpad, 0)->x,
264 motion_history_offset(touchpad, 1)->x,
265 motion_history_offset(touchpad, 2)->x,
266 motion_history_offset(touchpad, 3)->x);
267 *dy = estimate_delta(motion_history_offset(touchpad, 0)->y,
268 motion_history_offset(touchpad, 1)->y,
269 motion_history_offset(touchpad, 2)->y,
270 motion_history_offset(touchpad, 3)->y);
274 filter_motion(struct touchpad_dispatch *touchpad,
275 double *dx, double *dy, uint32_t time)
277 struct motion_params motion;
282 filter_dispatch(touchpad->filter, &motion, touchpad, time);
289 notify_button_pressed(struct touchpad_dispatch *touchpad, uint32_t time)
291 pointer_notify_button(
292 &touchpad->device->base,
294 DEFAULT_TOUCHPAD_SINGLE_TAP_BUTTON,
295 LIBINPUT_POINTER_BUTTON_STATE_PRESSED);
299 notify_button_released(struct touchpad_dispatch *touchpad, uint32_t time)
301 pointer_notify_button(
302 &touchpad->device->base,
304 DEFAULT_TOUCHPAD_SINGLE_TAP_BUTTON,
305 LIBINPUT_POINTER_BUTTON_STATE_RELEASED);
309 notify_tap(struct touchpad_dispatch *touchpad, uint32_t time)
311 notify_button_pressed(touchpad, time);
312 notify_button_released(touchpad, time);
316 process_fsm_events(struct touchpad_dispatch *touchpad, uint32_t time)
318 uint32_t timeout = UINT32_MAX;
319 enum fsm_event event;
322 if (!touchpad->fsm.enable)
325 if (touchpad->fsm.events_count == 0)
328 for (i = 0; i < touchpad->fsm.events_count; ++i) {
329 event = touchpad->fsm.events[i];
332 switch (touchpad->fsm.state) {
335 case FSM_EVENT_TOUCH:
336 touchpad->fsm.state = FSM_TOUCH;
344 case FSM_EVENT_RELEASE:
345 timeout = DEFAULT_TOUCHPAD_SINGLE_TAP_TIMEOUT;
346 touchpad->fsm.state = FSM_TAP;
349 touchpad->fsm.state = FSM_IDLE;
355 case FSM_EVENT_TIMEOUT:
356 notify_tap(touchpad, time);
357 touchpad->fsm.state = FSM_IDLE;
359 case FSM_EVENT_TOUCH:
360 notify_button_pressed(touchpad, time);
361 touchpad->fsm.state = FSM_TAP_2;
364 touchpad->fsm.state = FSM_IDLE;
370 case FSM_EVENT_MOTION:
371 touchpad->fsm.state = FSM_DRAG;
373 case FSM_EVENT_RELEASE:
374 notify_button_released(touchpad, time);
375 notify_tap(touchpad, time);
376 touchpad->fsm.state = FSM_IDLE;
379 touchpad->fsm.state = FSM_IDLE;
385 case FSM_EVENT_RELEASE:
386 notify_button_released(touchpad, time);
387 touchpad->fsm.state = FSM_IDLE;
390 touchpad->fsm.state = FSM_IDLE;
395 touchpad->fsm.state = FSM_IDLE;
400 if (timeout != UINT32_MAX) {
401 struct itimerspec its;
403 its.it_interval.tv_sec = 0;
404 its.it_interval.tv_nsec = 0;
405 its.it_value.tv_sec = timeout / 1000;
406 its.it_value.tv_nsec = (timeout % 1000) * 1000 * 1000;
407 timerfd_settime(touchpad->fsm.timer.fd, 0, &its, NULL);
410 touchpad->fsm.events_count = 0;
414 push_fsm_event(struct touchpad_dispatch *touchpad,
415 enum fsm_event event)
417 enum fsm_event *events;
418 size_t new_len = touchpad->fsm.events_len;
420 if (!touchpad->fsm.enable)
423 if (touchpad->fsm.events_count + 1 >= touchpad->fsm.events_len) {
428 events = realloc(touchpad->fsm.events,
429 sizeof(enum fsm_event) * new_len);
431 touchpad->fsm.state = FSM_IDLE;
435 touchpad->fsm.events = events;
436 touchpad->fsm.events_len = new_len;
439 touchpad->fsm.events[touchpad->fsm.events_count++] = event;
443 fsm_timeout_handler(int fd, void *data)
445 struct evdev_device *device = data;
446 struct touchpad_dispatch *touchpad =
447 (struct touchpad_dispatch *) device->dispatch;
453 len = read(fd, &expires, sizeof expires);
454 if (len != sizeof expires)
455 /* This will only happen if the application made the fd
456 * non-blocking, but this function should only be called
457 * upon the timeout, so lets continue anyway. */
458 fprintf(stderr, "timerfd read error: %m\n");
460 if (touchpad->fsm.events_count == 0) {
461 clock_gettime(CLOCK_MONOTONIC, &ts);
462 now = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
464 push_fsm_event(touchpad, FSM_EVENT_TIMEOUT);
465 process_fsm_events(touchpad, now);
470 touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
473 int center_x, center_y;
474 double dx = 0.0, dy = 0.0;
475 struct libinput_device *base = &touchpad->device->base;
477 if (touchpad->reset ||
478 touchpad->last_finger_state != touchpad->finger_state) {
480 touchpad->motion_count = 0;
481 touchpad->event_mask = TOUCHPAD_EVENT_NONE;
482 touchpad->event_mask_filter =
483 TOUCHPAD_EVENT_ABSOLUTE_X | TOUCHPAD_EVENT_ABSOLUTE_Y;
485 touchpad->last_finger_state = touchpad->finger_state;
487 process_fsm_events(touchpad, time);
491 touchpad->last_finger_state = touchpad->finger_state;
493 if (!(touchpad->event_mask & TOUCHPAD_EVENT_REPORT))
496 touchpad->event_mask &= ~TOUCHPAD_EVENT_REPORT;
498 if ((touchpad->event_mask & touchpad->event_mask_filter) !=
499 touchpad->event_mask_filter)
502 touchpad->event_mask_filter = TOUCHPAD_EVENT_ABSOLUTE_ANY;
503 touchpad->event_mask = 0;
505 /* Avoid noice by moving center only when delta reaches a threshold
506 * distance from the old center. */
507 if (touchpad->motion_count > 0) {
508 center_x = hysteresis(touchpad->hw_abs.x,
509 touchpad->hysteresis.center_x,
510 touchpad->hysteresis.margin_x);
511 center_y = hysteresis(touchpad->hw_abs.y,
512 touchpad->hysteresis.center_y,
513 touchpad->hysteresis.margin_y);
515 center_x = touchpad->hw_abs.x;
516 center_y = touchpad->hw_abs.y;
518 touchpad->hysteresis.center_x = center_x;
519 touchpad->hysteresis.center_y = center_y;
520 touchpad->hw_abs.x = center_x;
521 touchpad->hw_abs.y = center_y;
523 /* Update motion history tracker */
524 motion_index = (touchpad->motion_index + 1) % TOUCHPAD_HISTORY_LENGTH;
525 touchpad->motion_index = motion_index;
526 touchpad->motion_history[motion_index].x = touchpad->hw_abs.x;
527 touchpad->motion_history[motion_index].y = touchpad->hw_abs.y;
528 if (touchpad->motion_count < 4)
529 touchpad->motion_count++;
531 if (touchpad->motion_count >= 4) {
532 touchpad_get_delta(touchpad, &dx, &dy);
534 filter_motion(touchpad, &dx, &dy, time);
536 if (touchpad->finger_state == TOUCHPAD_FINGERS_ONE) {
537 pointer_notify_motion(
540 li_fixed_from_double(dx),
541 li_fixed_from_double(dy));
542 } else if (touchpad->finger_state == TOUCHPAD_FINGERS_TWO) {
547 LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
548 li_fixed_from_double(dx));
553 LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
554 li_fixed_from_double(dy));
558 if (!(touchpad->state & TOUCHPAD_STATE_MOVE) &&
559 ((int)dx || (int)dy)) {
560 touchpad->state |= TOUCHPAD_STATE_MOVE;
561 push_fsm_event(touchpad, FSM_EVENT_MOTION);
564 process_fsm_events(touchpad, time);
568 on_touch(struct touchpad_dispatch *touchpad)
570 touchpad->state |= TOUCHPAD_STATE_TOUCH;
572 push_fsm_event(touchpad, FSM_EVENT_TOUCH);
576 on_release(struct touchpad_dispatch *touchpad)
580 touchpad->state &= ~(TOUCHPAD_STATE_MOVE | TOUCHPAD_STATE_TOUCH);
582 push_fsm_event(touchpad, FSM_EVENT_RELEASE);
586 process_absolute(struct touchpad_dispatch *touchpad,
587 struct evdev_device *device,
588 struct input_event *e)
592 if (e->value > touchpad->pressure.touch_high &&
593 !(touchpad->state & TOUCHPAD_STATE_TOUCH))
595 else if (e->value < touchpad->pressure.touch_low &&
596 touchpad->state & TOUCHPAD_STATE_TOUCH)
597 on_release(touchpad);
601 if (touchpad->state & TOUCHPAD_STATE_TOUCH) {
602 touchpad->hw_abs.x = e->value;
603 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
604 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_X;
608 if (touchpad->state & TOUCHPAD_STATE_TOUCH) {
609 touchpad->hw_abs.y = e->value;
610 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
611 touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_Y;
618 process_key(struct touchpad_dispatch *touchpad,
619 struct evdev_device *device,
620 struct input_event *e,
627 if (!touchpad->has_pressure) {
628 if (e->value && !(touchpad->state & TOUCHPAD_STATE_TOUCH))
631 on_release(touchpad);
642 if (!touchpad->fsm.enable && e->code == BTN_LEFT &&
643 touchpad->finger_state == TOUCHPAD_FINGERS_TWO)
647 pointer_notify_button(
648 &touchpad->device->base,
651 e->value ? LIBINPUT_POINTER_BUTTON_STATE_PRESSED :
652 LIBINPUT_POINTER_BUTTON_STATE_RELEASED);
655 case BTN_TOOL_RUBBER:
657 case BTN_TOOL_PENCIL:
658 case BTN_TOOL_AIRBRUSH:
663 case BTN_TOOL_FINGER:
665 touchpad->finger_state |= TOUCHPAD_FINGERS_ONE;
667 touchpad->finger_state &= ~TOUCHPAD_FINGERS_ONE;
669 case BTN_TOOL_DOUBLETAP:
671 touchpad->finger_state |= TOUCHPAD_FINGERS_TWO;
673 touchpad->finger_state &= ~TOUCHPAD_FINGERS_TWO;
675 case BTN_TOOL_TRIPLETAP:
677 touchpad->finger_state |= TOUCHPAD_FINGERS_THREE;
679 touchpad->finger_state &= ~TOUCHPAD_FINGERS_THREE;
685 touchpad_process(struct evdev_dispatch *dispatch,
686 struct evdev_device *device,
687 struct input_event *e,
690 struct touchpad_dispatch *touchpad =
691 (struct touchpad_dispatch *) dispatch;
695 if (e->code == SYN_REPORT)
696 touchpad->event_mask |= TOUCHPAD_EVENT_REPORT;
699 process_absolute(touchpad, device, e);
702 process_key(touchpad, device, e, time);
706 touchpad_update_state(touchpad, time);
710 touchpad_destroy(struct evdev_dispatch *dispatch)
712 struct touchpad_dispatch *touchpad =
713 (struct touchpad_dispatch *) dispatch;
715 touchpad->filter->interface->destroy(touchpad->filter);
716 touchpad->device->base.device_interface->remove_fd(
717 touchpad->fsm.timer.fd_handle,
718 touchpad->device->base.device_interface_data);
719 close(touchpad->fsm.timer.fd);
720 free(touchpad->fsm.events);
724 struct evdev_dispatch_interface touchpad_interface = {
730 touchpad_init(struct touchpad_dispatch *touchpad,
731 struct evdev_device *device)
733 struct motion_filter *accel;
735 unsigned long prop_bits[INPUT_PROP_MAX];
736 struct input_absinfo absinfo;
737 unsigned long abs_bits[NBITS(ABS_MAX)];
745 touchpad->base.interface = &touchpad_interface;
746 touchpad->device = device;
749 touchpad->model = get_touchpad_model(device);
751 ioctl(device->fd, EVIOCGPROP(sizeof(prop_bits)), prop_bits);
752 has_buttonpad = TEST_BIT(prop_bits, INPUT_PROP_BUTTONPAD);
754 /* Configure pressure */
755 ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
756 if (TEST_BIT(abs_bits, ABS_PRESSURE)) {
757 ioctl(device->fd, EVIOCGABS(ABS_PRESSURE), &absinfo);
758 configure_touchpad_pressure(touchpad,
763 /* Configure acceleration factor */
764 width = abs(device->abs.max_x - device->abs.min_x);
765 height = abs(device->abs.max_y - device->abs.min_y);
766 diagonal = sqrt(width*width + height*height);
768 /* Set default parameters */
769 touchpad->constant_accel_factor =
770 DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal;
771 touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR;
772 touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR;
774 touchpad->hysteresis.margin_x =
775 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
776 touchpad->hysteresis.margin_y =
777 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
778 touchpad->hysteresis.center_x = 0;
779 touchpad->hysteresis.center_y = 0;
781 /* Configure acceleration profile */
782 accel = create_pointer_accelator_filter(touchpad_profile);
785 touchpad->filter = accel;
787 /* Setup initial state */
790 memset(touchpad->motion_history, 0, sizeof touchpad->motion_history);
791 touchpad->motion_index = 0;
792 touchpad->motion_count = 0;
794 touchpad->state = TOUCHPAD_STATE_NONE;
795 touchpad->last_finger_state = 0;
796 touchpad->finger_state = 0;
798 touchpad->fsm.events = NULL;
799 touchpad->fsm.events_count = 0;
800 touchpad->fsm.events_len = 0;
801 touchpad->fsm.state = FSM_IDLE;
803 touchpad->fsm.timer.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
804 touchpad->fsm.timer.fd_handle =
805 touchpad->device->base.device_interface->add_fd(
806 touchpad->fsm.timer.fd,
808 touchpad->device->base.device_interface_data);
810 if (touchpad->fsm.timer.fd_handle == NULL) {
811 close(touchpad->fsm.timer.fd);
812 accel->interface->destroy(accel);
817 touchpad->fsm.enable = !has_buttonpad;
822 struct evdev_dispatch *
823 evdev_touchpad_create(struct evdev_device *device)
825 struct touchpad_dispatch *touchpad;
827 touchpad = malloc(sizeof *touchpad);
828 if (touchpad == NULL)
831 if (touchpad_init(touchpad, device) != 0) {
836 return &touchpad->base;