xref: /third_party/libinput/src/evdev-tablet.h (revision a46c0ec8)
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
25#ifndef EVDEV_TABLET_H
26#define EVDEV_TABLET_H
27
28#include "evdev.h"
29
30#define LIBINPUT_TABLET_TOOL_AXIS_NONE 0
31#define LIBINPUT_TOOL_NONE 0
32#define LIBINPUT_TABLET_TOOL_TYPE_MAX LIBINPUT_TABLET_TOOL_TYPE_LENS
33
34#define TABLET_HISTORY_LENGTH 4
35
36enum tablet_status {
37	TABLET_NONE			= 0,
38	TABLET_AXES_UPDATED		= bit(0),
39	TABLET_BUTTONS_PRESSED		= bit(1),
40	TABLET_BUTTONS_DOWN		= bit(2),
41	TABLET_BUTTONS_RELEASED		= bit(3),
42	TABLET_TOOL_UPDATED		= bit(4),
43	TABLET_TOOL_IN_CONTACT		= bit(5),
44	TABLET_TOOL_LEAVING_PROXIMITY	= bit(6),
45	TABLET_TOOL_OUT_OF_PROXIMITY	= bit(7),
46	TABLET_TOOL_ENTERING_PROXIMITY	= bit(8),
47	TABLET_TOOL_ENTERING_CONTACT	= bit(9),
48	TABLET_TOOL_LEAVING_CONTACT	= bit(10),
49	TABLET_TOOL_OUT_OF_RANGE	= bit(11),
50};
51
52struct button_state {
53	unsigned char bits[NCHARS(KEY_CNT)];
54};
55
56struct tablet_dispatch {
57	struct evdev_dispatch base;
58	struct evdev_device *device;
59	unsigned int status;
60	unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)];
61	struct tablet_axes axes; /* for assembling the current state */
62	struct device_coords last_smooth_point;
63	struct {
64		unsigned int index;
65		unsigned int count;
66		struct tablet_axes samples[TABLET_HISTORY_LENGTH];
67		size_t size;
68	} history;
69
70	unsigned char axis_caps[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)];
71	int current_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1];
72	int prev_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1];
73
74	/* Only used for tablets that don't report serial numbers */
75	struct list tool_list;
76
77	struct button_state button_state;
78	struct button_state prev_button_state;
79
80	uint32_t tool_state;
81	uint32_t prev_tool_state;
82
83	struct {
84		enum libinput_tablet_tool_type type;
85		uint32_t id;
86		uint32_t serial;
87	} current_tool;
88
89	uint32_t cursor_proximity_threshold;
90
91	struct libinput_device_config_calibration calibration;
92
93	/* The paired touch device on devices with both pen & touch */
94	struct evdev_device *touch_device;
95	enum evdev_arbitration_state arbitration;
96
97	struct {
98		/* The device locked for rotation */
99		struct evdev_device *touch_device;
100		/* Last known left-handed state of the touchpad */
101		bool touch_device_left_handed_state;
102		bool rotate;
103		bool want_rotate;
104	} rotation;
105
106	struct {
107		bool need_to_force_prox_out;
108		struct libinput_timer prox_out_timer;
109		bool proximity_out_forced;
110		uint64_t last_event_time;
111
112		/* true while injecting BTN_TOOL_PEN events */
113		bool proximity_out_in_progress;
114	} quirks;
115};
116
117static inline struct tablet_dispatch*
118tablet_dispatch(struct evdev_dispatch *dispatch)
119{
120	evdev_verify_dispatch_type(dispatch, DISPATCH_TABLET);
121
122	return container_of(dispatch, struct tablet_dispatch, base);
123}
124
125static inline enum libinput_tablet_tool_axis
126evcode_to_axis(const uint32_t evcode)
127{
128	enum libinput_tablet_tool_axis axis;
129
130	switch (evcode) {
131	case ABS_X:
132		axis = LIBINPUT_TABLET_TOOL_AXIS_X;
133		break;
134	case ABS_Y:
135		axis = LIBINPUT_TABLET_TOOL_AXIS_Y;
136		break;
137	case ABS_Z:
138		axis = LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z;
139		break;
140	case ABS_DISTANCE:
141		axis = LIBINPUT_TABLET_TOOL_AXIS_DISTANCE;
142		break;
143	case ABS_PRESSURE:
144		axis = LIBINPUT_TABLET_TOOL_AXIS_PRESSURE;
145		break;
146	case ABS_TILT_X:
147		axis = LIBINPUT_TABLET_TOOL_AXIS_TILT_X;
148		break;
149	case ABS_TILT_Y:
150		axis = LIBINPUT_TABLET_TOOL_AXIS_TILT_Y;
151		break;
152	case ABS_WHEEL:
153		axis = LIBINPUT_TABLET_TOOL_AXIS_SLIDER;
154		break;
155	default:
156		axis = LIBINPUT_TABLET_TOOL_AXIS_NONE;
157		break;
158	}
159
160	return axis;
161}
162
163static inline enum libinput_tablet_tool_axis
164rel_evcode_to_axis(const uint32_t evcode)
165{
166	enum libinput_tablet_tool_axis axis;
167
168	switch (evcode) {
169	case REL_WHEEL:
170		axis = LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL;
171		break;
172	default:
173		axis = LIBINPUT_TABLET_TOOL_AXIS_NONE;
174		break;
175	}
176
177	return axis;
178}
179
180static inline uint32_t
181axis_to_evcode(const enum libinput_tablet_tool_axis axis)
182{
183	uint32_t evcode;
184
185	switch (axis) {
186	case LIBINPUT_TABLET_TOOL_AXIS_X:
187		evcode = ABS_X;
188		break;
189	case LIBINPUT_TABLET_TOOL_AXIS_Y:
190		evcode = ABS_Y;
191		break;
192	case LIBINPUT_TABLET_TOOL_AXIS_DISTANCE:
193		evcode = ABS_DISTANCE;
194		break;
195	case LIBINPUT_TABLET_TOOL_AXIS_PRESSURE:
196		evcode = ABS_PRESSURE;
197		break;
198	case LIBINPUT_TABLET_TOOL_AXIS_TILT_X:
199		evcode = ABS_TILT_X;
200		break;
201	case LIBINPUT_TABLET_TOOL_AXIS_TILT_Y:
202		evcode = ABS_TILT_Y;
203		break;
204	case LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z:
205		evcode = ABS_Z;
206		break;
207	case LIBINPUT_TABLET_TOOL_AXIS_SLIDER:
208		evcode = ABS_WHEEL;
209		break;
210	case LIBINPUT_TABLET_TOOL_AXIS_SIZE_MAJOR:
211		evcode = ABS_MT_TOUCH_MAJOR;
212		break;
213	case LIBINPUT_TABLET_TOOL_AXIS_SIZE_MINOR:
214		evcode = ABS_MT_TOUCH_MINOR;
215		break;
216	default:
217		abort();
218	}
219
220	return evcode;
221}
222
223static inline int
224tablet_tool_to_evcode(enum libinput_tablet_tool_type type)
225{
226	int code;
227
228	switch (type) {
229	case LIBINPUT_TABLET_TOOL_TYPE_PEN:	  code = BTN_TOOL_PEN;		break;
230	case LIBINPUT_TABLET_TOOL_TYPE_ERASER:	  code = BTN_TOOL_RUBBER;	break;
231	case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:	  code = BTN_TOOL_BRUSH;	break;
232	case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:	  code = BTN_TOOL_PENCIL;	break;
233	case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:  code = BTN_TOOL_AIRBRUSH;	break;
234	case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:	  code = BTN_TOOL_MOUSE;	break;
235	case LIBINPUT_TABLET_TOOL_TYPE_LENS:	  code = BTN_TOOL_LENS;		break;
236	default:
237		abort();
238	}
239
240	return code;
241}
242
243static inline const char *
244tablet_tool_type_to_string(enum libinput_tablet_tool_type type)
245{
246	const char *str;
247
248	switch (type) {
249	case LIBINPUT_TABLET_TOOL_TYPE_PEN:	  str = "pen";		break;
250	case LIBINPUT_TABLET_TOOL_TYPE_ERASER:	  str = "eraser";	break;
251	case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:	  str = "brush";	break;
252	case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:	  str = "pencil";	break;
253	case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:  str = "airbrush";	break;
254	case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:	  str = "mouse";	break;
255	case LIBINPUT_TABLET_TOOL_TYPE_LENS:	  str = "lens";		break;
256	default:
257		abort();
258	}
259
260	return str;
261}
262
263static inline struct libinput *
264tablet_libinput_context(const struct tablet_dispatch *tablet)
265{
266	return evdev_libinput_context(tablet->device);
267}
268
269#endif
270