FreeBSD Bugzilla – Attachment 167594 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]
makes devd to hanle all known input devices and unknown in /dev/input/
patch-config_devd.c (text/plain), 21.84 KB, created by
Ivan Rozhuk
on 2016-03-01 08:02:02 UTC
(
hide
)
Description:
makes devd to hanle all known input devices and unknown in /dev/input/
Filename:
MIME Type:
Creator:
Ivan Rozhuk
Created:
2016-03-01 08:02:02 UTC
Size:
21.84 KB
patch
obsolete
>--- config/devd.c.orig 2015-05-19 19:41:49 UTC >+++ config/devd.c >@@ -0,0 +1,748 @@ >+/* >+ * Copyright (c) 2012 Baptiste Daroussin >+ * Copyright (c) 2013, 2014 Alex Kozlov >+ * Copyright (c) 2014 Robert Millan >+ * Copyright (c) 2014 Jean-Sebastien Pedron >+ * Copyright (c) 2015 - 2016 Rozhuk Ivan >+ * >+ * 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 <sys/mouse.h> >+#include <sys/consio.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 <string.h> >+#include <paths.h> >+ >+#include "input.h" >+#include "inputstr.h" >+#include "hotplug.h" >+#include "config-backends.h" >+#include "os.h" >+ >+ >+/* from: <linux/input.h> */ >+#define _IOC_READ IOC_OUT >+struct input_id { >+ uint16_t bustype; >+ uint16_t vendor; >+ uint16_t product; >+ uint16_t version; >+}; >+ >+#define EVIOCGID _IOR('E', 0x02, struct input_id) /* get device ID */ >+#define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ >+ >+/* from: <linux/joystick.h> */ >+#define JSIOCGNAME(len) _IOC(_IOC_READ, 'j', 0x13, len) /* get identifier string */ >+ >+/* WebCamD specific. */ >+#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) >+ >+ >+#define _PATH_DEV_LEN (sizeof(_PATH_DEV) - 1) >+#define DEVD_PATH_DEV "devd:" _PATH_DEV >+#define DEVD_PATH_DEV_LEN (sizeof(DEVD_PATH_DEV) - 1) >+ >+#define DEVD_SOCK_PATH _PATH_VARRUN "devd.pipe" >+ >+#define DEVD_EVENT_ADD '+' >+#define DEVD_EVENT_REMOVE '-' >+#define DEVD_EVENT_NOTIFY '!' >+ >+#define RECONNECT_DELAY (5 * 1000) >+ >+ >+#define is_meuqual(__v1, __v1sz, __v2, __v2sz) \ >+ ((__v1sz) == (__v2sz) && NULL != (__v1) && NULL != (__v2) && \ >+ 0 == memcmp((__v1), (__v2), (__v1sz))) >+ >+#define is_meuqual_cstr(__cstr, __v, __vsz) \ >+ is_meuqual(__cstr, (sizeof(__cstr) - 1), __v, __vsz) >+ >+#define is_de_euqual_cstr(__de, __cstr) \ >+ (NULL != (__de) && \ >+ is_meuqual((__de)->d_name, (__de)->d_namlen, __cstr, (sizeof(__cstr) - 1))) >+ >+#define devd_get_val_cstr(__cstr, __buf, __bufsz, __valsz) \ >+ devd_get_val((__buf), (__bufsz), __cstr, (sizeof(__cstr) - 1), \ >+ (__valsz)) >+ >+ >+static int devd_skt; >+static char devd_buf[4096]; >+static size_t devd_buf_used = 0; >+static int is_kbdmux = 0; >+OsTimerPtr rtimer; >+ >+ >+/* Input devices. */ >+typedef struct hw_type_s { >+ const char *dev_name; >+ size_t dev_name_size; >+ size_t path_offset; >+ int flags; >+ const char *xdriver; >+} hw_type_t, *hw_type_p; >+ >+/* xdriver can be set via config "InputClass" section. >+ * Do not set xdriver name if device have more than one >+ * xf86-input-* drivers. >+ * "input/event" can be hadled by: xf86-input-evdev and >+ * xf86-input-wacom, let user chooses. >+ */ >+static hw_type_t hw_types[] = { >+ { "ukbd", 4, 0, ATTR_KEYBOARD, "kbd" }, >+ { "atkbd", 5, 0, ATTR_KEYBOARD, "kbd" }, >+ { "kbdmux", 6, 0, ATTR_KEYBOARD, "kbd" }, >+ { "sysmouse", 8, 0, ATTR_POINTER, "mouse" }, >+ { "ums", 3, 0, ATTR_POINTER, "mouse" }, >+ { "psm", 3, 0, ATTR_POINTER, "mouse" }, >+ { "vboxguest", 9, 0, ATTR_POINTER, "vboxmouse" }, >+ { "joy", 3, 0, ATTR_JOYSTICK, NULL }, >+ { "atp", 3, 0, ATTR_TOUCHPAD, NULL }, >+ { "uep", 3, 0, ATTR_TOUCHSCREEN, NULL }, >+ { "input/event",5, 6, ATTR_TOUCHPAD, NULL }, >+ { "input/js", 2, 6, ATTR_JOYSTICK, NULL }, >+ { NULL, 0, 0, 0, NULL }, >+}; >+ >+/* Input devices paths. */ >+static hw_type_t hw_type_path[] = { >+ { "input/", 0, 6, 0, NULL }, >+ { NULL, 0, 0, 0, NULL }, >+}; >+ >+ >+ >+static hw_type_p >+get_dev_type_by_name(const char *dev_name, size_t dev_name_size) >+{ >+ size_t i; >+ >+ if (NULL == dev_name || 0 == dev_name_size) >+ return (NULL); >+ for (i = 0; NULL != hw_types[i].dev_name; i ++) { >+ if (dev_name_size >= (hw_types[i].dev_name_size + hw_types[i].path_offset) && >+ 0 == memcmp(dev_name, hw_types[i].dev_name, >+ (hw_types[i].path_offset + hw_types[i].dev_name_size))) { >+ return (&hw_types[i]); >+ } >+ } >+ return (NULL); >+} >+ >+static hw_type_p >+get_dev_type_by_path(const char *dev_name, size_t dev_name_size, >+ hw_type_p hw_type_cust) >+{ >+ size_t i; >+ >+ if (NULL == dev_name || 0 == dev_name_size || NULL == hw_type_cust) >+ return (NULL); >+ for (i = 0; NULL != hw_type_path[i].dev_name; i ++) { >+ if (dev_name_size <= hw_type_path[i].path_offset || >+ 0 != memcmp(dev_name, hw_type_path[i].dev_name, >+ hw_type_path[i].path_offset)) >+ continue; >+ /* Path in white list. */ >+ hw_type_cust->dev_name = dev_name; >+ hw_type_cust->path_offset = hw_type_path[i].path_offset; >+ for (i = hw_type_cust->path_offset; i < dev_name_size; i ++) { >+ if (isdigit(dev_name[i])) >+ break; >+ } >+ hw_type_cust->dev_name_size = (i - hw_type_cust->path_offset); >+ hw_type_cust->flags = hw_type_path[i].flags; >+ hw_type_cust->xdriver = hw_type_path[i].xdriver; >+ return (hw_type_cust); >+ } >+ return (NULL); >+} >+ >+static int >+is_kbdmux_enabled(void) >+{ >+ /* Xorg uses /dev/ttyv0 as a console device */ >+ /* const char device[]="/dev/console"; */ >+ int fd; >+ const char *device = _PATH_TTY "v0"; >+ keyboard_info_t info; >+ >+ fd = open(device, O_RDONLY); >+ if (0 > fd) >+ return (0); >+ if (-1 == ioctl(fd, KDGKBINFO, &info) || >+ 0 != memcmp(info.kb_name, "kbdmux", 6)) { >+ close(fd); >+ return (0); >+ } >+ close(fd); >+ return (1); >+} >+ >+static char * >+sysctl_get_str(const char *sysctlname, size_t *size_ret) >+{ >+ char *dest; >+ size_t len; >+ >+ if (NULL == sysctlname) >+ return (NULL); >+ if (0 != sysctlbyname(sysctlname, NULL, &len, NULL, 0)) >+ return (NULL); >+ dest = malloc(len + 4); >+ if (NULL == dest) >+ return (NULL); >+ if (0 != sysctlbyname(sysctlname, dest, &len, NULL, 0)) { >+ free(dest); >+ return (NULL); >+ } >+ dest[len] = 0; >+ if (NULL != size_ret) >+ (*size_ret) = len; >+ return (dest); >+} >+ >+static char * >+devd_get_val(char *buf, size_t buf_size, const char *val_name, >+ size_t val_name_size, size_t *val_size) >+{ >+ char *ret, *buf_end, *ptr; >+ >+ buf_end = (buf + buf_size); >+ for (ret = buf; ret != NULL && ret < buf_end;) { >+ ret = memmem(ret, (buf_end - ret), val_name, val_name_size); >+ if (ret == NULL) >+ return (NULL); >+ /* Found. */ >+ /* Check: space before or buf+1. */ >+ if ((buf + 1) < ret && ret[-1] != ' ') { >+ ret += val_name_size; >+ continue; >+ } >+ /* Check: = after name and size for value. */ >+ ret += val_name_size; >+ if ((ret + 1) >= buf_end) >+ return (NULL); >+ if ('=' != ret[0]) >+ continue; >+ ret ++; >+ break; >+ } >+ if (ret == NULL || val_size == NULL) >+ return (ret); >+ /* Calc value data size. */ >+ ptr = memchr(ret, ' ', (buf_end - ret)); >+ if (ptr == NULL) /* End of string/last value. */ >+ ptr = buf_end; >+ (*val_size) = (ptr - ret); >+ return (ret); >+} >+ >+static void >+device_added(const char *dev_name, size_t dev_name_size, int allow_no_device) >+{ >+ int fd; >+ InputOption *options = NULL; >+ InputAttributes attrs; >+ DeviceIntPtr dev_iptr = NULL; >+ keyboard_info_t kbdi; >+ mousehw_t mshw; >+ struct input_id iid; >+ char *dev_path, config_info[(PATH_MAX + 32)]; >+ char sysctlname[PATH_MAX], *sdata, *ptr_pid, *ptr_vid; >+ char pnp_usb_id[PATH_MAX], vendor[PATH_MAX], product[PATH_MAX]; >+ size_t sdata_size, pid_size, vid_size; >+ hw_type_t *hwtype, hwtype_cust; >+ unsigned short vid, pid; >+ >+ >+ if (NULL == dev_name || 0 == dev_name_size || PATH_MAX < dev_name_size) >+ return; >+ /* Make dev_name null ended string. */ >+ memcpy(config_info, DEVD_PATH_DEV, DEVD_PATH_DEV_LEN); >+ memcpy((config_info + DEVD_PATH_DEV_LEN), dev_name, dev_name_size); >+ config_info[(DEVD_PATH_DEV_LEN + dev_name_size)] = 0; >+ /* Set / update pointers to dev_name and dev_path. */ >+ dev_path = (config_info + 5); /* Skip: "devd:" */ >+ dev_name = (dev_path + _PATH_DEV_LEN); /* Skip: "/dev/" */ >+ >+ /* Is known input device or path? */ >+ hwtype = get_dev_type_by_name(dev_name, dev_name_size); >+ if (NULL == hwtype) { >+ hwtype = get_dev_type_by_path(dev_name, dev_name_size, >+ &hwtype_cust); >+ } >+ if (NULL == hwtype) /* Not found in white list. */ >+ return; >+ /* Init and set attributes. */ >+ memset(&attrs, 0, sizeof(attrs)); >+ attrs.device = dev_path; >+ attrs.flags = hwtype->flags; >+ >+ /* Skip keyboard devices if kbdmux is enabled */ >+ if (is_kbdmux && 0 == allow_no_device && (hwtype->flags & ATTR_KEYBOARD)) { >+ LogMessage(X_INFO, "config/devd: kbdmux is enabled, ignoring device %s\n", >+ dev_name); >+ return; >+ } >+ /* Skip duplicate devices. */ >+ if (device_is_duplicate(config_info)) { >+ LogMessage(X_WARNING, "config/devd: device %s already added. ignoring\n", >+ dev_path); >+ return; >+ } >+ >+ /* Try to open device. */ >+ fd = open(dev_path, O_RDONLY); >+ if (0 > fd) { >+ if (0 == (hwtype->flags & ATTR_KEYBOARD)) { >+ LogMessage(X_INFO, "config/devd: device %s already opened\n", >+ dev_path); >+ /* >+ * Fail if cannot open device, it breaks AllowMouseOpenFail, >+ * but it should not matter when config/devd enabled >+ */ >+ return; >+ } >+ if (0 == allow_no_device) { >+ /* >+ * There can be only one keyboard attached to console and >+ * it is already added. >+ */ >+ LogMessage(X_WARNING, "config/devd: console keyboard is " >+ "already added, ignoring %s\n", >+ dev_path); >+ return; >+ } >+ /* >+ * 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. >+ */ >+ goto skip_ioctl; >+ } >+ >+ /* Try to get device info via ioctl(). */ >+ if (-1 != ioctl(fd, KDGKBINFO, &kbdi)) { /* Is this keyboard? */ >+ memcpy(product, kbdi.kb_name, sizeof(kbdi.kb_name)); >+ attrs.product = product; >+ attrs.flags = ATTR_KEYBOARD; >+ LogMessage(X_INFO, "config/devd: detected keyboard: %s, kb_index=%i, kb_unit=%i, kb_type=%i, kb_config=%i\n", >+ kbdi.kb_name, kbdi.kb_index, kbdi.kb_unit, kbdi.kb_type, kbdi.kb_config); >+ } else if (-1 != ioctl(fd, MOUSE_GETHWINFO, &mshw)) { /* Is this mouse? */ >+#ifdef notyet /* FreeBSD mouse drivers does not return real vid+pid. */ >+ /* construct USB ID in lowercase hex - "0000:ffff" */ >+ snprintf(pnp_usb_id, sizeof(pnp_usb_id), "%04x:%04x", >+ mshw.hwid, mshw.model); >+ attrs.usb_id = pnp_usb_id; >+#endif >+ >+ switch (mshw.type) { >+ case MOUSE_MOUSE: >+ case MOUSE_TRACKBALL: >+ case MOUSE_STICK: >+ attrs.flags = ATTR_POINTER; >+ break; >+ case MOUSE_PAD: >+ attrs.flags = ATTR_TOUCHPAD; >+ break; >+ } >+ LogMessage(X_INFO, "config/devd: detected mouse: hwid=%04x, model=%04x, type=%04x, iftype=%04x, buttons=%04x\n", >+ mshw.hwid, mshw.model, mshw.type, mshw.iftype, mshw.buttons); >+ } else if (-1 != ioctl(fd, JSIOCGNAME((sizeof(product) - 1)), product)) { /* Is this joystick? */ >+ attrs.product = product; >+ attrs.flags = ATTR_JOYSTICK; >+ LogMessage(X_INFO, "config/devd: detected joystick: %s\n", >+ product); >+ } else if (-1 != ioctl(fd, EVIOCGID, &iid) && >+ -1 != ioctl(fd, EVIOCGNAME((sizeof(product) - 1)), product)) { /* Is this event? */ >+ /* construct USB ID in lowercase hex - "0000:ffff" */ >+ snprintf(pnp_usb_id, sizeof(pnp_usb_id), "%04x:%04x", >+ iid.vendor, iid.product); >+ attrs.usb_id = pnp_usb_id; >+ attrs.product = product; >+ attrs.flags = (ATTR_POINTER | ATTR_TABLET | ATTR_TOUCHPAD); >+ LogMessage(X_INFO, "config/devd: detected event: %s, bustype=%04x, vendor=%04x, product=%04x, version=%04x\n", >+ product, iid.bustype, iid.vendor, iid.product, iid.version); >+ } >+ >+ if (NULL == attrs.usb_id) { /* Is this webcamd device? */ >+ if (-1 != ioctl(fd, WEBCAMD_IOCTL_GET_USB_VENDOR_ID, &vid) && >+ -1 != ioctl(fd, WEBCAMD_IOCTL_GET_USB_PRODUCT_ID, &pid)) { >+ snprintf(pnp_usb_id, sizeof(pnp_usb_id), >+ "%04x:%04x", vid, pid); >+ attrs.usb_id = pnp_usb_id; >+ LogMessage(X_INFO, "config/devd: WebCamD device: %s\n", pnp_usb_id); >+ } >+ } >+ >+ close(fd); >+ >+skip_ioctl: >+ /* Try to get device info via sysctl(). */ >+ if (NULL == attrs.usb_id && NULL == attrs.pnp_id) { >+ snprintf(sysctlname, sizeof(sysctlname), "dev.%.*s.%s.%%pnpinfo", >+ (int)hwtype->dev_name_size, (hwtype->dev_name + hwtype->path_offset), >+ (dev_name + hwtype->path_offset + hwtype->dev_name_size)); >+ sdata = sysctl_get_str(sysctlname, &sdata_size); >+ if (NULL != sdata) { >+ ptr_vid = devd_get_val_cstr("vendor", >+ sdata, sdata_size, &vid_size); >+ ptr_pid = devd_get_val_cstr("product", >+ sdata, sdata_size, &pid_size); >+ if (NULL != ptr_vid && NULL != ptr_pid) { /* usb_id */ >+ ptr_vid[vid_size] = 0; >+ ptr_pid[pid_size] = 0; >+ snprintf(pnp_usb_id, sizeof(pnp_usb_id), >+ "%s:%s", ptr_vid, ptr_pid); >+ attrs.usb_id = pnp_usb_id; >+ LogMessage(X_INFO, "config/devd: usb_id: %s\n", pnp_usb_id); >+ } else { /* pnp_id */ >+ strlcpy(pnp_usb_id, sdata, sizeof(pnp_usb_id)); >+ attrs.pnp_id = pnp_usb_id; >+ } >+ free(sdata); >+ } >+ } >+ if (NULL == attrs.vendor || NULL == attrs.product) { >+ snprintf(sysctlname, sizeof(sysctlname), "dev.%.*s.%s.%%desc", >+ (int)hwtype->dev_name_size, (hwtype->dev_name + hwtype->path_offset), >+ (dev_name + hwtype->path_offset + hwtype->dev_name_size)); >+ sdata = sysctl_get_str(sysctlname, &sdata_size); >+ if (NULL != sdata) { >+ /* Vendor. */ >+ ptr_pid = memchr(sdata, ' ', sdata_size); >+ if (NULL != ptr_pid) >+ ptr_pid[0] = 0; >+ strlcpy(vendor, sdata, sizeof(vendor)); >+ attrs.vendor = vendor; >+ /* Product. */ >+ if (NULL == attrs.product && NULL != ptr_pid) { >+ ptr_pid ++; >+ ptr_vid = memchr(ptr_pid, ',', >+ (sdata_size - (ptr_pid - sdata))); >+ if (NULL != ptr_vid) >+ ptr_vid[0] = 0; >+ strlcpy(product, ptr_pid, sizeof(product)); >+ attrs.product = product; >+ } else { >+ product[0] = 0; >+ } >+ free(sdata); >+ LogMessage(X_INFO, "config/devd: vendor: %s, product: %s\n", vendor, product); >+ } >+ } >+ >+ /* Init options. */ >+ options = input_option_new(NULL, "_source", "server/devd"); >+ if (NULL == options) >+ goto err_out; >+ >+ options = input_option_new(options, "config_info", config_info); >+ if (NULL == options) >+ goto err_out; >+ >+ options = input_option_new(options, "name", >+ ((NULL != attrs.product) ? attrs.product : dev_name)); >+ if (NULL == options) >+ goto err_out; >+ >+ if (fd >= 0) { >+ options = input_option_new(options, "device", dev_path); >+ if (NULL == options) >+ goto err_out; >+ } >+ >+ if (NULL != hwtype->xdriver) { >+ options = input_option_new(options, "driver", hwtype->xdriver); >+ if (NULL == options) >+ goto err_out; >+ } >+ >+ LogMessage(X_INFO, "config/devd: adding input device %s\n", dev_path); >+ NewInputDeviceRequest(options, &attrs, &dev_iptr); >+ goto done; >+ >+err_out: >+ LogMessage(X_INFO, "config/devd: error adding device '%s'\n", >+ dev_path); >+done: >+ input_option_free_list(&options); >+} >+ >+static void >+device_removed(const char *dev_name, size_t dev_name_size) >+{ >+ char config_info[(PATH_MAX + 32)]; >+ hw_type_t hwtype_cust; >+ >+ if (NULL == dev_name || 0 == dev_name_size || PATH_MAX < dev_name_size) >+ return; >+ if (NULL == get_dev_type_by_name(dev_name, dev_name_size) && >+ NULL == get_dev_type_by_path(dev_name, dev_name_size, &hwtype_cust)) >+ return; /* Device not in list - unknown. */ >+ memcpy(config_info, DEVD_PATH_DEV, DEVD_PATH_DEV_LEN); >+ memcpy((config_info + DEVD_PATH_DEV_LEN), dev_name, dev_name_size); >+ config_info[(DEVD_PATH_DEV_LEN + dev_name_size)] = 0; >+ >+ /* Skip non added devices. */ >+ if (device_is_duplicate(config_info)) { >+ LogMessage(X_INFO, "config/devd: removing input device '%s'\n", >+ (config_info + DEVD_PATH_DEV_LEN)); >+ } >+ remove_devices("devd", config_info); >+} >+ >+ >+static void >+disconnect_devd(int sock) >+{ >+ if (0 > sock) >+ return; >+ RemoveGeneralSocket(sock); >+ close(sock); >+} >+ >+static int >+connect_devd(void) >+{ >+ int sock; >+ struct sockaddr_un devd; >+ >+ sock = socket(AF_UNIX, SOCK_STREAM, 0); >+ if (0 > sock) { >+ LogMessage(X_ERROR, "config/devd: fail opening stream socket\n"); >+ return (-1); >+ } >+ >+ devd.sun_family = AF_UNIX; >+ memcpy(devd.sun_path, DEVD_SOCK_PATH, sizeof(DEVD_SOCK_PATH)); >+ if (0 > connect(sock, (struct sockaddr*)&devd, sizeof(devd))) { >+ 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, void *arg) >+{ >+ devd_buf_used = 0; >+ devd_skt = connect_devd(); >+ if (-1 == devd_skt) /* Try again after RECONNECT_DELAY */ >+ return (RECONNECT_DELAY); >+ TimerFree(rtimer); >+ rtimer = NULL; >+ LogMessage(X_INFO, "config/devd: reopening devd socket\n"); >+ >+ return (0); >+} >+ >+static void >+wakeup_handler(void *data, int err, void *read_mask) >+{ >+ int error; >+ char *ptr, *line, *val, *cdev; >+ size_t line_size, val_size, cdev_size; >+ ssize_t ios; >+ >+ if (0 > err) >+ return; >+ if (!FD_ISSET(devd_skt, (fd_set*)read_mask)) >+ return; >+ /* Read new data. */ >+ for (;;) { >+ ios = recv(devd_skt, (devd_buf + devd_buf_used), >+ (sizeof(devd_buf) - devd_buf_used), MSG_DONTWAIT); >+ if (0 < ios) { /* Read OK. */ >+ devd_buf_used += ios; >+ continue; /* Try to read more. */ >+ } >+ /* Something wrong. */ >+ error = errno; >+ if (error == EAGAIN) >+ break; /* All avaible data readed. */ >+ if (error == EINTR) >+ continue; >+ if (sizeof(devd_buf) == devd_buf_used) { /* Message to long, reset buf. */ >+ devd_buf_used = 0; >+ continue; >+ } >+ /* devd socket is lost */ >+ disconnect_devd(devd_skt); >+ rtimer = TimerSet(NULL, 0, 1, reconnect_handler, NULL); >+ LogMessage(X_WARNING, "config/devd: devd socket read error: %i - %s\n", error, strerror(error)); >+ return; >+ } >+ ptr = memchr(devd_buf, '\n', devd_buf_used); >+ if (NULL == ptr) >+ return; >+ >+ /* Process data. */ >+ line = (devd_buf + 1); >+ for (;;) { >+ line_size = (ptr - line); >+ if (DEVD_EVENT_NOTIFY != (*(line - 1))) >+ goto move_next_event; /* Handle only notify. */ >+ /* Check: is system=DEVFS. */ >+ val = devd_get_val_cstr("system", line, line_size, &val_size); >+ if (!is_meuqual_cstr("DEVFS", val, val_size)) >+ goto move_next_event; >+ /* Check: is subsystem=CDEV. */ >+ val = devd_get_val_cstr("subsystem", line, line_size, &val_size); >+ if (!is_meuqual_cstr("CDEV", val, val_size)) >+ goto move_next_event; >+ /* Get device name. */ >+ cdev = devd_get_val_cstr("cdev", line, line_size, &cdev_size); >+ if (NULL == cdev) >+ goto move_next_event; >+ /* Get event type. */ >+ val = devd_get_val_cstr("type", line, line_size, &val_size); >+ if (is_meuqual_cstr("CREATE", val, val_size)) { >+ device_added(cdev, cdev_size, 0); >+ } else if (is_meuqual_cstr("DESTROY", val, val_size)) { >+ device_removed(cdev, cdev_size); >+ } >+ >+move_next_event: >+ line += (line_size + 2); /* Skip '\n' and event type byte. */ >+ line_size = (line - devd_buf); >+ if (devd_buf_used <= line_size) { >+ devd_buf_used = 0; >+ return; >+ } >+ ptr = memchr(line, '\n', (devd_buf_used - line_size)); >+ if (NULL == ptr) >+ break; >+ } >+ /* Save line without end marker. */ >+ devd_buf_used -= (line_size - 1); >+ memmove(devd_buf, (line - 1), devd_buf_used); >+} >+ >+static void >+block_handler(void *data, struct timeval **tv, void *read_mask) >+{ >+} >+ >+int >+config_devd_init(void) >+{ >+ size_t i, j, dir_cnt, sdir_cnt, tm; >+ char devicename[PATH_MAX]; >+ struct dirent *de, **namelist, *sde, **snamelist; >+ >+ LogMessage(X_INFO, "config/devd: probing input devices...\n"); >+ >+ /* >+ * Add fake keyboard and give up on keyboards management >+ * if kbdmux is enabled >+ */ >+ is_kbdmux = is_kbdmux_enabled(); >+ if (is_kbdmux) >+ device_added("kbdmux0", 7, 1); >+ >+ /* Scan /dev/ for devices. */ >+ dir_cnt = scandir(_PATH_DEV, &namelist, 0, alphasort); >+ for (i = 0; i < dir_cnt; i ++) { >+ de = namelist[i]; >+ if (is_de_euqual_cstr(de, ".") || >+ is_de_euqual_cstr(de, "..")) { >+ free(de); >+ continue; >+ } >+ if (DT_DIR != de->d_type) { >+ device_added(de->d_name, de->d_namlen, 0); >+ } else { /* Sub folder. */ >+ snprintf(devicename, sizeof(devicename), >+ _PATH_DEV "%s", de->d_name); >+ sdir_cnt = scandir(devicename, &snamelist, 0, alphasort); >+ for (j = 0; j < sdir_cnt; j ++) { >+ sde = snamelist[j]; >+ if (!is_de_euqual_cstr(sde, ".") && >+ !is_de_euqual_cstr(sde, "..") && >+ DT_DIR != sde->d_type) { >+ tm = snprintf(devicename, sizeof(devicename), >+ "%s/%s", de->d_name, sde->d_name); >+ device_added(devicename, tm, 0); >+ } >+ free(sde); >+ } >+ free(snamelist); >+ } >+ free(de); >+ } >+ free(namelist); >+ >+ devd_buf_used = 0; >+ devd_skt = connect_devd(); >+ if (-1 == devd_skt) >+ return (0); >+ >+ /* 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(devd_skt); >+ >+ 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