FreeBSD Bugzilla – Attachment 161035 Details for
Bug 196678
x11-servers/xorg-server: Update to 1.20.7 + make config/devd recognize /dev/input/eventX from multimedia/webcamd
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Devd file for Xorg server
patch-config_devd.c (text/plain), 13.47 KB, created by
Hans Petter Selasky
on 2015-09-14 08:57:09 UTC
(
hide
)
Description:
Devd file for Xorg server
Filename:
MIME Type:
Creator:
Hans Petter Selasky
Created:
2015-09-14 08:57:09 UTC
Size:
13.47 KB
patch
obsolete
>--- config/devd.c.orig 2015-09-14 10:51:06.986114000 +0200 >+++ config/devd.c 2015-09-14 10:53:12.523679000 +0200 >@@ -0,0 +1,578 @@ >+/* >+ * Copyright (c) 2012 Baptiste Daroussin >+ * Copyright (c) 2013, 2014 Alex Kozlov >+ * Copyright (c) 2014 Robert Millan >+ * Copyright (c) 2014 Jean-Sebastien Pedron >+ * >+ * 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/kbio.h> >+#include <sys/socket.h> >+#include <sys/stat.h> >+#include <sys/sysctl.h> >+#include <sys/un.h> >+ >+#include <ctype.h> >+#include <dirent.h> >+#include <errno.h> >+#include <fcntl.h> >+#include <stdlib.h> >+#include <stdio.h> >+#include <stdbool.h> >+#include <unistd.h> >+#include <paths.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 RECONNECT_DELAY (5 * 1000) >+ >+static int sock_devd; >+static bool is_kbdmux = false; >+OsTimerPtr rtimer; >+ >+struct hw_type { >+ const char *driver; >+ int flag; >+ const char *xdriver; >+ const char *sysctldesc; >+}; >+ >+static const struct hw_type hw_types0[] = { >+ { _PATH_DEV "sysmouse", ATTR_POINTER, "mouse", NULL }, >+ { NULL, 0, NULL, NULL }, >+}; >+ >+static const struct hw_type hw_types1[] = { >+ { _PATH_DEV "ukbd%d", ATTR_KEYBOARD, "kbd", "dev.ukbd.%d.%%desc" }, >+ { _PATH_DEV "atkbd%d", ATTR_KEYBOARD, "kbd", "dev.atkbd.%d.%%desc" }, >+ { _PATH_DEV "kbdmux%d", ATTR_KEYBOARD, "kbd", NULL }, >+ { _PATH_DEV "ums%d", ATTR_POINTER, "mouse", "dev.ums.%d.%%desc" }, >+ { _PATH_DEV "psm%d", ATTR_POINTER, "mouse", "dev.psm.%d.%%desc" }, >+ { _PATH_DEV "joy%d", ATTR_JOYSTICK, "mouse", "dev.joy.%d.%%desc" }, >+ { _PATH_DEV "atp%d", ATTR_TOUCHPAD, "mouse", "dev.atp.%d.%%desc" }, >+ { _PATH_DEV "wsp%d", ATTR_TOUCHPAD, "mouse", "dev.wsp.%d.%%desc" }, >+ { _PATH_DEV "uep%d", ATTR_TOUCHSCREEN, "mouse", "dev.uep.%d.%%desc" }, >+ { _PATH_DEV "vboxguest", ATTR_POINTER, "vboxmouse", NULL }, >+ { _PATH_DEV "input/event%d", ATTR_TOUCHPAD, "evdev", NULL }, >+ { NULL, 0, NULL, NULL }, >+}; >+ >+static void >+get_usb_id(char **pptr, int fd) >+{ >+ unsigned short vendor; >+ unsigned short product; >+ unsigned int speed; >+#define WEBCAMD_IOCTL_GET_USB_VENDOR_ID _IOR('q', 250, unsigned short) >+#define WEBCAMD_IOCTL_GET_USB_PRODUCT_ID _IOR('q', 251, unsigned short) >+#define WEBCAMD_IOCTL_GET_USB_SPEED _IOR('q', 252, unsigned int) >+ if (ioctl(fd, WEBCAMD_IOCTL_GET_USB_VENDOR_ID, &vendor) == 0 && >+ ioctl(fd, WEBCAMD_IOCTL_GET_USB_PRODUCT_ID, &product) == 0 && >+ ioctl(fd, WEBCAMD_IOCTL_GET_USB_SPEED, &speed) == 0) { >+ if (asprintf(pptr, "%04x:%04x", vendor, product) == -1) >+ *pptr = NULL; >+ } >+} >+ >+static const char * >+skip_path_dev(const char *ptr) >+{ >+ if (strstr(ptr, _PATH_DEV) == ptr) >+ ptr += strlen(_PATH_DEV); >+ return (ptr); >+} >+ >+static char * >+sysctl_get_str(const char *sysctlname) >+{ >+ char *dest = NULL; >+ size_t len; >+ >+ if (sysctlname == NULL) >+ return NULL; >+ >+ if (sysctlbyname(sysctlname, NULL, &len, NULL, 0) == 0) { >+ dest = malloc(len + 1); >+ if (dest) { >+ if (sysctlbyname(sysctlname, dest, &len, NULL, 0) == 0) >+ dest[len] = '\0'; >+ else { >+ free(dest); >+ dest = NULL; >+ } >+ } >+ } >+ >+ return dest; >+} >+ >+static void >+device_added(const char *devicename, bool allow_no_device) >+{ >+ InputAttributes attrs = { }; >+ InputOption *options = NULL; >+ char *config_info = NULL; >+ DeviceIntPtr dev = NULL; >+ struct hw_type hw_type; >+ char *product = NULL; >+ char sysctlname[64]; >+ char *vendor = NULL; >+ int unit = 0; >+ int fd = -1; >+ char *walk; >+ int i; >+ >+ for (i = 0; hw_types0[i].driver != NULL; i++) { >+ if (strcmp(devicename, hw_types0[i].driver) == 0) { >+ hw_type = hw_types0[i]; >+ goto found; >+ } >+ } >+ for (i = 0; hw_types1[i].driver != NULL; i++) { >+ if (sscanf(devicename, hw_types1[i].driver, &unit) == 1) { >+ hw_type = hw_types1[i]; >+ goto found; >+ } >+ } >+ goto ignore; >+ >+found: >+ if (hw_type.xdriver == NULL) >+ goto ignore; >+ >+ /* set flags, if any */ >+ attrs.flags |= hw_type.flag; >+ >+ if (strcmp(hw_type.xdriver, "kbd") == 0) { >+ bool match = (strstr(hw_type.driver, >+ _PATH_DEV "kbdmux") == hw_type.driver); >+ >+ if (is_kbdmux) { >+ if (!match) >+ goto ignore; >+ } else { >+ if (match) >+ goto ignore; >+ } >+ } >+ >+ options = input_option_new(NULL, "_source", "server/devd"); >+ if (options == NULL) >+ goto error; >+ >+ if (hw_type.sysctldesc != NULL) { >+ snprintf(sysctlname, sizeof(sysctlname), >+ hw_type.sysctldesc, unit); >+ vendor = sysctl_get_str(sysctlname); >+ } >+ >+ if (vendor == NULL) { >+ options = input_option_new(options, "name", >+ skip_path_dev(devicename)); >+ } 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 != NULL) { >+ attrs.product = strdup(product); >+ options = input_option_new(options, >+ "name", product); >+ } else { >+ options = input_option_new(options, >+ "name", "Unknown"); >+ } >+ } >+ attrs.device = strdup(devicename); >+ >+ fd = open(devicename, O_RDONLY); >+ if (fd > -1) { >+ get_usb_id(&attrs.usb_id, fd); >+ close(fd); >+ options = input_option_new(options, "device", devicename); >+ if (options == NULL) >+ goto error; >+ } else if (allow_no_device) { >+ /* >+ * Don't pass "device" option if the keyboard is >+ * already attached to the console (ie. open() fails). >+ * This would activate a special logic in >+ * xf86-input-keyboard. Prevent any other attached to >+ * console keyboards being processed. There can be >+ * only one such device. >+ */ >+ } else { >+ goto ignore; >+ } >+ >+ options = input_option_new(options, "driver", hw_type.xdriver); >+ if (options == NULL) >+ goto error; >+ >+ if (asprintf(&config_info, "devd:%s", >+ skip_path_dev(devicename)) == -1) { >+ config_info = NULL; >+ goto error; >+ } >+ >+ if (device_is_duplicate(config_info)) >+ goto duplicate; >+ >+ options = input_option_new(options, "config_info", config_info); >+ if (options == NULL) >+ goto error; >+ >+ LogMessage(X_INFO, "config/devd: adding input device '%s'\n", >+ devicename); >+ >+ NewInputDeviceRequest(options, &attrs, &dev); >+ goto done; >+ >+duplicate: >+ LogMessage(X_WARNING, "config/devd: device '%s' already " >+ "added. Ignoring\n", devicename); >+ goto done; >+ >+error: >+ LogMessage(X_INFO, "config/devd: error adding device '%s'\n", >+ devicename); >+ goto done; >+ >+ignore: >+ LogMessage(X_INFO, "config/devd: ignoring device '%s'\n", >+ devicename); >+ goto done; >+ >+done: >+ free(config_info); >+ input_option_free_list(&options); >+ free(attrs.usb_id); >+ free(attrs.product); >+ free(attrs.device); >+ free(attrs.vendor); >+ free(vendor); >+} >+ >+static void >+devpath_scan_sub(char *path, int off, int rem) >+{ >+ struct dirent *entry; >+ DIR *dp; >+ >+ if ((dp = opendir(path)) == NULL) { >+ LogMessage(X_INFO, "Cannot open directory '%s'\n", path); >+ return; >+ } >+ while ((entry = readdir(dp)) != NULL) { >+ int len = strlen(entry->d_name); >+ if (len > rem) >+ continue; >+ strcpy(path + off, entry->d_name); >+ off += len; >+ rem -= len; >+ switch (entry->d_type) { >+ case DT_DIR: >+ if (strcmp(entry->d_name, ".") == 0 || >+ strcmp(entry->d_name, "..") == 0) >+ break; >+ if (rem < 1) >+ break; >+ path[off] = '/'; >+ path[off+1] = '\0'; >+ off++; >+ rem--; >+ /* recurse */ >+ devpath_scan_sub(path, off, rem); >+ off--; >+ rem++; >+ break; >+ case DT_SOCK: >+ case DT_FIFO: >+ case DT_LNK: >+ case DT_CHR: >+ /* add device, if any */ >+ device_added(path, false); >+ break; >+ default: >+ break; >+ } >+ off -= len; >+ rem += len; >+ } >+ closedir(dp); >+} >+ >+static void >+devpath_scan(void) >+{ >+ char path[PATH_MAX + 1]; >+ >+ strlcpy(path, _PATH_DEV, sizeof(path)); >+ >+ devpath_scan_sub(path, strlen(path), PATH_MAX - strlen(path)); >+} >+ >+static void >+device_removed(char *devicename) >+{ >+ char *config_info; >+ >+ if (asprintf(&config_info, "devd:%s", >+ skip_path_dev(devicename)) == -1) >+ return; >+ >+ if (device_is_duplicate(config_info)) { >+ LogMessage(X_INFO, "config/devd: removing input device '%s'\n", >+ devicename); >+ } >+ remove_devices("devd", config_info); >+ >+ free(config_info); >+} >+ >+static bool is_kbdmux_enabled(void) >+{ >+ /* Xorg uses /dev/ttyv0 as a console device */ >+ static const char device[]= { _PATH_DEV "ttyv0" }; >+ keyboard_info_t info; >+ int fd; >+ >+ fd = open(device, O_RDONLY); >+ >+ if (fd < 0) >+ return false; >+ >+ if (ioctl(fd, KDGKBINFO, &info) == -1) { >+ close(fd); >+ return false; >+ } >+ >+ close(fd); >+ >+ if (!strncmp(info.kb_name, "kbdmux", 6)) >+ return true; >+ >+ return false; >+} >+ >+static void >+disconnect_devd(int sock) >+{ >+ if (sock >= 0) { >+ RemoveGeneralSocket(sock); >+ close(sock); >+ } >+} >+ >+static int >+connect_devd(void) >+{ >+ struct sockaddr_un devd; >+ int sock; >+ >+ sock = socket(AF_UNIX, SOCK_STREAM, 0); >+ if (sock < 0) { >+ LogMessage(X_ERROR, "config/devd: fail opening stream socket\n"); >+ return -1; >+ } >+ >+ devd.sun_family = AF_UNIX; >+ strlcpy(devd.sun_path, DEVD_SOCK_PATH, sizeof(devd.sun_path)); >+ >+ if (connect(sock, (struct sockaddr *) &devd, sizeof(devd)) < 0) { >+ close(sock); >+ LogMessage(X_ERROR, "config/devd: fail to connect to devd\n"); >+ return -1; >+ } >+ >+ AddGeneralSocket(sock); >+ >+ return sock; >+} >+ >+static CARD32 >+reconnect_handler(OsTimerPtr timer, CARD32 time, pointer arg) >+{ >+ int newsock; >+ >+ if ((newsock = connect_devd()) > 0) { >+ sock_devd = newsock; >+ TimerFree(rtimer); >+ rtimer = NULL; >+ LogMessage(X_INFO, "config/devd: reopening devd socket\n"); >+ return 0; >+ } >+ >+ /* Try again after RECONNECT_DELAY */ >+ return RECONNECT_DELAY; >+} >+ >+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 < 0) { >+ if (errno == EINTR) >+ continue; >+ free(buf); >+ return -1; >+ /* EOF - devd socket is lost */ >+ } else if (ret == 0) { >+ disconnect_devd(sock_devd); >+ rtimer = TimerSet(NULL, 0, 1, reconnect_handler, NULL); >+ LogMessage(X_WARNING, "config/devd: devd socket is lost\n"); >+ 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); >+ >+ /* Number of bytes in the line, not counting the line break */ >+ return sz; >+} >+ >+static void >+wakeup_handler(void *data, int err, void *read_mask) >+{ >+ static const char cdev_create[] = { "!system=DEVFS subsystem=CDEV type=CREATE cdev=" }; >+ static const char cdev_destroy[] = { "!system=DEVFS subsystem=CDEV type=DESTROY cdev=" }; >+ static const char cdev_path[] = { _PATH_DEV }; >+ char *line = NULL; >+ char *devicename; >+ char *walk; >+ >+ if (err < 0) >+ return; >+ >+ if (FD_ISSET(sock_devd, (fd_set *) read_mask)) { >+ if (socket_getline(sock_devd, &line) < 0) >+ return; >+ if (strstr(line, cdev_create) == line) { >+ devicename = line + strlen(cdev_create) - strlen(cdev_path); >+ memcpy(devicename, cdev_path, strlen(cdev_path)); >+ walk = strchr(devicename, ' '); >+ if (walk != NULL) >+ walk[0] = '\0'; >+ device_added(devicename, false); >+ } else if (strstr(line, cdev_destroy) == line) { >+ devicename = line + strlen(cdev_destroy) - strlen(cdev_path); >+ memcpy(devicename, cdev_path, strlen(cdev_path)); >+ walk = strchr(devicename, ' '); >+ if (walk != NULL) >+ walk[0] = '\0'; >+ device_removed(devicename); >+ } >+ free(line); >+ } >+} >+ >+static void >+block_handler(void *data, struct timeval **tv, void *read_mask) >+{ >+} >+ >+int >+config_devd_init(void) >+{ >+ LogMessage(X_INFO, "config/devd: probing input devices...\n"); >+ >+ /* Check if kbdmux is enabled */ >+ is_kbdmux = is_kbdmux_enabled(); >+ >+ /* Try to add kbdmux device first */ >+ if (is_kbdmux) >+ device_added(_PATH_DEV "kbdmux0", true); >+ >+ /* Connect to devd, so that we don't loose any events */ >+ if ((sock_devd = connect_devd()) < 0) >+ return 0; >+ >+ /* Scan what is currently connected */ >+ devpath_scan(); >+ >+ /* Register wakeup handler */ >+ RegisterBlockAndWakeupHandlers(block_handler, >+ wakeup_handler, NULL); >+ >+ return 1; >+} >+ >+void >+config_devd_fini(void) >+{ >+ LogMessage(X_INFO, "config/devd: terminating backend...\n"); >+ >+ if (rtimer) { >+ TimerFree(rtimer); >+ rtimer = NULL; >+ } >+ >+ disconnect_devd(sock_devd); >+ >+ RemoveBlockAndWakeupHandlers(block_handler, >+ wakeup_handler, NULL); >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 196678
:
151548
|
151549
|
160696
|
160697
|
161034
|
161035
|
166727
|
167354
|
167426
|
167594
|
172378
|
175616
|
179892
|
180700
|
180710
|
180880
|
191592
|
195909
|
196037
|
197417
|
198703
|
203086
|
209380
|
211620
|
211740
|
211748
|
211749
|
211907