ODROID-U3 xorg-server debian package fork :
[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 --- a/config/Makefile.am
23 +++ b/config/Makefile.am
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
35 --- a/config/config-backends.h
36 +++ b/config/config-backends.h
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
46 --- a/config/config.c
47 +++ b/config/config.c
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
67 --- /dev/null
68 +++ b/config/devd.c
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 +}
457 --- a/configure.ac
458 +++ b/configure.ac
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
489 --- a/hw/xfree86/common/xf86Config.c
490 +++ b/hw/xfree86/common/xf86Config.c
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, "
512 --- a/hw/xfree86/common/xf86Globals.c
513 +++ b/hw/xfree86/common/xf86Globals.c
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,
524 --- a/include/dix-config.h.in
525 +++ b/include/dix-config.h.in
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