mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-01-10 14:00:15 +01:00
Add initial DMX dbus configuration support.
This commit is contained in:
parent
90037b647b
commit
17d6281ea6
4 changed files with 526 additions and 3 deletions
|
|
@ -20,11 +20,19 @@ if BUILDDOCS
|
|||
SUBDIRS += doc
|
||||
endif
|
||||
|
||||
if CONFIG_DBUS_API
|
||||
DBUS_SRCS = dmxdbus.c dmxdbus.h
|
||||
DBUS_INCS = -I$(top_srcdir)/config
|
||||
DBUS_DEFS = @DBUS_CFLAGS@
|
||||
endif
|
||||
|
||||
AM_CFLAGS = \
|
||||
-DHAVE_DMX_CONFIG_H \
|
||||
$(DIX_CFLAGS) \
|
||||
$(GLX_INCS) \
|
||||
$(GLX_DEFS) \
|
||||
$(DBUS_INCS) \
|
||||
$(DBUS_DEFS) \
|
||||
$(DMX_CFLAGS) \
|
||||
@DMXMODULES_CFLAGS@
|
||||
|
||||
|
|
@ -76,7 +84,8 @@ Xdmx_SOURCES = dmx.c \
|
|||
dmxlaunch.h \
|
||||
$(top_srcdir)/mi/miinitext.c \
|
||||
$(top_srcdir)/fb/fbcmap_mi.c \
|
||||
$(GLX_SRCS)
|
||||
$(GLX_SRCS) \
|
||||
$(DBUS_SRCS)
|
||||
|
||||
|
||||
#if COMPOSITE
|
||||
|
|
|
|||
19
hw/dmx/dmx.c
19
hw/dmx/dmx.c
|
|
@ -72,6 +72,8 @@ extern int PanoramiXNumScreens;
|
|||
#include "randrstr.h"
|
||||
#endif
|
||||
|
||||
#include "dmxdbus.h"
|
||||
|
||||
extern void DMXExtensionInit(void);
|
||||
|
||||
static unsigned char DMXCode;
|
||||
|
|
@ -118,6 +120,15 @@ static int _DMXXineramaActive(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void DMXResetProc(ExtensionEntry *extEntry)
|
||||
{
|
||||
|
||||
#ifdef CONFIG_DBUS_API
|
||||
dmx_dbus_fini ();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/** Initialize the extension. */
|
||||
void DMXExtensionInit(void)
|
||||
{
|
||||
|
|
@ -125,9 +136,13 @@ void DMXExtensionInit(void)
|
|||
|
||||
if ((extEntry = AddExtension(DMX_EXTENSION_NAME, 0, 0,
|
||||
ProcDMXDispatch, SProcDMXDispatch,
|
||||
NULL, StandardMinorOpcode)))
|
||||
greater than screen count.:hw/dmx/dmx.c
|
||||
DMXResetProc, StandardMinorOpcode)))
|
||||
DMXCode = extEntry->base;
|
||||
|
||||
#ifdef CONFIG_DBUS_API
|
||||
dmx_dbus_init ();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void dmxSetScreenAttribute(int bit, DMXScreenAttributesPtr attr,
|
||||
|
|
|
|||
465
hw/dmx/dmxdbus.c
Normal file
465
hw/dmx/dmxdbus.c
Normal file
|
|
@ -0,0 +1,465 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Daniel Stone
|
||||
* Copyright © 2008 Novell, Inc.
|
||||
*
|
||||
* 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 furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) 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,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
||||
* David Reveman <davidr@novell.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DMX_CONFIG_H
|
||||
#include <dmx-config.h>
|
||||
#endif
|
||||
|
||||
#include "config-backends.h"
|
||||
#include "dixstruct.h"
|
||||
#include "opaque.h" /* for 'display': there should be a better way. */
|
||||
#include "dmxdbus.h"
|
||||
#include "dmxextension.h"
|
||||
|
||||
#define API_VERSION 1
|
||||
|
||||
#define MATCH_RULE "type='method_call',interface='org.x.config.dmx'"
|
||||
#define MALFORMED_MSG "[dmx/dbus] malformed message, dropping"
|
||||
|
||||
static const unsigned int hexvalues[256] = {
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 9 */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 19 */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 29 */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 39 */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, /* 49 */
|
||||
0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0, 0x0, /* 59 */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xb, 0xb, 0xd, 0xe, /* 69 */
|
||||
0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 79 */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 89 */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xb, 0xc, /* 99 */
|
||||
0xd, 0xe, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
|
||||
};
|
||||
|
||||
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
|
||||
handle_attach_screen (DBusMessage *message,
|
||||
DBusMessage *reply,
|
||||
DBusError *error,
|
||||
int addInput)
|
||||
{
|
||||
DMXScreenAttributesRec attr;
|
||||
DBusMessageIter reply_iter;
|
||||
int screen, ret, size, i;
|
||||
char *display, *auth_type, *auth_data, *name;
|
||||
char *data, *ptr;
|
||||
|
||||
dbus_message_iter_init_append (reply, &reply_iter);
|
||||
|
||||
if (!dbus_message_get_args (message,
|
||||
error,
|
||||
DBUS_TYPE_UINT32,
|
||||
&screen,
|
||||
DBUS_TYPE_STRING,
|
||||
&display,
|
||||
DBUS_TYPE_STRING,
|
||||
&auth_type,
|
||||
DBUS_TYPE_STRING,
|
||||
&auth_data,
|
||||
DBUS_TYPE_STRING,
|
||||
&name,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
DebugF (MALFORMED_MSG ": %s, %s", error->name, error->message);
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
memset (&attr, 0, sizeof (attr));
|
||||
|
||||
attr.displayName = display;
|
||||
|
||||
if (screen >= dmxGetNumScreens ())
|
||||
{
|
||||
DMXScreenAttributesRec attribs;
|
||||
|
||||
for (screen = 0; screen < dmxGetNumScreens (); screen++)
|
||||
{
|
||||
dmxGetScreenAttributes (screen, &attribs);
|
||||
|
||||
if (!attribs.displayName || !*attribs.displayName)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
size = strlen (auth_data) / 2;
|
||||
data = ptr = malloc (size);
|
||||
if (!data)
|
||||
{
|
||||
ErrorF ("[dmx/dbus] couldn't translate auth data\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
*ptr++ = (char) ((hexvalues[(int) auth_data[0]] * 16) +
|
||||
(hexvalues[(int) auth_data[1]]));
|
||||
auth_data += 2;
|
||||
}
|
||||
|
||||
ret = dmxAttachScreen (screen,
|
||||
&attr,
|
||||
auth_type,
|
||||
data,
|
||||
size);
|
||||
|
||||
free (data);
|
||||
|
||||
if (ret != Success)
|
||||
{
|
||||
DebugF ("[dmx/dbus] dmxAttachScreen failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (addInput)
|
||||
{
|
||||
DMXInputAttributesRec attrib;
|
||||
int id;
|
||||
|
||||
memset (&attrib, 0, sizeof (attrib));
|
||||
|
||||
attrib.physicalScreen = screen;
|
||||
attrib.inputType = 2;
|
||||
|
||||
ret = dmxAddInput (&attrib, &id);
|
||||
if (ret != Success)
|
||||
{
|
||||
DebugF ("[dmx/dbus] dmxAddInput failed\n");
|
||||
dmxDetachScreen (screen);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_append_basic (&reply_iter,
|
||||
DBUS_TYPE_INT32,
|
||||
&screen))
|
||||
{
|
||||
ErrorF ("[dmx/dbus] couldn't append to iterator\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
attach_screen (DBusMessage *message,
|
||||
DBusMessage *reply,
|
||||
DBusError *error)
|
||||
{
|
||||
return handle_attach_screen (message, reply, error, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
attach_screen_output (DBusMessage *message,
|
||||
DBusMessage *reply,
|
||||
DBusError *error)
|
||||
{
|
||||
return handle_attach_screen (message, reply, error, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
detach_screen (DBusMessage *message,
|
||||
DBusMessage *reply,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusMessageIter reply_iter;
|
||||
int screen;
|
||||
char *name;
|
||||
|
||||
dbus_message_iter_init_append (reply, &reply_iter);
|
||||
|
||||
if (!dbus_message_get_args (message,
|
||||
error,
|
||||
DBUS_TYPE_STRING,
|
||||
&name,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
DebugF (MALFORMED_MSG ": %s, %s", error->name, error->message);
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
for (screen = 0; screen < dmxGetNumScreens (); screen++)
|
||||
{
|
||||
DMXScreenAttributesRec attribs;
|
||||
|
||||
dmxGetScreenAttributes (screen, &attribs);
|
||||
|
||||
if (!attribs.displayName || !*attribs.displayName)
|
||||
continue;
|
||||
|
||||
if (strcmp (attribs.displayName, name) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (screen == dmxGetNumScreens ())
|
||||
{
|
||||
DebugF ("[dmx/dbus] screen '%s' is not attached\n", name);
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
if (dmxDetachScreen (screen) != 0)
|
||||
{
|
||||
DebugF ("[dmx/dbus] failed to detach screen %d\n", screen);
|
||||
return BadMatch;
|
||||
}
|
||||
|
||||
DebugF ("[dmx/dbus] detaching screen %d\n", screen);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
list_screens (DBusMessage *message,
|
||||
DBusMessage *reply,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusMessageIter iter, subiter;
|
||||
int screen;
|
||||
|
||||
dbus_message_iter_init_append (reply, &iter);
|
||||
|
||||
for (screen = 0; screen < dmxGetNumScreens (); screen++)
|
||||
{
|
||||
DMXScreenAttributesRec attribs;
|
||||
|
||||
dmxGetScreenAttributes (screen, &attribs);
|
||||
|
||||
if (!attribs.displayName || !*attribs.displayName)
|
||||
continue;
|
||||
|
||||
if (!dbus_message_iter_open_container (&iter,
|
||||
DBUS_TYPE_STRUCT,
|
||||
NULL,
|
||||
&subiter))
|
||||
{
|
||||
ErrorF ("[dmx/dbus] couldn't init container\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_append_basic (&subiter,
|
||||
DBUS_TYPE_UINT32,
|
||||
&screen))
|
||||
{
|
||||
ErrorF ("[dmx/dbus] couldn't append to iterator\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_append_basic (&subiter,
|
||||
DBUS_TYPE_STRING,
|
||||
&attribs.displayName))
|
||||
{
|
||||
ErrorF("[dmx/dbus] couldn't append to iterator\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_close_container (&iter, &subiter))
|
||||
{
|
||||
ErrorF ("[dmx/dbus] couldn't close container\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
get_version (DBusMessage *message,
|
||||
DBusMessage *reply,
|
||||
DBusError *error)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
unsigned int version = API_VERSION;
|
||||
|
||||
dbus_message_iter_init_append (reply, &iter);
|
||||
|
||||
if (!dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &version))
|
||||
{
|
||||
ErrorF ("[dmx/dbus] couldn't append version\n");
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
message_handler (DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *data)
|
||||
{
|
||||
struct connection_info *info = data;
|
||||
DBusMessage *reply;
|
||||
DBusError error;
|
||||
|
||||
/* ret is the overall D-Bus handler result, whereas err is the internal
|
||||
* X error from our individual functions. */
|
||||
int err, ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
|
||||
DebugF ("[dmx/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 ("[dmx/dbus] failed to create reply\n");
|
||||
ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
goto err_start;
|
||||
}
|
||||
|
||||
if (strcmp (dbus_message_get_member (message), "attachScreen") == 0)
|
||||
err = attach_screen (message, reply, &error);
|
||||
else if (strcmp (dbus_message_get_member (message),
|
||||
"attachScreenOutput") == 0)
|
||||
err = attach_screen_output (message, reply, &error);
|
||||
else if (strcmp (dbus_message_get_member (message), "detachScreen") == 0)
|
||||
err = detach_screen (message, reply, &error);
|
||||
else if (strcmp (dbus_message_get_member (message), "listScreens") == 0)
|
||||
err = list_screens (message, reply, &error);
|
||||
else if (strcmp (dbus_message_get_member (message), "version") == 0)
|
||||
err = get_version (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;
|
||||
}
|
||||
|
||||
if (err != Success)
|
||||
{
|
||||
dbus_message_unref (reply);
|
||||
|
||||
reply = dbus_message_new_error_printf (message,
|
||||
DBUS_ERROR_FAILED,
|
||||
"XError: %d", ret);
|
||||
if (!reply)
|
||||
{
|
||||
ErrorF ("[dmx/dbus] failed to create reply\n");
|
||||
ret = DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
goto err_start;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 ("[dmx/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)
|
||||
{
|
||||
DBusObjectPathVTable vtable = { .message_function = message_handler };
|
||||
DBusError error;
|
||||
struct connection_info *info = data;
|
||||
|
||||
info->connection = connection;
|
||||
|
||||
dbus_error_init (&error);
|
||||
|
||||
/* blocks until we get a reply. */
|
||||
dbus_bus_add_match (info->connection, MATCH_RULE, &error);
|
||||
if (!dbus_error_is_set (&error))
|
||||
{
|
||||
if (dbus_connection_register_object_path (info->connection,
|
||||
info->busobject,
|
||||
&vtable,
|
||||
info))
|
||||
{
|
||||
DebugF ("[dbus] registered %s, %s\n", info->busname,
|
||||
info->busobject);
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorF ("[dmx/dbus] couldn't register object path\n");
|
||||
dbus_bus_remove_match (info->connection, MATCH_RULE, &error);
|
||||
reset_info (info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorF ("[dmx/dbus] couldn't add match: %s (%s)\n", error.name,
|
||||
error.message);
|
||||
reset_info (info);
|
||||
}
|
||||
|
||||
dbus_error_free (&error);
|
||||
}
|
||||
|
||||
static void
|
||||
disconnect_hook (void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static struct connection_info connection_data;
|
||||
static struct config_dbus_core_hook core_hook = {
|
||||
.connect = connect_hook,
|
||||
.disconnect = disconnect_hook,
|
||||
.data = &connection_data
|
||||
};
|
||||
|
||||
int
|
||||
dmx_dbus_init (void)
|
||||
{
|
||||
snprintf (connection_data.busobject, sizeof (connection_data.busobject),
|
||||
"/org/x/config/dmx/%d", atoi (display));
|
||||
|
||||
return config_dbus_core_add_hook (&core_hook);
|
||||
}
|
||||
|
||||
void
|
||||
dmx_dbus_fini (void)
|
||||
{
|
||||
config_dbus_core_remove_hook (&core_hook);
|
||||
reset_info (&connection_data);
|
||||
}
|
||||
34
hw/dmx/dmxdbus.h
Normal file
34
hw/dmx/dmxdbus.h
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright © 2008 David Reveman
|
||||
*
|
||||
* 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
|
||||
* David Reveman not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior permission.
|
||||
* David Reveman makes no representations about the suitability of this
|
||||
* software for any purpose. It is provided "as is" without express or
|
||||
* implied warranty.
|
||||
*
|
||||
* DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
|
||||
* NO EVENT SHALL DAVID REVEMAN 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.
|
||||
*
|
||||
* Author: David Reveman <davidr@novell.com>
|
||||
*/
|
||||
|
||||
#ifndef DMX_DBUS_H
|
||||
#define DMX_DBUS_H
|
||||
|
||||
#ifdef CONFIG_DBUS_API
|
||||
int dmx_dbus_init (void);
|
||||
void dmx_dbus_fini (void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Reference in a new issue