View | Details | Raw Unified | Return to bug 183478 | Differences between
and this patch

Collapse All | Expand All

(-)xorg-server/Makefile (-4 / +17 lines)
Lines 22-33 Link Here
22
22
23
OPTIONS_DEFINE=	AIGLX SUID
23
OPTIONS_DEFINE=	AIGLX SUID
24
OPTIONS_RADIO=	CONF
24
OPTIONS_RADIO=	CONF
25
OPTIONS_RADIO_CONF= HAL DEVD
25
OPTIONS_RADIO_CONF= HAL
26
AIGLX_DESC=	Compile with Accelerated Indirect GLX support
26
AIGLX_DESC=	Compile with Accelerated Indirect GLX support
27
SUID_DESC=	Install the Xorg server with setuid bit set
27
SUID_DESC=	Install the Xorg server with setuid bit set
28
HAL_DESC=	Compile with HAL config support
28
HAL_DESC=	Compile with HAL config support
29
DEVD_DESC=	Use devd for autoconfiguration of input devices (experimental)
29
OPTIONS_DEFAULT=AIGLX SUID
30
OPTIONS_DEFAULT=AIGLX SUID HAL
30
31
.if defined(WITH_NEW_XORG)
32
OPTIONS_RADIO_CONF+= DEVD
33
DEVD_DESC=	Use devd for autoconfiguration of input devices
34
OPTIONS_DEFAULT+=DEVD
35
.endif
31
36
32
OPTIONS_EXCLUDE_sparc64=	HAL
37
OPTIONS_EXCLUDE_sparc64=	HAL
33
38
Lines 97-103 Link Here
97
.endif
102
.endif
98
103
99
.if ${PORT_OPTIONS:MDEVD}
104
.if ${PORT_OPTIONS:MDEVD}
100
EXTRA_PATCHES+=		${FILESDIR}/extra-config_devd.c
105
EXTRA_PATCHES+=		${FILESDIR}/extra-devd
106
PLIST_SUB+=		DEVD=""
107
.else
108
PLIST_SUB+=		DEVD="@comment "
101
.endif
109
.endif
102
110
103
.if ${PORT_OPTIONS:MAIGLX}
111
.if ${PORT_OPTIONS:MAIGLX}
Lines 177-182 Link Here
177
		-e 's|^LTLIBRARIES = |LTLIBRARIES = libglx.la |g' \
185
		-e 's|^LTLIBRARIES = |LTLIBRARIES = libglx.la |g' \
178
		${WRKSRC}/hw/xfree86/dixmods/Makefile.in
186
		${WRKSRC}/hw/xfree86/dixmods/Makefile.in
179
.if ${PORT_OPTIONS:MDEVD}
187
.if ${PORT_OPTIONS:MDEVD}
188
	@${CP} ${FILESDIR}/devd.c.in ${WRKSRC}/config/devd.c
180
	@${ECHO_CMD} -e "\nint config_devd_init(void);\nvoid config_devd_fini(void);" \
189
	@${ECHO_CMD} -e "\nint config_devd_init(void);\nvoid config_devd_fini(void);" \
181
		>> ${WRKSRC}/config/config-backends.h
190
		>> ${WRKSRC}/config/config-backends.h
182
.endif
191
.endif
Lines 204-209 Link Here
204
.if defined(WITH_NEW_XORG)
213
.if defined(WITH_NEW_XORG)
205
	@${MKDIR} ${STAGEDIR}${PREFIX}/etc/X11/xorg.conf.d
214
	@${MKDIR} ${STAGEDIR}${PREFIX}/etc/X11/xorg.conf.d
206
.endif
215
.endif
216
.if ${PORT_OPTIONS:MDEVD}
217
	@${INSTALL_DATA} ${FILESDIR}/xhotplug.conf.in ${STAGEDIR}${PREFIX}/etc/devd/xhotplug.conf
218
	@${INSTALL_SCRIPT} ${FILESDIR}/xhotplug.in ${STAGEDIR}${PREFIX}/etc/rc.d/xhotplug
