Imported Debian patch 2:1.15.1-0ubuntu2.6
[deb_xorg-server.git] / debian / patches / 02_kbsd-input-devd.diff
1 >From d96e2bd2a2b48ede527ad7071d3e0eeda9861b73 Mon Sep 17 00:00:00 2001
2 From: Robert Millan <rmh@debian.org>
3 Date: Mon, 24 Feb 2014 23:22:57 +0100
4 Subject: [PATCH] Add devd config backend for FreeBSD (and GNU/kFreeBSD)
5
6 Based on original code by Baptiste Daroussin, with some fixes made
7 by Koop Mast and myself.
8
9 Signed-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
22 Index: 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
37 Index: 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
50 Index: 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
73 Index: 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 +}
465 Index: 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
499 Index: 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, "
524 Index: 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,
538 Index: 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