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