219
.endif
207
.endif # ! SLAVE_PORT
220
.endif # ! SLAVE_PORT
208
221
209
.include <bsd.port.post.mk>
222
.include <bsd.port.post.mk>
(-)xorg-server/files/devd.c.in (+376 lines)
Line 0 Link Here
1
#ifdef HAVE_DIX_CONFIG_H
2
#include <dix-config.h>
3
#endif
4
5
#include <errno.h>
6
#include <unistd.h>
7
#include <sys/socket.h>
8
#include <sys/stat.h>
9
#include <sys/types.h>
10
#include <sys/un.h>
11
12
#include "input.h"
13
#include "inputstr.h"
14
#include "hotplug.h"
15
#include "config-backends.h"
16
#include "os.h"
17
#include "opaque.h"             /* for 'display' */
18
19
#define DEVPIPE_PATH "/var/run/xorg-devpipe.pipe.%s"
20
#define DEVLIST_PATH "/var/run/xorg-devpipe.list"
21
22
static int pipe_fd = -1;
23
static char pipe_name[256];
24
25
static int
26
hex2int(char hex)
27
{
28
    return ('0' <= hex && hex <= '9') ? hex - '0' :
29
           ('a' <= hex && hex <= 'f') ? hex - 'a' + 10 :
30
           ('A' <= hex && hex <= 'F') ? hex - 'A' + 10 : 0;
31
}
32
33
static void
34
percent_decode(char *string)
35
{
36
    char *p, ch;
37
    for (p = string; (ch = *string);) {
38
        if (ch == '%') {
39
            if (!string[1] || !string[2]) break;
40
            *p++ = hex2int(string[1]) * 16 + hex2int(string[2]);
41
            string += 3;
42
        } else {
43
            *p++ = *string++;
44
        }
45
    }
46
    *p = 0;
47
}
48
49
#if XORG_VERSION_CURRENT > 10800000
50
static void
51
plus_device(const char *descr)
52
{
53
    InputAttributes attrs = { };
54
    DeviceIntPtr dev = NULL;
55
    InputOption *input_options = NULL;
56
    char key[256], *val;
57
    char *devname, *devpath, *config_info, **tag;
58
    int n;
59
60
    if (sscanf(descr, "%256s%n", key, &n) < 0)
61
        return;
62
    descr += n;
63
64
    devname = strdup(key);
65
    asprintf(&devpath, "/dev/%s", devname);
66
    asprintf(&config_info, "devd:%s", devname);
67
68
    if (device_is_duplicate(config_info)) {
69
        LogMessage(X_WARNING, "config/devd: device %s already added\n", devname);
70
        goto free2;
71
    }
72
73
    input_options = input_option_new(input_options, "device", devpath);
74
    input_options = input_option_new(input_options, "config_info", config_info);
75
76
    attrs.device = strdup(devpath);
77
78
    while (sscanf(descr, " %64[^=]%192[^ ]%n", key, &key[65], &n) >= 2) {
79
        descr += n;
80
        percent_decode(val = &key[66]);
81
        LogMessage(X_INFO, "config/devd: %s: %s=<%s>\n", devname, key, val);
82
        input_options = input_option_new(input_options, key, val);
83
        if (!strcmp(key, "product")) attrs.product = strdup(val);
84
        else if (!strcmp(key, "vendor")) attrs.vendor = strdup(val);
85
        else if (!strcmp(key, "pnp_id")) attrs.pnp_id = strdup(val);
86
        else if (!strcmp(key, "usb_id")) attrs.usb_id = strdup(val);
87
        else if (!strcmp(key, "tags")) attrs.tags = xstrtokenize(val, ",");
88
        else if (!strcmp(key, "flags")) {
89
            if (strstr(val, "keyboard")) attrs.flags |= ATTR_KEYBOARD;
90
            if (strstr(val, "pointer")) attrs.flags |= ATTR_POINTER;
91
            if (strstr(val, "joystick")) attrs.flags |= ATTR_JOYSTICK;
92
            if (strstr(val, "tablet")) attrs.flags |= ATTR_TABLET;
93
            if (strstr(val, "touchpad")) attrs.flags |= ATTR_TOUCHPAD;
94
            if (strstr(val, "touchscreen")) attrs.flags |= ATTR_TOUCHSCREEN;
95
        };
96
    }
97
98
    if (input_option_find(input_options, "name") == NULL)
99
        input_options = input_option_new(input_options, "name", devname);
100
101
    if (input_options == NULL) {
102
        LogMessage(X_ERROR, "config/devd: can't allocate space for input options\n");
103
        goto free;
104
    }
105
106
    LogMessage(X_INFO, "config/devd: adding device %s\n", devname);
107
    NewInputDeviceRequest(input_options, &attrs, &dev);
108
109
free:
110
    input_option_free_list(&input_options);
111
112
    if (attrs.product) free(attrs.product);
113
    if (attrs.vendor) free(attrs.vendor);
114
    if (attrs.device) free(attrs.device);
115
    if (attrs.pnp_id) free(attrs.pnp_id);
116
    if (attrs.usb_id) free(attrs.usb_id);
117
    if (attrs.tags) {
118
        for (tag = attrs.tags; *tag; tag++) free(*tag);
119
        free(attrs.tags);
120
    }
121
free2:
122
    free(config_info);
123
    free(devpath);
124
    free(devname);
125
}
126
127
#else
128
129
/* This branch is a Frankensteinian monster.
130
 * For some reason if you add devices from _init, xserver will
131
 * fail to load the drivers. Also, wakeup handler never gets
132
 * called. In short, this is a disaster, kill it with fire.
133
 * (Only left here for reference).
134
 */
