Now that the server has moved to using udev on linux, we have many configurations that were working using hal fdi files that will no longer be applied. The proper solution is to convert these configurations to using InputClass sections. I've taken a script that Martin Pitt wrote for parsing media player info from fdi files and converted it to generating InputClass sections. See the attached script. My python skills suck, so it might be suboptimal in a lot of ways.
One of the things I noticed when working on this is that some of the hal matches don't have corresponding InputClass Match* entries. Here are a couple things I'd like to add to make this transition easier. MatchOS - This affects the generic rules that the server installs on all platforms. Our current x11-input.fdi allows evdev to be the driver only on linux. It would be nice to add 'MatchOS "linux"' to 10-evdev.conf so that it could be installed unconditionally. PnP id matching - Since the serial devices don't export a name, most of the matching is done on the PnP ID. Here's the wacom fdi file: http://cgit.freedesktop.org/~whot/xf86-input-wacom/tree/fdi/wacom.fdi I'd like to add a MatchPnPID entry. Matching could be substring or glob. By the same token, it would be nice to match USB or PCI IDs, too. Maybe you could have three tags (MatchPnPID, MatchUSBID, MatchPCIID) or a magic MatchBusID entry. It would be nice to put this script in the server repo, but it's GPLv2+. Martin, would you be opposed to relicensing your contributions to X11 or dual licensing? The original script is here: http://cgit.freedesktop.org/~teuf/media-player-info/tree/tools/fdi2mpi.py Let me know what you guys think. -- Dan
#!/usr/bin/python # # Convert xorg keys from hal FDIs files to xorg.confInputClass sections. # # (C) 2010 Dan Nicholson # (C) 2009 Canonical Ltd. # Author: Dan Nicholson <[email protected]> # Author: Martin Pitt <[email protected]> # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # keymap is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with keymap; if not, write to the Free Software Foundation, # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. import sys, xml.dom.minidom # dict converting <match> 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', # Keys below aren't supported yet '/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 <match> 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) if value: value += '|' + v else: value = v if match == 'MatchOS': value = value.lower() 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 <match> 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 def print_section(matches, driver, ignore, options): ''' Print a valid InputClass section to stdout''' print 'Section "InputClass"' print '\tIdentifier "xxx"' 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 <match> 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))
_______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
