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