[PATCH v2 libinput 07/10] pad: implement support for the Express Key Remote
Peter Hutterer
peter.hutterer at who-t.net
Wed Jun 15 06:37:40 UTC 2016
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.
+ */
+ 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
##########################################
--
2.7.4
More information about the wayland-devel
mailing list