[ANNOUNCE] libevdev - a library to wrap the evdev kernel interface

Wander Lairson Costa wander.lairson at gmail.com
Thu Jun 27 15:17:03 PDT 2013


2013/6/27 Peter Hutterer <peter.hutterer at who-t.net>:
> On Thu, Jun 27, 2013 at 11:15:03AM -0300, Wander Lairson Costa wrote:
>> 2013/6/27 Peter Hutterer <peter.hutterer at who-t.net>:
>> > For the last month or so I've been spending some time on a helper library
>> > for evdev devices. The motivation is two-fold:
>> >
>> > * users of evdev currently issue ioctls directly, checking bit masks
>> >   manually. all this is a source for error, especially as there are some
>> >   inconsistencies in the ioctl APIs. For example, EV_REP does not behave the
>> >   same way as EV_KEY. this can be abstracted through a library.
>> >
>> > * SYN_DROPPED signals that the process is not reading events fast enough.
>> >   The process must re-sync the device, calculating the delta and processing
>> >   it accordingly. This is similar across all drivers, but needlessly
>> >   complicated.
>> >
>> > libevdev provides API calls for the various bits, so a client can work this
>> > way:
>> >
>> >   struct libevdev *dev;
>> >
>> >   fd = open("/dev/input/event0", O_RDONLY);
>> >   rc = libevdev_new_from_fd(fd, &dev);
>> >
>> >   if (libevdev_has_event_code(dev, EV_REL, REL_X))
>> >         /* do something */
>> >
>> > including the various checks that prevent OOM access for invalid types/codes.
>> >
>> > For event handling, libevdev provides one call that returns the next event
>> > in the queue:
>> >
>> >   rc = libevdev_next_event(dev, flags, &ev);
>> >
>> > if a SYN_DROPPED is the next event in the queue, libevdev syncs the device
>> > state and returns 1. The process can then handle the delta by simply parsing
>> > events until the device is fully synced again:
>> >
>> >   while ((rc = libevdev_next_event(dev, LIBEVEV_READ_SYNC, &ev)) == 1)
>> >      /* this is a synced event */
>> >
>> >   if (rc == -EAGAIN)
>> >      /* we are now fully synced */
>> >   else
>> >      /* error */
>> >
>> > For a more complete example: evtest written with libevdev would look like
>> > this:
>> > https://github.com/whot/libevdev/blob/master/tools/libevdev-events.c
>> >
>> > The code is still in its early stages and some parts are incomplete, but I'm
>> > at the point where I'd like some comments and eyeballs to help find any
>> > issues with the lot. Ideally, I'd like all of the X drivers and wayland to
>> > eventually use libevdev. Plans to switch evemu, mtdev, etc. are on the todo
>> > list somewhere too.
>> >
>> > Repository sits here:
>> >     https://github.com/whot/libevdev
>> > The API documentation is published here:
>> >     http://whot.github.io/libevdev/doc/html/modules.html
>> >
>> > Suggestions, comments, criticism, etc. welcome.
>> >
>>
>> Hi,
>>
>> First of all, congratulations for the work!
>
> thank.
>
>> I just gave a raw look at the documentation, and I see that
>> libevdev_new returns the struct as the function return value whereas
>> libevdev_new_from_fd returns it as an out parameter. Is there any
>> implementation detail that prohibited you from making them returning
>> the struct in the same way? My suggestion would be to choose a
>> consistent approach, either returns the struct as the return value or
>> as an output parameter, but do the same on both functions, if
>> possible.
>
> this is intentional.
>
> libevdev_new() merely allocates memory, and libevdev_set_fd() then
> associates the device with the pre-allocated struct. that can fail for a
> number of reasons, all expressed through an errno. libevdev_new() can only
> fail on allocation error.
>
> otoh, libevdev_new_from_fd() is a shortcut for both calls together. Since
> associating the device fd can fail, we need to return the error code. so we
> pretty much have a API choice of
>   int libevdev_new_from_fd(fd, struct libevdev**);
> or
>   struct libevdev* libevdev_new_from_fd(fd, int *errno);
>
> I chose the former because any client will have a struct libevdev variable
> or field already anyway, passing in a pointer is easy. In simpler clients,
> errno may be ignored (or just checked for == 0).
> does that make sense?
>

Indeed it makes sense, thanks for the explanation. However, I think
libevdev_new should receive an output struct pointer and return an
error code (even if currently it will always be 0). Besides the fact
it gets consistent with other functions, in the future it can do more
than a memory allocation, and in this case you would have to change
the ABI.

But this is more a matter of personal taste.


-- 
Best Regards,
Wander Lairson Costa


More information about the wayland-devel mailing list