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.
This commit is contained in:
parent
8bfa41e1bf
commit
1cdadc2f43
|
@ -1,10 +1,19 @@
|
|||
AM_CFLAGS = @DIX_CFLAGS@
|
||||
|
||||
noinst_LIBRARIES = libconfig.a
|
||||
libconfig_a_SOURCES = config.c
|
||||
|
||||
if HAVE_DBUS
|
||||
AM_CFLAGS += @DBUS_CFLAGS@
|
||||
libconfig_a_SOURCES += dbus-core.c
|
||||
endif
|
||||
|
||||
if CONFIG_DBUS_API
|
||||
dbusconfigdir = $(sysconfdir)/dbus-1/system.d
|
||||
dbusconfig_DATA = xorg-server.conf
|
||||
|
||||
noinst_LIBRARIES = libconfig.a
|
||||
|
||||
libconfig_a_SOURCES = config.c
|
||||
libconfig_a_SOURCES += dbus.c
|
||||
endif
|
||||
|
||||
EXTRA_DIST = xorg-server.conf
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders and/or authors
|
||||
* not be used in advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission. The copyright holders
|
||||
* and/or authors make no representations about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS AND/OR AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD
|
||||
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR AUTHORS BE LIABLE
|
||||
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
typedef void (*config_dbus_core_connect_hook)(DBusConnection *connection,
|
||||
void *data);
|
||||
typedef void (*config_dbus_core_disconnect_hook)(void *data);
|
||||
|
||||
struct config_dbus_core_hook {
|
||||
config_dbus_core_connect_hook connect;
|
||||
config_dbus_core_disconnect_hook disconnect;
|
||||
void *data;
|
||||
|
||||
struct config_dbus_core_hook *next;
|
||||
};
|
||||
|
||||
int config_dbus_core_init(void);
|
||||
void config_dbus_core_fini(void);
|
||||
int config_dbus_core_add_hook(struct config_dbus_core_hook *hook);
|
||||
void config_dbus_core_remove_hook(struct config_dbus_core_hook *hook);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DBUS_API
|
||||
int config_dbus_init(void);
|
||||
void config_dbus_fini(void);
|
||||
#endif
|
494
config/config.c
494
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"
|
||||
#include "config-backends.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)
|
||||
void
|
||||
config_init()
|
||||
{
|
||||
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;
|
||||
#if defined(CONFIG_DBUS_API)
|
||||
if (config_dbus_core_init()) {
|
||||
if (!config_dbus_init())
|
||||
ErrorF("[config] failed to initialise D-Bus API\n");
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
else {
|
||||
ErrorF("[config] failed to initialise D-Bus core\n");
|
||||
}
|
||||
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
configInitialise(void)
|
||||
config_fini()
|
||||
{
|
||||
TimerSet(NULL, 0, 1, configReconnect, NULL);
|
||||
#if defined(CONFIG_DBUS_API)
|
||||
config_dbus_fini();
|
||||
config_dbus_core_fini();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
configFini(void)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !HAVE_DBUS */
|
||||
|
||||
void
|
||||
configInitialise()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
configFini()
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* HAVE_DBUS */
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* 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
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders and/or authors
|
||||
* not be used in advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission. The copyright holders
|
||||
* and/or authors make no representations about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS AND/OR AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD
|
||||
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR AUTHORS BE LIABLE
|
||||
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#define DBUS_API_SUBJECT_TO_CHANGE
|
||||
#include <dbus/dbus.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "config-backends.h"
|
||||
#include "dix.h"
|
||||
#include "os.h"
|
||||
|
||||
/* How often to attempt reconnecting when we get booted off the bus. */
|
||||
#define RECONNECT_DELAY (10 * 1000) /* in ms */
|
||||
|
||||
struct dbus_core_info {
|
||||
int fd;
|
||||
DBusConnection *connection;
|
||||
OsTimerPtr timer;
|
||||
struct config_dbus_core_hook *hooks;
|
||||
};
|
||||
static struct dbus_core_info bus_info;
|
||||
|
||||
static CARD32 reconnect_timer(OsTimerPtr timer, CARD32 time, pointer arg);
|
||||
|
||||
static void
|
||||
wakeup_handler(pointer data, int err, pointer read_mask)
|
||||
{
|
||||
struct dbus_core_info *info = data;
|
||||
|
||||
if (info->connection && FD_ISSET(info->fd, (fd_set *) read_mask))
|
||||
dbus_connection_read_write_dispatch(info->connection, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
block_handler(pointer data, struct timeval **tv, pointer read_mask)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect (if we haven't already been forcefully disconnected), clean up
|
||||
* after ourselves, and call all registered disconnect hooks.
|
||||
*/
|
||||
static void
|
||||
teardown(void)
|
||||
{
|
||||
struct config_dbus_core_hook *hook;
|
||||
|
||||
if (bus_info.timer) {
|
||||
TimerCancel(bus_info.timer);
|
||||
bus_info.timer = NULL;
|
||||
}
|
||||
|
||||
/* We should really have pre-disconnect hooks and run them here, for
|
||||
* completeness. But then it gets awkward, given that you can't
|
||||
* guarantee that they'll be called ... */
|
||||
if (bus_info.connection)
|
||||
dbus_connection_unref(bus_info.connection);
|
||||
|
||||
RemoveBlockAndWakeupHandlers(block_handler, wakeup_handler, &bus_info);
|
||||
RemoveGeneralSocket(bus_info.fd);
|
||||
bus_info.fd = -1;
|
||||
bus_info.connection = NULL;
|
||||
|
||||
for (hook = bus_info.hooks; hook; hook = hook->next) {
|
||||
if (hook->disconnect)
|
||||
hook->disconnect(hook->data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
static DBusHandlerResult
|
||||
message_filter(DBusConnection *connection, DBusMessage *message, void *data)
|
||||
{
|
||||
/* If we get disconnected, then take everything down, and attempt to
|
||||
* reconnect immediately (assuming it's just a restart). The
|
||||
* connection isn't valid at this point, so throw it out immediately. */
|
||||
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL,
|
||||
"Disconnected")) {
|
||||
DebugF("[config/dbus-core] disconnected from bus\n");
|
||||
bus_info.connection = NULL;
|
||||
teardown();
|
||||
|
||||
bus_info.timer = TimerSet(NULL, 0, 1, reconnect_timer, NULL);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to connect to the system bus, and set a filter to deal with
|
||||
* disconnection (see message_filter above).
|
||||
*
|
||||
* @return 1 on success, 0 on failure.
|
||||
*/
|
||||
static int
|
||||
connect_to_bus(void)
|
||||
{
|
||||
DBusError error;
|
||||
struct config_dbus_core_hook *hook;
|
||||
|
||||
dbus_error_init(&error);
|
||||
bus_info.connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
if (!bus_info.connection || dbus_error_is_set(&error)) {
|
||||
DebugF("[config/dbus-core] error connecting to system bus: %s (%s)\n",
|
||||
error.name, error.message);
|
||||
goto err_begin;
|
||||
}
|
||||
|
||||
/* Thankyou. Really, thankyou. */
|
||||
dbus_connection_set_exit_on_disconnect(bus_info.connection, FALSE);
|
||||
|
||||
if (!dbus_connection_get_unix_fd(bus_info.connection, &bus_info.fd)) {
|
||||
ErrorF("[config/dbus-core] couldn't get fd for system bus\n");
|
||||
goto err_unref;
|
||||
}
|
||||
|
||||
if (!dbus_connection_add_filter(bus_info.connection, message_filter,
|
||||
&bus_info, NULL)) {
|
||||
ErrorF("[config/dbus-core] couldn't add filter: %s (%s)\n", error.name,
|
||||
error.message);
|
||||
goto err_fd;
|
||||
}
|
||||
|
||||
dbus_error_free(&error);
|
||||
AddGeneralSocket(bus_info.fd);
|
||||
|
||||
RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, &bus_info);
|
||||
|
||||
for (hook = bus_info.hooks; hook; hook = hook->next) {
|
||||
if (hook->connect)
|
||||
hook->connect(bus_info.connection, hook->data);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
err_fd:
|
||||
bus_info.fd = -1;
|
||||
err_unref:
|
||||
dbus_connection_unref(bus_info.connection);
|
||||
bus_info.connection = NULL;
|
||||
err_begin:
|
||||
dbus_error_free(&error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CARD32
|
||||
reconnect_timer(OsTimerPtr timer, CARD32 time, pointer arg)
|
||||
{
|
||||
if (connect_to_bus()) {
|
||||
bus_info.timer = NULL;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return RECONNECT_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
config_dbus_core_add_hook(struct config_dbus_core_hook *hook)
|
||||
{
|
||||
struct config_dbus_core_hook **prev;
|
||||
|
||||
for (prev = &bus_info.hooks; *prev; prev = &(*prev)->next)
|
||||
;
|
||||
*prev = hook;
|
||||
|
||||
/* If we're already connected, call the connect hook. */
|
||||
if (bus_info.connection)
|
||||
hook->connect(bus_info.connection, hook->data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
config_dbus_core_remove_hook(struct config_dbus_core_hook *hook)
|
||||
{
|
||||
struct config_dbus_core_hook **prev;
|
||||
|
||||
for (prev = &bus_info.hooks; *prev; prev = &(*prev)->next) {
|
||||
if (*prev == hook)
|
||||
*prev = hook->next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
config_dbus_core_init(void)
|
||||
{
|
||||
memset(&bus_info, 0, sizeof(bus_info));
|
||||
bus_info.fd = -1;
|
||||
bus_info.hooks = NULL;
|
||||
bus_info.connection = NULL;
|
||||
bus_info.timer = TimerSet(NULL, 0, 1, reconnect_timer, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
config_dbus_core_fini(void)
|
||||
{
|
||||
teardown();
|
||||
}
|
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
* 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
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of the copyright holders and/or authors
|
||||
* not be used in advertising or publicity pertaining to distribution of the
|
||||
* software without specific, written prior permission. The copyright holders
|
||||
* and/or authors make no representations about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS AND/OR AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD
|
||||
* TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND/OR AUTHORS BE LIABLE
|
||||
* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#define DBUS_API_SUBJECT_TO_CHANGE
|
||||
#include <dbus/dbus.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/X.h>
|
||||
|
||||
#include "config-backends.h"
|
||||
#include "opaque.h" /* for 'display': there should be a better way. */
|
||||
#include "input.h"
|
||||
#include "inputstr.h"
|
||||
|
||||
#define API_VERSION 1
|
||||
|
||||
#define MATCH_RULE "type='method_call',interface='org.x.config.input'"
|
||||
|
||||
#define MALFORMED_MSG "[config/dbus] 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; }
|
||||
|
||||
struct connection_info {
|
||||
char busobject[32];
|
||||
char busname[64];
|
||||
DBusConnection *connection;
|
||||
};
|
||||
|
||||
static void
|
||||
reset_info(struct connection_info *info)
|
||||
{
|
||||
info->connection = NULL;
|
||||
info->busname[0] = '\0';
|
||||
info->busobject[0] = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
add_device(DBusMessage *message, DBusMessage *reply, DBusError *error)
|
||||
{
|
||||
DBusMessageIter iter, reply_iter, subiter;
|
||||
InputOption *tmpo = NULL, *options = NULL;
|
||||
char *tmp = NULL;
|
||||
int ret, err;
|
||||
DeviceIntPtr dev = NULL;
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter)) {
|
||||
ErrorF("[config/dbus] couldn't initialise iterator\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
dbus_message_iter_init_append(reply, &reply_iter);
|
||||
|
||||
options = xcalloc(sizeof(*options), 1);
|
||||
if (!options) {
|
||||
ErrorF("[config/dbus] couldn't allocate option\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
options->key = xstrdup("_source");
|
||||
options->value = xstrdup("client/dbus");
|
||||
if (!options->key || !options->value) {
|
||||
ErrorF("[config/dbus] couldn't allocate first key/value pair\n");
|
||||
ret = BadAlloc;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
/* signature should be [ss][ss]... */
|
||||
while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY) {
|
||||
tmpo = xcalloc(sizeof(*tmpo), 1);
|
||||
if (!tmpo) {
|
||||
ErrorF("[config/dbus] 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();
|
||||
/* The _ prefix refers to internal settings, and may not be given by
|
||||
* the client. */
|
||||
if (tmp[0] == '_') {
|
||||
ErrorF("[config/dbus] attempted subterfuge: option name %s given\n",
|
||||
tmp);
|
||||
MALFORMED_MESSAGE();
|
||||
}
|
||||
options->key = xstrdup(tmp);
|
||||
if (!options->key) {
|
||||
ErrorF("[config/dbus] 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/dbus] NewInputDeviceRequest failed\n");
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
DebugF("[config/dbus] NewInputDeviceRequest provided no device\n");
|
||||
ret = BadImplementation;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32,
|
||||
&dev->id)) {
|
||||
ErrorF("[config/dbus] couldn't append to iterator\n");
|
||||
ret = BadAlloc;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
unwind:
|
||||
if (ret != Success) {
|
||||
if (dev)
|
||||
RemoveDevice(dev);
|
||||
|
||||
err = -ret;
|
||||
dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &err);
|
||||
}
|
||||
|
||||
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
|
||||
remove_device(DBusMessage *message, DBusMessage *reply, DBusError *error)
|
||||
{
|
||||
int deviceid, ret, err;
|
||||
DeviceIntPtr dev;
|
||||
DBusMessageIter iter, reply_iter;
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter)) {
|
||||
ErrorF("[config] failed to init iterator\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
dbus_message_iter_init_append(reply, &reply_iter);
|
||||
|
||||
if (!dbus_message_get_args(message, error, DBUS_TYPE_INT32,
|
||||
&deviceid, DBUS_TYPE_INVALID)) {
|
||||
MALFORMED_MESSAGE_ERROR();
|
||||
}
|
||||
|
||||
dev = LookupDeviceIntRec(deviceid);
|
||||
if (!dev) {
|
||||
DebugF("[config] bogus device id %d given\n", deviceid);
|
||||
ret = BadMatch;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
DebugF("[config] removing device %s (id %d)\n", dev->name, deviceid);
|
||||
|
||||
/* Call PIE here so we don't try to dereference a device that's
|
||||
* already been removed. */
|
||||
OsBlockSignals();
|
||||
ProcessInputEvents();
|
||||
DeleteInputDeviceRequest(dev);
|
||||
OsReleaseSignals();
|
||||
|
||||
ret = Success;
|
||||
|
||||
unwind:
|
||||
err = (ret == Success) ? ret : -ret;
|
||||
dbus_message_iter_append_basic(&reply_iter, DBUS_TYPE_INT32, &err);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
list_devices(DBusMessage *message, DBusMessage *reply, DBusError *error)
|
||||
{
|
||||
DeviceIntPtr dev;
|
||||
DBusMessageIter iter;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
|
||||
for (dev = inputInfo.devices; dev; dev = dev->next) {
|
||||
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32,
|
||||
&dev->id)) {
|
||||
ErrorF("[config/dbus] couldn't append to iterator\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
|
||||
&dev->name)) {
|
||||
ErrorF("[config/dbus] couldn't append to iterator\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
message_handler(DBusConnection *connection, DBusMessage *message, void *data)
|
||||
{
|
||||
DBusError error;
|
||||
DBusMessage *reply;
|
||||
struct connection_info *info = data;
|
||||
|
||||
/* ret is the overall D-Bus handler result, whereas err is the internal
|
||||
* X error from our individual functions. */
|
||||
int ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
int err;
|
||||
|
||||
DebugF("[config/dbus] received a message for %s\n",
|
||||
dbus_message_get_interface(message));
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply) {
|
||||
ErrorF("[config/dbus] failed to create reply\n");
|
||||
ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
goto err_start;
|
||||
}
|
||||
|
||||
if (strcmp(dbus_message_get_member(message), "add") == 0)
|
||||
err = add_device(message, reply, &error);
|
||||
else if (strcmp(dbus_message_get_member(message), "remove") == 0)
|
||||
err = remove_device(message, reply, &error);
|
||||
else if (strcmp(dbus_message_get_member(message), "listDevices") == 0)
|
||||
err = list_devices(message, reply, &error);
|
||||
else
|
||||
goto err_reply;
|
||||
|
||||
/* Failure to allocate is a special case. */
|
||||
if (err == BadAlloc) {
|
||||
ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
goto err_reply;
|
||||
}
|
||||
|
||||
/* While failure here is always an OOM, we don't return that,
|
||||
* since that would result in devices being double-added/removed. */
|
||||
if (dbus_connection_send(info->connection, reply, NULL))
|
||||
dbus_connection_flush(info->connection);
|
||||
else
|
||||
ErrorF("[config/dbus] failed to send reply\n");
|
||||
|
||||
ret = DBUS_HANDLER_RESULT_HANDLED;
|
||||
|
||||
err_reply:
|
||||
dbus_message_unref(reply);
|
||||
err_start:
|
||||
dbus_error_free(&error);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
connect_hook(DBusConnection *connection, void *data)
|
||||
{
|
||||
DBusError error;
|
||||
DBusObjectPathVTable vtable = { .message_function = message_handler, };
|
||||
struct connection_info *info = data;
|
||||
|
||||
info->connection = connection;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (!dbus_bus_request_name(info->connection, info->busname,
|
||||
0, &error)) {
|
||||
ErrorF("[config/dbus] couldn't take over org.x.config: %s (%s)\n",
|
||||
error.name, error.message);
|
||||
goto err_start;
|
||||
}
|
||||
|
||||
/* blocks until we get a reply. */
|
||||
dbus_bus_add_match(info->connection, MATCH_RULE, &error);
|
||||
if (dbus_error_is_set(&error)) {
|
||||
ErrorF("[config/dbus] couldn't add match: %s (%s)\n", error.name,
|
||||
error.message);
|
||||
goto err_name;
|
||||
}
|
||||
|
||||
if (!dbus_connection_register_object_path(info->connection,
|
||||
info->busobject, &vtable,
|
||||
info)) {
|
||||
ErrorF("[config/dbus] couldn't register object path\n");
|
||||
goto err_match;
|
||||
}
|
||||
|
||||
DebugF("[dbus] registered %s, %s\n", info->busname, info->busobject);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return;
|
||||
|
||||
err_match:
|
||||
dbus_bus_remove_match(info->connection, MATCH_RULE, &error);
|
||||
err_name:
|
||||
dbus_bus_release_name(info->connection, info->busname, &error);
|
||||
err_start:
|
||||
dbus_error_free(&error);
|
||||
|
||||
reset_info(info);
|
||||
}
|
||||
|
||||
static void
|
||||
disconnect_hook(void *data)
|
||||
{
|
||||
struct connection_info *info = data;
|
||||
|
||||
reset_info(info);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
pre_disconnect_hook(void)
|
||||
{
|
||||
DBusError error;
|
||||
|
||||
dbus_error_init(&error);
|
||||
dbus_connection_unregister_object_path(connection_data->connection,
|
||||
connection_data->busobject);
|
||||
dbus_bus_remove_match(connection_data->connection, MATCH_RULE,
|
||||
&error);
|
||||
dbus_bus_release_name(connection_data->connection,
|
||||
connection_data->busname, &error);
|
||||
dbus_error_free(&error);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct connection_info connection_data;
|
||||
static struct config_dbus_core_hook core_hook = {
|
||||
.connect = connect_hook,
|
||||
.disconnect = disconnect_hook,
|
||||
.data = &connection_data,
|
||||
};
|
||||
|
||||
int
|
||||
config_dbus_init(void)
|
||||
{
|
||||
snprintf(connection_data.busname, sizeof(connection_data.busname),
|
||||
"org.x.config.display%d", atoi(display));
|
||||
snprintf(connection_data.busobject, sizeof(connection_data.busobject),
|
||||
"/org/x/config/%d", atoi(display));
|
||||
|
||||
return config_dbus_core_add_hook(&core_hook);
|
||||
}
|
||||
|
||||
void
|
||||
config_dbus_fini(void)
|
||||
{
|
||||
config_dbus_core_remove_hook(&core_hook);
|
||||
}
|
35
configure.ac
35
configure.ac
|
@ -519,7 +519,7 @@ AC_ARG_ENABLE(fontcache, AS_HELP_STRING([--enable-fontcache], [Build FontCa
|
|||
AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes])
|
||||
AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--disable-xf86bigfont], [Build XF86 Big Font extension (default: enabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=yes])
|
||||
AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes])
|
||||
AC_ARG_ENABLE(dbus, AS_HELP_STRING([--disable-dbus], [Build D-BUS support (default: auto)]), [DBUS=$enableval], [DBUS=auto])
|
||||
AC_ARG_ENABLE(config-dbus, AS_HELP_STRING([--disable-config-dbus], [Build D-BUS support (default: auto)]), [CONFIG_DBUS_API=$enableval], [CONFIG_DBUS_API=auto])
|
||||
AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes])
|
||||
|
||||
dnl DDXes.
|
||||
|
@ -619,17 +619,32 @@ dnl Core modules for most extensions, et al.
|
|||
REQUIRED_MODULES="[randrproto >= 1.2] renderproto [fixesproto >= 4.0] [damageproto >= 1.1] xcmiscproto xextproto [xproto >= 7.0.9] xtrans [scrnsaverproto >= 1.1] bigreqsproto resourceproto fontsproto [inputproto >= 1.4.2] [kbproto >= 1.0.3]"
|
||||
REQUIRED_LIBS="xfont xau fontenc $PIXMAN"
|
||||
|
||||
if test "x$DBUS" = xauto; then
|
||||
PKG_CHECK_MODULES(DBUS, dbus-1, [DBUS=yes], [DBUS=no])
|
||||
dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas
|
||||
dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config
|
||||
dnl API.
|
||||
PKG_CHECK_MODULES(DBUS, dbus-1, [HAVE_DBUS=yes], [HAVE_DBUS=no])
|
||||
if test "x$HAVE_DBUS" = xyes; then
|
||||
AC_DEFINE(HAVE_DBUS, 1, [Have D-Bus support])
|
||||
fi
|
||||
if test "x$DBUS" = xyes; then
|
||||
PKG_CHECK_MODULES(DBUS, dbus-1)
|
||||
AC_DEFINE(HAVE_DBUS, 1, [Have D-BUS support])
|
||||
REQUIRED_MODULES="$REQUIRED_MODULES dbus-1"
|
||||
REQUIRED_LIBS="$REQUIRED_LIBS dbus-1"
|
||||
AM_CONDITIONAL(HAVE_DBUS, [test "x$HAVE_DBUS" = xyes])
|
||||
|
||||
if test "x$CONFIG_DBUS_API" = xauto; then
|
||||
CONFIG_DBUS_API="$HAVE_DBUS"
|
||||
fi
|
||||
if test "x$CONFIG_DBUS_API" = xyes; then
|
||||
if ! test "x$HAVE_DBUS" = xyes; then
|
||||
AC_MSG_ERROR([D-Bus configuration API requested, but D-Bus is not installed.])
|
||||
fi
|
||||
|
||||
AC_DEFINE(CONFIG_DBUS_API, 1, [Use the D-Bus input configuration API])
|
||||
CONFIG_LIB='$(top_builddir)/config/libconfig.a'
|
||||
NEED_DBUS="yes"
|
||||
fi
|
||||
AM_CONDITIONAL(CONFIG_DBUS_API, [test "x$CONFIG_DBUS_API" = xyes])
|
||||
|
||||
if test "x$NEED_DBUS" = xyes; then
|
||||
REQUIRED_LIBS="$REQUIRED_LIBS dbus-1"
|
||||
fi
|
||||
CONFIG_LIB='$(top_builddir)/config/libconfig.a'
|
||||
AM_CONDITIONAL(DBUS, [test "x$DBUS" = xyes])
|
||||
|
||||
AM_CONDITIONAL(XV, [test "x$XV" = xyes])
|
||||
if test "x$XV" = xyes; then
|
||||
|
|
|
@ -310,7 +310,7 @@ main(int argc, char *argv[], char *envp[])
|
|||
InitBlockAndWakeupHandlers();
|
||||
/* Perform any operating system dependent initializations you'd like */
|
||||
OsInit();
|
||||
configInitialise();
|
||||
config_init();
|
||||
if(serverGeneration == 1)
|
||||
{
|
||||
CreateWellKnownSockets();
|
||||
|
@ -482,7 +482,7 @@ main(int argc, char *argv[], char *envp[])
|
|||
FreeAllResources();
|
||||
#endif
|
||||
|
||||
configFini();
|
||||
config_fini();
|
||||
CloseDownDevices();
|
||||
for (i = screenInfo.numScreens - 1; i >= 0; i--)
|
||||
{
|
||||
|
|
|
@ -465,9 +465,12 @@
|
|||
/* Define to 1 if modules should avoid the libcwrapper */
|
||||
#undef NO_LIBCWRAPPER
|
||||
|
||||
/* Support D-BUS */
|
||||
/* Support D-Bus */
|
||||
#undef HAVE_DBUS
|
||||
|
||||
/* Support the D-Bus hotplug API */
|
||||
#undef CONFIG_DBUS_API
|
||||
|
||||
/* Use only built-in fonts */
|
||||
#undef BUILTIN_FONTS
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -21,10 +21,10 @@
|
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
#ifndef HOTPLUG_H
|
||||
#define HOTPLUG_H
|
||||
|
||||
void configInitialise(void);
|
||||
void configFini(void);
|
||||
void config_init(void);
|
||||
void config_fini(void);
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
#endif /* HOTPLUG_H */
|
||||
|
|
Loading…
Reference in New Issue