On 27/02/2014 23:25, Robert Millan wrote: > On 27/02/2014 18:25, Christoph Egger wrote: >> On Sun, Feb 23, 2014 at 11:44:35AM -0300, brunomaxi...@openmailbox.org wrote: >>> but, any input (mouse, touchpad, keyboard) doesn't work, so I can't >>> log in. >>> This is happening with you guys or just me? Any idea? >>> Thanks, >> >> Happens for me since xserver 1.15 or something (very recent update in >> jessie). I don't have any input working in any way (kfreebsd 9.2 or >> 9.3) with slim. I'll try to allocate some time to fix that but can't promise >> anything currently. > > Probably HAL-related. xserver 1.15 works fine with the devd patch, I tested > that version just a few days ago.
Here's the most recent version. Also needs the Debian bits from: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=736765#47 -- Robert Millan
>From d96e2bd2a2b48ede527ad7071d3e0eeda9861b73 Mon Sep 17 00:00:00 2001 From: Robert Millan <r...@debian.org> Date: Mon, 24 Feb 2014 23:22:57 +0100 Subject: [PATCH] Add devd config backend for FreeBSD (and GNU/kFreeBSD) Based on original code by Baptiste Daroussin, with some fixes made by Koop Mast and myself. Signed-off-by: Robert Millan <r...@freebsd.org> --- config/Makefile.am | 4 + config/config-backends.h | 5 + config/config.c | 5 + config/devd.c | 387 +++++++++++++++++++++++++++++++++++++++ configure.ac | 16 ++ hw/xfree86/common/xf86Config.c | 7 +- hw/xfree86/common/xf86Globals.c | 3 +- include/dix-config.h.in | 3 + 8 files changed, 427 insertions(+), 3 deletions(-) create mode 100644 config/devd.c diff --git a/config/Makefile.am b/config/Makefile.am index 0e20e8b..16f8aaa 100644 --- a/config/Makefile.am +++ b/config/Makefile.am @@ -34,6 +34,10 @@ if CONFIG_WSCONS libconfig_la_SOURCES += wscons.c endif # CONFIG_WSCONS +if CONFIG_DEVD +libconfig_la_SOURCES += devd.c +endif + endif # !CONFIG_HAL endif # !CONFIG_UDEV diff --git a/config/config-backends.h b/config/config-backends.h index 5f07557..889e2ad 100644 --- a/config/config-backends.h +++ b/config/config-backends.h @@ -44,3 +44,8 @@ void config_hal_fini(void); int config_wscons_init(void); void config_wscons_fini(void); #endif + +#ifdef CONFIG_DEVD +int config_devd_init(void); +void config_devd_fini(void); +#endif diff --git a/config/config.c b/config/config.c index 760cf19..cca5a31 100644 --- a/config/config.c +++ b/config/config.c @@ -53,6 +53,9 @@ config_init(void) #elif defined(CONFIG_WSCONS) if (!config_wscons_init()) ErrorF("[config] failed to initialise wscons\n"); +#elif defined(CONFIG_DEVD) + if (!config_devd_init()) + ErrorF("[config] failed to initialise devd\n"); #endif } @@ -65,6 +68,8 @@ config_fini(void) config_hal_fini(); #elif defined(CONFIG_WSCONS) config_wscons_fini(); +#elif defined(CONFIG_DEVD) + config_devd_fini(); #endif } diff --git a/config/devd.c b/config/devd.c new file mode 100644 index 0000000..92a66c4 --- /dev/null +++ b/config/devd.c @@ -0,0 +1,387 @@ +/* + * Copyright © 2012 Baptiste Daroussin + * Copyright © 2014 Robert Millan + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Baptiste Daroussin <b...@freebsd.org> + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/sysctl.h> +#include <sys/un.h> + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdbool.h> +#include <unistd.h> + +#include "input.h" +#include "inputstr.h" +#include "hotplug.h" +#include "config-backends.h" +#include "os.h" + +#define DEVD_SOCK_PATH "/var/run/devd.pipe" + +#define DEVD_EVENT_ADD '+' +#define DEVD_EVENT_REMOVE '-' + +static int sock_devd = -1; + +struct hw_type { + const char *driver; + int flag; + const char *xdriver; +}; + +static struct hw_type hw_types[] = { + {"ukbd", ATTR_KEYBOARD, "kbd"}, + {"atkbd", ATTR_KEYBOARD, "kbd"}, + {"ums", ATTR_POINTER, "mouse"}, + {"psm", ATTR_POINTER, "mouse"}, + {"uhid", ATTR_POINTER, "mouse"}, + {"joy", ATTR_JOYSTICK, NULL}, + {"atp", ATTR_TOUCHPAD, NULL}, + {"uep", ATTR_TOUCHSCREEN, NULL}, + {NULL, -1, NULL}, +}; + +static bool +sysctl_exists(const char *format, ...) +{ + va_list args; + char *name = NULL; + size_t len; + int ret; + + if (format == NULL) + return false; + + va_start(args, format); + vasprintf(&name, format, args); + va_end(args); + + ret = sysctlbyname(name, NULL, &len, NULL, 0); + + if (ret == -1) + len = 0; + + free(name); + return (len > 0); +} + +static char * +sysctl_get_str(const char *format, ...) +{ + va_list args; + char *name = NULL; + char *dest = NULL; + size_t len; + + if (format == NULL) + return NULL; + + va_start(args, format); + vasprintf(&name, format, args); + va_end(args); + + if (sysctlbyname(name, NULL, &len, NULL, 0) == 0) { + dest = malloc(len + 1); + if (!dest) + goto unwind; + if (sysctlbyname(name, dest, &len, NULL, 0) == 0) + dest[len] = '\0'; + else { + free(dest); + dest = NULL; + } + } + + unwind: + free(name); + return dest; +} + +static void +device_added(char *devname) +{ + char path[PATH_MAX]; + char *vendor; + char *product = NULL; + char *config_info = NULL; + char *walk; + InputOption *options = NULL; + InputAttributes attrs = { }; + DeviceIntPtr dev = NULL; + int i, rc; + int fd; + + for (i = 0; hw_types[i].driver != NULL; i++) { + if (strncmp(devname, hw_types[i].driver, + strlen(hw_types[i].driver)) == 0 && + isdigit(*(devname + strlen(hw_types[i].driver)))) { + attrs.flags |= hw_types[i].flag; + break; + } + } + if (hw_types[i].driver == NULL) { + LogMessageVerb(X_INFO, 10, "config/devd: ignoring device %s\n", + devname); + return; + } + if (hw_types[i].xdriver == NULL) { + LogMessageVerb(X_INFO, 10, "config/devd: ignoring device %s\n", + devname); + return; + } + snprintf(path, sizeof(path), "/dev/%s", devname); + + options = input_option_new(NULL, "_source", "server/devd"); + if (!options) + return; + + vendor = + sysctl_get_str("dev.%s.%s.%%desc", hw_types[i].driver, + devname + strlen(hw_types[i].driver)); + if (vendor == NULL) { + attrs.vendor = strdup("(unnamed)"); + attrs.product = strdup("(unnamed)"); + } + else { + if ((walk = strchr(vendor, ' ')) != NULL) { + walk[0] = '\0'; + walk++; + product = walk; + if ((walk = strchr(product, ',')) != NULL) + walk[0] = '\0'; + } + + attrs.vendor = strdup(vendor); + if (product) + attrs.product = strdup(product); + else + attrs.product = strdup("(unnamed)"); + + options = input_option_new(options, "name", xstrdup(attrs.product)); + + free(vendor); + } + attrs.usb_id = NULL; + attrs.device = strdup(path); + options = input_option_new(options, "driver", hw_types[i].xdriver); + if (attrs.flags & ATTR_KEYBOARD) { + /* + * Don't pass device option if keyboard is attached to console (open fails), + * thus activating special logic in xf86-input-keyboard. + */ + fd = open(path, O_RDONLY | O_NONBLOCK | O_EXCL); + if (fd > 0) { + close(fd); + options = input_option_new(options, "device", xstrdup(path)); + } + } + else { + options = input_option_new(options, "device", xstrdup(path)); + } + + if (asprintf(&config_info, "devd:%s", devname) == -1) { + config_info = NULL; + goto unwind; + } + + if (device_is_duplicate(config_info)) { + LogMessage(X_WARNING, "config/devd: device %s already added. " + "Ignoring.\n", attrs.product); + goto unwind; + } + + options = input_option_new(options, "config_info", config_info); + LogMessage(X_INFO, "config/devd: adding input device %s (%s)\n", + attrs.product, path); + + rc = NewInputDeviceRequest(options, &attrs, &dev); + + if (rc != Success) + goto unwind; + + unwind: + free(config_info); + input_option_free_list(&options); + + free(attrs.usb_id); + free(attrs.product); + free(attrs.device); + free(attrs.vendor); +} + +static void +device_removed(char *devname) +{ + char *value; + + if (asprintf(&value, "devd:%s", devname) == -1) + return; + + remove_devices("devd", value); + + free(value); +} + +static ssize_t +socket_getline(int fd, char **out) +{ + char *buf, *newbuf; + ssize_t ret, cap, sz = 0; + char c; + + cap = 1024; + buf = malloc(cap * sizeof(char)); + if (!buf) + return -1; + + for (;;) { + ret = read(sock_devd, &c, 1); + if (ret < 1) { + if (errno == EINTR) + continue; + free(buf); + return -1; + } + + if (c == '\n') + break; + + if (sz + 1 >= cap) { + cap *= 2; + newbuf = realloc(buf, cap * sizeof(char)); + if (!newbuf) { + free(buf); + return -1; + } + buf = newbuf; + } + buf[sz] = c; + sz++; + } + + buf[sz] = '\0'; + if (sz >= 0) + *out = buf; + else + free(buf); + + return sz; /* number of bytes in the line, not counting the line break */ +} + +static void +wakeup_handler(void *data, int err, void *read_mask) +{ + char *line = NULL; + char *walk; + + if (err < 0) + return; + + if (FD_ISSET(sock_devd, (fd_set *) read_mask)) { + if (socket_getline(sock_devd, &line) < 0) + return; + + walk = strchr(line + 1, ' '); + if (walk != NULL) + walk[0] = '\0'; + + switch (*line) { + case DEVD_EVENT_ADD: + device_added(line + 1); + break; + case DEVD_EVENT_REMOVE: + device_removed(line + 1); + break; + default: + break; + } + free(line); + } +} + +static void +block_handler(void *data, struct timeval **tv, void *read_mask) +{ +} + +int +config_devd_init(void) +{ + struct sockaddr_un devd; + char devicename[1024]; + int i, j; + + /* first scan the sysctl to determine the hardware if needed */ + + for (i = 0; hw_types[i].driver != NULL; i++) { + for (j = 0; sysctl_exists("dev.%s.%i.%%desc", hw_types[i].driver, j); + j++) { + snprintf(devicename, sizeof(devicename), "%s%i", hw_types[i].driver, + j); + device_added(devicename); + } + + } + sock_devd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock_devd < 0) { + ErrorF("config/devd: Fail opening stream socket"); + return 0; + } + + devd.sun_family = AF_UNIX; + strlcpy(devd.sun_path, DEVD_SOCK_PATH, sizeof(devd.sun_path)); + + if (connect(sock_devd, (struct sockaddr *) &devd, sizeof(devd)) < 0) { + close(sock_devd); + ErrorF("config/devd: Fail to connect to devd"); + return 0; + } + + RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); + AddGeneralSocket(sock_devd); + + return 1; +} + +void +config_devd_fini(void) +{ + if (sock_devd < 0) + return; + + RemoveGeneralSocket(sock_devd); + RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); + close(sock_devd); +} diff --git a/configure.ac b/configure.ac index 21a6591..27452e3 100644 --- a/configure.ac +++ b/configure.ac @@ -615,6 +615,7 @@ AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS exten AC_ARG_ENABLE(config-udev, AS_HELP_STRING([--enable-config-udev], [Build udev support (default: auto)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=auto]) 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]) AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto]) +AC_ARG_ENABLE(config-devd, AS_HELP_STRING([--disable-config-devd], [Build devd support (default: auto)]), [CONFIG_DEVD=$enableval], [CONFIG_DEVD=auto]) AC_ARG_ENABLE(config-wscons, AS_HELP_STRING([--enable-config-wscons], [Build wscons config support (default: auto)]), [CONFIG_WSCONS=$enableval], [CONFIG_WSCONS=auto]) AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes]) AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with vga access (default: enabled)]), [VGAHW=$enableval], [VGAHW=yes]) @@ -921,6 +922,21 @@ if test "x$CONFIG_WSCONS" = xyes; then AC_DEFINE(CONFIG_WSCONS, 1, [Use wscons for input auto configuration]) fi +if test "x$CONFIG_DEVD" = xauto; then + case $host_os in + freebsd* | kfreebsd*-gnu) + CONFIG_DEVD=yes; + ;; + *) + CONFIG_DEVD=no; + ;; + esac +fi +AM_CONDITIONAL(CONFIG_DEVD, [test "x$CONFIG_DEVD" = xyes]) +if test "x$CONFIG_DEVD" = xyes; then + AC_DEFINE(CONFIG_DEVD, 1, [Use devd for input auto configuration]) +fi + if test "x$USE_SIGIO_BY_DEFAULT" = xyes; then USE_SIGIO_BY_DEFAULT_VALUE=TRUE else diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 542d5ab..d012584 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -1379,15 +1379,18 @@ checkCoreInputDevices(serverLayoutPtr servlayoutp, Bool implicitLayout) } if (!xf86Info.forceInputDevices && !(foundPointer && foundKeyboard)) { -#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS) +#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS) || \ + defined(CONFIG_DEVD) const char *config_backend; #if defined(CONFIG_HAL) config_backend = "HAL"; #elif defined(CONFIG_UDEV) config_backend = "udev"; -#else +#elif defined(CONFIG_WSCONS) config_backend = "wscons"; +#elif defined(CONFIG_DEVD) + config_backend = "devd"; #endif xf86Msg(X_INFO, "The server relies on %s to provide the list of " "input devices.\n\tIf no devices become available, " diff --git a/hw/xfree86/common/xf86Globals.c b/hw/xfree86/common/xf86Globals.c index 7df7a80..4119e8b 100644 --- a/hw/xfree86/common/xf86Globals.c +++ b/hw/xfree86/common/xf86Globals.c @@ -123,7 +123,8 @@ xf86InfoRec xf86Info = { .log = LogNone, .disableRandR = FALSE, .randRFrom = X_DEFAULT, -#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS) +#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS) || \ + defined(CONFIG_DEVD) .forceInputDevices = FALSE, .autoAddDevices = TRUE, .autoEnableDevices = TRUE, diff --git a/include/dix-config.h.in b/include/dix-config.h.in index 7c77956..72df572 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -420,6 +420,9 @@ /* Support HAL for hotplug */ #undef CONFIG_HAL +/* Support devd for hotplug */ +#undef CONFIG_DEVD + /* Have a monotonic clock from clock_gettime() */ #undef MONOTONIC_CLOCK -- 1.7.10.4