hal/hald device_info.c,1.32,1.33 hald_dbus.c,1.62,1.63
David Zeuthen
david at kemper.freedesktop.org
Thu Jun 8 19:19:34 PDT 2006
Update of /cvs/hal/hal/hald
In directory kemper:/tmp/cvs-serv22208/hald
Modified Files:
device_info.c hald_dbus.c
Log Message:
2006-06-08 David Zeuthen <davidz at redhat.com>
Adds code so addons can claim interfaces and handle the methods on
them in the addon daemon code. The example here is setting the LCD
backlight on a Macbook Pro. Actual code for setting the backlight
is based on code from Nicolas Boichat found on the mactel-linux
mailing list.
* hald/linux2/addons/addon-macbookpro-backlight.c: New file.
* tools/hal-system-power-set-power-save: Bugfix so the right
backend script is invoked.
* libhal/libhal.h: Add prototype for libhal_device_claim_interface().
* libhal/libhal.c (libhal_device_claim_interface): New function.
* hald/linux2/addons/Makefile.am: Add rules for
hald-addon-macbookpro-backlight.
* hald/hald_dbus.c (device_emit_condition): Only allow helpers,
e.g. only messages from direct connections.
(device_claim_interface): New function to handle the
ClaimInterface() method
(do_introspect): Include introspection XML for ClaimInterface()
and the introspection XML returned by ClaimInterface()
invocations.
(reply_from_fwd_message): New function
(hald_dbus_filter_handle_methods): Handle ClaimInterface() and
forward messages to the claimed interfaces on the appropriate
objects.
(local_server_message_handler): Forward signals from helpers onto
the system message bus and DTRT when a helper disconnects.
* hald/device_info.c (handle_spawn): New function. One can now do
a <spawn udi="foo"> to spawn a child device. See the fdi file below
for usage.
(start, spawned_device_callouts_add_done, end): Handle spawning
device objects in response to <spawn>.
* fdi/policy/10osvendor/10-laptop-panel-mgmt-policy.fdi: Add rules
for matching the Macbook Pro in order to spawn a new device object
with an addon for handing methods on the org.fd.H.D.LaptopPanel
interface.
* hal.conf.in: Allow some interfaces to also emit signals.
* configure.in: Check for libpci so we can use it as an optional
dependency.
Index: device_info.c
===================================================================
RCS file: /cvs/hal/hal/hald/device_info.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- device_info.c 21 Jan 2006 06:36:51 -0000 1.32
+++ device_info.c 9 Jun 2006 02:19:32 -0000 1.33
@@ -41,6 +41,7 @@
#include "logger.h"
#include "device_info.h"
#include "device_store.h"
+#include "util.h"
/**
* @defgroup DeviceInfo Device Info File Parsing
@@ -86,7 +87,10 @@
CURELEM_REMOVE = 6,
/** Processing a clear element */
- CURELEM_CLEAR = 7
+ CURELEM_CLEAR = 7,
+
+ /** Processing a spawn element */
+ CURELEM_SPAWN = 8
};
/** What and how to merge */
@@ -100,7 +104,8 @@
MERGE_TYPE_COPY_PROPERTY = 6,
MERGE_TYPE_STRLIST = 7,
MERGE_TYPE_REMOVE = 8,
- MERGE_TYPE_CLEAR = 9
+ MERGE_TYPE_CLEAR = 9,
+ MERGE_TYPE_SPAWN = 10
};
/** Parsing Context
@@ -748,6 +753,36 @@
return;
}
+
+/** Called when the spawn element begins.
+ *
+ * @param pc Parsing context
+ * @param attr Attribute key/value pairs
+ */
+static void
+handle_spawn (ParsingContext * pc, const char **attr)
+{
+ int num_attrib;
+
+ pc->merge_type = MERGE_TYPE_UNKNOWN;
+
+ for (num_attrib = 0; attr[num_attrib] != NULL; num_attrib++) {
+ ;
+ }
+
+ if (num_attrib != 2)
+ return;
+
+ if (strcmp (attr[0], "udi") != 0)
+ return;
+
+ strncpy (pc->merge_key, attr[1], MAX_KEY_SIZE);
+
+ pc->merge_type = MERGE_TYPE_SPAWN;
+
+ return;
+}
+
/** Called when the remove element begins.
*
* @param pc Parsing context
@@ -988,6 +1023,21 @@
parsing_abort (pc);
}
pc->curelem = CURELEM_DEVICE_INFO;
+ } else if (strcmp (el, "spawn") == 0) {
+ if (pc->curelem != CURELEM_MATCH) {
+ HAL_ERROR (("%s:%d:%d: Element <spawn> can only be "
+ "inside <match>",
+ pc->file,
+ XML_GetCurrentLineNumber (pc->parser),
+ XML_GetCurrentColumnNumber (pc->parser)));
+ parsing_abort (pc);
+ }
+
+ pc->curelem = CURELEM_SPAWN;
+ if (pc->match_ok) {
+ handle_spawn (pc, attr);
+ }
+
} else {
HAL_ERROR (("%s:%d:%d: Unknown element <%s>",
pc->file,
@@ -1006,6 +1056,17 @@
}
+static void
+spawned_device_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+ HAL_INFO (("Add callouts completed udi=%s", d->udi));
+
+ /* Move from temporary to global device store */
+ hal_device_store_remove (hald_get_tdl (), d);
+ hal_device_store_add (hald_get_gdl (), d);
+
+}
+
/** Called by expat when an element ends.
*
* @param pc Parsing context
@@ -1201,6 +1262,31 @@
hal_device_property_remove (pc->device, pc->merge_key);
}
}
+ } else if (pc->merge_type == MERGE_TYPE_SPAWN) {
+ HalDevice *spawned;
+
+ spawned = hal_device_store_find (hald_get_gdl (), pc->merge_key);
+ if (spawned == NULL)
+ spawned = hal_device_store_find (hald_get_tdl (), pc->merge_key);
+
+ if (spawned == NULL) {
+ HAL_INFO (("Spawning new device object '%s' caused by <spawn> on udi '%s'",
+ pc->merge_key, pc->device->udi));
+
+ spawned = hal_device_new ();
+ hal_device_property_set_string (spawned, "info.bus", "unknown");
+ hal_device_property_set_string (spawned, "info.udi", pc->merge_key);
+ hal_device_property_set_string (spawned, "info.parent", pc->device->udi);
+ hal_device_set_udi (spawned, pc->merge_key);
+
+ hal_device_store_add (hald_get_tdl (), spawned);
+
+ di_search_and_merge (spawned, DEVICE_INFO_TYPE_INFORMATION);
+ di_search_and_merge (spawned, DEVICE_INFO_TYPE_POLICY);
+
+ hal_util_callout_device_add (spawned, spawned_device_callouts_add_done, NULL, NULL);
+ }
+
} else if (pc->curelem == CURELEM_CLEAR && pc->match_ok) {
if (pc->merge_type == MERGE_TYPE_CLEAR) {
hal_device_property_strlist_clear (pc->device, pc->merge_key);
@@ -1208,7 +1294,6 @@
}
-
pc->cdata_buf_len = 0;
pc->depth--;
Index: hald_dbus.c
===================================================================
RCS file: /cvs/hal/hal/hald/hald_dbus.c,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -d -r1.62 -r1.63
--- hald_dbus.c 6 Jun 2006 23:56:09 -0000 1.62
+++ hald_dbus.c 9 Jun 2006 02:19:32 -0000 1.63
@@ -2229,8 +2229,8 @@
udi = dbus_message_get_path (message);
- if (!local_interface && !sender_has_privileges (connection, message)) {
- raise_permission_denied (connection, message, "EmitCondition: not privileged");
+ if (!local_interface) {
+ raise_permission_denied (connection, message, "EmitCondition: only allowed for helpers");
return DBUS_HANDLER_RESULT_HANDLED;
}
@@ -2272,6 +2272,87 @@
return DBUS_HANDLER_RESULT_HANDLED;
}
+typedef struct
+{
+ DBusConnection *connection;
+ char *interface_name;
+ char *introspection_xml;
+ char *udi;
+} HelperInterfaceHandler;
+
+static GSList *helper_interface_handlers = NULL;
+
+static DBusHandlerResult
+device_claim_interface (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
+{
+ const char *udi;
+ HalDevice *device;
+ DBusMessageIter iter;
+ DBusMessage *reply;
+ DBusError error;
+ const char *interface_name;
+ const char *introspection_xml;
+ dbus_bool_t res;
+
+ HAL_TRACE (("entering"));
+
+ udi = dbus_message_get_path (message);
+
+ if (!local_interface) {
+ raise_permission_denied (connection, message, "ClaimInterface: only allowed for helpers");
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ HAL_DEBUG (("udi=%s", udi));
+
+ dbus_error_init (&error);
+ if (!dbus_message_get_args (message, &error,
+ DBUS_TYPE_STRING, &interface_name,
+ DBUS_TYPE_STRING, &introspection_xml,
+ DBUS_TYPE_INVALID)) {
+ raise_syntax (connection, message, "ClaimInterface");
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ device = hal_device_store_find (hald_get_gdl (), udi);
+ if (device == NULL)
+ device = hal_device_store_find (hald_get_tdl (), udi);
+
+ if (device == NULL) {
+ raise_no_such_device (connection, message, udi);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ res = TRUE;
+
+ HAL_INFO (("Local connection 0x%x to handle interface '%s' on udi '%s'",
+ connection,
+ interface_name,
+ udi));
+
+ hal_device_property_strlist_add (device, "info.interfaces", interface_name);
+
+ HelperInterfaceHandler *hih = g_new0 (HelperInterfaceHandler, 1);
+ hih->connection = connection;
+ hih->interface_name = g_strdup (interface_name);
+ hih->introspection_xml = g_strdup (introspection_xml);
+ hih->udi = g_strdup (udi);
+ helper_interface_handlers = g_slist_append (helper_interface_handlers, hih);
+
+
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ DIE (("No memory"));
+ dbus_message_iter_init_append (reply, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
+
+ if (!dbus_connection_send (connection, reply, NULL))
+ DIE (("No memory"));
+
+ dbus_message_unref (reply);
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
/*
* Create new device in tdl. Return temporary udi.
@@ -3054,6 +3135,12 @@
" <arg name=\"condition_name\" direction=\"in\" type=\"s\"/>\n"
" <arg name=\"condition_details\" direction=\"in\" type=\"s\"/>\n"
" </method>\n"
+
+ " <method name=\"ClaimInterface\">\n"
+ " <arg name=\"interface_name\" direction=\"in\" type=\"s\"/>\n"
+ " <arg name=\"introspection_xml\" direction=\"in\" type=\"s\"/>\n"
+ " </method>\n"
+
" </interface>\n");
GSList *interfaces;
@@ -3081,6 +3168,20 @@
method_names = hal_device_property_get_strlist (d, method_names_prop);
method_signatures = hal_device_property_get_strlist (d, method_signatures_prop);
method_argnames = hal_device_property_get_strlist (d, method_argnames_prop);
+
+ /* consult local list */
+ if (method_names == NULL) {
+ GSList *i;
+
+ for (i = helper_interface_handlers; i != NULL; i = g_slist_next (i)) {
+ HelperInterfaceHandler *hih = i->data;
+ if (strcmp (hih->udi, path) == 0) {
+ xml = g_string_append (xml, hih->introspection_xml);
+ }
+ }
+
+ }
+
for (j = method_names, k = method_signatures, l = method_argnames;
j != NULL && k != NULL && l != NULL;
j = g_slist_next (j), k = g_slist_next (k), l = g_slist_next (l)) {
@@ -3103,25 +3204,32 @@
switch (sig[n]) {
case 'a':
if (n == strlen (sig) - 1) {
- HAL_WARNING (("Broken signature for method %s on interface %s for object %s", name, ifname, path));
+ HAL_WARNING (("Broken signature for method %s "
+ "on interface %s for object %s",
+ name, ifname, path));
continue;
}
g_string_append_printf (
- xml,
- " <arg name=\"%s\" direction=\"in\" type=\"a%c\"/>\n", args[m], sig[n + 1]);
+ xml,
+ " <arg name=\"%s\" direction=\"in\" type=\"a%c\"/>\n",
+ args[m], sig[n + 1]);
n++;
break;
default:
g_string_append_printf (
- xml,
- " <arg name=\"%s\" direction=\"in\" type=\"%c\"/>\n", args[m], sig[n]);
+ xml,
+ " <arg name=\"%s\" direction=\"in\" type=\"%c\"/>\n",
+ args[m], sig[n]);
break;
}
}
- xml = g_string_append (xml,
- " <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n");
- xml = g_string_append (xml, " </method>\n");
+ xml = g_string_append (
+ xml,
+ " <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n");
+ xml = g_string_append (
+ xml,
+ " </method>\n");
}
@@ -3156,11 +3264,43 @@
return DBUS_HANDLER_RESULT_HANDLED;
}
+static void
+reply_from_fwd_message (DBusPendingCall *pending_call,
+ void *user_data)
+{
+ DBusMessage *reply_from_addon;
+ DBusMessage *method_from_caller;
+ DBusMessage *reply;
+
+ /*HAL_INFO (("in reply_from_fwd_message : user_data = 0x%x", user_data));*/
+
+ method_from_caller = (DBusMessage *) user_data;
+ reply_from_addon = dbus_pending_call_steal_reply (pending_call);
+
+ reply = dbus_message_copy (reply_from_addon);
+ dbus_message_set_destination (reply, dbus_message_get_sender (method_from_caller));
+ dbus_message_set_reply_serial (reply, dbus_message_get_serial (method_from_caller));
+
+ if (dbus_connection != NULL)
+ dbus_connection_send (dbus_connection, reply, NULL);
+
+ dbus_message_unref (reply_from_addon);
+ dbus_message_unref (reply);
+}
static DBusHandlerResult
hald_dbus_filter_handle_methods (DBusConnection *connection, DBusMessage *message,
void *user_data, dbus_bool_t local_interface)
{
+ /*
+ HAL_INFO (("connection=0x%x obj_path=%s interface=%s method=%s local_interface=%d",
+ connection,
+ dbus_message_get_path (message),
+ dbus_message_get_interface (message),
+ dbus_message_get_member (message),
+ local_interface));
+ */
+
if (dbus_message_is_method_call (message,
"org.freedesktop.Hal.Manager",
"GetAllDevices") &&
@@ -3310,6 +3450,16 @@
"EmitCondition")) {
return device_emit_condition (connection, message, local_interface);
} else if (dbus_message_is_method_call (message,
+ "org.freedesktop.Hal.Device",
+ "ClaimInterface")) {
+ return device_claim_interface (connection, message, local_interface);
+#if 0
+ } else if (dbus_message_is_method_call (message,
+ "org.freedesktop.Hal.Device",
+ "ReleaseInterface")) {
+ return device_release_interface (connection, message, local_interface);
+#endif
+ } else if (dbus_message_is_method_call (message,
"org.freedesktop.DBus.Introspectable",
"Introspect")) {
return do_introspect (connection, message, local_interface);
@@ -3329,12 +3479,48 @@
d = NULL;
- if (method != NULL) {
+ if (udi != NULL) {
d = hal_device_store_find (hald_get_gdl (), udi);
if (d == NULL)
d = hal_device_store_find (hald_get_tdl (), udi);
}
+ if (d != NULL && interface != NULL) {
+ GSList *i;
+
+ for (i = helper_interface_handlers; i != NULL; i = g_slist_next (i)) {
+ HelperInterfaceHandler *hih = i->data;
+ if (strcmp (hih->udi, udi) == 0 &&
+ strcmp (hih->interface_name, interface) == 0) {
+ DBusPendingCall *pending_call;
+ DBusMessage *copy;
+
+ /*HAL_INFO (("forwarding method to connection 0x%x", hih->connection));*/
+
+ dbus_message_ref (message);
+
+ /* send a copy of the message */
+ copy = dbus_message_copy (message);
+ if (!dbus_connection_send_with_reply (hih->connection,
+ copy,
+ &pending_call,
+ /*-1*/ 8000)) {
+ /* TODO: handle error */
+ } else {
+ /*HAL_INFO (("connection=%x message=%x", connection, message));*/
+ dbus_pending_call_set_notify (pending_call,
+ reply_from_fwd_message,
+ (void *) message,
+ NULL);
+ }
+
+ dbus_message_unref (copy);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+ }
+ }
+
if (d != NULL && interface != NULL && method != NULL && signature != NULL) {
GSList *interfaces;
GSList *i;
@@ -3397,11 +3583,6 @@
hald_dbus_filter_function (DBusConnection * connection,
DBusMessage * message, void *user_data)
{
- /*HAL_INFO (("obj_path=%s interface=%s method=%s",
- dbus_message_get_path(message),
- dbus_message_get_interface(message),
- dbus_message_get_member(message)));*/
-
if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
@@ -3433,13 +3614,11 @@
DBusMessage *message,
void *user_data)
{
-/*
- HAL_INFO (("local_server_message_handler: destination=%s obj_path=%s interface=%s method=%s",
+ /*HAL_INFO (("local_server_message_handler: destination=%s obj_path=%s interface=%s method=%s",
dbus_message_get_destination (message),
dbus_message_get_path (message),
dbus_message_get_interface (message),
- dbus_message_get_member (message)));
-*/
+ dbus_message_get_member (message)));*/
if (dbus_message_is_method_call (message, "org.freedesktop.DBus", "AddMatch")) {
DBusMessage *reply;
@@ -3454,12 +3633,41 @@
return DBUS_HANDLER_RESULT_HANDLED;
} else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
+ GSList *i;
+ GSList *j;
HAL_INFO (("Client to local_server was disconnected"));
+
+ for (i = helper_interface_handlers; i != NULL; i = j) {
+ HelperInterfaceHandler *hih = i->data;
+
+ j = g_slist_next (i);
+
+ if (hih->connection == connection) {
+ g_free (hih->interface_name);
+ g_free (hih->introspection_xml);
+ g_free (hih->udi);
+ g_free (hih);
+ helper_interface_handlers = g_slist_remove (helper_interface_handlers, i);
+ }
+ }
+
dbus_connection_unref (connection);
return DBUS_HANDLER_RESULT_HANDLED;
- }
- else return hald_dbus_filter_handle_methods (connection, message, user_data, TRUE);
+ } else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL) {
+ DBusMessage *copy;
+
+ /* it's a signal, just forward it onto the system message bus */
+ copy = dbus_message_copy (message);
+ if (dbus_connection != NULL) {
+ dbus_connection_send (dbus_connection, copy, NULL);
+ }
+ dbus_message_unref (copy);
+ } else {
+ return hald_dbus_filter_handle_methods (connection, message, user_data, TRUE);
+ }
+
+ return DBUS_HANDLER_RESULT_HANDLED;
}
static void
More information about the hal-commit
mailing list