[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#736765: my experience with i915kms, newcons and k-11



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, brunomaximom@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 <rmh@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 <rmh@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 <bapt@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


Reply to: