• 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 	} history;
68 
69 	unsigned char axis_caps[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)];
70 	int current_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1];
71 	int prev_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1];
72 
73 	/* Only used for tablets that don't report serial numbers */
74 	struct list tool_list;
75 
76 	struct button_state button_state;
77 	struct button_state prev_button_state;
78 
79 	uint32_t tool_state;
80 	uint32_t prev_tool_state;
81 
82 	struct {
83 		enum libinput_tablet_tool_type type;
84 		uint32_t id;
85 		uint32_t serial;
86 	} current_tool;
87 
88 	uint32_t cursor_proximity_threshold;
89 
90 	struct libinput_device_config_calibration calibration;
91 
92 	/* The paired touch device on devices with both pen & touch */
93 	struct evdev_device *touch_device;
94 	enum evdev_arbitration_state arbitration;
95 
96 	struct {
97 		/* The device locked for rotation */
98 		struct evdev_device *touch_device;
99 		/* Last known left-handed state of the touchpad */
100 		bool touch_device_left_handed_state;
101 		bool rotate;
102 		bool want_rotate;
103 	} rotation;
104 
105 	struct {
106 		bool need_to_force_prox_out;
107 		struct libinput_timer prox_out_timer;
108 		bool proximity_out_forced;
109 		uint64_t last_event_time;
110 
111 		/* true while injecting BTN_TOOL_PEN events */
112 		bool proximity_out_in_progress;
113 	} quirks;
114 };
115 
116 static inline struct tablet_dispatch*
tablet_dispatch(struct evdev_dispatch * dispatch)117 tablet_dispatch(struct evdev_dispatch *dispatch)
118 {
119 	evdev_verify_dispatch_type(dispatch, DISPATCH_TABLET);
120 
121 	return container_of(dispatch, struct tablet_dispatch, base);
122 }
123 
124 static inline enum libinput_tablet_tool_axis
evcode_to_axis(const uint32_t evcode)125 evcode_to_axis(const uint32_t evcode)
126 {
127 	enum libinput_tablet_tool_axis axis;
128 
129 	switch (evcode) {
130 	case ABS_X:
131 		axis = LIBINPUT_TABLET_TOOL_AXIS_X;
132 		break;
133 	case ABS_Y:
134 		axis = LIBINPUT_TABLET_TOOL_AXIS_Y;
135 		break;
136 	case ABS_Z:
137 		axis = LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z;
138 		break;
139 	case ABS_DISTANCE:
140 		axis = LIBINPUT_TABLET_TOOL_AXIS_DISTANCE;
141 		break;
142 	case ABS_PRESSURE:
143 		axis = LIBINPUT_TABLET_TOOL_AXIS_PRESSURE;
144 		break;
145 	case ABS_TILT_X:
146 		axis = LIBINPUT_TABLET_TOOL_AXIS_TILT_X;
147 		break;
148 	case ABS_TILT_Y:
149 		axis = LIBINPUT_TABLET_TOOL_AXIS_TILT_Y;
150 		break;
151 	case ABS_WHEEL:
152 		axis = LIBINPUT_TABLET_TOOL_AXIS_SLIDER;
153 		break;
154 	default:
155 		axis = LIBINPUT_TABLET_TOOL_AXIS_NONE;
156 		break;
157 	}
158 
159 	return axis;
160 }
161 
162 static inline enum libinput_tablet_tool_axis
rel_evcode_to_axis(const uint32_t evcode)163 rel_evcode_to_axis(const uint32_t evcode)
164 {
165 	enum libinput_tablet_tool_axis axis;
166 
167 	switch (evcode) {
168 	case REL_WHEEL:
169 		axis = LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL;
170 		break;
171 	default:
172 		axis = LIBINPUT_TABLET_TOOL_AXIS_NONE;
173 		break;
174 	}
175 
176 	return axis;
177 }
178 
179 static inline uint32_t
axis_to_evcode(const enum libinput_tablet_tool_axis axis)180 axis_to_evcode(const enum libinput_tablet_tool_axis axis)
181 {
182 	uint32_t evcode;
183 
184 	switch (axis) {
185 	case LIBINPUT_TABLET_TOOL_AXIS_X:
186 		evcode = ABS_X;
187 		break;
188 	case LIBINPUT_TABLET_TOOL_AXIS_Y:
189 		evcode = ABS_Y;
190 		break;
191 	case LIBINPUT_TABLET_TOOL_AXIS_DISTANCE:
192 		evcode = ABS_DISTANCE;
193 		break;
194 	case LIBINPUT_TABLET_TOOL_AXIS_PRESSURE:
195 		evcode = ABS_PRESSURE;
196 		break;
197 	case LIBINPUT_TABLET_TOOL_AXIS_TILT_X:
198 		evcode = ABS_TILT_X;
199 		break;
200 	case LIBINPUT_TABLET_TOOL_AXIS_TILT_Y:
201 		evcode = ABS_TILT_Y;
202 		break;
203 	case LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z:
204 		evcode = ABS_Z;
205 		break;
206 	case LIBINPUT_TABLET_TOOL_AXIS_SLIDER:
207 		evcode = ABS_WHEEL;
208 		break;
209 	case LIBINPUT_TABLET_TOOL_AXIS_SIZE_MAJOR:
210 		evcode = ABS_MT_TOUCH_MAJOR;
211 		break;
212 	case LIBINPUT_TABLET_TOOL_AXIS_SIZE_MINOR:
213 		evcode = ABS_MT_TOUCH_MINOR;
214 		break;
215 	default:
216 		abort();
217 	}
218 
219 	return evcode;
220 }
221 
222 static inline int
tablet_tool_to_evcode(enum libinput_tablet_tool_type type)223 tablet_tool_to_evcode(enum libinput_tablet_tool_type type)
224 {
225 	int code;
226 
227 	switch (type) {
228 	case LIBINPUT_TABLET_TOOL_TYPE_PEN:	  code = BTN_TOOL_PEN;		break;
229 	case LIBINPUT_TABLET_TOOL_TYPE_ERASER:	  code = BTN_TOOL_RUBBER;	break;
230 	case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:	  code = BTN_TOOL_BRUSH;	break;
231 	case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:	  code = BTN_TOOL_PENCIL;	break;
232 	case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:  code = BTN_TOOL_AIRBRUSH;	break;
233 	case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:	  code = BTN_TOOL_MOUSE;	break;
234 	case LIBINPUT_TABLET_TOOL_TYPE_LENS:	  code = BTN_TOOL_LENS;		break;
235 	default:
236 		abort();
237 	}
238 
239 	return code;
240 }
241 
242 static inline const char *
tablet_tool_type_to_string(enum libinput_tablet_tool_type type)243 tablet_tool_type_to_string(enum libinput_tablet_tool_type type)
244 {
245 	const char *str;
246 
247 	switch (type) {
248 	case LIBINPUT_TABLET_TOOL_TYPE_PEN:	  str = "pen";		break;
249 	case LIBINPUT_TABLET_TOOL_TYPE_ERASER:	  str = "eraser";	break;
250 	case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:	  str = "brush";	break;
251 	case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:	  str = "pencil";	break;
252 	case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:  str = "airbrush";	break;
253 	case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:	  str = "mouse";	break;
254 	case LIBINPUT_TABLET_TOOL_TYPE_LENS:	  str = "lens";		break;
255 	default:
256 		abort();
257 	}
258 
259 	return str;
260 }
261 
262 static inline struct libinput *
tablet_libinput_context(const struct tablet_dispatch * tablet)263 tablet_libinput_context(const struct tablet_dispatch *tablet)
264 {
265 	return evdev_libinput_context(tablet->device);
266 }
267 
268 #endif
269