[PATCH libinput 5/9] udev: add Elantech touchpad firmware detection
Hans de Goede
hdegoede at redhat.com
Wed Jul 8 05:34:43 PDT 2015
Hi,
On 01-07-15 08:08, Peter Hutterer wrote:
> Only firmware v4 (and probably whatever comes in the future) have resolution
> set, for the first couple of touchpads we need size hints. Add a callout that
> looks at the properties on the touchpad and decides the firmware version.
>
> The udev/hwdb is two-stage: the callout sets LIBINPUT_MODEL_FIRMWARE_VERSION
> which is then used in the hwdb to look up the actual size hint. This way we
> can keep the code relatively stable, the actual database of entries is just a
> text file.
>
> Size for the touchpads is pretty much arbitrary at this point. The v1, v2
> sizes are the ones from a Lenovo T61 which is a Synaptics touchpad but
> probably the same vintage.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> udev/.gitignore | 1 +
> udev/90-libinput-model-quirks.hwdb | 12 ++-
> udev/90-libinput-model-quirks.rules.in | 15 +++-
> udev/Makefile.am | 10 ++-
> udev/libinput-model-quirks.c | 146 +++++++++++++++++++++++++++++++++
> 5 files changed, 181 insertions(+), 3 deletions(-)
> create mode 100644 udev/libinput-model-quirks.c
>
> diff --git a/udev/.gitignore b/udev/.gitignore
> index 72c77a0..2fdaedc 100644
> --- a/udev/.gitignore
> +++ b/udev/.gitignore
> @@ -1,2 +1,3 @@
> libinput-device-group
> +libinput-model-quirks
> *.rules
> diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb
> index cf57e9c..3bfffbb 100644
> --- a/udev/90-libinput-model-quirks.hwdb
> +++ b/udev/90-libinput-model-quirks.hwdb
> @@ -11,7 +11,7 @@
> # Match string formats:
> # libinput:<modalias>
> # libinput:name:<name>:dmi:<dmi string>
> -
> +# libinput:name:<name>:fwversion:<version>
> #
> # Sort by brand, model
>
> @@ -30,6 +30,16 @@ libinput:touchpad:input:b0005v05ACp*
> LIBINPUT_MODEL_APPLE_TOUCHPAD=1
>
> ##########################################
> +# Elantech
> +##########################################
> +libinput:name:*Elantech*:fwversion:1
> +libinput:name:*Elantech*:fwversion:2
> + LIBINPUT_ATTR_SIZE_HINT=55x38
> +
> +libinput:name:*Elantech*:fwversion:3
> + LIBINPUT_ATTR_SIZE_HINT=70x50
> +
> +##########################################
> # Google
> ##########################################
>
> diff --git a/udev/90-libinput-model-quirks.rules.in b/udev/90-libinput-model-quirks.rules.in
> index 43674f5..fec071a 100644
> --- a/udev/90-libinput-model-quirks.rules.in
> +++ b/udev/90-libinput-model-quirks.rules.in
> @@ -11,6 +11,20 @@
> ACTION!="add|change", GOTO="libinput_model_quirks_end"
> KERNEL!="event*", GOTO="libinput_model_quirks_end"
>
> +# Touchpad firmware detection, two-stage process.
> +# First, run the program and import the LIBINPUT_MODEL_FIRMWARE_VERSION
> +# environment (if any)
> +KERNELS=="*input*", \
> + ENV{ID_INPUT_TOUCHPAD}=="1", \
> + IMPORT{program}="@UDEV_TEST_PATH at libinput-model-quirks %S%p"
> +
> +# Second, match on anything with that env set and import from the hwdb
> +KERNELS=="*input*", \
> + ENV{ID_INPUT_TOUCHPAD}=="1", \
> + ENV{LIBINPUT_MODEL_FIRMWARE_VERSION}!="", \
> + IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:fwversion:$env{LIBINPUT_MODEL_FIRMWARE_VERSION}'"
> +# End of touchpad firmware detection
> +
> # Matches below are exclusive, if one matches we skip the rest
> # hwdb matches:
> #
> @@ -24,5 +38,4 @@ KERNELS=="input*", \
> IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:$attr{[dmi/id]modalias}'", \
> GOTO="libinput_model_quirks_end"
>
> -
> LABEL="libinput_model_quirks_end"
> diff --git a/udev/Makefile.am b/udev/Makefile.am
> index e5cf95c..e850e09 100644
> --- a/udev/Makefile.am
> +++ b/udev/Makefile.am
> @@ -1,5 +1,6 @@
> udevdir=$(UDEV_DIR)
> -udev_PROGRAMS = libinput-device-group
> +udev_PROGRAMS = libinput-device-group \
> + libinput-model-quirks
>
> litest_rules = 80-libinput-device-groups-litest.rules \
> 90-libinput-model-quirks-litest.rules
> @@ -9,6 +10,13 @@ libinput_device_group_SOURCES = libinput-device-group.c
> libinput_device_group_CFLAGS = $(LIBUDEV_CFLAGS) $(GCC_CFLAGS)
> libinput_device_group_LDADD = $(LIBUDEV_LIBS)
>
> +libinput_model_quirks_SOURCES = libinput-model-quirks.c
> +libinput_model_quirks_CFLAGS = \
> + -I$(top_srcdir)/src \
> + $(LIBUDEV_CFLAGS) \
> + $(GCC_CFLAGS)
> +libinput_model_quirks_LDADD = $(LIBUDEV_LIBS)
> +
> udev_rulesdir=$(UDEV_DIR)/rules.d
> dist_udev_rules_DATA = \
> 80-libinput-device-groups.rules \
> diff --git a/udev/libinput-model-quirks.c b/udev/libinput-model-quirks.c
> new file mode 100644
> index 0000000..87c19d4
> --- /dev/null
> +++ b/udev/libinput-model-quirks.c
> @@ -0,0 +1,146 @@
> +/*
> + * Copyright © 2015 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 <fcntl.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <libudev.h>
> +#include <linux/input.h>
> +
> +#include "libinput-util.h"
> +
> +static inline const char *
> +prop_value(struct udev_device *device,
> + const char *prop_name)
> +{
> + struct udev_device *parent;
> + const char *prop_value = NULL;
> +
> + parent = device;
> + while (parent && !prop_value) {
> + prop_value = udev_device_get_property_value(parent, prop_name);
> + parent = udev_device_get_parent(parent);
> + }
> +
> + return prop_value;
> +}
> +
> +static void
> +handle_touchpad_elantech(struct udev_device *device)
> +{
> + const char *devpath;
> + int fd;
> + unsigned int version = 0;
> + struct input_absinfo absinfo;
> + unsigned long props[NLONGS(INPUT_PROP_CNT)];
> +
> + devpath = udev_device_get_devnode(device);
> + fd = open(devpath, O_RDONLY|O_CLOEXEC);
> + if (fd < 1)
> + return;
> +
> + /* Elantech v4: has resolution, we also assume that future versions
> + * will have resolution */
> + if (ioctl(fd, EVIOCGABS(ABS_X), &absinfo) < 0)
> + return;
> +
> + if (absinfo.resolution != 0) {
> + version = 4;
> + goto out;
> + }
> +
> + if (ioctl(fd, EVIOCGPROP(sizeof(props)), props) < 0)
> + goto out;
> +
> + /* Elantech v3: always a buttonpad */
> + if (long_bit_is_set(props, INPUT_PROP_BUTTONPAD)) {
> + version = 3;
> + goto out;
> + }
This is not true, some older kernels used to do this, but itis wrong,
newer kernels have:
case 2:
__set_bit(BTN_TOOL_QUADTAP, dev->keybit);
__set_bit(INPUT_PROP_SEMI_MT, dev->propbit);
/* fall through */
case 3:
if (etd->hw_version == 3)
elantech_set_buttonpad_prop(psmouse);
And:
static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
{
struct input_dev *dev = psmouse->dev;
struct elantech_data *etd = psmouse->private;
if (etd->fw_version & 0x001000) {
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
__clear_bit(BTN_RIGHT, dev->keybit);
}
}
Which dynamically detects if an elantech is a buttonpad or not,
and there are v3 devices out there of both variants.
Given the info we recently got from elantech that all <= v3
devices have a fixed resolution I guess we no longer need this.
I wonder if we should even bother handling this in userspace
for elantech devices at all. We can make the kernel driver
report the fixed resolution of for <= v3 device with a 1 line
kernel patch. I seem to have misplaced the mail from elantech with
the actual resolution, can you remind me what it was again ?
REgards,
Hans
More information about the wayland-devel
mailing list