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