input: test for LED feature and use it
authorRan Benita <ran234@gmail.com>
Fri, 20 Jan 2012 17:07:00 +0000 (19:07 +0200)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Tue, 20 Mar 2012 18:00:54 +0000 (19:00 +0100)
Add probing for LEDs in the input devices, and move the ioctl for the
LEDs state from the keyboard backends to the input subsystem itself
(thus not exposing the device's file descriptor unnecessarily).

Signed-off-by: Ran Benita <ran234@gmail.com>
Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
src/input.c
src/kbd.h
src/kbd_dumb.c
src/kbd_xkb.c

index beba2b2..293dfe4 100644 (file)
@@ -64,6 +64,7 @@ enum input_state {
 /* See probe_device_features(). */
 enum device_feature {
        FEATURE_HAS_KEYS = 0x01,
+       FEATURE_HAS_LEDS = 0x02,
 };
 
 struct kmscon_input_device {
@@ -153,6 +154,7 @@ static void device_data_arrived(struct kmscon_fd *fd, int mask, void *data)
 int kmscon_input_device_wake_up(struct kmscon_input_device *device)
 {
        int ret;
+       unsigned long ledbits[NLONGS(LED_CNT)] = { 0 };
 
        if (!device || !device->input || !device->input->eloop)
                return -EINVAL;
@@ -168,8 +170,17 @@ int kmscon_input_device_wake_up(struct kmscon_input_device *device)
        }
 
        if (device->features & FEATURE_HAS_KEYS) {
+               if (device->features & FEATURE_HAS_LEDS) {
+                       errno = 0;
+                       ioctl(device->rfd, EVIOCGLED(sizeof(ledbits)),
+                                                               &ledbits);
+                       if (errno)
+                               log_warn("input: cannot discover state of LEDs (%s): %m\n",
+                                                        device->devnode);
+               }
+
                /* rediscover the keyboard state if sth changed during sleep */
-               kmscon_kbd_reset(device->kbd, device->rfd);
+               kmscon_kbd_reset(device->kbd, ledbits);
 
                ret = kmscon_eloop_new_fd(device->input->eloop, &device->fd,
                                                device->rfd, KMSCON_READABLE,
@@ -401,6 +412,9 @@ static unsigned int probe_device_features(const char *node)
                }
        }
 
+       if (kmscon_evdev_bit_is_set(evbits, EV_LED))
+               features |= FEATURE_HAS_LEDS;
+
        close(fd);
        return features;
 
index f9915ac..b1d8476 100644 (file)
--- a/src/kbd.h
+++ b/src/kbd.h
@@ -67,7 +67,7 @@ void kmscon_kbd_unref(struct kmscon_kbd *state);
  * This resets the keyboard state in case it got out of sync. It's mainly used
  * to sync our notion of the keyboard state with what the keyboard LEDs show.
  */
-void kmscon_kbd_reset(struct kmscon_kbd *kbd, int evdev_fd);
+void kmscon_kbd_reset(struct kmscon_kbd *kbd, const unsigned long *ledbits);
 
 /*
  * This is the entry point to the keyboard processing.
index 4867ac6..df2feff 100644 (file)
@@ -330,38 +330,17 @@ void kmscon_kbd_unref(struct kmscon_kbd *kbd)
        free(kbd);
 }
 
-void kmscon_kbd_reset(struct kmscon_kbd *kbd, int evdev_fd)
+void kmscon_kbd_reset(struct kmscon_kbd *kbd, const unsigned long *ledbits)
 {
-       int i;
-       /* One long should be enough (LED_MAX is currently 16). */
-       unsigned long leds, bit;
-
        if (!kbd)
                return;
 
        kbd->mods = 0;
 
-       errno = 0;
-       ioctl(evdev_fd, EVIOCGLED(sizeof(leds)), &leds);
-       if (errno) {
-               log_warn("kbd-dumb: cannot discover modifiers state: %m\n");
-               return;
-       }
-
-       /* The LED_* constants specifiy the bit location. */
-       for (i=0, bit=0x01; i < LED_MAX; i++, bit<<=1) {
-               if (!(leds & bit))
-                       continue;
-
-               switch (i) {
-               case LED_NUML:
-                       kbd->mods |= KMSCON_MOD2_MASK;
-                       break;
-               case LED_CAPSL:
-                       kbd->mods |= KMSCON_LOCK_MASK;
-                       break;
-               }
-       }
+       if (kmscon_evdev_bit_is_set(ledbits, LED_NUML))
+               kbd->mods |= KMSCON_MOD2_MASK;
+       if (kmscon_evdev_bit_is_set(ledbits, LED_CAPSL))
+               kbd->mods |= KMSCON_LOCK_MASK;
 }
 
 int kmscon_kbd_process_key(struct kmscon_kbd *kbd,
index 55970e1..4827482 100644 (file)
@@ -62,7 +62,6 @@
 #include <inttypes.h>
 #include <stdbool.h>
 #include <string.h>
-#include <sys/ioctl.h>
 #include <linux/input.h>
 #include <xkbcommon/xkbcommon.h>
 
@@ -571,14 +570,21 @@ static struct xkb_indicator_map *find_indicator_map(struct xkb_desc *desc,
  * We don't reset the locked group, this should survive a VT switch, etc. The
  * locked modifiers are reset according to the keyboard LEDs.
  */
-void kmscon_kbd_reset(struct kmscon_kbd *kbd, int evdev_fd)
+void kmscon_kbd_reset(struct kmscon_kbd *kbd, const unsigned long *ledbits)
 {
        int i;
        struct xkb_desc *desc;
        struct xkb_state *state;
-       /* One long should be enough (LED_MAX is currently 16). */
-       unsigned long leds, bit;
        struct xkb_indicator_map *im;
+       static const struct {
+               int led;
+               const char *indicator_name;
+       } led_names[] = {
+               { LED_NUML, "Num Lock" },
+               { LED_CAPSL, "Caps Lock" },
+               { LED_SCROLLL, "Scroll Lock" },
+               { LED_COMPOSE, "Compose" },
+       };
 
        if (!kbd)
                return;
@@ -595,33 +601,11 @@ void kmscon_kbd_reset(struct kmscon_kbd *kbd, int evdev_fd)
        state->latched_mods = 0;
        state->locked_mods = 0;
 
-       errno = 0;
-       ioctl(evdev_fd, EVIOCGLED(sizeof(leds)), &leds);
-       if (errno) {
-               log_warn("kbd-xkb: cannot discover modifiers state: %m\n");
-               return;
-       }
-
-       /* The LED_* constants specifiy the bit location. */
-       for (i=0, bit=0x01; i < LED_MAX; i++, bit<<=1) {
-               if (!(leds & bit))
+       for (i = 0; i < sizeof(led_names) / sizeof(*led_names); i++) {
+               if (!kmscon_evdev_bit_is_set(ledbits, led_names[i].led))
                        continue;
 
-               im = NULL;
-               switch (i) {
-               case LED_NUML:
-                       im = find_indicator_map(desc, "Num Lock");
-                       break;
-               case LED_CAPSL:
-                       im = find_indicator_map(desc, "Caps Lock");
-                       break;
-               case LED_SCROLLL:
-                       im = find_indicator_map(desc, "Scroll Lock");
-                       break;
-               case LED_COMPOSE:
-                       im = find_indicator_map(desc, "Compose");
-                       break;
-               }
+               im = find_indicator_map(desc, led_names[i].indicator_name);
 
                /* Only locked modifiers really matter here. */
                if (im && im->which_mods == XkbIM_UseLocked)