[PATCH libevdev 3/7] Add setters for an event or slot value

Peter Hutterer peter.hutterer at who-t.net
Wed Aug 14 20:38:28 PDT 2013


On Wed, Aug 14, 2013 at 04:38:42PM +0200, Benjamin Tissoires wrote:
> On Wed, Aug 14, 2013 at 2:50 AM, Peter Hutterer
> <peter.hutterer at who-t.net> wrote:
> > Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> > ---
> >  libevdev/libevdev.c         |  47 ++++++++++++
> >  libevdev/libevdev.h         |  52 +++++++++++++
> >  test/test-libevdev-events.c | 180 ++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 279 insertions(+)
> >
> > diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
> > index 4603651..cade991 100644
> > --- a/libevdev/libevdev.c
> > +++ b/libevdev/libevdev.c
> > @@ -773,6 +773,29 @@ libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned
> >         return value;
> >  }
> >
> > +int libevdev_set_event_value(struct libevdev *dev, unsigned int type, unsigned int code, int value)
> > +{
> > +       int rc = 0;
> > +       struct input_event e;
> > +
> > +       if (!libevdev_has_event_type(dev, type) || !libevdev_has_event_code(dev, type, code))
> > +               return -1;
> > +
> > +       e.type = type;
> > +       e.code = code;
> > +       e.value = value;
> > +
> > +       switch(type) {
> > +               case EV_ABS: rc = update_abs_state(dev, &e); break;
> > +               case EV_KEY: rc = update_key_state(dev, &e); break;
> > +               default:
> > +                            rc = -1;
> > +                            break;
> > +       }
> > +
> > +       return rc;
> > +}
> > +
> >  int
> >  libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, unsigned int code, int *value)
> >  {
> > @@ -800,6 +823,30 @@ libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsigned
> >  }
> >
> >  int
> > +libevdev_set_slot_value(struct libevdev *dev, unsigned int slot, unsigned int code, int value)
> > +{
> 
> Ok, I am a little bit lost with all this:
> - in the kernel, the choice done was to first update the current slot,
> then you use the regular ioctl to set slots values (this is were my
> wonders start actually)
> - libevdev_set_event_value() can mimic the previous statement because
> update_abs_state() will update the right value for the current slot
> - so, we could replace all the fallowing implementation by calling
> twice libevdev_set_event_value() with first, the slot, and then, the
> actual value

first - adding the set_slot_value API was largely for symmetry to
libevdev_get_event_value() and libevdev_get_slot_value(). setting slot
values could be achieved by double-calls, but that would confuse the caller
code a bit. compare:

    for (i = 0; i < nslots; i++)
           libevdev_set_slot_value(dev, i, ABS_MT_POSITION_X, 1);

to the IMO much less obvious:

    for (i = 0; i < nslots; i++) {
        libevdev_set_event_value(dev, EV_ABS, ABS_MT_SLOT, i);
        libevdev_set_event_value(dev, EV_ABS, ABS_MT_POSITION_X, 1);
    }
    libevdev_set_event_value(dev, EV_ABS, ABS_MT_SLOT, old_slot);

> - libevdev has a special API to retrieve the current value of a particular slot

same reason as above.

> - libevdev_get_event_value() is not symmetric to
> libevdev_set_event_value() due to the special behavior of
> update_abs_state() regarding slots (as mentioned before)

this should be as simple as changing update_abs_state to not return after
update_mt_state. that way abs_info[x].value is always for the current slot,
but the mt state is maintained correctly too.

libevdev_get_event_value() will return the value stored there, which just
needs to be documented.

> - what happens if a device presents a lot of absolute axis, and
> therefore use ABS_MT_* as generic axis, and not the actual multitouch
> protocol?

libevdev_get/set_event_value should work fine.

> - what is the question related to the answer to the ultimate question
> of Life, the universe, and everything?

42

> The problem I see here is that we have no clue to know if ABS_MT_SLOT
> is used for the multitouch protocol or not.
> 
> Anyway, I would rather see something symmetric with the setters and
> the getters. So maybe, we should not use update_abs_state() in the
> setter, and I'll be happy.

patch coming up.

Cheers,
   Peter

> > +       if (!libevdev_has_event_type(dev, EV_ABS) || !libevdev_has_event_code(dev, EV_ABS, code))
> > +               return -1;
> > +
> > +       if (slot >= dev->num_slots || slot >= MAX_SLOTS)
> > +               return -1;
> > +
> > +       if (code > ABS_MT_MAX || code < ABS_MT_MIN)
> > +               return -1;
> > +
> > +       if (code == ABS_MT_SLOT) {
> > +               if (value < 0 || value >= libevdev_get_num_slots(dev))
> > +                       return -1;
> > +               dev->current_slot = value;
> > +       }
> > +
> > +       dev->mt_slot_vals[slot][code - ABS_MT_MIN] = value;
> > +
> > +
> > +       return 0;
> > +}
> > +
> > +int
> >  libevdev_fetch_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code, int *value)
> >  {
> >         if (libevdev_has_event_type(dev, EV_ABS) &&
> > diff --git a/libevdev/libevdev.h b/libevdev/libevdev.h
> > index ccb2cc7..4c01847 100644
> > --- a/libevdev/libevdev.h
> > +++ b/libevdev/libevdev.h
> > @@ -814,6 +814,30 @@ const struct input_absinfo* libevdev_get_abs_info(const struct libevdev *dev, un
> >  int libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned int code);
> >
> >  /**
> > + * @ingroup kernel
> > + *
> > + * Set the value for a given event type and code. This only makes sense for
> > + * some event types, e.g. setting the value for EV_REL is pointless.
> > + *
> > + * This is a local modification only affecting only this representation of
> > + * this device. A future call to libevdev_get_event_value() will return this
> > + * value, unless the value was overwritten by an event.
> > + *
> > + * @param dev The evdev device, already initialized with libevdev_set_fd()
> > + * @param type The event type for the code to query (EV_SYN, EV_REL, etc.)
> > + * @param code The event code to set the value for, one of ABS_X, LED_NUML, etc.
> > + * @param value The new value to set
> > + *
> > + * @return 0 on success, or -1 on failure.
> > + * @retval -1 the device does not have the event type or code enabled, or the code is outside the
> > + * allowed limits for the given type, or the type cannot be set.
> > + *
> > + * @see libevdev_set_slot_value
> > + * @see libevdev_get_event_value
> > + */
> > +int libevdev_set_event_value(struct libevdev *dev, unsigned int type, unsigned int code, int value);
> > +
> > +/**
> >   * @ingroup bits
> >   *
> >   * Fetch the current value of the event type. This is a shortcut for
> > @@ -863,6 +887,34 @@ int libevdev_fetch_event_value(const struct libevdev *dev, unsigned int type, un
> >  int libevdev_get_slot_value(const struct libevdev *dev, unsigned int slot, unsigned int code);
> >
> >  /**
> > + * @ingroup kernel
> > + *
> > + * Set the value for a given code for the given slot.
> > + *
> > + * This is a local modification only affecting only this representation of
> > + * this device. A future call to libevdev_get_slot_value() will return this
> > + * value, unless the value was overwritten by an event.
> > + *
> > + * This function does not set event values for axes outside the ABS_MT range,
> > + * use libevdev_set_event_value() instead.
> > + *
> > + * @param dev The evdev device, already initialized with libevdev_set_fd()
> > + * @param slot The numerical slot number, must be smaller than the total number
> > + * of slots on this device
> > + * @param code The event code to set the value for, one of ABS_MT_POSITION_X, etc.
> > + * @param value The new value to set
> > + *
> > + * @return 0 on success, or -1 on failure.
> > + * @retval -1 the device does not have the event code enabled, or the code is
> > + * outside the allowed limits for multitouch events, or the slot number is outside
> > + * the limits for this device, or the device does not support multitouch events.
> > + *
> > + * @see libevdev_set_event_value
> > + * @see libevdev_get_slot_value
> > + */
> > +int libevdev_set_slot_value(struct libevdev *dev, unsigned int slot, unsigned int code, int value);
> > +
> > +/**
> >   * @ingroup mt
> >   *
> >   * Fetch the current value of the code for the given slot. This is a shortcut for
> > diff --git a/test/test-libevdev-events.c b/test/test-libevdev-events.c
> > index 40f94dd..95105d1 100644
> > --- a/test/test-libevdev-events.c
> > +++ b/test/test-libevdev-events.c
> > @@ -806,6 +806,179 @@ START_TEST(test_mt_event_values_invalid)
> >  }
> >  END_TEST
> >
> > +START_TEST(test_event_value_setters)
> > +{
> > +       struct uinput_device* uidev;
> > +       struct libevdev *dev;
> > +       int rc;
> > +       struct input_absinfo abs[2];
> > +
> > +       memset(abs, 0, sizeof(abs));
> > +       abs[0].value = ABS_X;
> > +       abs[0].maximum = 1000;
> > +
> > +       abs[1].value = ABS_Y;
> > +       abs[1].maximum = 1000;
> > +
> > +       rc = test_create_abs_device(&uidev, &dev,
> > +                                   2, abs,
> > +                                   EV_SYN, SYN_REPORT,
> > +                                   EV_REL, REL_X,
> > +                                   EV_REL, REL_Y,
> > +                                   EV_KEY, BTN_LEFT,
> > +                                   EV_KEY, BTN_MIDDLE,
> > +                                   EV_KEY, BTN_RIGHT,
> > +                                   -1);
> > +       ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
> > +
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_KEY, BTN_LEFT), 0);
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_X), 0);
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_Y), 0);
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_REL, REL_X), 0);
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_REL, REL_Y), 0);
> > +
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_KEY, BTN_LEFT, 1), 0);
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_KEY, BTN_RIGHT, 1), 0);
> > +
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_KEY, BTN_LEFT), 1);
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_KEY, BTN_RIGHT), 1);
> > +
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_X, 10), 0);
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_Y, 20), 0);
> > +
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_X), 10);
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_ABS, ABS_Y), 20);
> > +
> > +       uinput_device_free(uidev);
> > +       libevdev_free(dev);
> > +
> > +}
> > +END_TEST
> > +
> > +START_TEST(test_event_value_setters_invalid)
> > +{
> > +       struct uinput_device* uidev;
> > +       struct libevdev *dev;
> > +       int rc;
> > +       struct input_absinfo abs[2];
> > +
> > +       memset(abs, 0, sizeof(abs));
> > +       abs[0].value = ABS_X;
> > +       abs[0].maximum = 1000;
> > +
> > +       abs[1].value = ABS_Y;
> > +       abs[1].maximum = 1000;
> > +
> > +       rc = test_create_abs_device(&uidev, &dev,
> > +                                   2, abs,
> > +                                   EV_SYN, SYN_REPORT,
> > +                                   EV_REL, REL_X,
> > +                                   EV_REL, REL_Y,
> > +                                   EV_KEY, BTN_LEFT,
> > +                                   EV_KEY, BTN_MIDDLE,
> > +                                   EV_KEY, BTN_RIGHT,
> > +                                   -1);
> > +       ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
> > +
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_REL, REL_X, 1), -1);
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_SW, SW_DOCK, 1), -1);
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_ABS, ABS_Z, 1), -1);
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_MAX + 1, 0, 1), -1);
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_SYN, SYN_REPORT, 0), -1);
> > +
> > +       uinput_device_free(uidev);
> > +       libevdev_free(dev);
> > +
> > +}
> > +END_TEST
> > +
> > +START_TEST(test_event_mt_value_setters)
> > +{
> > +       struct uinput_device* uidev;
> > +       struct libevdev *dev;
> > +       int rc;
> > +       struct input_absinfo abs[5];
> > +
> > +       memset(abs, 0, sizeof(abs));
> > +       abs[0].value = ABS_X;
> > +       abs[0].maximum = 1000;
> > +       abs[1].value = ABS_MT_POSITION_X;
> > +       abs[1].maximum = 1000;
> > +
> > +       abs[2].value = ABS_Y;
> > +       abs[2].maximum = 1000;
> > +       abs[3].value = ABS_MT_POSITION_Y;
> > +       abs[3].maximum = 1000;
> > +
> > +       abs[4].value = ABS_MT_SLOT;
> > +       abs[4].maximum = 2;
> > +
> > +       rc = test_create_abs_device(&uidev, &dev,
> > +                                   5, abs,
> > +                                   EV_SYN, SYN_REPORT,
> > +                                   -1);
> > +       ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
> > +
> > +       ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_MT_POSITION_X, 1), 0);
> > +       ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_MT_POSITION_Y, 2), 0);
> > +       ck_assert_int_eq(libevdev_set_slot_value(dev, 0, ABS_MT_POSITION_X, 3), 0);
> > +       ck_assert_int_eq(libevdev_set_slot_value(dev, 0, ABS_MT_POSITION_Y, 4), 0);
> > +
> > +       ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_X), 1);
> > +       ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_POSITION_Y), 2);
> > +       ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_X), 3);
> > +       ck_assert_int_eq(libevdev_get_slot_value(dev, 0, ABS_MT_POSITION_Y), 4);
> > +
> > +       ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_MT_SLOT, 1), 0);
> > +       ck_assert_int_eq(libevdev_get_slot_value(dev, 1, ABS_MT_SLOT), 1);
> > +       ck_assert_int_eq(libevdev_get_current_slot(dev), 1);
> > +
> > +       uinput_device_free(uidev);
> > +       libevdev_free(dev);
> > +}
> > +END_TEST
> > +
> > +START_TEST(test_event_mt_value_setters_invalid)
> > +{
> > +       struct uinput_device* uidev;
> > +       struct libevdev *dev;
> > +       int rc;
> > +       struct input_absinfo abs[5];
> > +
> > +       memset(abs, 0, sizeof(abs));
> > +       abs[0].value = ABS_X;
> > +       abs[0].maximum = 1000;
> > +       abs[1].value = ABS_MT_POSITION_X;
> > +       abs[1].maximum = 1000;
> > +
> > +       abs[2].value = ABS_Y;
> > +       abs[2].maximum = 1000;
> > +       abs[3].value = ABS_MT_POSITION_Y;
> > +       abs[3].maximum = 1000;
> > +
> > +       abs[4].value = ABS_MT_SLOT;
> > +       abs[4].maximum = 2;
> > +
> > +       rc = test_create_abs_device(&uidev, &dev,
> > +                                   5, abs,
> > +                                   EV_SYN, SYN_REPORT,
> > +                                   -1);
> > +       ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
> > +
> > +       /* invalid axis */
> > +       ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_Z, 1), -1);
> > +       /* valid, but non-mt axis */
> > +       ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_X, 1), -1);
> > +       /* invalid mt axis */
> > +       ck_assert_int_eq(libevdev_set_slot_value(dev, 1, ABS_MT_PRESSURE, 1), -1);
> > +       /* invalid slot no */
> > +       ck_assert_int_eq(libevdev_set_slot_value(dev, 4, ABS_X, 1), -1);
> > +
> > +       uinput_device_free(uidev);
> > +       libevdev_free(dev);
> > +}
> > +END_TEST
> > +
> >  Suite *
> >  libevdev_events(void)
> >  {
> > @@ -838,6 +1011,13 @@ libevdev_events(void)
> >         tcase_add_test(tc, test_mt_event_values_invalid);
> >         suite_add_tcase(s, tc);
> >
> > +       tc = tcase_create("event value setters");
> > +       tcase_add_test(tc, test_event_value_setters);
> > +       tcase_add_test(tc, test_event_value_setters_invalid);
> > +       tcase_add_test(tc, test_event_mt_value_setters);
> > +       tcase_add_test(tc, test_event_mt_value_setters_invalid);
> > +       suite_add_tcase(s, tc);
> > +
> >         return s;
> >  }
> >
> > --
> > 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