135
136
#error "DEVD backend does not work with xorg-server 1.7.7"
137
138
/* from new config/config.c */
139
static int
140
device_is_duplicate(char *config_info)
141
{
142
    DeviceIntPtr dev;
143
144
    for (dev = inputInfo.devices; dev; dev = dev->next)
145
        if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
146
            return 1;
147
148
    for (dev = inputInfo.off_devices; dev; dev = dev->next)
149
        if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
150
            return 1;
151
152
    return 0;
153
}
154
155
/* from new config/config.c */
156
static void
157
remove_device(const char *backend, DeviceIntPtr dev)
158
{
159
    /* this only gets called for devices that have already been added */
160
    LogMessage(X_INFO, "config/devd: removing device %s\n", dev->name);
161
162
    /* Call PIE here so we don't try to dereference a device that's
163
     * already been removed. */
164
    OsBlockSignals();
165
    ProcessInputEvents();
166
    DeleteInputDeviceRequest(dev);
167
    OsReleaseSignals();
168
}
169
170
/* from new config/config.c */
171
static void
172
remove_devices(const char *backend, const char *config_info)
173
{
174
    DeviceIntPtr dev, next;
175
176
    for (dev = inputInfo.devices; dev; dev = next) {
177
        next = dev->next;
178
        if (dev->config_info && strcmp(dev->config_info, config_info) == 0)
179
            remove_device(backend, dev);
180
    }
181
    for (dev = inputInfo.off_devices; dev; dev = next) {
182
        next = dev->next;
183
        if (dev->config_info && strcmp(dev->config_info, config_info) == 0)
184
            remove_device(backend, dev);
185
    }
186
}
187
188
/* from old config/hal.c */
189
static void
190
add_option(InputOption **options, const char *key, const char *value)
191
{
192
    if (!value || *value == '\0')
193
        return;
194
195
    for (; *options; options = &(*options)->next)
196
        ;
197
    *options = xcalloc(sizeof(**options), 1);
198
    if (!*options) /* Yeesh. */
199
        return;
200
    (*options)->key = xstrdup(key);
201
    (*options)->value = xstrdup(value);
202
    (*options)->next = NULL;
203
}
204
205
206
static void
207
plus_device(const char *descr)
208
{
209
    DeviceIntPtr dev = NULL;
210
    InputOption *input_options = NULL, *opt;
211
    char key[256], *val;
212
    char *devname, *devpath, *config_info, **tag;
213
    int n, gotname = 0;
214
215
    if (sscanf(descr, "%256s%n", key, &n) < 0)
216
        return;
217
    descr += n;
218
219
    devname = strdup(key);
220
    asprintf(&devpath, "/dev/%s", devname);
221
    asprintf(&config_info, "devd:%s", devname);
222
223
    if (device_is_duplicate(config_info)) {
224
        LogMessage(X_WARNING, "config/devd: device %s already added\n", devname);
225
        goto free2;
226
    }
227
228
    /*input_options = calloc(sizeof(*input_options), 1);
229
    if (input_options == NULL) {
230
        LogMessage(X_ERROR, "config/devd: calloc() failed\n");
231
        goto free2;
232
    }*/
233
234
    add_option(&input_options, "device", devpath);
235
    add_option(&input_options, "config_info", config_info);
236
237
    while (sscanf(descr, " %64[^=]%192[^ ]%n", key, &key[65], &n) >= 2) {
238
        descr += n;
239
        percent_decode(val = &key[66]);
240
        LogMessage(X_INFO, "config/devd: %s: %s=<%s>\n", devname, key, val);
241
        add_option(&input_options, key, val);
242
        if (strcmp(key, "name") == 0) gotname = 1;
243
    }
244
245
    if (!gotname)
246
        add_option(&input_options, "name", devname);
247
248
    LogMessage(X_INFO, "config/devd: adding device %s\n", devname);
249
    NewInputDeviceRequest(input_options, &dev);
250
251
free:
252
    while ((opt = input_options)) {
253
        input_options = opt->next;
254
        if (opt->key) free(opt->key);
255
        if (opt->value) free(opt->value);
256
        free(opt);
257
    }
258
free2:
259
    free(config_info);
260
    free(devpath);
261
    free(devname);
262
}
263
#endif
264
265
static void
266
minus_device(const char *descr)
267
{
268
    char devname[192], config_info[192 + 8];
269
270
    if (sscanf(descr, "%192s", devname) < 0)
271
        return;
272
    sprintf(config_info, "devd:%s", devname);
273
    remove_devices("devd", config_info);
274
}
275
276
static void
277
block_handler(pointer data, struct timeval **tv, pointer read_mask)
278
{
279
}
280
281
static void
282
wakeup_handler(pointer data, int err, pointer read_mask)
283
{
284
    char buffer[1024];
285
    int fd, n;
286
287
    if (err < 0) {
288
        //LogMessage(X_WARNING, "config/devd: ignoring error %d\n", err);
289
        return;
290
    }
291
292
    if (FD_ISSET(pipe_fd, (fd_set *) read_mask)) {
293
        fd = accept(pipe_fd, NULL, NULL);
294
        if (fd < 0) {
295
            LogMessage(X_WARNING, "config/devd: can't accept(): %s\n", strerror(errno));
296
            return;
297
        }
298
        // Please, don't block :)
299
        n = recv(fd, buffer, sizeof(buffer) - 1, 0);
300
        if (n < 0) {
301
            LogMessage(X_WARNING, "config/devd: recv() error: %s\n", strerror(errno));
302
            close(fd);
303
            return;
304
        }
305
        close(fd);
306
        buffer[n] = 0;
307
        LogMessage(X_INFO, "config/devd: received: %s\n", buffer);
308
        if (buffer[0] == '+') plus_device(&buffer[1]);
309
        if (buffer[0] == '-') minus_device(&buffer[1]);
310
    }
311
}
312
313
static void
314
plus_devlist_devices(void)
315
{
316
    FILE *db;
317
    char *line = NULL;
318
    size_t linecap = 0;
319
    ssize_t linelen;
320
321
    db = fopen(DEVLIST_PATH, "rb");
322
    if (db == NULL) return;
323
324
    while ((linelen = getline(&line, &linecap, db)) > 0) {
325
        if (line[linelen - 1] == '\n') {
326
            line[linelen - 1] = 0;
327
            plus_device(line);
328
        } else {
329
            LogMessage(X_ERROR, "config/devd: %s doesn not end with a newline\n", DEVLIST_PATH);
330
        }
331
    }
332
    if (line) free(line);
333
}
334
335
int
336
config_devd_init(void)
337
{
338
    struct sockaddr_un addr;
339
340
    snprintf(pipe_name, sizeof(pipe_name), DEVPIPE_PATH, display);
341
    pipe_fd = socket(AF_UNIX, SOCK_STREAM, 0);
342
    if (pipe_fd < 0) {
343
        LogMessage(X_ERROR, "config/devd: socket() failed: %s\n", strerror(errno));
344
        return 0;
345
    }
346
    addr.sun_family = AF_UNIX;
347
    strlcpy(addr.sun_path, pipe_name, sizeof(addr.sun_path));
348
    unlink(addr.sun_path);
349
    if (bind(pipe_fd, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
350
        LogMessage(X_ERROR, "config/devd: bind() failed: %s\n", strerror(errno));
351
        return 0;
352
    }
353
    chmod(addr.sun_path, 0666);
354
    if (listen(pipe_fd, 1) != 0) {
355
        LogMessage(X_ERROR, "config/devd: listen() failed: %s\n", strerror(errno));
356
        return 0;
357
    }
358
    LogMessage(X_INFO, "config/devd: listening on %s\n", pipe_name);
359
    RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL);
360
    AddGeneralSocket(pipe_fd);
361
    plus_devlist_devices();
362
    return 1;
363
}
364
365
void
366
config_devd_fini(void)
367
{
368
    if (pipe_fd >= 0) {
369
        RemoveGeneralSocket(pipe_fd);
370
        RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL);
371
        close(pipe_fd);
372
        unlink(pipe_name);
373
        pipe_fd = -1;
374
    }
