[PATCH libevdev 3/4] memcpy instead of invidual bittoggle

Peter Hutterer peter.hutterer at who-t.net
Fri Aug 30 16:11:23 PDT 2013


On Fri, Aug 30, 2013 at 10:30:27AM +0200, Benjamin Tissoires wrote:
> 
> 
> On Fri, Aug 30, 2013 at 3:06 AM, Peter Hutterer
> <peter.hutterer at who-t.net> wrote:
> > The ioctls return the number of bytes copied into the destination, so just
> > copy them into the device state instead of individually flipping bits.
> >
> > For easier review: rc is the return value of the EVIOCG* ioctl, which is
> > the number of bytes copied.
> >
> > Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> > ---
> 
> Reviewed-by: Benjamin TIssoires <benjamin.tissoires at gmail.com>
> 
> Hi Peter,
> 
> well, it took me some time to review this, because I felt that something
> weird could happen. I think I found a use case where thinks are broken
> (but it's a weird one, and is not fixed either by the patch):
> 
> Let's imagine first that we introduce in the kernel a new range of keys,
> big enough that NLONGS(KEY_CNT) is incremented.
> Of course, in order to avoid recompilation if we run the same lib
> against different kernels, we define those new KEY_* in libevdev. That
> means that NLONGS(KEY_CNT) in libevdev is bigger than NLONGS(KEY_CNT) in
> the kernel.
> 
> Now, let's look at the current code of sync_key_state():
> 
> ---
> 
> static int
> sync_key_state(struct libevdev *dev)
> {
> 	int rc;
> 	int i;
> 	unsigned long keystate[NLONGS(KEY_CNT)];
> 
> // keystate may contain here garbage
> 
> 	rc = ioctl(dev->fd, EVIOCGKEY(sizeof(keystate)), keystate);
> 	if (rc < 0)
> 		goto out;
> 
> // rc should be "sizeof(keystate) - sizeof(unsigned long)" if I am not
> // wrong
> 
> 	for (i = 0; i < KEY_CNT; i++) {
> 		int old, new;
> 		old = bit_is_set(dev->key_values, i);
> 		new = bit_is_set(keystate, i);
> 
> // "new" for bits in range [NLONGS(KEY_CNT) - 2 .. NLONGS(KEY_CNT) -1]
> // is random
> 
> 		if (old ^ new) {
> 			struct input_event *ev = queue_push(dev);
> 			init_event(dev, ev, EV_KEY, i, new ? 1 : 0);
> 
> // we are sending random events
> 
> 		}
> 		set_bit_state(dev->key_values, i, new);
> 	}
> 
> 	rc = 0;
> out:
> 	return rc ? -errno : 0;
> }
> 
> ---
> 
> Actually, what is bothering me, is that we don't take into account the
> return value "rc" before doing the for loop.
> 
> Would it cost too much to do:
> 
>   unsigned long keystate[NLONGS(KEY_CNT)] = {0};
> 
> in term of performance? Of course, if that fixes this problem. (and same
> goes for each other of the sync_*_state()).

good catch. I felt something wasn't right with this patch but just couldn't
put myu finger on it. I've amended as you requested, with a note in the
commit message. thanks for the review.

I don't think performance is a issue here, though I haven't measured the
impact.

Cheers,
   Peter

> 
> Cheers,
> Benjamin
> 
> >  libevdev/libevdev.c | 9 ++++++---
> >  1 file changed, 6 insertions(+), 3 deletions(-)
> >
> > diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
> > index 73405bc..9b37f70 100644
> > --- a/libevdev/libevdev.c
> > +++ b/libevdev/libevdev.c
> > @@ -320,9 +320,10 @@ sync_key_state(struct libevdev *dev)
> >                         struct input_event *ev = queue_push(dev);
> >                         init_event(dev, ev, EV_KEY, i, new ? 1 : 0);
> >                 }
> > -               set_bit_state(dev->key_values, i, new);
> >         }
> >
> > +       memcpy(dev->key_values, keystate, rc);
> > +
> >         rc = 0;
> >  out:
> >         return rc ? -errno : 0;
> > @@ -347,9 +348,10 @@ sync_sw_state(struct libevdev *dev)
> >                         struct input_event *ev = queue_push(dev);
> >                         init_event(dev, ev, EV_SW, i, new ? 1 : 0);
> >                 }
> > -               set_bit_state(dev->sw_values, i, new);
> >         }
> >
> > +       memcpy(dev->sw_values, swstate, rc);
> > +
> >         rc = 0;
> >  out:
> >         return rc ? -errno : 0;
> > @@ -374,9 +376,10 @@ sync_led_state(struct libevdev *dev)
> >                         struct input_event *ev = queue_push(dev);
> >                         init_event(dev, ev, EV_LED, i, new ? 1 : 0);
> >                 }
> > -               set_bit_state(dev->led_values, i, new);
> >         }
> >
> > +       memcpy(dev->led_values, ledstate, rc);
> > +
> >         rc = 0;
> >  out:
> >         return rc ? -errno : 0;
> > --
> > 1.8.2.1
> >
> > _______________________________________________
> > Input-tools mailing list
> > Input-tools at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/input-tools


More information about the Input-tools mailing list