[PATCH v2 libinput 07/10] pad: implement support for the Express Key Remote
Jason Gerecke
killertofu at gmail.com
Tue Jun 21 18:01:45 UTC 2016
On 06/14/2016 11:37 PM, Peter Hutterer wrote:
> Requires the newest libwacom. For distributions that want to ship libinput but
> don't have the new libwacom available: the actual minimum requirement is
> libwacom 0.17 but with that test cases will fail due to wrong button labelling
> for the EKR.
>
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> Changes to v1:
> - new in v2
>
> configure.ac | 2 +-
> src/evdev-tablet-pad-leds.c | 131 ++++++++++++++++++++++++++++++++++++-
> src/evdev.c | 1 +
> src/evdev.h | 1 +
> udev/90-libinput-model-quirks.hwdb | 3 +
> 5 files changed, 134 insertions(+), 4 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index 8278be2..740deac 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -203,7 +203,7 @@ AC_ARG_ENABLE(libwacom,
> [use_libwacom="$enableval"],
> [use_libwacom="yes"])
> if test "x$use_libwacom" = "xyes"; then
> - PKG_CHECK_MODULES(LIBWACOM, [libwacom >= 0.17], [HAVE_LIBWACOM="yes"])
> + PKG_CHECK_MODULES(LIBWACOM, [libwacom >= 0.20], [HAVE_LIBWACOM="yes"])
> AC_DEFINE(HAVE_LIBWACOM, 1, [Build with libwacom])
> fi
>
> diff --git a/src/evdev-tablet-pad-leds.c b/src/evdev-tablet-pad-leds.c
> index 87fce7a..c17e70d 100644
> --- a/src/evdev-tablet-pad-leds.c
> +++ b/src/evdev-tablet-pad-leds.c
> @@ -23,6 +23,7 @@
> #include "config.h"
>
> #include <assert.h>
> +#include <dirent.h>
> #include <limits.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> @@ -38,8 +39,10 @@
> struct pad_led_group {
> struct libinput_tablet_pad_mode_group base;
>
> - /* /sys/devices/<hid device>/wacom_led/status_led0_select */
> + /* /sys/devices/<hid device>/wacom_led/status_led0_select or
> + /sys/devices/<hid device>/wacom_remote/<id>/remote_mode on the EKR */
> int led_status_fd;
> + bool self_updating;
>
> struct list toggle_button_list;
> };
> @@ -79,6 +82,15 @@ pad_led_group_set_mode(struct pad_led_group *group,
> char buf[4] = {0};
> int rc;
>
> + /* EKR toggles the mode automatically so we just read the new mode
> + * from the fd */
> + if (group->self_updating) {
> + rc = pad_led_group_get_mode(group);
> + if (rc >= 0)
> + group->base.current_mode = rc;
> + return;
> + }
> +
> rc = snprintf(buf, sizeof(buf), "%d", mode);
> if (rc == -1)
> return;
> @@ -255,6 +267,63 @@ pad_led_get_sysfs_base_path(struct evdev_device *device,
> return rc != -1;
> }
>
> +static bool
> +pad_led_get_sysfs_ekr_path(struct evdev_device *device,
> + char *path_out,
> + size_t path_out_sz)
> +{
> + const char *hid_sysfs_path;
> + char path[PATH_MAX];
> + int rc;
> + DIR *dirp;
> + struct dirent *dp;
> + int serial = 0;
> +
> + hid_sysfs_path = pad_get_hid_sysfs_base_path(device);
> + if (hid_sysfs_path == NULL)
> + return false;
> +
> + rc = snprintf(path, sizeof(path), "%s/wacom_remote", hid_sysfs_path);
> + if (rc == -1)
> + return false;
> +
> + dirp = opendir(path);
> + if (!dirp)
> + return false;
> +
> + while ((dp = readdir(dirp)) != NULL) {
> + if (dp->d_name[0] == '.')
> + continue;
> +
> + /* There should be one entry per remote: the remote's serial
> + * in decimal notation. We always return
> + * the first we find, multiple remotes is not supported yet.
> + */
Supporting multiple EKRs is going to be very difficult given how they
work, so this is probably fine. I would only note that the statement
above doesn't quite mean what some may think. This list of remotes is a
list of *pairings* and may contain remotes which aren't actually within
communication range of the dongle. If more than one remote has ever been
paired with the dongle, this could mean problems. Of course, the list of
pairings can always be cleared by using the 'unpair_remote' sysfs command.
Jason
---
Now instead of four in the eights place /
you’ve got three, ‘Cause you added one /
(That is to say, eight) to the two, /
But you can’t take seven from three, /
So you look at the sixty-fours....
> + if (safe_atoi(dp->d_name, &serial))
> + break;
> + }
> + closedir(dirp);
> +
> + if (serial == 0)
> + return false;
> +
> + rc = snprintf(path_out,
> + path_out_sz,
> + "%s/wacom_remote/%d/remote_mode",
> + hid_sysfs_path,
> + serial);
> + if (rc == -1)
> + return false;
> +
> + rc = access(path, R_OK);
> + if (rc == -1)
> + log_error(device->base.seat->libinput,
> + "Unable to access EKR LED syspath %s (%s)\n",
> + path_out,
> + strerror(errno));
> + return rc != -1;
> +}
> +
> #if HAVE_LIBWACOM
> static int
> pad_init_led_groups(struct pad_dispatch *pad,
> @@ -316,6 +385,51 @@ pad_init_led_groups(struct pad_dispatch *pad,
>
> return 0;
> }
> +
> +static int
> +pad_init_ekr_group(struct pad_dispatch *pad,
> + struct evdev_device *device,
> + WacomDevice *wacom)
> +{
> + struct libinput *libinput = device->base.seat->libinput;
> + struct pad_led_group *group;
> + char syspath[PATH_MAX];
> + int rc = 1;
> + int fd;
> +
> + if (!pad_led_get_sysfs_ekr_path(device, syspath, sizeof(syspath)))
> + return 1;
> +
> + /* EKR has 3 LEDs, hardwired to the toggle button */
> + group = pad_group_new_basic(pad, 0, 3);
> + if (!group)
> + return 1;
> +
> + fd = open_restricted(libinput, syspath, O_RDONLY);
> + if (fd < 0) {
> + errno = -fd;
> + goto error;
> + }
> + group->led_status_fd = fd;
> + group->self_updating = true;
> +
> + rc = pad_led_group_get_mode(group);
> + if (rc < 0) {
> + errno = -rc;
> + goto error;
> + }
> +
> + group->base.current_mode = rc;
> +
> + list_insert(&pad->modes.mode_group_list, &group->base.link);
> +
> + return 0;
> +error:
> + log_error(libinput, "Unable to init EKR LED group: %s\n", strerror(errno));
> +
> + free(group);
> + return 1;
> +}
> #endif
>
> static inline struct libinput_tablet_pad_mode_group *
> @@ -401,6 +515,13 @@ pad_init_mode_rings(struct pad_dispatch *pad, WacomDevice *wacom)
> const WacomStatusLEDs *leds;
> int i, nleds;
>
> + /* the LED of the EKR is hardwired so libwacom doesn't export it */
> + if (pad->device->model_flags & EVDEV_MODEL_WACOM_EKR) {
> + group = pad_get_mode_group(pad, 0);
> + group->ring_mask |= 0x1;
> + return;
> + }
> +
> leds = libwacom_get_status_leds(wacom, &nleds);
> if (nleds == 0)
> return;
> @@ -471,7 +592,12 @@ pad_init_leds_from_libwacom(struct pad_dispatch *pad,
> if (!wacom)
> goto out;
>
> - if (pad_init_led_groups(pad, device, wacom) != 0)
> + if (libwacom_get_class(wacom) == WCLASS_REMOTE)
> + rc = pad_init_ekr_group(pad, device, wacom);
> + else
> + rc = pad_init_led_groups(pad, device, wacom);
> +
> + if (rc != 0)
> goto out;
>
> if ((rc = pad_init_mode_buttons(pad, wacom)) != 0)
> @@ -480,7 +606,6 @@ pad_init_leds_from_libwacom(struct pad_dispatch *pad,
> pad_init_mode_rings(pad, wacom);
> pad_init_mode_strips(pad, wacom);
>
> - rc = 0;
> out:
> if (wacom)
> libwacom_destroy(wacom);
> diff --git a/src/evdev.c b/src/evdev.c
> index e18492a..0cd9365 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -1806,6 +1806,7 @@ evdev_read_model_flags(struct evdev_device *device)
> MODEL(LENOVO_T450_TOUCHPAD),
> MODEL(PRECISE_TOUCHPAD),
> MODEL(TRACKBALL),
> + MODEL(WACOM_EKR),
> { NULL, EVDEV_MODEL_DEFAULT },
> #undef MODEL
> };
> diff --git a/src/evdev.h b/src/evdev.h
> index 9d6108c..caaf75c 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -116,6 +116,7 @@ enum evdev_device_model {
> EVDEV_MODEL_LENOVO_T450_TOUCHPAD= (1 << 17),
> EVDEV_MODEL_PRECISE_TOUCHPAD = (1 << 18),
> EVDEV_MODEL_TRACKBALL = (1 << 19),
> + EVDEV_MODEL_WACOM_EKR = (1 << 20),
> };
>
> struct mt_slot {
> diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb
> index 821bc16..ee628b4 100644
> --- a/udev/90-libinput-model-quirks.hwdb
> +++ b/udev/90-libinput-model-quirks.hwdb
> @@ -143,6 +143,9 @@ libinput:name:SynPS/2 Synaptics TouchPad:dmi:*svnSystem76*pvrkudp1*
> libinput:touchpad:input:b0003v056Ap*
> LIBINPUT_MODEL_WACOM_TOUCHPAD=1
>
> +libinput:name:*Wacom Express Key Remote Pad:dmi:*
> + LIBINPUT_MODEL_WACOM_EKR=1
> +
> ##########################################
> # Anything that has trackball in the name
> ##########################################
>
More information about the wayland-devel
mailing list