[PATCH libevdev 0/2] libevdev copy constructor

Peter Hutterer peter.hutterer at who-t.net
Tue Nov 5 14:56:53 PST 2013


On Tue, Nov 05, 2013 at 08:41:10AM +0100, David Herrmann wrote:
> Hi Peter
> 
> On Tue, Nov 5, 2013 at 8:31 AM, Peter Hutterer <peter.hutterer at who-t.net> wrote:
> > On Mon, Nov 04, 2013 at 03:51:17PM +0100, David Herrmann wrote:
> >> I am currently hacking on some input stuff and was wondering what to use to
> >> represent "evdev-capabilities". So imagine I have a libevdev object with an
> >> attached fd. On top of that I have a re-mapper which fixes some broken
> >> device-mappings. Now the remapping should be transparent to the application, so
> >> I want to tell the applications the _real_ type/code values of the device, not
> >> the raw ones from the kernel.
> >>
> >> This series introduces libevdev_new_from_libevdev(). I can thus create a copy of
> >> an existing libevdev object, then modify the enabled type/codes and pass it to
> >> the application as "capability set". The application can query it and see which
> >> codes are enabled.
> >>
> >> Another idea I had is to create an object like:
> >>   struct libevdev_caps {
> >>     unsigned long bits[NLONGS(EV_CNT)];
> >>     unsigned long props[NLONGS(INPUT_PROP_CNT)];
> >>     unsigned long key_bits[NLONGS(KEY_CNT)];
> >>     unsigned long rel_bits[NLONGS(REL_CNT)];
> >>     unsigned long abs_bits[NLONGS(ABS_CNT)];
> >>     unsigned long led_bits[NLONGS(LED_CNT)];
> >>     unsigned long msc_bits[NLONGS(MSC_CNT)];
> >>     unsigned long sw_bits[NLONGS(SW_CNT)];
> >>     unsigned long rep_bits[NLONGS(REP_CNT)]; /* convenience, always 1 */
> >>     unsigned long ff_bits[NLONGS(FF_CNT)];
> >>     unsigned long snd_bits[NLONGS(SND_CNT)];
> >>     struct input_absinfo abs_info[ABS_CNT];
> >>   };
> >> That is, exporting the real bits from libevdev to avoid having a copy of the
> >> other data. I doubt that we win anything by this, so I went with my first idea.
> >
> > main question here is whether this capability would be better off inside
> > libevdev? it would be adding complexity, but the question is how much is
> > needed, what's the scope etc. and whether the complexity is going to be
> > worse than having another layer that takes libevdev and presents it as
> > libevdev to the next layer, because then you need to emulate
> > libevdev_next_event() behaviour etc.
> >
> > as soon as you're handing over a libevdev object, the caller will likely
> > assume that it can treat it as such, so you'd have to emulate most/all the
> > API.
> >
> > I take it that's for libinputmapper?
> 
> Kind of. Still just hacking on stuff to figure our what works and what
> doesn't. Note that the copy-constructor would also be highly useful
> for uinput devices. Imagine you have an evdev device and want to
> create multiple uinput devices similar to it. You could just modify
> the source libevdev device, create the uinput device, and then restore
> the real libevdev device. But with the copy-constructor, you could
> just copy the libevdev device, adjust any bits, create the uinput
> device and throw it away afterwards (or keep it as representation of
> your uinput device for later queries).

this isn't too much different to creating a uinput device and then using
that as libevdev device to create the next one, right? I understand that
it seems less convenient but it should achieve the same thing.

> So I think this copy-constructor is useful regardless of the
> capability-thing I was talking about.

fwiw, one thing I've learned the hard way over the past couple of years is
that it's relatively easy to think up use-cases for anything. merging the
code based on that is bad usually, you'll end up with too many options,
APIs, etc. and all for niche or theoretical use-cases. not saying your
use-case is not worthy, but we definitely need more than a "could" before we
add APIs that just replicate behaviour that already exists.

> But ok, lets talk about the other idea:
> I wasn't intending to set the "fd" field on the separate libevdev
> object. So anyone who gets access to the separate libevdev object
> would notice that immediately (get_fd() fails, or any other function
> that requires initialized libevdev objects). All they could do is
> query the state. No need to emulate libevdev_next_event() or something
> else. This object is "dead" and intended to be so.
> As I said, the "cleaner" way is probably a libevdev_cap object which
> just contains the capabilities. We would embed it in "struct libevdev"
> but allow separate access. However, "struct libevdev" itself doesn't
> have that much more information than the capabilities, so I thought
> this might be overengineering and we should just (mis-)use "struct
> libevdev" for it.

what is the client supposed to do with the dead object? 
if the client doesn't expect events from the object anyway, why even bother
unsetting the fd? or otherwise, if the client does expect events how will
it know that a failed libevdev_next_event() doesn't signal that the device
is dead and needs to be removed?

also, what is the difference to 
   libevdev_new_from_fd(fd);
   libevdev_enable_some_bits(fd);
   libevdev_disable_some_other_bits(fd);
   libevdev_change_fd(-1); /* deactivate the fd */
   pass_libevdev_to_recipient();

this way the new object is still "dead" and won't send events, but can be
used to create uinput devices. Since it's initialized you can't re-use it
with set_fd() but you could still hook it up to some random other fd but you
could do that with the copy constructor too afaict.

Cheers,
   Peter


More information about the Input-tools mailing list