Refactor input backend-system

This is a rewrite of the input system. The backends itself are not
modified. However, it is now possible to have multiple backends and change
them on runtime.

Signed-off-by: David Herrmann <dh.herrmann@googlemail.com>
This commit is contained in:
David Herrmann 2012-07-21 19:06:50 +02:00
parent a0217124e5
commit 741b8d33df
7 changed files with 351 additions and 153 deletions

View File

@ -152,6 +152,9 @@ libuterm_la_SOURCES = \
src/uterm_video.c \ src/uterm_video.c \
src/uterm_monitor.c \ src/uterm_monitor.c \
src/uterm_input.c \ src/uterm_input.c \
src/uterm_input_plain.c \
external/imKStoUCS.h \
external/imKStoUCS.c \
src/uterm_vt.c \ src/uterm_vt.c \
src/vt.h \ src/vt.h \
src/vt.c src/vt.c
@ -195,12 +198,7 @@ endif
if UTERM_HAVE_XKBCOMMON if UTERM_HAVE_XKBCOMMON
libuterm_la_SOURCES += \ libuterm_la_SOURCES += \
src/uterm_input_xkb.c src/uterm_input_uxkb.c
else
libuterm_la_SOURCES += \
src/uterm_input_dumb.c \
external/imKStoUCS.h \
external/imKStoUCS.c
endif endif
include_HEADERS += \ include_HEADERS += \

View File

@ -336,7 +336,8 @@ if test ! x$enable_xkbcommon = xno ; then
fi fi
if test x$xkbcommon_enabled = xyes ; then if test x$xkbcommon_enabled = xyes ; then
test # dummy AC_DEFINE([UTERM_HAVE_XKBCOMMON], [1],
[Use xkbcommon as input keyboard handling backend])
else else
XKBCOMMON_CFLAGS="" XKBCOMMON_CFLAGS=""
XKBCOMMON_LIBS="" XKBCOMMON_LIBS=""

View File

