1 /*
2 * Copyright © 2014 Red Hat, Inc.
3 * Copyright © 2014 Lyude Paul
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24 #include "config.h"
25 #include "evdev-tablet.h"
26
27 #include <assert.h>
28 #include <stdbool.h>
29 #include <string.h>
30
31 #if HAVE_LIBWACOM
32 #include <libwacom/libwacom.h>
33 #endif
34
35 enum notify {
36 DONT_NOTIFY,
37 DO_NOTIFY,
38 };
39
40 /* The tablet sends events every ~2ms , 50ms should be plenty enough to
41 detect out-of-range.
42 This value is higher during test suite runs */
43 static int FORCED_PROXOUT_TIMEOUT = 50 * 1000; /* µs */
44
45 #define tablet_set_status(tablet_,s_) (tablet_)->status |= (s_)
46 #define tablet_unset_status(tablet_,s_) (tablet_)->status &= ~(s_)
47 #define tablet_has_status(tablet_,s_) (!!((tablet_)->status & (s_)))
48
49 static inline void
tablet_get_pressed_buttons(struct tablet_dispatch * tablet,struct button_state * buttons)50 tablet_get_pressed_buttons(struct tablet_dispatch *tablet,
51 struct button_state *buttons)
52 {
53 size_t i;
54 const struct button_state *state = &tablet->button_state,
55 *prev_state = &tablet->prev_button_state;
56
57 for (i = 0; i < sizeof(buttons->bits); i++)
58 buttons->bits[i] = state->bits[i] & ~(prev_state->bits[i]);
59 }
60
61 static inline void
tablet_get_released_buttons(struct tablet_dispatch * tablet,struct button_state * buttons)62 tablet_get_released_buttons(struct tablet_dispatch *tablet,
63 struct button_state *buttons)
64 {
65 size_t i;
66 const struct button_state *state = &tablet->button_state,
67 *prev_state = &tablet->prev_button_state;
68
69 for (i = 0; i < sizeof(buttons->bits); i++)
70 buttons->bits[i] = prev_state->bits[i] &
71 ~(state->bits[i]);
72 }
73
74 /* Merge the previous state with the current one so all buttons look like
75 * they just got pressed in this frame */
76 static inline void
tablet_force_button_presses(struct tablet_dispatch * tablet)77 tablet_force_button_presses(struct tablet_dispatch *tablet)
78 {
79 struct button_state *state = &tablet->button_state,
80 *prev_state = &tablet->prev_button_state;
81 size_t i;
82
83 for (i = 0; i < sizeof(state->bits); i++) {
84 state->bits[i] = state->bits[i] | prev_state->bits[i];
85 prev_state->bits[i] = 0;
86 }
87 }
88
89 static inline size_t
tablet_history_size(const struct tablet_dispatch * tablet)90 tablet_history_size(const struct tablet_dispatch *tablet)
91 {
92 return ARRAY_LENGTH(tablet->history.samples);
93 }
94
95 static inline void
tablet_history_reset(struct tablet_dispatch * tablet)96 tablet_history_reset(struct tablet_dispatch *tablet)
97 {
98 tablet->history.count = 0;
99 }
100
101 static inline void
tablet_history_push(struct tablet_dispatch * tablet,const struct tablet_axes * axes)102 tablet_history_push(struct tablet_dispatch *tablet,
103 const struct tablet_axes *axes)
104 {
105 unsigned int index = (tablet->history.index + 1) %
106 tablet_history_size(tablet);
107
108 tablet->history.samples[index] = *axes;
109 tablet->history.index = index;
110 tablet->history.count = min(tablet->history.count + 1,
111 tablet_history_size(tablet));
112
113 if (tablet->history.count < tablet_history_size(tablet))
114 tablet_history_push(tablet, axes);
115 }
116
117 /**
118 * Return a previous axis state, where index of 0 means "most recent", 1 is
119 * "one before most recent", etc.
120 */
121 static inline const struct tablet_axes*
tablet_history_get(const struct tablet_dispatch * tablet,unsigned int index)122 tablet_history_get(const struct tablet_dispatch *tablet, unsigned int index)
123 {
124 size_t sz = tablet_history_size(tablet);
125
126 assert(index < sz);
127 assert(index < tablet->history.count);
128
129 index = (tablet->history.index + sz - index) % sz;
130 return &tablet->history.samples[index];
131 }
132
133 static inline void
tablet_reset_changed_axes(struct tablet_dispatch * tablet)134 tablet_reset_changed_axes(struct tablet_dispatch *tablet)
135 {
136 memset(tablet->changed_axes, 0, sizeof(tablet->changed_axes));
137 }
138
139 static bool
tablet_device_has_axis(struct tablet_dispatch * tablet,enum libinput_tablet_tool_axis axis)140 tablet_device_has_axis(struct tablet_dispatch *tablet,
141 enum libinput_tablet_tool_axis axis)
142 {
143 struct libevdev *evdev = tablet->device->evdev;
144 bool has_axis = false;
145 unsigned int code;
146
147 if (axis == LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z) {
148 has_axis = (libevdev_has_event_code(evdev,
149 EV_KEY,
150 BTN_TOOL_MOUSE) &&
151 libevdev_has_event_code(evdev,
152 EV_ABS,
153 ABS_TILT_X) &&
154 libevdev_has_event_code(evdev,
155 EV_ABS,
156 ABS_TILT_Y));
157 code = axis_to_evcode(axis);
158 has_axis |= libevdev_has_event_code(evdev,
159 EV_ABS,
160 code);
161 } else if (axis == LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL) {
162 has_axis = libevdev_has_event_code(evdev,
163 EV_REL,
164 REL_WHEEL);
165 } else {
166 code = axis_to_evcode(axis);
167 has_axis = libevdev_has_event_code(evdev,
168 EV_ABS,
169 code);
170 }
171
172 return has_axis;
173 }
174
175 static inline bool
tablet_filter_axis_fuzz(const struct tablet_dispatch * tablet,const struct evdev_device * device,const struct input_event * e,enum libinput_tablet_tool_axis axis)176 tablet_filter_axis_fuzz(const struct tablet_dispatch *tablet,
177 const struct evdev_device *device,
178 const struct input_event *e,
179 enum libinput_tablet_tool_axis axis)
180 {
181 int delta, fuzz;
182 int current, previous;
183
184 previous = tablet->prev_value[axis];
185 current = e->value;
186 delta = previous - current;
187
188 fuzz = libevdev_get_abs_fuzz(device->evdev, e->code);
189
190 /* ABS_DISTANCE doesn't have have fuzz set and causes continuous
191 * updates for the cursor/lens tools. Add a minimum fuzz of 2, same
192 * as the xf86-input-wacom driver
193 */
194 switch (e->code) {
195 case ABS_DISTANCE:
196 fuzz = max(2, fuzz);
197 break;
198 default:
199 break;
200 }
201
202 return abs(delta) <= fuzz;
203 }
204
205 static void
tablet_process_absolute(struct tablet_dispatch * tablet,struct evdev_device * device,struct input_event * e,uint64_t time)206 tablet_process_absolute(struct tablet_dispatch *tablet,
207 struct evdev_device *device,
208 struct input_event *e,
209 uint64_t time)
210 {
211 enum libinput_tablet_tool_axis axis;
212
213 switch (e->code) {
214 case ABS_X:
215 case ABS_Y:
216 case ABS_Z:
217 case ABS_PRESSURE:
218 case ABS_TILT_X:
219 case ABS_TILT_Y:
220 case ABS_DISTANCE:
221 case ABS_WHEEL:
222 axis = evcode_to_axis(e->code);
223 if (axis == LIBINPUT_TABLET_TOOL_AXIS_NONE) {
224 evdev_log_bug_libinput(device,
225 "Invalid ABS event code %#x\n",
226 e->code);
227 break;
228 }
229
230 tablet->prev_value[axis] = tablet->current_value[axis];
231 if (tablet_filter_axis_fuzz(tablet, device, e, axis))
232 break;
233
234 tablet->current_value[axis] = e->value;
235 set_bit(tablet->changed_axes, axis);
236 tablet_set_status(tablet, TABLET_AXES_UPDATED);
237 break;
238 /* tool_id is the identifier for the tool we can use in libwacom
239 * to identify it (if we have one anyway) */
240 case ABS_MISC:
241 tablet->current_tool.id = e->value;
242 break;
243 /* Intuos 3 strip data. Should only happen on the Pad device, not on
244 the Pen device. */
245 case ABS_RX:
246 case ABS_RY:
247 /* Only on the 4D mouse (Intuos2), obsolete */
248 case ABS_RZ:
249 /* Only on the 4D mouse (Intuos2), obsolete.
250 The 24HD sends ABS_THROTTLE on the Pad device for the second
251 wheel but we shouldn't get here on kernel >= 3.17.
252 */
253 case ABS_THROTTLE:
254 default:
255 evdev_log_info(device,
256 "Unhandled ABS event code %#x\n",
257 e->code);
258 break;
259 }
260 }
261
262 static void
tablet_apply_rotation(struct evdev_device * device)263 tablet_apply_rotation(struct evdev_device *device)
264 {
265 struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch);
266
267 if (tablet->rotation.rotate == tablet->rotation.want_rotate)
268 return;
269
270 if (!tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))
271 return;
272
273 tablet->rotation.rotate = tablet->rotation.want_rotate;
274
275 evdev_log_debug(device,
276 "tablet-rotation: rotation is %s\n",
277 tablet->rotation.rotate ? "on" : "off");
278 }
279
280 static void
tablet_change_rotation(struct evdev_device * device,enum notify notify)281 tablet_change_rotation(struct evdev_device *device, enum notify notify)
282 {
283 struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch);
284 struct evdev_device *touch_device = tablet->touch_device;
285 struct evdev_dispatch *dispatch;
286 bool tablet_is_left, touchpad_is_left;
287
288 tablet_is_left = tablet->device->left_handed.enabled;
289 touchpad_is_left = tablet->rotation.touch_device_left_handed_state;
290
291 tablet->rotation.want_rotate = tablet_is_left || touchpad_is_left;
292 tablet_apply_rotation(device);
293
294 if (notify == DO_NOTIFY && touch_device) {
295 bool enable = device->left_handed.want_enabled;
296
297 dispatch = touch_device->dispatch;
298 if (dispatch->interface->left_handed_toggle)
299 dispatch->interface->left_handed_toggle(dispatch,
300 touch_device,
301 enable);
302 }
303 }
304
305 static void
tablet_change_to_left_handed(struct evdev_device * device)306 tablet_change_to_left_handed(struct evdev_device *device)
307 {
308 if (device->left_handed.enabled == device->left_handed.want_enabled)
309 return;
310
311 device->left_handed.enabled = device->left_handed.want_enabled;
312
313 tablet_change_rotation(device, DO_NOTIFY);
314 }
315
316 static void
tablet_update_tool(struct tablet_dispatch * tablet,struct evdev_device * device,enum libinput_tablet_tool_type tool,bool enabled)317 tablet_update_tool(struct tablet_dispatch *tablet,
318 struct evdev_device *device,
319 enum libinput_tablet_tool_type tool,
320 bool enabled)
321 {
322 assert(tool != LIBINPUT_TOOL_NONE);
323
324 if (enabled) {
325 tablet->current_tool.type = tool;
326 tablet_set_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY);
327 tablet_unset_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
328 }
329 else if (!tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY)) {
330 tablet_set_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
331 }
332 }
333
334 static inline double
normalize_slider(const struct input_absinfo * absinfo)335 normalize_slider(const struct input_absinfo *absinfo)
336 {
337 double range = absinfo->maximum - absinfo->minimum;
338 double value = (absinfo->value - absinfo->minimum) / range;
339
340 return value * 2 - 1;
341 }
342
343 static inline double
normalize_distance(const struct input_absinfo * absinfo)344 normalize_distance(const struct input_absinfo *absinfo)
345 {
346 double range = absinfo->maximum - absinfo->minimum;
347 double value = (absinfo->value - absinfo->minimum) / range;
348
349 return value;
350 }
351
352 static inline double
normalize_pressure(const struct input_absinfo * absinfo,struct libinput_tablet_tool * tool)353 normalize_pressure(const struct input_absinfo *absinfo,
354 struct libinput_tablet_tool *tool)
355 {
356 int offset;
357 double range;
358 double value;
359
360 /**
361 * If the tool has a pressure offset, we use that as the lower bound
362 * for the scaling range. If not, we use the upper threshold as the
363 * lower bound, so once we get past that minimum physical pressure
364 * we have logical 0 pressure.
365 *
366 * This means that there is a small range (lower-upper) where
367 * different physical pressure (default: 1-5%) result in the same
368 * logical pressure. This is, hopefully, not noticable.
369 *
370 * Note that that lower-upper range gives us a negative pressure, so
371 * we have to clip to 0 for those.
372 */
373
374 if (tool->has_pressure_offset)
375 offset = tool->pressure_offset;
376 else
377 offset = tool->pressure_threshold.upper;
378 range = absinfo->maximum - offset;
379 value = (absinfo->value - offset) / range;
380
381 return max(0.0, value);
382 }
383
384 static inline double
adjust_tilt(const struct input_absinfo * absinfo)385 adjust_tilt(const struct input_absinfo *absinfo)
386 {
387 double range = absinfo->maximum - absinfo->minimum;
388 double value = (absinfo->value - absinfo->minimum) / range;
389 const int WACOM_MAX_DEGREES = 64;
390
391 /* If resolution is nonzero, it's in units/radian. But require
392 * a min/max less/greater than zero so we can assume 0 is the
393 * center */
394 if (absinfo->resolution != 0 &&
395 absinfo->maximum > 0 &&
396 absinfo->minimum < 0) {
397 value = 180.0/M_PI * absinfo->value/absinfo->resolution;
398 } else {
399 /* Wacom supports physical [-64, 64] degrees, so map to that by
400 * default. If other tablets have a different physical range or
401 * nonzero physical offsets, they need extra treatment
402 * here.
403 */
404 /* Map to the (-1, 1) range */
405 value = (value * 2) - 1;
406 value *= WACOM_MAX_DEGREES;
407 }
408
409 return value;
410 }
411
412 static inline int32_t
invert_axis(const struct input_absinfo * absinfo)413 invert_axis(const struct input_absinfo *absinfo)
414 {
415 return absinfo->maximum - (absinfo->value - absinfo->minimum);
416 }
417
418 static void
convert_tilt_to_rotation(struct tablet_dispatch * tablet)419 convert_tilt_to_rotation(struct tablet_dispatch *tablet)
420 {
421 const int offset = 5;
422 double x, y;
423 double angle = 0.0;
424
425 /* Wacom Intuos 4, 5, Pro mouse calculates rotation from the x/y tilt
426 values. The device has a 175 degree CCW hardware offset but since we use
427 atan2 the effective offset is just 5 degrees.
428 */
429 x = tablet->axes.tilt.x;
430 y = tablet->axes.tilt.y;
431
432 /* atan2 is CCW, we want CW -> negate x */
433 if (x || y)
434 angle = ((180.0 * atan2(-x, y)) / M_PI);
435
436 angle = fmod(360 + angle - offset, 360);
437
438 tablet->axes.rotation = angle;
439 set_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z);
440 }
441
442 static double
convert_to_degrees(const struct input_absinfo * absinfo,double offset)443 convert_to_degrees(const struct input_absinfo *absinfo, double offset)
444 {
445 /* range is [0, 360[, i.e. range + 1 */
446 double range = absinfo->maximum - absinfo->minimum + 1;
447 double value = (absinfo->value - absinfo->minimum) / range;
448
449 return fmod(value * 360.0 + offset, 360.0);
450 }
451
452 static inline double
normalize_wheel(struct tablet_dispatch * tablet,int value)453 normalize_wheel(struct tablet_dispatch *tablet,
454 int value)
455 {
456 struct evdev_device *device = tablet->device;
457
458 return value * device->scroll.wheel_click_angle.x;
459 }
460
461 static inline void
tablet_update_xy(struct tablet_dispatch * tablet,struct evdev_device * device)462 tablet_update_xy(struct tablet_dispatch *tablet,
463 struct evdev_device *device)
464 {
465 const struct input_absinfo *absinfo;
466 int value;
467
468 if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X) ||
469 bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y)) {
470 absinfo = libevdev_get_abs_info(device->evdev, ABS_X);
471
472 if (tablet->rotation.rotate)
473 value = invert_axis(absinfo);
474 else
475 value = absinfo->value;
476
477 tablet->axes.point.x = value;
478
479 absinfo = libevdev_get_abs_info(device->evdev, ABS_Y);
480
481 if (tablet->rotation.rotate)
482 value = invert_axis(absinfo);
483 else
484 value = absinfo->value;
485
486 tablet->axes.point.y = value;
487
488 evdev_transform_absolute(device, &tablet->axes.point);
489 }
490 }
491
492 static inline struct normalized_coords
tablet_tool_process_delta(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool,const struct evdev_device * device,struct tablet_axes * axes,uint64_t time)493 tablet_tool_process_delta(struct tablet_dispatch *tablet,
494 struct libinput_tablet_tool *tool,
495 const struct evdev_device *device,
496 struct tablet_axes *axes,
497 uint64_t time)
498 {
499 const struct normalized_coords zero = { 0.0, 0.0 };
500 struct device_coords delta = { 0, 0 };
501 struct device_float_coords accel;
502
503 /* When tool contact changes, we probably got a cursor jump. Don't
504 try to calculate a delta for that event */
505 if (!tablet_has_status(tablet,
506 TABLET_TOOL_ENTERING_PROXIMITY) &&
507 !tablet_has_status(tablet, TABLET_TOOL_ENTERING_CONTACT) &&
508 !tablet_has_status(tablet, TABLET_TOOL_LEAVING_CONTACT) &&
509 (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X) ||
510 bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y))) {
511 delta.x = axes->point.x - tablet->last_smooth_point.x;
512 delta.y = axes->point.y - tablet->last_smooth_point.y;
513 }
514
515 if (axes->point.x != tablet->last_smooth_point.x)
516 set_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X);
517 if (axes->point.y != tablet->last_smooth_point.y)
518 set_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y);
519
520 tablet->last_smooth_point = axes->point;
521
522 accel.x = 1.0 * delta.x;
523 accel.y = 1.0 * delta.y;
524
525 if (device_float_is_zero(accel))
526 return zero;
527
528 return filter_dispatch(device->pointer.filter,
529 &accel,
530 tool,
531 time);
532 }
533
534 static inline void
tablet_update_pressure(struct tablet_dispatch * tablet,struct evdev_device * device,struct libinput_tablet_tool * tool)535 tablet_update_pressure(struct tablet_dispatch *tablet,
536 struct evdev_device *device,
537 struct libinput_tablet_tool *tool)
538 {
539 const struct input_absinfo *absinfo;
540
541 if (bit_is_set(tablet->changed_axes,
542 LIBINPUT_TABLET_TOOL_AXIS_PRESSURE)) {
543 absinfo = libevdev_get_abs_info(device->evdev, ABS_PRESSURE);
544 tablet->axes.pressure = normalize_pressure(absinfo, tool);
545 }
546 }
547
548 static inline void
tablet_update_distance(struct tablet_dispatch * tablet,struct evdev_device * device)549 tablet_update_distance(struct tablet_dispatch *tablet,
550 struct evdev_device *device)
551 {
552 const struct input_absinfo *absinfo;
553
554 if (bit_is_set(tablet->changed_axes,
555 LIBINPUT_TABLET_TOOL_AXIS_DISTANCE)) {
556 absinfo = libevdev_get_abs_info(device->evdev, ABS_DISTANCE);
557 tablet->axes.distance = normalize_distance(absinfo);
558 }
559 }
560
561 static inline void
tablet_update_slider(struct tablet_dispatch * tablet,struct evdev_device * device)562 tablet_update_slider(struct tablet_dispatch *tablet,
563 struct evdev_device *device)
564 {
565 const struct input_absinfo *absinfo;
566
567 if (bit_is_set(tablet->changed_axes,
568 LIBINPUT_TABLET_TOOL_AXIS_SLIDER)) {
569 absinfo = libevdev_get_abs_info(device->evdev, ABS_WHEEL);
570 tablet->axes.slider = normalize_slider(absinfo);
571 }
572 }
573
574 static inline void
tablet_update_tilt(struct tablet_dispatch * tablet,struct evdev_device * device)575 tablet_update_tilt(struct tablet_dispatch *tablet,
576 struct evdev_device *device)
577 {
578 const struct input_absinfo *absinfo;
579
580 /* mouse rotation resets tilt to 0 so always fetch both axes if
581 * either has changed */
582 if (bit_is_set(tablet->changed_axes,
583 LIBINPUT_TABLET_TOOL_AXIS_TILT_X) ||
584 bit_is_set(tablet->changed_axes,
585 LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) {
586
587 absinfo = libevdev_get_abs_info(device->evdev, ABS_TILT_X);
588 tablet->axes.tilt.x = adjust_tilt(absinfo);
589
590 absinfo = libevdev_get_abs_info(device->evdev, ABS_TILT_Y);
591 tablet->axes.tilt.y = adjust_tilt(absinfo);
592
593 if (device->left_handed.enabled) {
594 tablet->axes.tilt.x *= -1;
595 tablet->axes.tilt.y *= -1;
596 }
597 }
598 }
599
600 static inline void
tablet_update_artpen_rotation(struct tablet_dispatch * tablet,struct evdev_device * device)601 tablet_update_artpen_rotation(struct tablet_dispatch *tablet,
602 struct evdev_device *device)
603 {
604 const struct input_absinfo *absinfo;
605
606 if (bit_is_set(tablet->changed_axes,
607 LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z)) {
608 absinfo = libevdev_get_abs_info(device->evdev,
609 ABS_Z);
610 /* artpen has 0 with buttons pointing east */
611 tablet->axes.rotation = convert_to_degrees(absinfo, 90);
612 }
613 }
614
615 static inline void
tablet_update_mouse_rotation(struct tablet_dispatch * tablet,struct evdev_device * device)616 tablet_update_mouse_rotation(struct tablet_dispatch *tablet,
617 struct evdev_device *device)
618 {
619 if (bit_is_set(tablet->changed_axes,
620 LIBINPUT_TABLET_TOOL_AXIS_TILT_X) ||
621 bit_is_set(tablet->changed_axes,
622 LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) {
623 convert_tilt_to_rotation(tablet);
624 }
625 }
626
627 static inline void
tablet_update_rotation(struct tablet_dispatch * tablet,struct evdev_device * device)628 tablet_update_rotation(struct tablet_dispatch *tablet,
629 struct evdev_device *device)
630 {
631 /* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are
632 * already normalized and set if we have the mouse/lens tool */
633 if (tablet->current_tool.type == LIBINPUT_TABLET_TOOL_TYPE_MOUSE ||
634 tablet->current_tool.type == LIBINPUT_TABLET_TOOL_TYPE_LENS) {
635 tablet_update_mouse_rotation(tablet, device);
636 clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_X);
637 clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y);
638 tablet->axes.tilt.x = 0;
639 tablet->axes.tilt.y = 0;
640
641 /* tilt is already converted to left-handed, so mouse
642 * rotation is converted to left-handed automatically */
643 } else {
644
645 tablet_update_artpen_rotation(tablet, device);
646
647 if (device->left_handed.enabled) {
648 double r = tablet->axes.rotation;
649 tablet->axes.rotation = fmod(180 + r, 360);
650 }
651 }
652 }
653
654 static inline void
tablet_update_wheel(struct tablet_dispatch * tablet,struct evdev_device * device)655 tablet_update_wheel(struct tablet_dispatch *tablet,
656 struct evdev_device *device)
657 {
658 int a;
659
660 a = LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL;
661 if (bit_is_set(tablet->changed_axes, a)) {
662 /* tablet->axes.wheel_discrete is already set */
663 tablet->axes.wheel = normalize_wheel(tablet,
664 tablet->axes.wheel_discrete);
665 } else {
666 tablet->axes.wheel = 0;
667 tablet->axes.wheel_discrete = 0;
668 }
669 }
670
671 static void
tablet_smoothen_axes(const struct tablet_dispatch * tablet,struct tablet_axes * axes)672 tablet_smoothen_axes(const struct tablet_dispatch *tablet,
673 struct tablet_axes *axes)
674 {
675 size_t i;
676 size_t count = tablet_history_size(tablet);
677 struct tablet_axes smooth = { 0 };
678
679 for (i = 0; i < count; i++) {
680 const struct tablet_axes *a = tablet_history_get(tablet, i);
681
682 smooth.point.x += a->point.x;
683 smooth.point.y += a->point.y;
684
685 smooth.tilt.x += a->tilt.x;
686 smooth.tilt.y += a->tilt.y;
687 }
688
689 axes->point.x = smooth.point.x/count;
690 axes->point.y = smooth.point.y/count;
691
692 axes->tilt.x = smooth.tilt.x/count;
693 axes->tilt.y = smooth.tilt.y/count;
694 }
695
696 static bool
tablet_check_notify_axes(struct tablet_dispatch * tablet,struct evdev_device * device,struct libinput_tablet_tool * tool,struct tablet_axes * axes_out,uint64_t time)697 tablet_check_notify_axes(struct tablet_dispatch *tablet,
698 struct evdev_device *device,
699 struct libinput_tablet_tool *tool,
700 struct tablet_axes *axes_out,
701 uint64_t time)
702 {
703 struct tablet_axes axes = {0};
704 const char tmp[sizeof(tablet->changed_axes)] = {0};
705 bool rc = false;
706
707 if (memcmp(tmp, tablet->changed_axes, sizeof(tmp)) == 0) {
708 axes = tablet->axes;
709 goto out;
710 }
711
712 tablet_update_xy(tablet, device);
713 tablet_update_pressure(tablet, device, tool);
714 tablet_update_distance(tablet, device);
715 tablet_update_slider(tablet, device);
716 tablet_update_tilt(tablet, device);
717 tablet_update_wheel(tablet, device);
718 /* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are
719 * already normalized and set if we have the mouse/lens tool */
720 tablet_update_rotation(tablet, device);
721
722 axes.point = tablet->axes.point;
723 axes.pressure = tablet->axes.pressure;
724 axes.distance = tablet->axes.distance;
725 axes.slider = tablet->axes.slider;
726 axes.tilt = tablet->axes.tilt;
727 axes.wheel = tablet->axes.wheel;
728 axes.wheel_discrete = tablet->axes.wheel_discrete;
729 axes.rotation = tablet->axes.rotation;
730
731 rc = true;
732
733 out:
734 /* The tool position often jumps to a different spot when contact changes.
735 * If tool contact changes, clear the history to prevent axis smoothing
736 * from trying to average over the spatial discontinuity. */
737 if (tablet_has_status(tablet, TABLET_TOOL_ENTERING_CONTACT) ||
738 tablet_has_status(tablet, TABLET_TOOL_LEAVING_CONTACT)) {
739 tablet_history_reset(tablet);
740 }
741
742 tablet_history_push(tablet, &tablet->axes);
743 tablet_smoothen_axes(tablet, &axes);
744
745 /* The delta relies on the last *smooth* point, so we do it last */
746 axes.delta = tablet_tool_process_delta(tablet, tool, device, &axes, time);
747
748 *axes_out = axes;
749
750 return rc;
751 }
752
753 static void
tablet_update_button(struct tablet_dispatch * tablet,uint32_t evcode,uint32_t enable)754 tablet_update_button(struct tablet_dispatch *tablet,
755 uint32_t evcode,
756 uint32_t enable)
757 {
758 switch (evcode) {
759 case BTN_LEFT:
760 case BTN_RIGHT:
761 case BTN_MIDDLE:
762 case BTN_SIDE:
763 case BTN_EXTRA:
764 case BTN_FORWARD:
765 case BTN_BACK:
766 case BTN_TASK:
767 case BTN_STYLUS:
768 case BTN_STYLUS2:
769 break;
770 default:
771 evdev_log_info(tablet->device,
772 "Unhandled button %s (%#x)\n",
773 libevdev_event_code_get_name(EV_KEY, evcode),
774 evcode);
775 return;
776 }
777
778 if (enable) {
779 set_bit(tablet->button_state.bits, evcode);
780 tablet_set_status(tablet, TABLET_BUTTONS_PRESSED);
781 } else {
782 clear_bit(tablet->button_state.bits, evcode);
783 tablet_set_status(tablet, TABLET_BUTTONS_RELEASED);
784 }
785 }
786
787 static inline enum libinput_tablet_tool_type
tablet_evcode_to_tool(int code)788 tablet_evcode_to_tool(int code)
789 {
790 enum libinput_tablet_tool_type type;
791
792 switch (code) {
793 case BTN_TOOL_PEN: type = LIBINPUT_TABLET_TOOL_TYPE_PEN; break;
794 case BTN_TOOL_RUBBER: type = LIBINPUT_TABLET_TOOL_TYPE_ERASER; break;
795 case BTN_TOOL_BRUSH: type = LIBINPUT_TABLET_TOOL_TYPE_BRUSH; break;
796 case BTN_TOOL_PENCIL: type = LIBINPUT_TABLET_TOOL_TYPE_PENCIL; break;
797 case BTN_TOOL_AIRBRUSH: type = LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH; break;
798 case BTN_TOOL_MOUSE: type = LIBINPUT_TABLET_TOOL_TYPE_MOUSE; break;
799 case BTN_TOOL_LENS: type = LIBINPUT_TABLET_TOOL_TYPE_LENS; break;
800 default:
801 abort();
802 }
803
804 return type;
805 }
806
807 static void
tablet_process_key(struct tablet_dispatch * tablet,struct evdev_device * device,struct input_event * e,uint64_t time)808 tablet_process_key(struct tablet_dispatch *tablet,
809 struct evdev_device *device,
810 struct input_event *e,
811 uint64_t time)
812 {
813 enum libinput_tablet_tool_type type;
814
815 /* ignore kernel key repeat */
816 if (e->value == 2)
817 return;
818
819 switch (e->code) {
820 case BTN_TOOL_FINGER:
821 evdev_log_bug_libinput(device,
822 "Invalid tool 'finger' on tablet interface\n");
823 break;
824 case BTN_TOOL_PEN:
825 case BTN_TOOL_RUBBER:
826 case BTN_TOOL_BRUSH:
827 case BTN_TOOL_PENCIL:
828 case BTN_TOOL_AIRBRUSH:
829 case BTN_TOOL_MOUSE:
830 case BTN_TOOL_LENS:
831 type = tablet_evcode_to_tool(e->code);
832 tablet_set_status(tablet, TABLET_TOOL_UPDATED);
833 if (e->value)
834 tablet->tool_state |= bit(type);
835 else
836 tablet->tool_state &= ~bit(type);
837 break;
838 case BTN_TOUCH:
839 if (!bit_is_set(tablet->axis_caps,
840 LIBINPUT_TABLET_TOOL_AXIS_PRESSURE)) {
841 if (e->value)
842 tablet_set_status(tablet,
843 TABLET_TOOL_ENTERING_CONTACT);
844 else
845 tablet_set_status(tablet,
846 TABLET_TOOL_LEAVING_CONTACT);
847 }
848 break;
849 default:
850 tablet_update_button(tablet, e->code, e->value);
851 break;
852 }
853 }
854
855 static void
tablet_process_relative(struct tablet_dispatch * tablet,struct evdev_device * device,struct input_event * e,uint64_t time)856 tablet_process_relative(struct tablet_dispatch *tablet,
857 struct evdev_device *device,
858 struct input_event *e,
859 uint64_t time)
860 {
861 enum libinput_tablet_tool_axis axis;
862
863 switch (e->code) {
864 case REL_WHEEL:
865 axis = rel_evcode_to_axis(e->code);
866 if (axis == LIBINPUT_TABLET_TOOL_AXIS_NONE) {
867 evdev_log_bug_libinput(device,
868 "Invalid ABS event code %#x\n",
869 e->code);
870 break;
871 }
872 set_bit(tablet->changed_axes, axis);
873 tablet->axes.wheel_discrete = -1 * e->value;
874 tablet_set_status(tablet, TABLET_AXES_UPDATED);
875 break;
876 default:
877 evdev_log_info(device,
878 "Unhandled relative axis %s (%#x)\n",
879 libevdev_event_code_get_name(EV_REL, e->code),
880 e->code);
881 return;
882 }
883 }
884
885 static void
tablet_process_misc(struct tablet_dispatch * tablet,struct evdev_device * device,struct input_event * e,uint64_t time)886 tablet_process_misc(struct tablet_dispatch *tablet,
887 struct evdev_device *device,
888 struct input_event *e,
889 uint64_t time)
890 {
891 switch (e->code) {
892 case MSC_SERIAL:
893 if (e->value != -1)
894 tablet->current_tool.serial = e->value;
895
896 break;
897 case MSC_SCAN:
898 break;
899 default:
900 evdev_log_info(device,
901 "Unhandled MSC event code %s (%#x)\n",
902 libevdev_event_code_get_name(EV_MSC, e->code),
903 e->code);
904 break;
905 }
906 }
907
908 static inline void
copy_axis_cap(const struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool,enum libinput_tablet_tool_axis axis)909 copy_axis_cap(const struct tablet_dispatch *tablet,
910 struct libinput_tablet_tool *tool,
911 enum libinput_tablet_tool_axis axis)
912 {
913 if (bit_is_set(tablet->axis_caps, axis))
914 set_bit(tool->axis_caps, axis);
915 }
916
917 static inline void
copy_button_cap(const struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool,uint32_t button)918 copy_button_cap(const struct tablet_dispatch *tablet,
919 struct libinput_tablet_tool *tool,
920 uint32_t button)
921 {
922 struct libevdev *evdev = tablet->device->evdev;
923 if (libevdev_has_event_code(evdev, EV_KEY, button))
924 set_bit(tool->buttons, button);
925 }
926
927 static inline int
tool_set_bits_from_libwacom(const struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool)928 tool_set_bits_from_libwacom(const struct tablet_dispatch *tablet,
929 struct libinput_tablet_tool *tool)
930 {
931 int rc = 1;
932
933 #if HAVE_LIBWACOM
934 WacomDeviceDatabase *db;
935 const WacomStylus *s = NULL;
936 int code;
937 WacomStylusType type;
938 WacomAxisTypeFlags axes;
939
940 db = tablet_libinput_context(tablet)->libwacom.db;
941 if (!db)
942 return rc;
943
944 s = libwacom_stylus_get_for_id(db, tool->tool_id);
945 if (!s)
946 return rc;
947
948 type = libwacom_stylus_get_type(s);
949 if (type == WSTYLUS_PUCK) {
950 for (code = BTN_LEFT;
951 code < BTN_LEFT + libwacom_stylus_get_num_buttons(s);
952 code++)
953 copy_button_cap(tablet, tool, code);
954 } else {
955 if (libwacom_stylus_get_num_buttons(s) >= 2)
956 copy_button_cap(tablet, tool, BTN_STYLUS2);
957 if (libwacom_stylus_get_num_buttons(s) >= 1)
958 copy_button_cap(tablet, tool, BTN_STYLUS);
959 }
960
961 if (libwacom_stylus_has_wheel(s))
962 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL);
963
964 axes = libwacom_stylus_get_axes(s);
965
966 if (axes & WACOM_AXIS_TYPE_TILT) {
967 /* tilt on the puck is converted to rotation */
968 if (type == WSTYLUS_PUCK) {
969 set_bit(tool->axis_caps,
970 LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z);
971 } else {
972 copy_axis_cap(tablet,
973 tool,
974 LIBINPUT_TABLET_TOOL_AXIS_TILT_X);
975 copy_axis_cap(tablet,
976 tool,
977 LIBINPUT_TABLET_TOOL_AXIS_TILT_Y);
978 }
979 }
980 if (axes & WACOM_AXIS_TYPE_ROTATION_Z)
981 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z);
982 if (axes & WACOM_AXIS_TYPE_DISTANCE)
983 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_DISTANCE);
984 if (axes & WACOM_AXIS_TYPE_SLIDER)
985 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_SLIDER);
986 if (axes & WACOM_AXIS_TYPE_PRESSURE)
987 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
988
989 rc = 0;
990 #endif
991 return rc;
992 }
993
994 static void
tool_set_bits(const struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool)995 tool_set_bits(const struct tablet_dispatch *tablet,
996 struct libinput_tablet_tool *tool)
997 {
998 enum libinput_tablet_tool_type type = tool->type;
999
1000 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_X);
1001 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_Y);
1002
1003 #if HAVE_LIBWACOM
1004 if (tool_set_bits_from_libwacom(tablet, tool) == 0)
1005 return;
1006 #endif
1007 /* If we don't have libwacom, we simply copy any axis we have on the
1008 tablet onto the tool. Except we know that mice only have rotation
1009 anyway.
1010 */
1011 switch (type) {
1012 case LIBINPUT_TABLET_TOOL_TYPE_PEN:
1013 case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
1014 case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
1015 case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
1016 case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
1017 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
1018 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_DISTANCE);
1019 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_TILT_X);
1020 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y);
1021 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_SLIDER);
1022
1023 /* Rotation is special, it can be either ABS_Z or
1024 * BTN_TOOL_MOUSE+ABS_TILT_X/Y. Aiptek tablets have
1025 * mouse+tilt (and thus rotation), but they do not have
1026 * ABS_Z. So let's not copy the axis bit if we don't have
1027 * ABS_Z, otherwise we try to get the value from it later on
1028 * proximity in and go boom because the absinfo isn't there.
1029 */
1030 if (libevdev_has_event_code(tablet->device->evdev, EV_ABS,
1031 ABS_Z))
1032 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z);
1033 break;
1034 case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
1035 case LIBINPUT_TABLET_TOOL_TYPE_LENS:
1036 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z);
1037 copy_axis_cap(tablet, tool, LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL);
1038 break;
1039 default:
1040 break;
1041 }
1042
1043 /* If we don't have libwacom, copy all pen-related buttons from the
1044 tablet vs all mouse-related buttons */
1045 switch (type) {
1046 case LIBINPUT_TABLET_TOOL_TYPE_PEN:
1047 case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
1048 case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
1049 case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
1050 case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
1051 copy_button_cap(tablet, tool, BTN_STYLUS);
1052 copy_button_cap(tablet, tool, BTN_STYLUS2);
1053 break;
1054 case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
1055 case LIBINPUT_TABLET_TOOL_TYPE_LENS:
1056 copy_button_cap(tablet, tool, BTN_LEFT);
1057 copy_button_cap(tablet, tool, BTN_MIDDLE);
1058 copy_button_cap(tablet, tool, BTN_RIGHT);
1059 copy_button_cap(tablet, tool, BTN_SIDE);
1060 copy_button_cap(tablet, tool, BTN_EXTRA);
1061 break;
1062 default:
1063 break;
1064 }
1065 }
1066
1067 static inline int
axis_range_percentage(const struct input_absinfo * a,double percent)1068 axis_range_percentage(const struct input_absinfo *a, double percent)
1069 {
1070 return (a->maximum - a->minimum) * percent/100.0 + a->minimum;
1071 }
1072
1073 static inline void
tool_set_pressure_thresholds(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool)1074 tool_set_pressure_thresholds(struct tablet_dispatch *tablet,
1075 struct libinput_tablet_tool *tool)
1076 {
1077 struct evdev_device *device = tablet->device;
1078 const struct input_absinfo *pressure;
1079 struct quirks_context *quirks = NULL;
1080 struct quirks *q = NULL;
1081 struct quirk_range r;
1082 int lo = 0, hi = 1;
1083
1084 tool->pressure_offset = 0;
1085 tool->has_pressure_offset = false;
1086
1087 pressure = libevdev_get_abs_info(device->evdev, ABS_PRESSURE);
1088 if (!pressure)
1089 goto out;
1090
1091 quirks = evdev_libinput_context(device)->quirks;
1092 q = quirks_fetch_for_device(quirks, device->udev_device);
1093
1094 tool->pressure_offset = pressure->minimum;
1095
1096 /* 5 and 1% of the pressure range */
1097 hi = axis_range_percentage(pressure, 5);
1098 lo = axis_range_percentage(pressure, 1);
1099
1100 if (q && quirks_get_range(q, QUIRK_ATTR_PRESSURE_RANGE, &r)) {
1101 if (r.lower >= r.upper) {
1102 evdev_log_info(device,
1103 "Invalid pressure range, using defaults\n");
1104 } else {
1105 hi = r.upper;
1106 lo = r.lower;
1107 }
1108 }
1109 out:
1110 tool->pressure_threshold.upper = hi;
1111 tool->pressure_threshold.lower = lo;
1112
1113 quirks_unref(q);
1114 }
1115
1116 static struct libinput_tablet_tool *
tablet_get_tool(struct tablet_dispatch * tablet,enum libinput_tablet_tool_type type,uint32_t tool_id,uint32_t serial)1117 tablet_get_tool(struct tablet_dispatch *tablet,
1118 enum libinput_tablet_tool_type type,
1119 uint32_t tool_id,
1120 uint32_t serial)
1121 {
1122 struct libinput *libinput = tablet_libinput_context(tablet);
1123 struct libinput_tablet_tool *tool = NULL, *t;
1124 struct list *tool_list;
1125
1126 if (serial) {
1127 tool_list = &libinput->tool_list;
1128 /* Check if we already have the tool in our list of tools */
1129 list_for_each(t, tool_list, link) {
1130 if (type == t->type && serial == t->serial) {
1131 tool = t;
1132 break;
1133 }
1134 }
1135 }
1136
1137 /* If we get a tool with a delayed serial number, we already created
1138 * a 0-serial number tool for it earlier. Re-use that, even though
1139 * it means we can't distinguish this tool from others.
1140 * https://bugs.freedesktop.org/show_bug.cgi?id=97526
1141 */
1142 if (!tool) {
1143 tool_list = &tablet->tool_list;
1144 /* We can't guarantee that tools without serial numbers are
1145 * unique, so we keep them local to the tablet that they come
1146 * into proximity of instead of storing them in the global tool
1147 * list
1148 * Same as above, but don't bother checking the serial number
1149 */
1150 list_for_each(t, tool_list, link) {
1151 if (type == t->type) {
1152 tool = t;
1153 break;
1154 }
1155 }
1156
1157 /* Didn't find the tool but we have a serial. Switch
1158 * tool_list back so we create in the correct list */
1159 if (!tool && serial)
1160 tool_list = &libinput->tool_list;
1161 }
1162
1163 /* If we didn't already have the new_tool in our list of tools,
1164 * add it */
1165 if (!tool) {
1166 tool = zalloc(sizeof *tool);
1167
1168 *tool = (struct libinput_tablet_tool) {
1169 .type = type,
1170 .serial = serial,
1171 .tool_id = tool_id,
1172 .refcount = 1,
1173 };
1174
1175 tool_set_pressure_thresholds(tablet, tool);
1176 tool_set_bits(tablet, tool);
1177
1178 list_insert(tool_list, &tool->link);
1179 }
1180
1181 return tool;
1182 }
1183
1184 static void
tablet_notify_button_mask(struct tablet_dispatch * tablet,struct evdev_device * device,uint64_t time,struct libinput_tablet_tool * tool,const struct button_state * buttons,enum libinput_button_state state)1185 tablet_notify_button_mask(struct tablet_dispatch *tablet,
1186 struct evdev_device *device,
1187 uint64_t time,
1188 struct libinput_tablet_tool *tool,
1189 const struct button_state *buttons,
1190 enum libinput_button_state state)
1191 {
1192 struct libinput_device *base = &device->base;
1193 size_t i;
1194 size_t nbits = 8 * sizeof(buttons->bits);
1195 enum libinput_tablet_tool_tip_state tip_state;
1196
1197 tip_state = tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT) ?
1198 LIBINPUT_TABLET_TOOL_TIP_DOWN : LIBINPUT_TABLET_TOOL_TIP_UP;
1199
1200 for (i = 0; i < nbits; i++) {
1201 if (!bit_is_set(buttons->bits, i))
1202 continue;
1203
1204 tablet_notify_button(base,
1205 time,
1206 tool,
1207 tip_state,
1208 &tablet->axes,
1209 i,
1210 state);
1211 }
1212 }
1213
1214 static void
tablet_notify_buttons(struct tablet_dispatch * tablet,struct evdev_device * device,uint64_t time,struct libinput_tablet_tool * tool,enum libinput_button_state state)1215 tablet_notify_buttons(struct tablet_dispatch *tablet,
1216 struct evdev_device *device,
1217 uint64_t time,
1218 struct libinput_tablet_tool *tool,
1219 enum libinput_button_state state)
1220 {
1221 struct button_state buttons;
1222
1223 if (state == LIBINPUT_BUTTON_STATE_PRESSED)
1224 tablet_get_pressed_buttons(tablet, &buttons);
1225 else
1226 tablet_get_released_buttons(tablet, &buttons);
1227
1228 tablet_notify_button_mask(tablet,
1229 device,
1230 time,
1231 tool,
1232 &buttons,
1233 state);
1234 }
1235
1236 static void
sanitize_pressure_distance(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool)1237 sanitize_pressure_distance(struct tablet_dispatch *tablet,
1238 struct libinput_tablet_tool *tool)
1239 {
1240 bool tool_in_contact;
1241 const struct input_absinfo *distance,
1242 *pressure;
1243
1244 distance = libevdev_get_abs_info(tablet->device->evdev, ABS_DISTANCE);
1245 pressure = libevdev_get_abs_info(tablet->device->evdev, ABS_PRESSURE);
1246
1247 if (!pressure || !distance)
1248 return;
1249
1250 if (!bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_DISTANCE) &&
1251 !bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE))
1252 return;
1253
1254 tool_in_contact = (pressure->value > tool->pressure_offset);
1255
1256 /* Keep distance and pressure mutually exclusive */
1257 if (distance &&
1258 (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_DISTANCE) ||
1259 bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE)) &&
1260 distance->value > distance->minimum &&
1261 pressure->value > pressure->minimum) {
1262 if (tool_in_contact) {
1263 clear_bit(tablet->changed_axes,
1264 LIBINPUT_TABLET_TOOL_AXIS_DISTANCE);
1265 tablet->axes.distance = 0;
1266 } else {
1267 clear_bit(tablet->changed_axes,
1268 LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
1269 tablet->axes.pressure = 0;
1270 }
1271 } else if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE) &&
1272 !tool_in_contact) {
1273 /* Make sure that the last axis value sent to the caller is a 0 */
1274 if (tablet->axes.pressure == 0)
1275 clear_bit(tablet->changed_axes,
1276 LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
1277 else
1278 tablet->axes.pressure = 0;
1279 }
1280 }
1281
1282 static inline void
sanitize_mouse_lens_rotation(struct tablet_dispatch * tablet)1283 sanitize_mouse_lens_rotation(struct tablet_dispatch *tablet)
1284 {
1285 /* If we have a mouse/lens cursor and the tilt changed, the rotation
1286 changed. Mark this, calculate the angle later */
1287 if ((tablet->current_tool.type == LIBINPUT_TABLET_TOOL_TYPE_MOUSE ||
1288 tablet->current_tool.type == LIBINPUT_TABLET_TOOL_TYPE_LENS) &&
1289 (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_X) ||
1290 bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)))
1291 set_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z);
1292 }
1293
1294 static void
sanitize_tablet_axes(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool)1295 sanitize_tablet_axes(struct tablet_dispatch *tablet,
1296 struct libinput_tablet_tool *tool)
1297 {
1298 sanitize_pressure_distance(tablet, tool);
1299 sanitize_mouse_lens_rotation(tablet);
1300 }
1301
1302 static void
detect_pressure_offset(struct tablet_dispatch * tablet,struct evdev_device * device,struct libinput_tablet_tool * tool)1303 detect_pressure_offset(struct tablet_dispatch *tablet,
1304 struct evdev_device *device,
1305 struct libinput_tablet_tool *tool)
1306 {
1307 const struct input_absinfo *pressure, *distance;
1308 int offset;
1309
1310 if (!bit_is_set(tablet->changed_axes,
1311 LIBINPUT_TABLET_TOOL_AXIS_PRESSURE))
1312 return;
1313
1314 pressure = libevdev_get_abs_info(device->evdev, ABS_PRESSURE);
1315 distance = libevdev_get_abs_info(device->evdev, ABS_DISTANCE);
1316
1317 if (!pressure || !distance)
1318 return;
1319
1320 offset = pressure->value;
1321
1322 /* If we have an event that falls below the current offset, adjust
1323 * the offset downwards. A fast contact can start with a
1324 * higher-than-needed pressure offset and then we'd be tied into a
1325 * high pressure offset for the rest of the session.
1326 */
1327 if (tool->has_pressure_offset) {
1328 if (offset < tool->pressure_offset)
1329 tool->pressure_offset = offset;
1330 return;
1331 }
1332
1333 if (offset <= pressure->minimum)
1334 return;
1335
1336 /* we only set a pressure offset on proximity in */
1337 if (!tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY))
1338 return;
1339
1340 /* If we're closer than 50% of the distance axis, skip pressure
1341 * offset detection, too likely to be wrong */
1342 if (distance->value < axis_range_percentage(distance, 50))
1343 return;
1344
1345 if (offset > axis_range_percentage(pressure, 20)) {
1346 evdev_log_error(device,
1347 "Ignoring pressure offset greater than 20%% detected on tool %s (serial %#x). "
1348 "See %stablet-support.html\n",
1349 tablet_tool_type_to_string(tool->type),
1350 tool->serial,
1351 HTTP_DOC_LINK);
1352 return;
1353 }
1354
1355 evdev_log_info(device,
1356 "Pressure offset detected on tool %s (serial %#x). "
1357 "See %stablet-support.html\n",
1358 tablet_tool_type_to_string(tool->type),
1359 tool->serial,
1360 HTTP_DOC_LINK);
1361 tool->pressure_offset = offset;
1362 tool->has_pressure_offset = true;
1363 tool->pressure_threshold.lower = pressure->minimum;
1364 }
1365
1366 static void
detect_tool_contact(struct tablet_dispatch * tablet,struct evdev_device * device,struct libinput_tablet_tool * tool)1367 detect_tool_contact(struct tablet_dispatch *tablet,
1368 struct evdev_device *device,
1369 struct libinput_tablet_tool *tool)
1370 {
1371 const struct input_absinfo *p;
1372 int pressure;
1373
1374 if (!bit_is_set(tool->axis_caps, LIBINPUT_TABLET_TOOL_AXIS_PRESSURE))
1375 return;
1376
1377 /* if we have pressure, always use that for contact, not BTN_TOUCH */
1378 if (tablet_has_status(tablet, TABLET_TOOL_ENTERING_CONTACT))
1379 evdev_log_bug_libinput(device,
1380 "Invalid status: entering contact\n");
1381 if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_CONTACT) &&
1382 !tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY))
1383 evdev_log_bug_libinput(device,
1384 "Invalid status: leaving contact\n");
1385
1386 p = libevdev_get_abs_info(tablet->device->evdev, ABS_PRESSURE);
1387 if (!p) {
1388 evdev_log_bug_libinput(device,
1389 "Missing pressure axis\n");
1390 return;
1391 }
1392 pressure = p->value;
1393
1394 if (tool->has_pressure_offset)
1395 pressure -= (tool->pressure_offset - p->minimum);
1396
1397 if (pressure <= tool->pressure_threshold.lower &&
1398 tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT)) {
1399 tablet_set_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
1400 } else if (pressure >= tool->pressure_threshold.upper &&
1401 !tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT)) {
1402 tablet_set_status(tablet, TABLET_TOOL_ENTERING_CONTACT);
1403 }
1404 }
1405
1406 static void
tablet_mark_all_axes_changed(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool)1407 tablet_mark_all_axes_changed(struct tablet_dispatch *tablet,
1408 struct libinput_tablet_tool *tool)
1409 {
1410 static_assert(sizeof(tablet->changed_axes) ==
1411 sizeof(tool->axis_caps),
1412 "Mismatching array sizes");
1413
1414 memcpy(tablet->changed_axes,
1415 tool->axis_caps,
1416 sizeof(tablet->changed_axes));
1417 }
1418
1419 static void
tablet_update_proximity_state(struct tablet_dispatch * tablet,struct evdev_device * device,struct libinput_tablet_tool * tool)1420 tablet_update_proximity_state(struct tablet_dispatch *tablet,
1421 struct evdev_device *device,
1422 struct libinput_tablet_tool *tool)
1423 {
1424 const struct input_absinfo *distance;
1425 int dist_max = tablet->cursor_proximity_threshold;
1426 int dist;
1427
1428 distance = libevdev_get_abs_info(tablet->device->evdev, ABS_DISTANCE);
1429 if (!distance)
1430 return;
1431
1432 dist = distance->value;
1433 if (dist == 0)
1434 return;
1435
1436 /* Tool got into permitted range */
1437 if (dist < dist_max &&
1438 (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_RANGE) ||
1439 tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))) {
1440 tablet_unset_status(tablet,
1441 TABLET_TOOL_OUT_OF_RANGE);
1442 tablet_unset_status(tablet,
1443 TABLET_TOOL_OUT_OF_PROXIMITY);
1444 tablet_set_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY);
1445 tablet_mark_all_axes_changed(tablet, tool);
1446
1447 tablet_set_status(tablet, TABLET_BUTTONS_PRESSED);
1448 tablet_force_button_presses(tablet);
1449 return;
1450 }
1451
1452 if (dist < dist_max)
1453 return;
1454
1455 /* Still out of range/proximity */
1456 if (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_RANGE) ||
1457 tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))
1458 return;
1459
1460 /* Tool entered prox but is outside of permitted range */
1461 if (tablet_has_status(tablet,
1462 TABLET_TOOL_ENTERING_PROXIMITY)) {
1463 tablet_set_status(tablet,
1464 TABLET_TOOL_OUT_OF_RANGE);
1465 tablet_unset_status(tablet,
1466 TABLET_TOOL_ENTERING_PROXIMITY);
1467 return;
1468 }
1469
1470 /* Tool was in prox and is now outside of range. Set leaving
1471 * proximity, on the next event it will be OUT_OF_PROXIMITY and thus
1472 * caught by the above conditions */
1473 tablet_set_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
1474 }
1475
1476 static struct phys_rect
tablet_calculate_arbitration_rect(struct tablet_dispatch * tablet)1477 tablet_calculate_arbitration_rect(struct tablet_dispatch *tablet)
1478 {
1479 struct evdev_device *device = tablet->device;
1480 struct phys_rect r = {0};
1481 struct phys_coords mm;
1482
1483 mm = evdev_device_units_to_mm(device, &tablet->axes.point);
1484
1485 /* The rect we disable is 20mm left of the tip, 50mm north of the
1486 * tip, and 200x200mm large.
1487 * If the stylus is tilted left (tip further right than the eraser
1488 * end) assume left-handed mode.
1489 *
1490 * Obviously if we'd run out of the boundaries, we rescale the rect
1491 * accordingly.
1492 */
1493 if (tablet->axes.tilt.x > 0) {
1494 r.x = mm.x - 20;
1495 r.w = 200;
1496 } else {
1497 r.x = mm.x + 20;
1498 r.w = 200;
1499 r.x -= r.w;
1500 }
1501
1502 if (r.x < 0) {
1503 r.w -= r.x;
1504 r.x = 0;
1505 }
1506
1507 r.y = mm.y - 50;
1508 r.h = 200;
1509 if (r.y < 0) {
1510 r.h -= r.y;
1511 r.y = 0;
1512 }
1513
1514 return r;
1515 }
1516
1517 static inline void
tablet_update_touch_device_rect(struct tablet_dispatch * tablet,const struct tablet_axes * axes,uint64_t time)1518 tablet_update_touch_device_rect(struct tablet_dispatch *tablet,
1519 const struct tablet_axes *axes,
1520 uint64_t time)
1521 {
1522 struct evdev_dispatch *dispatch;
1523 struct phys_rect rect = {0};
1524
1525 if (tablet->touch_device == NULL ||
1526 tablet->arbitration != ARBITRATION_IGNORE_RECT)
1527 return;
1528
1529 rect = tablet_calculate_arbitration_rect(tablet);
1530
1531 dispatch = tablet->touch_device->dispatch;
1532 if (dispatch->interface->touch_arbitration_update_rect)
1533 dispatch->interface->touch_arbitration_update_rect(dispatch,
1534 tablet->touch_device,
1535 &rect,
1536 time);
1537 }
1538
1539 static inline bool
tablet_send_proximity_in(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool,struct evdev_device * device,struct tablet_axes * axes,uint64_t time)1540 tablet_send_proximity_in(struct tablet_dispatch *tablet,
1541 struct libinput_tablet_tool *tool,
1542 struct evdev_device *device,
1543 struct tablet_axes *axes,
1544 uint64_t time)
1545 {
1546 if (!tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY))
1547 return false;
1548
1549 tablet_notify_proximity(&device->base,
1550 time,
1551 tool,
1552 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN,
1553 tablet->changed_axes,
1554 axes);
1555 tablet_unset_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY);
1556 tablet_unset_status(tablet, TABLET_AXES_UPDATED);
1557
1558 tablet_reset_changed_axes(tablet);
1559 axes->delta.x = 0;
1560 axes->delta.y = 0;
1561
1562 return true;
1563 }
1564
1565 static inline bool
tablet_send_proximity_out(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool,struct evdev_device * device,struct tablet_axes * axes,uint64_t time)1566 tablet_send_proximity_out(struct tablet_dispatch *tablet,
1567 struct libinput_tablet_tool *tool,
1568 struct evdev_device *device,
1569 struct tablet_axes *axes,
1570 uint64_t time)
1571 {
1572 if (!tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY))
1573 return false;
1574
1575 tablet_notify_proximity(&device->base,
1576 time,
1577 tool,
1578 LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT,
1579 tablet->changed_axes,
1580 axes);
1581
1582 tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
1583 tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
1584
1585 tablet_reset_changed_axes(tablet);
1586 axes->delta.x = 0;
1587 axes->delta.y = 0;
1588
1589 return true;
1590 }
1591
1592 static inline bool
tablet_send_tip(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool,struct evdev_device * device,struct tablet_axes * axes,uint64_t time)1593 tablet_send_tip(struct tablet_dispatch *tablet,
1594 struct libinput_tablet_tool *tool,
1595 struct evdev_device *device,
1596 struct tablet_axes *axes,
1597 uint64_t time)
1598 {
1599 if (tablet_has_status(tablet, TABLET_TOOL_ENTERING_CONTACT)) {
1600 tablet_notify_tip(&device->base,
1601 time,
1602 tool,
1603 LIBINPUT_TABLET_TOOL_TIP_DOWN,
1604 tablet->changed_axes,
1605 axes);
1606 tablet_unset_status(tablet, TABLET_AXES_UPDATED);
1607 tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT);
1608 tablet_set_status(tablet, TABLET_TOOL_IN_CONTACT);
1609
1610 tablet_reset_changed_axes(tablet);
1611 axes->delta.x = 0;
1612 axes->delta.y = 0;
1613
1614 return true;
1615 }
1616
1617 if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_CONTACT)) {
1618 tablet_notify_tip(&device->base,
1619 time,
1620 tool,
1621 LIBINPUT_TABLET_TOOL_TIP_UP,
1622 tablet->changed_axes,
1623 axes);
1624 tablet_unset_status(tablet, TABLET_AXES_UPDATED);
1625 tablet_unset_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
1626 tablet_unset_status(tablet, TABLET_TOOL_IN_CONTACT);
1627
1628 tablet_reset_changed_axes(tablet);
1629 axes->delta.x = 0;
1630 axes->delta.y = 0;
1631
1632 return true;
1633 }
1634
1635 return false;
1636 }
1637
1638 static inline void
tablet_send_axes(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool,struct evdev_device * device,struct tablet_axes * axes,uint64_t time)1639 tablet_send_axes(struct tablet_dispatch *tablet,
1640 struct libinput_tablet_tool *tool,
1641 struct evdev_device *device,
1642 struct tablet_axes *axes,
1643 uint64_t time)
1644 {
1645 enum libinput_tablet_tool_tip_state tip_state;
1646
1647 if (!tablet_has_status(tablet, TABLET_AXES_UPDATED))
1648 return;
1649
1650 if (tablet_has_status(tablet,
1651 TABLET_TOOL_IN_CONTACT))
1652 tip_state = LIBINPUT_TABLET_TOOL_TIP_DOWN;
1653 else
1654 tip_state = LIBINPUT_TABLET_TOOL_TIP_UP;
1655
1656 tablet_notify_axis(&device->base,
1657 time,
1658 tool,
1659 tip_state,
1660 tablet->changed_axes,
1661 axes);
1662 tablet_unset_status(tablet, TABLET_AXES_UPDATED);
1663 tablet_reset_changed_axes(tablet);
1664 axes->delta.x = 0;
1665 axes->delta.y = 0;
1666 }
1667
1668 static inline void
tablet_send_buttons(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool,struct evdev_device * device,uint64_t time)1669 tablet_send_buttons(struct tablet_dispatch *tablet,
1670 struct libinput_tablet_tool *tool,
1671 struct evdev_device *device,
1672 uint64_t time)
1673 {
1674 if (tablet_has_status(tablet, TABLET_BUTTONS_RELEASED)) {
1675 tablet_notify_buttons(tablet,
1676 device,
1677 time,
1678 tool,
1679 LIBINPUT_BUTTON_STATE_RELEASED);
1680 tablet_unset_status(tablet, TABLET_BUTTONS_RELEASED);
1681 }
1682
1683 if (tablet_has_status(tablet, TABLET_BUTTONS_PRESSED)) {
1684 tablet_notify_buttons(tablet,
1685 device,
1686 time,
1687 tool,
1688 LIBINPUT_BUTTON_STATE_PRESSED);
1689 tablet_unset_status(tablet, TABLET_BUTTONS_PRESSED);
1690 }
1691 }
1692
1693 static void
tablet_send_events(struct tablet_dispatch * tablet,struct libinput_tablet_tool * tool,struct evdev_device * device,uint64_t time)1694 tablet_send_events(struct tablet_dispatch *tablet,
1695 struct libinput_tablet_tool *tool,
1696 struct evdev_device *device,
1697 uint64_t time)
1698 {
1699 struct tablet_axes axes = {0};
1700
1701 if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
1702 /* Tool is leaving proximity, we can't rely on the last axis
1703 * information (it'll be mostly 0), so we just get the
1704 * current state and skip over updating the axes.
1705 */
1706 axes = tablet->axes;
1707
1708 /* Dont' send an axis event, but we may have a tip event
1709 * update */
1710 tablet_unset_status(tablet, TABLET_AXES_UPDATED);
1711 } else {
1712 if (tablet_check_notify_axes(tablet, device, tool, &axes, time))
1713 tablet_update_touch_device_rect(tablet, &axes, time);
1714 }
1715
1716 assert(tablet->axes.delta.x == 0);
1717 assert(tablet->axes.delta.y == 0);
1718
1719 tablet_send_proximity_in(tablet, tool, device, &axes, time);
1720 if (!tablet_send_tip(tablet, tool, device, &axes, time))
1721 tablet_send_axes(tablet, tool, device, &axes, time);
1722
1723 tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT);
1724 tablet_reset_changed_axes(tablet);
1725
1726 tablet_send_buttons(tablet, tool, device, time);
1727
1728 if (tablet_send_proximity_out(tablet, tool, device, &axes, time)) {
1729 tablet_change_to_left_handed(device);
1730 tablet_apply_rotation(device);
1731 tablet_history_reset(tablet);
1732 }
1733 }
1734
1735 /**
1736 * Handling for the proximity out workaround. Some tablets only send
1737 * BTN_TOOL_PEN on the very first event, then leave it set even when the pen
1738 * leaves the detectable range. To libinput this looks like we always have
1739 * the pen in proximity.
1740 *
1741 * To avoid this, we set a timer on BTN_TOOL_PEN in. We expect the tablet to
1742 * continuously send events, and while it's doing so we keep updating the
1743 * timer. Once we go Xms without an event we assume proximity out and inject
1744 * a BTN_TOOL_PEN event into the sequence through the timer func.
1745 *
1746 * We need to remember that we did that, on the first event after the
1747 * timeout we need to emulate a BTN_TOOL_PEN event again to force proximity
1748 * in.
1749 *
1750 * Other tools never send the BTN_TOOL_PEN event. For those tools, we
1751 * piggyback along with the proximity out quirks by injecting
1752 * the event during the first event frame.
1753 */
1754 static inline void
tablet_proximity_out_quirk_set_timer(struct tablet_dispatch * tablet,uint64_t time)1755 tablet_proximity_out_quirk_set_timer(struct tablet_dispatch *tablet,
1756 uint64_t time)
1757 {
1758 if (tablet->quirks.need_to_force_prox_out)
1759 libinput_timer_set(&tablet->quirks.prox_out_timer,
1760 time + FORCED_PROXOUT_TIMEOUT);
1761 }
1762
1763 static bool
tablet_update_tool_state(struct tablet_dispatch * tablet,struct evdev_device * device,uint64_t time)1764 tablet_update_tool_state(struct tablet_dispatch *tablet,
1765 struct evdev_device *device,
1766 uint64_t time)
1767 {
1768 enum libinput_tablet_tool_type type;
1769 uint32_t changed;
1770 int state;
1771 uint32_t doubled_up_new_tool_bit = 0;
1772
1773 /* we were already out of proximity but now got a tool update but
1774 * our tool state is zero - i.e. we got a valid prox out from the
1775 * device.
1776 */
1777 if (tablet->quirks.proximity_out_forced &&
1778 tablet_has_status(tablet, TABLET_TOOL_UPDATED) &&
1779 !tablet->tool_state) {
1780 tablet->quirks.need_to_force_prox_out = false;
1781 tablet->quirks.proximity_out_forced = false;
1782 }
1783 /* We need to emulate a BTN_TOOL_PEN if we get an axis event (i.e.
1784 * stylus is def. in proximity) and:
1785 * - we forced a proximity out before, or
1786 * - on the very first event after init, because if we didn't get a
1787 * BTN_TOOL_PEN and the state for the tool was 0, this device will
1788 * never send the event.
1789 * We don't do this for pure button events because we discard those.
1790 *
1791 * But: on some devices the proximity out is delayed by the kernel,
1792 * so we get it after our forced prox-out has triggered. In that
1793 * case we need to just ignore the change.
1794 */
1795 if (tablet_has_status(tablet, TABLET_AXES_UPDATED)) {
1796 if (tablet->quirks.proximity_out_forced) {
1797 if (!tablet_has_status(tablet, TABLET_TOOL_UPDATED) &&
1798 !tablet->tool_state)
1799 tablet->tool_state = bit(LIBINPUT_TABLET_TOOL_TYPE_PEN);
1800 tablet->quirks.proximity_out_forced = false;
1801 } else if (tablet->tool_state == 0 &&
1802 tablet->current_tool.type == LIBINPUT_TOOL_NONE) {
1803 tablet->tool_state = bit(LIBINPUT_TABLET_TOOL_TYPE_PEN);
1804 tablet->quirks.proximity_out_forced = false;
1805 }
1806 }
1807
1808 if (tablet->tool_state == tablet->prev_tool_state)
1809 return false;
1810
1811 /* Kernel tools are supposed to be mutually exclusive, if we have
1812 * two, we force a proximity out for the older tool and handle the
1813 * new tool as separate proximity in event.
1814 */
1815 if (tablet->tool_state & (tablet->tool_state - 1)) {
1816 /* tool_state has 2 bits set. We set the current tool state
1817 * to zero, thus setting everything up for a prox out on the
1818 * tool. Once that is set up, we change the tool state to be
1819 * the new one we just got so when we re-process this
1820 * function we now get the new tool as prox in.
1821 * Importantly, we basically rely on nothing else happening
1822 * in the meantime.
1823 */
1824 doubled_up_new_tool_bit = tablet->tool_state ^ tablet->prev_tool_state;
1825 tablet->tool_state = 0;
1826 }
1827
1828 changed = tablet->tool_state ^ tablet->prev_tool_state;
1829 type = ffs(changed) - 1;
1830 state = !!(tablet->tool_state & bit(type));
1831
1832 tablet_update_tool(tablet, device, type, state);
1833
1834 /* The proximity timeout is only needed for BTN_TOOL_PEN, devices
1835 * that require it don't do erasers */
1836 if (type == LIBINPUT_TABLET_TOOL_TYPE_PEN) {
1837 if (state) {
1838 tablet_proximity_out_quirk_set_timer(tablet, time);
1839 } else {
1840 /* If we get a BTN_TOOL_PEN 0 when *not* injecting
1841 * events it means the tablet will give us the right
1842 * events after all and we can disable our
1843 * timer-based proximity out.
1844 */
1845 if (!tablet->quirks.proximity_out_in_progress)
1846 tablet->quirks.need_to_force_prox_out = false;
1847
1848 libinput_timer_cancel(&tablet->quirks.prox_out_timer);
1849 }
1850 }
1851
1852 tablet->prev_tool_state = tablet->tool_state;
1853
1854 if (doubled_up_new_tool_bit) {
1855 tablet->tool_state = doubled_up_new_tool_bit;
1856 return true; /* need to re-process */
1857 }
1858 return false;
1859 }
1860
1861 static struct libinput_tablet_tool *
tablet_get_current_tool(struct tablet_dispatch * tablet)1862 tablet_get_current_tool(struct tablet_dispatch *tablet)
1863 {
1864 if (tablet->current_tool.type == LIBINPUT_TOOL_NONE)
1865 return NULL;
1866
1867 return tablet_get_tool(tablet,
1868 tablet->current_tool.type,
1869 tablet->current_tool.id,
1870 tablet->current_tool.serial);
1871 }
1872
1873 static void
tablet_flush(struct tablet_dispatch * tablet,struct evdev_device * device,uint64_t time)1874 tablet_flush(struct tablet_dispatch *tablet,
1875 struct evdev_device *device,
1876 uint64_t time)
1877 {
1878 struct libinput_tablet_tool *tool;
1879 bool process_tool_twice;
1880
1881 reprocess:
1882 process_tool_twice = tablet_update_tool_state(tablet, device, time);
1883
1884 tool = tablet_get_current_tool(tablet);
1885 if (!tool)
1886 return; /* OOM */
1887
1888 if (tool->type == LIBINPUT_TABLET_TOOL_TYPE_MOUSE ||
1889 tool->type == LIBINPUT_TABLET_TOOL_TYPE_LENS)
1890 tablet_update_proximity_state(tablet, device, tool);
1891
1892 if (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY) ||
1893 tablet_has_status(tablet, TABLET_TOOL_OUT_OF_RANGE))
1894 return;
1895
1896 if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) {
1897 /* Release all stylus buttons */
1898 memset(tablet->button_state.bits,
1899 0,
1900 sizeof(tablet->button_state.bits));
1901 tablet_set_status(tablet, TABLET_BUTTONS_RELEASED);
1902 if (tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT))
1903 tablet_set_status(tablet, TABLET_TOOL_LEAVING_CONTACT);
1904 } else if (tablet_has_status(tablet, TABLET_AXES_UPDATED) ||
1905 tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY)) {
1906 if (tablet_has_status(tablet,
1907 TABLET_TOOL_ENTERING_PROXIMITY))
1908 tablet_mark_all_axes_changed(tablet, tool);
1909 detect_pressure_offset(tablet, device, tool);
1910 detect_tool_contact(tablet, device, tool);
1911 sanitize_tablet_axes(tablet, tool);
1912 }
1913
1914 tablet_send_events(tablet, tool, device, time);
1915
1916 if (process_tool_twice)
1917 goto reprocess;
1918 }
1919
1920 static inline void
tablet_set_touch_device_enabled(struct tablet_dispatch * tablet,enum evdev_arbitration_state which,const struct phys_rect * rect,uint64_t time)1921 tablet_set_touch_device_enabled(struct tablet_dispatch *tablet,
1922 enum evdev_arbitration_state which,
1923 const struct phys_rect *rect,
1924 uint64_t time)
1925 {
1926 struct evdev_device *touch_device = tablet->touch_device;
1927 struct evdev_dispatch *dispatch;
1928
1929 if (touch_device == NULL)
1930 return;
1931
1932 tablet->arbitration = which;
1933
1934 dispatch = touch_device->dispatch;
1935 if (dispatch->interface->touch_arbitration_toggle)
1936 dispatch->interface->touch_arbitration_toggle(dispatch,
1937 touch_device,
1938 which,
1939 rect,
1940 time);
1941 }
1942
1943 static inline void
tablet_toggle_touch_device(struct tablet_dispatch * tablet,struct evdev_device * tablet_device,uint64_t time)1944 tablet_toggle_touch_device(struct tablet_dispatch *tablet,
1945 struct evdev_device *tablet_device,
1946 uint64_t time)
1947 {
1948 enum evdev_arbitration_state which;
1949 struct phys_rect r = {0};
1950 struct phys_rect *rect = NULL;
1951
1952 if (tablet_has_status(tablet,
1953 TABLET_TOOL_OUT_OF_RANGE) ||
1954 tablet_has_status(tablet, TABLET_NONE) ||
1955 tablet_has_status(tablet,
1956 TABLET_TOOL_LEAVING_PROXIMITY) ||
1957 tablet_has_status(tablet,
1958 TABLET_TOOL_OUT_OF_PROXIMITY)) {
1959 which = ARBITRATION_NOT_ACTIVE;
1960 } else if (tablet->axes.tilt.x == 0) {
1961 which = ARBITRATION_IGNORE_ALL;
1962 } else if (tablet->arbitration != ARBITRATION_IGNORE_RECT) {
1963 /* This enables rect-based arbitration, updates are sent
1964 * elsewhere */
1965 r = tablet_calculate_arbitration_rect(tablet);
1966 rect = &r;
1967 which = ARBITRATION_IGNORE_RECT;
1968 } else {
1969 return;
1970 }
1971
1972 tablet_set_touch_device_enabled(tablet,
1973 which,
1974 rect,
1975 time);
1976 }
1977
1978 static inline void
tablet_reset_state(struct tablet_dispatch * tablet)1979 tablet_reset_state(struct tablet_dispatch *tablet)
1980 {
1981 struct button_state zero = {0};
1982
1983 /* Update state */
1984 memcpy(&tablet->prev_button_state,
1985 &tablet->button_state,
1986 sizeof(tablet->button_state));
1987 tablet_unset_status(tablet, TABLET_TOOL_UPDATED);
1988
1989 if (memcmp(&tablet->button_state, &zero, sizeof(zero)) == 0)
1990 tablet_unset_status(tablet, TABLET_BUTTONS_DOWN);
1991 else
1992 tablet_set_status(tablet, TABLET_BUTTONS_DOWN);
1993 }
1994
1995 static void
tablet_proximity_out_quirk_timer_func(uint64_t now,void * data)1996 tablet_proximity_out_quirk_timer_func(uint64_t now, void *data)
1997 {
1998 struct tablet_dispatch *tablet = data;
1999 struct timeval tv = us2tv(now);
2000 struct input_event events[2] = {
2001 { .input_event_sec = tv.tv_sec,
2002 .input_event_usec = tv.tv_usec,
2003 .type = EV_KEY,
2004 .code = BTN_TOOL_PEN,
2005 .value = 0 },
2006 { .input_event_sec = tv.tv_sec,
2007 .input_event_usec = tv.tv_usec,
2008 .type = EV_SYN,
2009 .code = SYN_REPORT,
2010 .value = 0 },
2011 };
2012 struct input_event *e;
2013
2014 if (tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT) ||
2015 tablet_has_status(tablet, TABLET_BUTTONS_DOWN)) {
2016 tablet_proximity_out_quirk_set_timer(tablet, now);
2017 return;
2018 }
2019
2020 if (tablet->quirks.last_event_time > now - FORCED_PROXOUT_TIMEOUT) {
2021 tablet_proximity_out_quirk_set_timer(tablet,
2022 tablet->quirks.last_event_time);
2023 return;
2024 }
2025
2026 evdev_log_debug(tablet->device, "tablet: forcing proximity after timeout\n");
2027
2028 tablet->quirks.proximity_out_in_progress = true;
2029 ARRAY_FOR_EACH(events, e) {
2030 tablet->base.interface->process(&tablet->base,
2031 tablet->device,
2032 e,
2033 now);
2034 }
2035 tablet->quirks.proximity_out_in_progress = false;
2036
2037 tablet->quirks.proximity_out_forced = true;
2038 }
2039
2040 static void
tablet_process(struct evdev_dispatch * dispatch,struct evdev_device * device,struct input_event * e,uint64_t time)2041 tablet_process(struct evdev_dispatch *dispatch,
2042 struct evdev_device *device,
2043 struct input_event *e,
2044 uint64_t time)
2045 {
2046 struct tablet_dispatch *tablet = tablet_dispatch(dispatch);
2047
2048 switch (e->type) {
2049 case EV_ABS:
2050 tablet_process_absolute(tablet, device, e, time);
2051 break;
2052 case EV_REL:
2053 tablet_process_relative(tablet, device, e, time);
2054 break;
2055 case EV_KEY:
2056 tablet_process_key(tablet, device, e, time);
2057 break;
2058 case EV_MSC:
2059 tablet_process_misc(tablet, device, e, time);
2060 break;
2061 case EV_SYN:
2062 tablet_flush(tablet, device, time);
2063 tablet_toggle_touch_device(tablet, device, time);
2064 tablet_reset_state(tablet);
2065 tablet->quirks.last_event_time = time;
2066 break;
2067 default:
2068 evdev_log_error(device,
2069 "Unexpected event type %s (%#x)\n",
2070 libevdev_event_type_get_name(e->type),
2071 e->type);
2072 break;
2073 }
2074 }
2075
2076 static void
tablet_suspend(struct evdev_dispatch * dispatch,struct evdev_device * device)2077 tablet_suspend(struct evdev_dispatch *dispatch,
2078 struct evdev_device *device)
2079 {
2080 struct tablet_dispatch *tablet = tablet_dispatch(dispatch);
2081 struct libinput *li = tablet_libinput_context(tablet);
2082 uint64_t now = libinput_now(li);
2083
2084 tablet_set_touch_device_enabled(tablet,
2085 ARBITRATION_NOT_ACTIVE,
2086 NULL,
2087 now);
2088
2089 if (!tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY)) {
2090 tablet_set_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY);
2091 tablet_flush(tablet, device, libinput_now(li));
2092 }
2093 }
2094
2095 static void
tablet_destroy(struct evdev_dispatch * dispatch)2096 tablet_destroy(struct evdev_dispatch *dispatch)
2097 {
2098 struct tablet_dispatch *tablet = tablet_dispatch(dispatch);
2099 struct libinput_tablet_tool *tool, *tmp;
2100 struct libinput *li = tablet_libinput_context(tablet);
2101
2102 libinput_timer_cancel(&tablet->quirks.prox_out_timer);
2103 libinput_timer_destroy(&tablet->quirks.prox_out_timer);
2104
2105 list_for_each_safe(tool, tmp, &tablet->tool_list, link) {
2106 libinput_tablet_tool_unref(tool);
2107 }
2108
2109 libinput_libwacom_unref(li);
2110
2111 free(tablet);
2112 }
2113
2114 static void
tablet_device_added(struct evdev_device * device,struct evdev_device * added_device)2115 tablet_device_added(struct evdev_device *device,
2116 struct evdev_device *added_device)
2117 {
2118 struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch);
2119 bool is_touchscreen, is_ext_touchpad;
2120
2121 if (libinput_device_get_device_group(&device->base) !=
2122 libinput_device_get_device_group(&added_device->base))
2123 return;
2124
2125 is_touchscreen = evdev_device_has_capability(added_device,
2126 LIBINPUT_DEVICE_CAP_TOUCH);
2127 is_ext_touchpad = evdev_device_has_capability(added_device,
2128 LIBINPUT_DEVICE_CAP_POINTER) &&
2129 (added_device->tags & EVDEV_TAG_EXTERNAL_TOUCHPAD);
2130 /* Touch screens or external touchpads only */
2131 if (is_touchscreen || is_ext_touchpad) {
2132 evdev_log_debug(device,
2133 "touch-arbitration: activated for %s<->%s\n",
2134 device->devname,
2135 added_device->devname);
2136 tablet->touch_device = added_device;
2137 }
2138
2139 if (is_ext_touchpad) {
2140 evdev_log_debug(device,
2141 "tablet-rotation: %s will rotate %s\n",
2142 device->devname,
2143 added_device->devname);
2144 tablet->rotation.touch_device = added_device;
2145
2146 if (libinput_device_config_left_handed_get(&added_device->base)) {
2147 tablet->rotation.touch_device_left_handed_state = true;
2148 tablet_change_rotation(device, DO_NOTIFY);
2149 }
2150 }
2151
2152 }
2153
2154 static void
tablet_device_removed(struct evdev_device * device,struct evdev_device * removed_device)2155 tablet_device_removed(struct evdev_device *device,
2156 struct evdev_device *removed_device)
2157 {
2158 struct tablet_dispatch *tablet = tablet_dispatch(device->dispatch);
2159
2160 if (tablet->touch_device == removed_device)
2161 tablet->touch_device = NULL;
2162
2163 if (tablet->rotation.touch_device == removed_device) {
2164 tablet->rotation.touch_device = NULL;
2165 tablet->rotation.touch_device_left_handed_state = false;
2166 tablet_change_rotation(device, DO_NOTIFY);
2167 }
2168 }
2169
2170 static void
tablet_check_initial_proximity(struct evdev_device * device,struct evdev_dispatch * dispatch)2171 tablet_check_initial_proximity(struct evdev_device *device,
2172 struct evdev_dispatch *dispatch)
2173 {
2174 struct tablet_dispatch *tablet = tablet_dispatch(dispatch);
2175 struct libinput *li = tablet_libinput_context(tablet);
2176 int code, state;
2177 enum libinput_tablet_tool_type tool;
2178
2179 for (tool = LIBINPUT_TABLET_TOOL_TYPE_PEN;
2180 tool <= LIBINPUT_TABLET_TOOL_TYPE_MAX;
2181 tool++) {
2182 code = tablet_tool_to_evcode(tool);
2183
2184 /* we only expect one tool to be in proximity at a time */
2185 if (libevdev_fetch_event_value(device->evdev,
2186 EV_KEY,
2187 code,
2188 &state) && state) {
2189 tablet->tool_state = bit(tool);
2190 tablet->prev_tool_state = bit(tool);
2191 break;
2192 }
2193 }
2194
2195 if (!tablet->tool_state)
2196 return;
2197
2198 tablet_update_tool(tablet, device, tool, state);
2199 if (tablet->quirks.need_to_force_prox_out)
2200 tablet_proximity_out_quirk_set_timer(tablet, libinput_now(li));
2201
2202 tablet->current_tool.id =
2203 libevdev_get_event_value(device->evdev,
2204 EV_ABS,
2205 ABS_MISC);
2206
2207 /* we can't fetch MSC_SERIAL from the kernel, so we set the serial
2208 * to 0 for now. On the first real event from the device we get the
2209 * serial (if any) and that event will be converted into a proximity
2210 * event */
2211 tablet->current_tool.serial = 0;
2212 }
2213
2214 /* Called when the touchpad toggles to left-handed */
2215 static void
tablet_left_handed_toggled(struct evdev_dispatch * dispatch,struct evdev_device * device,bool left_handed_enabled)2216 tablet_left_handed_toggled(struct evdev_dispatch *dispatch,
2217 struct evdev_device *device,
2218 bool left_handed_enabled)
2219 {
2220 struct tablet_dispatch *tablet = tablet_dispatch(dispatch);
2221
2222 if (!tablet->rotation.touch_device)
2223 return;
2224
2225 evdev_log_debug(device,
2226 "tablet-rotation: touchpad is %s\n",
2227 left_handed_enabled ? "left-handed" : "right-handed");
2228
2229 /* Our left-handed config is independent even though rotation is
2230 * locked. So we rotate when either device is left-handed. But it
2231 * can only be actually changed when the device is in a neutral
2232 * state, hence the want_rotate.
2233 */
2234 tablet->rotation.touch_device_left_handed_state = left_handed_enabled;
2235 tablet_change_rotation(device, DONT_NOTIFY);
2236 }
2237
2238 static struct evdev_dispatch_interface tablet_interface = {
2239 .process = tablet_process,
2240 .suspend = tablet_suspend,
2241 .remove = NULL,
2242 .destroy = tablet_destroy,
2243 .device_added = tablet_device_added,
2244 .device_removed = tablet_device_removed,
2245 .device_suspended = NULL,
2246 .device_resumed = NULL,
2247 .post_added = tablet_check_initial_proximity,
2248 .touch_arbitration_toggle = NULL,
2249 .touch_arbitration_update_rect = NULL,
2250 .get_switch_state = NULL,
2251 .left_handed_toggle = tablet_left_handed_toggled,
2252 };
2253
2254 static void
tablet_init_calibration(struct tablet_dispatch * tablet,struct evdev_device * device)2255 tablet_init_calibration(struct tablet_dispatch *tablet,
2256 struct evdev_device *device)
2257 {
2258 if (libevdev_has_property(device->evdev, INPUT_PROP_DIRECT))
2259 evdev_init_calibration(device, &tablet->calibration);
2260 }
2261
2262 static void
tablet_init_proximity_threshold(struct tablet_dispatch * tablet,struct evdev_device * device)2263 tablet_init_proximity_threshold(struct tablet_dispatch *tablet,
2264 struct evdev_device *device)
2265 {
2266 /* This rules out most of the bamboos and other devices, we're
2267 * pretty much down to
2268 */
2269 if (!libevdev_has_event_code(device->evdev, EV_KEY, BTN_TOOL_MOUSE) &&
2270 !libevdev_has_event_code(device->evdev, EV_KEY, BTN_TOOL_LENS))
2271 return;
2272
2273 /* 42 is the default proximity threshold the xf86-input-wacom driver
2274 * uses for Intuos/Cintiq models. Graphire models have a threshold
2275 * of 10 but since they haven't been manufactured in ages and the
2276 * intersection of users having a graphire, running libinput and
2277 * wanting to use the mouse/lens cursor tool is small enough to not
2278 * worry about it for now. If we need to, we can introduce a udev
2279 * property later.
2280 *
2281 * Value is in device coordinates.
2282 */
2283 tablet->cursor_proximity_threshold = 42;
2284 }
2285
2286 static uint32_t
tablet_accel_config_get_profiles(struct libinput_device * libinput_device)2287 tablet_accel_config_get_profiles(struct libinput_device *libinput_device)
2288 {
2289 return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
2290 }
2291
2292 static enum libinput_config_status
tablet_accel_config_set_profile(struct libinput_device * libinput_device,enum libinput_config_accel_profile profile)2293 tablet_accel_config_set_profile(struct libinput_device *libinput_device,
2294 enum libinput_config_accel_profile profile)
2295 {
2296 return LIBINPUT_CONFIG_STATUS_UNSUPPORTED;
2297 }
2298
2299 static enum libinput_config_accel_profile
tablet_accel_config_get_profile(struct libinput_device * libinput_device)2300 tablet_accel_config_get_profile(struct libinput_device *libinput_device)
2301 {
2302 return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
2303 }
2304
2305 static enum libinput_config_accel_profile
tablet_accel_config_get_default_profile(struct libinput_device * libinput_device)2306 tablet_accel_config_get_default_profile(struct libinput_device *libinput_device)
2307 {
2308 return LIBINPUT_CONFIG_ACCEL_PROFILE_NONE;
2309 }
2310
2311 static int
tablet_init_accel(struct tablet_dispatch * tablet,struct evdev_device * device)2312 tablet_init_accel(struct tablet_dispatch *tablet, struct evdev_device *device)
2313 {
2314 const struct input_absinfo *x, *y;
2315 struct motion_filter *filter;
2316
2317 x = device->abs.absinfo_x;
2318 y = device->abs.absinfo_y;
2319
2320 filter = create_pointer_accelerator_filter_tablet(x->resolution,
2321 y->resolution);
2322 if (!filter)
2323 return -1;
2324
2325 evdev_device_init_pointer_acceleration(device, filter);
2326
2327 /* we override the profile hooks for accel configuration with hooks
2328 * that don't allow selection of profiles */
2329 device->pointer.config.get_profiles = tablet_accel_config_get_profiles;
2330 device->pointer.config.set_profile = tablet_accel_config_set_profile;
2331 device->pointer.config.get_profile = tablet_accel_config_get_profile;
2332 device->pointer.config.get_default_profile = tablet_accel_config_get_default_profile;
2333
2334 return 0;
2335 }
2336
2337 static void
tablet_init_left_handed(struct evdev_device * device)2338 tablet_init_left_handed(struct evdev_device *device)
2339 {
2340 if (evdev_tablet_has_left_handed(device))
2341 evdev_init_left_handed(device,
2342 tablet_change_to_left_handed);
2343 }
2344
2345 static bool
tablet_reject_device(struct evdev_device * device)2346 tablet_reject_device(struct evdev_device *device)
2347 {
2348 struct libevdev *evdev = device->evdev;
2349 double w, h;
2350 bool has_xy, has_pen, has_btn_stylus, has_size;
2351
2352 has_xy = libevdev_has_event_code(evdev, EV_ABS, ABS_X) &&
2353 libevdev_has_event_code(evdev, EV_ABS, ABS_Y);
2354 has_pen = libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN);
2355 has_btn_stylus = libevdev_has_event_code(evdev, EV_KEY, BTN_STYLUS);
2356 has_size = evdev_device_get_size(device, &w, &h) == 0;
2357
2358 if (has_xy && (has_pen || has_btn_stylus) && has_size)
2359 return false;
2360
2361 evdev_log_bug_libinput(device,
2362 "missing tablet capabilities:%s%s%s%s. "
2363 "Ignoring this device.\n",
2364 has_xy ? "" : " xy",
2365 has_pen ? "" : " pen",
2366 has_btn_stylus ? "" : " btn-stylus",
2367 has_size ? "" : " resolution");
2368 return true;
2369 }
2370
2371 static int
tablet_init(struct tablet_dispatch * tablet,struct evdev_device * device)2372 tablet_init(struct tablet_dispatch *tablet,
2373 struct evdev_device *device)
2374 {
2375 struct libevdev *evdev = device->evdev;
2376 enum libinput_tablet_tool_axis axis;
2377 int rc;
2378
2379 tablet->base.dispatch_type = DISPATCH_TABLET;
2380 tablet->base.interface = &tablet_interface;
2381 tablet->device = device;
2382 tablet->status = TABLET_NONE;
2383 tablet->current_tool.type = LIBINPUT_TOOL_NONE;
2384 list_init(&tablet->tool_list);
2385
2386 if (tablet_reject_device(device))
2387 return -1;
2388
2389 if (!libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN)) {
2390 libevdev_enable_event_code(evdev, EV_KEY, BTN_TOOL_PEN, NULL);
2391 tablet->quirks.proximity_out_forced = true;
2392 }
2393
2394 /* Our rotation code only works with Wacoms, let's wait until
2395 * someone shouts */
2396 if (evdev_device_get_id_vendor(device) != VENDOR_ID_WACOM) {
2397 libevdev_disable_event_code(evdev, EV_KEY, BTN_TOOL_MOUSE);
2398 libevdev_disable_event_code(evdev, EV_KEY, BTN_TOOL_LENS);
2399 }
2400
2401 tablet_init_calibration(tablet, device);
2402 tablet_init_proximity_threshold(tablet, device);
2403 rc = tablet_init_accel(tablet, device);
2404 if (rc != 0)
2405 return rc;
2406
2407 evdev_init_sendevents(device, &tablet->base);
2408 tablet_init_left_handed(device);
2409
2410 for (axis = LIBINPUT_TABLET_TOOL_AXIS_X;
2411 axis <= LIBINPUT_TABLET_TOOL_AXIS_MAX;
2412 axis++) {
2413 if (tablet_device_has_axis(tablet, axis))
2414 set_bit(tablet->axis_caps, axis);
2415 }
2416
2417 tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY);
2418
2419 /* We always enable the proximity out quirk, but disable it once a
2420 device gives us the right event sequence */
2421 tablet->quirks.need_to_force_prox_out = true;
2422
2423 libinput_timer_init(&tablet->quirks.prox_out_timer,
2424 tablet_libinput_context(tablet),
2425 "proxout",
2426 tablet_proximity_out_quirk_timer_func,
2427 tablet);
2428
2429 return 0;
2430 }
2431
2432 struct evdev_dispatch *
evdev_tablet_create(struct evdev_device * device)2433 evdev_tablet_create(struct evdev_device *device)
2434 {
2435 struct tablet_dispatch *tablet;
2436 struct libinput *li = evdev_libinput_context(device);
2437
2438 libinput_libwacom_ref(li);
2439
2440 /* Stop false positives caused by the forced proximity code */
2441 if (getenv("LIBINPUT_RUNNING_TEST_SUITE"))
2442 FORCED_PROXOUT_TIMEOUT = 150 * 1000; /* µs */
2443
2444 tablet = zalloc(sizeof *tablet);
2445
2446 if (tablet_init(tablet, device) != 0) {
2447 tablet_destroy(&tablet->base);
2448 return NULL;
2449 }
2450
2451 return &tablet->base;
2452 }
2453