[PATCH libevdev 2/2] Add support for EV_SW

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


On Wed, Aug 28, 2013 at 11:20:44AM +0200, Benjamin Tissoires wrote:
> On Tue, Aug 27, 2013 at 12:12 AM, Peter Hutterer
> <peter.hutterer at who-t.net> wrote:
> > Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> > ---
> >  libevdev/libevdev-int.h     |  1 +
> >  libevdev/libevdev.c         | 52 ++++++++++++++++++++++++++++++++++++++++++
> >  test/test-libevdev-events.c | 55 +++++++++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 108 insertions(+)
> >
> > diff --git a/libevdev/libevdev-int.h b/libevdev/libevdev-int.h
> > index 28933ef..38375a5 100644
> > --- a/libevdev/libevdev-int.h
> > +++ b/libevdev/libevdev-int.h
> > @@ -90,6 +90,7 @@ struct libevdev {
> >         unsigned long snd_bits[NLONGS(SND_CNT)];
> >         unsigned long key_values[NLONGS(KEY_CNT)];
> >         unsigned long led_values[NLONGS(LED_CNT)];
> > +       unsigned long sw_values[NLONGS(SW_CNT)];
> >         struct input_absinfo abs_info[ABS_CNT];
> >         unsigned int mt_slot_vals[MAX_SLOTS][ABS_MT_CNT];
> >         int num_slots; /**< valid slots in mt_slot_vals */
> > diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
> > index b692590..4df0ea3 100644
> > --- a/libevdev/libevdev.c
> > +++ b/libevdev/libevdev.c
> > @@ -239,6 +239,10 @@ libevdev_set_fd(struct libevdev* dev, int fd)
> >         if (rc < 0)
> >                 goto out;
> >
> > +       rc = ioctl(fd, EVIOCGSW(sizeof(dev->sw_values)), dev->sw_values);
> > +       if (rc < 0)
> > +               goto out;
> > +
> >         /* rep is a special case, always set it to 1 for both values if EV_REP is set */
> >         if (bit_is_set(dev->bits, EV_REP)) {
> >                 for (i = 0; i < REP_CNT; i++)
> > @@ -325,6 +329,33 @@ out:
> >  }
> >
> >  static int
> > +sync_sw_state(struct libevdev *dev)
> > +{
> > +       int rc;
> > +       int i;
> > +       unsigned long swstate[NLONGS(SW_CNT)];
> > +
> > +       rc = ioctl(dev->fd, EVIOCGSW(sizeof(swstate)), swstate);
> > +       if (rc < 0)
> > +               goto out;
> > +
> > +       for (i = 0; i < SW_MAX; i++) {
> 
> looks like sync_key_state() and sync_led_state() are also buggy here:
> the condition should be i <= SW_MAX, not "<".
> 
> Actually, it does not matter because *_MAX are not the last declared
> event, but still, it may break at some point.

amended, thanks. I had the fixes for key/led in some other branch already,
but hadn't sent those out yet.

Cheers,
   Peter

> 
> > +               int old, new;
> > +               old = bit_is_set(dev->sw_values, i);
> > +               new = bit_is_set(swstate, i);
> > +               if (old ^ new) {
> > +                       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);
> > +       }
> > +
> > +       rc = 0;
> > +out:
> > +       return rc ? -errno : 0;
> > +}
> > +
> > +static int
> >  sync_led_state(struct libevdev *dev)
> >  {
> >         int rc;
> > @@ -472,6 +503,8 @@ sync_state(struct libevdev *dev)
> >                 rc = sync_key_state(dev);
> >         if (libevdev_has_event_type(dev, EV_LED))
> >                 rc = sync_led_state(dev);
> > +       if (libevdev_has_event_type(dev, EV_SW))
> > +               rc = sync_sw_state(dev);
> >         if (rc == 0 && libevdev_has_event_type(dev, EV_ABS))
> >                 rc = sync_abs_state(dev);
> >         if (rc == 0 && libevdev_has_event_code(dev, EV_ABS, ABS_MT_SLOT))
> > @@ -555,6 +588,20 @@ update_led_state(struct libevdev *dev, const struct input_event *e)
> >  }
> >
> >  static int
> > +update_sw_state(struct libevdev *dev, const struct input_event *e)
> > +{
> > +       if (!libevdev_has_event_type(dev, EV_SW))
> > +               return 1;
> > +
> > +       if (e->code > SW_MAX)
> > +               return 1;
> > +
> > +       set_bit_state(dev->sw_values, e->code, e->value != 0);
> > +
> > +       return 0;
> > +}
> > +
> > +static int
> >  update_state(struct libevdev *dev, const struct input_event *e)
> >  {
> >         int rc = 0;
> > @@ -572,6 +619,9 @@ update_state(struct libevdev *dev, const struct input_event *e)
> >                 case EV_LED:
> >                         rc = update_led_state(dev, e);
> >                         break;
> > +               case EV_SW:
> > +                       rc = update_sw_state(dev, e);
> > +                       break;
> >         }
> >
> >         dev->last_event_time = e->time;
> > @@ -821,6 +871,7 @@ libevdev_get_event_value(const struct libevdev *dev, unsigned int type, unsigned
> >                 case EV_ABS: value = dev->abs_info[code].value; break;
> >                 case EV_KEY: value = bit_is_set(dev->key_values, code); break;
> >                 case EV_LED: value = bit_is_set(dev->led_values, code); break;
> > +               case EV_SW: value = bit_is_set(dev->sw_values, code); break;
> >                 default:
> >                         value = 0;
> >                         break;
> > @@ -845,6 +896,7 @@ int libevdev_set_event_value(struct libevdev *dev, unsigned int type, unsigned i
> >                 case EV_ABS: rc = update_abs_state(dev, &e); break;
> >                 case EV_KEY: rc = update_key_state(dev, &e); break;
> >                 case EV_LED: rc = update_led_state(dev, &e); break;
> > +               case EV_SW: rc = update_sw_state(dev, &e); break;
> >                 default:
> >                              rc = -1;
> >                              break;
> > diff --git a/test/test-libevdev-events.c b/test/test-libevdev-events.c
> > index 669de12..046f957 100644
> > --- a/test/test-libevdev-events.c
> > +++ b/test/test-libevdev-events.c
> > @@ -499,6 +499,52 @@ START_TEST(test_syn_delta_led)
> >  }
> >  END_TEST
> >
> > +START_TEST(test_syn_delta_sw)
> > +{
> > +       struct uinput_device* uidev;
> > +       struct libevdev *dev;
> > +       int rc;
> > +       struct input_event ev;
> > +
> > +       rc = test_create_device(&uidev, &dev,
> > +                               EV_SYN, SYN_REPORT,
> > +                               EV_SYN, SYN_DROPPED,
> > +                               EV_SW, SW_LID,
> > +                               EV_SW, SW_MICROPHONE_INSERT,
> > +                               -1);
> > +       ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
> > +
> > +       uinput_device_event(uidev, EV_SW, SW_LID, 1);
> > +       uinput_device_event(uidev, EV_SW, SW_MICROPHONE_INSERT, 1);
> > +       uinput_device_event(uidev, EV_SYN, SYN_REPORT, 0);
> > +       rc = libevdev_next_event(dev, LIBEVDEV_FORCE_SYNC, &ev);
> > +       ck_assert_int_eq(rc, 1);
> > +
> > +       rc = libevdev_next_event(dev, LIBEVDEV_READ_SYNC, &ev);
> > +       ck_assert_int_eq(rc, 1);
> > +       ck_assert_int_eq(ev.type, EV_SW);
> > +       ck_assert_int_eq(ev.code, SW_LID);
> > +       ck_assert_int_eq(ev.value, 1);
> > +       rc = libevdev_next_event(dev, LIBEVDEV_READ_SYNC, &ev);
> > +       ck_assert_int_eq(rc, 1);
> > +       ck_assert_int_eq(ev.type, EV_SW);
> > +       ck_assert_int_eq(ev.code, SW_MICROPHONE_INSERT);
> > +       ck_assert_int_eq(ev.value, 1);
> > +       rc = libevdev_next_event(dev, LIBEVDEV_READ_SYNC, &ev);
> > +       ck_assert_int_eq(rc, 1);
> > +       ck_assert_int_eq(ev.type, EV_SYN);
> > +       ck_assert_int_eq(ev.code, SYN_REPORT);
> > +       rc = libevdev_next_event(dev, LIBEVDEV_READ_SYNC, &ev);
> > +       ck_assert_int_eq(rc, -EAGAIN);
> > +
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_SW, SW_LID), 1);
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_SW, SW_MICROPHONE_INSERT), 1);
> > +
> > +       uinput_device_free(uidev);
> > +       libevdev_free(dev);
> > +}
> > +END_TEST
> > +
> >  START_TEST(test_skipped_sync)
> >  {
> >         struct uinput_device* uidev;
> > @@ -876,6 +922,8 @@ START_TEST(test_event_value_setters)
> >                                     EV_KEY, BTN_RIGHT,
> >                                     EV_LED, LED_NUML,
> >                                     EV_LED, LED_CAPSL,
> > +                                   EV_SW, SW_LID,
> > +                                   EV_SW, SW_TABLET_MODE,
> >                                     -1);
> >         ck_assert_msg(rc == 0, "Failed to create device: %s", strerror(-rc));
> >
> > @@ -903,6 +951,12 @@ START_TEST(test_event_value_setters)
> >         ck_assert_int_eq(libevdev_get_event_value(dev, EV_LED, LED_NUML), 1);
> >         ck_assert_int_eq(libevdev_get_event_value(dev, EV_LED, LED_CAPSL), 1);
> >
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_SW, SW_LID, 1), 0);
> > +       ck_assert_int_eq(libevdev_set_event_value(dev, EV_SW, SW_TABLET_MODE, 1), 0);
> > +
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_SW, SW_LID), 1);
> > +       ck_assert_int_eq(libevdev_get_event_value(dev, EV_SW, SW_TABLET_MODE), 1);
> > +
> >         uinput_device_free(uidev);
> >         libevdev_free(dev);
> >
> > @@ -1104,6 +1158,7 @@ libevdev_events(void)
> >         tcase_add_test(tc, test_syn_delta_abs);
> >         tcase_add_test(tc, test_syn_delta_mt);
> >         tcase_add_test(tc, test_syn_delta_led);
> > +       tcase_add_test(tc, test_syn_delta_sw);
> >         suite_add_tcase(s, tc);
> >
> >         tc = tcase_create("skipped syncs");
> > --
> > 1.8.2.1
> >
> > _______________________________________________
> > Input-tools mailing list
> > Input-tools at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/input-tools
> 
> Besides the small nitpick above:
> 
> Reviewed-by: Benjamin Tissoires <benjamin.tissoires at gmail.com>
> 
> Cheers,
> Benjamin


More information about the Input-tools mailing list