Zbigniew Jędrzejewski-Szmek 708deb
From 5d301b8aecc286d6ec7e92b0864d66360ea57205 Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek 708deb
From: David Herrmann <dh.herrmann@gmail.com>
Zbigniew Jędrzejewski-Szmek 708deb
Date: Mon, 22 Sep 2014 17:34:13 +0200
Zbigniew Jędrzejewski-Szmek 708deb
Subject: [PATCH] terminal: make evdev logind-matches per session
Zbigniew Jędrzejewski-Szmek 708deb
Zbigniew Jędrzejewski-Szmek 708deb
Instead of adding matches per device, we now add logind matches per
Zbigniew Jędrzejewski-Szmek 708deb
session. This reduces the number of matches considerably and saves
Zbigniew Jędrzejewski-Szmek 708deb
resources.
Zbigniew Jędrzejewski-Szmek 708deb
---
Zbigniew Jędrzejewski-Szmek 708deb
 src/libsystemd-terminal/idev-evdev.c    | 170 ++++++++------------------------
Zbigniew Jędrzejewski-Szmek 708deb
 src/libsystemd-terminal/idev-internal.h |   4 +
Zbigniew Jędrzejewski-Szmek 708deb
 src/libsystemd-terminal/idev.c          | 114 +++++++++++++++++++++
Zbigniew Jędrzejewski-Szmek 708deb
 3 files changed, 158 insertions(+), 130 deletions(-)
