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