commit b96f614

Michael Forney  ·  2014-01-22 22:18:53 +0000 UTC
parent 0df9b8d
seat: Add option input hotplugging support through libudev
4 files changed,  +134, -6
+3, -0
 1@@ -19,6 +19,9 @@ Dependencies
 2 * [wld](http://github.com/michaelforney/wld)
 3 * linux\[>=3.12\] (for EVIOCREVOKE)
 4 
 5+For input hotplugging support, the following is also required:
 6+* libudev
 7+
 8 For XWayland support, the following are also required:
 9 * libxcb
10 * xcb-util-wm
+5, -4
 1@@ -12,9 +12,10 @@ CFLAGS          = -pipe
 2 PKG_CONFIG      ?= pkg-config
 3 WAYLAND_SCANNER ?= wayland-scanner
 4 
 5-ENABLE_DEBUG    = 1
 6+ENABLE_DEBUG        = 1
 7 
 8-ENABLE_STATIC   = 1
 9-ENABLE_SHARED   = 1
10-ENABLE_XWAYLAND = 1
11+ENABLE_STATIC       = 1
12+ENABLE_SHARED       = 1
13+ENABLE_HOTPLUGGING  = 1
14+ENABLE_XWAYLAND     = 1
15 
+5, -0
 1@@ -63,6 +63,11 @@ SWC_SOURCES +=                      \
 2     libswc/bindings.c               \
 3     libswc/screen.c
 4 
 5+ifeq ($(ENABLE_HOTPLUGGING),1)
 6+$(dir)_CFLAGS += -DENABLE_HOTPLUGGING
 7+$(dir)_PACKAGES += libudev
 8+endif
 9+
10 ifeq ($(ENABLE_XWAYLAND),1)
11 $(dir)_CFLAGS += -DENABLE_XWAYLAND
12 $(dir)_PACKAGES +=                  \
+121, -2
  1@@ -35,13 +35,21 @@
  2 #include <stdlib.h>
  3 #include <stdio.h>
  4 #include <string.h>
  5-#include <libudev.h>
  6+#ifdef ENABLE_HOTPLUGGING
  7+# include <libudev.h>
  8+#endif
  9 
 10 static struct
 11 {
 12     char * name;
 13     uint32_t capabilities;
 14 
 15+#ifdef ENABLE_HOTPLUGGING
 16+    struct udev * udev;
 17+    struct udev_monitor * monitor;
 18+    struct wl_event_source * monitor_source;
 19+#endif
 20+
 21     struct swc_keyboard keyboard;
 22     struct swc_pointer pointer;
 23     struct swc_data_device data_device;
 24@@ -249,6 +257,105 @@ static bool add_devices()
 25     return true;
 26 }
 27 
 28+#ifdef ENABLE_HOTPLUGGING
 29+static int handle_monitor_data(int fd, uint32_t mask, void * data)
 30+{
 31+    struct udev_device * udev_device;
 32+    const char * path, * action, * sysname;
 33+    unsigned num;
 34+
 35+    if (!(udev_device = udev_monitor_receive_device(seat.monitor)))
 36+        return 0;
 37+
 38+    if (!(action = udev_device_get_action(udev_device)))
 39+        goto done;
 40+
 41+    sysname = udev_device_get_sysname(udev_device);
 42+
 43+    if (sscanf(sysname, "event%u", &num) != 1)
 44+        goto done;
 45+
 46+    path = udev_device_get_devnode(udev_device);
 47+
 48+    if (strcmp(action, "add") == 0)
 49+        add_device(path);
 50+    else if (strcmp(action, "remove") == 0)
 51+    {
 52+        struct swc_evdev_device * device, * next;
 53+
 54+        wl_list_for_each_safe(device, next, &seat.devices, link)
 55+        {
 56+            if (strcmp(device->path, path) == 0)
 57+            {
 58+                wl_list_remove(&device->link);
 59+                swc_evdev_device_destroy(device);
 60+                break;
 61+            }
 62+        }
 63+    }
 64+
 65+  done:
 66+    udev_device_unref(udev_device);
 67+    return 0;
 68+}
 69+
 70+bool initialize_monitor()
 71+{
 72+    int fd;
 73+
 74+    if (!(seat.udev = udev_new()))
 75+    {
 76+        ERROR("Could not create udev context\n");
 77+        goto error0;
 78+    }
 79+
 80+    if (!(seat.monitor = udev_monitor_new_from_netlink(seat.udev, "udev")))
 81+    {
 82+        ERROR("Could not create udev monitor\n");
 83+        goto error1;
 84+    }
 85+
 86+    if (udev_monitor_filter_add_match_subsystem_devtype(seat.monitor,
 87+                                                        "input", NULL) != 0)
 88+    {
 89+        ERROR("Could not set up udev monitor filter\n");
 90+        goto error2;
 91+    }
 92+
 93+    if (udev_monitor_enable_receiving(seat.monitor) != 0)
 94+    {
 95+        ERROR("Could not enable receiving for udev monitor\n");
 96+        goto error2;
 97+    }
 98+
 99+    fd = udev_monitor_get_fd(seat.monitor);
100+    seat.monitor_source = wl_event_loop_add_fd
101+        (swc.event_loop, fd, WL_EVENT_READABLE, &handle_monitor_data, NULL);
102+
103+    if (!seat.monitor_source)
104+    {
105+        ERROR("Could not create event source for udev monitor\n");
106+        goto error2;
107+    }
108+
109+    return true;
110+
111+  error2:
112+    udev_monitor_unref(seat.monitor);
113+  error1:
114+    udev_unref(seat.udev);
115+  error0:
116+    return false;
117+}
118+
119+void finalize_monitor()
120+{
121+    wl_event_source_remove(seat.monitor_source);
122+    udev_monitor_unref(seat.monitor);
123+    udev_unref(seat.udev);
124+}
125+#endif
126+
127 bool swc_seat_initialize(const char * seat_name)
128 {
129     if (!(seat.name = strdup(seat_name)))
130@@ -290,12 +397,21 @@ bool swc_seat_initialize(const char * seat_name)
131         goto error4;
132     }
133 
134-    if (!add_devices())
135+#ifdef ENABLE_HOTPLUGGING
136+    if (!initialize_monitor())
137         goto error5;
138+#endif
139+
140+    if (!add_devices())
141+        goto error6;
142 
143     return true;
144 
145+  error6:
146+#ifdef ENABLE_HOTPLUGGING
147+    finalize_monitor();
148   error5:
149+#endif
150     swc_pointer_finalize(&seat.pointer);
151   error4:
152     swc_keyboard_finalize(&seat.keyboard);
153@@ -313,6 +429,9 @@ void swc_seat_finalize()
154 {
155     struct swc_evdev_device * device, * tmp;
156 
157+#ifdef ENABLE_HOTPLUGGING
158+    finalize_monitor();
159+#endif
160     swc_pointer_finalize(&seat.pointer);
161     swc_keyboard_finalize(&seat.keyboard);
162