@ -182,8 +182,10 @@ static void seat_add_video(struct kmscon_seat *seat,
ret = kmscon_ui_new(&seat->ui, seat->app->eloop, seat->video, ret = kmscon_ui_new(&seat->ui, seat->app->eloop, seat->video,
seat->input); seat->input);
if (ret) if (ret) {
log_error("cannot create UI object");
goto err_video; goto err_video;
}
seat->vdev = dev; seat->vdev = dev;
log_debug("new graphics device on seat %s", seat->sname); log_debug("new graphics device on seat %s", seat->sname);

View File

@ -88,7 +88,7 @@ static void notify_key(struct uterm_input_dev *dev,
if (type != EV_KEY) if (type != EV_KEY)
return; return;
ret = kbd_dev_process_key(dev->kbd, value, code, &ev); ret = kbd_dev_process(dev->kbd, value, code, &ev);
if (ret) if (ret)
return; return;
@ -200,7 +200,7 @@ static void input_new_dev(struct uterm_input *input,
if (!dev->node) if (!dev->node)
goto err_free; goto err_free;
ret = kbd_dev_new(&dev->kbd, input->desc); ret = kbd_desc_alloc(input->desc, &dev->kbd);
if (ret) if (ret)
goto err_node; goto err_node;
@ -254,11 +254,22 @@ int uterm_input_new(struct uterm_input **out,
goto err_free; goto err_free;
ret = kbd_desc_new(&input->desc, ret = kbd_desc_new(&input->desc,
conf_global.xkb_layout, conf_global.xkb_layout,
conf_global.xkb_variant, conf_global.xkb_variant,
conf_global.xkb_options); conf_global.xkb_options,
if (ret) KBD_UXKB);
if (ret == -EOPNOTSUPP) {
log_info("XKB keyboard backend not available, trying plain backend");
ret = kbd_desc_new(&input->desc,
conf_global.xkb_layout,
conf_global.xkb_variant,
conf_global.xkb_options,
KBD_PLAIN);
if (ret)
goto err_hook;
} else if (ret) {
goto err_hook; goto err_hook;
}
log_debug("new object %p", input); log_debug("new object %p", input);
ev_eloop_ref(input->eloop); ev_eloop_ref(input->eloop);

View File

@ -47,12 +47,7 @@
#include "uterm.h" #include "uterm.h"
#include "uterm_internal.h" #include "uterm_internal.h"
#define LOG_SUBSYSTEM "input_dumb" #define LOG_SUBSYSTEM "input_plain"
struct kbd_dev {
unsigned long ref;
unsigned int mods;
};
/* /*
* These tables do not contain all possible keys from linux/input.h. * These tables do not contain all possible keys from linux/input.h.
@ -284,21 +279,7 @@ static const struct {
[KEY_RIGHTMETA] = { UTERM_MOD4_MASK, MOD_NORMAL }, [KEY_RIGHTMETA] = { UTERM_MOD4_MASK, MOD_NORMAL },
}; };
int kbd_dev_new(struct kbd_dev **out, struct kbd_desc *desc) static void plain_dev_ref(struct kbd_dev *kbd)
{
struct kbd_dev *kbd;
kbd = malloc(sizeof(*kbd));
if (!kbd)
return -ENOMEM;
memset(kbd, 0, sizeof(*kbd));
kbd->ref = 1;
*out = kbd;
return 0;
}
void kbd_dev_ref(struct kbd_dev *kbd)
{ {
if (!kbd || !kbd->ref) if (!kbd || !kbd->ref)
return; return;
@ -306,7 +287,7 @@ void kbd_dev_ref(struct kbd_dev *kbd)
++kbd->ref; ++kbd->ref;
} }
void kbd_dev_unref(struct kbd_dev *kbd) static void plain_dev_unref(struct kbd_dev *kbd)
{ {
if (!kbd || !kbd->ref || --kbd->ref) if (!kbd || !kbd->ref || --kbd->ref)
return; return;
@ -314,23 +295,23 @@ void kbd_dev_unref(struct kbd_dev *kbd)
free(kbd); free(kbd);
} }
void kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits) static void plain_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
{ {
if (!kbd) if (!kbd)
return; return;
kbd->mods = 0; kbd->plain.mods = 0;
if (input_bit_is_set(ledbits, LED_NUML)) if (input_bit_is_set(ledbits, LED_NUML))
kbd->mods |= UTERM_MOD2_MASK; kbd->plain.mods |= UTERM_MOD2_MASK;
if (input_bit_is_set(ledbits, LED_CAPSL)) if (input_bit_is_set(ledbits, LED_CAPSL))
kbd->mods |= UTERM_LOCK_MASK; kbd->plain.mods |= UTERM_LOCK_MASK;
} }
int kbd_dev_process_key(struct kbd_dev *kbd, static int plain_dev_process(struct kbd_dev *kbd,
uint16_t key_state, uint16_t key_state,
uint16_t code, uint16_t code,
struct uterm_input_event *out) struct uterm_input_event *out)
{ {
uint32_t keysym; uint32_t keysym;
unsigned int mod; unsigned int mod;
@ -353,12 +334,12 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
*/ */
if (key_state == 1) { if (key_state == 1) {
if (mod_type == MOD_NORMAL) if (mod_type == MOD_NORMAL)
kbd->mods |= mod; kbd->plain.mods |= mod;
else if (mod_type == MOD_LOCK) else if (mod_type == MOD_LOCK)
kbd->mods ^= mod; kbd->plain.mods ^= mod;
} else if (key_state == 0) { } else if (key_state == 0) {
if (mod_type == MOD_NORMAL) if (mod_type == MOD_NORMAL)
kbd->mods &= ~mod; kbd->plain.mods &= ~mod;
} }
/* Don't deliver events purely for modifiers. */ /* Don't deliver events purely for modifiers. */
@ -370,11 +351,11 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
keysym = 0; keysym = 0;
if (!keysym && kbd->mods & UTERM_MOD2_MASK) if (!keysym && kbd->plain.mods & UTERM_MOD2_MASK)
keysym = keytab_numlock[code]; keysym = keytab_numlock[code];
if (!keysym && kbd->mods & UTERM_SHIFT_MASK) if (!keysym && kbd->plain.mods & UTERM_SHIFT_MASK)
keysym = keytab_shift[code]; keysym = keytab_shift[code];
if (!keysym && kbd->mods & UTERM_LOCK_MASK) if (!keysym && kbd->plain.mods & UTERM_LOCK_MASK)
keysym = keytab_capslock[code]; keysym = keytab_capslock[code];
if (!keysym) if (!keysym)
keysym = keytab_normal[code]; keysym = keytab_normal[code];
@ -385,34 +366,81 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
out->keycode = code; out->keycode = code;
out->keysym = keysym; out->keysym = keysym;
out->unicode = KeysymToUcs4(keysym) ?: UTERM_INPUT_INVALID; out->unicode = KeysymToUcs4(keysym) ?: UTERM_INPUT_INVALID;
out->mods = kbd->mods; out->mods = kbd->plain.mods;
return 0; return 0;
} }
int kbd_desc_new(struct kbd_desc **out, static int plain_desc_init(struct kbd_desc **out,
const char *layout, const char *layout,
const char *variant, const char *variant,
const char *options) const char *options)
{ {
struct kbd_desc *desc;
if (!out) if (!out)
return -EINVAL; return -EINVAL;
desc = malloc(sizeof(*desc));
if (!desc)
return -ENOMEM;
memset(desc, 0, sizeof(*desc));
desc->ops = &plain_desc_ops;
log_debug("new keyboard description (%s, %s, %s)", log_debug("new keyboard description (%s, %s, %s)",
layout, variant, options); layout, variant, options);
*out = NULL; *out = desc;
return 0; return 0;
} }
void kbd_desc_ref(struct kbd_desc *desc) static void plain_desc_ref(struct kbd_desc *desc)
{ {
if (!desc || !desc->ref)
return;
++desc->ref;
} }
void kbd_desc_unref(struct kbd_desc *desc) static void plain_desc_unref(struct kbd_desc *desc)
{ {
if (!desc || !desc->ref || --desc->ref)
return;
log_debug("destroying keyboard description");
free(desc);
} }
void kbd_keysym_to_string(uint32_t keysym, char *str, size_t size) static int plain_desc_alloc(struct kbd_desc *desc, struct kbd_dev **out)
{
struct kbd_dev *kbd;
kbd = malloc(sizeof(*kbd));
if (!kbd)
return -ENOMEM;
memset(kbd, 0, sizeof(*kbd));
kbd->ref = 1;
kbd->ops = &plain_dev_ops;
*out = kbd;
return 0;
}
static void plain_keysym_to_string(uint32_t keysym, char *str, size_t size)
{ {
snprintf(str, size, "%#x", keysym); snprintf(str, size, "%#x", keysym);
} }
const struct kbd_desc_ops plain_desc_ops = {
.init = plain_desc_init,
.ref = plain_desc_ref,
.unref = plain_desc_unref,
.alloc = plain_desc_alloc,
.keysym_to_string = plain_keysym_to_string,
};
const struct kbd_dev_ops plain_dev_ops = {
.ref = plain_dev_ref,
.unref = plain_dev_unref,
.reset = plain_dev_reset,
.process = plain_dev_process,
};

View File

@ -35,44 +35,9 @@
#include "uterm.h" #include "uterm.h"
#include "uterm_internal.h" #include "uterm_internal.h"
#define LOG_SUBSYSTEM "input_xkb" #define LOG_SUBSYSTEM "input_uxkb"
struct kbd_desc { static void uxkb_dev_ref(struct kbd_dev *kbd)
unsigned long ref;
struct xkb_context *ctx;
struct xkb_keymap *keymap;
};
struct kbd_dev {
unsigned long ref;
struct kbd_desc *desc;
struct xkb_state *state;
};
int kbd_dev_new(struct kbd_dev **out, struct kbd_desc *desc)
{
struct kbd_dev *kbd;
kbd = malloc(sizeof(*kbd));
if (!kbd)
return -ENOMEM;
memset(kbd, 0, sizeof(*kbd));
kbd->ref = 1;
kbd->desc = desc;
kbd->state = xkb_state_new(desc->keymap);
if (!kbd->state) {
free(kbd);
return -ENOMEM;
}
kbd_desc_ref(desc);
*out = kbd;
return 0;
}
void kbd_dev_ref(struct kbd_dev *kbd)
{ {
if (!kbd || !kbd->ref) if (!kbd || !kbd->ref)
return; return;
@ -80,12 +45,12 @@ void kbd_dev_ref(struct kbd_dev *kbd)
++kbd->ref; ++kbd->ref;
} }
void kbd_dev_unref(struct kbd_dev *kbd) static void uxkb_dev_unref(struct kbd_dev *kbd)
{ {
if (!kbd || !kbd->ref || --kbd->ref) if (!kbd || !kbd->ref || --kbd->ref)
return; return;
xkb_state_unref(kbd->state); xkb_state_unref(kbd->uxkb.state);
kbd_desc_unref(kbd->desc); kbd_desc_unref(kbd->desc);
free(kbd); free(kbd);
} }
@ -120,10 +85,10 @@ static unsigned int get_effective_modmask(struct xkb_state *state)
return mods; return mods;
} }
int kbd_dev_process_key(struct kbd_dev *kbd, static int uxkb_dev_process(struct kbd_dev *kbd,
uint16_t key_state, uint16_t key_state,
uint16_t code, uint16_t code,
struct uterm_input_event *out) struct uterm_input_event *out)
{ {
struct xkb_state *state; struct xkb_state *state;
struct xkb_keymap *keymap; struct xkb_keymap *keymap;
@ -134,7 +99,7 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
if (!kbd) if (!kbd)
return -EINVAL; return -EINVAL;
state = kbd->state; state = kbd->uxkb.state;
keymap = xkb_state_get_map(state); keymap = xkb_state_get_map(state);
keycode = code + EVDEV_KEYCODE_OFFSET; keycode = code + EVDEV_KEYCODE_OFFSET;
@ -161,8 +126,8 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
*/ */
out->keycode = code; out->keycode = code;
out->keysym = keysyms[0]; out->keysym = keysyms[0];
out->mods = get_effective_modmask(state);; out->mods = get_effective_modmask(state);
out->unicode = xkb_keysym_to_utf32(out->keysym) ?: UTERM_INPUT_INVALID; out->unicode = xkb_keysym_to_utf32(out->keysym) ? : UTERM_INPUT_INVALID;
return 0; return 0;
} }
@ -172,7 +137,7 @@ int kbd_dev_process_key(struct kbd_dev *kbd,
* We don't reset the locked group, this should survive a VT switch, etc. The * We don't reset the locked group, this should survive a VT switch, etc. The
* locked modifiers are reset according to the keyboard LEDs. * locked modifiers are reset according to the keyboard LEDs.
*/ */
void kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits) static void uxkb_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
{ {
unsigned int i; unsigned int i;
struct xkb_state *state; struct xkb_state *state;
@ -188,7 +153,7 @@ void kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
if (!kbd) if (!kbd)
return; return;
state = kbd->state; state = kbd->uxkb.state;
for (i = 0; i < sizeof(led_names) / sizeof(*led_names); i++) { for (i = 0; i < sizeof(led_names) / sizeof(*led_names); i++) {
if (!input_bit_is_set(ledbits, led_names[i].led)) if (!input_bit_is_set(ledbits, led_names[i].led))
@ -205,10 +170,10 @@ void kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits)
(void)state; (void)state;
} }
int kbd_desc_new(struct kbd_desc **out, static int uxkb_desc_init(struct kbd_desc **out,
const char *layout, const char *layout,
const char *variant, const char *variant,
const char *options) const char *options)
{ {
int ret; int ret;
struct kbd_desc *desc; struct kbd_desc *desc;
@ -229,15 +194,16 @@ int kbd_desc_new(struct kbd_desc **out,
memset(desc, 0, sizeof(*desc)); memset(desc, 0, sizeof(*desc));
desc->ref = 1; desc->ref = 1;
desc->ops = &uxkb_desc_ops;
desc->ctx = xkb_context_new(0); desc->uxkb.ctx = xkb_context_new(0);
if (!desc->ctx) { if (!desc->uxkb.ctx) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_desc; goto err_desc;
} }
desc->keymap = xkb_map_new_from_names(desc->ctx, &rmlvo, 0); desc->uxkb.keymap = xkb_map_new_from_names(desc->uxkb.ctx, &rmlvo, 0);
if (!desc->keymap) { if (!desc->uxkb.keymap) {
log_warn("failed to create keymap (%s, %s, %s), " log_warn("failed to create keymap (%s, %s, %s), "
"reverting to default US keymap", "reverting to default US keymap",
layout, variant, options); layout, variant, options);
@ -246,8 +212,9 @@ int kbd_desc_new(struct kbd_desc **out,
rmlvo.variant = ""; rmlvo.variant = "";
rmlvo.options = ""; rmlvo.options = "";
desc->keymap = xkb_map_new_from_names(desc->ctx, &rmlvo, 0); desc->uxkb.keymap = xkb_map_new_from_names(desc->uxkb.ctx,
if (!desc->keymap) { &rmlvo, 0);
if (!desc->uxkb.keymap) {
log_warn("failed to create keymap"); log_warn("failed to create keymap");
ret = -EFAULT; ret = -EFAULT;
goto err_ctx; goto err_ctx;
@ -260,13 +227,13 @@ int kbd_desc_new(struct kbd_desc **out,
return 0; return 0;
err_ctx: err_ctx:
xkb_context_unref(desc->ctx); xkb_context_unref(desc->uxkb.ctx);
err_desc: err_desc:
free(desc); free(desc);
return ret; return ret;
} }
void kbd_desc_ref(struct kbd_desc *desc) static void uxkb_desc_ref(struct kbd_desc *desc)
{ {
if (!desc || !desc->ref) if (!desc || !desc->ref)
return; return;
@ -274,18 +241,57 @@ void kbd_desc_ref(struct kbd_desc *desc)
++desc->ref; ++desc->ref;
} }
void kbd_desc_unref(struct kbd_desc *desc) static void uxkb_desc_unref(struct kbd_desc *desc)
{ {
if (!desc || !desc->ref || --desc->ref) if (!desc || !desc->ref || --desc->ref)
return; return;
log_debug("destroying keyboard description"); log_debug("destroying keyboard description");
xkb_map_unref(desc->keymap); xkb_map_unref(desc->uxkb.keymap);
xkb_context_unref(desc->ctx); xkb_context_unref(desc->uxkb.ctx);
free(desc); free(desc);
} }
void kbd_keysym_to_string(uint32_t keysym, char *str, size_t size) static int uxkb_desc_alloc(struct kbd_desc *desc, struct kbd_dev **out)
{
struct kbd_dev *kbd;
kbd = malloc(sizeof(*kbd));
if (!kbd)
return -ENOMEM;
memset(kbd, 0, sizeof(*kbd));
kbd->ref = 1;
kbd->desc = desc;
kbd->ops = &uxkb_dev_ops;
kbd->uxkb.state = xkb_state_new(desc->uxkb.keymap);
if (!kbd->uxkb.state) {
free(kbd);
return -ENOMEM;
}
kbd_desc_ref(desc);
*out = kbd;
return 0;
}
static void uxkb_keysym_to_string(uint32_t keysym, char *str, size_t size)
{ {
xkb_keysym_get_name(keysym, str, size); xkb_keysym_get_name(keysym, str, size);
} }
const struct kbd_desc_ops uxkb_desc_ops = {
.init = uxkb_desc_init,
.ref = uxkb_desc_ref,
.unref = uxkb_desc_unref,
.alloc = uxkb_desc_alloc,
.keysym_to_string = uxkb_keysym_to_string,
};
const struct kbd_dev_ops uxkb_dev_ops = {
.ref = uxkb_dev_ref,
.unref = uxkb_dev_unref,
.reset = uxkb_dev_reset,
.process = uxkb_dev_process,
};

View File

@ -372,37 +372,189 @@ static inline bool input_bit_is_set(const unsigned long *array, int bit)
struct kbd_desc; struct kbd_desc;
struct kbd_dev; struct kbd_dev;
int kbd_desc_new(struct kbd_desc **out, struct kbd_desc_ops {
const char *layout, int (*init) (struct kbd_desc **out, const char *layout,
const char *variant, const char *variant, const char *options);
const char *options); void (*ref) (struct kbd_desc *desc);
void kbd_desc_ref(struct kbd_desc *desc); void (*unref) (struct kbd_desc *desc);
void kbd_desc_unref(struct kbd_desc *desc); int (*alloc) (struct kbd_desc *desc, struct kbd_dev **out);
void (*keysym_to_string) (uint32_t keysym, char *str, size_t size);
};
int kbd_dev_new(struct kbd_dev **out, struct kbd_desc *desc); struct kbd_dev_ops {
void kbd_dev_ref(struct kbd_dev *state); void (*ref) (struct kbd_dev *dev);
void kbd_dev_unref(struct kbd_dev *state); void (*unref) (struct kbd_dev *dev);
void (*reset) (struct kbd_dev *dev, const unsigned long *ledbits);
/* int (*process) (struct kbd_dev *dev, uint16_t state, uint16_t code,
* 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 kbd_dev_reset(struct kbd_dev *kbd, const unsigned long *ledbits);
/*
* This is the entry point to the keyboard processing.
* We get an evdev scancode and the keyboard state, and should put out a
* proper input event.
* Some evdev input events shouldn't result in us sending an input event
* (e.g. a key release):
* - If the event was filled out, 0 is returned.
* - Otherwise, if there was no error, -ENOKEY is returned.
*/
int kbd_dev_process_key(struct kbd_dev *kbd,
uint16_t key_state,
uint16_t code,
struct uterm_input_event *out); struct uterm_input_event *out);
};
void kbd_dev_keysym_to_string(uint32_t keysym, char *str, size_t size); struct plain_desc {
int unused;
};
struct plain_dev {
unsigned int mods;
};
static const bool plain_available = true;
extern const struct kbd_desc_ops plain_desc_ops;
extern const struct kbd_dev_ops plain_dev_ops;
#ifdef UTERM_HAVE_XKBCOMMON
struct uxkb_desc {
struct xkb_context *ctx;
struct xkb_keymap *keymap;
};
struct uxkb_dev {
struct xkb_state *state;
};
static const bool uxkb_available = true;
extern const struct kbd_desc_ops uxkb_desc_ops;
extern const struct kbd_dev_ops uxkb_dev_ops;
#else /* !UTERM_HAVE_XKBCOMMON */
struct uxkb_desc {
int unused;
};
struct uxkb_dev {
int unused;
};
static const bool xkb_available = false;
static const struct kbd_desc_ops uxkb_desc_ops;
static const struct kbd_dev_ops uxkb_dev_ops;
#endif /* UTERM_HAVE_XKBCOMMON */
struct kbd_desc {
unsigned long ref;
const struct kbd_desc_ops *ops;
union {
struct plain_desc plain;
struct uxkb_desc uxkb;
};
};
struct kbd_dev {
unsigned long ref;
struct kbd_desc *desc;
const struct kbd_dev_ops *ops;
union {
struct plain_dev plain;
struct uxkb_dev uxkb;
};
};
enum kbd_mode {
KBD_PLAIN,
KBD_UXKB,
};
static inline int kbd_desc_new(struct kbd_desc **out, const char *layout,
const char *variant, const char *options,
unsigned int mode)
{
const struct kbd_desc_ops *ops;
switch (mode) {
case KBD_UXKB:
if (!uxkb_available) {
log_error("XKB KBD backend not available");
return -EOPNOTSUPP;
}
ops = &uxkb_desc_ops;
break;
case KBD_PLAIN:
if (!plain_available) {
log_error("plain KBD backend not available");
return -EOPNOTSUPP;
}
ops = &plain_desc_ops;
break;
default:
log_error("unknown KBD backend %u", mode);
return -EINVAL;
}
return ops->init(out, layout, variant, options);
}
static inline void kbd_desc_ref(struct kbd_desc *desc)
{
if (!desc)
return;
return desc->ops->ref(desc);
}
static inline void kbd_desc_unref(struct kbd_desc *desc)
{
if (!desc)
return;
return desc->ops->unref(desc);
}
static inline int kbd_desc_alloc(struct kbd_desc *desc, struct kbd_dev **out)
{
if (!desc)
return -EINVAL;
return desc->ops->alloc(desc, out);
}
static inline void kbd_desc_keysym_to_string(struct kbd_desc *desc,
uint32_t keysym,
char *str, size_t size)
{
if (!desc)
return;
return desc->ops->keysym_to_string(keysym, str, size);
}
static inline void kbd_dev_ref(struct kbd_dev *dev)
{
if (!dev)
return;
return dev->ops->ref(dev);
}
static inline void kbd_dev_unref(struct kbd_dev *dev)
{
if (!dev)
return;
return dev->ops->unref(dev);
}
static inline void kbd_dev_reset(struct kbd_dev *dev,
const unsigned long *ledbits)
{
if (!dev)
return;
return dev->ops->reset(dev, ledbits);
}
static inline int kbd_dev_process(struct kbd_dev *dev,
uint16_t key_state,
uint16_t code,
struct uterm_input_event *out)
{
if (!dev)
return -EINVAL;
return dev->ops->process(dev, key_state, code, out);
}
#endif /* UTERM_INTERNAL_H */ #endif /* UTERM_INTERNAL_H */