Hi PrasannaKumar

On Mon, Feb 15, 2016 at 04:21:23PM +0530, PrasannaKumar Muralidharan wrote:
> From: PrasannaKumar Muralidharan <prasannatsmku...@gmail.com>
> 
> I am implementing dial input device support and would like to get feedback
> on the code that I have implemented so far. Did not implement test cases
> as of now, any pointers on how the test framework works will be helpful.
> 
> Smartwatch can use dial input, Car can use steering wheel rotation as
> input for maps may be. But I would like to know if dial input device
> support is useful before proceeding further?
> 
> Appreciate positive and negative comments.

First: yes, implementing support for dial interfaces is within the scope of
libinput, I think it makes sense to add this. But not quite in this form,
the various CAP flags are libinput interfaces that denote a specific
functionality. We should not add one per event group.

A while ago we started work on the so-called buttonset interface which is 
a generic interface to support a bunch of devices like yours:
https://lists.freedesktop.org/archives/wayland-devel/2016-January/026670.html

Since that patchset we've split out the wacom-specific parts so you can
ignore any strip/ring handling. There is no dial axis atm, but there
could be.

Have a look at that patchset, the documentation should explain what the
interface is for, etc. I think adding dial to buttonset and then getting
that interface ready for merging is the best approach here.

One comment on the API (to save you from scrolling down):
libinput_event_dial_get_rotation_count() should simply be
libinput_event_dial_get_rotation() and return the value in degrees. This is
more flexible than the current one which reads like it's multiples of 360
degrees?

Cheers,
   Peter
 
