• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
36 enum 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 
52 struct button_state {
53 	unsigned char bits[NCHARS(KEY_CNT)];
54 };
55 
56 struct 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 
117 static inline struct tablet_dispatch*
tablet_dispatch(struct evdev_dispatch * dispatch)118 tablet_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 
125 static inline enum libinput_tablet_tool_axis
evcode_to_axis(const uint32_t evcode)126 evcode_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 
163 static inline enum libinput_tablet_tool_axis
rel_evcode_to_axis(const uint32_t evcode)164 rel_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 
180 static inline uint32_t
axis_to_evcode(const enum libinput_tablet_tool_axis axis)181 axis_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 
223 static inline int
tablet_tool_to_evcode(enum libinput_tablet_tool_type type)224 tablet_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 
243 static inline const char *
tablet_tool_type_to_string(enum libinput_tablet_tool_type type)244 tablet_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 
263 static inline struct libinput *
tablet_libinput_context(const struct tablet_dispatch * tablet)264 tablet_libinput_context(const struct tablet_dispatch *tablet)
265 {
266 	return evdev_libinput_context(tablet->device);
267 }
268 
269 #endif
270