Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
---
 test/Makefile.am                       |   7 +
 test/litest-device-wacom-intuos3-pad.c | 107 +++++++++
 test/litest-device-wacom-intuos5-pad.c | 112 ++++++++++
 test/litest-int.h                      |  16 ++
 test/litest.c                          | 195 ++++++++++++++++-
 test/litest.h                          |  39 ++++
 test/misc.c                            |  51 +++++
 test/pad.c                             | 381 +++++++++++++++++++++++++++++++++
 8 files changed, 907 insertions(+), 1 deletion(-)
 create mode 100644 test/litest-device-wacom-intuos3-pad.c
 create mode 100644 test/litest-device-wacom-intuos5-pad.c
 create mode 100644 test/pad.c

diff --git a/test/Makefile.am b/test/Makefile.am
index bee7203..f90d326 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -47,6 +47,8 @@ liblitest_la_SOURCES = \
        litest-device-wacom-bamboo-tablet.c \
        litest-device-wacom-cintiq-tablet.c \
        litest-device-wacom-intuos-tablet.c \
+       litest-device-wacom-intuos3-pad.c \
+       litest-device-wacom-intuos5-pad.c \
        litest-device-wacom-isdv4-tablet.c \
        litest-device-wacom-touch.c \
        litest-device-wacom-intuos-finger.c \
@@ -70,6 +72,7 @@ run_tests = \
        test-touchpad \
        test-touchpad-tap \
        test-touchpad-buttons \
+       test-pad \
        test-tablet \
        test-device \
        test-gestures \
@@ -119,6 +122,10 @@ test_tablet_SOURCES = tablet.c
 test_tablet_LDADD = $(TEST_LIBS)
 test_tablet_LDFLAGS = -static
 
+test_pad_SOURCES = pad.c
+test_pad_LDADD = $(TEST_LIBS)
+test_pad_LDFLAGS = -static
+
 test_touchpad_SOURCES = touchpad.c
 test_touchpad_LDADD = $(TEST_LIBS)
 test_touchpad_LDFLAGS = -no-install
