diff --git a/src/input.c b/src/input.c index beba2b2..293dfe4 100644 --- a/src/input.c +++ b/src/input.c @@ -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; diff --git a/src/kbd.h b/src/kbd.h index f9915ac..b1d8476 100644 --- 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. diff --git a/src/kbd_dumb.c b/src/kbd_dumb.c index 4867ac6..df2feff 100644 --- a/src/kbd_dumb.c +++ b/src/kbd_dumb.c @@ -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, diff --git a/src/kbd_xkb.c b/src/kbd_xkb.c index 55970e1..4827482 100644 --- a/src/kbd_xkb.c +++ b/src/kbd_xkb.c @@ -62,7 +62,6 @@ #include #include #include -#include #include #include @@ -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)