From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- xorg-server/config/udev.c | 670 +++++++++++++++++++++++----------------------- 1 file changed, 335 insertions(+), 335 deletions(-) (limited to 'xorg-server/config') diff --git a/xorg-server/config/udev.c b/xorg-server/config/udev.c index 63eb83605..e7383dc36 100644 --- a/xorg-server/config/udev.c +++ b/xorg-server/config/udev.c @@ -1,335 +1,335 @@ -/* - * Copyright © 2009 Julien Cristau - * - * 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: Julien Cristau - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include - -#include "input.h" -#include "inputstr.h" -#include "hotplug.h" -#include "config-backends.h" -#include "os.h" - -#define UDEV_XKB_PROP_KEY "xkb" - -#define LOG_PROPERTY(path, prop, val) \ - LogMessageVerb(X_INFO, 10, \ - "config/udev: getting property %s on %s " \ - "returned \"%s\"\n", \ - (prop), (path), (val) ? (val) : "(null)") -#define LOG_SYSATTR(path, attr, val) \ - LogMessageVerb(X_INFO, 10, \ - "config/udev: getting attribute %s on %s " \ - "returned \"%s\"\n", \ - (attr), (path), (val) ? (val) : "(null)") - -static struct udev_monitor *udev_monitor; - -static void -device_added(struct udev_device *udev_device) -{ - const char *path, *name = NULL; - char *config_info = NULL; - const char *syspath; - const char *tags_prop; - const char *key, *value, *tmp; - InputOption *options = NULL, *tmpo; - InputAttributes attrs = {}; - DeviceIntPtr dev = NULL; - struct udev_list_entry *set, *entry; - struct udev_device *parent; - int rc; - - path = udev_device_get_devnode(udev_device); - - syspath = udev_device_get_syspath(udev_device); - - if (!path || !syspath) - return; - - if (!udev_device_get_property_value(udev_device, "ID_INPUT")) { - LogMessageVerb(X_INFO, 10, - "config/udev: ignoring device %s without " - "property ID_INPUT set\n", - path); - return; - } - - options = calloc(sizeof(*options), 1); - if (!options) - return; - - options->key = strdup("_source"); - options->value = strdup("server/udev"); - if (!options->key || !options->value) - goto unwind; - - parent = udev_device_get_parent(udev_device); - if (parent) { - const char *ppath = udev_device_get_devnode(parent); - const char *product = udev_device_get_property_value(parent, "PRODUCT"); - const char *pnp_id = udev_device_get_sysattr_value(parent, "id"); - unsigned int usb_vendor, usb_model; - - name = udev_device_get_sysattr_value(parent, "name"); - LOG_SYSATTR(ppath, "name", name); - if (!name) { - name = udev_device_get_property_value(parent, "NAME"); - LOG_PROPERTY(ppath, "NAME", name); - } - - if (pnp_id) - attrs.pnp_id = strdup(pnp_id); - LOG_SYSATTR(ppath, "id", pnp_id); - - /* construct USB ID in lowercase hex - "0000:ffff" */ - if (product && sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) { - if (asprintf(&attrs.usb_id, "%04x:%04x", usb_vendor, usb_model) - == -1) - attrs.usb_id = NULL; - else - LOG_PROPERTY(path, "PRODUCT", product); - } - } - if (!name) - name = "(unnamed)"; - else - attrs.product = strdup(name); - add_option(&options, "name", name); - - add_option(&options, "path", path); - add_option(&options, "device", path); - if (path) - attrs.device = strdup(path); - - tags_prop = udev_device_get_property_value(udev_device, "ID_INPUT.tags"); - LOG_PROPERTY(path, "ID_INPUT.tags", tags_prop); - attrs.tags = xstrtokenize(tags_prop, ","); - - if (asprintf(&config_info, "udev:%s", syspath) == -1) { - config_info = NULL; - goto unwind; - } - - if (device_is_duplicate(config_info)) { - LogMessage(X_WARNING, "config/udev: device %s already added. " - "Ignoring.\n", name); - goto unwind; - } - - set = udev_device_get_properties_list_entry(udev_device); - udev_list_entry_foreach(entry, set) { - key = udev_list_entry_get_name(entry); - if (!key) - continue; - value = udev_list_entry_get_value(entry); - if (!strncasecmp(key, UDEV_XKB_PROP_KEY, - sizeof(UDEV_XKB_PROP_KEY) - 1)) { - LOG_PROPERTY(path, key, value); - tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1; - if (!strcasecmp(tmp, "rules")) - add_option(&options, "xkb_rules", value); - else if (!strcasecmp(tmp, "layout")) - add_option(&options, "xkb_layout", value); - else if (!strcasecmp(tmp, "variant")) - add_option(&options, "xkb_variant", value); - else if (!strcasecmp(tmp, "model")) - add_option(&options, "xkb_model", value); - else if (!strcasecmp(tmp, "options")) - add_option(&options, "xkb_options", value); - } else if (!strcmp(key, "ID_VENDOR")) { - LOG_PROPERTY(path, key, value); - attrs.vendor = strdup(value); - } else if (!strcmp(key, "ID_INPUT_KEY")) { - LOG_PROPERTY(path, key, value); - attrs.flags |= ATTR_KEYBOARD; - } else if (!strcmp(key, "ID_INPUT_MOUSE")) { - LOG_PROPERTY(path, key, value); - attrs.flags |= ATTR_POINTER; - } else if (!strcmp(key, "ID_INPUT_JOYSTICK")) { - LOG_PROPERTY(path, key, value); - attrs.flags |= ATTR_JOYSTICK; - } else if (!strcmp(key, "ID_INPUT_TABLET")) { - LOG_PROPERTY(path, key, value); - attrs.flags |= ATTR_TABLET; - } else if (!strcmp(key, "ID_INPUT_TOUCHPAD")) { - LOG_PROPERTY(path, key, value); - attrs.flags |= ATTR_TOUCHPAD; - } else if (!strcmp(key, "ID_INPUT_TOUCHSCREEN")) { - LOG_PROPERTY(path, key, value); - attrs.flags |= ATTR_TOUCHSCREEN; - } - } - - add_option(&options, "config_info", config_info); - - LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n", - name, path); - rc = NewInputDeviceRequest(options, &attrs, &dev); - if (rc != Success) - goto unwind; - - unwind: - free(config_info); - while ((tmpo = options)) { - options = tmpo->next; - free(tmpo->key); /* NULL if dev != NULL */ - free(tmpo->value); /* NULL if dev != NULL */ - free(tmpo); - } - - free(attrs.usb_id); - free(attrs.pnp_id); - free(attrs.product); - free(attrs.device); - free(attrs.vendor); - if (attrs.tags) { - char **tag = attrs.tags; - while (*tag) { - free(*tag); - tag++; - } - free(attrs.tags); - } - - return; -} - -static void -device_removed(struct udev_device *device) -{ - char *value; - const char *syspath = udev_device_get_syspath(device); - - if (asprintf(&value, "udev:%s", syspath) == -1) - return; - - remove_devices("udev", value); - - free(value); -} - -static void -wakeup_handler(pointer data, int err, pointer read_mask) -{ - int udev_fd = udev_monitor_get_fd(udev_monitor); - struct udev_device *udev_device; - const char *action; - - if (err < 0) - return; - - if (FD_ISSET(udev_fd, (fd_set *)read_mask)) { - udev_device = udev_monitor_receive_device(udev_monitor); - if (!udev_device) - return; - action = udev_device_get_action(udev_device); - if (action) { - if (!strcmp(action, "add") || !strcmp(action, "change")) { - device_removed(udev_device); - device_added(udev_device); - } - else if (!strcmp(action, "remove")) - device_removed(udev_device); - } - udev_device_unref(udev_device); - } -} - -static void -block_handler(pointer data, struct timeval **tv, pointer read_mask) -{ -} - -int -config_udev_init(void) -{ - struct udev *udev; - struct udev_enumerate *enumerate; - struct udev_list_entry *devices, *device; - - udev = udev_new(); - if (!udev) - return 0; - udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); - if (!udev_monitor) - return 0; - - udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input", NULL); - udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL); /* For Wacom serial devices */ - - if (udev_monitor_enable_receiving(udev_monitor)) { - ErrorF("config/udev: failed to bind the udev monitor\n"); - return 0; - } - - enumerate = udev_enumerate_new(udev); - if (!enumerate) - return 0; - - udev_enumerate_add_match_subsystem(enumerate, "input"); - udev_enumerate_add_match_subsystem(enumerate, "tty"); - - udev_enumerate_scan_devices(enumerate); - devices = udev_enumerate_get_list_entry(enumerate); - udev_list_entry_foreach(device, devices) { - const char *syspath = udev_list_entry_get_name(device); - struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath); - - /* Device might be gone by the time we try to open it */ - if (!udev_device) - continue; - - device_added(udev_device); - udev_device_unref(udev_device); - } - udev_enumerate_unref(enumerate); - - RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); - AddGeneralSocket(udev_monitor_get_fd(udev_monitor)); - - return 1; -} - -void -config_udev_fini(void) -{ - struct udev *udev; - - if (!udev_monitor) - return; - - udev = udev_monitor_get_udev(udev_monitor); - - RemoveGeneralSocket(udev_monitor_get_fd(udev_monitor)); - RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); - udev_monitor_unref(udev_monitor); - udev_monitor = NULL; - udev_unref(udev); -} +/* + * Copyright © 2009 Julien Cristau + * + * 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: Julien Cristau + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include + +#include "input.h" +#include "inputstr.h" +#include "hotplug.h" +#include "config-backends.h" +#include "os.h" + +#define UDEV_XKB_PROP_KEY "xkb" + +#define LOG_PROPERTY(path, prop, val) \ + LogMessageVerb(X_INFO, 10, \ + "config/udev: getting property %s on %s " \ + "returned \"%s\"\n", \ + (prop), (path), (val) ? (val) : "(null)") +#define LOG_SYSATTR(path, attr, val) \ + LogMessageVerb(X_INFO, 10, \ + "config/udev: getting attribute %s on %s " \ + "returned \"%s\"\n", \ + (attr), (path), (val) ? (val) : "(null)") + +static struct udev_monitor *udev_monitor; + +static void +device_added(struct udev_device *udev_device) +{ + const char *path, *name = NULL; + char *config_info = NULL; + const char *syspath; + const char *tags_prop; + const char *key, *value, *tmp; + InputOption *options = NULL, *tmpo; + InputAttributes attrs = {}; + DeviceIntPtr dev = NULL; + struct udev_list_entry *set, *entry; + struct udev_device *parent; + int rc; + + path = udev_device_get_devnode(udev_device); + + syspath = udev_device_get_syspath(udev_device); + + if (!path || !syspath) + return; + + if (!udev_device_get_property_value(udev_device, "ID_INPUT")) { + LogMessageVerb(X_INFO, 10, + "config/udev: ignoring device %s without " + "property ID_INPUT set\n", + path); + return; + } + + options = calloc(sizeof(*options), 1); + if (!options) + return; + + options->key = strdup("_source"); + options->value = strdup("server/udev"); + if (!options->key || !options->value) + goto unwind; + + parent = udev_device_get_parent(udev_device); + if (parent) { + const char *ppath = udev_device_get_devnode(parent); + const char *product = udev_device_get_property_value(parent, "PRODUCT"); + const char *pnp_id = udev_device_get_sysattr_value(parent, "id"); + unsigned int usb_vendor, usb_model; + + name = udev_device_get_sysattr_value(parent, "name"); + LOG_SYSATTR(ppath, "name", name); + if (!name) { + name = udev_device_get_property_value(parent, "NAME"); + LOG_PROPERTY(ppath, "NAME", name); + } + + if (pnp_id) + attrs.pnp_id = strdup(pnp_id); + LOG_SYSATTR(ppath, "id", pnp_id); + + /* construct USB ID in lowercase hex - "0000:ffff" */ + if (product && sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) { + if (asprintf(&attrs.usb_id, "%04x:%04x", usb_vendor, usb_model) + == -1) + attrs.usb_id = NULL; + else + LOG_PROPERTY(path, "PRODUCT", product); + } + } + if (!name) + name = "(unnamed)"; + else + attrs.product = strdup(name); + add_option(&options, "name", name); + + add_option(&options, "path", path); + add_option(&options, "device", path); + if (path) + attrs.device = strdup(path); + + tags_prop = udev_device_get_property_value(udev_device, "ID_INPUT.tags"); + LOG_PROPERTY(path, "ID_INPUT.tags", tags_prop); + attrs.tags = xstrtokenize(tags_prop, ","); + + if (asprintf(&config_info, "udev:%s", syspath) == -1) { + config_info = NULL; + goto unwind; + } + + if (device_is_duplicate(config_info)) { + LogMessage(X_WARNING, "config/udev: device %s already added. " + "Ignoring.\n", name); + goto unwind; + } + + set = udev_device_get_properties_list_entry(udev_device); + udev_list_entry_foreach(entry, set) { + key = udev_list_entry_get_name(entry); + if (!key) + continue; + value = udev_list_entry_get_value(entry); + if (!strncasecmp(key, UDEV_XKB_PROP_KEY, + sizeof(UDEV_XKB_PROP_KEY) - 1)) { + LOG_PROPERTY(path, key, value); + tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1; + if (!strcasecmp(tmp, "rules")) + add_option(&options, "xkb_rules", value); + else if (!strcasecmp(tmp, "layout")) + add_option(&options, "xkb_layout", value); + else if (!strcasecmp(tmp, "variant")) + add_option(&options, "xkb_variant", value); + else if (!strcasecmp(tmp, "model")) + add_option(&options, "xkb_model", value); + else if (!strcasecmp(tmp, "options")) + add_option(&options, "xkb_options", value); + } else if (!strcmp(key, "ID_VENDOR")) { + LOG_PROPERTY(path, key, value); + attrs.vendor = strdup(value); + } else if (!strcmp(key, "ID_INPUT_KEY")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_KEYBOARD; + } else if (!strcmp(key, "ID_INPUT_MOUSE")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_POINTER; + } else if (!strcmp(key, "ID_INPUT_JOYSTICK")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_JOYSTICK; + } else if (!strcmp(key, "ID_INPUT_TABLET")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_TABLET; + } else if (!strcmp(key, "ID_INPUT_TOUCHPAD")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_TOUCHPAD; + } else if (!strcmp(key, "ID_INPUT_TOUCHSCREEN")) { + LOG_PROPERTY(path, key, value); + attrs.flags |= ATTR_TOUCHSCREEN; + } + } + + add_option(&options, "config_info", config_info); + + LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n", + name, path); + rc = NewInputDeviceRequest(options, &attrs, &dev); + if (rc != Success) + goto unwind; + + unwind: + free(config_info); + while ((tmpo = options)) { + options = tmpo->next; + free(tmpo->key); /* NULL if dev != NULL */ + free(tmpo->value); /* NULL if dev != NULL */ + free(tmpo); + } + + free(attrs.usb_id); + free(attrs.pnp_id); + free(attrs.product); + free(attrs.device); + free(attrs.vendor); + if (attrs.tags) { + char **tag = attrs.tags; + while (*tag) { + free(*tag); + tag++; + } + free(attrs.tags); + } + + return; +} + +static void +device_removed(struct udev_device *device) +{ + char *value; + const char *syspath = udev_device_get_syspath(device); + + if (asprintf(&value, "udev:%s", syspath) == -1) + return; + + remove_devices("udev", value); + + free(value); +} + +static void +wakeup_handler(pointer data, int err, pointer read_mask) +{ + int udev_fd = udev_monitor_get_fd(udev_monitor); + struct udev_device *udev_device; + const char *action; + + if (err < 0) + return; + + if (FD_ISSET(udev_fd, (fd_set *)read_mask)) { + udev_device = udev_monitor_receive_device(udev_monitor); + if (!udev_device) + return; + action = udev_device_get_action(udev_device); + if (action) { + if (!strcmp(action, "add") || !strcmp(action, "change")) { + device_removed(udev_device); + device_added(udev_device); + } + else if (!strcmp(action, "remove")) + device_removed(udev_device); + } + udev_device_unref(udev_device); + } +} + +static void +block_handler(pointer data, struct timeval **tv, pointer read_mask) +{ +} + +int +config_udev_init(void) +{ + struct udev *udev; + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *device; + + udev = udev_new(); + if (!udev) + return 0; + udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); + if (!udev_monitor) + return 0; + + udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input", NULL); + udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL); /* For Wacom serial devices */ + + if (udev_monitor_enable_receiving(udev_monitor)) { + ErrorF("config/udev: failed to bind the udev monitor\n"); + return 0; + } + + enumerate = udev_enumerate_new(udev); + if (!enumerate) + return 0; + + udev_enumerate_add_match_subsystem(enumerate, "input"); + udev_enumerate_add_match_subsystem(enumerate, "tty"); + + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + udev_list_entry_foreach(device, devices) { + const char *syspath = udev_list_entry_get_name(device); + struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath); + + /* Device might be gone by the time we try to open it */ + if (!udev_device) + continue; + + device_added(udev_device); + udev_device_unref(udev_device); + } + udev_enumerate_unref(enumerate); + + RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); + AddGeneralSocket(udev_monitor_get_fd(udev_monitor)); + + return 1; +} + +void +config_udev_fini(void) +{ + struct udev *udev; + + if (!udev_monitor) + return; + + udev = udev_monitor_get_udev(udev_monitor); + + RemoveGeneralSocket(udev_monitor_get_fd(udev_monitor)); + RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, NULL); + udev_monitor_unref(udev_monitor); + udev_monitor = NULL; + udev_unref(udev); +} -- cgit v1.2.3