summaryrefslogtreecommitdiff
path: root/src/libsystemd-terminal/idev.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsystemd-terminal/idev.c')
-rw-r--r--src/libsystemd-terminal/idev.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/src/libsystemd-terminal/idev.c b/src/libsystemd-terminal/idev.c
index 2316a66529..0ed518cded 100644
--- a/src/libsystemd-terminal/idev.c
+++ b/src/libsystemd-terminal/idev.c
@@ -27,6 +27,7 @@
#include <systemd/sd-bus.h>
#include <systemd/sd-event.h>
#include <systemd/sd-login.h>
+#include <xkbcommon/xkbcommon.h>
#include "hashmap.h"
#include "idev.h"
#include "idev-internal.h"
@@ -525,10 +526,40 @@ void idev_session_disable(idev_session *s) {
}
}
+static int add_link(idev_element *e, idev_device *d) {
+ idev_link *l;
+
+ assert(e);
+ assert(d);
+
+ l = new0(idev_link, 1);
+ if (!l)
+ return -ENOMEM;
+
+ l->element = e;
+ l->device = d;
+ LIST_PREPEND(links_by_element, e->links, l);
+ LIST_PREPEND(links_by_device, d->links, l);
+ device_attach(d, l);
+
+ return 0;
+}
+
+static int guess_type(struct udev_device *d) {
+ const char *id_key;
+
+ id_key = udev_device_get_property_value(d, "ID_INPUT_KEY");
+ if (streq_ptr(id_key, "1"))
+ return IDEV_DEVICE_KEYBOARD;
+
+ return IDEV_DEVICE_CNT;
+}
+
int idev_session_add_evdev(idev_session *s, struct udev_device *ud) {
idev_element *e;
+ idev_device *d;
dev_t devnum;
- int r;
+ int r, type;
assert_return(s, -EINVAL);
assert_return(ud, -EINVAL);
@@ -549,7 +580,34 @@ int idev_session_add_evdev(idev_session *s, struct udev_device *ud) {
if (r != 0)
return r;
- return 0;
+ type = guess_type(ud);
+ if (type < 0)
+ return type;
+
+ switch (type) {
+ case IDEV_DEVICE_KEYBOARD:
+ d = idev_find_keyboard(s, e->name);
+ if (d) {
+ log_debug("idev: %s: keyboard for new evdev element '%s' already available",
+ s->name, e->name);
+ return 0;
+ }
+
+ r = idev_keyboard_new(&d, s, e->name);
+ if (r < 0)
+ return r;
+
+ r = add_link(e, d);
+ if (r < 0) {
+ idev_device_free(d);
+ return r;
+ }
+
+ return session_add_device(s, d);
+ default:
+ /* unknown elements are silently ignored */
+ return 0;
+ }
}
int idev_session_remove_evdev(idev_session *s, struct udev_device *ud) {