Zbigniew Jędrzejewski-Szmek 708deb
Zbigniew Jędrzejewski-Szmek 708deb
diff --git a/src/libsystemd-terminal/idev-evdev.c b/src/libsystemd-terminal/idev-evdev.c
Zbigniew Jędrzejewski-Szmek 708deb
index 719e18c316..63fa89e47d 100644
Zbigniew Jędrzejewski-Szmek 708deb
--- a/src/libsystemd-terminal/idev-evdev.c
Zbigniew Jędrzejewski-Szmek 708deb
+++ b/src/libsystemd-terminal/idev-evdev.c
Zbigniew Jędrzejewski-Szmek 708deb
@@ -60,9 +60,6 @@ struct unmanaged_evdev {
Zbigniew Jędrzejewski-Szmek 708deb
 struct managed_evdev {
Zbigniew Jędrzejewski-Szmek 708deb
         idev_evdev evdev;
Zbigniew Jędrzejewski-Szmek 708deb
         dev_t devnum;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        sd_bus_slot *slot_pause_device;
Zbigniew Jędrzejewski-Szmek 708deb
-        sd_bus_slot *slot_resume_device;
Zbigniew Jędrzejewski-Szmek 708deb
         sd_bus_slot *slot_take_device;
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
         bool requested : 1;             /* TakeDevice() was sent */
Zbigniew Jędrzejewski-Szmek 708deb
@@ -580,7 +577,7 @@ static int managed_evdev_take_device_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 708deb
         return 0;
Zbigniew Jędrzejewski-Szmek 708deb
 }
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
-static void managed_evdev_resume(idev_element *e) {
Zbigniew Jędrzejewski-Szmek 708deb
+static void managed_evdev_enable(idev_element *e) {
Zbigniew Jędrzejewski-Szmek 708deb
         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
Zbigniew Jędrzejewski-Szmek 708deb
         managed_evdev *em = managed_evdev_from_element(e);
Zbigniew Jędrzejewski-Szmek 708deb
         idev_session *s = e->session;
Zbigniew Jędrzejewski-Szmek 708deb
@@ -628,7 +625,7 @@ error:
Zbigniew Jędrzejewski-Szmek 708deb
                   s->name, e->name, strerror(-r));
Zbigniew Jędrzejewski-Szmek 708deb
 }
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
-static void managed_evdev_pause(idev_element *e) {
Zbigniew Jędrzejewski-Szmek 708deb
+static void managed_evdev_disable(idev_element *e) {
Zbigniew Jędrzejewski-Szmek 708deb
         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
Zbigniew Jędrzejewski-Szmek 708deb
         managed_evdev *em = managed_evdev_from_element(e);
Zbigniew Jędrzejewski-Szmek 708deb
         idev_session *s = e->session;
Zbigniew Jędrzejewski-Szmek 708deb
@@ -686,24 +683,45 @@ static void managed_evdev_pause(idev_element *e) {
Zbigniew Jędrzejewski-Szmek 708deb
                           s->name, e->name, strerror(-r));
Zbigniew Jędrzejewski-Szmek 708deb
 }
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
-static int managed_evdev_pause_device_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 708deb
-                                         sd_bus_message *signal,
Zbigniew Jędrzejewski-Szmek 708deb
-                                         void *userdata,
Zbigniew Jędrzejewski-Szmek 708deb
-                                         sd_bus_error *ret_error) {
Zbigniew Jędrzejewski-Szmek 708deb
-        managed_evdev *em = userdata;
Zbigniew Jędrzejewski-Szmek 708deb
-        idev_element *e = &em->evdev.element;
Zbigniew Jędrzejewski-Szmek 708deb
+static void managed_evdev_resume(idev_element *e, int fd) {
Zbigniew Jędrzejewski-Szmek 708deb
+        managed_evdev *em = managed_evdev_from_element(e);
Zbigniew Jędrzejewski-Szmek 708deb
+        idev_session *s = e->session;
Zbigniew Jędrzejewski-Szmek 708deb
+        int r;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        /*
Zbigniew Jędrzejewski-Szmek 708deb
+         * We get ResumeDevice signals whenever logind resumed a previously
Zbigniew Jędrzejewski-Szmek 708deb
+         * paused device. The arguments contain the major/minor number of the
Zbigniew Jędrzejewski-Szmek 708deb
+         * related device and a new file-descriptor for the freshly opened
Zbigniew Jędrzejewski-Szmek 708deb
+         * device-node. We take the file-descriptor and immediately resume the
Zbigniew Jędrzejewski-Szmek 708deb
+         * device.
Zbigniew Jędrzejewski-Szmek 708deb
+         */
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
Zbigniew Jędrzejewski-Szmek 708deb
+        if (fd < 0) {
Zbigniew Jędrzejewski-Szmek 708deb
+                log_debug("idev-evdev: %s/%s: cannot duplicate evdev fd: %m",
Zbigniew Jędrzejewski-Szmek 708deb
+                          s->name, e->name);
Zbigniew Jędrzejewski-Szmek 708deb
+                return;
Zbigniew Jędrzejewski-Szmek 708deb
+        }
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        r = idev_evdev_resume(&em->evdev, fd);
Zbigniew Jędrzejewski-Szmek 708deb
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
+                log_debug("idev-evdev: %s/%s: cannot resume: %s",
Zbigniew Jędrzejewski-Szmek 708deb
+                          s->name, e->name, strerror(-r));
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        return;
Zbigniew Jędrzejewski-Szmek 708deb
+}
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+static void managed_evdev_pause(idev_element *e, const char *mode) {
Zbigniew Jędrzejewski-Szmek 708deb
+        managed_evdev *em = managed_evdev_from_element(e);
Zbigniew Jędrzejewski-Szmek 708deb
         idev_session *s = e->session;
Zbigniew Jędrzejewski-Szmek 708deb
         idev_context *c = s->context;
Zbigniew Jędrzejewski-Szmek 708deb
-        uint32_t major, minor;
Zbigniew Jędrzejewski-Szmek 708deb
-        const char *mode;
Zbigniew Jędrzejewski-Szmek 708deb
         int r;
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
         /*
Zbigniew Jędrzejewski-Szmek 708deb
          * We get PauseDevice() signals from logind whenever a device we
Zbigniew Jędrzejewski-Szmek 708deb
          * requested was, or is about to be, paused. Arguments are major/minor
Zbigniew Jędrzejewski-Szmek 708deb
          * number of the device and the mode of the operation.
Zbigniew Jędrzejewski-Szmek 708deb
-         * In case the event is not about our device, we ignore it. Otherwise,
Zbigniew Jędrzejewski-Szmek 708deb
-         * we treat it as asynchronous access-revocation (as if we got HUP on
Zbigniew Jędrzejewski-Szmek 708deb
+         * We treat it as asynchronous access-revocation (as if we got HUP on
Zbigniew Jędrzejewski-Szmek 708deb
          * the device fd). Note that we might have already treated the HUP
Zbigniew Jędrzejewski-Szmek 708deb
          * event via EPOLLHUP, whichever comes first.
Zbigniew Jędrzejewski-Szmek 708deb
          *
Zbigniew Jędrzejewski-Szmek 708deb
@@ -728,17 +746,6 @@ static int managed_evdev_pause_device_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 708deb
          * acknowledge the request.
Zbigniew Jędrzejewski-Szmek 708deb
          */
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
-        r = sd_bus_message_read(signal, "uus", &major, &minor, &mode);
Zbigniew Jędrzejewski-Szmek 708deb
-        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 708deb
-                log_debug("idev-evdev: %s/%s: erroneous PauseDevice signal",
Zbigniew Jędrzejewski-Szmek 708deb
-                          s->name, e->name);
Zbigniew Jędrzejewski-Szmek 708deb
-                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
-        }
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        /* not our device? */
Zbigniew Jędrzejewski-Szmek 708deb
-        if (makedev(major, minor) != em->devnum)
Zbigniew Jędrzejewski-Szmek 708deb
-                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
         idev_evdev_pause(&em->evdev, true);
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
         if (streq(mode, "pause")) {
Zbigniew Jędrzejewski-Szmek 708deb
@@ -763,7 +770,7 @@ static int managed_evdev_pause_device_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 708deb
                                                    "org.freedesktop.login1.Session",
Zbigniew Jędrzejewski-Szmek 708deb
                                                    "PauseDeviceComplete");
Zbigniew Jędrzejewski-Szmek 708deb
                 if (r >= 0) {
Zbigniew Jędrzejewski-Szmek 708deb
-                        r = sd_bus_message_append(m, "uu", major, minor);
Zbigniew Jędrzejewski-Szmek 708deb
+                        r = sd_bus_message_append(m, "uu", major(em->devnum), minor(em->devnum));
Zbigniew Jędrzejewski-Szmek 708deb
                         if (r >= 0)
Zbigniew Jędrzejewski-Szmek 708deb
                                 r = sd_bus_send(c->sysbus, m, NULL);
Zbigniew Jędrzejewski-Szmek 708deb
                 }
Zbigniew Jędrzejewski-Szmek 708deb
@@ -772,99 +779,6 @@ static int managed_evdev_pause_device_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 708deb
                         log_debug("idev-evdev: %s/%s: cannot send PauseDeviceComplete: %s",
Zbigniew Jędrzejewski-Szmek 708deb
                                   s->name, e->name, strerror(-r));
Zbigniew Jędrzejewski-Szmek 708deb
         }
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        return 0;
Zbigniew Jędrzejewski-Szmek 708deb
-}
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-static int managed_evdev_resume_device_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 708deb
-                                          sd_bus_message *signal,
Zbigniew Jędrzejewski-Szmek 708deb
-                                          void *userdata,
Zbigniew Jędrzejewski-Szmek 708deb
-                                          sd_bus_error *ret_error) {
Zbigniew Jędrzejewski-Szmek 708deb
-        managed_evdev *em = userdata;
Zbigniew Jędrzejewski-Szmek 708deb
-        idev_element *e = &em->evdev.element;
Zbigniew Jędrzejewski-Szmek 708deb
-        idev_session *s = e->session;
Zbigniew Jędrzejewski-Szmek 708deb
-        uint32_t major, minor;
Zbigniew Jędrzejewski-Szmek 708deb
-        int r, fd;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        /*
Zbigniew Jędrzejewski-Szmek 708deb
-         * We get ResumeDevice signals whenever logind resumed a previously
Zbigniew Jędrzejewski-Szmek 708deb
-         * paused device. The arguments contain the major/minor number of the
Zbigniew Jędrzejewski-Szmek 708deb
-         * related device and a new file-descriptor for the freshly opened
Zbigniew Jędrzejewski-Szmek 708deb
-         * device-node.
Zbigniew Jędrzejewski-Szmek 708deb
-         * If the signal is not about our device, we simply ignore it.
Zbigniew Jędrzejewski-Szmek 708deb
-         * Otherwise, we take the file-descriptor and immediately resume the
Zbigniew Jędrzejewski-Szmek 708deb
-         * device.
Zbigniew Jędrzejewski-Szmek 708deb
-         */
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        r = sd_bus_message_read(signal, "uuh", &major, &minor, &fd;;
Zbigniew Jędrzejewski-Szmek 708deb
-        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 708deb
-                log_debug("idev-evdev: %s/%s: erroneous ResumeDevice signal",
Zbigniew Jędrzejewski-Szmek 708deb
-                          s->name, e->name);
Zbigniew Jędrzejewski-Szmek 708deb
-                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
-        }
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        /* not our device? */
Zbigniew Jędrzejewski-Szmek 708deb
-        if (makedev(major, minor) != em->devnum)
Zbigniew Jędrzejewski-Szmek 708deb
-                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        fd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
Zbigniew Jędrzejewski-Szmek 708deb
-        if (fd < 0) {
Zbigniew Jędrzejewski-Szmek 708deb
-                log_debug("idev-evdev: %s/%s: cannot duplicate evdev fd: %m",
Zbigniew Jędrzejewski-Szmek 708deb
-                          s->name, e->name);
Zbigniew Jędrzejewski-Szmek 708deb
-                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
-        }
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        r = idev_evdev_resume(&em->evdev, fd);
Zbigniew Jędrzejewski-Szmek 708deb
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
-                log_debug("idev-evdev: %s/%s: cannot resume: %s",
Zbigniew Jędrzejewski-Szmek 708deb
-                          s->name, e->name, strerror(-r));
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        return 0;
Zbigniew Jędrzejewski-Szmek 708deb
-}
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-static int managed_evdev_setup_bus(managed_evdev *em) {
Zbigniew Jędrzejewski-Szmek 708deb
-        idev_element *e = &em->evdev.element;
Zbigniew Jędrzejewski-Szmek 708deb
-        idev_session *s = e->session;
Zbigniew Jędrzejewski-Szmek 708deb
-        idev_context *c = s->context;
Zbigniew Jędrzejewski-Szmek 708deb
-        _cleanup_free_ char *match = NULL;
Zbigniew Jędrzejewski-Szmek 708deb
-        int r;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        match = strjoin("type='signal',"
Zbigniew Jędrzejewski-Szmek 708deb
-                        "sender='org.freedesktop.login1',"
Zbigniew Jędrzejewski-Szmek 708deb
-                        "interface='org.freedesktop.login1.Session',"
Zbigniew Jędrzejewski-Szmek 708deb
-                        "member='PauseDevice',"
Zbigniew Jędrzejewski-Szmek 708deb
-                        "path='", s->path, "'",
Zbigniew Jędrzejewski-Szmek 708deb
-                        NULL);
Zbigniew Jędrzejewski-Szmek 708deb
-        if (!match)
Zbigniew Jędrzejewski-Szmek 708deb
-                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        r = sd_bus_add_match(c->sysbus,
Zbigniew Jędrzejewski-Szmek 708deb
-                             &em->slot_pause_device,
Zbigniew Jędrzejewski-Szmek 708deb
-                             match,
Zbigniew Jędrzejewski-Szmek 708deb
-                             managed_evdev_pause_device_fn,
Zbigniew Jędrzejewski-Szmek 708deb
-                             em);
Zbigniew Jędrzejewski-Szmek 708deb
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
-                return r;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        free(match);
Zbigniew Jędrzejewski-Szmek 708deb
-        match = strjoin("type='signal',"
Zbigniew Jędrzejewski-Szmek 708deb
-                        "sender='org.freedesktop.login1',"
Zbigniew Jędrzejewski-Szmek 708deb
-                        "interface='org.freedesktop.login1.Session',"
Zbigniew Jędrzejewski-Szmek 708deb
-                        "member='ResumeDevice',"
Zbigniew Jędrzejewski-Szmek 708deb
-                        "path='", s->path, "'",
Zbigniew Jędrzejewski-Szmek 708deb
-                        NULL);
Zbigniew Jędrzejewski-Szmek 708deb
-        if (!match)
Zbigniew Jędrzejewski-Szmek 708deb
-                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        r = sd_bus_add_match(c->sysbus,
Zbigniew Jędrzejewski-Szmek 708deb
-                             &em->slot_resume_device,
Zbigniew Jędrzejewski-Szmek 708deb
-                             match,
Zbigniew Jędrzejewski-Szmek 708deb
-                             managed_evdev_resume_device_fn,
Zbigniew Jędrzejewski-Szmek 708deb
-                             em);
Zbigniew Jędrzejewski-Szmek 708deb
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
-                return r;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
-        return 0;
Zbigniew Jędrzejewski-Szmek 708deb
 }
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
 static int managed_evdev_new(idev_element **out, idev_session *s, struct udev_device *ud) {
Zbigniew Jędrzejewski-Szmek 708deb
@@ -893,10 +807,6 @@ static int managed_evdev_new(idev_element **out, idev_session *s, struct udev_de
Zbigniew Jędrzejewski-Szmek 708deb
         em->evdev = IDEV_EVDEV_INIT(&managed_evdev_vtable, s);
Zbigniew Jędrzejewski-Szmek 708deb
         em->devnum = devnum;
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
-        r = managed_evdev_setup_bus(em);
Zbigniew Jędrzejewski-Szmek 708deb
-        if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
-                return r;
Zbigniew Jędrzejewski-Szmek 708deb
-
Zbigniew Jędrzejewski-Szmek 708deb
         r = idev_element_add(e, name);
Zbigniew Jędrzejewski-Szmek 708deb
         if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
                 return r;
Zbigniew Jędrzejewski-Szmek 708deb
@@ -910,18 +820,18 @@ static int managed_evdev_new(idev_element **out, idev_session *s, struct udev_de
Zbigniew Jędrzejewski-Szmek 708deb
 static void managed_evdev_free(idev_element *e) {
Zbigniew Jędrzejewski-Szmek 708deb
         managed_evdev *em = managed_evdev_from_element(e);
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
-        em->slot_resume_device = sd_bus_slot_unref(em->slot_resume_device);
Zbigniew Jędrzejewski-Szmek 708deb
-        em->slot_pause_device = sd_bus_slot_unref(em->slot_pause_device);
Zbigniew Jędrzejewski-Szmek 708deb
         idev_evdev_destroy(&em->evdev);
Zbigniew Jędrzejewski-Szmek 708deb
         free(em);
Zbigniew Jędrzejewski-Szmek 708deb
 }
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
 static const idev_element_vtable managed_evdev_vtable = {
Zbigniew Jędrzejewski-Szmek 708deb
         .free                   = managed_evdev_free,
Zbigniew Jędrzejewski-Szmek 708deb
-        .enable                 = managed_evdev_resume,
Zbigniew Jędrzejewski-Szmek 708deb
-        .disable                = managed_evdev_pause,
Zbigniew Jędrzejewski-Szmek 708deb
-        .open                   = managed_evdev_resume,
Zbigniew Jędrzejewski-Szmek 708deb
-        .close                  = managed_evdev_pause,
Zbigniew Jędrzejewski-Szmek 708deb
+        .enable                 = managed_evdev_enable,
Zbigniew Jędrzejewski-Szmek 708deb
+        .disable                = managed_evdev_disable,
Zbigniew Jędrzejewski-Szmek 708deb
+        .open                   = managed_evdev_enable,
Zbigniew Jędrzejewski-Szmek 708deb
+        .close                  = managed_evdev_disable,
Zbigniew Jędrzejewski-Szmek 708deb
+        .resume                 = managed_evdev_resume,
Zbigniew Jędrzejewski-Szmek 708deb
+        .pause                  = managed_evdev_pause,
Zbigniew Jędrzejewski-Szmek 708deb
 };
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
 /*
Zbigniew Jędrzejewski-Szmek 708deb
diff --git a/src/libsystemd-terminal/idev-internal.h b/src/libsystemd-terminal/idev-internal.h
Zbigniew Jędrzejewski-Szmek 708deb
index c416f4fadd..a159aef211 100644
Zbigniew Jędrzejewski-Szmek 708deb
--- a/src/libsystemd-terminal/idev-internal.h
Zbigniew Jędrzejewski-Szmek 708deb
+++ b/src/libsystemd-terminal/idev-internal.h
Zbigniew Jędrzejewski-Szmek 708deb
@@ -116,6 +116,8 @@ struct idev_element_vtable {
Zbigniew Jędrzejewski-Szmek 708deb
         void (*disable) (idev_element *e);
Zbigniew Jędrzejewski-Szmek 708deb
         void (*open) (idev_element *e);
Zbigniew Jędrzejewski-Szmek 708deb
         void (*close) (idev_element *e);
Zbigniew Jędrzejewski-Szmek 708deb
+        void (*resume) (idev_element *e, int fd);
Zbigniew Jędrzejewski-Szmek 708deb
+        void (*pause) (idev_element *e, const char *mode);
Zbigniew Jędrzejewski-Szmek 708deb
         void (*feedback) (idev_element *e, idev_data *data);
Zbigniew Jędrzejewski-Szmek 708deb
 };
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
@@ -155,6 +157,8 @@ struct idev_session {
Zbigniew Jędrzejewski-Szmek 708deb
         idev_context *context;
Zbigniew Jędrzejewski-Szmek 708deb
         char *name;
Zbigniew Jędrzejewski-Szmek 708deb
         char *path;
Zbigniew Jędrzejewski-Szmek 708deb
+        sd_bus_slot *slot_resume_device;
Zbigniew Jędrzejewski-Szmek 708deb
+        sd_bus_slot *slot_pause_device;
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
         Hashmap *element_map;
Zbigniew Jędrzejewski-Szmek 708deb
         Hashmap *device_map;
Zbigniew Jędrzejewski-Szmek 708deb
diff --git a/src/libsystemd-terminal/idev.c b/src/libsystemd-terminal/idev.c
Zbigniew Jędrzejewski-Szmek 708deb
index 8592930662..e979b608b6 100644
Zbigniew Jędrzejewski-Szmek 708deb
--- a/src/libsystemd-terminal/idev.c
Zbigniew Jędrzejewski-Szmek 708deb
+++ b/src/libsystemd-terminal/idev.c
Zbigniew Jędrzejewski-Szmek 708deb
@@ -274,6 +274,22 @@ static void element_disable(idev_element *e) {
Zbigniew Jędrzejewski-Szmek 708deb
         }
Zbigniew Jędrzejewski-Szmek 708deb
 }
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
+static void element_resume(idev_element *e, int fd) {
Zbigniew Jędrzejewski-Szmek 708deb
+        assert(e);
Zbigniew Jędrzejewski-Szmek 708deb
+        assert(fd >= 0);
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        if (e->vtable->resume)
Zbigniew Jędrzejewski-Szmek 708deb
+                e->vtable->resume(e, fd);
Zbigniew Jędrzejewski-Szmek 708deb
+}
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+static void element_pause(idev_element *e, const char *mode) {
Zbigniew Jędrzejewski-Szmek 708deb
+        assert(e);
Zbigniew Jędrzejewski-Szmek 708deb
+        assert(mode);
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        if (e->vtable->pause)
Zbigniew Jędrzejewski-Szmek 708deb
+                e->vtable->pause(e, mode);
Zbigniew Jędrzejewski-Szmek 708deb
+}
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
 /*
Zbigniew Jędrzejewski-Szmek 708deb
  * Sessions
Zbigniew Jędrzejewski-Szmek 708deb
  */
Zbigniew Jędrzejewski-Szmek 708deb
@@ -417,6 +433,98 @@ idev_session *idev_find_session(idev_context *c, const char *name) {
Zbigniew Jędrzejewski-Szmek 708deb
         return hashmap_get(c->session_map, name);
Zbigniew Jędrzejewski-Szmek 708deb
 }
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
+static int session_resume_device_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 708deb
+                                    sd_bus_message *signal,
Zbigniew Jędrzejewski-Szmek 708deb
+                                    void *userdata,
Zbigniew Jędrzejewski-Szmek 708deb
+                                    sd_bus_error *ret_error) {
Zbigniew Jędrzejewski-Szmek 708deb
+        idev_session *s = userdata;
Zbigniew Jędrzejewski-Szmek 708deb
+        idev_element *e;
Zbigniew Jędrzejewski-Szmek 708deb
+        uint32_t major, minor;
Zbigniew Jędrzejewski-Szmek 708deb
+        int r, fd;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        r = sd_bus_message_read(signal, "uuh", &major, &minor, &fd;;
Zbigniew Jędrzejewski-Szmek 708deb
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 708deb
+                log_debug("idev: %s: erroneous ResumeDevice signal", s->name);
Zbigniew Jędrzejewski-Szmek 708deb
+                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
+        }
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        e = idev_find_evdev(s, makedev(major, minor));
Zbigniew Jędrzejewski-Szmek 708deb
+        if (!e)
Zbigniew Jędrzejewski-Szmek 708deb
+                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        element_resume(e, fd);
Zbigniew Jędrzejewski-Szmek 708deb
+        return 0;
Zbigniew Jędrzejewski-Szmek 708deb
+}
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+static int session_pause_device_fn(sd_bus *bus,
Zbigniew Jędrzejewski-Szmek 708deb
+                                   sd_bus_message *signal,
Zbigniew Jędrzejewski-Szmek 708deb
+                                   void *userdata,
Zbigniew Jędrzejewski-Szmek 708deb
+                                   sd_bus_error *ret_error) {
Zbigniew Jędrzejewski-Szmek 708deb
+        idev_session *s = userdata;
Zbigniew Jędrzejewski-Szmek 708deb
+        idev_element *e;
Zbigniew Jędrzejewski-Szmek 708deb
+        uint32_t major, minor;
Zbigniew Jędrzejewski-Szmek 708deb
+        const char *mode;
Zbigniew Jędrzejewski-Szmek 708deb
+        int r;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        r = sd_bus_message_read(signal, "uus", &major, &minor, &mode);
Zbigniew Jędrzejewski-Szmek 708deb
+        if (r < 0) {
Zbigniew Jędrzejewski-Szmek 708deb
+                log_debug("idev: %s: erroneous PauseDevice signal", s->name);
Zbigniew Jędrzejewski-Szmek 708deb
+                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
+        }
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        e = idev_find_evdev(s, makedev(major, minor));
Zbigniew Jędrzejewski-Szmek 708deb
+        if (!e)
Zbigniew Jędrzejewski-Szmek 708deb
+                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        element_pause(e, mode);
Zbigniew Jędrzejewski-Szmek 708deb
+        return 0;
Zbigniew Jędrzejewski-Szmek 708deb
+}
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+static int session_setup_bus(idev_session *s) {
Zbigniew Jędrzejewski-Szmek 708deb
+        _cleanup_free_ char *match = NULL;
Zbigniew Jędrzejewski-Szmek 708deb
+        int r;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        if (!s->managed)
Zbigniew Jędrzejewski-Szmek 708deb
+                return 0;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        match = strjoin("type='signal',"
Zbigniew Jędrzejewski-Szmek 708deb
+                        "sender='org.freedesktop.login1',"
Zbigniew Jędrzejewski-Szmek 708deb
+                        "interface='org.freedesktop.login1.Session',"
Zbigniew Jędrzejewski-Szmek 708deb
+                        "member='ResumeDevice',"
Zbigniew Jędrzejewski-Szmek 708deb
+                        "path='", s->path, "'",
Zbigniew Jędrzejewski-Szmek 708deb
+                        NULL);
Zbigniew Jędrzejewski-Szmek 708deb
+        if (!match)
Zbigniew Jędrzejewski-Szmek 708deb
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        r = sd_bus_add_match(s->context->sysbus,
Zbigniew Jędrzejewski-Szmek 708deb
+                             &s->slot_resume_device,
Zbigniew Jędrzejewski-Szmek 708deb
+                             match,
Zbigniew Jędrzejewski-Szmek 708deb
+                             session_resume_device_fn,
Zbigniew Jędrzejewski-Szmek 708deb
+                             s);
Zbigniew Jędrzejewski-Szmek 708deb
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
+                return r;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        free(match);
Zbigniew Jędrzejewski-Szmek 708deb
+        match = strjoin("type='signal',"
Zbigniew Jędrzejewski-Szmek 708deb
+                        "sender='org.freedesktop.login1',"
Zbigniew Jędrzejewski-Szmek 708deb
+                        "interface='org.freedesktop.login1.Session',"
Zbigniew Jędrzejewski-Szmek 708deb
+                        "member='PauseDevice',"
Zbigniew Jędrzejewski-Szmek 708deb
+                        "path='", s->path, "'",
Zbigniew Jędrzejewski-Szmek 708deb
+                        NULL);
Zbigniew Jędrzejewski-Szmek 708deb
+        if (!match)
Zbigniew Jędrzejewski-Szmek 708deb
+                return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        r = sd_bus_add_match(s->context->sysbus,
Zbigniew Jędrzejewski-Szmek 708deb
+                             &s->slot_pause_device,
Zbigniew Jędrzejewski-Szmek 708deb
+                             match,
Zbigniew Jędrzejewski-Szmek 708deb
+                             session_pause_device_fn,
Zbigniew Jędrzejewski-Szmek 708deb
+                             s);
Zbigniew Jędrzejewski-Szmek 708deb
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
+                return r;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
+        return 0;
Zbigniew Jędrzejewski-Szmek 708deb
+}
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
 int idev_session_new(idev_session **out,
Zbigniew Jędrzejewski-Szmek 708deb
                      idev_context *c,
Zbigniew Jędrzejewski-Szmek 708deb
                      unsigned int flags,
Zbigniew Jędrzejewski-Szmek 708deb
@@ -462,6 +570,10 @@ int idev_session_new(idev_session **out,
Zbigniew Jędrzejewski-Szmek 708deb
         if (!s->device_map)
Zbigniew Jędrzejewski-Szmek 708deb
                 return -ENOMEM;
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
+        r = session_setup_bus(s);
Zbigniew Jędrzejewski-Szmek 708deb
+        if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
+                return r;
Zbigniew Jędrzejewski-Szmek 708deb
+
Zbigniew Jędrzejewski-Szmek 708deb
         r = hashmap_put(c->session_map, s->name, s);
Zbigniew Jędrzejewski-Szmek 708deb
         if (r < 0)
Zbigniew Jędrzejewski-Szmek 708deb
                 return r;
Zbigniew Jędrzejewski-Szmek 708deb
@@ -485,6 +597,8 @@ idev_session *idev_session_free(idev_session *s) {
Zbigniew Jędrzejewski-Szmek 708deb
         if (s->name)
Zbigniew Jędrzejewski-Szmek 708deb
                 hashmap_remove_value(s->context->session_map, s->name, s);
Zbigniew Jędrzejewski-Szmek 708deb
 
Zbigniew Jędrzejewski-Szmek 708deb
+        s->slot_pause_device = sd_bus_slot_unref(s->slot_pause_device);
Zbigniew Jędrzejewski-Szmek 708deb
+        s->slot_resume_device = sd_bus_slot_unref(s->slot_resume_device);
Zbigniew Jędrzejewski-Szmek 708deb
         s->context = idev_context_unref(s->context);
Zbigniew Jędrzejewski-Szmek 708deb
         hashmap_free(s->device_map);
Zbigniew Jędrzejewski-Szmek 708deb
         hashmap_free(s->element_map);