--- xorg-server-1.4/hw/xfree86/common/xf86Xinput.c.hal 2007-11-21 18:32:54.000000000 -0200 +++ xorg-server-1.4/hw/xfree86/common/xf86Xinput.c 2007-11-21 18:37:11.000000000 -0200 @@ -433,7 +433,11 @@ unwind: xfree(idev->driver); if(idev->identifier) xfree(idev->identifier); +#ifndef CONFIG_HAL + /* If CONFIG_HAL is defined, and we use xorg.conf default options, must + * not delete this, as the driver may be initialized more than once */ xf86optionListFree(idev->commonOptions); +#endif xfree(idev); return rval; } --- xorg-server-1.4/config/hal.c.hal 2007-11-20 16:31:06.000000000 -0200 +++ xorg-server-1.4/config/hal.c 2007-11-21 18:49:17.000000000 -0200 @@ -38,15 +38,13 @@ #include "config-backends.h" #include "os.h" -#define TYPE_NONE 0 -#define TYPE_KEYS 1 -#define TYPE_POINTER 2 - struct config_hal_info { DBusConnection *system_bus; LibHalContext *hal_ctx; }; +void check_input_defaults(LibHalContext *hal_ctx, const char *udi, int type); + static void remove_device(DeviceIntPtr dev) { @@ -119,23 +117,27 @@ static char * get_prop_string_array(LibHalContext *hal_ctx, const char *udi, const char *prop) { char **props, *ret, *str; - int i, len = 0; + int i, count, len = 0; props = libhal_device_get_property_strlist(hal_ctx, udi, prop, NULL); if (props) { - for (i = 0; props[i]; i++) - len += strlen(props[i]); + for (count = 0; props[count]; count++) + len += strlen(props[count]); - ret = xcalloc(sizeof(char), len + i); /* i - 1 commas, 1 NULL */ + ret = xcalloc(sizeof(char), len + count); /* count commas - 1, 1 NULL */ if (!ret) { libhal_free_string_array(props); return NULL; } str = ret; - for (i = 0; props[i]; i++) { - str = strcpy(str, props[i]); - *str++ = ','; + for (i = 0;;) { + strcpy(str, props[i]); + str += strlen(props[i]); + if (++i < count) + *str++ = ','; + else + break; } *str = '\0'; @@ -186,6 +188,7 @@ device_added(LibHalContext *hal_ctx, con if (type == TYPE_NONE) goto out_error; + check_input_defaults(hal_ctx, udi, type); driver = get_prop_string(hal_ctx, udi, "input.x11_driver"); path = get_prop_string(hal_ctx, udi, "input.device"); if (!driver || !path) { --- xorg-server-1.4/config/hal-defaults.c.hal 2007-11-20 16:21:44.000000000 -0200 +++ xorg-server-1.4/config/hal-defaults.c 2007-11-21 19:21:32.000000000 -0200 @@ -0,0 +1,189 @@ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#include "input.h" +#include "inputstr.h" +#include "hotplug.h" +#include "config-backends.h" +#include "os.h" + +#include "xf86Xinput.h" +#include "xf86Opt.h" +#include "xf86Optrec.h" + +extern InputInfo inputInfo; + +void check_input_defaults(LibHalContext *hal_ctx, const char *udi, int type); + +static int set_prop_string(LibHalContext *hal_ctx, const char *udi, + const char *name, const char *value); +static int append_prop_string(LibHalContext *hal_ctx, const char *udi, + const char *name, const char *value); + + +/* verbatim copy from XF86Config parser xf86nameCompare. + * Need this because this code is also linked with kdriver servers, but + * only one library is generated, otherwise, could use xf86NameCmp or + * directly call xf86nameCompare if building the "main" xf86 server. + */ +static int +nameCompare (const char *s1, const char *s2) +{ + char c1, c2; + + if (!s1 || *s1 == 0) { + if (!s2 || *s2 == 0) + return (0); + else + return (1); + } + + while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') + s1++; + while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') + s2++; + c1 = (isupper (*s1) ? tolower (*s1) : *s1); + c2 = (isupper (*s2) ? tolower (*s2) : *s2); + while (c1 == c2) + { + if (c1 == '\0') + return (0); + s1++; + s2++; + while (*s1 == '_' || *s1 == ' ' || *s1 == '\t') + s1++; + while (*s2 == '_' || *s2 == ' ' || *s2 == '\t') + s2++; + c1 = (isupper (*s1) ? tolower (*s1) : *s1); + c2 = (isupper (*s2) ? tolower (*s2) : *s2); + } + return (c1 - c2); +} + +void +check_input_defaults(LibHalContext *hal_ctx, const char *udi, int type) +{ + DeviceIntPtr device; + LocalDevicePtr local; + InputDriverPtr driver; + IDevRec *idev; + XF86OptionPtr options; + int driver_type; + + /* There isn't a mapping of hal device name to xorg.conf device name... */ + for (device = inputInfo.devices; device; device = device->next) { + local = (LocalDevicePtr)device->public.devicePrivate; + if (local) { + driver = local->drv; + if (driver) { + if ((type & TYPE_KEYS) && + strcmp("kbd", driver->driverName) == 0) + driver_type = TYPE_KEYS; + else if ((type & TYPE_POINTER) && + strcmp("mouse", driver->driverName) == 0) + driver_type = TYPE_POINTER; + else + /* Good luck :-) + * There isn't a mapping from hal devices to xorg.conf + * devices, so cannot guess further. + */ + continue; + + set_prop_string(hal_ctx, udi, + "input.x11_driver", driver->driverName); + + /* The hal interface requires this to be set, but the + * device set in the xorg.conf has also the property + * of not matching the hal name. + * This also causes hal.c:device_added() "fail" because + * it will not find the path of the device. + * But this is probably the better workaround, as keyboards + * dont usually have an explicit device, and the /dev/mouse + * similar doesn't work properly with hal (weird things will + * happen, because it will end reading the same events from 2 + * descriptors usually, i.e. a click will become double click, + * etc. + */ + libhal_device_remove_property(hal_ctx, udi, + "input.device", NULL); + + idev = local->conf_idev; + for (options = local->options; + options; + options = options->list.next) { +#define check_option() options->opt_used && (driver_type & type) +#define check_option_string(x_name, hal_name) \ + if (check_option() && nameCompare(options->opt_name, x_name) == 0) \ + set_prop_string(hal_ctx, udi, hal_name, options->opt_val) + +#if 0 /* ... */ + /* If it is set, it means that the calling function should + * not fail, usually hal.c:device_added(). + */ + check_option_string("device", "input.device"); +#endif + + check_option_string("xkb_rules", "input.xkb.rules"); + check_option_string("xkb_model", "input.xkb.model"); + check_option_string("xkb_layout", "input.xkb.layout"); + check_option_string("xkb_variant", "input.xkb.variant"); + check_option_string("xkb_variant", "input.xkb.variant"); + if (check_option() && + nameCompare(options->opt_name, "xkb_options") == 0) { + char *ptr, *str; + + /* XXX No error checking, just restart from scratch + * in case value already exists, possibly set at another + * X session */ + libhal_device_remove_property(hal_ctx, udi, + "input.xkb.options", NULL); + + str = Xstrdup(options->opt_val); + for (ptr = strtok(str, " \t,"); + ptr; + ptr = strtok(NULL, " \t,")) { + append_prop_string(hal_ctx, udi, + "input.xkb.options", ptr); + } + Xfree(str); + } + } + } + } + } +} + +static int +set_prop_string(LibHalContext *hal_ctx, const char *udi, + const char *name, const char *value) +{ + int result; + + result = libhal_device_set_property_string(hal_ctx, udi, name, value, NULL); + DebugF(" [config/hal] setting %s as %s on %s returned %d\n", + name, value, udi, result); + + return (result); +} + +static int +append_prop_string(LibHalContext *hal_ctx, const char *udi, + const char *name, const char *value) +{ + int result; + + result = libhal_device_property_strlist_append(hal_ctx, udi, + name, value, NULL); + DebugF(" [config/hal] appending %s to %s on %s returned %d\n", + value, name, udi, result); + + return (result); +} + --- xorg-server-1.4/config/config-backends.h.hal 2007-11-20 16:18:45.000000000 -0200 +++ xorg-server-1.4/config/config-backends.h 2007-11-21 12:02:41.000000000 -0200 @@ -30,6 +30,12 @@ #ifdef HAVE_DBUS #include +#ifdef CONFIG_HAL +#define TYPE_NONE 0 +#define TYPE_KEYS 1 +#define TYPE_POINTER 2 +#endif + typedef void (*config_dbus_core_connect_hook)(DBusConnection *connection, void *data); typedef void (*config_dbus_core_disconnect_hook)(void *data);