Replace fprintf() by weston_log()
[profile/ivi/weston.git] / src / evdev-touchpad.c
1 /*
2  * Copyright © 2012 Jonas Ådahl
3  *
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.
13  *
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.
21  */
22
23 #include <stdlib.h>
24 #include <math.h>
25 #include <string.h>
26 #include <linux/input.h>
27
28 #include "filter.h"
29 #include "evdev-private.h"
30
31 /* Default values */
32 #define DEFAULT_CONSTANT_ACCEL_NUMERATOR 50
33 #define DEFAULT_MIN_ACCEL_FACTOR 0.16
34 #define DEFAULT_MAX_ACCEL_FACTOR 1.0
35 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
36
37 enum touchpad_model {
38         TOUCHPAD_MODEL_UNKNOWN = 0,
39         TOUCHPAD_MODEL_SYNAPTICS,
40         TOUCHPAD_MODEL_ALPS,
41         TOUCHPAD_MODEL_APPLETOUCH,
42         TOUCHPAD_MODEL_ELANTECH
43 };
44
45 #define TOUCHPAD_EVENT_NONE             0
46 #define TOUCHPAD_EVENT_ABSOLUTE_ANY     (1 << 0)
47 #define TOUCHPAD_EVENT_ABSOLUTE_X       (1 << 1)
48 #define TOUCHPAD_EVENT_ABSOLUTE_Y       (1 << 2)
49 #define TOUCHPAD_EVENT_REPORT           (1 << 3)
50
51 struct touchpad_model_spec {
52         short vendor;
53         short product;
54         enum touchpad_model model;
55 };
56
57 static struct touchpad_model_spec touchpad_spec_table[] = {
58         {0x0002, 0x0007, TOUCHPAD_MODEL_SYNAPTICS},
59         {0x0002, 0x0008, TOUCHPAD_MODEL_ALPS},
60         {0x05ac, 0x0000, TOUCHPAD_MODEL_APPLETOUCH},
61         {0x0002, 0x000e, TOUCHPAD_MODEL_ELANTECH},
62         {0x0000, 0x0000, TOUCHPAD_MODEL_UNKNOWN}
63 };
64
65 enum touchpad_state {
66         TOUCHPAD_STATE_NONE = 0,
67         TOUCHPAD_STATE_TOUCH,
68         TOUCHPAD_STATE_PRESS
69 };
70
71 #define TOUCHPAD_HISTORY_LENGTH 4
72
73 struct touchpad_motion {
74         int32_t x;
75         int32_t y;
76 };
77
78 enum touchpad_fingers_state {
79         TOUCHPAD_FINGERS_ONE   = (1 << 0),
80         TOUCHPAD_FINGERS_TWO   = (1 << 1),
81         TOUCHPAD_FINGERS_THREE = (1 << 2)
82 };
83
84 struct touchpad_dispatch {
85         struct evdev_dispatch base;
86         struct evdev_input_device *device;
87
88         enum touchpad_model model;
89         enum touchpad_state state;
90         int finger_state;
91         int last_finger_state;
92
93         double constant_accel_factor;
94         double min_accel_factor;
95         double max_accel_factor;
96
97         unsigned int event_mask;
98         unsigned int event_mask_filter;
99
100         int reset;
101
102         struct {
103                 int32_t x;
104                 int32_t y;
105         } hw_abs;
106
107         int has_pressure;
108         struct {
109                 int32_t touch_low;
110                 int32_t touch_high;
111                 int32_t press;
112         } pressure;
113
114         struct {
115                 int32_t margin_x;
116                 int32_t margin_y;
117                 int32_t center_x;
118                 int32_t center_y;
119         } hysteresis;
120
121         struct touchpad_motion motion_history[TOUCHPAD_HISTORY_LENGTH];
122         int motion_index;
123         unsigned int motion_count;
124
125         struct wl_list motion_filters;
126 };
127
128 static enum touchpad_model
129 get_touchpad_model(struct evdev_input_device *device)
130 {
131         struct input_id id;
132         unsigned int i;
133
134         if (ioctl(device->fd, EVIOCGID, &id) < 0)
135                 return TOUCHPAD_MODEL_UNKNOWN;
136
137         for (i = 0; i < sizeof touchpad_spec_table; i++)
138                 if (touchpad_spec_table[i].vendor == id.vendor &&
139                     (!touchpad_spec_table[i].product ||
140                      touchpad_spec_table[i].product == id.product))
141                         return touchpad_spec_table[i].model;
142
143         return TOUCHPAD_MODEL_UNKNOWN;
144 }
145
146 static void
147 configure_touchpad_pressure(struct touchpad_dispatch *touchpad,
148                             int32_t pressure_min, int32_t pressure_max)
149 {
150         int32_t range = pressure_max - pressure_min + 1;
151
152         touchpad->has_pressure = 1;
153
154         /* Magic numbers from xf86-input-synaptics */
155         switch (touchpad->model) {
156         case TOUCHPAD_MODEL_ELANTECH:
157                 touchpad->pressure.touch_low = pressure_min + 1;
158                 touchpad->pressure.touch_high = pressure_min + 1;
159                 break;
160         default:
161                 touchpad->pressure.touch_low =
162                         pressure_min + range * (25.0/256.0);
163                 touchpad->pressure.touch_high =
164                         pressure_min + range * (30.0/256.0);
165         }
166
167         touchpad->pressure.press = pressure_min + range;
168 }
169
170 static double
171 touchpad_profile(struct weston_motion_filter *filter,
172                  void *data,
173                  double velocity,
174                  uint32_t time)
175 {
176         struct touchpad_dispatch *touchpad =
177                 (struct touchpad_dispatch *) data;
178
179         double accel_factor;
180
181         accel_factor = velocity * touchpad->constant_accel_factor;
182
183         if (accel_factor > touchpad->max_accel_factor)
184                 accel_factor = touchpad->max_accel_factor;
185         else if (accel_factor < touchpad->min_accel_factor)
186                 accel_factor = touchpad->min_accel_factor;
187
188         return accel_factor;
189 }
190
191 static void
192 configure_touchpad(struct touchpad_dispatch *touchpad,
193                    struct evdev_input_device *device)
194 {
195         struct weston_motion_filter *accel;
196
197         struct input_absinfo absinfo;
198         unsigned long abs_bits[NBITS(ABS_MAX)];
199
200         double width;
201         double height;
202         double diagonal;
203
204         /* Detect model */
205         touchpad->model = get_touchpad_model(device);
206
207         /* Configure pressure */
208         ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
209         if (TEST_BIT(abs_bits, ABS_PRESSURE)) {
210                 ioctl(device->fd, EVIOCGABS(ABS_PRESSURE), &absinfo);
211                 configure_touchpad_pressure(touchpad,
212                                             absinfo.minimum,
213                                             absinfo.maximum);
214         }
215
216         /* Configure acceleration factor */
217         width = abs(device->abs.max_x - device->abs.min_x);
218         height = abs(device->abs.max_y - device->abs.min_y);
219         diagonal = sqrt(width*width + height*height);
220
221         touchpad->constant_accel_factor =
222                 DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal;
223
224         touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR;
225         touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR;
226
227         touchpad->hysteresis.margin_x =
228                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
229         touchpad->hysteresis.margin_y =
230                 diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
231         touchpad->hysteresis.center_x = 0;
232         touchpad->hysteresis.center_y = 0;
233
234         /* Configure acceleration profile */
235         accel = create_pointer_accelator_filter(touchpad_profile);
236         wl_list_insert(&touchpad->motion_filters, &accel->link);
237
238         /* Setup initial state */
239         touchpad->reset = 1;
240
241         memset(touchpad->motion_history, 0, sizeof touchpad->motion_history);
242         touchpad->motion_index = 0;
243         touchpad->motion_count = 0;
244
245         touchpad->state = TOUCHPAD_STATE_NONE;
246         touchpad->last_finger_state = 0;
247         touchpad->finger_state = 0;
248 }
249
250 static inline struct touchpad_motion *
251 motion_history_offset(struct touchpad_dispatch *touchpad, int offset)
252 {
253         int offset_index =
254                 (touchpad->motion_index - offset + TOUCHPAD_HISTORY_LENGTH) %
255                 TOUCHPAD_HISTORY_LENGTH;
256
257         return &touchpad->motion_history[offset_index];
258 }
259
260 static double
261 estimate_delta(int x0, int x1, int x2, int x3)
262 {
263         return (x0 + x1 - x2 - x3) / 4;
264 }
265
266 static int
267 hysteresis(int in, int center, int margin)
268 {
269         int diff = in - center;
270         if (abs(diff) <= margin)
271                 return center;
272
273         if (diff > margin)
274                 return center + diff - margin;
275         else if (diff < -margin)
276                 return center + diff + margin;
277         return center + diff;
278 }
279
280 static void
281 touchpad_get_delta(struct touchpad_dispatch *touchpad, double *dx, double *dy)
282 {
283         *dx = estimate_delta(motion_history_offset(touchpad, 0)->x,
284                              motion_history_offset(touchpad, 1)->x,
285                              motion_history_offset(touchpad, 2)->x,
286                              motion_history_offset(touchpad, 3)->x);
287         *dy = estimate_delta(motion_history_offset(touchpad, 0)->y,
288                              motion_history_offset(touchpad, 1)->y,
289                              motion_history_offset(touchpad, 2)->y,
290                              motion_history_offset(touchpad, 3)->y);
291 }
292
293 static void
294 filter_motion(struct touchpad_dispatch *touchpad,
295               double *dx, double *dy, uint32_t time)
296 {
297         struct weston_motion_filter *filter;
298         struct weston_motion_params motion;
299
300         motion.dx = *dx;
301         motion.dy = *dy;
302
303         wl_list_for_each(filter, &touchpad->motion_filters, link)
304                 weston_filter_dispatch(filter, &motion, touchpad, time);
305
306         *dx = motion.dx;
307         *dy = motion.dy;
308 }
309
310 static void
311 touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
312 {
313         int motion_index;
314         int center_x, center_y;
315         double dx, dy;
316
317         if (touchpad->reset ||
318             touchpad->last_finger_state != touchpad->finger_state) {
319                 touchpad->reset = 0;
320                 touchpad->motion_count = 0;
321                 touchpad->event_mask = TOUCHPAD_EVENT_NONE;
322                 touchpad->event_mask_filter =
323                         TOUCHPAD_EVENT_ABSOLUTE_X | TOUCHPAD_EVENT_ABSOLUTE_Y;
324
325                 touchpad->last_finger_state = touchpad->finger_state;
326
327                 return;
328         }
329         touchpad->last_finger_state = touchpad->finger_state;
330
331         if (!(touchpad->event_mask & TOUCHPAD_EVENT_REPORT))
332                 return;
333         else
334                 touchpad->event_mask &= ~TOUCHPAD_EVENT_REPORT;
335
336         if ((touchpad->event_mask & touchpad->event_mask_filter) !=
337             touchpad->event_mask_filter)
338                 return;
339
340         touchpad->event_mask_filter = TOUCHPAD_EVENT_ABSOLUTE_ANY;
341         touchpad->event_mask = 0;
342
343         /* Avoid noice by moving center only when delta reaches a threshold
344          * distance from the old center. */
345         if (touchpad->motion_count > 0) {
346                 center_x = hysteresis(touchpad->hw_abs.x,
347                                       touchpad->hysteresis.center_x,
348                                       touchpad->hysteresis.margin_x);
349                 center_y = hysteresis(touchpad->hw_abs.y,
350                                       touchpad->hysteresis.center_y,
351                                       touchpad->hysteresis.margin_y);
352         }
353         else {
354                 center_x = touchpad->hw_abs.x;
355                 center_y = touchpad->hw_abs.y;
356         }
357         touchpad->hysteresis.center_x = center_x;
358         touchpad->hysteresis.center_y = center_y;
359         touchpad->hw_abs.x = center_x;
360         touchpad->hw_abs.y = center_y;
361
362         /* Update motion history tracker */
363         motion_index = (touchpad->motion_index + 1) % TOUCHPAD_HISTORY_LENGTH;
364         touchpad->motion_index = motion_index;
365         touchpad->motion_history[motion_index].x = touchpad->hw_abs.x;
366         touchpad->motion_history[motion_index].y = touchpad->hw_abs.y;
367         if (touchpad->motion_count < 4)
368                 touchpad->motion_count++;
369
370         if (touchpad->motion_count >= 4) {
371                 touchpad_get_delta(touchpad, &dx, &dy);
372
373                 filter_motion(touchpad, &dx, &dy, time);
374
375                 touchpad->device->rel.dx = wl_fixed_from_double(dx);
376                 touchpad->device->rel.dy = wl_fixed_from_double(dy);
377                 touchpad->device->pending_events |= EVDEV_RELATIVE_MOTION;
378         }
379 }
380
381 static inline void
382 process_absolute(struct touchpad_dispatch *touchpad,
383                  struct evdev_input_device *device,
384                  struct input_event *e)
385 {
386         switch (e->code) {
387         case ABS_PRESSURE:
388                 if (e->value > touchpad->pressure.press)
389                         touchpad->state = TOUCHPAD_STATE_PRESS;
390                 else if (e->value > touchpad->pressure.touch_high)
391                         touchpad->state = TOUCHPAD_STATE_TOUCH;
392                 else if (e->value < touchpad->pressure.touch_low) {
393                         if (touchpad->state > TOUCHPAD_STATE_NONE)
394                                 touchpad->reset = 1;
395
396                         touchpad->state = TOUCHPAD_STATE_NONE;
397                 }
398
399                 break;
400         case ABS_X:
401                 if (touchpad->state >= TOUCHPAD_STATE_TOUCH) {
402                         touchpad->hw_abs.x = e->value;
403                         touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
404                         touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_X;
405                 }
406                 break;
407         case ABS_Y:
408                 if (touchpad->state >= TOUCHPAD_STATE_TOUCH) {
409                         touchpad->hw_abs.y = e->value;
410                         touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
411                         touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_Y;
412                 }
413                 break;
414         }
415 }
416
417 static inline void
418 process_key(struct touchpad_dispatch *touchpad,
419             struct evdev_input_device *device,
420             struct input_event *e,
421             uint32_t time)
422 {
423         switch (e->code) {
424         case BTN_TOUCH:
425                 if (!touchpad->has_pressure) {
426                         if (!e->value) {
427                                 touchpad->state = TOUCHPAD_STATE_NONE;
428                                 touchpad->reset = 1;
429                         } else {
430                                 touchpad->state =
431                                         e->value ?
432                                         TOUCHPAD_STATE_TOUCH :
433                                         TOUCHPAD_STATE_NONE;
434                         }
435                 }
436                 break;
437         case BTN_LEFT:
438         case BTN_RIGHT:
439         case BTN_MIDDLE:
440         case BTN_SIDE:
441         case BTN_EXTRA:
442         case BTN_FORWARD:
443         case BTN_BACK:
444         case BTN_TASK:
445                 notify_button(&device->master->base.seat,
446                               time, e->code,
447                               e->value ? WL_POINTER_BUTTON_STATE_PRESSED :
448                                          WL_POINTER_BUTTON_STATE_RELEASED);
449                 break;
450         case BTN_TOOL_PEN:
451         case BTN_TOOL_RUBBER:
452         case BTN_TOOL_BRUSH:
453         case BTN_TOOL_PENCIL:
454         case BTN_TOOL_AIRBRUSH:
455         case BTN_TOOL_MOUSE:
456         case BTN_TOOL_LENS:
457                 touchpad->reset = 1;
458                 break;
459         case BTN_TOOL_FINGER:
460                 touchpad->finger_state =
461                         ~TOUCHPAD_FINGERS_ONE | e->value ?
462                         TOUCHPAD_FINGERS_ONE : 0;
463                 break;
464         case BTN_TOOL_DOUBLETAP:
465                 touchpad->finger_state =
466                         ~TOUCHPAD_FINGERS_TWO | e->value ?
467                         TOUCHPAD_FINGERS_TWO : 0;
468                 break;
469         case BTN_TOOL_TRIPLETAP:
470                 touchpad->finger_state =
471                         ~TOUCHPAD_FINGERS_THREE | e->value ?
472                         TOUCHPAD_FINGERS_THREE : 0;
473                 break;
474         }
475 }
476
477 static void
478 touchpad_process(struct evdev_dispatch *dispatch,
479                  struct evdev_input_device *device,
480                  struct input_event *e,
481                  uint32_t time)
482 {
483         struct touchpad_dispatch *touchpad =
484                 (struct touchpad_dispatch *) dispatch;
485
486         switch (e->type) {
487         case EV_SYN:
488                 if (e->code == SYN_REPORT)
489                         touchpad->event_mask |= TOUCHPAD_EVENT_REPORT;
490                 break;
491         case EV_ABS:
492                 process_absolute(touchpad, device, e);
493                 break;
494         case EV_KEY:
495                 process_key(touchpad, device, e, time);
496                 break;
497         }
498
499         touchpad_update_state(touchpad, time);
500 }
501
502 static void
503 touchpad_destroy(struct evdev_dispatch *dispatch)
504 {
505         struct touchpad_dispatch *touchpad =
506                 (struct touchpad_dispatch *) dispatch;
507         struct weston_motion_filter *filter;
508         struct weston_motion_filter *next;
509
510         wl_list_for_each_safe(filter, next, &touchpad->motion_filters, link)
511                 filter->interface->destroy(filter);
512
513         free(dispatch);
514 }
515
516 struct evdev_dispatch_interface touchpad_interface = {
517         touchpad_process,
518         touchpad_destroy
519 };
520
521 struct evdev_dispatch *
522 evdev_touchpad_create(struct evdev_input_device *device)
523 {
524         struct touchpad_dispatch *touchpad;
525
526         touchpad = malloc(sizeof *touchpad);
527         if (touchpad == NULL)
528                 return NULL;
529
530         touchpad->base.interface = &touchpad_interface;
531
532         touchpad->device = device;
533         wl_list_init(&touchpad->motion_filters);
534
535         configure_touchpad(touchpad, device);
536
537         return &touchpad->base;
538 }