diff --git a/test/litest-device-wacom-intuos3-pad.c 
b/test/litest-device-wacom-intuos3-pad.c
new file mode 100644
index 0000000..c05da02
--- /dev/null
+++ b/test/litest-device-wacom-intuos3-pad.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+
+static void
+litest_wacom_intuos3_pad_setup(void)
+{
+       struct litest_device *d = 
litest_create_device(LITEST_WACOM_INTUOS3_PAD);
+       litest_set_current_device(d);
+}
+
+static struct input_event down[] = {
+       { .type = -1, .code = -1 },
+};
+
+static struct input_event move[] = {
+       { .type = -1, .code = -1 },
+};
+
+static struct input_event strip_start[] = {
+       { .type = EV_ABS, .code = ABS_RX, .value = LITEST_AUTO_ASSIGN },
+       { .type = EV_ABS, .code = ABS_MISC, .value = 15 },
+       { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+       { .type = -1, .code = -1 },
+} ;
+
+static struct input_event strip_change[] = {
+       { .type = EV_ABS, .code = ABS_RX, .value = LITEST_AUTO_ASSIGN },
+       { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+       { .type = -1, .code = -1 },
+} ;
+
+static struct input_event strip_end[] = {
+       { .type = EV_ABS, .code = ABS_RX, .value = 0 },
+       { .type = EV_ABS, .code = ABS_MISC, .value = 0 },
+       { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+       { .type = -1, .code = -1 },
+} ;
+
+static struct litest_device_interface interface = {
+       .touch_down_events = down,
+       .touch_move_events = move,
+       .pad_strip_start_events = strip_start,
+       .pad_strip_change_events = strip_change,
+       .pad_strip_end_events = strip_end,
+};
+
+static struct input_absinfo absinfo[] = {
+       { ABS_X, 0, 1, 0, 0, 0 },
+       { ABS_Y, 0, 1, 0, 0, 0 },
+       { ABS_RX, 0, 4096, 0, 0, 0 },
+       { ABS_MISC, 0, 0, 0, 0, 0 },
+       { .value = -1 },
+};
+
+static struct input_id input_id = {
+       .bustype = 0x3,
+       .vendor = 0x56a,
+       .product = 0xb7,
+};
+
+static int events[] = {
+       EV_KEY, BTN_0,
+       EV_KEY, BTN_1,
+       EV_KEY, BTN_2,
+       EV_KEY, BTN_3,
+       EV_KEY, BTN_STYLUS,
+       -1, -1,
+};
+
+struct litest_test_device litest_wacom_intuos3_pad_device = {
+       .type = LITEST_WACOM_INTUOS3_PAD,
+       .features = LITEST_TABLET_PAD | LITEST_STRIP,
+       .shortname = "wacom-intuos3-pad",
+       .setup = litest_wacom_intuos3_pad_setup,
+       .interface = &interface,
+
+       .name = "Wacom Intuos3 4x6 Pad",
+       .id = &input_id,
+       .events = events,
+       .absinfo = absinfo,
+};
diff --git a/test/litest-device-wacom-intuos5-pad.c 
b/test/litest-device-wacom-intuos5-pad.c
new file mode 100644
index 0000000..bbdf526
--- /dev/null
+++ b/test/litest-device-wacom-intuos5-pad.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "litest.h"
+#include "litest-int.h"
+
+static void
+litest_wacom_intuos5_pad_setup(void)
+{
+       struct litest_device *d = 
litest_create_device(LITEST_WACOM_INTUOS5_PAD);
+       litest_set_current_device(d);
+}
+
+static struct input_event down[] = {
+       { .type = -1, .code = -1 },
+};
+
+static struct input_event move[] = {
+       { .type = -1, .code = -1 },
+};
+
+static struct input_event ring_start[] = {
+       { .type = EV_ABS, .code = ABS_WHEEL, .value = LITEST_AUTO_ASSIGN },
+       { .type = EV_ABS, .code = ABS_MISC, .value = 15 },
+       { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+       { .type = -1, .code = -1 },
+} ;
+
+static struct input_event ring_change[] = {
+       { .type = EV_ABS, .code = ABS_WHEEL, .value = LITEST_AUTO_ASSIGN },
+       { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+       { .type = -1, .code = -1 },
+} ;
+
+static struct input_event ring_end[] = {
+       { .type = EV_ABS, .code = ABS_WHEEL, .value = 0 },
+       { .type = EV_ABS, .code = ABS_MISC, .value = 0 },
+       { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+       { .type = -1, .code = -1 },
+} ;
+
+static struct litest_device_interface interface = {
+       .touch_down_events = down,
+       .touch_move_events = move,
+       .pad_ring_start_events = ring_start,
+       .pad_ring_change_events = ring_change,
+       .pad_ring_end_events = ring_end,
+};
+
+static struct input_absinfo absinfo[] = {
+       { ABS_X, 0, 1, 0, 0, 0 },
+       { ABS_Y, 0, 1, 0, 0, 0 },
+       { ABS_WHEEL, 0, 71, 0, 0, 0 },
+       { ABS_MISC, 0, 0, 0, 0, 10 },
+       { .value = -1 },
+};
+
+static struct input_id input_id = {
+       .bustype = 0x3,
+       .vendor = 0x56a,
+       .product = 0x27,
+};
+
+static int events[] = {
+       EV_KEY, BTN_0,
+       EV_KEY, BTN_1,
+       EV_KEY, BTN_2,
+       EV_KEY, BTN_3,
+       EV_KEY, BTN_4,
+       EV_KEY, BTN_5,
+       EV_KEY, BTN_6,
+       EV_KEY, BTN_7,
+       EV_KEY, BTN_8,
+       EV_KEY, BTN_STYLUS,
+       -1, -1,
+};
+
+struct litest_test_device litest_wacom_intuos5_pad_device = {
+       .type = LITEST_WACOM_INTUOS5_PAD,
+       .features = LITEST_TABLET_PAD | LITEST_RING,
+       .shortname = "wacom-pad",
+       .setup = litest_wacom_intuos5_pad_setup,
+       .interface = &interface,
+
+       .name = "Wacom Intuos5 touch M Pad",
+       .id = &input_id,
+       .events = events,
+       .absinfo = absinfo,
+};
diff --git a/test/litest-int.h b/test/litest-int.h
index 8d0308b..1a9060d 100644
--- a/test/litest-int.h
+++ b/test/litest-int.h
@@ -105,6 +105,22 @@ struct litest_device_interface {
        struct input_event *tablet_proximity_out_events;
        struct input_event *tablet_motion_events;
 
+       /**
+        * Pad events, LITEST_AUTO_ASSIGN is allowed on event values
+        * for ABS_WHEEL
+        */
+       struct input_event *pad_ring_start_events;
+       struct input_event *pad_ring_change_events;
+       struct input_event *pad_ring_end_events;
+
+       /**
+        * Pad events, LITEST_AUTO_ASSIGN is allowed on event values
+        * for ABS_RX
+        */
+       struct input_event *pad_strip_start_events;
+       struct input_event *pad_strip_change_events;
+       struct input_event *pad_strip_end_events;
+
        int min[2]; /* x/y axis minimum */
        int max[2]; /* x/y axis maximum */
 };
diff --git a/test/litest.c b/test/litest.c
index dcb34a9..fc51b8e 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -378,6 +378,8 @@ extern struct litest_test_device litest_huion_tablet_device;
 extern struct litest_test_device litest_cyborg_rat_device;
 extern struct litest_test_device litest_yubikey_device;
 extern struct litest_test_device litest_synaptics_i2c_device;
+extern struct litest_test_device litest_wacom_intuos3_pad_device;
+extern struct litest_test_device litest_wacom_intuos5_pad_device;
 
 struct litest_test_device* devices[] = {
        &litest_synaptics_clickpad_device,
@@ -422,6 +424,8 @@ struct litest_test_device* devices[] = {
        &litest_cyborg_rat_device,
        &litest_yubikey_device,
        &litest_synaptics_i2c_device,
+       &litest_wacom_intuos3_pad_device,
+       &litest_wacom_intuos5_pad_device,
        NULL,
 };
 
@@ -1791,6 +1795,15 @@ litest_scale_axis(const struct litest_device *d,
        return (abs->maximum - abs->minimum) * val/100.0 + abs->minimum;
 }
 
+static inline int
+litest_scale_range(int min, int max, double val)
+{
+       litest_assert_int_ge((int)val, 0);
+       litest_assert_int_le((int)val, 100);
+
+       return (max - min) * val/100.0 + min;
+}
+
 int
 litest_scale(const struct litest_device *d, unsigned int axis, double val)
 {
@@ -1801,12 +1814,120 @@ litest_scale(const struct litest_device *d, unsigned 
int axis, double val)
        if (axis <= ABS_Y) {
                min = d->interface->min[axis];
                max = d->interface->max[axis];
-               return (max - min) * val/100.0 + min;
+
+               return litest_scale_range(min, max, val);
        } else {
                return litest_scale_axis(d, axis, val);
        }
 }
 
+static inline int
+auto_assign_pad_value(struct litest_device *dev,
+                     struct input_event *ev,
+                     double value)
+{
+       const struct input_absinfo *abs;
+
+       if (ev->value != LITEST_AUTO_ASSIGN ||
+           ev->type != EV_ABS)
+               return value;
+
+       abs = libevdev_get_abs_info(dev->evdev, ev->code);
+       litest_assert_notnull(abs);
+
+       if (ev->code == ABS_RX || ev->code == ABS_RY) {
+               double min = abs->minimum != 0 ? log2(abs->minimum) : 0,
+                      max = abs->maximum != 0 ? log2(abs->maximum) : 0;
+
+               /* Value 0 is reserved for finger up, so a value of 0% is
+                * actually 1 */
+               if (value == 0.0) {
+                       return 1;
+               } else {
+                       value = litest_scale_range(min, max, value);
+                       return pow(2, value);
+               }
+       } else {
+               return litest_scale_range(abs->minimum, abs->maximum, value);
+       }
+}
+
+void
+litest_pad_ring_start(struct litest_device *d, double value)
+{
+       struct input_event *ev;
+
+       ev = d->interface->pad_ring_start_events;
+       while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
+               value = auto_assign_pad_value(d, ev, value);
+               litest_event(d, ev->type, ev->code, value);
+               ev++;
+       }
+}
+
+void
+litest_pad_ring_change(struct litest_device *d, double value)
+{
+       struct input_event *ev;
+
+       ev = d->interface->pad_ring_change_events;
+       while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
+               value = auto_assign_pad_value(d, ev, value);
+               litest_event(d, ev->type, ev->code, value);
+               ev++;
+       }
+}
+
+void
+litest_pad_ring_end(struct litest_device *d)
+{
+       struct input_event *ev;
+
+       ev = d->interface->pad_ring_end_events;
+       while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
+               litest_event(d, ev->type, ev->code, ev->value);
+               ev++;
+       }
+}
+
+void
+litest_pad_strip_start(struct litest_device *d, double value)
+{
+       struct input_event *ev;
+
+       ev = d->interface->pad_strip_start_events;
+       while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
+               value = auto_assign_pad_value(d, ev, value);
+               litest_event(d, ev->type, ev->code, value);
+               ev++;
+       }
+}
+
+void
+litest_pad_strip_change(struct litest_device *d, double value)
+{
+       struct input_event *ev;
+
+       ev = d->interface->pad_strip_change_events;
+       while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
+               value = auto_assign_pad_value(d, ev, value);
+               litest_event(d, ev->type, ev->code, value);
+               ev++;
+       }
+}
+
+void
+litest_pad_strip_end(struct litest_device *d)
+{
+       struct input_event *ev;
+
+       ev = d->interface->pad_strip_end_events;
+       while (ev && (int16_t)ev->type != -1 && (int16_t)ev->code != -1) {
+               litest_event(d, ev->type, ev->code, ev->value);
+               ev++;
+       }
+}
+
 void
 litest_wait_for_event(struct libinput *li)
 {
@@ -2445,6 +2566,78 @@ void litest_assert_tablet_proximity_event(struct 
libinput *li,
        libinput_event_destroy(event);
 }
 
+struct libinput_event_tablet_pad *
+litest_is_pad_button_event(struct libinput_event *event,
+                          unsigned int button,
+                          enum libinput_button_state state)
+{
+       struct libinput_event_tablet_pad *p;
+       enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_BUTTON;
+
+       litest_assert(event != NULL);
+       litest_assert_int_eq(libinput_event_get_type(event), type);
+
+       p = libinput_event_get_tablet_pad_event(event);
+       litest_assert(p != NULL);
+
+       return p;
+}
+
+struct libinput_event_tablet_pad *
+litest_is_pad_ring_event(struct libinput_event *event,
+                        unsigned int number,
+                        enum libinput_tablet_pad_ring_axis_source source)
+{
+       struct libinput_event_tablet_pad *p;
+       enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_RING;
+
+       litest_assert(event != NULL);
+       litest_assert_int_eq(libinput_event_get_type(event), type);
+       p = libinput_event_get_tablet_pad_event(event);
+
+       litest_assert_int_eq(libinput_event_tablet_pad_get_ring_number(p),
+                            number);
+       litest_assert_int_eq(libinput_event_tablet_pad_get_ring_source(p),
+                            source);
+
+       return p;
+}
+
+struct libinput_event_tablet_pad *
+litest_is_pad_strip_event(struct libinput_event *event,
+                         unsigned int number,
+                         enum libinput_tablet_pad_strip_axis_source source)
+{
+       struct libinput_event_tablet_pad *p;
+       enum libinput_event_type type = LIBINPUT_EVENT_TABLET_PAD_STRIP;
+
+       litest_assert(event != NULL);
+       litest_assert_int_eq(libinput_event_get_type(event), type);
+       p = libinput_event_get_tablet_pad_event(event);
+
+       litest_assert_int_eq(libinput_event_tablet_pad_get_strip_number(p),
+                            number);
+       litest_assert_int_eq(libinput_event_tablet_pad_get_strip_source(p),
+                            source);
+
+       return p;
+}
+
+void
+litest_assert_pad_button_event(struct libinput *li,
+                              unsigned int button,
+                              enum libinput_button_state state)
+{
+       struct libinput_event *event;
+       struct libinput_event_tablet_pad *pev;
+
+       litest_wait_for_event(li);
+       event = libinput_get_event(li);
+
+       pev = litest_is_pad_button_event(event, button, state);
+       libinput_event_destroy(libinput_event_tablet_pad_get_base_event(pev));
+}
+
 void
 litest_assert_scroll(struct libinput *li,
                     enum libinput_pointer_axis axis,
diff --git a/test/litest.h b/test/litest.h
index fe08093..ab2c0db 100644
--- a/test/litest.h
+++ b/test/litest.h
@@ -195,6 +195,8 @@ enum litest_device_type {
        LITEST_CYBORG_RAT = -41,
        LITEST_YUBIKEY = -42,
        LITEST_SYNAPTICS_I2C = -43,
+       LITEST_WACOM_INTUOS3_PAD = -44,
+       LITEST_WACOM_INTUOS5_PAD = -45,
 };
 
 enum litest_device_feature {
@@ -221,6 +223,9 @@ enum litest_device_feature {
        LITEST_DISTANCE = 1 << 18,
        LITEST_TOOL_SERIAL = 1 << 19,
        LITEST_TILT = 1 << 20,
+       LITEST_TABLET_PAD = 1 << 21,
+       LITEST_RING = 1 << 22,
+       LITEST_STRIP = 1 << 23,
 };
 
 struct litest_device {
@@ -432,6 +437,24 @@ litest_tablet_motion(struct litest_device *d,
                     struct axis_replacement *axes);
 
 void
+litest_pad_ring_start(struct litest_device *d, double value);
+
+void
+litest_pad_ring_change(struct litest_device *d, double value);
+
+void
+litest_pad_ring_end(struct litest_device *d);
+
+void
+litest_pad_strip_start(struct litest_device *d, double value);
+
+void
+litest_pad_strip_change(struct litest_device *d, double value);
+
+void
+litest_pad_strip_end(struct litest_device *d);
+
+void
 litest_hover_start(struct litest_device *d,
                   unsigned int slot,
                   double x,
@@ -517,6 +540,19 @@ struct libinput_event_tablet_tool *
 litest_is_tablet_event(struct libinput_event *event,
                       enum libinput_event_type type);
 
+struct libinput_event_tablet_pad *
+litest_is_pad_button_event(struct libinput_event *event,
+                          unsigned int button,
+                          enum libinput_button_state state);
+struct libinput_event_tablet_pad *
+litest_is_pad_ring_event(struct libinput_event *event,
+                        unsigned int number,
+                        enum libinput_tablet_pad_ring_axis_source source);
+struct libinput_event_tablet_pad *
+litest_is_pad_strip_event(struct libinput_event *event,
+                         unsigned int number,
+                         enum libinput_tablet_pad_strip_axis_source source);
+
 void
 litest_assert_button_event(struct libinput *li,
                           unsigned int button,
@@ -540,6 +576,9 @@ void
 litest_assert_tablet_proximity_event(struct libinput *li,
                                     enum libinput_tablet_tool_proximity_state 
state);
 
+void litest_assert_pad_button_event(struct libinput *li,
+                                   unsigned int button,
+                                   enum libinput_button_state state);
 struct libevdev_uinput *
 litest_create_uinput_device(const char *name,
                            struct input_id *id,
diff --git a/test/misc.c b/test/misc.c
index e8b41e5..304710f 100644
--- a/test/misc.c
+++ b/test/misc.c
@@ -134,6 +134,7 @@ START_TEST(event_conversion_device_notify)
                        ck_assert(libinput_event_get_touch_event(event) == 
NULL);
                        ck_assert(libinput_event_get_gesture_event(event) == 
NULL);
                        ck_assert(libinput_event_get_tablet_tool_event(event) 
== NULL);
+                       ck_assert(libinput_event_get_tablet_pad_event(event) == 
NULL);
                        litest_restore_log_handler(li);
                }
 
@@ -190,6 +191,7 @@ START_TEST(event_conversion_pointer)
                        ck_assert(libinput_event_get_touch_event(event) == 
NULL);
                        ck_assert(libinput_event_get_gesture_event(event) == 
NULL);
                        ck_assert(libinput_event_get_tablet_tool_event(event) 
== NULL);
+                       ck_assert(libinput_event_get_tablet_pad_event(event) == 
NULL);
                        litest_restore_log_handler(li);
                }
                libinput_event_destroy(event);
@@ -240,6 +242,7 @@ START_TEST(event_conversion_pointer_abs)
                        ck_assert(libinput_event_get_touch_event(event) == 
NULL);
                        ck_assert(libinput_event_get_gesture_event(event) == 
NULL);
                        ck_assert(libinput_event_get_tablet_tool_event(event) 
== NULL);
+                       ck_assert(libinput_event_get_tablet_pad_event(event) == 
NULL);
                        litest_restore_log_handler(li);
                }
                libinput_event_destroy(event);
@@ -283,6 +286,7 @@ START_TEST(event_conversion_key)
                        ck_assert(libinput_event_get_touch_event(event) == 
NULL);
                        ck_assert(libinput_event_get_gesture_event(event) == 
NULL);
                        ck_assert(libinput_event_get_tablet_tool_event(event) 
== NULL);
+                       ck_assert(libinput_event_get_tablet_pad_event(event) == 
NULL);
                        litest_restore_log_handler(li);
                }
                libinput_event_destroy(event);
@@ -333,6 +337,7 @@ START_TEST(event_conversion_touch)
                        ck_assert(libinput_event_get_keyboard_event(event) == 
NULL);
                        ck_assert(libinput_event_get_gesture_event(event) == 
NULL);
                        ck_assert(libinput_event_get_tablet_tool_event(event) 
== NULL);
+                       ck_assert(libinput_event_get_tablet_pad_event(event) == 
NULL);
                        litest_restore_log_handler(li);
                }
                libinput_event_destroy(event);
@@ -381,6 +386,7 @@ START_TEST(event_conversion_gesture)
                        ck_assert(libinput_event_get_pointer_event(event) == 
NULL);
                        ck_assert(libinput_event_get_keyboard_event(event) == 
NULL);
                        ck_assert(libinput_event_get_touch_event(event) == 
NULL);
+                       ck_assert(libinput_event_get_tablet_pad_event(event) == 
NULL);
                        litest_restore_log_handler(li);
                }
                libinput_event_destroy(event);
@@ -427,6 +433,50 @@ START_TEST(event_conversion_tablet)
                        ck_assert(libinput_event_get_pointer_event(event) == 
NULL);
                        ck_assert(libinput_event_get_keyboard_event(event) == 
NULL);
                        ck_assert(libinput_event_get_touch_event(event) == 
NULL);
+                       ck_assert(libinput_event_get_tablet_pad_event(event) == 
NULL);
+                       litest_restore_log_handler(li);
+               }
+               libinput_event_destroy(event);
+       }
+
+       ck_assert_int_gt(events, 0);
+}
+END_TEST
+
+START_TEST(event_conversion_tablet_pad)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       struct libinput_event *event;
+       int events = 0;
+
+       litest_button_click(dev, BTN_0, true);
+       litest_pad_ring_start(dev, 10);
+       litest_pad_ring_end(dev);
+
+       libinput_dispatch(li);
+
+       while ((event = libinput_get_event(li))) {
+               enum libinput_event_type type;
+               type = libinput_event_get_type(event);
+
+               if (type >= LIBINPUT_EVENT_TABLET_PAD_BUTTON &&
+                   type <= LIBINPUT_EVENT_TABLET_PAD_STRIP) {
+                       struct libinput_event_tablet_pad *p;
+                       struct libinput_event *base;
+
+                       p = libinput_event_get_tablet_pad_event(event);
+                       base = libinput_event_tablet_pad_get_base_event(p);
+                       ck_assert(event == base);
+
+                       events++;
+
+                       litest_disable_log_handler(li);
+                       ck_assert(libinput_event_get_device_notify_event(event) 
== NULL);
+                       ck_assert(libinput_event_get_pointer_event(event) == 
NULL);
+                       ck_assert(libinput_event_get_keyboard_event(event) == 
NULL);
+                       ck_assert(libinput_event_get_touch_event(event) == 
NULL);
+                       ck_assert(libinput_event_get_tablet_tool_event(event) 
== NULL);
                        litest_restore_log_handler(li);
                }
                libinput_event_destroy(event);
@@ -895,6 +945,7 @@ litest_setup_tests(void)
        litest_add_for_device("events:conversion", event_conversion_touch, 
LITEST_WACOM_TOUCH);
        litest_add_for_device("events:conversion", event_conversion_gesture, 
LITEST_BCM5974);
        litest_add_for_device("events:conversion", event_conversion_tablet, 
LITEST_WACOM_CINTIQ);
+       litest_add_for_device("events:conversion", event_conversion_tablet_pad, 
LITEST_WACOM_INTUOS5_PAD);
        litest_add_no_device("bitfield_helpers", bitfield_helpers);
 
        litest_add_no_device("context:refcount", context_ref_counting);
diff --git a/test/pad.c b/test/pad.c
new file mode 100644
index 0000000..0286bd0
--- /dev/null
+++ b/test/pad.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright © 2016 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <check.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libinput.h>
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "libinput-util.h"
+#include "litest.h"
+
+START_TEST(pad_cap)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+
+       ck_assert(libinput_device_has_capability(device,
+                                                
LIBINPUT_DEVICE_CAP_TABLET_PAD));
+
+}
+END_TEST
+
+START_TEST(pad_no_cap)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+
+       ck_assert(!libinput_device_has_capability(device,
+                                                 
LIBINPUT_DEVICE_CAP_TABLET_PAD));
+}
+END_TEST
+
+START_TEST(pad_has_button)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+       unsigned int code;
+       bool available;
+
+       for (code = BTN_LEFT; code < KEY_MAX; code++) {
+               available = libevdev_has_event_code(dev->evdev,
+                                                   EV_KEY,
+                                                   code);
+               ck_assert_int_eq(libinput_device_tablet_pad_has_button(device,
+                                                                      code),
+                                available);
+       }
+
+}
+END_TEST
+
+START_TEST(pad_button)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       unsigned int code;
+
+       litest_drain_events(li);
+
+       for (code = BTN_LEFT; code < KEY_MAX; code++) {
+               if (!libevdev_has_event_code(dev->evdev,
+                                            EV_KEY,
+                                            code))
+                       continue;
+
+               litest_button_click(dev, code, 1);
+               libinput_dispatch(li);
+
+               litest_assert_pad_button_event(li,
+                                              code,
+                                              LIBINPUT_BUTTON_STATE_PRESSED);
+
+               litest_button_click(dev, code, 0);
+               libinput_dispatch(li);
+
+               litest_assert_pad_button_event(li,
+                                              code,
+                                              LIBINPUT_BUTTON_STATE_RELEASED);
+
+       }
+
+       litest_assert_empty_queue(li);
+
+}
+END_TEST
+
+START_TEST(pad_button_seat_count)
+{
+       struct litest_device *first, *second;
+       struct libinput *li;
+       unsigned int code;
+       struct libinput_event *ev;
+       struct libinput_event_tablet_pad *pev;
+       bool tested_at_least_one = false;
+
+       first = litest_current_device();
+       li = first->libinput;
+       second = litest_add_device(li, LITEST_WACOM_INTUOS5_PAD);
+
+       litest_drain_events(li);
+
+       for (code = BTN_LEFT; code < KEY_MAX; code++) {
+               if (!libevdev_has_event_code(first->evdev,
+                                            EV_KEY,
+                                            code) ||
+                   !libevdev_has_event_code(second->evdev,
+                                            EV_KEY,
+                                            code))
+                       continue;
+
+               tested_at_least_one = true;
+
+               litest_button_click(first, code, 1);
+               libinput_dispatch(li);
+
+               ev = libinput_get_event(li);
+               pev = litest_is_pad_button_event(ev,
+                                                code,
+                                                LIBINPUT_BUTTON_STATE_PRESSED);
+               
ck_assert_int_eq(libinput_event_tablet_pad_get_seat_button_count(pev),
+                                1);
+               libinput_event_destroy(ev);
+
+               litest_button_click(second, code, 1);
+               libinput_dispatch(li);
+
+               ev = libinput_get_event(li);
+               pev = litest_is_pad_button_event(ev,
+                                                code,
+                                                LIBINPUT_BUTTON_STATE_PRESSED);
+               
ck_assert_int_eq(libinput_event_tablet_pad_get_seat_button_count(pev),
+                                2);
+               libinput_event_destroy(ev);
+
+               litest_button_click(first, code, 0);
+               libinput_dispatch(li);
+
+               ev = libinput_get_event(li);
+               pev = litest_is_pad_button_event(ev,
+                                                code,
+                                                LIBINPUT_BUTTON_STATE_PRESSED);
+               
ck_assert_int_eq(libinput_event_tablet_pad_get_seat_button_count(pev),
+                                1);
+               libinput_event_destroy(ev);
+
+               litest_button_click(second, code, 0);
+               libinput_dispatch(li);
+
+               ev = libinput_get_event(li);
+               pev = litest_is_pad_button_event(ev,
+                                                code,
+                                                LIBINPUT_BUTTON_STATE_PRESSED);
+               
ck_assert_int_eq(libinput_event_tablet_pad_get_seat_button_count(pev),
+                                0);
+               libinput_event_destroy(ev);
+       }
+
+       litest_assert_empty_queue(li);
+
+       litest_delete_device(second);
+
+       ck_assert(tested_at_least_one);
+}
+END_TEST
+
+START_TEST(pad_has_ring)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+       int nrings;
+
+       nrings = libinput_device_tablet_pad_get_num_rings(device);
+       ck_assert_int_ge(nrings, 1);
+}
+END_TEST
+
+START_TEST(pad_ring)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       struct libinput_event *ev;
+       struct libinput_event_tablet_pad *pev;
+       int val;
+       double degrees, expected;
+
+       litest_pad_ring_start(dev, 10);
+
+       litest_drain_events(li);
+
+       /* Wacom's 0 value is at 275 degrees */
+       expected = 270;
+
+       for (val = 0; val < 100; val += 10) {
+               litest_pad_ring_change(dev, val);
+               libinput_dispatch(li);
+
+               ev = libinput_get_event(li);
+               pev = litest_is_pad_ring_event(ev,
+                                              0,
+                                              
LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
+
+               degrees = libinput_event_tablet_pad_get_ring_position(pev);
+               ck_assert_double_ge(degrees, 0.0);
+               ck_assert_double_lt(degrees, 360.0);
+
+               /* rounding errors, mostly caused by small physical range */
+               ck_assert_double_ge(degrees, expected - 2);
+               ck_assert_double_le(degrees, expected + 2);
+
+               libinput_event_destroy(ev);
+
+               expected = fmod(degrees + 36, 360);
+       }
+
+       litest_pad_ring_end(dev);
+}
+END_TEST
+
+START_TEST(pad_ring_finger_up)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       struct libinput_event *ev;
+       struct libinput_event_tablet_pad *pev;
+       double degrees;
+
+       litest_pad_ring_start(dev, 10);
+
+       litest_drain_events(li);
+
+       litest_pad_ring_end(dev);
+       libinput_dispatch(li);
+
+       ev = libinput_get_event(li);
+       pev = litest_is_pad_ring_event(ev,
+                                      0,
+                                      LIBINPUT_TABLET_PAD_RING_SOURCE_FINGER);
+
+       degrees = libinput_event_tablet_pad_get_ring_position(pev);
+       ck_assert_double_eq(degrees, -1.0);
+       libinput_event_destroy(ev);
+
+       litest_assert_empty_queue(li);
+}
+END_TEST
+
+START_TEST(pad_has_strip)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput_device *device = dev->libinput_device;
+       int nstrips;
+
+       nstrips = libinput_device_tablet_pad_get_num_strips(device);
+       ck_assert_int_ge(nstrips, 1);
+}
+END_TEST
+
+START_TEST(pad_strip)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       struct libinput_event *ev;
+       struct libinput_event_tablet_pad *pev;
+       int val;
+       double pos, expected;
+
+       litest_pad_strip_start(dev, 10);
+
+       litest_drain_events(li);
+
+       expected = 0;
+
+       /* 9.5 works with the generic axis scaling without jumping over a
+        * value. */
+       for (val = 0; val < 100; val += 9.5) {
+               litest_pad_strip_change(dev, val);
+               libinput_dispatch(li);
+
+               ev = libinput_get_event(li);
+               pev = litest_is_pad_strip_event(ev,
+                                               0,
+                                               
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
+
+               pos = libinput_event_tablet_pad_get_strip_position(pev);
+               ck_assert_double_ge(pos, 0.0);
+               ck_assert_double_lt(pos, 1.0);
+
+               /* rounding errors, mostly caused by small physical range */
+               ck_assert_double_ge(pos, expected - 0.02);
+               ck_assert_double_le(pos, expected + 0.02);
+
+               libinput_event_destroy(ev);
+
+               expected = pos + 0.08;
+       }
+
+       litest_pad_strip_change(dev, 100);
+       libinput_dispatch(li);
+
+       ev = libinput_get_event(li);
+       pev = litest_is_pad_strip_event(ev,
+                                          0,
+                                          
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
+       pos = libinput_event_tablet_pad_get_strip_position(pev);
+       ck_assert_double_eq(pos, 1.0);
+       libinput_event_destroy(ev);
+
+       litest_pad_strip_end(dev);
+}
+END_TEST
+
+START_TEST(pad_strip_finger_up)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+       struct libinput_event *ev;
+       struct libinput_event_tablet_pad *pev;
+       double pos;
+
+       litest_pad_strip_start(dev, 10);
+       litest_drain_events(li);
+
+       litest_pad_strip_end(dev);
+       libinput_dispatch(li);
+
+       ev = libinput_get_event(li);
+       pev = litest_is_pad_strip_event(ev,
+                                       0,
+                                       
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER);
+
+       pos = libinput_event_tablet_pad_get_strip_position(pev);
+       ck_assert_double_eq(pos, -1.0);
+       libinput_event_destroy(ev);
+
+       litest_assert_empty_queue(li);
+}
+END_TEST
+
+void
+litest_setup_tests(void)
+{
+       litest_add("pad:cap", pad_cap, LITEST_TABLET_PAD, LITEST_ANY);
+       litest_add("pad:cap", pad_no_cap, LITEST_ANY, LITEST_TABLET_PAD);
+
+       litest_add("pad:button", pad_has_button, LITEST_TABLET_PAD, LITEST_ANY);
+       litest_add("pad:button", pad_button, LITEST_TABLET_PAD, LITEST_ANY);
+       litest_add("pad:button", pad_button_seat_count, LITEST_TABLET_PAD, 
LITEST_ANY);
+       litest_add("pad:button", pad_button_seat_count, LITEST_TABLET_PAD, 
LITEST_ANY);
+
+       litest_add("pad:ring", pad_has_ring, LITEST_RING, LITEST_ANY);
+       litest_add("pad:ring", pad_ring, LITEST_RING, LITEST_ANY);
+       litest_add("pad:ring", pad_ring_finger_up, LITEST_RING, LITEST_ANY);
+
+       litest_add("pad:strip", pad_has_strip, LITEST_STRIP, LITEST_ANY);
+       litest_add("pad:strip", pad_strip, LITEST_STRIP, LITEST_ANY);
+       litest_add("pad:strip", pad_strip_finger_up, LITEST_STRIP, LITEST_ANY);
+
+}
-- 
2.5.0

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to