diff options
author | Daniel Stone <daniel@fooishbar.org> | 2007-07-08 14:28:58 +0300 |
---|---|---|
committer | Daniel Stone <daniel@fooishbar.org> | 2007-08-01 01:53:31 +0300 |
commit | 1cdadc2f43d9069572814510d04b1a560c488fcb (patch) | |
tree | 09e403c8ff69abbc00e635c787c83e43fd3a26d7 /config/config.c | |
parent | 8bfa41e1bf3f588780d7e9f6f900b1fde0570a7e (diff) |
Hotplug: Separate D-Bus into core and hotplug API components
Break up D-Bus into two components: a D-Bus core that can be used by any
part of the server (for the moment, just the D-Bus hotplug API, and the
forthcoming HAL hotplug API), and the old D-Bus hotplug API.
Diffstat (limited to 'config/config.c')
-rw-r--r-- | config/config.c | 494 |
1 files changed, 16 insertions, 478 deletions
diff --git a/config/config.c b/config/config.c index 9b38faf49..a6d36c0ee 100644 --- a/config/config.c +++ b/config/config.c @@ -1,5 +1,5 @@ /* - * Copyright © 2006 Daniel Stone + * Copyright © 2006-2007 Daniel Stone * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -25,490 +25,28 @@ #include <dix-config.h> #endif -#ifdef HAVE_DBUS -#define DBUS_API_SUBJECT_TO_CHANGE -#include <dbus/dbus.h> -#include <string.h> -#include <sys/select.h> - -#include <X11/X.h> - -#include "opaque.h" /* for 'display': there has to be a better way */ - /* the above comment lies. there is no better way. */ -#include "input.h" -#include "inputstr.h" #include "hotplug.h" -#include "os.h" - -#define CONFIG_MATCH_RULE "type='method_call',interface='org.x.config.input'" - -#define MALFORMED_MSG "[config] malformed message, dropping" -#define MALFORMED_MESSAGE() { DebugF(MALFORMED_MSG "\n"); \ - ret = BadValue; \ - goto unwind; } -#define MALFORMED_MESSAGE_ERROR() { DebugF(MALFORMED_MSG ": %s, %s", \ - error->name, error->message); \ - ret = BadValue; \ - goto unwind; } - -/* How often to attempt reconnecting when we get booted off the bus. */ -#define RECONNECT_DELAY 10000 /* in ms */ - -struct config_data { - int fd; - DBusConnection *connection; - char busobject[32]; - char busname[64]; -}; - -static struct config_data *configData; - -static CARD32 configReconnect(OsTimerPtr timer, CARD32 time, pointer arg); - -static void -configWakeupHandler(pointer blockData, int err, pointer pReadMask) -{ - struct config_data *data = blockData; - - if (data->connection && FD_ISSET(data->fd, (fd_set *) pReadMask)) - dbus_connection_read_write_dispatch(data->connection, 0); -} - -static void -configBlockHandler(pointer data, struct timeval **tv, pointer pReadMask) -{ -} - -static void -configTeardown(void) -{ - if (configData) { - RemoveGeneralSocket(configData->fd); - RemoveBlockAndWakeupHandlers(configBlockHandler, configWakeupHandler, - configData); - xfree(configData); - configData = NULL; - } -} - -static int -configAddDevice(DBusMessage *message, DBusMessageIter *iter, - DBusMessage *reply, DBusMessageIter *r_iter, - DBusError *error) -{ - DBusMessageIter subiter; - InputOption *tmpo = NULL, *options = NULL; - char *tmp = NULL; - int ret = BadMatch; - DeviceIntPtr dev = NULL; - - DebugF("[config] adding device\n"); - - /* signature should be [ss][ss]... */ - options = (InputOption *) xcalloc(sizeof(InputOption), 1); - if (!options) { - ErrorF("[config] couldn't allocate option\n"); - return BadAlloc; - } - - options->key = xstrdup("_source"); - options->value = xstrdup("client/dbus"); - if(!options->key || !options->value) { - ErrorF("[config] couldn't allocate first key/value pair\n"); - ret = BadAlloc; - goto unwind; - } - - while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_ARRAY) { - tmpo = (InputOption *) xcalloc(sizeof(InputOption), 1); - if (!tmpo) { - ErrorF("[config] couldn't allocate option\n"); - ret = BadAlloc; - goto unwind; - } - tmpo->next = options; - options = tmpo; - - dbus_message_iter_recurse(iter, &subiter); - - if (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_STRING) - MALFORMED_MESSAGE(); - - dbus_message_iter_get_basic(&subiter, &tmp); - if (!tmp) - MALFORMED_MESSAGE(); - if (tmp[0] == '_') { - ErrorF("[config] attempted subterfuge: option name %s given\n", - tmp); - MALFORMED_MESSAGE(); - } - options->key = xstrdup(tmp); - if (!options->key) { - ErrorF("[config] couldn't duplicate key!\n"); - ret = BadAlloc; - goto unwind; - } - - if (!dbus_message_iter_has_next(&subiter)) - MALFORMED_MESSAGE(); - dbus_message_iter_next(&subiter); - if (dbus_message_iter_get_arg_type(&subiter) != DBUS_TYPE_STRING) - MALFORMED_MESSAGE(); - - dbus_message_iter_get_basic(&subiter, &tmp); - if (!tmp) - MALFORMED_MESSAGE(); - options->value = xstrdup(tmp); - if (!options->value) { - ErrorF("[config] couldn't duplicate option!\n"); - ret = BadAlloc; - goto unwind; - } - - dbus_message_iter_next(iter); - } - - ret = NewInputDeviceRequest(options, &dev); - if (ret != Success) { - DebugF("[config] NewInputDeviceRequest failed\n"); - goto unwind; - } - - if (!dev) { - DebugF("[config] NewInputDeviceRequest succeeded, without device\n"); - ret = BadMatch; - goto unwind; - } - - if (!dbus_message_iter_append_basic(r_iter, DBUS_TYPE_INT32, &(dev->id))) { - ErrorF("[config] couldn't append to iterator\n"); - ret = BadAlloc; - goto unwind; - } - -unwind: - if (dev && ret != Success) - RemoveDevice(dev); - - while (options) { - tmpo = options; - options = options->next; - if (tmpo->key) - xfree(tmpo->key); - if (tmpo->value) - xfree(tmpo->value); - xfree(tmpo); - } - - return ret; -} - -static int -configRemoveDevice(DBusMessage *message, DBusMessageIter *iter, - DBusError *error) -{ - int deviceid = -1; - int ret = BadMatch; - DeviceIntPtr pDev = NULL; - - if (!dbus_message_get_args(message, error, DBUS_TYPE_INT32, - &deviceid, DBUS_TYPE_INVALID)) { - MALFORMED_MESSAGE_ERROR(); - } - - if (deviceid < 0 || !(pDev = LookupDeviceIntRec(deviceid))) { - DebugF("[config] bogus device id %d given\n", deviceid); - ret = BadMatch; - goto unwind; - } - - DebugF("[config] removing device %s (id %d)\n", pDev->name, deviceid); - - /* Call PIE here so we don't try to dereference a device that's - * already been removed. */ - OsBlockSignals(); - ProcessInputEvents(); - DeleteInputDeviceRequest(pDev); - OsReleaseSignals(); - - return Success; - -unwind: - return ret; -} - -static int -configListDevices(DBusMessage *message, DBusMessageIter *iter, - DBusMessage *reply, DBusMessageIter *r_iter, - DBusError *error) -{ - DeviceIntPtr d; - int ret = BadMatch; - - for (d = inputInfo.devices; d; d = d->next) { - if (!dbus_message_iter_append_basic(r_iter, DBUS_TYPE_INT32, - &(d->id))) { - ErrorF("[config] couldn't append to iterator\n"); - ret = BadAlloc; - goto unwind; - } - if (!dbus_message_iter_append_basic(r_iter, DBUS_TYPE_STRING, - &(d->name))) { - ErrorF("[config] couldn't append to iterator\n"); - ret = BadAlloc; - goto unwind; - } - } - -unwind: - return ret; -} - -static DBusHandlerResult -configMessage(DBusConnection *connection, DBusMessage *message, void *closure) -{ - DBusMessageIter iter; - DBusError error; - DBusMessage *reply; - DBusMessageIter r_iter; - DBusConnection *bus = closure; - int ret = BadDrawable; /* nonsensical value */ - - dbus_error_init(&error); - - DebugF("[config] received a message\n"); - - if (strcmp(dbus_message_get_interface(message), - "org.x.config.input") == 0) { - - if (!(reply = dbus_message_new_method_return(message))) { - ErrorF("[config] failed to create the reply message\n"); - dbus_error_free(&error); - return DBUS_HANDLER_RESULT_NEED_MEMORY; - } - dbus_message_iter_init_append(reply, &r_iter); - - /* listDevices doesn't take any arguments */ - if (strcmp(dbus_message_get_member(message), "listDevices") == 0) - ret = configListDevices(message, NULL, reply, &r_iter, &error); - else - { - if (!dbus_message_iter_init(message, &iter)) { - ErrorF("[config] failed to init iterator\n"); - dbus_message_unref(reply); - dbus_error_free(&error); - return DBUS_HANDLER_RESULT_NEED_MEMORY; /* ?? */ - } - - if (strcmp(dbus_message_get_member(message), "add") == 0) - ret = configAddDevice(message, &iter, reply, &r_iter, &error); - else if (strcmp(dbus_message_get_member(message), "remove") == 0) - ret = configRemoveDevice(message, &iter, &error); - } - - if (ret != BadDrawable && ret != BadAlloc) { - if (!strlen(dbus_message_get_signature(reply))) - { - ret = -ret; /* return errors as negative numbers */ - if (!dbus_message_iter_append_basic(&r_iter, DBUS_TYPE_INT32, &ret)) { - ErrorF("[config] couldn't append to iterator\n"); - dbus_message_unref(reply); - dbus_error_free(&error); - return DBUS_HANDLER_RESULT_HANDLED; - } - } - - if (!dbus_connection_send(bus, reply, NULL)) - ErrorF("[config] failed to send reply\n"); - } - dbus_message_unref(reply); - dbus_connection_flush(bus); - } - - dbus_error_free(&error); - - if (ret == BadAlloc) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - else if (ret == BadDrawable) - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - else - return DBUS_HANDLER_RESULT_HANDLED; -} - -/** - * This is a filter, which only handles the disconnected signal, which - * doesn't go to the normal message handling function. This takes - * precedence over the message handling function, so have have to be - * careful to ignore anything we don't want to deal with here. - * - * Yes, this is brutally stupid. - */ -static DBusHandlerResult -configFilter(DBusConnection *connection, DBusMessage *message, void *closure) -{ - if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, - "Disconnected")) { - ErrorF("[dbus] disconnected from bus\n"); - TimerSet(NULL, 0, RECONNECT_DELAY, configReconnect, NULL); - configTeardown(); - return DBUS_HANDLER_RESULT_HANDLED; - } - - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -} - -static Bool -configSetup(void) -{ - DBusError error; - DBusObjectPathVTable vtable = { .message_function = configMessage }; - - if (!configData) - configData = (struct config_data *) xcalloc(sizeof(struct config_data), 1); - if (!configData) { - ErrorF("[dbus] failed to allocate data struct\n"); - return FALSE; - } - - dbus_error_init(&error); - configData->connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); - if (!configData->connection || dbus_error_is_set(&error)) { - DebugF("[dbus] some kind of error occurred while connecting: %s (%s)\n", - error.name, error.message); - dbus_error_free(&error); - xfree(configData); - configData = NULL; - return FALSE; - } - - dbus_connection_set_exit_on_disconnect(configData->connection, FALSE); - - if (!dbus_connection_get_unix_fd(configData->connection, &configData->fd)) { - dbus_connection_unref(configData->connection); - ErrorF("[dbus] couldn't get fd for bus\n"); - dbus_error_free(&error); - xfree(configData); - configData = NULL; - return FALSE; - } - - snprintf(configData->busname, sizeof(configData->busname), - "org.x.config.display%d", atoi(display)); - if (!dbus_bus_request_name(configData->connection, configData->busname, - 0, &error) || dbus_error_is_set(&error)) { - ErrorF("[dbus] couldn't take over org.x.config: %s (%s)\n", - error.name, error.message); - dbus_error_free(&error); - dbus_connection_unref(configData->connection); - xfree(configData); - configData = NULL; - return FALSE; - } - - /* blocks until we get a reply. */ - dbus_bus_add_match(configData->connection, CONFIG_MATCH_RULE, &error); - if (dbus_error_is_set(&error)) { - ErrorF("[dbus] couldn't match X.Org rule: %s (%s)\n", error.name, - error.message); - dbus_error_free(&error); - dbus_bus_release_name(configData->connection, configData->busname, - &error); - dbus_connection_unref(configData->connection); - xfree(configData); - configData = NULL; - return FALSE; - } - - if (!dbus_connection_add_filter(configData->connection, configFilter, - configData, NULL)) { - - ErrorF("[dbus] couldn't add signal filter: %s (%s)\n", error.name, - error.message); - dbus_error_free(&error); - dbus_bus_release_name(configData->connection, configData->busname, - &error); - dbus_bus_remove_match(configData->connection, CONFIG_MATCH_RULE, - &error); - dbus_connection_unref(configData->connection); - xfree(configData); - configData = NULL; - return FALSE; - } - - snprintf(configData->busobject, sizeof(configData->busobject), - "/org/x/config/%d", atoi(display)); - if (!dbus_connection_register_object_path(configData->connection, - configData->busobject, &vtable, - configData->connection)) { - ErrorF("[dbus] couldn't register object path\n"); - dbus_bus_release_name(configData->connection, configData->busname, - &error); - dbus_bus_remove_match(configData->connection, CONFIG_MATCH_RULE, - &error); - dbus_connection_unref(configData->connection); - dbus_error_free(&error); - xfree(configData); - configData = NULL; - return FALSE; - } - - DebugF("[dbus] registered object path %s\n", configData->busobject); - - dbus_error_free(&error); - AddGeneralSocket(configData->fd); - - RegisterBlockAndWakeupHandlers(configBlockHandler, configWakeupHandler, - configData); - - return TRUE; -} - -static CARD32 -configReconnect(OsTimerPtr timer, CARD32 time, pointer arg) -{ - if (configSetup()) - return 0; - else - return RECONNECT_DELAY; -} - -void -configInitialise(void) -{ - TimerSet(NULL, 0, 1, configReconnect, NULL); -} +#include "config-backends.h" void -configFini(void) +config_init() { - DBusError error; - - if (configData) { - dbus_error_init(&error); - dbus_connection_unregister_object_path(configData->connection, - configData->busobject); - dbus_connection_remove_filter(configData->connection, configFilter, - configData); - dbus_bus_remove_match(configData->connection, CONFIG_MATCH_RULE, - &error); - dbus_bus_release_name(configData->connection, configData->busname, - &error); - dbus_connection_unref(configData->connection); - dbus_error_free(&error); - configTeardown(); +#if defined(CONFIG_DBUS_API) + if (config_dbus_core_init()) { + if (!config_dbus_init()) + ErrorF("[config] failed to initialise D-Bus API\n"); } -} - -#else /* !HAVE_DBUS */ - -void -configInitialise() -{ + else { + ErrorF("[config] failed to initialise D-Bus core\n"); + } +#endif } void -configFini() +config_fini() { +#if defined(CONFIG_DBUS_API) + config_dbus_fini(); + config_dbus_core_fini(); +#endif } - -#endif /* HAVE_DBUS */ |