/* See probe_device_features(). */
enum device_feature {
FEATURE_HAS_KEYS = 0x01,
+ FEATURE_HAS_LEDS = 0x02,
};
struct kmscon_input_device {
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;
}
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,
}
}
+ if (kmscon_evdev_bit_is_set(evbits, EV_LED))
+ features |= FEATURE_HAS_LEDS;
+
close(fd);
return features;
* 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.
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,
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
-#include <sys/ioctl.h>
#include <linux/input.h>
#include <xkbcommon/xkbcommon.h>
* 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;
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)