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:
parent
6b7265447e
commit
5811fee0da
16
src/input.c
16
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;
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user