libinput/udev/libinput-fuzz-to-zero.c
Peter Hutterer e7a9c07ffe udev: parse the EVDEV_ABS properties for a potential fuzz setting
Where a fuzz is defined in the 60-evdev.hwdb, we rely on a udev builtin to
set the kernel device to that fuzz value. Unfortunately that happens after our
program is called with this order of events:
1. 60-evdev.rules calls IMPORT(builtin) for the hwdb which sets the EVDEV_ABS_*
  properties. It also sets RUN{builtin}=keyboard but that's not invoked yet.
2. 90-libinput-fuzz-override.rules calls IMPORT{program} for our fuzz override
  bits. That sets the kernel fuzz value to 0 and sets the LIBINPUT_FUZZ_*
  propertie
3. The keyboard builtin is run once all the rules have been processed.

Our problem is that where the fuzz is set in a hwdb entry, the kernel fuzz is
still unset when we get to look at it, so we always end up with a fuzz of zero
for us and a nonzero kernel fuzz.

Work around this by checking the EVDEV_ABS property, extracting the fuzz from
there and re-printing that property without the fuzz. This way we ensure the
kernel remains at zero fuzz and we use the one from the hwdb instead.

Fixes #346

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
2019-09-11 12:24:02 +10:00

118 lines
2.7 KiB
C

/*
* 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 <stdint.h>
#include <string.h>
#include <unistd.h>
#include <libudev.h>
#include <linux/input.h>
#include <libevdev/libevdev.h>
#include "util-strings.h"
#include "util-macros.h"
#include "util-bits.h"
static void
reset_absfuzz_to_zero(struct udev_device *device)
{
const char *devnode;
struct libevdev *evdev = NULL;
int fd = -1;
int rc;
unsigned int *code;
unsigned int axes[] = {ABS_X,
ABS_Y,
ABS_MT_POSITION_X,
ABS_MT_POSITION_Y};
devnode = udev_device_get_devnode(device);
if (!devnode)
goto out;
fd = open(devnode, O_RDWR);
if (fd < 0)
goto out;
rc = libevdev_new_from_fd(fd, &evdev);
if (rc != 0)
goto out;
if (!libevdev_has_event_type(evdev, EV_ABS))
goto out;
ARRAY_FOR_EACH(axes, code) {
struct input_absinfo abs;
int fuzz;
fuzz = libevdev_get_abs_fuzz(evdev, *code);
if (!fuzz)
continue;
abs = *libevdev_get_abs_info(evdev, *code);
abs.fuzz = 0;
libevdev_kernel_set_abs_info(evdev, *code, &abs);
}
out:
close(fd);
libevdev_free(evdev);
}
int main(int argc, char **argv)
{
int rc = 1;
struct udev *udev = NULL;
struct udev_device *device = NULL;
const char *syspath;
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;
reset_absfuzz_to_zero(device);
rc = 0;
out:
if (device)
udev_device_unref(device);
if (udev)
udev_unref(udev);
return rc;
}