input: test for LED feature and use it

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>
This commit is contained in:
Ran Benita 2012-01-20 19:07:00 +02:00 committed by David Herrmann
parent 6b7265447e
commit 5811fee0da
4 changed files with 34 additions and 57 deletions

View 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;

View File

@ -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.

View 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,

View 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)