From 43a3a6ced0f86803794367d0e5ec135f1aa5e570 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 10 Feb 2015 16:05:04 +1000 Subject: [PATCH 1/9] evdev: add missing %s for accelerometer tagging Oh gcc warning, where are thou? Signed-off-by: Peter Hutterer --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index c2d172fc..525d5d7c 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1393,7 +1393,7 @@ evdev_configure_device(struct evdev_device *device) } log_info(libinput, - "input device '%s', %s is tagged by udev as:%s%s%s%s%s%s\n", + "input device '%s', %s is tagged by udev as:%s%s%s%s%s%s%s\n", device->devname, devnode, udev_tags & EVDEV_UDEV_TAG_KEYBOARD ? " Keyboard" : "", udev_tags & EVDEV_UDEV_TAG_MOUSE ? " Mouse" : "", From d6da0e18c21a18c00c29104a8ba2febe1315207c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Feb 2015 13:48:34 +1000 Subject: [PATCH 2/9] Add two missing @ref tags Signed-off-by: Peter Hutterer --- src/libinput.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libinput.h b/src/libinput.h index 577c0067..857b3fa8 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -730,11 +730,11 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, * The coordinate system is identical to the cursor movement, i.e. a * scroll value of 1 represents the equivalent relative motion of 1. * - * For pointer events that are not of type LIBINPUT_EVENT_POINTER_AXIS, + * For pointer events that are not of type @ref LIBINPUT_EVENT_POINTER_AXIS, * this function returns 0. * * @note It is an application bug to call this function for events other than - * LIBINPUT_EVENT_POINTER_AXIS. + * @ref LIBINPUT_EVENT_POINTER_AXIS. * * @return the source for this axis event */ From a9f216ab47ea2f643f20ed741b741a2b5766eba3 Mon Sep 17 00:00:00 2001 From: Marek Chalupa Date: Thu, 12 Feb 2015 09:25:36 -0500 Subject: [PATCH 3/9] add simple symbols leak checker This patch adds simple script that compares libinput.sym file to the functions that are marked by LIBINPUT_EXPORT. This script is added to make check target. Signed-off-by: Marek Chalupa Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- .gitignore | 1 + configure.ac | 3 +++ test/Makefile.am | 3 ++- test/symbols-leak-test.in | 17 +++++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100755 test/symbols-leak-test.in diff --git a/.gitignore b/.gitignore index 3ea8576b..2253d454 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,5 @@ doc/libinput.doxygen doc/html tags test/test-* +test/symbols-leak-test* test-driver diff --git a/configure.ac b/configure.ac index f47c5a49..1e60e585 100644 --- a/configure.ac +++ b/configure.ac @@ -164,6 +164,9 @@ AC_CONFIG_FILES([Makefile src/libinput-version.h test/Makefile tools/Makefile]) +AC_CONFIG_FILES([test/symbols-leak-test], + [chmod +x test/symbols-leak-test]) + AC_OUTPUT AC_MSG_RESULT([ diff --git a/test/Makefile.am b/test/Makefile.am index 5b9c7ab6..5743ca4f 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -50,7 +50,8 @@ build_tests = \ test-build-std-gnuc90 noinst_PROGRAMS = $(build_tests) $(run_tests) -TESTS = $(run_tests) +noinst_SCRIPTS = symbols-leak-test +TESTS = $(run_tests) symbols-leak-test .NOTPARALLEL: diff --git a/test/symbols-leak-test.in b/test/symbols-leak-test.in new file mode 100755 index 00000000..448ef2f8 --- /dev/null +++ b/test/symbols-leak-test.in @@ -0,0 +1,17 @@ +#!/bin/bash + +### simple check for exported symbols + +# make bash exit if any command will exit with non-0 return value +set -e + +# make sure the paths are alright +cd `dirname $0` + +diff -a -u \ + <(cat @top_srcdir@/src/libinput.sym | \ + grep '^\s\+libinput_.*' | \ + sed -e 's/^\s\+\(.*\);/\1/' | sort) \ + <(cat @top_srcdir@/src/*.c | \ + grep LIBINPUT_EXPORT -A 1 | grep '^libinput_.*' | \ + sed -e 's/(.*//' | sort) From 761baeb6e608a73bbcb464d998ca24ba09d282de Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 13 Feb 2015 14:36:56 +1000 Subject: [PATCH 4/9] Add libinput_device_pointer_has_button over the plain has_button If a device has multiple capabilities, has_button is imprecise. A device with tablet and pointer capability for example may have BTN_LEFT on the pointer interface but not on the tablet interface. Signed-off-by: Peter Hutterer --- src/libinput.c | 10 ++++++++-- src/libinput.h | 10 +++++++++- src/libinput.sym | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/libinput.c b/src/libinput.c index 81862d56..b903caa6 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1364,11 +1364,17 @@ libinput_device_get_size(struct libinput_device *device, } LIBINPUT_EXPORT int -libinput_device_has_button(struct libinput_device *device, uint32_t code) +libinput_device_pointer_has_button(struct libinput_device *device, uint32_t code) { return evdev_device_has_button((struct evdev_device *)device, code); } +LIBINPUT_EXPORT int +libinput_device_has_button(struct libinput_device *device, uint32_t code) +{ + return libinput_device_pointer_has_button(device, code); +} + LIBINPUT_EXPORT struct libinput_event * libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event) { @@ -1805,7 +1811,7 @@ LIBINPUT_EXPORT enum libinput_config_status libinput_device_config_scroll_set_button(struct libinput_device *device, uint32_t button) { - if (button && !libinput_device_has_button(device, button)) + if (button && !libinput_device_pointer_has_button(device, button)) return LIBINPUT_CONFIG_STATUS_INVALID; if ((libinput_device_config_scroll_get_methods(device) & diff --git a/src/libinput.h b/src/libinput.h index 857b3fa8..0fdca7b7 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -1661,7 +1661,15 @@ libinput_device_get_size(struct libinput_device *device, * on error. */ int -libinput_device_has_button(struct libinput_device *device, uint32_t code); +libinput_device_pointer_has_button(struct libinput_device *device, uint32_t code); + +/** + * @ingroup device + * + * @deprecated Use libinput_device_pointer_has_button() instead. + */ +int +libinput_device_has_button(struct libinput_device *device, uint32_t code) LIBINPUT_ATTRIBUTE_DEPRECATED; /** * @ingroup device diff --git a/src/libinput.sym b/src/libinput.sym index cf13789f..644e9105 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -133,4 +133,6 @@ LIBINPUT_0.11.0 { libinput_device_group_ref; libinput_device_group_set_user_data; libinput_device_group_unref; + + libinput_device_pointer_has_button; } LIBINPUT_0.9.0; From f0d7eaf11e40e54fe3ace5c50718168c66d45c7a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 10 Feb 2015 14:59:05 +1000 Subject: [PATCH 5/9] tools: print the device group in event-debug Signed-off-by: Peter Hutterer Reviewed-by: Benjamin Tissoires --- tools/event-debug.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/event-debug.c b/tools/event-debug.c index 297e47d8..38a6e823 100644 --- a/tools/event-debug.c +++ b/tools/event-debug.c @@ -122,13 +122,24 @@ print_device_notify(struct libinput_event *ev) { struct libinput_device *dev = libinput_event_get_device(ev); struct libinput_seat *seat = libinput_device_get_seat(dev); + struct libinput_device_group *group; double w, h; uint32_t scroll_methods; + static int next_group_id = 0; + intptr_t group_id; - printf("%-33s %5s %7s", + group = libinput_device_get_device_group(dev); + group_id = (intptr_t)libinput_device_group_get_user_data(group); + if (!group_id) { + group_id = ++next_group_id; + libinput_device_group_set_user_data(group, (void*)group_id); + } + + printf("%-33s %5s %7s group%d", libinput_device_get_name(dev), libinput_seat_get_physical_name(seat), - libinput_seat_get_logical_name(seat)); + libinput_seat_get_logical_name(seat), + (int)group_id); printf(" cap:"); if (libinput_device_has_capability(dev, From 2b2a1b0eb9f4e3bc835401e1436731fcf4b2163b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 10 Feb 2015 14:23:32 +1000 Subject: [PATCH 6/9] Add udev bits to assign LIBINPUT_DEVICE_GROUP The easiest way to get a device group is by looking at the phys path of the input device (which looks like usb-0000:00:14.0-1/input1) and dropping the /inputX bit. The rest is the same for devices that belong together (except on the Cintiq 22HD Touch). Ideally we could just take ATTRS{phys} but we can't select substrings to drop into ENV so we need to do it ourselves. This patch adds a callout that takes a syspath and prints the mangled path, to be used in LIBINPUT_DEVICE_GROUP. The rule triggers on any device that has a non-zero phys attribute, this groups devices like tablets together but also devices like mice with multiple interfaces. Signed-off-by: Peter Hutterer Tested-by: Benjamin Tissoires --- Makefile.am | 2 +- configure.ac | 18 ++++++- udev/.gitignore | 1 + udev/80-libinput-device-groups.rules | 8 +++ udev/Makefile.am | 9 ++++ udev/libinput-device-group.c | 77 ++++++++++++++++++++++++++++ 6 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 udev/.gitignore create mode 100644 udev/80-libinput-device-groups.rules create mode 100644 udev/Makefile.am create mode 100644 udev/libinput-device-group.c diff --git a/Makefile.am b/Makefile.am index 05698ba5..fc6e6b79 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = src doc test tools +SUBDIRS = src doc test tools udev ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} diff --git a/configure.ac b/configure.ac index 1e60e585..2ccd30d7 100644 --- a/configure.ac +++ b/configure.ac @@ -69,6 +69,19 @@ fi AC_SUBST(GCC_CFLAGS) AC_SUBST(GCC_CXXFLAGS) +udev_dir_default="$libdir/udev" +AC_ARG_WITH(udev-dir, + AS_HELP_STRING([--with-udev-dir=DIR], + [udev base directory [[default=$udev_dir_default]]]), + [], + [with_udev_dir="yes"]) +AS_CASE($with_udev_dir, + [no|""], [AC_MSG_ERROR([You must define a udev base directory])], + [yes], [udevdir="$udev_dir_default"], + [udevdir="$with_udev_dir"]) +UDEV_DIR=${udevdir} +AC_SUBST(UDEV_DIR) + AC_ARG_ENABLE([documentation], [AC_HELP_STRING([--enable-documentation], [Enable building the documentation (default=auto)])], @@ -163,14 +176,15 @@ AC_CONFIG_FILES([Makefile src/libinput.pc src/libinput-version.h test/Makefile - tools/Makefile]) + tools/Makefile + udev/Makefile]) AC_CONFIG_FILES([test/symbols-leak-test], [chmod +x test/symbols-leak-test]) - AC_OUTPUT AC_MSG_RESULT([ Prefix ${prefix} + udev base dir ${UDEV_DIR} Build documentation ${build_documentation} Build tests ${build_tests} diff --git a/udev/.gitignore b/udev/.gitignore new file mode 100644 index 00000000..d8e1456b --- /dev/null +++ b/udev/.gitignore @@ -0,0 +1 @@ +libinput-device-group diff --git a/udev/80-libinput-device-groups.rules b/udev/80-libinput-device-groups.rules new file mode 100644 index 00000000..f826bec6 --- /dev/null +++ b/udev/80-libinput-device-groups.rules @@ -0,0 +1,8 @@ +ACTION!="add|change", GOTO="libinput_device_group_end" +KERNEL!="event[0-9]*", GOTO="libinput_device_group_end" + +ATTRS{phys}=="?*", \ + PROGRAM="libinput-device-group %S%p", \ + ENV{LIBINPUT_DEVICE_GROUP}="%c" + +LABEL="libinput_device_group_end" diff --git a/udev/Makefile.am b/udev/Makefile.am new file mode 100644 index 00000000..3691172c --- /dev/null +++ b/udev/Makefile.am @@ -0,0 +1,9 @@ +udevdir=$(UDEV_DIR) +udev_PROGRAMS = libinput-device-group + +libinput_device_group_SOURCES = libinput-device-group.c +libinput_device_group_CFLAGS = $(LIBUDEV_CFLAGS) $(GCC_CFLAGS) +libinput_device_group_LDADD = $(LIBUDEV_LIBS) + +udev_rulesdir=$(UDEV_DIR)/rules.d +dist_udev_rules_DATA = 80-libinput-device-groups.rules diff --git a/udev/libinput-device-group.c b/udev/libinput-device-group.c new file mode 100644 index 00000000..50bfbe02 --- /dev/null +++ b/udev/libinput-device-group.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int rc = 1; + struct udev *udev = NULL; + struct udev_device *device = NULL; + const char *syspath, + *phys = NULL; + char *group, + *str; + + if (argc != 2) + return 1; + + syspath = argv[1]; + + udev = udev_new(); + if (!udev) + goto out; + + device = udev_device_new_from_syspath(udev, syspath); + if (!device) + goto out; + + /* Find the first parent with ATTRS{phys} set. For tablets that + * value looks like usb-0000:00:14.0-1/input1. Drop the /input1 + * bit and use the remainder as device group identifier */ + while (device != NULL) { + struct udev_device *parent; + + phys = udev_device_get_sysattr_value(device, "phys"); + if (phys) + break; + + parent = udev_device_get_parent(device); + udev_device_ref(parent); + udev_device_unref(device); + device = parent; + } + + if (!phys) + goto out; + + group = strdup(phys); + if (!group) + goto out; + + str = strstr(group, "/input"); + if (str) + *str = '\0'; + + /* Cintiq 22HD Touch has + usb-0000:00:14.0-6.3.1/input0 for the touch + usb-0000:00:14.0-6.3.0/input0 for the pen + Check if there's a . after the last -, if so, cut off the string + there. + */ + str = strrchr(group, '.'); + if (str && str > strrchr(group, '-')) + *str = '\0'; + + printf("%s\n", group); + free(group); + + rc = 0; +out: + if (device) + udev_device_unref(device); + if (udev) + udev_unref(udev); + + return rc; +} From cbeacfed13e164d3c7ba549a63f08317f067d884 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 9 Feb 2015 18:45:45 -0500 Subject: [PATCH 7/9] Use LIBINPUT_DEVICE_GROUP from udev as group identifier Store it as identifier in the device group, any two devices that have a the same non-NULL identifier share the group. Signed-off-by: Benjamin Tissoires Signed-off-by: Peter Hutterer --- doc/device-configuration-via-udev.dox | 5 ++++ src/evdev.c | 42 +++++++++++++++++++++++---- src/libinput-private.h | 3 +- src/libinput.c | 17 +++++++++-- src/libinput.h | 3 ++ 5 files changed, 61 insertions(+), 9 deletions(-) diff --git a/doc/device-configuration-via-udev.dox b/doc/device-configuration-via-udev.dox index bee36598..68a45af0 100644 --- a/doc/device-configuration-via-udev.dox +++ b/doc/device-configuration-via-udev.dox @@ -12,6 +12,11 @@ The following udev properties are supported:
Sets the calibration matrix, see libinput_device_config_calibration_get_default_matrix(). If unset, defaults to the identity matrix.
+
LIBINPUT_DEVICE_GROUP
+
A string identifying the @ref libinput_device_group for this device. Two +devices with the same property value are grouped into the same device group, +the value itself is irrelevant otherwise. +
ID_SEAT
Assigns the physical seat for this device. See libinput_seat_get_physical_name(). Defaults to "seat0".
diff --git a/src/evdev.c b/src/evdev.c index 525d5d7c..11fa89ba 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1579,6 +1579,42 @@ out: return rc; } +static int +evdev_set_device_group(struct evdev_device *device, + struct udev_device *udev_device) +{ + struct libinput_device_group *group = NULL; + const char *udev_group; + + udev_group = udev_device_get_property_value(udev_device, + "LIBINPUT_DEVICE_GROUP"); + if (udev_group) { + struct libinput_device *d; + + list_for_each(d, &device->base.seat->devices_list, link) { + const char *identifier = d->group->identifier; + + if (identifier && + strcmp(identifier, udev_group) == 0) { + group = d->group; + break; + } + } + } + + if (!group) { + group = libinput_device_group_create(udev_group); + if (!group) + return 1; + libinput_device_set_device_group(&device->base, group); + libinput_device_group_unref(group); + } else { + libinput_device_set_device_group(&device->base, group); + } + + return 0; +} + struct evdev_device * evdev_device_create(struct libinput_seat *seat, struct udev_device *udev_device) @@ -1589,7 +1625,6 @@ evdev_device_create(struct libinput_seat *seat, int fd; int unhandled_device = 0; const char *devnode = udev_device_get_devnode(udev_device); - struct libinput_device_group *group; /* Use non-blocking mode so that we can loop on read on * evdev_device_data() until all events on the fd are @@ -1660,11 +1695,8 @@ evdev_device_create(struct libinput_seat *seat, if (!device->source) goto err; - group = libinput_device_group_create(); - if (!group) + if (evdev_set_device_group(device, udev_device)) goto err; - libinput_device_set_device_group(&device->base, group); - libinput_device_group_unref(group); list_insert(seat->devices_list.prev, &device->base.link); diff --git a/src/libinput-private.h b/src/libinput-private.h index 23f66e40..14f5d674 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -168,6 +168,7 @@ struct libinput_device_config { struct libinput_device_group { int refcount; void *user_data; + char *identifier; /* unique identifier or NULL for singletons */ }; struct libinput_device { @@ -247,7 +248,7 @@ libinput_device_init(struct libinput_device *device, struct libinput_seat *seat); struct libinput_device_group * -libinput_device_group_create(void); +libinput_device_group_create(const char *identifier); void libinput_device_set_device_group(struct libinput_device *device, diff --git a/src/libinput.c b/src/libinput.c index b903caa6..bb0595e6 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1407,13 +1407,23 @@ libinput_device_group_ref(struct libinput_device_group *group) } struct libinput_device_group * -libinput_device_group_create(void) +libinput_device_group_create(const char *identifier) { struct libinput_device_group *group; group = zalloc(sizeof *group); - if (group) - group->refcount = 1; + if (!group) + return NULL; + + group->refcount = 1; + if (identifier) { + group->identifier = strdup(identifier); + if (!group->identifier) { + free(group); + group = NULL; + } + } + return group; } @@ -1428,6 +1438,7 @@ libinput_device_set_device_group(struct libinput_device *device, static void libinput_device_group_destroy(struct libinput_device_group *group) { + free(group->identifier); free(group); } diff --git a/src/libinput.h b/src/libinput.h index 0fdca7b7..09503a29 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -1471,6 +1471,9 @@ libinput_device_get_context(struct libinput_device *device); * libinput_device_group_unref() to continue using the handle outside of the * immediate scope. * + * Device groups are assigned based on the LIBINPUT_DEVICE_GROUP udev + * property, see @ref udev_config. + * * @return The device group this device belongs to */ struct libinput_device_group * From 65e077759b1a1ca3218e27ae32c46b901a747c05 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 13 Feb 2015 11:40:19 +1000 Subject: [PATCH 8/9] evdev: check the first parent of the event node for ID_INPUT tags Bluetooth tablet devices' rules can't tag the event node directly, they can only tag the first parent (the /sys/class/input/input1234 node). Check that parent for tags too, lest we miss something important. Signed-off-by: Peter Hutterer Tested-by: Benjamin Tissoires --- src/evdev.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 11fa89ba..cf21d2e2 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1356,16 +1356,23 @@ evdev_device_get_udev_tags(struct evdev_device *device, { const char *prop; enum evdev_device_udev_tags tags = 0; - const struct evdev_udev_tag_match *match = evdev_udev_tag_matches; + const struct evdev_udev_tag_match *match; + int i; - while (match->name) { - prop = udev_device_get_property_value(device->udev_device, + for (i = 0; i < 2 && udev_device; i++) { + match = evdev_udev_tag_matches; + while (match->name) { + prop = udev_device_get_property_value( + udev_device, match->name); - if (prop) - tags |= match->tag; + if (prop) + tags |= match->tag; - match++; + match++; + } + udev_device = udev_device_get_parent(udev_device); } + return tags; } From a138069d5c8ce23dd9fafa3ff89d89a8bed9b1b0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 18 Feb 2015 07:43:03 +1000 Subject: [PATCH 9/9] Rename noaccel to unaccel for consistency No functional changes, this affects the declaration only. Signed-off-by: Peter Hutterer --- src/libinput-private.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libinput-private.h b/src/libinput-private.h index 14f5d674..410f39a8 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -283,8 +283,8 @@ pointer_notify_motion(struct libinput_device *device, uint64_t time, double dx, double dy, - double dx_noaccel, - double dy_noaccel); + double dx_unaccel, + double dy_unaccel); void pointer_notify_motion_absolute(struct libinput_device *device,