summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkwm <kwm@058c260c-8361-11dd-a0ac-aa2bafec7d09>2014-09-08 20:29:39 +0800
committerkwm <kwm@058c260c-8361-11dd-a0ac-aa2bafec7d09>2014-09-08 20:29:39 +0800
commit4f9abaade7b5e17e5980913de5423aeee47a6f2c (patch)
treea6d354f87bf0aac97ba8c55dd361833f40207fa3
parent21015ec1509a38e011dc8db6934b627b5f782544 (diff)
downloadxorg-devel-ports-4f9abaade7b5e17e5980913de5423aeee47a6f2c.tar.gz
xorg-devel-ports-4f9abaade7b5e17e5980913de5423aeee47a6f2c.tar.zst
xorg-devel-ports-4f9abaade7b5e17e5980913de5423aeee47a6f2c.zip
Update devd support [1]
Remove experimental note from DEVD descr. Submitted by: ak@ [1] git-svn-id: https://trillian.chruetertee.ch/svn/ports/trunk@1503 058c260c-8361-11dd-a0ac-aa2bafec7d09
-rw-r--r--x11-servers/xorg-server/Makefile7
-rw-r--r--x11-servers/xorg-server/files/extra-new-devd390
2 files changed, 394 insertions, 3 deletions
diff --git a/x11-servers/xorg-server/Makefile b/x11-servers/xorg-server/Makefile
index 2d6d212..fdcbe4b 100644
--- a/x11-servers/xorg-server/Makefile
+++ b/x11-servers/xorg-server/Makefile
@@ -26,7 +26,7 @@ OPTIONS_RADIO_CONF= HAL DEVD
AIGLX_DESC= Compile with Accelerated Indirect GLX support
SUID_DESC= Install the Xorg server with setuid bit set
HAL_DESC= Compile with HAL config support
-DEVD_DESC= Use devd for autoconfiguration of input devices (experimental)
+DEVD_DESC= Use devd for autoconfiguration of input devices
OPTIONS_DEFAULT=AIGLX SUID DEVD
OPTIONS_EXCLUDE_sparc64= HAL
@@ -94,10 +94,11 @@ CONFIGURE_ARGS+= --enable-config-hal=no
.endif
.if ${PORT_OPTIONS:MDEVD}
-EXTRA_PATCHES+= ${FILESDIR}/extra-devd
. if defined(WITH_NEW_XORG)
+EXTRA_PATCHES+= ${FILESDIR}/extra-new-devd
EXTRA_PATCHES+= ${FILESDIR}/extra-new-config_devd
. else
+EXTRA_PATCHES+= ${FILESDIR}/extra-devd
EXTRA_PATCHES+= ${FILESDIR}/extra-old-config_devd
. endif
.endif
@@ -197,7 +198,7 @@ post-configure:
post-install:
# The .xorg dir because else the xorg-server might not load the correct
# libglx module.
- ${MKDIR} ${STAGEDIR}${PREFIX}/lib/xorg/modules/extensions/.xorg
+ @${MKDIR} ${STAGEDIR}${PREFIX}/lib/xorg/modules/extensions/.xorg
${INSTALL_LIB} ${WRKSRC}/hw/xfree86/dixmods/.libs/libglx.so \
${STAGEDIR}${PREFIX}/lib/xorg/modules/extensions/.xorg/
diff --git a/x11-servers/xorg-server/files/extra-new-devd b/x11-servers/xorg-server/files/extra-new-devd
new file mode 100644
index 0000000..c3d54f2
--- /dev/null
+++ b/x11-servers/xorg-server/files/extra-new-devd
@@ -0,0 +1,390 @@
+Index: config/devd.c
+@@ -0,0 +1,388 @@
++/*
++ * Copyright (c) 2012 Baptiste Daroussin
++ * Copyright (c) 2013, 2014 Alex Kozlov
++ * Copyright (c) 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);
++}