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 36enum 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 52struct button_state { 53 unsigned char bits[NCHARS(KEY_CNT)]; 54}; 55 56struct 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 117static inline struct tablet_dispatch* 118tablet_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 125static inline enum libinput_tablet_tool_axis 126evcode_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 163static inline enum libinput_tablet_tool_axis 164rel_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 180static inline uint32_t 181axis_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 223static inline int 224tablet_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 243static inline const char * 244tablet_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 263static inline struct libinput * 264tablet_libinput_context(const struct tablet_dispatch *tablet) 265{ 266 return evdev_libinput_context(tablet->device); 267} 268 269#endif 270