1a46c0ec8Sopenharmony_ci/* 2a46c0ec8Sopenharmony_ci * Copyright © 2014 Red Hat, Inc. 3a46c0ec8Sopenharmony_ci * 4a46c0ec8Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5a46c0ec8Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6a46c0ec8Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7a46c0ec8Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8a46c0ec8Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9a46c0ec8Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10a46c0ec8Sopenharmony_ci * 11a46c0ec8Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12a46c0ec8Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13a46c0ec8Sopenharmony_ci * Software. 14a46c0ec8Sopenharmony_ci * 15a46c0ec8Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16a46c0ec8Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17a46c0ec8Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18a46c0ec8Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19a46c0ec8Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20a46c0ec8Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21a46c0ec8Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 22a46c0ec8Sopenharmony_ci */ 23a46c0ec8Sopenharmony_ci 24a46c0ec8Sopenharmony_ci#include <config.h> 25a46c0ec8Sopenharmony_ci 26a46c0ec8Sopenharmony_ci#include <assert.h> 27a46c0ec8Sopenharmony_ci#include <errno.h> 28a46c0ec8Sopenharmony_ci#include <fcntl.h> 29a46c0ec8Sopenharmony_ci#include <fnmatch.h> 30a46c0ec8Sopenharmony_ci#include <getopt.h> 31a46c0ec8Sopenharmony_ci#include <limits.h> 32a46c0ec8Sopenharmony_ci#include <stdio.h> 33a46c0ec8Sopenharmony_ci#include <stdlib.h> 34a46c0ec8Sopenharmony_ci#include <string.h> 35a46c0ec8Sopenharmony_ci#include <sys/stat.h> 36a46c0ec8Sopenharmony_ci#include <libudev.h> 37a46c0ec8Sopenharmony_ci#include <unistd.h> 38a46c0ec8Sopenharmony_ci 39a46c0ec8Sopenharmony_ci#include <libevdev/libevdev.h> 40a46c0ec8Sopenharmony_ci 41a46c0ec8Sopenharmony_ci#include "builddir.h" 42a46c0ec8Sopenharmony_ci#include "shared.h" 43a46c0ec8Sopenharmony_ci#include "util-macros.h" 44a46c0ec8Sopenharmony_ci#include "util-strings.h" 45a46c0ec8Sopenharmony_ci 46a46c0ec8Sopenharmony_cistatic uint32_t dispatch_counter = 0; 47a46c0ec8Sopenharmony_ci 48a46c0ec8Sopenharmony_civoid 49a46c0ec8Sopenharmony_citools_dispatch(struct libinput *libinput) 50a46c0ec8Sopenharmony_ci{ 51a46c0ec8Sopenharmony_ci dispatch_counter++; 52a46c0ec8Sopenharmony_ci libinput_dispatch(libinput); 53a46c0ec8Sopenharmony_ci} 54a46c0ec8Sopenharmony_ci 55a46c0ec8Sopenharmony_ciLIBINPUT_ATTRIBUTE_PRINTF(3, 0) 56a46c0ec8Sopenharmony_cistatic void 57a46c0ec8Sopenharmony_cilog_handler(struct libinput *li, 58a46c0ec8Sopenharmony_ci enum libinput_log_priority priority, 59a46c0ec8Sopenharmony_ci const char *format, 60a46c0ec8Sopenharmony_ci va_list args) 61a46c0ec8Sopenharmony_ci{ 62a46c0ec8Sopenharmony_ci static int is_tty = -1; 63a46c0ec8Sopenharmony_ci static uint32_t last_dispatch_no = 0; 64a46c0ec8Sopenharmony_ci static bool color_toggle = false; 65a46c0ec8Sopenharmony_ci 66a46c0ec8Sopenharmony_ci if (is_tty == -1) 67a46c0ec8Sopenharmony_ci is_tty = isatty(STDOUT_FILENO); 68a46c0ec8Sopenharmony_ci 69a46c0ec8Sopenharmony_ci if (is_tty) { 70a46c0ec8Sopenharmony_ci if (priority >= LIBINPUT_LOG_PRIORITY_ERROR) { 71a46c0ec8Sopenharmony_ci printf(ANSI_RED); 72a46c0ec8Sopenharmony_ci } else if (priority >= LIBINPUT_LOG_PRIORITY_INFO) { 73a46c0ec8Sopenharmony_ci printf(ANSI_HIGHLIGHT); 74a46c0ec8Sopenharmony_ci } else if (priority == LIBINPUT_LOG_PRIORITY_DEBUG) { 75a46c0ec8Sopenharmony_ci if (dispatch_counter != last_dispatch_no) 76a46c0ec8Sopenharmony_ci color_toggle = !color_toggle; 77a46c0ec8Sopenharmony_ci uint8_t r = 0, 78a46c0ec8Sopenharmony_ci g = 135, 79a46c0ec8Sopenharmony_ci b = 95 + (color_toggle ? 80 :0); 80a46c0ec8Sopenharmony_ci printf("\x1B[38;2;%u;%u;%um", r, g, b); 81a46c0ec8Sopenharmony_ci } 82a46c0ec8Sopenharmony_ci } 83a46c0ec8Sopenharmony_ci 84a46c0ec8Sopenharmony_ci if (priority < LIBINPUT_LOG_PRIORITY_INFO) { 85a46c0ec8Sopenharmony_ci if (dispatch_counter != last_dispatch_no) { 86a46c0ec8Sopenharmony_ci last_dispatch_no = dispatch_counter; 87a46c0ec8Sopenharmony_ci printf("%4u: ", dispatch_counter); 88a46c0ec8Sopenharmony_ci } else { 89a46c0ec8Sopenharmony_ci printf(" %4s ", "..."); 90a46c0ec8Sopenharmony_ci } 91a46c0ec8Sopenharmony_ci } 92a46c0ec8Sopenharmony_ci vprintf(format, args); 93a46c0ec8Sopenharmony_ci 94a46c0ec8Sopenharmony_ci if (is_tty) 95a46c0ec8Sopenharmony_ci printf(ANSI_NORMAL); 96a46c0ec8Sopenharmony_ci} 97a46c0ec8Sopenharmony_ci 98a46c0ec8Sopenharmony_civoid 99a46c0ec8Sopenharmony_citools_init_options(struct tools_options *options) 100a46c0ec8Sopenharmony_ci{ 101a46c0ec8Sopenharmony_ci memset(options, 0, sizeof(*options)); 102a46c0ec8Sopenharmony_ci options->tapping = -1; 103a46c0ec8Sopenharmony_ci options->tap_map = -1; 104a46c0ec8Sopenharmony_ci options->drag = -1; 105a46c0ec8Sopenharmony_ci options->drag_lock = -1; 106a46c0ec8Sopenharmony_ci options->natural_scroll = -1; 107a46c0ec8Sopenharmony_ci options->left_handed = -1; 108a46c0ec8Sopenharmony_ci options->middlebutton = -1; 109a46c0ec8Sopenharmony_ci options->dwt = -1; 110a46c0ec8Sopenharmony_ci options->dwtp = -1; 111a46c0ec8Sopenharmony_ci options->click_method = -1; 112a46c0ec8Sopenharmony_ci options->scroll_method = -1; 113a46c0ec8Sopenharmony_ci options->scroll_button = -1; 114a46c0ec8Sopenharmony_ci options->scroll_button_lock = -1; 115a46c0ec8Sopenharmony_ci options->speed = 0.0; 116a46c0ec8Sopenharmony_ci options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_NONE; 117a46c0ec8Sopenharmony_ci /* initialize accel args */ 118a46c0ec8Sopenharmony_ci static double points[] = {0.0, 1.0}; 119a46c0ec8Sopenharmony_ci options->custom_points = points; 120a46c0ec8Sopenharmony_ci options->custom_npoints = ARRAY_LENGTH(points); 121a46c0ec8Sopenharmony_ci options->custom_type = LIBINPUT_ACCEL_TYPE_FALLBACK; 122a46c0ec8Sopenharmony_ci options->custom_step = 1.0; 123a46c0ec8Sopenharmony_ci} 124a46c0ec8Sopenharmony_ci 125a46c0ec8Sopenharmony_ciint 126a46c0ec8Sopenharmony_citools_parse_option(int option, 127a46c0ec8Sopenharmony_ci const char *optarg, 128a46c0ec8Sopenharmony_ci struct tools_options *options) 129a46c0ec8Sopenharmony_ci{ 130a46c0ec8Sopenharmony_ci switch(option) { 131a46c0ec8Sopenharmony_ci case OPT_TAP_ENABLE: 132a46c0ec8Sopenharmony_ci options->tapping = 1; 133a46c0ec8Sopenharmony_ci break; 134a46c0ec8Sopenharmony_ci case OPT_TAP_DISABLE: 135a46c0ec8Sopenharmony_ci options->tapping = 0; 136a46c0ec8Sopenharmony_ci break; 137a46c0ec8Sopenharmony_ci case OPT_TAP_MAP: 138a46c0ec8Sopenharmony_ci if (!optarg) 139a46c0ec8Sopenharmony_ci return 1; 140a46c0ec8Sopenharmony_ci 141a46c0ec8Sopenharmony_ci if (streq(optarg, "lrm")) { 142a46c0ec8Sopenharmony_ci options->tap_map = LIBINPUT_CONFIG_TAP_MAP_LRM; 143a46c0ec8Sopenharmony_ci } else if (streq(optarg, "lmr")) { 144a46c0ec8Sopenharmony_ci options->tap_map = LIBINPUT_CONFIG_TAP_MAP_LMR; 145a46c0ec8Sopenharmony_ci } else { 146a46c0ec8Sopenharmony_ci return 1; 147a46c0ec8Sopenharmony_ci } 148a46c0ec8Sopenharmony_ci break; 149a46c0ec8Sopenharmony_ci case OPT_DRAG_ENABLE: 150a46c0ec8Sopenharmony_ci options->drag = 1; 151a46c0ec8Sopenharmony_ci break; 152a46c0ec8Sopenharmony_ci case OPT_DRAG_DISABLE: 153a46c0ec8Sopenharmony_ci options->drag = 0; 154a46c0ec8Sopenharmony_ci break; 155a46c0ec8Sopenharmony_ci case OPT_DRAG_LOCK_ENABLE: 156a46c0ec8Sopenharmony_ci options->drag_lock = 1; 157a46c0ec8Sopenharmony_ci break; 158a46c0ec8Sopenharmony_ci case OPT_DRAG_LOCK_DISABLE: 159a46c0ec8Sopenharmony_ci options->drag_lock = 0; 160a46c0ec8Sopenharmony_ci break; 161a46c0ec8Sopenharmony_ci case OPT_NATURAL_SCROLL_ENABLE: 162a46c0ec8Sopenharmony_ci options->natural_scroll = 1; 163a46c0ec8Sopenharmony_ci break; 164a46c0ec8Sopenharmony_ci case OPT_NATURAL_SCROLL_DISABLE: 165a46c0ec8Sopenharmony_ci options->natural_scroll = 0; 166a46c0ec8Sopenharmony_ci break; 167a46c0ec8Sopenharmony_ci case OPT_LEFT_HANDED_ENABLE: 168a46c0ec8Sopenharmony_ci options->left_handed = 1; 169a46c0ec8Sopenharmony_ci break; 170a46c0ec8Sopenharmony_ci case OPT_LEFT_HANDED_DISABLE: 171a46c0ec8Sopenharmony_ci options->left_handed = 0; 172a46c0ec8Sopenharmony_ci break; 173a46c0ec8Sopenharmony_ci case OPT_MIDDLEBUTTON_ENABLE: 174a46c0ec8Sopenharmony_ci options->middlebutton = 1; 175a46c0ec8Sopenharmony_ci break; 176a46c0ec8Sopenharmony_ci case OPT_MIDDLEBUTTON_DISABLE: 177a46c0ec8Sopenharmony_ci options->middlebutton = 0; 178a46c0ec8Sopenharmony_ci break; 179a46c0ec8Sopenharmony_ci case OPT_DWT_ENABLE: 180a46c0ec8Sopenharmony_ci options->dwt = LIBINPUT_CONFIG_DWT_ENABLED; 181a46c0ec8Sopenharmony_ci break; 182a46c0ec8Sopenharmony_ci case OPT_DWT_DISABLE: 183a46c0ec8Sopenharmony_ci options->dwt = LIBINPUT_CONFIG_DWT_DISABLED; 184a46c0ec8Sopenharmony_ci break; 185a46c0ec8Sopenharmony_ci case OPT_DWTP_ENABLE: 186a46c0ec8Sopenharmony_ci options->dwtp = LIBINPUT_CONFIG_DWTP_ENABLED; 187a46c0ec8Sopenharmony_ci break; 188a46c0ec8Sopenharmony_ci case OPT_DWTP_DISABLE: 189a46c0ec8Sopenharmony_ci options->dwtp = LIBINPUT_CONFIG_DWTP_DISABLED; 190a46c0ec8Sopenharmony_ci break; 191a46c0ec8Sopenharmony_ci case OPT_CLICK_METHOD: 192a46c0ec8Sopenharmony_ci if (!optarg) 193a46c0ec8Sopenharmony_ci return 1; 194a46c0ec8Sopenharmony_ci 195a46c0ec8Sopenharmony_ci if (streq(optarg, "none")) { 196a46c0ec8Sopenharmony_ci options->click_method = 197a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_CLICK_METHOD_NONE; 198a46c0ec8Sopenharmony_ci } else if (streq(optarg, "clickfinger")) { 199a46c0ec8Sopenharmony_ci options->click_method = 200a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER; 201a46c0ec8Sopenharmony_ci } else if (streq(optarg, "buttonareas")) { 202a46c0ec8Sopenharmony_ci options->click_method = 203a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; 204a46c0ec8Sopenharmony_ci } else { 205a46c0ec8Sopenharmony_ci return 1; 206a46c0ec8Sopenharmony_ci } 207a46c0ec8Sopenharmony_ci break; 208a46c0ec8Sopenharmony_ci case OPT_SCROLL_METHOD: 209a46c0ec8Sopenharmony_ci if (!optarg) 210a46c0ec8Sopenharmony_ci return 1; 211a46c0ec8Sopenharmony_ci 212a46c0ec8Sopenharmony_ci if (streq(optarg, "none")) { 213a46c0ec8Sopenharmony_ci options->scroll_method = 214a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_SCROLL_NO_SCROLL; 215a46c0ec8Sopenharmony_ci } else if (streq(optarg, "twofinger")) { 216a46c0ec8Sopenharmony_ci options->scroll_method = 217a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_SCROLL_2FG; 218a46c0ec8Sopenharmony_ci } else if (streq(optarg, "edge")) { 219a46c0ec8Sopenharmony_ci options->scroll_method = 220a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_SCROLL_EDGE; 221a46c0ec8Sopenharmony_ci } else if (streq(optarg, "button")) { 222a46c0ec8Sopenharmony_ci options->scroll_method = 223a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN; 224a46c0ec8Sopenharmony_ci } else { 225a46c0ec8Sopenharmony_ci return 1; 226a46c0ec8Sopenharmony_ci } 227a46c0ec8Sopenharmony_ci break; 228a46c0ec8Sopenharmony_ci case OPT_SCROLL_BUTTON: 229a46c0ec8Sopenharmony_ci if (!optarg) { 230a46c0ec8Sopenharmony_ci return 1; 231a46c0ec8Sopenharmony_ci } 232a46c0ec8Sopenharmony_ci options->scroll_button = 233a46c0ec8Sopenharmony_ci libevdev_event_code_from_name(EV_KEY, 234a46c0ec8Sopenharmony_ci optarg); 235a46c0ec8Sopenharmony_ci if (options->scroll_button == -1) { 236a46c0ec8Sopenharmony_ci fprintf(stderr, 237a46c0ec8Sopenharmony_ci "Invalid button %s\n", 238a46c0ec8Sopenharmony_ci optarg); 239a46c0ec8Sopenharmony_ci return 1; 240a46c0ec8Sopenharmony_ci } 241a46c0ec8Sopenharmony_ci break; 242a46c0ec8Sopenharmony_ci case OPT_SCROLL_BUTTON_LOCK_ENABLE: 243a46c0ec8Sopenharmony_ci options->scroll_button_lock = true; 244a46c0ec8Sopenharmony_ci break; 245a46c0ec8Sopenharmony_ci case OPT_SCROLL_BUTTON_LOCK_DISABLE: 246a46c0ec8Sopenharmony_ci options->scroll_button_lock = false; 247a46c0ec8Sopenharmony_ci break; 248a46c0ec8Sopenharmony_ci case OPT_SPEED: 249a46c0ec8Sopenharmony_ci if (!optarg) 250a46c0ec8Sopenharmony_ci return 1; 251a46c0ec8Sopenharmony_ci options->speed = atof(optarg); 252a46c0ec8Sopenharmony_ci break; 253a46c0ec8Sopenharmony_ci case OPT_PROFILE: 254a46c0ec8Sopenharmony_ci if (!optarg) 255a46c0ec8Sopenharmony_ci return 1; 256a46c0ec8Sopenharmony_ci 257a46c0ec8Sopenharmony_ci if (streq(optarg, "adaptive")) 258a46c0ec8Sopenharmony_ci options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE; 259a46c0ec8Sopenharmony_ci else if (streq(optarg, "flat")) 260a46c0ec8Sopenharmony_ci options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; 261a46c0ec8Sopenharmony_ci else if (streq(optarg, "custom")) 262a46c0ec8Sopenharmony_ci options->profile = LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM; 263a46c0ec8Sopenharmony_ci else 264a46c0ec8Sopenharmony_ci return 1; 265a46c0ec8Sopenharmony_ci break; 266a46c0ec8Sopenharmony_ci case OPT_DISABLE_SENDEVENTS: 267a46c0ec8Sopenharmony_ci if (!optarg) 268a46c0ec8Sopenharmony_ci return 1; 269a46c0ec8Sopenharmony_ci 270a46c0ec8Sopenharmony_ci snprintf(options->disable_pattern, 271a46c0ec8Sopenharmony_ci sizeof(options->disable_pattern), 272a46c0ec8Sopenharmony_ci "%s", 273a46c0ec8Sopenharmony_ci optarg); 274a46c0ec8Sopenharmony_ci break; 275a46c0ec8Sopenharmony_ci case OPT_APPLY_TO: 276a46c0ec8Sopenharmony_ci if (!optarg) 277a46c0ec8Sopenharmony_ci return 1; 278a46c0ec8Sopenharmony_ci 279a46c0ec8Sopenharmony_ci snprintf(options->match, 280a46c0ec8Sopenharmony_ci sizeof(options->match), 281a46c0ec8Sopenharmony_ci "%s", 282a46c0ec8Sopenharmony_ci optarg); 283a46c0ec8Sopenharmony_ci break; 284a46c0ec8Sopenharmony_ci case OPT_CUSTOM_POINTS: 285a46c0ec8Sopenharmony_ci if (!optarg) 286a46c0ec8Sopenharmony_ci return 1; 287a46c0ec8Sopenharmony_ci options->custom_points = double_array_from_string(optarg, 288a46c0ec8Sopenharmony_ci ";", 289a46c0ec8Sopenharmony_ci &options->custom_npoints); 290a46c0ec8Sopenharmony_ci if (!options->custom_points || options->custom_npoints < 2) { 291a46c0ec8Sopenharmony_ci fprintf(stderr, 292a46c0ec8Sopenharmony_ci "Invalid --set-custom-points\n" 293a46c0ec8Sopenharmony_ci "Please provide at least 2 points separated by a semicolon\n" 294a46c0ec8Sopenharmony_ci " e.g. --set-custom-points=\"1.0;1.5\"\n"); 295a46c0ec8Sopenharmony_ci return 1; 296a46c0ec8Sopenharmony_ci } 297a46c0ec8Sopenharmony_ci break; 298a46c0ec8Sopenharmony_ci case OPT_CUSTOM_STEP: 299a46c0ec8Sopenharmony_ci if (!optarg) 300a46c0ec8Sopenharmony_ci return 1; 301a46c0ec8Sopenharmony_ci options->custom_step = strtod(optarg, NULL); 302a46c0ec8Sopenharmony_ci break; 303a46c0ec8Sopenharmony_ci case OPT_CUSTOM_TYPE: 304a46c0ec8Sopenharmony_ci if (!optarg) 305a46c0ec8Sopenharmony_ci return 1; 306a46c0ec8Sopenharmony_ci if (streq(optarg, "fallback")) 307a46c0ec8Sopenharmony_ci options->custom_type = LIBINPUT_ACCEL_TYPE_FALLBACK; 308a46c0ec8Sopenharmony_ci else if (streq(optarg, "motion")) 309a46c0ec8Sopenharmony_ci options->custom_type = LIBINPUT_ACCEL_TYPE_MOTION; 310a46c0ec8Sopenharmony_ci else if (streq(optarg, "scroll")) 311a46c0ec8Sopenharmony_ci options->custom_type = LIBINPUT_ACCEL_TYPE_SCROLL; 312a46c0ec8Sopenharmony_ci else { 313a46c0ec8Sopenharmony_ci fprintf(stderr, "Invalid --set-custom-type\n" 314a46c0ec8Sopenharmony_ci "Valid custom types: fallback|motion|scroll\n"); 315a46c0ec8Sopenharmony_ci return 1; 316a46c0ec8Sopenharmony_ci } 317a46c0ec8Sopenharmony_ci break; 318a46c0ec8Sopenharmony_ci case OPT_ROTATION_ANGLE: 319a46c0ec8Sopenharmony_ci if (!optarg) 320a46c0ec8Sopenharmony_ci return 1; 321a46c0ec8Sopenharmony_ci 322a46c0ec8Sopenharmony_ci if (!safe_atou(optarg, &options->angle)) { 323a46c0ec8Sopenharmony_ci fprintf(stderr, "Invalid --set-rotation-angle value\n"); 324a46c0ec8Sopenharmony_ci return 1; 325a46c0ec8Sopenharmony_ci } 326a46c0ec8Sopenharmony_ci } 327a46c0ec8Sopenharmony_ci return 0; 328a46c0ec8Sopenharmony_ci} 329a46c0ec8Sopenharmony_ci 330a46c0ec8Sopenharmony_cistatic int 331a46c0ec8Sopenharmony_ciopen_restricted(const char *path, int flags, void *user_data) 332a46c0ec8Sopenharmony_ci{ 333a46c0ec8Sopenharmony_ci bool *grab = user_data; 334a46c0ec8Sopenharmony_ci int fd = open(path, flags); 335a46c0ec8Sopenharmony_ci 336a46c0ec8Sopenharmony_ci if (fd < 0) 337a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to open %s (%s)\n", 338a46c0ec8Sopenharmony_ci path, strerror(errno)); 339a46c0ec8Sopenharmony_ci else if (grab && *grab && ioctl(fd, EVIOCGRAB, (void*)1) == -1) 340a46c0ec8Sopenharmony_ci fprintf(stderr, "Grab requested, but failed for %s (%s)\n", 341a46c0ec8Sopenharmony_ci path, strerror(errno)); 342a46c0ec8Sopenharmony_ci 343a46c0ec8Sopenharmony_ci return fd < 0 ? -errno : fd; 344a46c0ec8Sopenharmony_ci} 345a46c0ec8Sopenharmony_ci 346a46c0ec8Sopenharmony_cistatic void 347a46c0ec8Sopenharmony_ciclose_restricted(int fd, void *user_data) 348a46c0ec8Sopenharmony_ci{ 349a46c0ec8Sopenharmony_ci close(fd); 350a46c0ec8Sopenharmony_ci} 351a46c0ec8Sopenharmony_ci 352a46c0ec8Sopenharmony_cistatic const struct libinput_interface interface = { 353a46c0ec8Sopenharmony_ci .open_restricted = open_restricted, 354a46c0ec8Sopenharmony_ci .close_restricted = close_restricted, 355a46c0ec8Sopenharmony_ci}; 356a46c0ec8Sopenharmony_ci 357a46c0ec8Sopenharmony_cistatic struct libinput * 358a46c0ec8Sopenharmony_citools_open_udev(const char *seat, bool verbose, bool *grab) 359a46c0ec8Sopenharmony_ci{ 360a46c0ec8Sopenharmony_ci struct libinput *li; 361a46c0ec8Sopenharmony_ci struct udev *udev = udev_new(); 362a46c0ec8Sopenharmony_ci 363a46c0ec8Sopenharmony_ci if (!udev) { 364a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to initialize udev\n"); 365a46c0ec8Sopenharmony_ci return NULL; 366a46c0ec8Sopenharmony_ci } 367a46c0ec8Sopenharmony_ci 368a46c0ec8Sopenharmony_ci li = libinput_udev_create_context(&interface, grab, udev); 369a46c0ec8Sopenharmony_ci if (!li) { 370a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to initialize context from udev\n"); 371a46c0ec8Sopenharmony_ci goto out; 372a46c0ec8Sopenharmony_ci } 373a46c0ec8Sopenharmony_ci 374a46c0ec8Sopenharmony_ci libinput_log_set_handler(li, log_handler); 375a46c0ec8Sopenharmony_ci if (verbose) 376a46c0ec8Sopenharmony_ci libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG); 377a46c0ec8Sopenharmony_ci 378a46c0ec8Sopenharmony_ci if (libinput_udev_assign_seat(li, seat)) { 379a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to set seat\n"); 380a46c0ec8Sopenharmony_ci libinput_unref(li); 381a46c0ec8Sopenharmony_ci li = NULL; 382a46c0ec8Sopenharmony_ci goto out; 383a46c0ec8Sopenharmony_ci } 384a46c0ec8Sopenharmony_ci 385a46c0ec8Sopenharmony_ciout: 386a46c0ec8Sopenharmony_ci udev_unref(udev); 387a46c0ec8Sopenharmony_ci return li; 388a46c0ec8Sopenharmony_ci} 389a46c0ec8Sopenharmony_ci 390a46c0ec8Sopenharmony_cistatic struct libinput * 391a46c0ec8Sopenharmony_citools_open_device(const char **paths, bool verbose, bool *grab) 392a46c0ec8Sopenharmony_ci{ 393a46c0ec8Sopenharmony_ci struct libinput_device *device; 394a46c0ec8Sopenharmony_ci struct libinput *li; 395a46c0ec8Sopenharmony_ci const char **p = paths; 396a46c0ec8Sopenharmony_ci 397a46c0ec8Sopenharmony_ci li = libinput_path_create_context(&interface, grab); 398a46c0ec8Sopenharmony_ci if (!li) { 399a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to initialize path context\n"); 400a46c0ec8Sopenharmony_ci return NULL; 401a46c0ec8Sopenharmony_ci } 402a46c0ec8Sopenharmony_ci 403a46c0ec8Sopenharmony_ci if (verbose) { 404a46c0ec8Sopenharmony_ci libinput_log_set_handler(li, log_handler); 405a46c0ec8Sopenharmony_ci libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG); 406a46c0ec8Sopenharmony_ci } 407a46c0ec8Sopenharmony_ci 408a46c0ec8Sopenharmony_ci while (*p) { 409a46c0ec8Sopenharmony_ci device = libinput_path_add_device(li, *p); 410a46c0ec8Sopenharmony_ci if (!device) { 411a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to initialize device %s\n", *p); 412a46c0ec8Sopenharmony_ci libinput_unref(li); 413a46c0ec8Sopenharmony_ci li = NULL; 414a46c0ec8Sopenharmony_ci break; 415a46c0ec8Sopenharmony_ci } 416a46c0ec8Sopenharmony_ci p++; 417a46c0ec8Sopenharmony_ci } 418a46c0ec8Sopenharmony_ci 419a46c0ec8Sopenharmony_ci return li; 420a46c0ec8Sopenharmony_ci} 421a46c0ec8Sopenharmony_ci 422a46c0ec8Sopenharmony_cistatic void 423a46c0ec8Sopenharmony_citools_setenv_quirks_dir(void) 424a46c0ec8Sopenharmony_ci{ 425a46c0ec8Sopenharmony_ci char *builddir = builddir_lookup(); 426a46c0ec8Sopenharmony_ci if (builddir) { 427a46c0ec8Sopenharmony_ci setenv("LIBINPUT_QUIRKS_DIR", LIBINPUT_QUIRKS_SRCDIR, 0); 428a46c0ec8Sopenharmony_ci free(builddir); 429a46c0ec8Sopenharmony_ci } 430a46c0ec8Sopenharmony_ci} 431a46c0ec8Sopenharmony_ci 432a46c0ec8Sopenharmony_cistruct libinput * 433a46c0ec8Sopenharmony_citools_open_backend(enum tools_backend which, 434a46c0ec8Sopenharmony_ci const char **seat_or_device, 435a46c0ec8Sopenharmony_ci bool verbose, 436a46c0ec8Sopenharmony_ci bool *grab) 437a46c0ec8Sopenharmony_ci{ 438a46c0ec8Sopenharmony_ci struct libinput *li; 439a46c0ec8Sopenharmony_ci 440a46c0ec8Sopenharmony_ci tools_setenv_quirks_dir(); 441a46c0ec8Sopenharmony_ci 442a46c0ec8Sopenharmony_ci switch (which) { 443a46c0ec8Sopenharmony_ci case BACKEND_UDEV: 444a46c0ec8Sopenharmony_ci li = tools_open_udev(seat_or_device[0], verbose, grab); 445a46c0ec8Sopenharmony_ci break; 446a46c0ec8Sopenharmony_ci case BACKEND_DEVICE: 447a46c0ec8Sopenharmony_ci li = tools_open_device(seat_or_device, verbose, grab); 448a46c0ec8Sopenharmony_ci break; 449a46c0ec8Sopenharmony_ci default: 450a46c0ec8Sopenharmony_ci abort(); 451a46c0ec8Sopenharmony_ci } 452a46c0ec8Sopenharmony_ci 453a46c0ec8Sopenharmony_ci return li; 454a46c0ec8Sopenharmony_ci} 455a46c0ec8Sopenharmony_ci 456a46c0ec8Sopenharmony_civoid 457a46c0ec8Sopenharmony_citools_device_apply_config(struct libinput_device *device, 458a46c0ec8Sopenharmony_ci struct tools_options *options) 459a46c0ec8Sopenharmony_ci{ 460a46c0ec8Sopenharmony_ci const char *name = libinput_device_get_name(device); 461a46c0ec8Sopenharmony_ci 462a46c0ec8Sopenharmony_ci if (libinput_device_config_send_events_get_modes(device) & 463a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_SEND_EVENTS_DISABLED && 464a46c0ec8Sopenharmony_ci fnmatch(options->disable_pattern, name, 0) != FNM_NOMATCH) { 465a46c0ec8Sopenharmony_ci libinput_device_config_send_events_set_mode(device, 466a46c0ec8Sopenharmony_ci LIBINPUT_CONFIG_SEND_EVENTS_DISABLED); 467a46c0ec8Sopenharmony_ci } 468a46c0ec8Sopenharmony_ci 469a46c0ec8Sopenharmony_ci if (strlen(options->match) > 0 && 470a46c0ec8Sopenharmony_ci fnmatch(options->match, name, 0) == FNM_NOMATCH) 471a46c0ec8Sopenharmony_ci return; 472a46c0ec8Sopenharmony_ci 473a46c0ec8Sopenharmony_ci if (options->tapping != -1) 474a46c0ec8Sopenharmony_ci libinput_device_config_tap_set_enabled(device, options->tapping); 475a46c0ec8Sopenharmony_ci if (options->tap_map != (enum libinput_config_tap_button_map)-1) 476a46c0ec8Sopenharmony_ci libinput_device_config_tap_set_button_map(device, 477a46c0ec8Sopenharmony_ci options->tap_map); 478a46c0ec8Sopenharmony_ci if (options->drag != -1) 479a46c0ec8Sopenharmony_ci libinput_device_config_tap_set_drag_enabled(device, 480a46c0ec8Sopenharmony_ci options->drag); 481a46c0ec8Sopenharmony_ci if (options->drag_lock != -1) 482a46c0ec8Sopenharmony_ci libinput_device_config_tap_set_drag_lock_enabled(device, 483a46c0ec8Sopenharmony_ci options->drag_lock); 484a46c0ec8Sopenharmony_ci if (options->natural_scroll != -1) 485a46c0ec8Sopenharmony_ci libinput_device_config_scroll_set_natural_scroll_enabled(device, 486a46c0ec8Sopenharmony_ci options->natural_scroll); 487a46c0ec8Sopenharmony_ci if (options->left_handed != -1) 488a46c0ec8Sopenharmony_ci libinput_device_config_left_handed_set(device, options->left_handed); 489a46c0ec8Sopenharmony_ci if (options->middlebutton != -1) 490a46c0ec8Sopenharmony_ci libinput_device_config_middle_emulation_set_enabled(device, 491a46c0ec8Sopenharmony_ci options->middlebutton); 492a46c0ec8Sopenharmony_ci 493a46c0ec8Sopenharmony_ci if (options->dwt != -1) 494a46c0ec8Sopenharmony_ci libinput_device_config_dwt_set_enabled(device, options->dwt); 495a46c0ec8Sopenharmony_ci 496a46c0ec8Sopenharmony_ci if (options->dwtp != -1) 497a46c0ec8Sopenharmony_ci libinput_device_config_dwtp_set_enabled(device, options->dwtp); 498a46c0ec8Sopenharmony_ci 499a46c0ec8Sopenharmony_ci if (options->click_method != (enum libinput_config_click_method)-1) 500a46c0ec8Sopenharmony_ci libinput_device_config_click_set_method(device, options->click_method); 501a46c0ec8Sopenharmony_ci 502a46c0ec8Sopenharmony_ci if (options->scroll_method != (enum libinput_config_scroll_method)-1) 503a46c0ec8Sopenharmony_ci libinput_device_config_scroll_set_method(device, 504a46c0ec8Sopenharmony_ci options->scroll_method); 505a46c0ec8Sopenharmony_ci if (options->scroll_button != -1) 506a46c0ec8Sopenharmony_ci libinput_device_config_scroll_set_button(device, 507a46c0ec8Sopenharmony_ci options->scroll_button); 508a46c0ec8Sopenharmony_ci if (options->scroll_button_lock != -1) 509a46c0ec8Sopenharmony_ci libinput_device_config_scroll_set_button_lock(device, 510a46c0ec8Sopenharmony_ci options->scroll_button_lock); 511a46c0ec8Sopenharmony_ci 512a46c0ec8Sopenharmony_ci if (libinput_device_config_accel_is_available(device)) { 513a46c0ec8Sopenharmony_ci libinput_device_config_accel_set_speed(device, 514a46c0ec8Sopenharmony_ci options->speed); 515a46c0ec8Sopenharmony_ci if (options->profile != LIBINPUT_CONFIG_ACCEL_PROFILE_NONE) 516a46c0ec8Sopenharmony_ci libinput_device_config_accel_set_profile(device, 517a46c0ec8Sopenharmony_ci options->profile); 518a46c0ec8Sopenharmony_ci } 519a46c0ec8Sopenharmony_ci 520a46c0ec8Sopenharmony_ci if (options->profile == LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM) { 521a46c0ec8Sopenharmony_ci struct libinput_config_accel *config = 522a46c0ec8Sopenharmony_ci libinput_config_accel_create(LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM); 523a46c0ec8Sopenharmony_ci libinput_config_accel_set_points(config, 524a46c0ec8Sopenharmony_ci options->custom_type, 525a46c0ec8Sopenharmony_ci options->custom_step, 526a46c0ec8Sopenharmony_ci options->custom_npoints, 527a46c0ec8Sopenharmony_ci options->custom_points); 528a46c0ec8Sopenharmony_ci libinput_device_config_accel_apply(device, config); 529a46c0ec8Sopenharmony_ci libinput_config_accel_destroy(config); 530a46c0ec8Sopenharmony_ci } 531a46c0ec8Sopenharmony_ci 532a46c0ec8Sopenharmony_ci if (options->angle != 0) 533a46c0ec8Sopenharmony_ci libinput_device_config_rotation_set_angle(device, options->angle % 360); 534a46c0ec8Sopenharmony_ci} 535a46c0ec8Sopenharmony_ci 536a46c0ec8Sopenharmony_cistatic char* 537a46c0ec8Sopenharmony_cifind_device(const char *udev_tag) 538a46c0ec8Sopenharmony_ci{ 539a46c0ec8Sopenharmony_ci struct udev *udev; 540a46c0ec8Sopenharmony_ci struct udev_enumerate *e = NULL; 541a46c0ec8Sopenharmony_ci struct udev_list_entry *entry = NULL; 542a46c0ec8Sopenharmony_ci struct udev_device *device; 543a46c0ec8Sopenharmony_ci const char *path, *sysname; 544a46c0ec8Sopenharmony_ci char *device_node = NULL; 545a46c0ec8Sopenharmony_ci 546a46c0ec8Sopenharmony_ci udev = udev_new(); 547a46c0ec8Sopenharmony_ci if (!udev) 548a46c0ec8Sopenharmony_ci goto out; 549a46c0ec8Sopenharmony_ci 550a46c0ec8Sopenharmony_ci e = udev_enumerate_new(udev); 551a46c0ec8Sopenharmony_ci udev_enumerate_add_match_subsystem(e, "input"); 552a46c0ec8Sopenharmony_ci udev_enumerate_scan_devices(e); 553a46c0ec8Sopenharmony_ci 554a46c0ec8Sopenharmony_ci udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { 555a46c0ec8Sopenharmony_ci path = udev_list_entry_get_name(entry); 556a46c0ec8Sopenharmony_ci device = udev_device_new_from_syspath(udev, path); 557a46c0ec8Sopenharmony_ci if (!device) 558a46c0ec8Sopenharmony_ci continue; 559a46c0ec8Sopenharmony_ci 560a46c0ec8Sopenharmony_ci sysname = udev_device_get_sysname(device); 561a46c0ec8Sopenharmony_ci if (!strneq("event", sysname, 5)) { 562a46c0ec8Sopenharmony_ci udev_device_unref(device); 563a46c0ec8Sopenharmony_ci continue; 564a46c0ec8Sopenharmony_ci } 565a46c0ec8Sopenharmony_ci 566a46c0ec8Sopenharmony_ci if (udev_device_get_property_value(device, udev_tag)) 567a46c0ec8Sopenharmony_ci device_node = safe_strdup(udev_device_get_devnode(device)); 568a46c0ec8Sopenharmony_ci 569a46c0ec8Sopenharmony_ci udev_device_unref(device); 570a46c0ec8Sopenharmony_ci 571a46c0ec8Sopenharmony_ci if (device_node) 572a46c0ec8Sopenharmony_ci break; 573a46c0ec8Sopenharmony_ci } 574a46c0ec8Sopenharmony_ciout: 575a46c0ec8Sopenharmony_ci udev_enumerate_unref(e); 576a46c0ec8Sopenharmony_ci udev_unref(udev); 577a46c0ec8Sopenharmony_ci 578a46c0ec8Sopenharmony_ci return device_node; 579a46c0ec8Sopenharmony_ci} 580a46c0ec8Sopenharmony_ci 581a46c0ec8Sopenharmony_cibool 582a46c0ec8Sopenharmony_cifind_touchpad_device(char *path, size_t path_len) 583a46c0ec8Sopenharmony_ci{ 584a46c0ec8Sopenharmony_ci char *devnode = find_device("ID_INPUT_TOUCHPAD"); 585a46c0ec8Sopenharmony_ci 586a46c0ec8Sopenharmony_ci if (devnode) { 587a46c0ec8Sopenharmony_ci snprintf(path, path_len, "%s", devnode); 588a46c0ec8Sopenharmony_ci free(devnode); 589a46c0ec8Sopenharmony_ci } 590a46c0ec8Sopenharmony_ci 591a46c0ec8Sopenharmony_ci return devnode != NULL; 592a46c0ec8Sopenharmony_ci} 593a46c0ec8Sopenharmony_ci 594a46c0ec8Sopenharmony_cibool 595a46c0ec8Sopenharmony_ciis_touchpad_device(const char *devnode) 596a46c0ec8Sopenharmony_ci{ 597a46c0ec8Sopenharmony_ci struct udev *udev; 598a46c0ec8Sopenharmony_ci struct udev_device *dev = NULL; 599a46c0ec8Sopenharmony_ci struct stat st; 600a46c0ec8Sopenharmony_ci bool is_touchpad = false; 601a46c0ec8Sopenharmony_ci 602a46c0ec8Sopenharmony_ci if (stat(devnode, &st) < 0) 603a46c0ec8Sopenharmony_ci return false; 604a46c0ec8Sopenharmony_ci 605a46c0ec8Sopenharmony_ci udev = udev_new(); 606a46c0ec8Sopenharmony_ci if (!udev) 607a46c0ec8Sopenharmony_ci goto out; 608a46c0ec8Sopenharmony_ci 609a46c0ec8Sopenharmony_ci dev = udev_device_new_from_devnum(udev, 'c', st.st_rdev); 610a46c0ec8Sopenharmony_ci if (!dev) 611a46c0ec8Sopenharmony_ci goto out; 612a46c0ec8Sopenharmony_ci 613a46c0ec8Sopenharmony_ci is_touchpad = udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD"); 614a46c0ec8Sopenharmony_ciout: 615a46c0ec8Sopenharmony_ci if (dev) 616a46c0ec8Sopenharmony_ci udev_device_unref(dev); 617a46c0ec8Sopenharmony_ci udev_unref(udev); 618a46c0ec8Sopenharmony_ci 619a46c0ec8Sopenharmony_ci return is_touchpad; 620a46c0ec8Sopenharmony_ci} 621a46c0ec8Sopenharmony_ci 622a46c0ec8Sopenharmony_cistatic inline void 623a46c0ec8Sopenharmony_cisetup_path(void) 624a46c0ec8Sopenharmony_ci{ 625a46c0ec8Sopenharmony_ci const char *path = getenv("PATH"); 626a46c0ec8Sopenharmony_ci char new_path[PATH_MAX]; 627a46c0ec8Sopenharmony_ci const char *extra_path = LIBINPUT_TOOL_PATH; 628a46c0ec8Sopenharmony_ci char *builddir = builddir_lookup(); 629a46c0ec8Sopenharmony_ci 630a46c0ec8Sopenharmony_ci snprintf(new_path, 631a46c0ec8Sopenharmony_ci sizeof(new_path), 632a46c0ec8Sopenharmony_ci "%s:%s", 633a46c0ec8Sopenharmony_ci builddir ? builddir : extra_path, 634a46c0ec8Sopenharmony_ci path ? path : ""); 635a46c0ec8Sopenharmony_ci setenv("PATH", new_path, 1); 636a46c0ec8Sopenharmony_ci free(builddir); 637a46c0ec8Sopenharmony_ci} 638a46c0ec8Sopenharmony_ci 639a46c0ec8Sopenharmony_ciint 640a46c0ec8Sopenharmony_citools_exec_command(const char *prefix, int real_argc, char **real_argv) 641a46c0ec8Sopenharmony_ci{ 642a46c0ec8Sopenharmony_ci char *argv[64] = {NULL}; 643a46c0ec8Sopenharmony_ci char executable[128]; 644a46c0ec8Sopenharmony_ci const char *command; 645a46c0ec8Sopenharmony_ci int rc; 646a46c0ec8Sopenharmony_ci 647a46c0ec8Sopenharmony_ci assert((size_t)real_argc < ARRAY_LENGTH(argv)); 648a46c0ec8Sopenharmony_ci 649a46c0ec8Sopenharmony_ci command = real_argv[0]; 650a46c0ec8Sopenharmony_ci 651a46c0ec8Sopenharmony_ci rc = snprintf(executable, 652a46c0ec8Sopenharmony_ci sizeof(executable), 653a46c0ec8Sopenharmony_ci "%s-%s", 654a46c0ec8Sopenharmony_ci prefix, 655a46c0ec8Sopenharmony_ci command); 656a46c0ec8Sopenharmony_ci if (rc >= (int)sizeof(executable)) { 657a46c0ec8Sopenharmony_ci fprintf(stderr, "Failed to assemble command.\n"); 658a46c0ec8Sopenharmony_ci return EXIT_FAILURE; 659a46c0ec8Sopenharmony_ci } 660a46c0ec8Sopenharmony_ci 661a46c0ec8Sopenharmony_ci argv[0] = executable; 662a46c0ec8Sopenharmony_ci for (int i = 1; i < real_argc; i++) 663a46c0ec8Sopenharmony_ci argv[i] = real_argv[i]; 664a46c0ec8Sopenharmony_ci 665a46c0ec8Sopenharmony_ci setup_path(); 666a46c0ec8Sopenharmony_ci 667a46c0ec8Sopenharmony_ci rc = execvp(executable, argv); 668a46c0ec8Sopenharmony_ci if (rc) { 669a46c0ec8Sopenharmony_ci if (errno == ENOENT) { 670a46c0ec8Sopenharmony_ci fprintf(stderr, 671a46c0ec8Sopenharmony_ci "libinput: %s is not installed\n", 672a46c0ec8Sopenharmony_ci command); 673a46c0ec8Sopenharmony_ci return EXIT_INVALID_USAGE; 674a46c0ec8Sopenharmony_ci } 675a46c0ec8Sopenharmony_ci fprintf(stderr, 676a46c0ec8Sopenharmony_ci "Failed to execute '%s' (%s)\n", 677a46c0ec8Sopenharmony_ci command, 678a46c0ec8Sopenharmony_ci strerror(errno)); 679a46c0ec8Sopenharmony_ci } 680a46c0ec8Sopenharmony_ci 681a46c0ec8Sopenharmony_ci return EXIT_FAILURE; 682a46c0ec8Sopenharmony_ci} 683a46c0ec8Sopenharmony_ci 684a46c0ec8Sopenharmony_cistatic void 685a46c0ec8Sopenharmony_cisprintf_event_codes(char *buf, size_t sz, struct quirks *quirks, enum quirk q) 686a46c0ec8Sopenharmony_ci{ 687a46c0ec8Sopenharmony_ci const struct quirk_tuples *t; 688a46c0ec8Sopenharmony_ci size_t off = 0; 689a46c0ec8Sopenharmony_ci int printed; 690a46c0ec8Sopenharmony_ci const char *name; 691a46c0ec8Sopenharmony_ci 692a46c0ec8Sopenharmony_ci quirks_get_tuples(quirks, q, &t); 693a46c0ec8Sopenharmony_ci name = quirk_get_name(q); 694a46c0ec8Sopenharmony_ci printed = snprintf(buf, sz, "%s=", name); 695a46c0ec8Sopenharmony_ci assert(printed != -1); 696a46c0ec8Sopenharmony_ci off += printed; 697a46c0ec8Sopenharmony_ci 698a46c0ec8Sopenharmony_ci for (size_t i = 0; off < sz && i < t->ntuples; i++) { 699a46c0ec8Sopenharmony_ci unsigned int type = t->tuples[i].first; 700a46c0ec8Sopenharmony_ci unsigned int code = t->tuples[i].second; 701a46c0ec8Sopenharmony_ci bool enable = t->tuples[i].third; 702a46c0ec8Sopenharmony_ci 703a46c0ec8Sopenharmony_ci const char *name = libevdev_event_code_get_name(type, code); 704a46c0ec8Sopenharmony_ci 705a46c0ec8Sopenharmony_ci printed = snprintf(buf + off, sz - off, "%c%s;", enable ? '+' : '-', name); 706a46c0ec8Sopenharmony_ci assert(printed != -1); 707a46c0ec8Sopenharmony_ci off += printed; 708a46c0ec8Sopenharmony_ci } 709a46c0ec8Sopenharmony_ci} 710a46c0ec8Sopenharmony_ci 711a46c0ec8Sopenharmony_cistatic void 712a46c0ec8Sopenharmony_cisprintf_input_props(char *buf, size_t sz, struct quirks *quirks, enum quirk q) 713a46c0ec8Sopenharmony_ci{ 714a46c0ec8Sopenharmony_ci const struct quirk_tuples *t; 715a46c0ec8Sopenharmony_ci size_t off = 0; 716a46c0ec8Sopenharmony_ci int printed; 717a46c0ec8Sopenharmony_ci const char *name; 718a46c0ec8Sopenharmony_ci 719a46c0ec8Sopenharmony_ci quirks_get_tuples(quirks, q, &t); 720a46c0ec8Sopenharmony_ci name = quirk_get_name(q); 721a46c0ec8Sopenharmony_ci printed = snprintf(buf, sz, "%s=", name); 722a46c0ec8Sopenharmony_ci assert(printed != -1); 723a46c0ec8Sopenharmony_ci off += printed; 724a46c0ec8Sopenharmony_ci 725a46c0ec8Sopenharmony_ci for (size_t i = 0; off < sz && i < t->ntuples; i++) { 726a46c0ec8Sopenharmony_ci unsigned int prop = t->tuples[i].first; 727a46c0ec8Sopenharmony_ci bool enable = t->tuples[i].second; 728a46c0ec8Sopenharmony_ci 729a46c0ec8Sopenharmony_ci const char *name = libevdev_property_get_name(prop); 730a46c0ec8Sopenharmony_ci 731a46c0ec8Sopenharmony_ci printed = snprintf(buf + off, sz - off, "%c%s;", enable ? '+' : '-', name); 732a46c0ec8Sopenharmony_ci assert(printed != -1); 733a46c0ec8Sopenharmony_ci off += printed; 734a46c0ec8Sopenharmony_ci } 735a46c0ec8Sopenharmony_ci} 736a46c0ec8Sopenharmony_ci 737a46c0ec8Sopenharmony_civoid 738a46c0ec8Sopenharmony_citools_list_device_quirks(struct quirks_context *ctx, 739a46c0ec8Sopenharmony_ci struct udev_device *device, 740a46c0ec8Sopenharmony_ci void (*callback)(void *data, const char *str), 741a46c0ec8Sopenharmony_ci void *userdata) 742a46c0ec8Sopenharmony_ci{ 743a46c0ec8Sopenharmony_ci char buf[256]; 744a46c0ec8Sopenharmony_ci 745a46c0ec8Sopenharmony_ci struct quirks *quirks; 746a46c0ec8Sopenharmony_ci enum quirk q; 747a46c0ec8Sopenharmony_ci 748a46c0ec8Sopenharmony_ci quirks = quirks_fetch_for_device(ctx, device); 749a46c0ec8Sopenharmony_ci if (!quirks) 750a46c0ec8Sopenharmony_ci return; 751a46c0ec8Sopenharmony_ci 752a46c0ec8Sopenharmony_ci q = QUIRK_MODEL_ALPS_SERIAL_TOUCHPAD; 753a46c0ec8Sopenharmony_ci do { 754a46c0ec8Sopenharmony_ci if (quirks_has_quirk(quirks, q)) { 755a46c0ec8Sopenharmony_ci const char *name; 756a46c0ec8Sopenharmony_ci bool b; 757a46c0ec8Sopenharmony_ci 758a46c0ec8Sopenharmony_ci name = quirk_get_name(q); 759a46c0ec8Sopenharmony_ci quirks_get_bool(quirks, q, &b); 760a46c0ec8Sopenharmony_ci snprintf(buf, sizeof(buf), "%s=%d", name, b ? 1 : 0); 761a46c0ec8Sopenharmony_ci callback(userdata, buf); 762a46c0ec8Sopenharmony_ci } 763a46c0ec8Sopenharmony_ci } while(++q < _QUIRK_LAST_MODEL_QUIRK_); 764a46c0ec8Sopenharmony_ci 765a46c0ec8Sopenharmony_ci q = QUIRK_ATTR_SIZE_HINT; 766a46c0ec8Sopenharmony_ci do { 767a46c0ec8Sopenharmony_ci if (quirks_has_quirk(quirks, q)) { 768a46c0ec8Sopenharmony_ci const char *name; 769a46c0ec8Sopenharmony_ci struct quirk_dimensions dim; 770a46c0ec8Sopenharmony_ci struct quirk_range r; 771a46c0ec8Sopenharmony_ci uint32_t v; 772a46c0ec8Sopenharmony_ci char *s; 773a46c0ec8Sopenharmony_ci double d; 774a46c0ec8Sopenharmony_ci bool b; 775a46c0ec8Sopenharmony_ci 776a46c0ec8Sopenharmony_ci name = quirk_get_name(q); 777a46c0ec8Sopenharmony_ci 778a46c0ec8Sopenharmony_ci switch (q) { 779a46c0ec8Sopenharmony_ci case QUIRK_ATTR_SIZE_HINT: 780a46c0ec8Sopenharmony_ci case QUIRK_ATTR_RESOLUTION_HINT: 781a46c0ec8Sopenharmony_ci quirks_get_dimensions(quirks, q, &dim); 782a46c0ec8Sopenharmony_ci snprintf(buf, sizeof(buf), "%s=%zdx%zd", name, dim.x, dim.y); 783a46c0ec8Sopenharmony_ci callback(userdata, buf); 784a46c0ec8Sopenharmony_ci break; 785a46c0ec8Sopenharmony_ci case QUIRK_ATTR_TOUCH_SIZE_RANGE: 786a46c0ec8Sopenharmony_ci case QUIRK_ATTR_PRESSURE_RANGE: 787a46c0ec8Sopenharmony_ci quirks_get_range(quirks, q, &r); 788a46c0ec8Sopenharmony_ci snprintf(buf, sizeof(buf), "%s=%d:%d", name, r.upper, r.lower); 789a46c0ec8Sopenharmony_ci callback(userdata, buf); 790a46c0ec8Sopenharmony_ci break; 791a46c0ec8Sopenharmony_ci case QUIRK_ATTR_PALM_SIZE_THRESHOLD: 792a46c0ec8Sopenharmony_ci case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD: 793a46c0ec8Sopenharmony_ci case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD: 794a46c0ec8Sopenharmony_ci case QUIRK_ATTR_THUMB_SIZE_THRESHOLD: 795a46c0ec8Sopenharmony_ci quirks_get_uint32(quirks, q, &v); 796a46c0ec8Sopenharmony_ci snprintf(buf, sizeof(buf), "%s=%u", name, v); 797a46c0ec8Sopenharmony_ci callback(userdata, buf); 798a46c0ec8Sopenharmony_ci break; 799a46c0ec8Sopenharmony_ci case QUIRK_ATTR_LID_SWITCH_RELIABILITY: 800a46c0ec8Sopenharmony_ci case QUIRK_ATTR_KEYBOARD_INTEGRATION: 801a46c0ec8Sopenharmony_ci case QUIRK_ATTR_TRACKPOINT_INTEGRATION: 802a46c0ec8Sopenharmony_ci case QUIRK_ATTR_TPKBCOMBO_LAYOUT: 803a46c0ec8Sopenharmony_ci case QUIRK_ATTR_MSC_TIMESTAMP: 804a46c0ec8Sopenharmony_ci quirks_get_string(quirks, q, &s); 805a46c0ec8Sopenharmony_ci snprintf(buf, sizeof(buf), "%s=%s", name, s); 806a46c0ec8Sopenharmony_ci callback(userdata, buf); 807a46c0ec8Sopenharmony_ci break; 808a46c0ec8Sopenharmony_ci case QUIRK_ATTR_TRACKPOINT_MULTIPLIER: 809a46c0ec8Sopenharmony_ci quirks_get_double(quirks, q, &d); 810a46c0ec8Sopenharmony_ci snprintf(buf, sizeof(buf), "%s=%0.2f", name, d); 811a46c0ec8Sopenharmony_ci callback(userdata, buf); 812a46c0ec8Sopenharmony_ci break; 813a46c0ec8Sopenharmony_ci case QUIRK_ATTR_USE_VELOCITY_AVERAGING: 814a46c0ec8Sopenharmony_ci case QUIRK_ATTR_TABLET_SMOOTHING: 815a46c0ec8Sopenharmony_ci quirks_get_bool(quirks, q, &b); 816a46c0ec8Sopenharmony_ci snprintf(buf, sizeof(buf), "%s=%d", name, b); 817a46c0ec8Sopenharmony_ci callback(userdata, buf); 818a46c0ec8Sopenharmony_ci break; 819a46c0ec8Sopenharmony_ci case QUIRK_ATTR_EVENT_CODE: 820a46c0ec8Sopenharmony_ci sprintf_event_codes(buf, sizeof(buf), quirks, q); 821a46c0ec8Sopenharmony_ci callback(userdata, buf); 822a46c0ec8Sopenharmony_ci break; 823a46c0ec8Sopenharmony_ci case QUIRK_ATTR_INPUT_PROP: 824a46c0ec8Sopenharmony_ci sprintf_input_props(buf, sizeof(buf), quirks, q); 825a46c0ec8Sopenharmony_ci callback(userdata, buf); 826a46c0ec8Sopenharmony_ci break; 827a46c0ec8Sopenharmony_ci default: 828a46c0ec8Sopenharmony_ci abort(); 829a46c0ec8Sopenharmony_ci break; 830a46c0ec8Sopenharmony_ci } 831a46c0ec8Sopenharmony_ci } 832a46c0ec8Sopenharmony_ci } while(++q < _QUIRK_LAST_ATTR_QUIRK_); 833a46c0ec8Sopenharmony_ci 834a46c0ec8Sopenharmony_ci quirks_unref(quirks); 835a46c0ec8Sopenharmony_ci} 836