375
    LogMessage(X_INFO, "config/devd: finished\n");
376
}
(-)xorg-server/files/extra-config_devd.c (-481 lines)
Lines 1-481 Link Here
1
--- /dev/null	2013-08-03 00:44:23.000000000 +0200
2
+++ config/devd.c	2013-08-03 00:45:15.162836806 +0200
3
@@ -0,0 +1,478 @@
4
+/*
5
+ * Copyright © 2012 Baptiste Daroussin
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a
8
+ * copy of this software and associated documentation files (the "Software"),
9
+ * to deal in the Software without restriction, including without limitation
10
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11
+ * and/or sell copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice (including the next
15
+ * paragraph) shall be included in all copies or substantial portions of the
16
+ * Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
+ * DEALINGS IN THE SOFTWARE.
25
+ *
26
+ * Author: Baptiste Daroussin <bapt@FreeBSD.org>
27
+ */
28
+
29
+#ifdef HAVE_DIX_CONFIG_H
30
+#include <dix-config.h>
31
+#endif
32
+
33
+#include <sys/types.h>
34
+#include <sys/socket.h>
35
+#include <sys/sysctl.h>
36
+#include <sys/un.h>
37
+
38
+#include <ctype.h>
39
+#include <stdlib.h>
40
+#include <stdio.h>
41
+#include <stdarg.h>
42
+#include <stdbool.h>
43
+#include <unistd.h>
44
+
45
+#include "input.h"
46
+#include "inputstr.h"
47
+#include "hotplug.h"
48
+#include "config-backends.h"
49
+#include "os.h"
50
+
51
+#define DEVD_SOCK_PATH "/var/run/devd.pipe"
52
+
53
+#define DEVD_EVENT_ADD		'+'
54
+#define DEVD_EVENT_REMOVE	'-'
55
+
56
+static int sock_devd = -1;
57
+
58
+#if XORG_VERSION_CURRENT < 10800000
59
+enum {
60
+	ATTR_KEYBOARD,
61
+	ATTR_POINTER,
62
+	ATTR_JOYSTICK,
63
+	ATTR_TOUCHPAD,
64
+	ATTR_TOUCHSCREEN,
65
+};
66
+#endif
67
+
68
+struct hw_type {
69
+	const char *driver;
70
+	int flag;
71
+	const char *xdriver;
72
+};
73
+
74
+static struct hw_type hw_types[] = {
75
+	{ "ukbd", ATTR_KEYBOARD, "kdb" },
76
+	{ "atkbd", ATTR_KEYBOARD, "kdb" },
77
+	{ "ums", ATTR_POINTER, "mouse" },
78
+	{ "psm", ATTR_POINTER, "mouse" },
79
+	{ "uhid", ATTR_POINTER, "mouse" },
80
+	{ "joy", ATTR_JOYSTICK, NULL },
81
+	{ "atp", ATTR_TOUCHPAD, NULL },
82
+	{ "uep", ATTR_TOUCHSCREEN, NULL },
83
+	{ NULL, -1, NULL },
84
+};
85
+
86
+#if XORG_VERSION_CURRENT < 10800000
87
+static void
88
+add_option(InputOption **options, const char *key, const char *value)
89
+{
90
+    if (!value || *value == '\0')
91
+        return;
92
+
93
+    for (; *options; options = &(*options)->next)
94
+        ;
95
+    *options = calloc(sizeof(**options), 1);
96
+    if (!*options) /* Yeesh. */
97
+        return;
98
+    (*options)->key = xstrdup(key);
99
+    (*options)->value = xstrdup(value);
100
+    (*options)->next = NULL;
101
+}
102
+
103
+static void
104
+remove_device(DeviceIntPtr dev)
105
+{
106
+    /* this only gets called for devices that have already been added */
107
+    LogMessage(X_INFO, "config/devd: removing device %s\n", dev->name);
108
+
109
+    /* Call PIE here so we don't try to dereference a device that's
110
+     * already been removed. */
111
+    OsBlockSignals();
112
+    ProcessInputEvents();
113
+    DeleteInputDeviceRequest(dev);
114
+    OsReleaseSignals();
115
+}
116
+
117
+static bool
118
+device_is_duplicate(char *config_info)
119
+{
120
+    DeviceIntPtr dev;
121
+
122
+    for (dev = inputInfo.devices; dev; dev = dev->next)
123
+        if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
124
+            return true;
125
+
126
+    for (dev = inputInfo.off_devices; dev; dev = dev->next)
127
+        if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
128
+            return true;
129
+
130
+    return false;
131
+}
132
+
133
+#endif
134
+
135
+static bool
136
+sysctl_exists(const char *format, ...)
137
+{
138
+	va_list args;
139
+	char *name = NULL;
140
+	size_t len;
141
+	int ret;
142
+
143
+	if (format == NULL)
144
+		return false;
145
+
146
+	va_start(args, format);
147
+	vasprintf(&name, format, args);
148
+	va_end(args);
149
+
150
+	ret = sysctlbyname(name, NULL, &len, NULL, 0);
151
+
152
+	if (ret == -1)
153
+		len = 0;
154
+
155
+	free(name);
156
+	return (len > 0);
157
+}
158
+
159
+static char *
160
+sysctl_get_str(const char *format, ...)
161
+{
162
+	va_list args;
163
+	char *name = NULL;
164
+	char *dest = NULL;
165
+	size_t len;
166
+
167
+	if (format == NULL)
168
+		return NULL;
169
+
170
+	va_start(args, format);
171
+	vasprintf(&name, format, args);
172
+	va_end(args);
173
+
174
+	if (sysctlbyname(name, NULL, &len, NULL, 0) == 0) {
175
+		dest = malloc(len + 1);
176
+		if (sysctlbyname(name, dest, &len, NULL, 0) == 0)
177
+			dest[len] = '\0';
178
+		else {
179
+			free(dest);
180
+			dest = NULL;
181
+		}
182
+	}
183
+
184
+	free(name);
185
+	return dest;
186
+}
187
+
188
+static void
189
+device_added(char *line)
190
+{
191
+    char *walk;
192
+    char *path;
193
+    char *vendor;
194
+    char *product = NULL;
195
+    char *config_info = NULL;
196
+    InputOption *options = NULL;
197
+#if XORG_VERSION_CURRENT > 10800000
198
+    InputAttributes attrs = {};
199
+#else
200
+    InputOption *tmpo;
201
+#endif
202
+    DeviceIntPtr dev = NULL;
203
+    int i, rc;
204
+
205
+    walk = strchr(line, ' ');
206
+    if (walk != NULL)
207
+        walk[0] = '\0';
208
+
209
+    for (i = 0; hw_types[i].driver != NULL; i++) {
210
+        if (strncmp(line, hw_types[i].driver,
211
+                    strlen(hw_types[i].driver)) == 0 &&
212
+            isnumber(*(line + strlen(hw_types[i].driver)))) {
213
+#if XORG_VERSION_CURRENT > 10800000
214
+            attrs.flags |= hw_types[i].flag;
215
+#endif
216
+            break;
217
+        }
218
+    }
219
+    if (hw_types[i].driver == NULL) {
220
+        LogMessageVerb(X_INFO, 10, "config/devd: ignoring device %s\n", line);
221
+        return;
222
+    }
223
+
224
+#if XORG_VERSION_CURRENT < 10800000
225
+    if (hw_types[i].xdriver == NULL) {
226
+        LogMessageVerb(X_INFO, 10, "config/devd: ignoring device %s\n", line);
227
+        return;
228
+    }
229
+#endif
230
+    if (asprintf(&path, "/dev/%s", line) == -1)
231
+        return;
232
+
233
+#if XORG_VERSION_CURRENT < 10800000
234
+    options = calloc(sizeof(*options), 1);
235
+    if (!options)
236
+        return;
237
+
238
+    add_option(&options, "_source", "server/devd");
239
+#else
240
+    options =  input_option_new(NULL, "_source", "server/devd");
241
+    if (!options)
242
+        return;
243
+#endif
244
+
245
+    vendor = sysctl_get_str("dev.%s.%s.%%desc", hw_types[i].driver, line + strlen(hw_types[i].driver));
246
+    if (vendor == NULL) {
247
+#if XORG_VERSION_CURRENT > 10800000
248
+        attrs.vendor = strdup("(unnamed)");
249
+#endif
250
+    } else {
251
+        if ((product = strchr(vendor, ' ')) != NULL) {
252
+            product[0] = '\0';
253
+            product++;
254
+        }
255
+#if XORG_VERSION_CURRENT > 10800000
256
+        attrs.vendor = strdup(vendor);
257
+#endif
258
+        if (product != NULL && (walk = strchr(product, ',')) != NULL)
259
+            walk[0] = '\0';
260
+#if XORG_VERSION_CURRENT > 10800000
261
+        attrs.product = strdup(product != NULL ? product : "(unnamed)");
262
+	options = input_option_new(options, "name", product != NULL ? product : "(unnamed)");
263
+#else
264
+        add_option(&options, "name", product != NULL ? product : "(unnamed)");
265
+#endif
266
+    }
267
+#if XORG_VERSION_CURRENT > 10800000
268
+    attrs.usb_id = NULL;
269
+    options = input_option_new(options, "path", path);
270
+    options = input_option_new(options, "device", path);
271
+#else
272
+    add_option(&options, "path", path);
273
+    add_option(&options, "device", path);
274
+#endif
275
+
276
+#if XORG_VERSION_CURRENT < 10800000
277
+    add_option(&options, "driver", hw_types[i].xdriver);
278
+#endif
279
+
280
+    if (asprintf(&config_info, "devd:%s", line) == -1) {
281
+        config_info = NULL;
282
+        goto unwind;
283
+    }
284
+
285
+    if (device_is_duplicate(config_info)) {
286
+        LogMessage(X_WARNING, "config/devd: device %s already added. "
287
+                              "Ignoring.\n", product != NULL ? product : "(unnamed)");
288
+        goto unwind;
289
+    }
290
+
291
+#if XORG_VERSION_CURRENT < 10800000
292
+    add_option(&options, "config_info", config_info);
293
+#else
294
+    options = input_option_new(options, "config_info", config_info);
295
+#endif
296
+    LogMessage(X_INFO, "config/devd: Adding input device %s (%s)\n",
297
+               product != NULL ? product : "(unnamed)", path);
298
+
299
+#if XORG_VERSION_CURRENT > 10800000
300
+    rc = NewInputDeviceRequest(options, &attrs, &dev);
301
+#else
302
+    rc = NewInputDeviceRequest(options, &dev);
303
+#endif
304
+
305
+    if (rc != Success)
306
+        goto unwind;
307
+
308
+ unwind:
309
+    free(config_info);
310
+#if XORG_VERSION_CURRENT < 10800000
311
+    while ((tmpo = options)) {
312
+        options = tmpo->next;
313
+        free(tmpo->key);        /* NULL if dev != NULL */
314
+        free(tmpo->value);      /* NULL if dev != NULL */
315
+        free(tmpo);
316
+    }
317
+#else
318
+    input_option_free_list(&options);
319
+#endif
320
+
321
+#if XORG_VERSION_CURRENT > 10800000
322
+    free(attrs.usb_id);
323
+    free(attrs.product);
324
+    free(attrs.device);
325
+    free(attrs.vendor);
326
+#endif
327
+
328
+    return;
329
+}
330
+
331
+static void
332
+device_removed(char *line)
333
+{
334
+    char *walk;
335
+    char *value;
336
+#if XORG_VERSION_CURRENT < 10800000
337
+    DeviceIntPtr dev, next;
338
+#endif
339
+
340
+    walk = strchr(line, ' ');
341
+    if (walk != NULL)
342
+        walk[0] = '\0';
343
+
344
+    if (asprintf(&value, "devd:%s", line) == -1)
345
+        return;
346
+
347
+#if XORG_VERSION_CURRENT > 10800000
348
+    remove_devices("dev", value);
349
+#else
350
+    for (dev = inputInfo.devices; dev; dev = next) {
351
+        next = dev->next;
352
+        if (dev->config_info && strcmp(dev->config_info, value) == 0)
353
+            remove_device(dev);
354
+    }
355
+    for (dev = inputInfo.off_devices; dev; dev = next) {
356
+	next = dev->next;
357
+        if (dev->config_info && strcmp(dev->config_info, value) == 0)
358
+            remove_device(dev);
359
+    }
360
+#endif
361
+
362
+    free(value);
363
+}
364
+
365
+static ssize_t
366
+socket_getline(int fd, char **out)
367
+{
368
+	char *buf;
369
+	ssize_t ret, cap, sz = 0;
370
+	char c;
371
+
372
+	cap = 1024;
373
+	buf = malloc(cap * sizeof(char));
374
+	if (!buf)
375
+		return -1;
376
+
377
+	for (;;) {
378
+		ret = read(sock_devd, &c, 1);
379
+		if (ret < 1) {
380
+			free(buf);
381
+			return -1;
382
+		}
383
+
384
+		if (c == '\n')
385
+			break;
386
+
387
+		if (sz + 1 >= cap) {
388
+			cap *= 2;
389
+			buf = realloc(buf, cap *sizeof(char));
390
+		}
391
+		buf[sz] = c;
392
+		sz++;
393
+	}
394
+
395
+	buf[sz] = '\0';
396
+	if (sz > 0)
397
+		*out = buf;
398
+	else
399
+		free(buf);
400
+
401
+	return sz; /* number of bytes in the line, not counting the line break*/
402
+}
403
+
404
+static void
405
+wakeup_handler(pointer data, int err, pointer read_mask)
406
+{
407
+    char *line = NULL;
408
+
409
+    if (err < 0)
410
+        return;
411
+
412
+    if (FD_ISSET(sock_devd, (fd_set *)read_mask)) {
413
+        if (socket_getline(sock_devd, &line) < 0)
414
+            return;
415
+
416
+        switch(*line) {
417
+		case DEVD_EVENT_ADD:
418
+			device_added(line++);
419
+			break;
420
+		case DEVD_EVENT_REMOVE:
421
+			device_removed(line++);
422
+			break;
423
+		default:
424
+			break;
425
+	}
426
+	free(line);
427
+    }
428
+}
429
+
430
+static void
431
+block_handler(pointer data, struct timeval **tv, pointer read_mask)
432
+{
433
+}
434
+
435
+int
436
+config_devd_init(void)
437
+{
438
+    struct sockaddr_un devd;
439
+    char devicename[1024];
440
+    int i, j;
441
+
442
+    /* first scan the sysctl to determine the hardware if needed */
443
+
444
+    for (i = 0; hw_types[i].driver != NULL; i++) {
445
+        for (j = 0; sysctl_exists("dev.%s.%i.%%desc", hw_types[i].driver, j); j++) {
446
+            snprintf(devicename, 1024, "%s%i", hw_types[i].driver, j);
447
+            device_added(devicename);
448
+        }
449
+
450
+    }
451
+    sock_devd = socket(AF_UNIX, SOCK_STREAM, 0);
452
+    if (sock_devd < 0) {
453
+        ErrorF("config/devd: Fail opening stream socket");
454
+        return 0;
455
+    }
456
+
457
+    devd.sun_family = AF_UNIX;
458
+    strlcpy(devd.sun_path, DEVD_SOCK_PATH, sizeof(devd.sun_path));
459
+
460
+    if (connect(sock_devd, (struct sockaddr *) &devd, sizeof(struct sockaddr_un)) < 0) {
461
+        close(sock_devd);
462
+        ErrorF("config/devd: Fail to connect to devd");
463
+        return 0;
464
+    }
465
+
466
+    RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL);
467
+    AddGeneralSocket(sock_devd);
468
+
469
+    return 1;
470
+}
471
+
472
+void
473
+config_devd_fini(void)
474
+{
475
+    if (sock_devd < 0)
476
+        return;
477
+
478
+    RemoveGeneralSocket(sock_devd);
479
+    RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL);
480
+    close(sock_devd);
481
+}
(-)xorg-server/files/extra-devd (+52 lines)
Line 0 Link Here
1
--- config/config.c.orig	2013-09-19 20:20:55.000000000 +0300
2
+++ config/config.c	2013-09-19 20:23:16.000000000 +0300
3
@@ -56,6 +56,8 @@
4
     if (!config_wscons_init())
