ODROID-U3 xorg-server debian package fork :
[deb_xorg-server.git] / debian / patches / 02_kbsd-input-devd.diff
CommitLineData
7217e0ca
ML
1>From d96e2bd2a2b48ede527ad7071d3e0eeda9861b73 Mon Sep 17 00:00:00 2001
2From: Robert Millan <rmh@debian.org>
3Date: Mon, 24 Feb 2014 23:22:57 +0100
4Subject: [PATCH] Add devd config backend for FreeBSD (and GNU/kFreeBSD)
5
6Based on original code by Baptiste Daroussin, with some fixes made
7by Koop Mast and myself.
8
9Signed-off-by: Robert Millan <rmh@freebsd.org>
10---
11 config/Makefile.am | 4 +
12 config/config-backends.h | 5 +
13 config/config.c | 5 +
14 config/devd.c | 387 +++++++++++++++++++++++++++++++++++++++
15 configure.ac | 16 ++
16 hw/xfree86/common/xf86Config.c | 7 +-
17 hw/xfree86/common/xf86Globals.c | 3 +-
18 include/dix-config.h.in | 3 +
19 8 files changed, 427 insertions(+), 3 deletions(-)
20 create mode 100644 config/devd.c
21
4db25562
JB
22--- a/config/Makefile.am
23+++ b/config/Makefile.am
7217e0ca
ML
24@@ -40,6 +40,10 @@ if CONFIG_WSCONS
25 libconfig_la_SOURCES += wscons.c
26 endif # CONFIG_WSCONS
27
28+if CONFIG_DEVD
29+libconfig_la_SOURCES += devd.c
30+endif
31+
32 endif # CONFIG_NEED_DBUS
33
34 endif # !CONFIG_UDEV
4db25562
JB
35--- a/config/config-backends.h
36+++ b/config/config-backends.h
7217e0ca
ML
37@@ -75,3 +75,8 @@ void config_hal_fini(void);
38 int config_wscons_init(void);
39 void config_wscons_fini(void);
40 #endif
41+
42+#ifdef CONFIG_DEVD
43+int config_devd_init(void);
44+void config_devd_fini(void);
45+#endif
4db25562
JB
46--- a/config/config.c
47+++ b/config/config.c
7217e0ca
ML
48@@ -64,6 +64,9 @@ config_init(void)
49 #elif defined(CONFIG_WSCONS)
50 if (!config_wscons_init())
51 ErrorF("[config] failed to initialise wscons\n");
52+#elif defined(CONFIG_DEVD)
53+ if (!config_devd_init())
54+ ErrorF("[config] failed to initialise devd\n");
55 #endif
56 }
57
58@@ -82,6 +85,8 @@ config_fini(void)
59 config_dbus_core_fini();
60 #elif defined(CONFIG_WSCONS)
61 config_wscons_fini();
62+#elif defined(CONFIG_DEVD)
63+ config_devd_fini();
64 #endif
65 }
66
7217e0ca 67--- /dev/null
4db25562 68+++ b/config/devd.c
7217e0ca
ML
69@@ -0,0 +1,387 @@
70+/*
71+ * Copyright © 2012 Baptiste Daroussin
72+ * Copyright © 2014 Robert Millan
73+ *
74+ * Permission is hereby granted, free of charge, to any person obtaining a
75+ * copy of this software and associated documentation files (the "Software"),
76+ * to deal in the Software without restriction, including without limitation
77+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
78+ * and/or sell copies of the Software, and to permit persons to whom the
79+ * Software is furnished to do so, subject to the following conditions:
80+ *
81+ * The above copyright notice and this permission notice (including the next
82+ * paragraph) shall be included in all copies or substantial portions of the
83+ * Software.
84+ *
85+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
88+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
90+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
91+ * DEALINGS IN THE SOFTWARE.
92+ *
93+ * Author: Baptiste Daroussin <bapt@FreeBSD.org>
94+ */
95+
96+#ifdef HAVE_DIX_CONFIG_H
97+#include <dix-config.h>
98+#endif
99+
100+#include <sys/types.h>
101+#include <sys/socket.h>
102+#include <sys/sysctl.h>
103+#include <sys/un.h>
104+
105+#include <ctype.h>
106+#include <errno.h>
107+#include <fcntl.h>
108+#include <stdlib.h>
109+#include <stdio.h>
110+#include <stdarg.h>
111+#include <stdbool.h>
112+#include <unistd.h>
113+
114+#include "input.h"
115+#include "inputstr.h"
116+#include "hotplug.h"
117+#include "config-backends.h"
118+#include "os.h"
119+
120+#define DEVD_SOCK_PATH "/var/run/devd.pipe"
121+
122+#define DEVD_EVENT_ADD '+'
123+#define DEVD_EVENT_REMOVE '-'
124+
125+static int sock_devd = -1;
126+
127+struct hw_type {
128+ const char *driver;
129+ int flag;
130+ const char *xdriver;
131+};
132+
133+static struct hw_type hw_types[] = {
134+ {"ukbd", ATTR_KEYBOARD, "kbd"},
135+ {"atkbd", ATTR_KEYBOARD, "kbd"},
136+ {"ums", ATTR_POINTER, "mouse"},
137+ {"psm", ATTR_POINTER, "mouse"},
138+ {"uhid", ATTR_POINTER, "mouse"},
139+ {"joy", ATTR_JOYSTICK, NULL},
140+ {"atp", ATTR_TOUCHPAD, NULL},
141+ {"uep", ATTR_TOUCHSCREEN, NULL},
142+ {NULL, -1, NULL},
143+};
144+
145+static bool
146+sysctl_exists(const char *format, ...)
147+{
148+ va_list args;
149+ char *name = NULL;
150+ size_t len;
151+ int ret;
152+
153+ if (format == NULL)
154+ return false;
155+
156+ va_start(args, format);
157+ vasprintf(&name, format, args);
158+ va_end(args);
159+
160+ ret = sysctlbyname(name, NULL, &len, NULL, 0);
161+
162+ if (ret == -1)
163+ len = 0;
164+
165+ free(name);
166+ return (len > 0);
167+}
168+
169+static char *
170+sysctl_get_str(const char *format, ...)
171+{
172+ va_list args;
173+ char *name = NULL;
174+ char *dest = NULL;
175+ size_t len;
176+
177+ if (format == NULL)
178+ return NULL;
179+
180+ va_start(args, format);
181+ vasprintf(&name, format, args);
182+ va_end(args);
183+
184+ if (sysctlbyname(name, NULL, &len, NULL, 0) == 0) {
185+ dest = malloc(len + 1);
186+ if (!dest)
187+ goto unwind;
188+ if (sysctlbyname(name, dest, &len, NULL, 0) == 0)
189+ dest[len] = '\0';
190+ else {
191+ free(dest);
192+ dest = NULL;
193+ }
194+ }
195+
196+ unwind:
197+ free(name);
198+ return dest;
199+}
200+
201+static void
202+device_added(char *devname)
203+{
204+ char path[PATH_MAX];
205+ char *vendor;
206+ char *product = NULL;
207+ char *config_info = NULL;
208+ char *walk;
209+ InputOption *options = NULL;
210+ InputAttributes attrs = { };
211+ DeviceIntPtr dev = NULL;
212+ int i, rc;
213+ int fd;
214+
215+ for (i = 0; hw_types[i].driver != NULL; i++) {
216+ if (strncmp(devname, hw_types[i].driver,
217+ strlen(hw_types[i].driver)) == 0 &&
218+ isdigit(*(devname + strlen(hw_types[i].driver)))) {
219+ attrs.flags |= hw_types[i].flag;
220+ break;
221+ }
222+ }
223+ if (hw_types[i].driver == NULL) {
224+ LogMessageVerb(X_INFO, 10, "config/devd: ignoring device %s\n",
225+ devname);
226+ return;
227+ }
228+ if (hw_types[i].xdriver == NULL) {
229+ LogMessageVerb(X_INFO, 10, "config/devd: ignoring device %s\n",
230+ devname);
231+ return;
232+ }
233+ snprintf(path, sizeof(path), "/dev/%s", devname);
234+
235+ options = input_option_new(NULL, "_source", "server/devd");
236+ if (!options)
237+ return;
238+
239+ vendor =
240+ sysctl_get_str("dev.%s.%s.%%desc", hw_types[i].driver,
241+ devname + strlen(hw_types[i].driver));
242+ if (vendor == NULL) {
243+ attrs.vendor = strdup("(unnamed)");
244+ attrs.product = strdup("(unnamed)");
245+ }
246+ else {
247+ if ((walk = strchr(vendor, ' ')) != NULL) {
248+ walk[0] = '\0';
249+ walk++;
250+ product = walk;
251+ if ((walk = strchr(product, ',')) != NULL)
252+ walk[0] = '\0';
253+ }
254+
255+ attrs.vendor = strdup(vendor);
256+ if (product)
257+ attrs.product = strdup(product);
258+ else
259+ attrs.product = strdup("(unnamed)");
260+
261+ options = input_option_new(options, "name", xstrdup(attrs.product));
262+
263+ free(vendor);
264+ }
265+ attrs.usb_id = NULL;
266+ attrs.device = strdup(path);
267+ options = input_option_new(options, "driver", hw_types[i].xdriver);
268+ if (attrs.flags & ATTR_KEYBOARD) {
269+ /*
270+ * Don't pass device option if keyboard is attached to console (open fails),
271+ * thus activating special logic in xf86-input-keyboard.
272+ */
273+ fd = open(path, O_RDONLY | O_NONBLOCK | O_EXCL);
274+ if (fd > 0) {
275+ close(fd);
276+ options = input_option_new(options, "device", xstrdup(path));
277+ }
278+ }
279+ else {
280+ options = input_option_new(options, "device", xstrdup(path));
281+ }
282+
283+ if (asprintf(&config_info, "devd:%s", devname) == -1) {
284+ config_info = NULL;
285+ goto unwind;
286+ }
287+
288+ if (device_is_duplicate(config_info)) {
289+ LogMessage(X_WARNING, "config/devd: device %s already added. "
290+ "Ignoring.\n", attrs.product);
291+ goto unwind;
292+ }
293+
294+ options = input_option_new(options, "config_info", config_info);
295+ LogMessage(X_INFO, "config/devd: adding input device %s (%s)\n",
296+ attrs.product, path);
297+
298+ rc = NewInputDeviceRequest(options, &attrs, &dev);
299+
300+ if (rc != Success)
301+ goto unwind;
302+
303+ unwind:
304+ free(config_info);
305+ input_option_free_list(&options);
306+
307+ free(attrs.usb_id);
308+ free(attrs.product);
309+ free(attrs.device);
310+ free(attrs.vendor);
311+}
312+
313+static void
314+device_removed(char *devname)
315+{
316+ char *value;
317+
318+ if (asprintf(&value, "devd:%s", devname) == -1)
319+ return;
320+
321+ remove_devices("devd", value);
322+
323+ free(value);
324+}
325+
326+static ssize_t
327+socket_getline(int fd, char **out)
328+{
329+ char *buf, *newbuf;
330+ ssize_t ret, cap, sz = 0;
331+ char c;
332+
333+ cap = 1024;
334+ buf = malloc(cap * sizeof(char));
335+ if (!buf)
336+ return -1;
337+
338+ for (;;) {
339+ ret = read(sock_devd, &c, 1);
340+ if (ret < 1) {
341+ if (errno == EINTR)
342+ continue;
343+ free(buf);
344+ return -1;
345+ }
346+
347+ if (c == '\n')
348+ break;
349+
350+ if (sz + 1 >= cap) {
351+ cap *= 2;
352+ newbuf = realloc(buf, cap * sizeof(char));
353+ if (!newbuf) {
354+ free(buf);
355+ return -1;
356+ }
357+ buf = newbuf;
358+ }
359+ buf[sz] = c;
360+ sz++;
361+ }
362+
363+ buf[sz] = '\0';
364+ if (sz >= 0)
365+ *out = buf;
366+ else
367+ free(buf);
368+
369+ return sz; /* number of bytes in the line, not counting the line break */
370+}
371+
372+static void
373+wakeup_handler(void *data, int err, void *read_mask)
374+{
375+ char *line = NULL;
376+ char *walk;
377+
378+ if (err < 0)
379+ return;
380+
381+ if (FD_ISSET(sock_devd, (fd_set *) read_mask)) {
382+ if (socket_getline(sock_devd, &line) < 0)
383+ return;
384+
385+ walk = strchr(line + 1, ' ');
386+ if (walk != NULL)
387+ walk[0] = '\0';
388+
389+ switch (*line) {
390+ case DEVD_EVENT_ADD:
391+ device_added(line + 1);
392+ break;
393+ case DEVD_EVENT_REMOVE:
394+ device_removed(line + 1);
395+ break;
396+ default:
397+ break;
398+ }
399+ free(line);
400+ }
401+}
402+
403+static void
404+block_handler(void *data, struct timeval **tv, void *read_mask)
405+{
406+}
407+
408+int
409+config_devd_init(void)
410+{
411+ struct sockaddr_un devd;
412+ char devicename[1024];
413+ int i, j;
414+
415+ /* first scan the sysctl to determine the hardware if needed */
416+
417+ for (i = 0; hw_types[i].driver != NULL; i++) {
418+ for (j = 0; sysctl_exists("dev.%s.%i.%%desc", hw_types[i].driver, j);
419+ j++) {
420+ snprintf(devicename, sizeof(devicename), "%s%i", hw_types[i].driver,
421+ j);
422+ device_added(devicename);
423+ }
424+
425+ }
426+ sock_devd = socket(AF_UNIX, SOCK_STREAM, 0);
427+ if (sock_devd < 0) {
428+ ErrorF("config/devd: Fail opening stream socket");
429+ return 0;
430+ }
431+
432+ devd.sun_family = AF_UNIX;
433+ strlcpy(devd.sun_path, DEVD_SOCK_PATH, sizeof(devd.sun_path));
434+
435+ if (connect(sock_devd, (struct sockaddr *) &devd, sizeof(devd)) < 0) {
436+ close(sock_devd);
437+ ErrorF("config/devd: Fail to connect to devd");
438+ return 0;
439+ }
440+
441+ RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL);
442+ AddGeneralSocket(sock_devd);
443+
444+ return 1;
445+}
446+
447+void
448+config_devd_fini(void)
449+{
450+ if (sock_devd < 0)
451+ return;
452+
453+ RemoveGeneralSocket(sock_devd);
454+ RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL);
455+ close(sock_devd);
456+}
4db25562
JB
457--- a/configure.ac
458+++ b/configure.ac
7217e0ca
ML
459@@ -618,6 +618,7 @@ AC_ARG_ENABLE(config-udev, AS_HELP_ST
460 AC_ARG_ENABLE(config-udev-kms, AS_HELP_STRING([--enable-config-udev-kms], [Build udev kms support (default: auto)]), [CONFIG_UDEV_KMS=$enableval], [CONFIG_UDEV_KMS=auto])
461 AC_ARG_ENABLE(config-dbus, AS_HELP_STRING([--enable-config-dbus], [Build D-BUS API support (default: no)]), [CONFIG_DBUS_API=$enableval], [CONFIG_DBUS_API=no])
462 AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto])
463+AC_ARG_ENABLE(config-devd, AS_HELP_STRING([--disable-config-devd], [Build devd support (default: auto)]), [CONFIG_DEVD=$enableval], [CONFIG_DEVD=auto])
464 AC_ARG_ENABLE(config-wscons, AS_HELP_STRING([--enable-config-wscons], [Build wscons config support (default: auto)]), [CONFIG_WSCONS=$enableval], [CONFIG_WSCONS=auto])
465 AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes])
466 AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with vga access (default: enabled)]), [VGAHW=$enableval], [VGAHW=yes])
467@@ -922,6 +923,21 @@ if test "x$CONFIG_WSCONS" = xyes; then
468 AC_DEFINE(CONFIG_WSCONS, 1, [Use wscons for input auto configuration])
469 fi
470
471+if test "x$CONFIG_DEVD" = xauto; then
472+ case $host_os in
473+ freebsd* | kfreebsd*-gnu)
474+ CONFIG_DEVD=yes;
475+ ;;
476+ *)
477+ CONFIG_DEVD=no;
478+ ;;
479+ esac
480+fi
481+AM_CONDITIONAL(CONFIG_DEVD, [test "x$CONFIG_DEVD" = xyes])
482+if test "x$CONFIG_DEVD" = xyes; then
483+ AC_DEFINE(CONFIG_DEVD, 1, [Use devd for input auto configuration])
484+fi
485+
486 if test "x$USE_SIGIO_BY_DEFAULT" = xyes; then
487 USE_SIGIO_BY_DEFAULT_VALUE=TRUE
488 else
4db25562
JB
489--- a/hw/xfree86/common/xf86Config.c
490+++ b/hw/xfree86/common/xf86Config.c
7217e0ca
ML
491@@ -1377,15 +1377,18 @@ checkCoreInputDevices(serverLayoutPtr se
492 }
493
494 if (!xf86Info.forceInputDevices && !(foundPointer && foundKeyboard)) {
495-#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS)
496+#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS) || \
497+ defined(CONFIG_DEVD)
498 const char *config_backend;
499
500 #if defined(CONFIG_HAL)
501 config_backend = "HAL";
502 #elif defined(CONFIG_UDEV)
503 config_backend = "udev";
504-#else
505+#elif defined(CONFIG_WSCONS)
506 config_backend = "wscons";
507+#elif defined(CONFIG_DEVD)
508+ config_backend = "devd";
509 #endif
510 xf86Msg(X_INFO, "The server relies on %s to provide the list of "
511 "input devices.\n\tIf no devices become available, "
4db25562
JB
512--- a/hw/xfree86/common/xf86Globals.c
513+++ b/hw/xfree86/common/xf86Globals.c
7217e0ca
ML
514@@ -123,7 +123,8 @@ xf86InfoRec xf86Info = {
515 .log = LogNone,
516 .disableRandR = FALSE,
517 .randRFrom = X_DEFAULT,
518-#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS)
519+#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS) || \
520+ defined(CONFIG_DEVD)
521 .forceInputDevices = FALSE,
522 .autoAddDevices = TRUE,
523 .autoEnableDevices = TRUE,
4db25562
JB
524--- a/include/dix-config.h.in
525+++ b/include/dix-config.h.in
7217e0ca
ML
526@@ -420,6 +420,9 @@
527 /* Support HAL for hotplug */
528 #undef CONFIG_HAL
529
530+/* Support devd for hotplug */
531+#undef CONFIG_DEVD
532+
533 /* Have a monotonic clock from clock_gettime() */
534 #undef MONOTONIC_CLOCK
535