[PATCH libevdev 4/4] uinput: support the new UI_DEV_SETUP/UI_ABS_SETUP ioctls

Benjamin Tissoires benjamin.tissoires at gmail.com
Wed Apr 13 19:05:55 UTC 2016


On Thu, Apr 7, 2016 at 3:34 AM, Peter Hutterer <peter.hutterer at who-t.net> wrote:
> Available in kernel 4.5 and later (uinput version 5), these ioctls allow us to
> set the absinfo correctly, i.e. including the resolution.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---

Looks good to me:
Reviewed-by: Benjamin Tissoires <benjamin.tissoires at gmail.com>

Cheers,
Benjamin

>  libevdev/libevdev-uinput.c | 74 +++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 64 insertions(+), 10 deletions(-)
>
> diff --git a/libevdev/libevdev-uinput.c b/libevdev/libevdev-uinput.c
> index 0046607..893d169 100644
> --- a/libevdev/libevdev-uinput.c
> +++ b/libevdev/libevdev-uinput.c
> @@ -62,6 +62,19 @@ alloc_uinput_device(const char *name)
>         return uinput_dev;
>  }
>
> +static inline int
> +set_abs(const struct libevdev *dev, int fd, unsigned int code)
> +{
> +       const struct input_absinfo *abs = libevdev_get_abs_info(dev, code);
> +       struct uinput_abs_setup abs_setup = {0};
> +       int rc;
> +
> +       abs_setup.code = code;
> +       abs_setup.absinfo = *abs;
> +       rc = ioctl(fd, UI_ABS_SETUP, &abs_setup);
> +       return rc;
> +}
> +
>  static int
>  set_evbits(const struct libevdev *dev, int fd, struct uinput_user_dev *uidev)
>  {
> @@ -113,13 +126,21 @@ set_evbits(const struct libevdev *dev, int fd, struct uinput_user_dev *uidev)
>                                 goto out;
>
>                         if (type == EV_ABS) {
> -                               const struct input_absinfo *abs = libevdev_get_abs_info(dev, code);
> -                               uidev->absmin[code] = abs->minimum;
> -                               uidev->absmax[code] = abs->maximum;
> -                               uidev->absfuzz[code] = abs->fuzz;
> -                               uidev->absflat[code] = abs->flat;
> -                               /* uinput has no resolution in the device struct, this needs
> -                                * to be fixed in the kernel */
> +                               if (uidev == NULL) {
> +                                       rc = set_abs(dev, fd, code);
> +                                       if (rc != 0)
> +                                               goto out;
> +                               } else {
> +                                       const struct input_absinfo *abs =
> +                                               libevdev_get_abs_info(dev, code);
> +
> +                                       uidev->absmin[code] = abs->minimum;
> +                                       uidev->absmax[code] = abs->maximum;
> +                                       uidev->absfuzz[code] = abs->fuzz;
> +                                       uidev->absflat[code] = abs->flat;
> +                                       /* uinput has no resolution in the
> +                                        * device struct */
> +                               }
>                         }
>                 }
>
> @@ -272,8 +293,8 @@ fetch_syspath_and_devnode(struct libevdev_uinput *uinput_dev)
>  }
>
>  static int
> -uinput_create(const struct libevdev *dev, int fd,
> -             struct libevdev_uinput *new_device)
> +uinput_create_write(const struct libevdev *dev, int fd,
> +                   struct libevdev_uinput *new_device)
>  {
>         int rc;
>         struct uinput_user_dev uidev;
> @@ -305,12 +326,40 @@ error:
>         return -errno;
>  }
>
> +static int
> +uinput_create_DEV_SETUP(const struct libevdev *dev, int fd,
> +                       struct libevdev_uinput *new_device)
> +{
> +       int rc;
> +       struct uinput_setup setup;
> +
> +       if (set_evbits(dev, fd, NULL) != 0)
> +               goto error;
> +       if (set_props(dev, fd) != 0)
> +               goto error;
> +
> +       memset(&setup, 0, sizeof(setup));
> +       strncpy(setup.name, libevdev_get_name(dev), UINPUT_MAX_NAME_SIZE - 1);
> +       setup.id.vendor = libevdev_get_id_vendor(dev);
> +       setup.id.product = libevdev_get_id_product(dev);
> +       setup.id.bustype = libevdev_get_id_bustype(dev);
> +       setup.id.version = libevdev_get_id_version(dev);
> +       setup.ff_effects_max = libevdev_has_event_type(dev, EV_FF) ? 10 : 0;
> +
> +       rc = ioctl(fd, UI_DEV_SETUP, &setup);
> +       if (rc == 0)
> +               errno = 0;
> +error:
> +       return -errno;
> +}
> +
>  LIBEVDEV_EXPORT int
>  libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct libevdev_uinput** uinput_dev)
>  {
>         int rc;
>         struct libevdev_uinput *new_device;
>         int close_fd_on_error = (fd == LIBEVDEV_UINPUT_OPEN_MANAGED);
> +       unsigned int uinput_version = 0;
>
>         new_device = alloc_uinput_device(libevdev_get_name(dev));
>         if (!new_device)
> @@ -328,7 +377,12 @@ libevdev_uinput_create_from_device(const struct libevdev *dev, int fd, struct li
>                 goto error;
>         }
>
> -       rc = uinput_create(dev, fd, new_device);
> +       if (ioctl(fd, UI_GET_VERSION, &uinput_version) == 0 &&
> +           uinput_version >= 5)
> +               rc = uinput_create_DEV_SETUP(dev, fd, new_device);
> +       else
> +               rc = uinput_create_write(dev, fd, new_device);
> +
>         if (rc != 0)
>                 goto error;
>
> --
> 2.5.5
>
> _______________________________________________
> Input-tools mailing list
> Input-tools at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/input-tools


More information about the Input-tools mailing list