From 4c61bf84b11e26e6f22648668c95ea760a379163 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 11 Jun 2010 12:14:52 +0000 Subject: xserver git update 11/6/2010 --- xorg-server/config/Makefile.am | 78 +++++++-------- xorg-server/config/dbus.c | 7 +- xorg-server/config/fdi2iclass.py | 202 +++++++++++++++++++++++++++++++++++++++ xorg-server/config/hal.c | 80 +++++++++------- xorg-server/config/udev.c | 62 +++++++++++- 5 files changed, 348 insertions(+), 81 deletions(-) create mode 100644 xorg-server/config/fdi2iclass.py (limited to 'xorg-server/config') diff --git a/xorg-server/config/Makefile.am b/xorg-server/config/Makefile.am index 675a3b260..d8a7b45f6 100644 --- a/xorg-server/config/Makefile.am +++ b/xorg-server/config/Makefile.am @@ -1,39 +1,39 @@ -AM_CFLAGS = $(DIX_CFLAGS) - -noinst_LTLIBRARIES = libconfig.la -libconfig_la_SOURCES = config.c config-backends.h - -if CONFIG_UDEV - -AM_CFLAGS += $(UDEV_CFLAGS) -libconfig_la_SOURCES += udev.c -libconfig_la_LIBADD = $(UDEV_LIBS) - -xorgconfddir = $(datadir)/X11/$(XF86CONFIGDIR) -xorgconfd_DATA = 10-evdev.conf - -else - -if CONFIG_NEED_DBUS -AM_CFLAGS += $(DBUS_CFLAGS) -libconfig_la_SOURCES += dbus-core.c -libconfig_la_LIBADD = $(DBUS_LIBS) - -if CONFIG_DBUS_API -dbusconfigdir = $(sysconfdir)/dbus-1/system.d -dbusconfig_DATA = xorg-server.conf - -libconfig_la_SOURCES += dbus.c -endif - -if CONFIG_HAL -AM_CFLAGS += $(HAL_CFLAGS) -libconfig_la_SOURCES += hal.c -libconfig_la_LIBADD += $(HAL_LIBS) -endif - -endif # CONFIG_NEED_DBUS - -endif # !CONFIG_UDEV - -EXTRA_DIST = xorg-server.conf x11-input.fdi 10-evdev.conf +AM_CFLAGS = $(DIX_CFLAGS) + +noinst_LTLIBRARIES = libconfig.la +libconfig_la_SOURCES = config.c config-backends.h + +if CONFIG_UDEV + +AM_CFLAGS += $(UDEV_CFLAGS) +libconfig_la_SOURCES += udev.c +libconfig_la_LIBADD = $(UDEV_LIBS) + +xorgconfddir = $(datadir)/X11/$(XF86CONFIGDIR) +xorgconfd_DATA = 10-evdev.conf + +else + +if CONFIG_NEED_DBUS +AM_CFLAGS += $(DBUS_CFLAGS) +libconfig_la_SOURCES += dbus-core.c +libconfig_la_LIBADD = $(DBUS_LIBS) + +if CONFIG_DBUS_API +dbusconfigdir = $(sysconfdir)/dbus-1/system.d +dbusconfig_DATA = xorg-server.conf + +libconfig_la_SOURCES += dbus.c +endif + +if CONFIG_HAL +AM_CFLAGS += $(HAL_CFLAGS) +libconfig_la_SOURCES += hal.c +libconfig_la_LIBADD += $(HAL_LIBS) +endif + +endif # CONFIG_NEED_DBUS + +endif # !CONFIG_UDEV + +EXTRA_DIST = xorg-server.conf x11-input.fdi 10-evdev.conf fdi2iclass.py diff --git a/xorg-server/config/dbus.c b/xorg-server/config/dbus.c index d6316623b..5d11feaa1 100644 --- a/xorg-server/config/dbus.c +++ b/xorg-server/config/dbus.c @@ -27,7 +27,6 @@ #include #endif -#define DBUS_API_SUBJECT_TO_CHANGE #include #include @@ -184,10 +183,8 @@ unwind: while (options) { tmpo = options; options = options->next; - if (tmpo->key) - free(tmpo->key); - if (tmpo->value) - free(tmpo->value); + free(tmpo->key); + free(tmpo->value); free(tmpo); } diff --git a/xorg-server/config/fdi2iclass.py b/xorg-server/config/fdi2iclass.py new file mode 100644 index 000000000..9dc06a76f --- /dev/null +++ b/xorg-server/config/fdi2iclass.py @@ -0,0 +1,202 @@ +#!/usr/bin/python +# +# Convert xorg keys from hal FDIs files to xorg.conf InputClass sections. +# Modified from Martin Pitt's original fdi2mpi.py script: +# http://cgit.freedesktop.org/media-player-info/tree/tools/fdi2mpi.py +# +# (C) 2010 Dan Nicholson +# (C) 2009 Canonical Ltd. +# Author: Dan Nicholson +# Author: Martin Pitt +# +# 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 +# fur- nished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice 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, +# FIT- NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- +# NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import sys, xml.dom.minidom + +# dict converting tags to Match* entries +match_table = { + 'info.product': 'MatchProduct', + 'input.product': 'MatchProduct', + 'info.vendor': 'MatchVendor', + 'input.vendor': 'MatchVendor', + 'info.device': 'MatchDevicePath', + 'linux.device_file': 'MatchDevicePath', + '/org/freedesktop/Hal/devices/computer:system.kernel.name': 'MatchOS', + '@info.parent:pnp.id': 'MatchPnPID', +} + +# dict converting info.capabilities list to Match* entries +cap_match_table = { + 'input.keys': 'MatchIsKeyboard', + 'input.keyboard': 'MatchIsKeyboard', + 'input.keypad': 'MatchIsKeyboard', + 'input.mouse': 'MatchIsPointer', + 'input.joystick': 'MatchIsJoystick', + 'input.tablet': 'MatchIsTablet', + 'input.touchpad': 'MatchIsTouchpad', + 'input.touchscreen': 'MatchIsTouchscreen', +} + +def device_glob(path): + '''Convert a contains device path to a glob entry''' + if path[0] != '/': + path = '*' + path + return path + '*' + +def parse_match(node): + '''Parse a tag to a tuple with InputClass values''' + match = None + value = None + booltype = False + + # see what type of key we have + if node.attributes.has_key('key'): + key = node.attributes['key'].nodeValue + if key in match_table: + match = match_table[key] + elif key == 'info.capabilities': + booltype = True + + # bail out now if it's unrecognized + if not match and not booltype: + return (match, value) + + if node.attributes.has_key('string'): + value = node.attributes['string'].nodeValue + elif node.attributes.has_key('contains'): + value = node.attributes['contains'].nodeValue + if match == 'MatchDevicePath': + value = device_glob(value) + elif booltype and value in cap_match_table: + match = cap_match_table[value] + value = 'yes' + elif node.attributes.has_key('string_outof'): + value = node.attributes['string_outof'].nodeValue.replace(';','|') + elif node.attributes.has_key('contains_outof'): + all_values = node.attributes['contains_outof'].nodeValue.split(';') + for v in all_values: + if match == 'MatchDevicePath': + v = device_glob(v) + elif match == 'MatchPnPID' and len(v) < 7: + v += '*' + if value: + value += '|' + v + else: + value = v + + return (match, value) + +def parse_options(node): + '''Parse the x11_* options and return InputClass entries''' + driver = '' + ignore = False + options = [] + for n in node.childNodes: + if n.nodeType != xml.dom.minidom.Node.ELEMENT_NODE: + continue + + tag = n.tagName + key = n.attributes['key'].nodeValue + value = '' + + if n.hasChildNodes(): + content_node = n.childNodes[0] + assert content_node.nodeType == xml.dom.Node.TEXT_NODE + value = content_node.nodeValue + + if tag == 'match': + continue + assert tag in ('addset', 'merge', 'append', 'remove') + + if tag == 'remove' and key == 'input.x11_driver': + ignore = True + elif key == 'input.x11_driver': + driver = value + elif key.startswith('input.x11_options.'): + option = key.split('.', 2)[2] + options.append((option, value)) + + return (driver, ignore, options) + +def is_match_node(node): + '''Check if a node is a element''' + return node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE and \ + node.tagName == 'match' + +def parse_all_matches(node): + '''Parse a x11 match tag and any parents that don't supply their + own options''' + matches = [] + + while True: + (key, value) = parse_match(node) + if key and value: + matches.append((key, value)) + + # walk up to a parent match node + node = node.parentNode + if node == None or not is_match_node(node): + break + + # leave if there other options at this level + children = set([n.tagName for n in node.childNodes + if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE]) + if children & set(['addset', 'merge', 'append']): + break + + return matches + +# stupid counter to give "unique" rule names +num_sections = 1 +def print_section(matches, driver, ignore, options): + '''Print a valid InputClass section to stdout''' + global num_sections + print 'Section "InputClass"' + print '\tIdentifier "Converted Class %d"' % num_sections + num_sections += 1 + for m, v in matches: + print '\t%s "%s"' % (m, v) + if driver: + print '\tDriver "%s"' % driver + if ignore: + print '\tOption "Ignore" "yes"' + for o, v in options: + print '\tOption "%s" "%s"' % (o, v) + print 'EndSection' + +def parse_fdi(fdi): + '''Parse x11 matches from fdi''' + # find all leaf nodes + num = 0 + for match_node in fdi.getElementsByTagName('match'): + children = set([n.tagName for n in match_node.childNodes + if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE]) + + # see if there are any options at this level + (driver, ignore, options) = parse_options(match_node) + if not driver and not ignore and not options: + continue + + matches = parse_all_matches(match_node) + if num > 0: + print + print_section(matches, driver, ignore, options) + num += 1 + +for f in sys.argv[1:]: + parse_fdi(xml.dom.minidom.parse(f)) diff --git a/xorg-server/config/hal.c b/xorg-server/config/hal.c index 738cb3185..1245bb192 100644 --- a/xorg-server/config/hal.c +++ b/xorg-server/config/hal.c @@ -129,6 +129,7 @@ static void device_added(LibHalContext *hal_ctx, const char *udi) { char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL; + char *hal_tags, *parent; InputOption *options = NULL, *tmpo = NULL; InputAttributes attrs = {0}; DeviceIntPtr dev = NULL; @@ -164,7 +165,9 @@ device_added(LibHalContext *hal_ctx, const char *udi) attrs.product = xstrdup(name); attrs.vendor = get_prop_string(hal_ctx, udi, "info.vendor"); - attrs.tags = xstrtokenize(get_prop_string(hal_ctx, udi, "input.tags"), ","); + hal_tags = get_prop_string(hal_ctx, udi, "input.tags"); + attrs.tags = xstrtokenize(hal_tags, ","); + free(hal_tags); if (libhal_device_query_capability(hal_ctx, udi, "input.keys", NULL)) attrs.flags |= ATTR_KEYBOARD; @@ -179,6 +182,29 @@ device_added(LibHalContext *hal_ctx, const char *udi) if (libhal_device_query_capability(hal_ctx, udi, "input.touchscreen", NULL)) attrs.flags |= ATTR_TOUCHSCREEN; + parent = get_prop_string(hal_ctx, udi, "info.parent"); + if (parent) { + int usb_vendor, usb_product; + + attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id"); + + /* construct USB ID in lowercase - "0000:ffff" */ + usb_vendor = libhal_device_get_property_int(hal_ctx, parent, + "usb.vendor_id", NULL); + LogMessageVerb(X_INFO, 10, + "config/hal: getting usb.vendor_id on %s " + "returned %04x\n", parent, usb_vendor); + usb_product = libhal_device_get_property_int(hal_ctx, parent, + "usb.product_id", NULL); + LogMessageVerb(X_INFO, 10, + "config/hal: getting usb.product_id on %s " + "returned %04x\n", parent, usb_product); + if (usb_vendor && usb_product) + attrs.usb_id = Xprintf("%04x:%04x", usb_vendor, usb_product); + + free(parent); + } + options = calloc(sizeof(*options), 1); if (!options){ LogMessage(X_ERROR, "config/hal: couldn't allocate space for input options!\n"); @@ -251,28 +277,23 @@ device_added(LibHalContext *hal_ctx, const char *udi) { if (!strcasecmp(&tmp[3], "layout")) { - if (xkb_opts.layout) - free(xkb_opts.layout); + free(xkb_opts.layout); xkb_opts.layout = strdup(tmp_val); } else if (!strcasecmp(&tmp[3], "model")) { - if (xkb_opts.model) - free(xkb_opts.model); + free(xkb_opts.model); xkb_opts.model = strdup(tmp_val); } else if (!strcasecmp(&tmp[3], "rules")) { - if (xkb_opts.rules) - free(xkb_opts.rules); + free(xkb_opts.rules); xkb_opts.rules = strdup(tmp_val); } else if (!strcasecmp(&tmp[3], "variant")) { - if (xkb_opts.variant) - free(xkb_opts.variant); + free(xkb_opts.variant); xkb_opts.variant = strdup(tmp_val); } else if (!strcasecmp(&tmp[3], "options")) { - if (xkb_opts.options) - free(xkb_opts.options); + free(xkb_opts.options); xkb_opts.options = strdup(tmp_val); } } else @@ -289,8 +310,7 @@ device_added(LibHalContext *hal_ctx, const char *udi) (!strcasecmp(&tmp[3], "options")) && (tmp_val = get_prop_string_array(hal_ctx, udi, psi_key))) { - if (xkb_opts.options) - free(xkb_opts.options); + free(xkb_opts.options); xkb_opts.options = strdup(tmp_val); } } @@ -366,22 +386,17 @@ device_added(LibHalContext *hal_ctx, const char *udi) } for (; dev; dev = dev->next){ - if (dev->config_info) - free(dev->config_info); + free(dev->config_info); dev->config_info = xstrdup(config_info); } unwind: if (set) libhal_free_property_set(set); - if (path) - free(path); - if (driver) - free(driver); - if (name) - free(name); - if (config_info) - free(config_info); + free(path); + free(driver); + free(name); + free(config_info); while (!dev && (tmpo = options)) { options = tmpo->next; free(tmpo->key); @@ -392,6 +407,8 @@ unwind: free(attrs.product); free(attrs.vendor); free(attrs.device); + free(attrs.pnp_id); + free(attrs.usb_id); if (attrs.tags) { char **tag = attrs.tags; while (*tag) { @@ -401,16 +418,11 @@ unwind: free(attrs.tags); } - if (xkb_opts.layout) - free(xkb_opts.layout); - if (xkb_opts.rules) - free(xkb_opts.rules); - if (xkb_opts.model) - free(xkb_opts.model); - if (xkb_opts.variant) - free(xkb_opts.variant); - if (xkb_opts.options) - free(xkb_opts.options); + free(xkb_opts.layout); + free(xkb_opts.rules); + free(xkb_opts.model); + free(xkb_opts.variant); + free(xkb_opts.options); dbus_error_free(&error); @@ -635,7 +647,7 @@ config_hal_init(void) } /* verbose message */ - LogMessageVerb(X_INFO,7,"config/hal: initialized"); + LogMessageVerb(X_INFO,7,"config/hal: initialized\n"); return 1; } diff --git a/xorg-server/config/udev.c b/xorg-server/config/udev.c index 304ee2c93..bf463168e 100644 --- a/xorg-server/config/udev.c +++ b/xorg-server/config/udev.c @@ -28,6 +28,7 @@ #endif #include +#include #include "input.h" #include "inputstr.h" @@ -37,6 +38,17 @@ #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 @@ -45,6 +57,8 @@ 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 *usb_vendor = NULL, *usb_model = NULL; const char *key, *value, *tmp; InputOption *options = NULL, *tmpo; InputAttributes attrs = {}; @@ -60,8 +74,13 @@ device_added(struct udev_device *udev_device) if (!path || !syspath) return; - if (!udev_device_get_property_value(udev_device, "ID_INPUT")) + 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) @@ -74,9 +93,17 @@ device_added(struct udev_device *udev_device) parent = udev_device_get_parent(udev_device); if (parent) { + const char *ppath = udev_device_get_devnode(parent); + name = udev_device_get_sysattr_value(parent, "name"); - if (!name) + LOG_SYSATTR(ppath, "name", name); + if (!name) { name = udev_device_get_property_value(parent, "NAME"); + LOG_PROPERTY(ppath, "NAME", name); + } + + attrs.pnp_id = udev_device_get_sysattr_value(parent, "id"); + LOG_SYSATTR(ppath, "id", attrs.pnp_id); } if (!name) name = "(unnamed)"; @@ -87,7 +114,10 @@ device_added(struct udev_device *udev_device) add_option(&options, "path", path); add_option(&options, "device", path); attrs.device = path; - attrs.tags = xstrtokenize(udev_device_get_property_value(udev_device, "ID_INPUT.tags"), ","); + + 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, ","); config_info = Xprintf("udev:%s", syspath); if (!config_info) @@ -107,6 +137,7 @@ device_added(struct udev_device *udev_device) 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); @@ -119,21 +150,45 @@ device_added(struct udev_device *udev_device) else if (!strcasecmp(tmp, "options")) add_option(&options, "xkb_options", value); } else if (!strcmp(key, "ID_VENDOR")) { + LOG_PROPERTY(path, key, value); attrs.vendor = value; + } else if (!strcmp(key, "ID_VENDOR_ID")) { + LOG_PROPERTY(path, key, value); + usb_vendor = value; + } else if (!strcmp(key, "ID_VENDOR_MODEL")) { + LOG_PROPERTY(path, key, value); + usb_model = 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; } } + + /* construct USB ID in lowercase hex - "0000:ffff" */ + if (usb_vendor && usb_model) { + attrs.usb_id = Xprintf("%s:%s", usb_vendor, usb_model); + if (attrs.usb_id) { + char *cur; + for (cur = attrs.usb_id; *cur; cur++) + *cur = tolower(*cur); + } + } + LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n", name, path); rc = NewInputDeviceRequest(options, &attrs, &dev); @@ -154,6 +209,7 @@ device_added(struct udev_device *udev_device) free(tmpo); } + free(attrs.usb_id); if (attrs.tags) { char **tag = attrs.tags; while (*tag) { -- cgit v1.2.3