5
         ErrorF("[config] failed to initialise wscons\n");
6
 #endif
7
+    if (!config_devd_init())
8
+        ErrorF("[config] failed to initialise devd backend\n");
9
 }
10
 
11
 void
12
@@ -74,6 +76,7 @@
13
 #elif defined(CONFIG_WSCONS)
14
     config_wscons_fini();
15
 #endif
16
+    config_devd_fini();
17
 }
18
 
19
 static void
20
--- hw/xfree86/common/xf86Config.c.orig	2013-09-20 00:07:58.000000000 +0300
21
+++ hw/xfree86/common/xf86Config.c	2013-09-20 00:16:33.000000000 +0300
22
@@ -1371,15 +1371,17 @@
23
     }
24
 
25
     if (!xf86Info.forceInputDevices && !(foundPointer && foundKeyboard)) {
26
-#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS)
27
+#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS) || 1
28
         const char *config_backend;
29
 
30
 #if defined(CONFIG_HAL)
31
         config_backend = "HAL";
32
 #elif defined(CONFIG_UDEV)
33
         config_backend = "udev";
34
-#else
35
+#elif defined(CONFIG_WSCONS)
36
         config_backend = "wscons";
37
+#else
38
+        config_backend = "devd";
39
 #endif
40
         xf86Msg(X_INFO, "The server relies on %s to provide the list of "
41
                 "input devices.\n\tIf no devices become available, "
42
--- hw/xfree86/common/xf86Globals.c.orig	2013-09-20 00:11:46.000000000 +0300
43
+++ hw/xfree86/common/xf86Globals.c	2013-09-20 00:16:13.000000000 +0300
44
@@ -122,7 +122,7 @@
45
     .log = LogNone,
46
     .disableRandR = FALSE,
47
     .randRFrom = X_DEFAULT,
48
-#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS)
49
+#if defined(CONFIG_HAL) || defined(CONFIG_UDEV) || defined(CONFIG_WSCONS) || 1
50
     .forceInputDevices = FALSE,
51
     .autoAddDevices = TRUE,
52
     .autoEnableDevices = TRUE
(-)xorg-server/files/xhotplug.conf.in (+22 lines)
Line 0 Link Here
1
attach 200 {
2
    device-name "(joy|psm)[0-9]+";
3
    action "/usr/local/etc/rc.d/xhotplug add $device-name";
4
};
5
attach 200 {
6
    device-name "(atp|uep|uhid)[0-9]+";
7
    action "/usr/local/etc/rc.d/xhotplug add/usb $device-name $port.$devaddr";
8
};
9
attach 200 {
10
    device-name "ums[0-9]+";
11
    action "/etc/rc.d/moused quietstart $device-name";
12
    action "/usr/local/etc/rc.d/xhotplug add/usb $device-name $port.$devaddr";
13
};
14
detach 200 {
15
    device-name "(atp|joy|psm|uep|uhid)[0-9]+";
16
    action "/usr/local/etc/rc.d/xhotplug remove $device-name";
17
};
18
detach 200 {
19
    device-name "ums[0-9]+";
20
    action "/etc/rc.d/moused stop $device-name";
21
    action "/usr/local/etc/rc.d/xhotplug remove $device-name";
22
};
(-)xorg-server/files/xhotplug.in (+143 lines)
Line 0 Link Here
1
#!/bin/sh
2
#
3
# PROVIDE:	xhotplug
4
# REQUIRE:	moused cleanvar
5
6
devlist=/var/run/xorg-devpipe.list
7
devpipe=/var/run/xorg-devpipe.pipe
8
9
fmt_options() {
10
    /usr/bin/awk '
11
    function quote(str, suffix, i) {
12
      sub("= +", "=", str);
13
      sub(" +$", "", str);
14
      match(str, "=.*")
15
      if (RLENGTH <= 1) return
16
      for (i = 1; i <= length(str); i++) {
17
        c = substr(str, i, 1);
18
        if (c ~ /[a-zA-Z0-9=:._-]/) {
19
          printf "%s", c
20
        } else {
21
          printf "%%%02x", charmap[c]
22
        }
23
      }
24
    }
25
    BEGIN {
26
      for(i = 0; i < 256; i++)
27
        charmap[sprintf("%c", i)] = i
28
      for (i = 1; i <= ARGC; i++) {
29
        quote(ARGV[i])
30
        printf " "
31
      }
32
    }' "$@"
33
}
34
35
driver_options() {
36
    case "$1" in
37
    *kbd*) printf "driver=kbd flags=keyboard ";;
38
    atp*|psm*|ums*) printf "driver=mouse flags=pointer ";;
39
    joy*) printf "flags=joystick ";;