> ---
>  src/Makefile.am        |  2 ++
>  src/evdev-dial.c       | 80 
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/evdev-dial.h       |  6 ++++
>  src/evdev.c            | 12 ++++++++
>  src/evdev.h            |  6 ++++
>  src/libinput-private.h |  5 ++++
>  src/libinput.c         | 74 ++++++++++++++++++++++++++++++++++++++++++++++
>  src/libinput.h         | 46 +++++++++++++++++++++++++++++
>  src/libinput.sym       |  5 ++++
>  tools/event-debug.c    | 23 +++++++++++++++
>  10 files changed, 259 insertions(+)
>  create mode 100644 src/evdev-dial.c
>  create mode 100644 src/evdev-dial.h
> 
> diff --git a/src/Makefile.am b/src/Makefile.am
> index 343e75c..20a32a5 100644
> --- a/src/Makefile.am
> +++ b/src/Makefile.am
> @@ -11,6 +11,8 @@ libinput_la_SOURCES =                       \
>       libinput-private.h              \
>       evdev.c                         \
>       evdev.h                         \
> +     evdev-dial.c                    \
> +     evdev-dial.h                    \
>       evdev-middle-button.c           \
>       evdev-mt-touchpad.c             \
>       evdev-mt-touchpad.h             \
> diff --git a/src/evdev-dial.c b/src/evdev-dial.c
> new file mode 100644
> index 0000000..2427724
> --- /dev/null
> +++ b/src/evdev-dial.c
> @@ -0,0 +1,80 @@
> +#include "config.h"
> +
> +#include <assert.h>
> +#include <math.h>
> +#include <stdbool.h>
> +#include <limits.h>
> +
> +#include "evdev-dial.h"
> +
> +static void
> +dial_process(struct evdev_dispatch *dispatch,
> +          struct evdev_device *device,
> +          struct input_event *event,
> +          uint64_t time)
> +{
> +     struct libinput_device *base = &device->base;
> +     dial_notify(base, time, (int16_t)event->value);
> +}
> +
> +/*
> +static void
> +dial_suspend(struct evdev_dispatch *dispatch,
> +          struct evdev_device *device)
> +{
> +
> +}
> +
> +static void
> +dial_remove(struct evdev_dispatch *dispatch)
> +{
> +
> +}
> +*/
> +
> +static void
> +dial_destroy(struct evdev_dispatch *dispatch)
> +{
> +     free(dispatch);
> +}
> +
> +/*
> +static void
> +dial_device_added(struct evdev_device *device,
> +               struct evdev_device *added_device)
> +{
> +
> +}
> +
> +static void
> +dial_device_removed(struct evdev_device *device,
> +                 struct evdev_device *removed_device)
> +{
> +
> +}
> +*/
> +
> +/* TODO: Check whether other callbacks have to be implemented? */
> +static struct evdev_dispatch_interface dial_interface = {
> +     dial_process,
> +     NULL, /* device suspend */
> +     NULL, /* device remove */
> +     dial_destroy,
> +     NULL, /* device added */
> +     NULL, /* device removed */
> +     NULL, /* device suspended */
> +     NULL, /* device resumed */
> +     NULL, /* device post added */
> +};
> +
> +struct evdev_dispatch *
> +evdev_dial_create(struct evdev_device *device)
> +{
> +     struct evdev_dispatch *dispatch = zalloc(sizeof(struct evdev_dispatch));
> +     if (!dispatch)
> +             return NULL;
> +
> +     dispatch->interface = &dial_interface;
> +
> +     return dispatch;
> +}
> diff --git a/src/evdev-dial.h b/src/evdev-dial.h
> new file mode 100644
> index 0000000..0e191e7
> --- /dev/null
> +++ b/src/evdev-dial.h
> @@ -0,0 +1,6 @@
> +#ifndef EVDEV_DIAL_H
> +#define EVDEV_DIAL_H
> +
> +#include "evdev.h"
> +
> +#endif /* EVDEV_DIAL_H */
> diff --git a/src/evdev.c b/src/evdev.c
> index 66673a8..1e044fb 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -63,6 +63,7 @@ enum evdev_device_udev_tags {
>          EVDEV_UDEV_TAG_ACCELEROMETER = (1 << 7),
>          EVDEV_UDEV_TAG_BUTTONSET = (1 << 8),
>          EVDEV_UDEV_TAG_POINTINGSTICK = (1 << 9),
> +        EVDEV_UDEV_TAG_DIAL = (1 << 10),
>  };
>  
>  struct evdev_udev_tag_match {
> @@ -82,6 +83,7 @@ static const struct evdev_udev_tag_match 
> evdev_udev_tag_matches[] = {
>       {"ID_INPUT_JOYSTICK",           EVDEV_UDEV_TAG_JOYSTICK},
>       {"ID_INPUT_ACCELEROMETER",      EVDEV_UDEV_TAG_ACCELEROMETER},
>       {"ID_INPUT_POINTINGSTICK",      EVDEV_UDEV_TAG_POINTINGSTICK},
> +     {"ID_INPUT_DIAL",               EVDEV_UDEV_TAG_DIAL},
>  
>       /* sentinel value */
>       { 0 },
> @@ -779,6 +781,7 @@ evdev_need_touch_frame(struct evdev_device *device)
>       switch (device->pending_event) {
>       case EVDEV_NONE:
>       case EVDEV_RELATIVE_MOTION:
> +     case EVDEV_RELATIVE_DIAL:
>               break;
>       case EVDEV_ABSOLUTE_MT_DOWN:
>       case EVDEV_ABSOLUTE_MT_MOTION:
> @@ -2157,6 +2160,15 @@ evdev_configure_device(struct evdev_device *device)
>               return -1;
>       }
>  
> +     if (udev_tags & EVDEV_UDEV_TAG_DIAL) {
> +             device->dispatch = evdev_dial_create(device);
> +             device->seat_caps |= EVDEV_DEVICE_DIAL;
> +             log_info(libinput, "input device '%s', '%s' is a rotatory 
> dial\n",
> +                      device->devname, devnode);
> +
> +             return device->dispatch == NULL ? -1 : 0;
> +     }
> +
>       return 0;
>  }
>  
> diff --git a/src/evdev.h b/src/evdev.h
> index 8b567a8..b26ae10 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -54,6 +54,7 @@ enum evdev_event_type {
>       EVDEV_ABSOLUTE_MT_MOTION,
>       EVDEV_ABSOLUTE_MT_UP,
>       EVDEV_RELATIVE_MOTION,
> +     EVDEV_RELATIVE_DIAL,
>  };
>  
>  enum evdev_device_seat_capability {
> @@ -62,6 +63,7 @@ enum evdev_device_seat_capability {
>       EVDEV_DEVICE_TOUCH = (1 << 2),
>       EVDEV_DEVICE_TABLET = (1 << 3),
>       EVDEV_DEVICE_GESTURE = (1 << 5),
> +     EVDEV_DEVICE_DIAL = (1 << 9),
>  };
>  
>  enum evdev_device_tags {
> @@ -69,6 +71,7 @@ enum evdev_device_tags {
>       EVDEV_TAG_INTERNAL_TOUCHPAD = (1 << 1),
>       EVDEV_TAG_TRACKPOINT = (1 << 2),
>       EVDEV_TAG_KEYBOARD = (1 << 3),
> +     EVDEV_TAG_DIAL = (1 << 4),
>  };
>  
>  enum evdev_middlebutton_state {
> @@ -309,6 +312,9 @@ struct evdev_dispatch *
>  evdev_touchpad_create(struct evdev_device *device);
>  
>  struct evdev_dispatch *
> +evdev_dial_create(struct evdev_device *device);
> +
> +struct evdev_dispatch *
>  evdev_mt_touchpad_create(struct evdev_device *device);
>  
>  struct evdev_dispatch *
> diff --git a/src/libinput-private.h b/src/libinput-private.h
> index bc7000d..eabed47 100644
> --- a/src/libinput-private.h
> +++ b/src/libinput-private.h
> @@ -503,6 +503,11 @@ gesture_notify_pinch_end(struct libinput_device *device,
>                        int cancelled);
>  
>  void
> +dial_notify(struct libinput_device *device,
> +         uint64_t time,
> +         int16_t value);
> +
> +void
>  touch_notify_frame(struct libinput_device *device,
>                  uint64_t time);
>  
> diff --git a/src/libinput.c b/src/libinput.c
> index 2bcd416..8fc6ed8 100644
> --- a/src/libinput.c
> +++ b/src/libinput.c
> @@ -125,6 +125,12 @@ struct libinput_event_gesture {
>       double angle;
>  };
>  
> +struct libinput_event_dial {
> +     struct libinput_event base;
> +     uint64_t time;
> +     int16_t count;
> +};
> +
>  struct libinput_event_tablet_tool {
>       struct libinput_event base;
>       uint32_t button;
> @@ -318,6 +324,15 @@ libinput_event_get_tablet_tool_event(struct 
> libinput_event *event)
>       return (struct libinput_event_tablet_tool *) event;
>  }
>  
> +LIBINPUT_EXPORT struct libinput_event_dial *
> +libinput_event_get_dial_event(struct libinput_event *event)
> +{
> +     require_event_type(libinput_event_get_context(event), event->type, NULL,
> +                        LIBINPUT_EVENT_DIAL);
> +
> +     return (struct libinput_event_dial *) event;
> +}
> +
>  LIBINPUT_EXPORT struct libinput_event_device_notify *
>  libinput_event_get_device_notify_event(struct libinput_event *event)
>  {
> @@ -1473,6 +1488,39 @@ libinput_tablet_tool_unref(struct libinput_tablet_tool 
> *tool)
>       return NULL;
>  }
>  
> +LIBINPUT_EXPORT uint32_t
> +libinput_event_dial_get_time(struct libinput_event_dial *event)
> +{
> +     require_event_type(libinput_event_get_context(&event->base),
> +                        event->base.type,
> +                        0,
> +                        LIBINPUT_EVENT_DIAL);
> +
> +     return us2ms(event->time);
> +}
> +
> +LIBINPUT_EXPORT uint64_t
> +libinput_event_dial_get_time_usec(struct libinput_event_dial *event)
> +{
> +     require_event_type(libinput_event_get_context(&event->base),
> +                        event->base.type,
> +                        0,
> +                        LIBINPUT_EVENT_DIAL);
> +
> +     return event->time;
> +}
> +
> +LIBINPUT_EXPORT int16_t
> +libinput_event_dial_get_rotation_count(struct libinput_event_dial *event)
> +{
> +     require_event_type(libinput_event_get_context(&event->base),
> +                        event->base.type,
> +                        0,
> +                        LIBINPUT_EVENT_DIAL);
> +
> +     return event->count;
> +}
> +
>  struct libinput_source *
>  libinput_add_fd(struct libinput *libinput,
>               int fd,
> @@ -1953,6 +2001,9 @@ device_has_cap(struct libinput_device *device,
>       case LIBINPUT_DEVICE_CAP_TABLET_TOOL:
>               capability = "CAP_TABLET";
>               break;
> +     case LIBINPUT_DEVICE_CAP_DIAL:
> +             capability = "CAP_DIAL";
> +             break;
>       }
>  
>       log_bug_libinput(device->seat->libinput,
> @@ -2451,6 +2502,7 @@ event_type_to_str(enum libinput_event_type type)
>       CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_BEGIN);
>       CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_UPDATE);
>       CASE_RETURN_STRING(LIBINPUT_EVENT_GESTURE_PINCH_END);
> +     CASE_RETURN_STRING(LIBINPUT_EVENT_DIAL);
>       case LIBINPUT_EVENT_NONE:
>               abort();
>       }
> @@ -2458,6 +2510,28 @@ event_type_to_str(enum libinput_event_type type)
>       return NULL;
>  }
>  
> +void
> +dial_notify(struct libinput_device *device,
> +         uint64_t time,
> +         int16_t value)
> +{
> +     struct libinput_event_dial *dial_event;
> +
> +     if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_DIAL))
> +             return;
> +
> +     dial_event = zalloc(sizeof *dial_event);
> +     if (!dial_event)
> +             return;
> +
> +     *dial_event = (struct libinput_event_dial) {
> +             .time = time,
> +             .count = value,
> +     };
> +
> +     post_device_event(device, time, LIBINPUT_EVENT_DIAL, &dial_event->base);
> +}
> +
>  static void
>  libinput_post_event(struct libinput *libinput,
>                   struct libinput_event *event)
> diff --git a/src/libinput.h b/src/libinput.h
> index 8ed5632..fdba4f2 100644
> --- a/src/libinput.h
> +++ b/src/libinput.h
> @@ -60,6 +60,7 @@ enum libinput_device_capability {
>       LIBINPUT_DEVICE_CAP_TOUCH = 2,
>       LIBINPUT_DEVICE_CAP_TABLET_TOOL = 3,
>       LIBINPUT_DEVICE_CAP_GESTURE = 5,
> +     LIBINPUT_DEVICE_CAP_DIAL = 8,
>  };
>  
>  /**
> @@ -345,6 +346,8 @@ enum libinput_event_type {
>       LIBINPUT_EVENT_GESTURE_PINCH_BEGIN,
>       LIBINPUT_EVENT_GESTURE_PINCH_UPDATE,
>       LIBINPUT_EVENT_GESTURE_PINCH_END,
> +
> +     LIBINPUT_EVENT_DIAL = 900,
>  };
>  
>  /**
> @@ -552,6 +555,20 @@ libinput_event_get_gesture_event(struct libinput_event 
> *event);
>  /**
>   * @ingroup event
>   *
> + * Return the dial event that is this input event. If the event type does
> + * not match the device event types, this function returns NULL.
> + *
> + * The inverse of this function is
> + * libinput_event_device_notify_get_base_event().
> + *
> + * @return A device event, or NULL for other events
> + */
> +struct libinput_event_dial *
> +libinput_event_get_dial_event(struct libinput_event *event);
> +
> +/**
> ++ * @ingroup event
> ++ *
>   * Return the tablet event that is this input event. If the event type does 
> not
>   * match the tablet event types, this function returns NULL.
>   *
> @@ -2082,6 +2099,35 @@ libinput_tablet_tool_set_user_data(struct 
> libinput_tablet_tool *tool,
>                                  void *user_data);
>  
>  /**
> + * @ingroup event_dial
> + *
> + * @return The event time for this event
> + */
> +uint32_t
> +libinput_event_dial_get_time(struct libinput_event_dial *event);
> +
> +/**
> + * @ingroup event_dial
> + *
> + * @return The event time for this event in microseconds
> + */
> +uint64_t
> +libinput_event_dial_get_time_usec(struct libinput_event_dial *event);
> +
> +/**
> + * @ingroup event_dial
> + *
> + * Return the number of rotation made in the dial.
> + *
> + * Positive value indicates clockwise dial rotation, negavtive value 
> indicates
> + * anticlockwise dial rotation.
> + *
> + * @return the number of dial rotation
> + */
> +int16_t
> +libinput_event_dial_get_rotation_count(struct libinput_event_dial *event);
> +
> +/**
>   * @defgroup base Initialization and manipulation of libinput contexts
>   */
>  
> diff --git a/src/libinput.sym b/src/libinput.sym
> index a211388..ce0d859 100644
> --- a/src/libinput.sym
> +++ b/src/libinput.sym
> @@ -233,4 +233,9 @@ LIBINPUT_1.2 {
>       libinput_tablet_tool_ref;
>       libinput_tablet_tool_set_user_data;
>       libinput_tablet_tool_unref;
> +
> +     libinput_event_get_dial_event;
> +     libinput_event_dial_get_time;
> +     libinput_event_dial_get_time_usec;
> +     libinput_event_dial_get_rotation_count;
>  } LIBINPUT_1.1;
> diff --git a/tools/event-debug.c b/tools/event-debug.c
> index 648111e..039c64d 100644
> --- a/tools/event-debug.c
> +++ b/tools/event-debug.c
> @@ -121,6 +121,9 @@ print_event_header(struct libinput_event *ev)
>       case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
>               type = "TABLET_BUTTON";
>               break;
> +     case LIBINPUT_EVENT_DIAL:
> +             type = "DIAL_ROTATE";
> +             break;
>       }
>  
>       printf("%-7s    %-16s ", libinput_device_get_sysname(dev), type);
> @@ -543,6 +546,23 @@ print_gesture_event_without_coords(struct libinput_event 
> *ev)
>  }
>  
>  static void
> +print_dial_event(struct libinput_event *ev)
> +{
> +     struct libinput_event_dial *t = libinput_event_get_dial_event(ev);
> +     enum libinput_event_type type;
> +     int16_t count = 0;
> +
> +     type = libinput_event_get_type(ev);
> +
> +     print_event_time(libinput_event_dial_get_time(t));
> +     count = libinput_event_dial_get_rotation_count(t);
> +     if (count > 0)
> +             printf("Dial rotated clockwise %d times\n", count);
> +     else
> +             printf("Dial rotated anti-clockwise %d times\n", count);
> +}
> +
> +static void
>  print_gesture_event_with_coords(struct libinput_event *ev)
>  {
>       struct libinput_event_gesture *t = libinput_event_get_gesture_event(ev);
> @@ -647,6 +667,9 @@ handle_and_print_events(struct libinput *li)
>               case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
>                       print_tablet_button_event(ev);
>                       break;
> +             case LIBINPUT_EVENT_DIAL:
> +                     print_dial_event(ev);
> +                     break;
>               }
>  
>               libinput_event_destroy(ev);
> -- 
> 2.5.0
_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to