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