1a46c0ec8Sopenharmony_ci/* 2a46c0ec8Sopenharmony_ci * Copyright © 2015 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 <stdbool.h> 29a46c0ec8Sopenharmony_ci#include <stdio.h> 30a46c0ec8Sopenharmony_ci#include <getopt.h> 31a46c0ec8Sopenharmony_ci#include <stdlib.h> 32a46c0ec8Sopenharmony_ci#include <string.h> 33a46c0ec8Sopenharmony_ci#include <unistd.h> 34a46c0ec8Sopenharmony_ci 35a46c0ec8Sopenharmony_ci#include "filter.h" 36a46c0ec8Sopenharmony_ci#include "libinput-util.h" 37a46c0ec8Sopenharmony_ci 38a46c0ec8Sopenharmony_cistatic void 39a46c0ec8Sopenharmony_ciprint_ptraccel_deltas(struct motion_filter *filter, double step) 40a46c0ec8Sopenharmony_ci{ 41a46c0ec8Sopenharmony_ci struct device_float_coords motion; 42a46c0ec8Sopenharmony_ci struct normalized_coords accel; 43a46c0ec8Sopenharmony_ci uint64_t time = 0; 44a46c0ec8Sopenharmony_ci double i; 45a46c0ec8Sopenharmony_ci 46a46c0ec8Sopenharmony_ci printf("# gnuplot:\n"); 47a46c0ec8Sopenharmony_ci printf("# set xlabel dx unaccelerated\n"); 48a46c0ec8Sopenharmony_ci printf("# set ylabel dx accelerated\n"); 49a46c0ec8Sopenharmony_ci printf("# set style data lines\n"); 50a46c0ec8Sopenharmony_ci printf("# plot \"gnuplot.data\" using 1:2 title \"step %.2f\"\n", step); 51a46c0ec8Sopenharmony_ci printf("#\n"); 52a46c0ec8Sopenharmony_ci 53a46c0ec8Sopenharmony_ci /* Accel flattens out after 15 and becomes linear */ 54a46c0ec8Sopenharmony_ci for (i = 0.0; i < 15.0; i += step) { 55a46c0ec8Sopenharmony_ci motion.x = i; 56a46c0ec8Sopenharmony_ci motion.y = 0; 57a46c0ec8Sopenharmony_ci time += us(12500); /* pretend 80Hz data */ 58a46c0ec8Sopenharmony_ci 59a46c0ec8Sopenharmony_ci accel = filter_dispatch(filter, &motion, NULL, time); 60a46c0ec8Sopenharmony_ci 61a46c0ec8Sopenharmony_ci printf("%.2f %.3f\n", i, accel.x); 62a46c0ec8Sopenharmony_ci } 63a46c0ec8Sopenharmony_ci} 64a46c0ec8Sopenharmony_ci 65a46c0ec8Sopenharmony_cistatic void 66a46c0ec8Sopenharmony_ciprint_ptraccel_movement(struct motion_filter *filter, 67a46c0ec8Sopenharmony_ci int nevents, 68a46c0ec8Sopenharmony_ci double max_dx, 69a46c0ec8Sopenharmony_ci double step) 70a46c0ec8Sopenharmony_ci{ 71a46c0ec8Sopenharmony_ci struct device_float_coords motion; 72a46c0ec8Sopenharmony_ci struct normalized_coords accel; 73a46c0ec8Sopenharmony_ci uint64_t time = 0; 74a46c0ec8Sopenharmony_ci double dx; 75a46c0ec8Sopenharmony_ci int i; 76a46c0ec8Sopenharmony_ci 77a46c0ec8Sopenharmony_ci printf("# gnuplot:\n"); 78a46c0ec8Sopenharmony_ci printf("# set xlabel \"event number\"\n"); 79a46c0ec8Sopenharmony_ci printf("# set ylabel \"delta motion\"\n"); 80a46c0ec8Sopenharmony_ci printf("# set style data lines\n"); 81a46c0ec8Sopenharmony_ci printf("# plot \"gnuplot.data\" using 1:2 title \"dx out\", \\\n"); 82a46c0ec8Sopenharmony_ci printf("# \"gnuplot.data\" using 1:3 title \"dx in\"\n"); 83a46c0ec8Sopenharmony_ci printf("#\n"); 84a46c0ec8Sopenharmony_ci 85a46c0ec8Sopenharmony_ci if (nevents == 0) { 86a46c0ec8Sopenharmony_ci if (step > 1.0) 87a46c0ec8Sopenharmony_ci nevents = max_dx; 88a46c0ec8Sopenharmony_ci else 89a46c0ec8Sopenharmony_ci nevents = 1.0 * max_dx/step + 0.5; 90a46c0ec8Sopenharmony_ci 91a46c0ec8Sopenharmony_ci /* Print more events than needed so we see the curve 92a46c0ec8Sopenharmony_ci * flattening out */ 93a46c0ec8Sopenharmony_ci nevents *= 1.5; 94a46c0ec8Sopenharmony_ci } 95a46c0ec8Sopenharmony_ci 96a46c0ec8Sopenharmony_ci dx = 0; 97a46c0ec8Sopenharmony_ci 98a46c0ec8Sopenharmony_ci for (i = 0; i < nevents; i++) { 99a46c0ec8Sopenharmony_ci motion.x = dx; 100a46c0ec8Sopenharmony_ci motion.y = 0; 101a46c0ec8Sopenharmony_ci time += us(12500); /* pretend 80Hz data */ 102a46c0ec8Sopenharmony_ci 103a46c0ec8Sopenharmony_ci accel = filter_dispatch(filter, &motion, NULL, time); 104a46c0ec8Sopenharmony_ci 105a46c0ec8Sopenharmony_ci printf("%d %.3f %.3f\n", i, accel.x, dx); 106a46c0ec8Sopenharmony_ci 107a46c0ec8Sopenharmony_ci if (dx < max_dx) 108a46c0ec8Sopenharmony_ci dx += step; 109a46c0ec8Sopenharmony_ci } 110a46c0ec8Sopenharmony_ci} 111a46c0ec8Sopenharmony_ci 112a46c0ec8Sopenharmony_cistatic void 113a46c0ec8Sopenharmony_ciprint_ptraccel_sequence(struct motion_filter *filter, 114a46c0ec8Sopenharmony_ci int nevents, 115a46c0ec8Sopenharmony_ci double *deltas) 116a46c0ec8Sopenharmony_ci{ 117a46c0ec8Sopenharmony_ci struct device_float_coords motion; 118a46c0ec8Sopenharmony_ci struct normalized_coords accel; 119a46c0ec8Sopenharmony_ci uint64_t time = 0; 120a46c0ec8Sopenharmony_ci double *dx; 121a46c0ec8Sopenharmony_ci int i; 122a46c0ec8Sopenharmony_ci 123a46c0ec8Sopenharmony_ci printf("# gnuplot:\n"); 124a46c0ec8Sopenharmony_ci printf("# set xlabel \"event number\"\n"); 125a46c0ec8Sopenharmony_ci printf("# set ylabel \"delta motion\"\n"); 126a46c0ec8Sopenharmony_ci printf("# set style data lines\n"); 127a46c0ec8Sopenharmony_ci printf("# plot \"gnuplot.data\" using 1:2 title \"dx out\", \\\n"); 128a46c0ec8Sopenharmony_ci printf("# \"gnuplot.data\" using 1:3 title \"dx in\"\n"); 129a46c0ec8Sopenharmony_ci printf("#\n"); 130a46c0ec8Sopenharmony_ci 131a46c0ec8Sopenharmony_ci dx = deltas; 132a46c0ec8Sopenharmony_ci 133a46c0ec8Sopenharmony_ci for (i = 0; i < nevents; i++, dx++) { 134a46c0ec8Sopenharmony_ci motion.x = *dx; 135a46c0ec8Sopenharmony_ci motion.y = 0; 136a46c0ec8Sopenharmony_ci time += us(12500); /* pretend 80Hz data */ 137a46c0ec8Sopenharmony_ci 138a46c0ec8Sopenharmony_ci accel = filter_dispatch(filter, &motion, NULL, time); 139a46c0ec8Sopenharmony_ci 140a46c0ec8Sopenharmony_ci printf("%d %.3f %.3f\n", i, accel.x, *dx); 141a46c0ec8Sopenharmony_ci } 142a46c0ec8Sopenharmony_ci} 143a46c0ec8Sopenharmony_ci 144a46c0ec8Sopenharmony_ci/* mm/s → units/µs */ 145a46c0ec8Sopenharmony_cistatic inline double 146a46c0ec8Sopenharmony_cimmps_to_upus(double mmps, int dpi) 147a46c0ec8Sopenharmony_ci{ 148a46c0ec8Sopenharmony_ci return mmps * (dpi/25.4) / 1e6; 149a46c0ec8Sopenharmony_ci} 150a46c0ec8Sopenharmony_ci 151a46c0ec8Sopenharmony_cistatic void 152a46c0ec8Sopenharmony_ciprint_accel_func(struct motion_filter *filter, 153a46c0ec8Sopenharmony_ci accel_profile_func_t profile, 154a46c0ec8Sopenharmony_ci int dpi) 155a46c0ec8Sopenharmony_ci{ 156a46c0ec8Sopenharmony_ci double mmps; 157a46c0ec8Sopenharmony_ci 158a46c0ec8Sopenharmony_ci printf("# gnuplot:\n"); 159a46c0ec8Sopenharmony_ci printf("# set xlabel \"speed (mm/s)\"\n"); 160a46c0ec8Sopenharmony_ci printf("# set ylabel \"raw accel factor\"\n"); 161a46c0ec8Sopenharmony_ci printf("# set style data lines\n"); 162a46c0ec8Sopenharmony_ci printf("# plot \"gnuplot.data\" using 1:2 title 'accel factor'\n"); 163a46c0ec8Sopenharmony_ci printf("#\n"); 164a46c0ec8Sopenharmony_ci printf("# data: velocity(mm/s) factor velocity(units/us) velocity(units/ms)\n"); 165a46c0ec8Sopenharmony_ci for (mmps = 0.0; mmps < 1000.0; mmps += 1) { 166a46c0ec8Sopenharmony_ci double units_per_us = mmps_to_upus(mmps, dpi); 167a46c0ec8Sopenharmony_ci double units_per_ms = units_per_us * 1000.0; 168a46c0ec8Sopenharmony_ci double result = profile(filter, NULL, units_per_us, 0 /* time */); 169a46c0ec8Sopenharmony_ci printf("%.8f\t%.4f\t%.8f\t%.8f\n", mmps, result, units_per_us, units_per_ms); 170a46c0ec8Sopenharmony_ci } 171a46c0ec8Sopenharmony_ci} 172a46c0ec8Sopenharmony_ci 173a46c0ec8Sopenharmony_cistatic void 174a46c0ec8Sopenharmony_ciusage(void) 175a46c0ec8Sopenharmony_ci{ 176a46c0ec8Sopenharmony_ci printf("Usage: %s [options] [dx1] [dx2] [...] > gnuplot.data\n", program_invocation_short_name); 177a46c0ec8Sopenharmony_ci printf("\n" 178a46c0ec8Sopenharmony_ci "Options:\n" 179a46c0ec8Sopenharmony_ci "--mode=<accel|motion|delta|sequence> \n" 180a46c0ec8Sopenharmony_ci " accel ... print accel factor (default)\n" 181a46c0ec8Sopenharmony_ci " motion ... print motion to accelerated motion\n" 182a46c0ec8Sopenharmony_ci " delta ... print delta to accelerated delta\n" 183a46c0ec8Sopenharmony_ci " sequence ... print motion for custom delta sequence\n" 184a46c0ec8Sopenharmony_ci "--maxdx=<double> ... in motion mode only. Stop increasing dx at maxdx\n" 185a46c0ec8Sopenharmony_ci "--steps=<double> ... in motion and delta modes only. Increase dx by step each round\n" 186a46c0ec8Sopenharmony_ci "--speed=<double> ... accel speed [-1, 1], default 0\n" 187a46c0ec8Sopenharmony_ci "--dpi=<int> ... device resolution in DPI (default: 1000)\n" 188a46c0ec8Sopenharmony_ci "--filter=<linear|low-dpi|touchpad|x230|trackpoint> \n" 189a46c0ec8Sopenharmony_ci " linear ... the default motion filter\n" 190a46c0ec8Sopenharmony_ci " low-dpi ... low-dpi filter, use --dpi with this argument\n" 191a46c0ec8Sopenharmony_ci " touchpad ... the touchpad motion filter\n" 192a46c0ec8Sopenharmony_ci " x230 ... custom filter for the Lenovo x230 touchpad\n" 193a46c0ec8Sopenharmony_ci " trackpoint... trackpoint motion filter\n" 194a46c0ec8Sopenharmony_ci " custom ... custom motion filter, use --custom-points and --custom-step with this argument\n" 195a46c0ec8Sopenharmony_ci "--custom-points=\"<double>;...;<double>\" ... n points defining a custom acceleration function\n" 196a46c0ec8Sopenharmony_ci "--custom-step=<double> ... distance along the x-axis between each point, \n" 197a46c0ec8Sopenharmony_ci " starting from 0. defaults to 1.0\n" 198a46c0ec8Sopenharmony_ci "\n" 199a46c0ec8Sopenharmony_ci "If extra arguments are present and mode is not given, mode defaults to 'sequence'\n" 200a46c0ec8Sopenharmony_ci "and the arguments are interpreted as sequence of delta x coordinates\n" 201a46c0ec8Sopenharmony_ci "\n" 202a46c0ec8Sopenharmony_ci "If stdin is a pipe, mode defaults to 'sequence' and the pipe is read \n" 203a46c0ec8Sopenharmony_ci "for delta coordinates\n" 204a46c0ec8Sopenharmony_ci "\n" 205a46c0ec8Sopenharmony_ci "Delta coordinates passed into this tool must be in dpi as\n" 206a46c0ec8Sopenharmony_ci "specified by the --dpi argument\n" 207a46c0ec8Sopenharmony_ci "\n" 208a46c0ec8Sopenharmony_ci "Output best viewed with gnuplot. See output for gnuplot commands\n"); 209a46c0ec8Sopenharmony_ci} 210a46c0ec8Sopenharmony_ci 211a46c0ec8Sopenharmony_cienum mode { 212a46c0ec8Sopenharmony_ci ACCEL, 213a46c0ec8Sopenharmony_ci MOTION, 214a46c0ec8Sopenharmony_ci DELTA, 215a46c0ec8Sopenharmony_ci SEQUENCE, 216a46c0ec8Sopenharmony_ci}; 217a46c0ec8Sopenharmony_ci 218a46c0ec8Sopenharmony_ciint 219a46c0ec8Sopenharmony_cimain(int argc, char **argv) 220a46c0ec8Sopenharmony_ci{ 221a46c0ec8Sopenharmony_ci struct motion_filter *filter; 222a46c0ec8Sopenharmony_ci double step = 0.1, 223a46c0ec8Sopenharmony_ci max_dx = 10; 224a46c0ec8Sopenharmony_ci int nevents = 0; 225a46c0ec8Sopenharmony_ci enum mode mode = ACCEL; 226a46c0ec8Sopenharmony_ci double custom_deltas[1024]; 227a46c0ec8Sopenharmony_ci double speed = 0.0; 228a46c0ec8Sopenharmony_ci int dpi = 1000; 229a46c0ec8Sopenharmony_ci bool use_averaging = false; 230a46c0ec8Sopenharmony_ci const char *filter_type = "linear"; 231a46c0ec8Sopenharmony_ci accel_profile_func_t profile = NULL; 232a46c0ec8Sopenharmony_ci double tp_multiplier = 1.0; 233a46c0ec8Sopenharmony_ci struct libinput_config_accel_custom_func custom_func = { 234a46c0ec8Sopenharmony_ci .step = 1.0, 235a46c0ec8Sopenharmony_ci .npoints = 2, 236a46c0ec8Sopenharmony_ci .points = {0.0, 1.0}, 237a46c0ec8Sopenharmony_ci }; 238a46c0ec8Sopenharmony_ci struct libinput_config_accel *accel_config = 239a46c0ec8Sopenharmony_ci libinput_config_accel_create(LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM); 240a46c0ec8Sopenharmony_ci 241a46c0ec8Sopenharmony_ci enum { 242a46c0ec8Sopenharmony_ci OPT_HELP = 1, 243a46c0ec8Sopenharmony_ci OPT_MODE, 244a46c0ec8Sopenharmony_ci OPT_NEVENTS, 245a46c0ec8Sopenharmony_ci OPT_MAXDX, 246a46c0ec8Sopenharmony_ci OPT_STEP, 247a46c0ec8Sopenharmony_ci OPT_SPEED, 248a46c0ec8Sopenharmony_ci OPT_DPI, 249a46c0ec8Sopenharmony_ci OPT_FILTER, 250a46c0ec8Sopenharmony_ci OPT_CUSTOM_POINTS, 251a46c0ec8Sopenharmony_ci OPT_CUSTOM_STEP, 252a46c0ec8Sopenharmony_ci }; 253a46c0ec8Sopenharmony_ci 254a46c0ec8Sopenharmony_ci while (1) { 255a46c0ec8Sopenharmony_ci int c; 256a46c0ec8Sopenharmony_ci int option_index = 0; 257a46c0ec8Sopenharmony_ci static struct option long_options[] = { 258a46c0ec8Sopenharmony_ci {"help", 0, 0, OPT_HELP }, 259a46c0ec8Sopenharmony_ci {"mode", 1, 0, OPT_MODE }, 260a46c0ec8Sopenharmony_ci {"nevents", 1, 0, OPT_NEVENTS }, 261a46c0ec8Sopenharmony_ci {"maxdx", 1, 0, OPT_MAXDX }, 262a46c0ec8Sopenharmony_ci {"step", 1, 0, OPT_STEP }, 263a46c0ec8Sopenharmony_ci {"speed", 1, 0, OPT_SPEED }, 264a46c0ec8Sopenharmony_ci {"dpi", 1, 0, OPT_DPI }, 265a46c0ec8Sopenharmony_ci {"filter", 1, 0, OPT_FILTER }, 266a46c0ec8Sopenharmony_ci {"custom-points", 1, 0, OPT_CUSTOM_POINTS }, 267a46c0ec8Sopenharmony_ci {"custom-step", 1, 0, OPT_CUSTOM_STEP }, 268a46c0ec8Sopenharmony_ci {0, 0, 0, 0} 269a46c0ec8Sopenharmony_ci }; 270a46c0ec8Sopenharmony_ci 271a46c0ec8Sopenharmony_ci c = getopt_long(argc, argv, "", 272a46c0ec8Sopenharmony_ci long_options, &option_index); 273a46c0ec8Sopenharmony_ci if (c == -1) 274a46c0ec8Sopenharmony_ci break; 275a46c0ec8Sopenharmony_ci 276a46c0ec8Sopenharmony_ci switch (c) { 277a46c0ec8Sopenharmony_ci case OPT_HELP: 278a46c0ec8Sopenharmony_ci usage(); 279a46c0ec8Sopenharmony_ci exit(0); 280a46c0ec8Sopenharmony_ci break; 281a46c0ec8Sopenharmony_ci case OPT_MODE: 282a46c0ec8Sopenharmony_ci if (streq(optarg, "accel")) 283a46c0ec8Sopenharmony_ci mode = ACCEL; 284a46c0ec8Sopenharmony_ci else if (streq(optarg, "motion")) 285a46c0ec8Sopenharmony_ci mode = MOTION; 286a46c0ec8Sopenharmony_ci else if (streq(optarg, "delta")) 287a46c0ec8Sopenharmony_ci mode = DELTA; 288a46c0ec8Sopenharmony_ci else if (streq(optarg, "sequence")) 289a46c0ec8Sopenharmony_ci mode = SEQUENCE; 290a46c0ec8Sopenharmony_ci else { 291a46c0ec8Sopenharmony_ci usage(); 292a46c0ec8Sopenharmony_ci return 1; 293a46c0ec8Sopenharmony_ci } 294a46c0ec8Sopenharmony_ci break; 295a46c0ec8Sopenharmony_ci case OPT_NEVENTS: 296a46c0ec8Sopenharmony_ci nevents = atoi(optarg); 297a46c0ec8Sopenharmony_ci if (nevents == 0) { 298a46c0ec8Sopenharmony_ci usage(); 299a46c0ec8Sopenharmony_ci return 1; 300a46c0ec8Sopenharmony_ci } 301a46c0ec8Sopenharmony_ci break; 302a46c0ec8Sopenharmony_ci case OPT_MAXDX: 303a46c0ec8Sopenharmony_ci max_dx = strtod(optarg, NULL); 304a46c0ec8Sopenharmony_ci if (max_dx == 0.0) { 305a46c0ec8Sopenharmony_ci usage(); 306a46c0ec8Sopenharmony_ci return 1; 307a46c0ec8Sopenharmony_ci } 308a46c0ec8Sopenharmony_ci break; 309a46c0ec8Sopenharmony_ci case OPT_STEP: 310a46c0ec8Sopenharmony_ci step = strtod(optarg, NULL); 311a46c0ec8Sopenharmony_ci if (step == 0.0) { 312a46c0ec8Sopenharmony_ci usage(); 313a46c0ec8Sopenharmony_ci return 1; 314a46c0ec8Sopenharmony_ci } 315a46c0ec8Sopenharmony_ci break; 316a46c0ec8Sopenharmony_ci case OPT_SPEED: 317a46c0ec8Sopenharmony_ci speed = strtod(optarg, NULL); 318a46c0ec8Sopenharmony_ci break; 319a46c0ec8Sopenharmony_ci case OPT_DPI: 320a46c0ec8Sopenharmony_ci dpi = strtod(optarg, NULL); 321a46c0ec8Sopenharmony_ci break; 322a46c0ec8Sopenharmony_ci case OPT_FILTER: 323a46c0ec8Sopenharmony_ci filter_type = optarg; 324a46c0ec8Sopenharmony_ci break; 325a46c0ec8Sopenharmony_ci case OPT_CUSTOM_POINTS: { 326a46c0ec8Sopenharmony_ci size_t npoints; 327a46c0ec8Sopenharmony_ci double *points = double_array_from_string(optarg, 328a46c0ec8Sopenharmony_ci ";", 329a46c0ec8Sopenharmony_ci &npoints); 330a46c0ec8Sopenharmony_ci if (!points || 331a46c0ec8Sopenharmony_ci npoints < LIBINPUT_ACCEL_NPOINTS_MIN || 332a46c0ec8Sopenharmony_ci npoints > LIBINPUT_ACCEL_NPOINTS_MAX) { 333a46c0ec8Sopenharmony_ci fprintf(stderr, 334a46c0ec8Sopenharmony_ci "Invalid --custom-points\n" 335a46c0ec8Sopenharmony_ci "Please provide at least 2 points separated by a semicolon\n" 336a46c0ec8Sopenharmony_ci " e.g. --custom-points=\"1.0;1.5\"\n"); 337a46c0ec8Sopenharmony_ci free(points); 338a46c0ec8Sopenharmony_ci return 1; 339a46c0ec8Sopenharmony_ci } 340a46c0ec8Sopenharmony_ci custom_func.npoints = npoints; 341a46c0ec8Sopenharmony_ci memcpy(custom_func.points, 342a46c0ec8Sopenharmony_ci points, 343a46c0ec8Sopenharmony_ci sizeof(*points) * npoints); 344a46c0ec8Sopenharmony_ci free(points); 345a46c0ec8Sopenharmony_ci break; 346a46c0ec8Sopenharmony_ci } 347a46c0ec8Sopenharmony_ci case OPT_CUSTOM_STEP: 348a46c0ec8Sopenharmony_ci custom_func.step = strtod(optarg, NULL); 349a46c0ec8Sopenharmony_ci break; 350a46c0ec8Sopenharmony_ci default: 351a46c0ec8Sopenharmony_ci usage(); 352a46c0ec8Sopenharmony_ci exit(1); 353a46c0ec8Sopenharmony_ci break; 354a46c0ec8Sopenharmony_ci } 355a46c0ec8Sopenharmony_ci } 356a46c0ec8Sopenharmony_ci 357a46c0ec8Sopenharmony_ci if (streq(filter_type, "linear")) { 358a46c0ec8Sopenharmony_ci filter = create_pointer_accelerator_filter_linear(dpi, 359a46c0ec8Sopenharmony_ci use_averaging); 360a46c0ec8Sopenharmony_ci profile = pointer_accel_profile_linear; 361a46c0ec8Sopenharmony_ci } else if (streq(filter_type, "low-dpi")) { 362a46c0ec8Sopenharmony_ci filter = create_pointer_accelerator_filter_linear_low_dpi(dpi, 363a46c0ec8Sopenharmony_ci use_averaging); 364a46c0ec8Sopenharmony_ci profile = pointer_accel_profile_linear_low_dpi; 365a46c0ec8Sopenharmony_ci } else if (streq(filter_type, "touchpad")) { 366a46c0ec8Sopenharmony_ci filter = create_pointer_accelerator_filter_touchpad(dpi, 367a46c0ec8Sopenharmony_ci 0, 0, 368a46c0ec8Sopenharmony_ci use_averaging); 369a46c0ec8Sopenharmony_ci profile = touchpad_accel_profile_linear; 370a46c0ec8Sopenharmony_ci } else if (streq(filter_type, "x230")) { 371a46c0ec8Sopenharmony_ci filter = create_pointer_accelerator_filter_lenovo_x230(dpi, 372a46c0ec8Sopenharmony_ci use_averaging); 373a46c0ec8Sopenharmony_ci profile = touchpad_lenovo_x230_accel_profile; 374a46c0ec8Sopenharmony_ci } else if (streq(filter_type, "trackpoint")) { 375a46c0ec8Sopenharmony_ci filter = create_pointer_accelerator_filter_trackpoint(tp_multiplier, 376a46c0ec8Sopenharmony_ci use_averaging); 377a46c0ec8Sopenharmony_ci profile = trackpoint_accel_profile; 378a46c0ec8Sopenharmony_ci } else if (streq(filter_type, "custom")) { 379a46c0ec8Sopenharmony_ci libinput_config_accel_set_points(accel_config, 380a46c0ec8Sopenharmony_ci LIBINPUT_ACCEL_TYPE_MOTION, 381a46c0ec8Sopenharmony_ci custom_func.step, 382a46c0ec8Sopenharmony_ci custom_func.npoints, 383a46c0ec8Sopenharmony_ci custom_func.points); 384a46c0ec8Sopenharmony_ci filter = create_custom_accelerator_filter(); 385a46c0ec8Sopenharmony_ci profile = custom_accel_profile_motion; 386a46c0ec8Sopenharmony_ci filter_set_accel_config(filter, accel_config); 387a46c0ec8Sopenharmony_ci } else { 388a46c0ec8Sopenharmony_ci fprintf(stderr, "Invalid filter type %s\n", filter_type); 389a46c0ec8Sopenharmony_ci return 1; 390a46c0ec8Sopenharmony_ci } 391a46c0ec8Sopenharmony_ci 392a46c0ec8Sopenharmony_ci assert(filter != NULL); 393a46c0ec8Sopenharmony_ci filter_set_speed(filter, speed); 394a46c0ec8Sopenharmony_ci 395a46c0ec8Sopenharmony_ci if (!isatty(STDIN_FILENO)) { 396a46c0ec8Sopenharmony_ci char buf[12]; 397a46c0ec8Sopenharmony_ci mode = SEQUENCE; 398a46c0ec8Sopenharmony_ci nevents = 0; 399a46c0ec8Sopenharmony_ci memset(custom_deltas, 0, sizeof(custom_deltas)); 400a46c0ec8Sopenharmony_ci 401a46c0ec8Sopenharmony_ci while(fgets(buf, sizeof(buf), stdin) && nevents < 1024) { 402a46c0ec8Sopenharmony_ci custom_deltas[nevents++] = strtod(buf, NULL); 403a46c0ec8Sopenharmony_ci } 404a46c0ec8Sopenharmony_ci } else if (optind < argc) { 405a46c0ec8Sopenharmony_ci mode = SEQUENCE; 406a46c0ec8Sopenharmony_ci nevents = 0; 407a46c0ec8Sopenharmony_ci memset(custom_deltas, 0, sizeof(custom_deltas)); 408a46c0ec8Sopenharmony_ci while (optind < argc) 409a46c0ec8Sopenharmony_ci custom_deltas[nevents++] = strtod(argv[optind++], NULL); 410a46c0ec8Sopenharmony_ci } else if (mode == SEQUENCE) { 411a46c0ec8Sopenharmony_ci usage(); 412a46c0ec8Sopenharmony_ci return 1; 413a46c0ec8Sopenharmony_ci } 414a46c0ec8Sopenharmony_ci 415a46c0ec8Sopenharmony_ci switch (mode) { 416a46c0ec8Sopenharmony_ci case ACCEL: 417a46c0ec8Sopenharmony_ci print_accel_func(filter, profile, dpi); 418a46c0ec8Sopenharmony_ci break; 419a46c0ec8Sopenharmony_ci case DELTA: 420a46c0ec8Sopenharmony_ci print_ptraccel_deltas(filter, step); 421a46c0ec8Sopenharmony_ci break; 422a46c0ec8Sopenharmony_ci case MOTION: 423a46c0ec8Sopenharmony_ci print_ptraccel_movement(filter, nevents, max_dx, step); 424a46c0ec8Sopenharmony_ci break; 425a46c0ec8Sopenharmony_ci case SEQUENCE: 426a46c0ec8Sopenharmony_ci print_ptraccel_sequence(filter, nevents, custom_deltas); 427a46c0ec8Sopenharmony_ci break; 428a46c0ec8Sopenharmony_ci } 429a46c0ec8Sopenharmony_ci 430a46c0ec8Sopenharmony_ci libinput_config_accel_destroy(accel_config); 431a46c0ec8Sopenharmony_ci filter_destroy(filter); 432a46c0ec8Sopenharmony_ci 433a46c0ec8Sopenharmony_ci return 0; 434a46c0ec8Sopenharmony_ci} 435