40
    uep*) printf "driver=egalax flags=touchscreen ";;
41
    esac
42
}
43
44
std_options() {
45
    local desc
46
    desc="`/sbin/sysctl -nq dev.${1%%[0-9]*}.${1##*[a-z]}.%desc`"
47
    [ -n "${desc%%,*}" ] && fmt_options "name=${desc%%,*}"
48
}
49
50
usb_options() {
51
    local desc line nl product product_id vendor vendor_id
52
    desc=`/usr/sbin/usbconfig -d "$1" dump_device_desc`
53
    nl=`printf '\nx'`
54
    nl=${nl%x}
55
    while line=${desc%%$nl*}; do
56
        case "$line" in
57
        *idVendor\ =*)
58
            vendor_id=${line#*= 0x}
59
            vendor_id=${vendor_id% }
60
            ;;
61
        *idProduct\ =*)
62
            product_id=${line#*= 0x}
63
            product_id=${product_id% }
64
            ;;
65
        *iManufacturer\ =*)
66
            vendor=${line#*<}
67
            vendor=${vendor%>*}
68
            [ "$vendor" = "no string" ] && vendor=
69
            ;;
70
        *iProduct\ =*)
71
            product=${line#*<}
72
            product=${product%>*}
73
            [ "$product" = "no string" ] && product=
74
            ;;
75
        esac
76
        [ "$desc" = "${desc#*$nl}" ] && break
77
        desc=${desc#*$nl}
78
    done
79
    fmt_options \
80
        "usb_id=$vendor_id:$product_id" \
81
        "vendor=$vendor" \
82
        "product=$product" \
83
        "name=$vendor $product"
84
}
85
86
send_message() {
87
    for socket in "$devpipe"*; do
88
        [ -S "$socket" ] && printf -- "%s" "$*" | /usr/bin/nc -w 5 -U "$socket"
89
    done
90
}
91
92
add_entry() {
93
    printf "%s\n" "$*" >> "$devlist"
94
    send_message "+$*"
95
}
96
97
remove_entry() {
98
    [ -f "$devlist" ] && /usr/bin/sed -EI '' "/^$1( |\$)/d" "$devlist"
99
    send_message "-$1"
100
}
101
102
case "$1" in
103
faststart|forcestart|onestart|quietstart|start)
104
    add_entry syscons driver=kbd device= flags=keyboard \
