libinput/tools/libinput-list-quirks.c
Peter Hutterer 39cc6d054a tools: list-quirks: print the value of the quirk too
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2018-06-20 14:01:17 +10:00

322 lines
8 KiB
C

/*
* Copyright © 2018 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <getopt.h>
#include <sys/stat.h>
#include "libinput-util.h"
#include "quirks.h"
static bool verbose = false;
static void
log_handler(struct libinput *this_is_null,
enum libinput_log_priority priority,
const char *format,
va_list args)
{
FILE *out = stdout;
enum quirks_log_priorities p = (enum quirks_log_priorities)priority;
char buf[256] = {0};
const char *prefix = "";
switch (p) {
case QLOG_NOISE:
case QLOG_DEBUG:
if (!verbose)
return;
prefix = "quirks debug";
break;
case QLOG_INFO:
prefix = "quirks info";
break;
case QLOG_ERROR:
out = stderr;
prefix = "quirks error";
break;
case QLOG_PARSER_ERROR:
out = stderr;
prefix = "quirks parser error";
break;
}
snprintf(buf, sizeof(buf), "%s: %s", prefix, format);
vfprintf(out, buf, args);
}
static void
list_device_quirks(struct quirks_context *ctx, struct udev_device *device)
{
struct quirks *quirks;
enum quirk qlist[] = {
QUIRK_MODEL_ALPS_TOUCHPAD,
QUIRK_MODEL_APPLE_TOUCHPAD,
QUIRK_MODEL_APPLE_MAGICMOUSE,
QUIRK_MODEL_TABLET_NO_TILT,
QUIRK_MODEL_APPLE_TOUCHPAD_ONEBUTTON,
QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER,
QUIRK_MODEL_CYBORG_RAT,
QUIRK_MODEL_CHROMEBOOK,
QUIRK_MODEL_HP6910_TOUCHPAD,
QUIRK_MODEL_HP8510_TOUCHPAD,
QUIRK_MODEL_HP_PAVILION_DM4_TOUCHPAD,
QUIRK_MODEL_HP_STREAM11_TOUCHPAD,
QUIRK_MODEL_HP_ZBOOK_STUDIO_G3,
QUIRK_MODEL_TABLET_NO_PROXIMITY_OUT,
QUIRK_MODEL_LENOVO_SCROLLPOINT,
QUIRK_MODEL_LENOVO_X230,
QUIRK_MODEL_LENOVO_T450_TOUCHPAD,
QUIRK_MODEL_TABLET_MODE_NO_SUSPEND,
QUIRK_MODEL_LENOVO_CARBON_X1_6TH,
QUIRK_MODEL_TRACKBALL,
QUIRK_MODEL_LOGITECH_MARBLE_MOUSE,
QUIRK_MODEL_BOUNCING_KEYS,
QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD,
QUIRK_MODEL_SYSTEM76_BONOBO,
QUIRK_MODEL_CLEVO_W740SU,
QUIRK_MODEL_SYSTEM76_GALAGO,
QUIRK_MODEL_SYSTEM76_KUDU,
QUIRK_MODEL_WACOM_TOUCHPAD,
QUIRK_ATTR_SIZE_HINT,
QUIRK_ATTR_TOUCH_SIZE_RANGE,
QUIRK_ATTR_PALM_SIZE_THRESHOLD,
QUIRK_ATTR_LID_SWITCH_RELIABILITY,
QUIRK_ATTR_KEYBOARD_INTEGRATION,
QUIRK_ATTR_TPKBCOMBO_LAYOUT,
QUIRK_ATTR_PRESSURE_RANGE,
QUIRK_ATTR_PALM_PRESSURE_THRESHOLD,
QUIRK_ATTR_RESOLUTION_HINT,
QUIRK_ATTR_TRACKPOINT_RANGE,
QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD,
};
enum quirk *q;
quirks = quirks_fetch_for_device(ctx, device);
if (!quirks) {
printf("Device has no quirks defined\n");
return;
}
ARRAY_FOR_EACH(qlist, q) {
const char *name;
struct quirk_dimensions dim;
struct quirk_range r;
uint32_t v;
char *s;
if (!quirks_has_quirk(quirks, *q))
continue;
name = quirk_get_name(*q);
switch (*q) {
case QUIRK_MODEL_ALPS_TOUCHPAD:
case QUIRK_MODEL_APPLE_TOUCHPAD:
case QUIRK_MODEL_APPLE_MAGICMOUSE:
case QUIRK_MODEL_TABLET_NO_TILT:
case QUIRK_MODEL_APPLE_TOUCHPAD_ONEBUTTON:
case QUIRK_MODEL_TOUCHPAD_VISIBLE_MARKER:
case QUIRK_MODEL_CYBORG_RAT:
case QUIRK_MODEL_CHROMEBOOK:
case QUIRK_MODEL_HP6910_TOUCHPAD:
case QUIRK_MODEL_HP8510_TOUCHPAD:
case QUIRK_MODEL_HP_PAVILION_DM4_TOUCHPAD:
case QUIRK_MODEL_HP_STREAM11_TOUCHPAD:
case QUIRK_MODEL_HP_ZBOOK_STUDIO_G3:
case QUIRK_MODEL_TABLET_NO_PROXIMITY_OUT:
case QUIRK_MODEL_LENOVO_SCROLLPOINT:
case QUIRK_MODEL_LENOVO_X230:
case QUIRK_MODEL_LENOVO_T450_TOUCHPAD:
case QUIRK_MODEL_TABLET_MODE_NO_SUSPEND:
case QUIRK_MODEL_LENOVO_CARBON_X1_6TH:
case QUIRK_MODEL_TRACKBALL:
case QUIRK_MODEL_LOGITECH_MARBLE_MOUSE:
case QUIRK_MODEL_BOUNCING_KEYS:
case QUIRK_MODEL_SYNAPTICS_SERIAL_TOUCHPAD:
case QUIRK_MODEL_SYSTEM76_BONOBO:
case QUIRK_MODEL_CLEVO_W740SU:
case QUIRK_MODEL_SYSTEM76_GALAGO:
case QUIRK_MODEL_SYSTEM76_KUDU:
case QUIRK_MODEL_WACOM_TOUCHPAD:
printf("%s=1\n", name);
break;
case QUIRK_ATTR_SIZE_HINT:
case QUIRK_ATTR_RESOLUTION_HINT:
quirks_get_dimensions(quirks, *q, &dim);
printf("%s=%ldx%ld\n", name, dim.x, dim.y);
break;
case QUIRK_ATTR_TOUCH_SIZE_RANGE:
case QUIRK_ATTR_PRESSURE_RANGE:
quirks_get_range(quirks, *q, &r);
printf("%s=%d:%d\n", name, r.upper, r.lower);
break;
case QUIRK_ATTR_PALM_SIZE_THRESHOLD:
case QUIRK_ATTR_PALM_PRESSURE_THRESHOLD:
case QUIRK_ATTR_TRACKPOINT_RANGE:
case QUIRK_ATTR_THUMB_PRESSURE_THRESHOLD:
quirks_get_uint32(quirks, *q, &v);
printf("%s=%u\n", name, v);
break;
case QUIRK_ATTR_LID_SWITCH_RELIABILITY:
case QUIRK_ATTR_KEYBOARD_INTEGRATION:
case QUIRK_ATTR_TPKBCOMBO_LAYOUT:
quirks_get_string(quirks, *q, &s);
printf("%s=%s\n", name, s);
break;
}
}
quirks_unref(quirks);
}
static void
usage(void)
{
printf("Usage:\n"
" libinput list-quirks [--data-dir /path/to/data/dir] /dev/input/event0\n"
" Print the quirks for the given device\n"
"\n"
" libinput list-quirks [--data-dir /path/to/data/dir] --validate-only\n"
" Validate the database\n");
}
int
main(int argc, char **argv)
{
struct udev *udev = NULL;
struct udev_device *device = NULL;
const char *path;
const char *data_path = NULL,
*override_file = NULL;
int rc = 1;
struct quirks_context *quirks;
bool validate = false;
while (1) {
int c;
int option_index = 0;
enum {
OPT_VERBOSE,
OPT_DATADIR,
OPT_VALIDATE,
};
static struct option opts[] = {
{ "help", no_argument, 0, 'h' },
{ "verbose", no_argument, 0, OPT_VERBOSE },
{ "data-dir", required_argument, 0, OPT_DATADIR },
{ "validate-only", no_argument, 0, OPT_VALIDATE },
{ 0, 0, 0, 0}
};
c = getopt_long(argc, argv, "h", opts, &option_index);
if (c == -1)
break;
switch(c) {
case '?':
exit(1);
break;
case 'h':
usage();
exit(0);
break;
case OPT_VERBOSE:
verbose = true;
break;
case OPT_DATADIR:
data_path = optarg;
break;
case OPT_VALIDATE:
validate = true;
break;
default:
usage();
return 1;
}
}
if (optind >= argc && !validate) {
usage();
return 1;
}
/* Overriding the data dir means no custom override file */
if (!data_path) {
data_path = LIBINPUT_DATA_DIR;
override_file = LIBINPUT_DATA_OVERRIDE_FILE;
}
quirks = quirks_init_subsystem(data_path,
override_file,
log_handler,
NULL,
QLOG_CUSTOM_LOG_PRIORITIES);
if (!quirks) {
fprintf(stderr,
"Failed to initialize the device quirks. "
"Please see the above errors "
"and/or re-run with --verbose for more details\n");
return 1;
}
if (validate) {
rc = 0;
goto out;
}
udev = udev_new();
path = argv[optind];
if (strneq(path, "/sys/", 5)) {
device = udev_device_new_from_syspath(udev, path);
} else {
struct stat st;
if (stat(path, &st) < 0) {
fprintf(stderr, "Error: %s: %m\n", path);
goto out;
}
device = udev_device_new_from_devnum(udev, 'c', st.st_rdev);
}
if (device) {
list_device_quirks(quirks, device);
rc = 0;
} else {
usage();
rc = 1;
}
udev_device_unref(device);
out:
udev_unref(udev);
quirks_context_unref(quirks);
return rc;
}