Re: [RFC][PATCH] Input: Add infrastrucutre for selecting clockid for event time stamps.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Jan 7, 2012 at 11:40 AM, John Stultz <john.stultz@xxxxxxxxxx> wrote:
> Ok, hopefully getting close. Updated fixing the bool/int issue
> Daniel pointed out. Let me know if you have any other thoughts!
>
> thanks
> -john
>
> As noted by Arve and others since wall time can jump backwards, it
> is difficult to use for input because one cannot determine if one
> event occured before another or for how long a key was pressed.
>
> However, the timestamp field is part of the kernel ABI, and cannot
> be changed without possibly breaking existing users.
>
> This patch adds a new IOCTL that allows a clockid to be set in
> the evdev_client struct that will specify which time base to
> use for event timestamps (ie: CLOCK_MONOTONIC instead
> of CLOCK_REALTIME).
>
> For now we only support CLOCK_MONOTONIC and CLOCK_REALTIME, but
> in the future we could support other clockids if appropriate.
>
> The default remains CLOCK_REALTIME, so we don't change the ABI.
>
> CC: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>
> CC: Daniel Kurtz <djkurtz@xxxxxxxxxx>
> CC: linux-input@xxxxxxxxxxxxxxx
> CC: Arve Hjønnevåg <arve@xxxxxxxxxxx>
> CC: Brian Swetland <swetland@xxxxxxxxxx>
> CC: Colin Cross <ccross@xxxxxxxxxxx>
> CC: Dima Zavin <dima@xxxxxxxxxxx>
> Signed-off-by: John Stultz <john.stultz@xxxxxxxxxx>
> ---
>  drivers/input/evdev.c |   33 +++++++++++++++++++++++++++++----
>  include/linux/input.h |    2 ++
>  2 files changed, 31 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
> index 4cf2534..edabd9e 100644
> --- a/drivers/input/evdev.c
> +++ b/drivers/input/evdev.c
> @@ -46,6 +46,7 @@ struct evdev_client {
>        struct fasync_struct *fasync;
>        struct evdev *evdev;
>        struct list_head node;
> +       int timestamp_clkid;
>        unsigned int bufsize;
>        struct input_event buffer[];
>  };
> @@ -54,8 +55,19 @@ static struct evdev *evdev_table[EVDEV_MINORS];
>  static DEFINE_MUTEX(evdev_table_mutex);
>
>  static void evdev_pass_event(struct evdev_client *client,
> -                            struct input_event *event)
> +                            struct input_event *event,
> +                            ktime_t mono, ktime_t real)
>  {
> +       struct timespec ts;
> +
> +       if (client->timestamp_clkid == CLOCK_MONOTONIC)
> +               ts = ktime_to_timespec(mono);
> +       else
> +               ts = ktime_to_timespec(real);
> +       event->time.tv_sec = ts.tv_sec;
> +       event->time.tv_usec = ts.tv_nsec / NSEC_PER_USEC;

Maybe just:

 event->time = (client->timestamp_clkid == CLOCK_MONOTONIC) ?
                      ktime_to_timeval(mono) : ktime_to_timeval(real);

Either way, lgtm...

Reviewed-by: Daniel Kurtz <djkurtz@xxxxxxxxxx>

> +
> +
>        /* Interrupts are disabled, just acquire the lock. */
>        spin_lock(&client->buffer_lock);
>
> @@ -94,8 +106,11 @@ static void evdev_event(struct input_handle *handle,
>        struct evdev *evdev = handle->private;
>        struct evdev_client *client;
>        struct input_event event;
> +       ktime_t time_mono, time_real;
> +
> +       time_mono = ktime_get();
> +       time_real = ktime_sub(time_mono, ktime_get_monotonic_offset());
>
> -       do_gettimeofday(&event.time);
>        event.type = type;
>        event.code = code;
>        event.value = value;
> @@ -103,11 +118,12 @@ static void evdev_event(struct input_handle *handle,
>        rcu_read_lock();
>
>        client = rcu_dereference(evdev->grab);
> +
>        if (client)
> -               evdev_pass_event(client, &event);
> +               evdev_pass_event(client, &event, time_mono, time_real);
>        else
>                list_for_each_entry_rcu(client, &evdev->client_list, node)
> -                       evdev_pass_event(client, &event);
> +                       evdev_pass_event(client, &event, time_mono, time_real);
>
>        rcu_read_unlock();
>
> @@ -683,6 +699,15 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
>                else
>                        return evdev_ungrab(evdev, client);
>
> +       case EVIOCCLOCKID:
> +               if (copy_from_user(&i, p, sizeof(unsigned int)))
> +                       return -EFAULT;
> +               if ((i == CLOCK_MONOTONIC) || (i == CLOCK_REALTIME)) {
> +                       client->timestamp_clkid = i;
> +                       return 0;
> +               }
> +               return -EINVAL;
> +
>        case EVIOCGKEYCODE:
>                return evdev_handle_get_keycode(dev, p);
>
> diff --git a/include/linux/input.h b/include/linux/input.h
> index 3862e32..9618e14 100644
> --- a/include/linux/input.h
> +++ b/include/linux/input.h
> @@ -129,6 +129,8 @@ struct input_keymap_entry {
>
>  #define EVIOCGRAB              _IOW('E', 0x90, int)                    /* Grab/Release device */
>
> +#define EVIOCCLOCKID           _IOW('E', 0xA0, int)                    /* Set clockid to be used for timestamps */
> +
>  /*
>  * Device properties and quirks
>  */
> --
> 1.7.3.2.146.gca209
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-input" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux