evdev: Add an internal device suspend / resume notification system
authorHans de Goede <hdegoede@redhat.com>
Tue, 16 Sep 2014 14:22:37 +0000 (16:22 +0200)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 18 Sep 2014 03:29:42 +0000 (13:29 +1000)
We have the ability for a device to form a link to another device through the
device_added / device_removed callbacks. A device having such a link to
another device may also want to know when that other device is disabled /
enabled (suspended / resumed). So add a notification mechanism for this too.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
src/evdev-mt-touchpad.c
src/evdev.c
src/evdev.h

index d1e4acd..4161d9b 100644 (file)
@@ -696,6 +696,8 @@ static struct evdev_dispatch_interface tp_interface = {
        tp_destroy,
        tp_device_added,
        tp_device_removed,
+       NULL, /* device_suspended */
+       NULL, /* device_resumed */
        tp_tag_device,
 };
 
index 85e4d71..cb43c27 100644 (file)
@@ -692,6 +692,8 @@ struct evdev_dispatch_interface fallback_interface = {
        fallback_destroy,
        NULL, /* device_added */
        NULL, /* device_removed */
+       NULL, /* device_suspended */
+       NULL, /* device_resumed */
        fallback_tag_device,
 };
 
@@ -1078,11 +1080,17 @@ evdev_notify_added_device(struct evdev_device *device)
                if (dev == &device->base)
                        continue;
 
+               /* Notify existing device d about addition of device device */
                if (d->dispatch->interface->device_added)
                        d->dispatch->interface->device_added(d, device);
 
+               /* Notify new device device about existing device d */
                if (device->dispatch->interface->device_added)
                        device->dispatch->interface->device_added(device, d);
+
+               /* Notify new device device if existing device d is suspended */
+               if (d->suspended && device->dispatch->interface->device_suspended)
+                       device->dispatch->interface->device_suspended(device, d);
        }
 
        notify_added_device(&device->base);
@@ -1413,9 +1421,51 @@ release_pressed_keys(struct evdev_device *device)
        }
 }
 
+void
+evdev_notify_suspended_device(struct evdev_device *device)
+{
+       struct libinput_device *it;
+
+       if (device->suspended)
+               return;
+
+       list_for_each(it, &device->base.seat->devices_list, link) {
+               struct evdev_device *d = (struct evdev_device*)it;
+               if (it == &device->base)
+                       continue;
+
+               if (d->dispatch->interface->device_suspended)
+                       d->dispatch->interface->device_suspended(d, device);
+       }
+
+       device->suspended = 1;
+}
+
+void
+evdev_notify_resumed_device(struct evdev_device *device)
+{
+       struct libinput_device *it;
+
+       if (!device->suspended)
+               return;
+
+       list_for_each(it, &device->base.seat->devices_list, link) {
+               struct evdev_device *d = (struct evdev_device*)it;
+               if (it == &device->base)
+                       continue;
+
+               if (d->dispatch->interface->device_resumed)
+                       d->dispatch->interface->device_resumed(d, device);
+       }
+
+       device->suspended = 0;
+}
+
 int
 evdev_device_suspend(struct evdev_device *device)
 {
+       evdev_notify_suspended_device(device);
+
        if (device->source) {
                libinput_remove_source(device->base.seat->libinput,
                                       device->source);
@@ -1506,6 +1556,8 @@ evdev_device_resume(struct evdev_device *device)
 
        memset(device->hw_key_mask, 0, sizeof(device->hw_key_mask));
 
+       evdev_notify_resumed_device(device);
+
        return 0;
 }
 
index e1506d2..4047a6d 100644 (file)
@@ -110,6 +110,7 @@ struct evdev_device {
        enum evdev_device_tags tags;
 
        int is_mt;
+       int suspended;
 
        struct {
                struct motion_filter *filter;
@@ -145,6 +146,14 @@ struct evdev_dispatch_interface {
        void (*device_removed)(struct evdev_device *device,
                               struct evdev_device *removed_device);
 
+       /* A device was suspended */
+       void (*device_suspended)(struct evdev_device *device,
+                                struct evdev_device *suspended_device);
+
+       /* A device was resumed */
+       void (*device_resumed)(struct evdev_device *device,
+                              struct evdev_device *resumed_device);
+
        /* Tag device with one of EVDEV_TAG */
        void (*tag_device)(struct evdev_device *device,
                           struct udev_device *udev_device);
@@ -228,6 +237,12 @@ int
 evdev_device_resume(struct evdev_device *device);
 
 void
+evdev_notify_suspended_device(struct evdev_device *device);
+
+void
+evdev_notify_resumed_device(struct evdev_device *device);
+
+void
 evdev_keyboard_notify_key(struct evdev_device *device,
                          uint32_t time,
                          int key,