105
        name=System%20Keyboard product=syscons
106
    add_entry sysmouse driver=mouse flags=pointer \
107
        name=System%20Mouse product=sysmouse
108
    ;;
109
faststop|forcestop|onestop|quietstop|stop)
110
    rm -f "$devlist"
111
    ;;
112
add)
113
    device=$2
114
    shift 2
115
    add_entry "$device" \
116
        "`driver_options "$device"; std_options "$device"; fmt_options "$@"`"
117
    ;;
118
add/usb)
119
    device=$2
120
    usb=$3
121
    shift 3
122
    add_entry "$device" \
123
        "`driver_options "$device"; usb_options "$usb"; fmt_options "$@"`"
124
    ;;
125
remove)
126
    device=$2
127
    remove_entry "$device"
128
    ;;
129
list)
130
    [ -f "$devlist" ] && cat "$devlist"
131
    ;;
132
*)
133
    echo "unknown command: $*" 1>&2
134
    echo "usage:" 1>&2
135
    echo "  $0 start" 1>&2
136
    echo "  $0 stop" 1>&2
137
    echo "  $0 add <devname> [<option>=<value> ...]" 1>&2
138
    echo "  $0 add/usb <devname> <busnum>.<devaddr> [<option>=<value> ...]" 1>&2
139
    echo "  $0 remove <devname>" 1>&2
140
    echo "  $0 list" 1>&2
141
    exit 1
142
    ;;
143
esac
(-)xorg-server/pkg-plist (+2 lines)
Lines 8-13 Link Here
8
%%SUID%%@mode
8
%%SUID%%@mode
9
bin/cvt
9
bin/cvt
10
bin/gtf
10
bin/gtf
11
%%DEVD%%etc/devd/xhotplug.conf
12
%%DEVD%%etc/rc.d/xhotplug
11
include/xorg/BT.h
13
include/xorg/BT.h
12
include/xorg/IBM.h
14
include/xorg/IBM.h
13
include/xorg/TI.h
15
include/xorg/TI.h

Return to bug 183478