12912Sartem /***************************************************************************
22912Sartem * CVSID: $Id$
32912Sartem *
42912Sartem * dbus.c : D-BUS interface of HAL daemon
52912Sartem *
62912Sartem * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
72912Sartem *
82912Sartem * Licensed under the Academic Free License version 2.1
92912Sartem *
102912Sartem * This program is free software; you can redistribute it and/or modify
112912Sartem * it under the terms of the GNU General Public License as published by
122912Sartem * the Free Software Foundation; either version 2 of the License, or
132912Sartem * (at your option) any later version.
142912Sartem *
152912Sartem * This program is distributed in the hope that it will be useful,
162912Sartem * but WITHOUT ANY WARRANTY; without even the implied warranty of
172912Sartem * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
182912Sartem * GNU General Public License for more details.
192912Sartem *
202912Sartem * You should have received a copy of the GNU General Public License
212912Sartem * along with this program; if not, write to the Free Software
222912Sartem * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
232912Sartem *
242912Sartem **************************************************************************/
252912Sartem
262912Sartem #ifdef HAVE_CONFIG_H
272912Sartem # include <config.h>
282912Sartem #endif
292912Sartem
302912Sartem #include <stdlib.h>
312912Sartem #include <stdio.h>
322912Sartem #include <string.h>
332912Sartem #include <unistd.h>
342912Sartem #include <stdarg.h>
352912Sartem #include <stdint.h>
362912Sartem #include <sys/time.h>
372912Sartem
382912Sartem #include <dbus/dbus.h>
392912Sartem #include <dbus/dbus-glib-lowlevel.h>
402912Sartem
412912Sartem #include "hald.h"
422912Sartem #include "hald_dbus.h"
432912Sartem #include "device.h"
442912Sartem #include "device_store.h"
452912Sartem #include "device_info.h"
462912Sartem #include "logger.h"
472912Sartem #include "osspec.h"
482912Sartem #include "util.h"
492912Sartem #include "hald_runner.h"
502912Sartem
512912Sartem #define HALD_DBUS_ADDRESS "unix:tmpdir=" HALD_SOCKET_DIR
522912Sartem
532912Sartem static DBusConnection *dbus_connection = NULL;
542912Sartem
552912Sartem static void
562912Sartem raise_error (DBusConnection *connection,
572912Sartem DBusMessage *in_reply_to,
582912Sartem const char *error_name,
592912Sartem char *format, ...) __attribute__((format (printf, 4, 5)));
602912Sartem
612912Sartem /**
622912Sartem * @defgroup DaemonErrors Error conditions
632912Sartem * @ingroup HalDaemon
642912Sartem * @brief Various error messages the HAL daemon can raise
652912Sartem * @{
662912Sartem */
672912Sartem
682912Sartem /** Raise HAL error
692912Sartem *
702912Sartem * @param connection D-Bus connection
712912Sartem * @param in_reply_to message to report error on
722912Sartem * @param error_name D-Bus error name
732912Sartem * @param format printf-style format for error message
742912Sartem */
752912Sartem static void
raise_error(DBusConnection * connection,DBusMessage * in_reply_to,const char * error_name,char * format,...)762912Sartem raise_error (DBusConnection *connection,
772912Sartem DBusMessage *in_reply_to,
782912Sartem const char *error_name,
792912Sartem char *format, ...)
802912Sartem {
812912Sartem char buf[512];
822912Sartem DBusMessage *reply;
832912Sartem
842912Sartem va_list args;
852912Sartem va_start(args, format);
862912Sartem vsnprintf(buf, sizeof buf, format, args);
872912Sartem va_end(args);
882912Sartem
892912Sartem HAL_WARNING ((buf));
902912Sartem reply = dbus_message_new_error (in_reply_to, error_name, buf);
912912Sartem if (reply == NULL)
922912Sartem DIE (("No memory"));
932912Sartem if (!dbus_connection_send (connection, reply, NULL))
942912Sartem DIE (("No memory"));
952912Sartem dbus_message_unref (reply);
962912Sartem }
972912Sartem
982912Sartem /** Raise the org.freedesktop.Hal.NoSuchDevice error
992912Sartem *
1002912Sartem * @param connection D-Bus connection
1012912Sartem * @param in_reply_to message to report error on
1022912Sartem * @param udi Unique device id given
1032912Sartem */
1042912Sartem static void
raise_no_such_device(DBusConnection * connection,DBusMessage * in_reply_to,const char * udi)1052912Sartem raise_no_such_device (DBusConnection *connection,
1062912Sartem DBusMessage *in_reply_to, const char *udi)
1072912Sartem {
1082912Sartem raise_error (
1092912Sartem connection, in_reply_to,
1102912Sartem "org.freedesktop.Hal.NoSuchDevice",
1112912Sartem "No device with id %s",
1122912Sartem udi
1132912Sartem );
1142912Sartem }
1152912Sartem
1162912Sartem /** Raise the org.freedesktop.Hal.NoSuchProperty error
1172912Sartem *
1182912Sartem * @param connection D-Bus connection
1192912Sartem * @param in_reply_to message to report error on
1202912Sartem * @param device_id Id of the device
1212912Sartem * @param key Key of the property that didn't exist
1222912Sartem */
1232912Sartem static void
raise_no_such_property(DBusConnection * connection,DBusMessage * in_reply_to,const char * device_id,const char * key)1242912Sartem raise_no_such_property (DBusConnection *connection,
1252912Sartem DBusMessage *in_reply_to,
1262912Sartem const char *device_id, const char *key)
1272912Sartem {
1282912Sartem raise_error (
1292912Sartem connection, in_reply_to,
1302912Sartem "org.freedesktop.Hal.NoSuchProperty",
1312912Sartem "No property %s on device with id %s",
1322912Sartem key, device_id
1332912Sartem );
1342912Sartem }
1352912Sartem
1362912Sartem /** Raise the org.freedesktop.Hal.TypeMismatch error
1372912Sartem *
1382912Sartem * @param connection D-Bus connection
1392912Sartem * @param in_reply_to message to report error on
1402912Sartem * @param device_id Id of the device
1412912Sartem * @param key Key of the property
1422912Sartem */
1432912Sartem static void
raise_property_type_error(DBusConnection * connection,DBusMessage * in_reply_to,const char * device_id,const char * key)1442912Sartem raise_property_type_error (DBusConnection *connection,
1452912Sartem DBusMessage *in_reply_to,
1462912Sartem const char *device_id, const char *key)
1472912Sartem {
1482912Sartem raise_error (
1492912Sartem connection, in_reply_to,
1502912Sartem "org.freedesktop.Hal.TypeMismatch",
1512912Sartem "Type mismatch setting property %s on device with id %s",
1522912Sartem key, device_id
1532912Sartem );
1542912Sartem }
1552912Sartem
1562912Sartem /** Raise the org.freedesktop.Hal.SyntaxError error
1572912Sartem *
1582912Sartem * @param connection D-Bus connection
1592912Sartem * @param in_reply_to message to report error on
1602912Sartem * @param method_name Name of the method that was invoked with
1612912Sartem * the wrong signature
1622912Sartem */
1632912Sartem static void
raise_syntax(DBusConnection * connection,DBusMessage * in_reply_to,const char * method_name)1642912Sartem raise_syntax (DBusConnection *connection,
1652912Sartem DBusMessage *in_reply_to, const char *method_name)
1662912Sartem {
1672912Sartem raise_error (
1682912Sartem connection, in_reply_to,
1692912Sartem "org.freedesktop.Hal.SyntaxError",
1702912Sartem "There is a syntax error in the invocation of the method %s",
1712912Sartem method_name
1722912Sartem );
1732912Sartem }
1742912Sartem
1752912Sartem /** Raise the org.freedesktop.Hal.DeviceNotLocked error
1762912Sartem *
1772912Sartem * @param connection D-Bus connection
1782912Sartem * @param in_reply_to message to report error on
1792912Sartem * @param device device which isn't locked
1802912Sartem */
1812912Sartem static void
raise_device_not_locked(DBusConnection * connection,DBusMessage * in_reply_to,HalDevice * device)1822912Sartem raise_device_not_locked (DBusConnection *connection,
1832912Sartem DBusMessage *in_reply_to,
1842912Sartem HalDevice *device)
1852912Sartem {
1862912Sartem raise_error (
1872912Sartem connection, in_reply_to,
1882912Sartem "org.freedesktop.Hal.DeviceNotLocked",
1892912Sartem "The device %s is not locked",
1902912Sartem hal_device_get_udi (device)
1912912Sartem );
1922912Sartem }
1932912Sartem
1942912Sartem /** Raise the org.freedesktop.Hal.DeviceAlreadyLocked error
1952912Sartem *
1962912Sartem * @param connection D-Bus connection
1972912Sartem * @param in_reply_to message to report error on
1982912Sartem * @param device device which isn't locked
1992912Sartem */
2002912Sartem static void
raise_device_already_locked(DBusConnection * connection,DBusMessage * in_reply_to,HalDevice * device)2012912Sartem raise_device_already_locked (DBusConnection *connection,
2022912Sartem DBusMessage *in_reply_to,
2032912Sartem HalDevice *device)
2042912Sartem {
2052912Sartem DBusMessage *reply;
2062912Sartem const char *reason;
2072912Sartem
2082912Sartem reason = hal_device_property_get_string (device, "info.locked.reason");
2092912Sartem HAL_WARNING (("Device %s is already locked: %s",
2102912Sartem hal_device_get_udi (device), reason));
2112912Sartem
2122912Sartem
2132912Sartem reply = dbus_message_new_error (in_reply_to,
2142912Sartem "org.freedesktop.Hal.DeviceAlreadyLocked",
2152912Sartem reason);
2162912Sartem
2172912Sartem if (reply == NULL || !dbus_connection_send (connection, reply, NULL))
2182912Sartem DIE (("No memory"));
2192912Sartem
2202912Sartem dbus_message_unref (reply);
2212912Sartem }
2222912Sartem
2232912Sartem /** Raise the org.freedesktop.Hal.BranchAlreadyClaimed error
2242912Sartem *
2252912Sartem * @param connection D-Bus connection
2262912Sartem * @param in_reply_to message to report error on
2272912Sartem * @param udi branch which isn't claimed
2282912Sartem */
2292912Sartem static void
raise_branch_already_claimed(DBusConnection * connection,DBusMessage * in_reply_to,HalDevice * device)2302912Sartem raise_branch_already_claimed (DBusConnection *connection,
2312912Sartem DBusMessage *in_reply_to,
2322912Sartem HalDevice *device)
2332912Sartem {
2342912Sartem DBusMessage *reply;
2352912Sartem const char *claim_service;
2362912Sartem
2372912Sartem claim_service = hal_device_property_get_string (device, "info.claimed.service");
2382912Sartem HAL_WARNING (("Branch %s is already claimed by: %s",
2392912Sartem hal_device_get_udi (device), claim_service));
2402912Sartem
2412912Sartem
2422912Sartem reply = dbus_message_new_error (in_reply_to,
2432912Sartem "org.freedesktop.Hal.BranchAlreadyClaimed",
2442912Sartem claim_service);
2452912Sartem
2462912Sartem if (reply == NULL || !dbus_connection_send (connection, reply, NULL))
2472912Sartem DIE (("No memory"));
2482912Sartem
2492912Sartem dbus_message_unref (reply);
2502912Sartem }
2512912Sartem
2522912Sartem /** Raise the org.freedesktop.Hal.BranchNotClaimed error
2532912Sartem *
2542912Sartem * @param connection D-Bus connection
2552912Sartem * @param in_reply_to message to report error on
2562912Sartem * @param udi branch which isn't claimed
2572912Sartem */
2582912Sartem static void
raise_branch_not_claimed(DBusConnection * connection,DBusMessage * in_reply_to,HalDevice * device)2592912Sartem raise_branch_not_claimed (DBusConnection *connection,
2602912Sartem DBusMessage *in_reply_to,
2612912Sartem HalDevice *device)
2622912Sartem {
2632912Sartem raise_error (
2642912Sartem connection, in_reply_to,
2652912Sartem "org.freedesktop.Hal.BranchNotClaimed",
2662912Sartem "The branch %s is not claimed",
2672912Sartem hal_device_get_udi (device)
2682912Sartem );
2692912Sartem }
2702912Sartem
2712912Sartem /** Raise the org.freedesktop.Hal.PermissionDenied error
2722912Sartem *
2732912Sartem * @param connection D-Bus connection
2742912Sartem * @param in_reply_to message to report error on
2752912Sartem * @param message what you're not allowed to do
2762912Sartem */
2772912Sartem static void
raise_permission_denied(DBusConnection * connection,DBusMessage * in_reply_to,const char * reason)2782912Sartem raise_permission_denied (DBusConnection *connection,
2792912Sartem DBusMessage *in_reply_to,
2802912Sartem const char *reason)
2812912Sartem {
2822912Sartem raise_error (
2832912Sartem connection, in_reply_to,
2842912Sartem "org.freedesktop.Hal.PermissionDenied",
2852912Sartem "Permission denied: %s",
2862912Sartem reason
2872912Sartem );
2882912Sartem }
2892912Sartem
2902912Sartem /** @} */
2912912Sartem
2922912Sartem /**
2932912Sartem * @defgroup ManagerInterface D-BUS interface org.freedesktop.Hal.Manager
2942912Sartem * @ingroup HalDaemon
2952912Sartem * @brief D-BUS interface for querying device objects
2962912Sartem *
2972912Sartem * @{
2982912Sartem */
2992912Sartem
3002912Sartem static gboolean
foreach_device_get_udi(HalDeviceStore * store,HalDevice * device,gpointer user_data)3012912Sartem foreach_device_get_udi (HalDeviceStore *store, HalDevice *device,
3022912Sartem gpointer user_data)
3032912Sartem {
3042912Sartem DBusMessageIter *iter = user_data;
3052912Sartem const char *udi;
3062912Sartem
3072912Sartem udi = hal_device_get_udi (device);
3082912Sartem dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &udi);
3092912Sartem
3102912Sartem return TRUE;
3112912Sartem }
3122912Sartem
3132912Sartem /** Get all devices.
3142912Sartem *
3152912Sartem * <pre>
3162912Sartem * array{object_reference} Manager.GetAllDevices()
3172912Sartem * </pre>
3182912Sartem *
3192912Sartem * @param connection D-BUS connection
3202912Sartem * @param message Message
3212912Sartem * @return What to do with the message
3222912Sartem */
3232912Sartem DBusHandlerResult
manager_get_all_devices(DBusConnection * connection,DBusMessage * message)3242912Sartem manager_get_all_devices (DBusConnection * connection,
3252912Sartem DBusMessage * message)
3262912Sartem {
3272912Sartem DBusMessage *reply;
3282912Sartem DBusMessageIter iter;
3292912Sartem DBusMessageIter iter_array;
3302912Sartem
3312912Sartem reply = dbus_message_new_method_return (message);
3322912Sartem if (reply == NULL)
3332912Sartem DIE (("No memory"));
3342912Sartem
3352912Sartem dbus_message_iter_init_append (reply, &iter);
3362912Sartem dbus_message_iter_open_container (&iter,
3372912Sartem DBUS_TYPE_ARRAY,
3382912Sartem DBUS_TYPE_STRING_AS_STRING,
3392912Sartem &iter_array);
3402912Sartem
3412912Sartem hal_device_store_foreach (hald_get_gdl (),
3422912Sartem foreach_device_get_udi,
3432912Sartem &iter_array);
3442912Sartem
3452912Sartem dbus_message_iter_close_container (&iter, &iter_array);
3462912Sartem
3472912Sartem if (!dbus_connection_send (connection, reply, NULL))
3482912Sartem DIE (("No memory"));
3492912Sartem
3502912Sartem dbus_message_unref (reply);
3512912Sartem
3522912Sartem return DBUS_HANDLER_RESULT_HANDLED;
3532912Sartem }
3542912Sartem
3552912Sartem typedef struct {
3562912Sartem const char *key;
3572912Sartem const char *value;
3582912Sartem DBusMessageIter *iter;
3592912Sartem } DeviceMatchInfo;
3602912Sartem
3612912Sartem static gboolean
foreach_device_match_get_udi(HalDeviceStore * store,HalDevice * device,gpointer user_data)3622912Sartem foreach_device_match_get_udi (HalDeviceStore *store, HalDevice *device,
3632912Sartem gpointer user_data)
3642912Sartem {
3652912Sartem DeviceMatchInfo *info = user_data;
3662912Sartem const char *dev_value;
3672912Sartem
3682912Sartem if (hal_device_property_get_type (device,
3692912Sartem info->key) != DBUS_TYPE_STRING)
3702912Sartem return TRUE;
3712912Sartem
3722912Sartem dev_value = hal_device_property_get_string (device, info->key);
3732912Sartem
3742912Sartem if (dev_value != NULL && strcmp (dev_value, info->value) == 0) {
3752912Sartem const char *udi;
3762912Sartem udi = hal_device_get_udi (device);
3772912Sartem dbus_message_iter_append_basic (info->iter,
3782912Sartem DBUS_TYPE_STRING,
3792912Sartem &udi);
3802912Sartem }
3812912Sartem
3822912Sartem return TRUE;
3832912Sartem }
3842912Sartem
3852912Sartem static gboolean
foreach_device_match_get_udi_tdl(HalDeviceStore * store,HalDevice * device,gpointer user_data)3862912Sartem foreach_device_match_get_udi_tdl (HalDeviceStore *store, HalDevice *device,
3872912Sartem gpointer user_data)
3882912Sartem {
3892912Sartem DeviceMatchInfo *info = user_data;
3902912Sartem const char *dev_value;
3912912Sartem
3922912Sartem /* skip devices in the TDL that hasn't got a real UDI yet */
3932912Sartem if (strncmp (device->udi, "/org/freedesktop/Hal/devices/temp",
3942912Sartem sizeof ("/org/freedesktop/Hal/devices/temp")) == 0)
3952912Sartem return TRUE;
3962912Sartem
3972912Sartem if (hal_device_property_get_type (device,
3982912Sartem info->key) != DBUS_TYPE_STRING)
3992912Sartem return TRUE;
4002912Sartem
4012912Sartem dev_value = hal_device_property_get_string (device, info->key);
4022912Sartem
4032912Sartem if (dev_value != NULL && strcmp (dev_value, info->value) == 0) {
4042912Sartem const char *udi;
4052912Sartem udi = hal_device_get_udi (device);
4062912Sartem
4072912Sartem dbus_message_iter_append_basic (info->iter,
4082912Sartem DBUS_TYPE_STRING,
4092912Sartem &udi);
4102912Sartem }
4112912Sartem
4122912Sartem return TRUE;
4132912Sartem }
4142912Sartem
4152912Sartem /** Find devices in the GDL where a single string property matches a given
4162912Sartem * value. Also returns devices in the TDL that has a non-tmp UDI.
4172912Sartem *
4182912Sartem * <pre>
4192912Sartem * array{object_reference} Manager.FindDeviceStringMatch(string key,
4202912Sartem * string value)
4212912Sartem * </pre>
4222912Sartem *
4232912Sartem * @param connection D-BUS connection
4242912Sartem * @param message Message
4252912Sartem * @return What to do with the message
4262912Sartem */
4272912Sartem DBusHandlerResult
manager_find_device_string_match(DBusConnection * connection,DBusMessage * message)4282912Sartem manager_find_device_string_match (DBusConnection * connection,
4292912Sartem DBusMessage * message)
4302912Sartem {
4312912Sartem DBusMessage *reply;
4322912Sartem DBusMessageIter iter;
4332912Sartem DBusMessageIter iter_array;
4342912Sartem DBusError error;
4352912Sartem const char *key;
4362912Sartem const char *value;
4372912Sartem DeviceMatchInfo info;
4382912Sartem
4392912Sartem HAL_TRACE (("entering"));
4402912Sartem
4412912Sartem dbus_error_init (&error);
4422912Sartem if (!dbus_message_get_args (message, &error,
4432912Sartem DBUS_TYPE_STRING, &key,
4442912Sartem DBUS_TYPE_STRING, &value,
4452912Sartem DBUS_TYPE_INVALID)) {
4462912Sartem raise_syntax (connection, message,
4472912Sartem "Manager.FindDeviceStringMatch");
4482912Sartem return DBUS_HANDLER_RESULT_HANDLED;
4492912Sartem }
4502912Sartem
4512912Sartem reply = dbus_message_new_method_return (message);
4522912Sartem if (reply == NULL)
4532912Sartem DIE (("No memory"));
4542912Sartem
4552912Sartem dbus_message_iter_init_append (reply, &iter);
4562912Sartem dbus_message_iter_open_container (&iter,
4572912Sartem DBUS_TYPE_ARRAY,
4582912Sartem DBUS_TYPE_STRING_AS_STRING,
4592912Sartem &iter_array);
4602912Sartem
4612912Sartem info.key = key;
4622912Sartem info.value = value;
4632912Sartem info.iter = &iter_array;
4642912Sartem
4652912Sartem hal_device_store_foreach (hald_get_gdl (),
4662912Sartem foreach_device_match_get_udi,
4672912Sartem &info);
4682912Sartem
4692912Sartem /* Also returns devices in the TDL that has a non-tmp UDI */
4702912Sartem hal_device_store_foreach (hald_get_tdl (),
4712912Sartem foreach_device_match_get_udi_tdl,
4722912Sartem &info);
4732912Sartem
4742912Sartem dbus_message_iter_close_container (&iter, &iter_array);
4752912Sartem
4762912Sartem if (!dbus_connection_send (connection, reply, NULL))
4772912Sartem DIE (("No memory"));
4782912Sartem
4792912Sartem dbus_message_unref (reply);
4802912Sartem
4812912Sartem return DBUS_HANDLER_RESULT_HANDLED;
4822912Sartem }
4832912Sartem
4842912Sartem typedef struct {
4852912Sartem const char *capability;
4862912Sartem DBusMessageIter *iter;
4872912Sartem } DeviceCapabilityInfo;
4882912Sartem
4892912Sartem static gboolean
foreach_device_by_capability(HalDeviceStore * store,HalDevice * device,gpointer user_data)4902912Sartem foreach_device_by_capability (HalDeviceStore *store, HalDevice *device, gpointer user_data)
4912912Sartem {
4922912Sartem DeviceCapabilityInfo *info = (DeviceCapabilityInfo *) user_data;
4932912Sartem
4942912Sartem if (hal_device_has_capability (device, info->capability)) {
4952912Sartem dbus_message_iter_append_basic (info->iter,
4962912Sartem DBUS_TYPE_STRING,
4972912Sartem &(device->udi));
4982912Sartem }
4992912Sartem
5002912Sartem return TRUE;
5012912Sartem }
5022912Sartem
5032912Sartem /** Find devices in the GDL with a given capability.
5042912Sartem *
5052912Sartem * <pre>
5062912Sartem * array{object_reference} Manager.FindDeviceByCapability(string capability)
5072912Sartem * </pre>
5082912Sartem *
5092912Sartem * @param connection D-BUS connection
5102912Sartem * @param message Message
5112912Sartem * @return What to do with the message
5122912Sartem */
5132912Sartem DBusHandlerResult
manager_find_device_by_capability(DBusConnection * connection,DBusMessage * message)5142912Sartem manager_find_device_by_capability (DBusConnection * connection,
5152912Sartem DBusMessage * message)
5162912Sartem {
5172912Sartem DBusMessage *reply;
5182912Sartem DBusMessageIter iter;
5192912Sartem DBusMessageIter iter_array;
5202912Sartem DBusError error;
5212912Sartem const char *capability;
5222912Sartem DeviceCapabilityInfo info;
5232912Sartem
5242912Sartem HAL_TRACE (("entering"));
5252912Sartem
5262912Sartem dbus_error_init (&error);
5272912Sartem if (!dbus_message_get_args (message, &error,
5282912Sartem DBUS_TYPE_STRING, &capability,
5292912Sartem DBUS_TYPE_INVALID)) {
5302912Sartem raise_syntax (connection, message,
5312912Sartem "Manager.FindDeviceByCapability");
5322912Sartem return DBUS_HANDLER_RESULT_HANDLED;
5332912Sartem }
5342912Sartem
5352912Sartem reply = dbus_message_new_method_return (message);
5362912Sartem if (reply == NULL)
5372912Sartem DIE (("No memory"));
5382912Sartem
5392912Sartem dbus_message_iter_init_append (reply, &iter);
5402912Sartem dbus_message_iter_open_container (&iter,
5412912Sartem DBUS_TYPE_ARRAY,
5422912Sartem DBUS_TYPE_STRING_AS_STRING,
5432912Sartem &iter_array);
5442912Sartem
5452912Sartem info.capability = capability;
5462912Sartem info.iter = &iter_array;
5472912Sartem
5482912Sartem hal_device_store_foreach (hald_get_gdl (),
5492912Sartem foreach_device_by_capability,
5502912Sartem &info);
5512912Sartem
5522912Sartem dbus_message_iter_close_container (&iter, &iter_array);
5532912Sartem
5542912Sartem if (!dbus_connection_send (connection, reply, NULL))
5552912Sartem DIE (("No memory"));
5562912Sartem
5572912Sartem dbus_message_unref (reply);
5582912Sartem
5592912Sartem return DBUS_HANDLER_RESULT_HANDLED;
5602912Sartem }
5612912Sartem
5622912Sartem
5632912Sartem /** Determine if a device exists.
5642912Sartem *
5652912Sartem * <pre>
5662912Sartem * bool Manager.DeviceExists(string udi)
5672912Sartem * </pre>
5682912Sartem *
5692912Sartem * @param connection D-BUS connection
5702912Sartem * @param message Message
5712912Sartem * @return What to do with the message
5722912Sartem */
5732912Sartem DBusHandlerResult
manager_device_exists(DBusConnection * connection,DBusMessage * message)5742912Sartem manager_device_exists (DBusConnection * connection, DBusMessage * message)
5752912Sartem {
5762912Sartem DBusMessage *reply;
5772912Sartem DBusMessageIter iter;
5782912Sartem DBusError error;
5792912Sartem HalDevice *d;
5802912Sartem const char *udi;
5812912Sartem dbus_bool_t b;
5822912Sartem
5832912Sartem dbus_error_init (&error);
5842912Sartem if (!dbus_message_get_args (message, &error,
5852912Sartem DBUS_TYPE_STRING, &udi,
5862912Sartem DBUS_TYPE_INVALID)) {
5872912Sartem raise_syntax (connection, message, "Manager.DeviceExists");
5882912Sartem return DBUS_HANDLER_RESULT_HANDLED;
5892912Sartem }
5902912Sartem
5912912Sartem HAL_TRACE (("entering, udi=%s", udi));
5922912Sartem
5932912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
5942912Sartem
5952912Sartem if (d == NULL)
5962912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
5972912Sartem
5982912Sartem reply = dbus_message_new_method_return (message);
5992912Sartem dbus_message_iter_init_append (reply, &iter);
6002912Sartem b = d != NULL;
6012912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &b);
6022912Sartem
6032912Sartem if (reply == NULL)
6042912Sartem DIE (("No memory"));
6052912Sartem
6062912Sartem if (!dbus_connection_send (connection, reply, NULL))
6072912Sartem DIE (("No memory"));
6082912Sartem
6092912Sartem dbus_message_unref (reply);
6102912Sartem return DBUS_HANDLER_RESULT_HANDLED;
6112912Sartem }
6122912Sartem
6132912Sartem /** Send signal DeviceAdded(string udi) on the org.freedesktop.Hal.Manager
6142912Sartem * interface on the object /org/freedesktop/Hal/Manager.
6152912Sartem *
6162912Sartem * @param device The HalDevice added
6172912Sartem */
6182912Sartem void
manager_send_signal_device_added(HalDevice * device)6192912Sartem manager_send_signal_device_added (HalDevice *device)
6202912Sartem {
6212912Sartem const char *udi = hal_device_get_udi (device);
6222912Sartem DBusMessage *message;
6232912Sartem DBusMessageIter iter;
6242912Sartem
6252912Sartem if (dbus_connection == NULL)
6262912Sartem goto out;
6272912Sartem
6282912Sartem HAL_TRACE (("entering, udi=%s", udi));
6292912Sartem
6302912Sartem message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
6312912Sartem "org.freedesktop.Hal.Manager",
6322912Sartem "DeviceAdded");
6332912Sartem
6342912Sartem dbus_message_iter_init_append (message, &iter);
6352912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
6362912Sartem
6372912Sartem if (!dbus_connection_send (dbus_connection, message, NULL))
6382912Sartem DIE (("error broadcasting message"));
6392912Sartem
6402912Sartem dbus_message_unref (message);
6412912Sartem
6422912Sartem out:
6432912Sartem ;
6442912Sartem }
6452912Sartem
6462912Sartem /** Send signal DeviceRemoved(string udi) on the org.freedesktop.Hal.Manager
6472912Sartem * interface on the object /org/freedesktop/Hal/Manager.
6482912Sartem *
6492912Sartem * @param device The HalDevice removed
6502912Sartem */
6512912Sartem void
manager_send_signal_device_removed(HalDevice * device)6522912Sartem manager_send_signal_device_removed (HalDevice *device)
6532912Sartem {
6542912Sartem const char *udi = hal_device_get_udi (device);
6552912Sartem DBusMessage *message;
6562912Sartem DBusMessageIter iter;
6572912Sartem
6582912Sartem if (dbus_connection == NULL)
6592912Sartem goto out;
6602912Sartem
6612912Sartem HAL_TRACE (("entering, udi=%s", udi));
6622912Sartem
6632912Sartem message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
6642912Sartem "org.freedesktop.Hal.Manager",
6652912Sartem "DeviceRemoved");
6662912Sartem
6672912Sartem dbus_message_iter_init_append (message, &iter);
6682912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
6692912Sartem
6702912Sartem if (!dbus_connection_send (dbus_connection, message, NULL))
6712912Sartem DIE (("error broadcasting message"));
6722912Sartem
6732912Sartem dbus_message_unref (message);
6742912Sartem out:
6752912Sartem ;
6762912Sartem }
6772912Sartem
6782912Sartem /** Send signal NewCapability(string udi, string capability) on the
6792912Sartem * org.freedesktop.Hal.Manager interface on the object
6802912Sartem * /org/freedesktop/Hal/Manager.
6812912Sartem *
6822912Sartem * @param udi Unique Device Id
6832912Sartem * @param capability Capability
6842912Sartem */
6852912Sartem void
manager_send_signal_new_capability(HalDevice * device,const char * capability)6862912Sartem manager_send_signal_new_capability (HalDevice *device,
6872912Sartem const char *capability)
6882912Sartem {
6892912Sartem const char *udi = hal_device_get_udi (device);
6902912Sartem DBusMessage *message;
6912912Sartem DBusMessageIter iter;
6922912Sartem
6932912Sartem if (dbus_connection == NULL)
6942912Sartem goto out;
6952912Sartem
6962912Sartem HAL_TRACE (("entering, udi=%s, cap=%s", udi, capability));
6972912Sartem
6982912Sartem message = dbus_message_new_signal ("/org/freedesktop/Hal/Manager",
6992912Sartem "org.freedesktop.Hal.Manager",
7002912Sartem "NewCapability");
7012912Sartem
7022912Sartem dbus_message_iter_init_append (message, &iter);
7032912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
7042912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
7052912Sartem
7062912Sartem if (!dbus_connection_send (dbus_connection, message, NULL))
7072912Sartem DIE (("error broadcasting message"));
7082912Sartem
7092912Sartem dbus_message_unref (message);
7102912Sartem out:
7112912Sartem ;
7122912Sartem }
7132912Sartem
7142912Sartem /** @} */
7152912Sartem
7162912Sartem /**
7172912Sartem * @defgroup DeviceInterface D-BUS interface org.freedesktop.Hal.Device
7182912Sartem * @ingroup HalDaemon
7192912Sartem * @brief D-BUS interface for generic device operations
7202912Sartem * @{
7212912Sartem */
7222912Sartem
7232912Sartem static gboolean
foreach_property_append(HalDevice * device,HalProperty * p,gpointer user_data)7242912Sartem foreach_property_append (HalDevice *device, HalProperty *p,
7252912Sartem gpointer user_data)
7262912Sartem {
7272912Sartem DBusMessageIter *iter;
7282912Sartem DBusMessageIter iter_dict_entry;
7292912Sartem const char *key;
7302912Sartem int type;
7312912Sartem
7322912Sartem iter = (DBusMessageIter *)user_data;
7332912Sartem
7342912Sartem dbus_message_iter_open_container (iter,
7352912Sartem DBUS_TYPE_DICT_ENTRY,
7362912Sartem NULL,
7372912Sartem &iter_dict_entry);
7382912Sartem
7392912Sartem key = hal_property_get_key (p);
7402912Sartem type = hal_property_get_type (p);
7412912Sartem
7422912Sartem dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING, &key);
7432912Sartem
7442912Sartem switch (type) {
7452912Sartem case HAL_PROPERTY_TYPE_STRING:
7462912Sartem {
7472912Sartem DBusMessageIter iter_var;
7482912Sartem const char *v;
7492912Sartem
7502912Sartem v = hal_property_get_string (p);
7512912Sartem
7522912Sartem dbus_message_iter_open_container (&iter_dict_entry,
7532912Sartem DBUS_TYPE_VARIANT,
7542912Sartem DBUS_TYPE_STRING_AS_STRING,
7552912Sartem &iter_var);
7562912Sartem
7572912Sartem dbus_message_iter_append_basic (&iter_var,
7582912Sartem DBUS_TYPE_STRING,
7592912Sartem &v);
7602912Sartem
7612912Sartem dbus_message_iter_close_container (&iter_dict_entry,
7622912Sartem &iter_var);
7632912Sartem break;
7642912Sartem }
7652912Sartem case HAL_PROPERTY_TYPE_INT32:
7662912Sartem {
7672912Sartem DBusMessageIter iter_var;
7682912Sartem dbus_int32_t v;
7692912Sartem
7702912Sartem v = hal_property_get_int (p);
7712912Sartem
7722912Sartem dbus_message_iter_open_container (&iter_dict_entry,
7732912Sartem DBUS_TYPE_VARIANT,
7742912Sartem DBUS_TYPE_INT32_AS_STRING,
7752912Sartem &iter_var);
7762912Sartem
7772912Sartem dbus_message_iter_append_basic (&iter_var,
7782912Sartem DBUS_TYPE_INT32,
7792912Sartem &v);
7802912Sartem
7812912Sartem dbus_message_iter_close_container (&iter_dict_entry,
7822912Sartem &iter_var);
7832912Sartem break;
7842912Sartem }
7852912Sartem case HAL_PROPERTY_TYPE_UINT64:
7862912Sartem {
7872912Sartem DBusMessageIter iter_var;
7882912Sartem dbus_uint64_t v;
7892912Sartem
7902912Sartem v = hal_property_get_uint64 (p);
7912912Sartem
7922912Sartem dbus_message_iter_open_container (&iter_dict_entry,
7932912Sartem DBUS_TYPE_VARIANT,
7942912Sartem DBUS_TYPE_UINT64_AS_STRING,
7952912Sartem &iter_var);
7962912Sartem
7972912Sartem dbus_message_iter_append_basic (&iter_var,
7982912Sartem DBUS_TYPE_UINT64,
7992912Sartem &v);
8002912Sartem
8012912Sartem dbus_message_iter_close_container (&iter_dict_entry,
8022912Sartem &iter_var);
8032912Sartem break;
8042912Sartem }
8052912Sartem case HAL_PROPERTY_TYPE_DOUBLE:
8062912Sartem {
8072912Sartem DBusMessageIter iter_var;
8082912Sartem double v;
8092912Sartem
8102912Sartem v = hal_property_get_double (p);
8112912Sartem
8122912Sartem dbus_message_iter_open_container (&iter_dict_entry,
8132912Sartem DBUS_TYPE_VARIANT,
8142912Sartem DBUS_TYPE_DOUBLE_AS_STRING,
8152912Sartem &iter_var);
8162912Sartem
8172912Sartem dbus_message_iter_append_basic (&iter_var,
8182912Sartem DBUS_TYPE_DOUBLE,
8192912Sartem &v);
8202912Sartem
8212912Sartem dbus_message_iter_close_container (&iter_dict_entry,
8222912Sartem &iter_var);
8232912Sartem break;
8242912Sartem }
8252912Sartem case HAL_PROPERTY_TYPE_BOOLEAN:
8262912Sartem {
8272912Sartem DBusMessageIter iter_var;
8282912Sartem dbus_bool_t v;
8292912Sartem
8302912Sartem v = hal_property_get_bool (p);
8312912Sartem
8322912Sartem dbus_message_iter_open_container (&iter_dict_entry,
8332912Sartem DBUS_TYPE_VARIANT,
8342912Sartem DBUS_TYPE_BOOLEAN_AS_STRING,
8352912Sartem &iter_var);
8362912Sartem
8372912Sartem dbus_message_iter_append_basic (&iter_var,
8382912Sartem DBUS_TYPE_BOOLEAN,
8392912Sartem &v);
8402912Sartem
8412912Sartem dbus_message_iter_close_container (&iter_dict_entry,
8422912Sartem &iter_var);
8432912Sartem break;
8442912Sartem }
8452912Sartem case HAL_PROPERTY_TYPE_STRLIST:
8462912Sartem {
8472912Sartem DBusMessageIter iter_var, iter_array;
8482912Sartem GSList *iter;
8492912Sartem
8502912Sartem dbus_message_iter_open_container (&iter_dict_entry,
8512912Sartem DBUS_TYPE_VARIANT,
8522912Sartem DBUS_TYPE_ARRAY_AS_STRING
8532912Sartem DBUS_TYPE_STRING_AS_STRING,
8542912Sartem &iter_var);
8552912Sartem
8562912Sartem dbus_message_iter_open_container (&iter_var,
8572912Sartem DBUS_TYPE_ARRAY,
8582912Sartem DBUS_TYPE_STRING_AS_STRING,
8592912Sartem &iter_array);
8602912Sartem
8612912Sartem for (iter = hal_property_get_strlist (p); iter != NULL; iter = iter->next) {
8622912Sartem
8632912Sartem const char *v;
8642912Sartem v = (const char *) iter->data;
8652912Sartem
8662912Sartem dbus_message_iter_append_basic (&iter_array,
8672912Sartem DBUS_TYPE_STRING,
8682912Sartem &v);
8692912Sartem }
8702912Sartem
8712912Sartem dbus_message_iter_close_container (&iter_var,
8722912Sartem &iter_array);
8732912Sartem
8742912Sartem dbus_message_iter_close_container (&iter_dict_entry,
8752912Sartem &iter_var);
8762912Sartem break;
8772912Sartem }
8782912Sartem
8792912Sartem default:
8802912Sartem HAL_WARNING (("Unknown property type 0x%04x", type));
8812912Sartem break;
8822912Sartem }
8832912Sartem
8842912Sartem dbus_message_iter_close_container (iter, &iter_dict_entry);
8852912Sartem
8862912Sartem
8872912Sartem return TRUE;
8882912Sartem }
8892912Sartem
8902912Sartem
8912912Sartem
8922912Sartem /** Get all properties on a device.
8932912Sartem *
8942912Sartem * <pre>
8952912Sartem * map{string, any} Device.GetAllProperties()
8962912Sartem *
8972912Sartem * raises org.freedesktop.Hal.NoSuchDevice
8982912Sartem * </pre>
8992912Sartem *
9002912Sartem * @param connection D-BUS connection
9012912Sartem * @param message Message
9022912Sartem * @return What to do with the message
9032912Sartem */
9042912Sartem DBusHandlerResult
device_get_all_properties(DBusConnection * connection,DBusMessage * message)9052912Sartem device_get_all_properties (DBusConnection * connection,
9062912Sartem DBusMessage * message)
9072912Sartem {
9082912Sartem DBusMessage *reply;
9092912Sartem DBusMessageIter iter;
9102912Sartem DBusMessageIter iter_dict;
9112912Sartem HalDevice *d;
9122912Sartem const char *udi;
9132912Sartem
9142912Sartem udi = dbus_message_get_path (message);
9152912Sartem
9162912Sartem HAL_TRACE (("entering, udi=%s", udi));
9172912Sartem
9182912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
9192912Sartem if (d == NULL)
9202912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
9212912Sartem
9222912Sartem if (d == NULL) {
9232912Sartem raise_no_such_device (connection, message, udi);
9242912Sartem return DBUS_HANDLER_RESULT_HANDLED;
9252912Sartem }
9262912Sartem
9272912Sartem reply = dbus_message_new_method_return (message);
9282912Sartem if (reply == NULL)
9292912Sartem DIE (("No memory"));
9302912Sartem
9312912Sartem dbus_message_iter_init_append (reply, &iter);
9322912Sartem
9332912Sartem dbus_message_iter_open_container (&iter,
9342912Sartem DBUS_TYPE_ARRAY,
9352912Sartem DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
9362912Sartem DBUS_TYPE_STRING_AS_STRING
9372912Sartem DBUS_TYPE_VARIANT_AS_STRING
9382912Sartem DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
9392912Sartem &iter_dict);
9402912Sartem
9412912Sartem hal_device_property_foreach (d,
9422912Sartem foreach_property_append,
9432912Sartem &iter_dict);
9442912Sartem
9452912Sartem dbus_message_iter_close_container (&iter, &iter_dict);
9462912Sartem
9472912Sartem if (!dbus_connection_send (connection, reply, NULL))
9482912Sartem DIE (("No memory"));
9492912Sartem
9502912Sartem dbus_message_unref (reply);
9512912Sartem
9522912Sartem return DBUS_HANDLER_RESULT_HANDLED;
9532912Sartem }
9542912Sartem
9552912Sartem #ifdef sun
9562912Sartem #include <sys/stat.h>
9572912Sartem static dbus_bool_t
user_at_console(unsigned long uid)9582912Sartem user_at_console(unsigned long uid)
9592912Sartem {
9602912Sartem struct stat st;
9612912Sartem
9622912Sartem return ((stat("/dev/console", &st) == 0) && (st.st_uid == uid));
9632912Sartem }
9642912Sartem #endif /* sun */
9652912Sartem
9662912Sartem static dbus_bool_t
sender_has_privileges(DBusConnection * connection,DBusMessage * message)9672912Sartem sender_has_privileges (DBusConnection *connection, DBusMessage *message)
9682912Sartem {
9692912Sartem DBusError error;
9702912Sartem unsigned long user_uid;
9712912Sartem const char *user_base_svc;
9722912Sartem dbus_bool_t ret;
9732912Sartem
9742912Sartem ret = FALSE;
9752912Sartem
9762912Sartem user_base_svc = dbus_message_get_sender (message);
9772912Sartem if (user_base_svc == NULL) {
9782912Sartem HAL_WARNING (("Cannot determine base service of caller"));
9792912Sartem goto out;
9802912Sartem }
9812912Sartem
9822912Sartem HAL_DEBUG (("base_svc = %s", user_base_svc));
9832912Sartem
9842912Sartem dbus_error_init (&error);
9852912Sartem user_uid = dbus_bus_get_unix_user (connection, user_base_svc, &error);
9862912Sartem if (user_uid == (unsigned long) -1 || dbus_error_is_set (&error)) {
9872912Sartem HAL_WARNING (("Could not get uid for connection: %s %s", error.name, error.message));
9882912Sartem dbus_error_free (&error);
9892912Sartem goto out;
9902912Sartem }
9912912Sartem
9922912Sartem HAL_INFO (("uid for caller is %ld", user_uid));
9932912Sartem
9942912Sartem if (user_uid != 0 && user_uid != geteuid()) {
9952912Sartem #ifdef sun
9962912Sartem if (dbus_message_is_method_call (message,
9972912Sartem "org.freedesktop.Hal.Device",
9982912Sartem "Rescan")) {
9992912Sartem if (user_at_console(user_uid)) {
10002912Sartem ret = TRUE;
10012912Sartem goto out;
10022912Sartem }
10032912Sartem }
10042912Sartem #endif
10052912Sartem HAL_WARNING (("uid %d is not privileged", user_uid));
10062912Sartem goto out;
10072912Sartem }
10082912Sartem
10092912Sartem ret = TRUE;
10102912Sartem
10112912Sartem out:
10122912Sartem return ret;
10132912Sartem }
10142912Sartem
10152912Sartem
10162912Sartem /** Set multiple properties on a device in an atomic fashion.
10172912Sartem *
10182912Sartem * <pre>
10192912Sartem * Device.GetAllProperties(map{string, any} properties)
10202912Sartem *
10212912Sartem * raises org.freedesktop.Hal.NoSuchDevice
10222912Sartem * </pre>
10232912Sartem *
10242912Sartem * @param connection D-BUS connection
10252912Sartem * @param message Message
10262912Sartem * @return What to do with the message
10272912Sartem */
10282912Sartem static DBusHandlerResult
device_set_multiple_properties(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)10292912Sartem device_set_multiple_properties (DBusConnection *connection, DBusMessage *message, dbus_bool_t local_interface)
10302912Sartem {
10312912Sartem DBusMessage *reply;
10322912Sartem DBusMessageIter iter;
10332912Sartem DBusMessageIter dict_iter;
10342912Sartem HalDevice *d;
10352912Sartem const char *udi;
10362912Sartem
10372912Sartem udi = dbus_message_get_path (message);
10382912Sartem
10392912Sartem HAL_TRACE (("entering, udi=%s", udi));
10402912Sartem
10412912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
10422912Sartem if (d == NULL)
10432912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
10442912Sartem
10452912Sartem if (d == NULL) {
10462912Sartem raise_no_such_device (connection, message, udi);
10472912Sartem return DBUS_HANDLER_RESULT_HANDLED;
10482912Sartem }
10492912Sartem
10502912Sartem if (!local_interface && !sender_has_privileges (connection, message)) {
10512912Sartem raise_permission_denied (connection, message, "SetProperty: not privileged");
10522912Sartem return DBUS_HANDLER_RESULT_HANDLED;
10532912Sartem }
10542912Sartem
10552912Sartem dbus_message_iter_init (message, &iter);
10562912Sartem
10572912Sartem if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY &&
10582912Sartem dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_DICT_ENTRY) {
10592912Sartem HAL_ERROR (("error, expecting an array of dict entries", __FILE__, __LINE__));
10602912Sartem raise_syntax (connection, message, udi);
10612912Sartem return DBUS_HANDLER_RESULT_HANDLED;
10622912Sartem }
10632912Sartem
10642912Sartem dbus_message_iter_recurse (&iter, &dict_iter);
10652912Sartem
10662912Sartem /* update atomically */
10672912Sartem device_property_atomic_update_begin ();
10682912Sartem
10692912Sartem while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
10702912Sartem {
10712912Sartem DBusMessageIter dict_entry_iter, var_iter, array_iter;
10722912Sartem const char *key;
10732912Sartem int change_type;
10742912Sartem dbus_bool_t rc;
10752912Sartem
10762912Sartem dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
10772912Sartem dbus_message_iter_get_basic (&dict_entry_iter, &key);
10782912Sartem
10792912Sartem dbus_message_iter_next (&dict_entry_iter);
10802912Sartem dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
10812912Sartem change_type = dbus_message_iter_get_arg_type (&var_iter);
10822912Sartem
10832912Sartem rc = FALSE;
10842912Sartem
10852912Sartem switch (change_type) {
10862912Sartem case DBUS_TYPE_ARRAY:
10872912Sartem if (dbus_message_iter_get_element_type (&var_iter) != DBUS_TYPE_STRING) {
10882912Sartem /* TODO: error */
10892912Sartem }
10902912Sartem dbus_message_iter_recurse (&var_iter, &array_iter);
10912912Sartem
10922912Sartem hal_device_property_strlist_clear (d, key);
10932912Sartem
10942912Sartem while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRING) {
10952912Sartem const char *v;
10962912Sartem dbus_message_iter_get_basic (&array_iter, &v);
10972912Sartem HAL_INFO ((" strlist elem %s -> %s", key, v));
10982912Sartem rc = hal_device_property_strlist_append (d, key, v);
10992912Sartem dbus_message_iter_next (&array_iter);
11002912Sartem }
11012912Sartem
11022912Sartem break;
11032912Sartem case DBUS_TYPE_STRING:
11042912Sartem {
11052912Sartem const char *v;
11062912Sartem dbus_message_iter_get_basic (&var_iter, &v);
11072912Sartem HAL_INFO (("%s -> %s", key, v));
11082912Sartem rc = hal_device_property_set_string (d, key, v);
11092912Sartem break;
11102912Sartem }
11112912Sartem case DBUS_TYPE_INT32:
11122912Sartem {
11132912Sartem dbus_int32_t v;
11142912Sartem dbus_message_iter_get_basic (&var_iter, &v);
11152912Sartem HAL_INFO (("%s -> %d", key, v));
11162912Sartem rc = hal_device_property_set_int (d, key, v);
11172912Sartem break;
11182912Sartem }
11192912Sartem case DBUS_TYPE_UINT64:
11202912Sartem {
11212912Sartem dbus_uint64_t v;
11222912Sartem dbus_message_iter_get_basic (&var_iter, &v);
11232912Sartem HAL_INFO (("%s -> %lld", key, v));
11242912Sartem rc = hal_device_property_set_uint64 (d, key, v);
11252912Sartem break;
11262912Sartem }
11272912Sartem case DBUS_TYPE_DOUBLE:
11282912Sartem {
11292912Sartem double v;
11302912Sartem dbus_message_iter_get_basic (&var_iter, &v);
11312912Sartem HAL_INFO (("%s -> %g", key, v));
11322912Sartem rc = hal_device_property_set_double (d, key, v);
11332912Sartem break;
11342912Sartem }
11352912Sartem case DBUS_TYPE_BOOLEAN:
11362912Sartem {
11372912Sartem gboolean v;
11382912Sartem dbus_message_iter_get_basic (&var_iter, &v);
11392912Sartem HAL_INFO (("%s -> %s", key, v ? "True" : "False"));
11402912Sartem rc = hal_device_property_set_bool (d, key, v);
11412912Sartem break;
11422912Sartem }
11432912Sartem default:
11442912Sartem /* TODO: error */
11452912Sartem break;
11462912Sartem }
11472912Sartem
11482912Sartem /* TODO: error out on rc==FALSE? */
11492912Sartem
11502912Sartem dbus_message_iter_next (&dict_iter);
11512912Sartem }
11522912Sartem
11532912Sartem device_property_atomic_update_end ();
11542912Sartem
11552912Sartem
11562912Sartem reply = dbus_message_new_method_return (message);
11572912Sartem if (reply == NULL)
11582912Sartem DIE (("No memory"));
11592912Sartem
11602912Sartem if (!dbus_connection_send (connection, reply, NULL))
11612912Sartem DIE (("No memory"));
11622912Sartem
11632912Sartem dbus_message_unref (reply);
11642912Sartem return DBUS_HANDLER_RESULT_HANDLED;
11652912Sartem }
11662912Sartem
11672912Sartem
11682912Sartem /** Get a property on a device.
11692912Sartem *
11702912Sartem * <pre>
11712912Sartem * any Device.GetProperty(string key)
11722912Sartem * string Device.GetPropertyString(string key)
11732912Sartem * int Device.GetPropertyInteger(string key)
11742912Sartem * bool Device.GetPropertyBoolean(string key)
11752912Sartem * double Device.GetPropertyDouble(string key)
11762912Sartem *
11772912Sartem * raises org.freedesktop.Hal.NoSuchDevice,
11782912Sartem * org.freedesktop.Hal.NoSuchProperty
11792912Sartem * </pre>
11802912Sartem *
11812912Sartem * @param connection D-BUS connection
11822912Sartem * @param message Message
11832912Sartem * @return What to do with the message
11842912Sartem */
11852912Sartem DBusHandlerResult
device_get_property(DBusConnection * connection,DBusMessage * message)11862912Sartem device_get_property (DBusConnection * connection, DBusMessage * message)
11872912Sartem {
11882912Sartem DBusMessage *reply;
11892912Sartem DBusMessageIter iter;
11902912Sartem DBusError error;
11912912Sartem HalDevice *d;
11922912Sartem const char *udi;
11932912Sartem char *key;
11942912Sartem int type;
11952912Sartem HalProperty *p;
11962912Sartem
11972912Sartem udi = dbus_message_get_path (message);
11982912Sartem
11992912Sartem HAL_TRACE (("entering, udi=%s", udi));
12002912Sartem
12012912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
12022912Sartem if (d == NULL)
12032912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
12042912Sartem
12052912Sartem if (d == NULL) {
12062912Sartem raise_no_such_device (connection, message, udi);
12072912Sartem return DBUS_HANDLER_RESULT_HANDLED;
12082912Sartem }
12092912Sartem
12102912Sartem dbus_error_init (&error);
12112912Sartem if (!dbus_message_get_args (message, &error,
12122912Sartem DBUS_TYPE_STRING, &key,
12132912Sartem DBUS_TYPE_INVALID)) {
12142912Sartem raise_syntax (connection, message, "GetProperty");
12152912Sartem return DBUS_HANDLER_RESULT_HANDLED;
12162912Sartem }
12172912Sartem
12182912Sartem p = hal_device_property_find (d, key);
12192912Sartem if (p == NULL) {
12202912Sartem raise_no_such_property (connection, message, udi, key);
12212912Sartem return DBUS_HANDLER_RESULT_HANDLED;
12222912Sartem }
12232912Sartem
12242912Sartem reply = dbus_message_new_method_return (message);
12252912Sartem if (reply == NULL)
12262912Sartem DIE (("No memory"));
12272912Sartem
12282912Sartem dbus_message_iter_init_append (reply, &iter);
12292912Sartem
12302912Sartem type = hal_property_get_type (p);
12312912Sartem switch (type) {
12322912Sartem case HAL_PROPERTY_TYPE_STRING:
12332912Sartem {
12342912Sartem const char *s;
12352912Sartem s = hal_property_get_string (p);
12362912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &s);
12372912Sartem break;
12382912Sartem }
12392912Sartem case HAL_PROPERTY_TYPE_INT32:
12402912Sartem {
12412912Sartem dbus_int32_t i;
12422912Sartem i = hal_property_get_int (p);
12432912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &i);
12442912Sartem break;
12452912Sartem }
12462912Sartem case HAL_PROPERTY_TYPE_UINT64:
12472912Sartem {
12482912Sartem dbus_uint64_t ul;
12492912Sartem ul = hal_property_get_uint64 (p);
12502912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &ul);
12512912Sartem break;
12522912Sartem }
12532912Sartem case HAL_PROPERTY_TYPE_DOUBLE:
12542912Sartem {
12552912Sartem double d;
12562912Sartem d = hal_property_get_double (p);
12572912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &d);
12582912Sartem break;
12592912Sartem }
12602912Sartem case HAL_PROPERTY_TYPE_BOOLEAN:
12612912Sartem {
12622912Sartem dbus_bool_t b;
12632912Sartem b = hal_property_get_bool (p);
12642912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &b);
12652912Sartem break;
12662912Sartem }
12672912Sartem case HAL_PROPERTY_TYPE_STRLIST:
12682912Sartem {
12692912Sartem GSList *l;
12702912Sartem DBusMessageIter iter_array;
12712912Sartem
12722912Sartem dbus_message_iter_open_container (&iter,
12732912Sartem DBUS_TYPE_ARRAY,
12742912Sartem DBUS_TYPE_STRING_AS_STRING,
12752912Sartem &iter_array);
12762912Sartem
12772912Sartem for (l = hal_property_get_strlist (p); l != NULL; l = g_slist_next (l)) {
12782912Sartem dbus_message_iter_append_basic (&iter_array, DBUS_TYPE_STRING, &(l->data));
12792912Sartem }
12802912Sartem
12812912Sartem dbus_message_iter_close_container (&iter, &iter_array);
12822912Sartem }
12832912Sartem break;
12842912Sartem
12852912Sartem default:
12862912Sartem HAL_WARNING (("Unknown property type %d", type));
12872912Sartem break;
12882912Sartem }
12892912Sartem
12902912Sartem if (!dbus_connection_send (connection, reply, NULL))
12912912Sartem DIE (("No memory"));
12922912Sartem
12932912Sartem dbus_message_unref (reply);
12942912Sartem
12952912Sartem return DBUS_HANDLER_RESULT_HANDLED;
12962912Sartem }
12972912Sartem
12982912Sartem
12992912Sartem /** Get the type of a property on a device.
13002912Sartem *
13012912Sartem * <pre>
13022912Sartem * int Device.GetPropertyType(string key)
13032912Sartem *
13042912Sartem * raises org.freedesktop.Hal.NoSuchDevice,
13052912Sartem * org.freedesktop.Hal.NoSuchProperty
13062912Sartem * </pre>
13072912Sartem *
13082912Sartem * @param connection D-BUS connection
13092912Sartem * @param message Message
13102912Sartem * @return What to do with the message
13112912Sartem */
13122912Sartem DBusHandlerResult
device_get_property_type(DBusConnection * connection,DBusMessage * message)13132912Sartem device_get_property_type (DBusConnection * connection,
13142912Sartem DBusMessage * message)
13152912Sartem {
13162912Sartem DBusMessage *reply;
13172912Sartem DBusMessageIter iter;
13182912Sartem DBusError error;
13192912Sartem HalDevice *d;
13202912Sartem const char *udi;
13212912Sartem char *key;
13222912Sartem HalProperty *p;
13232912Sartem dbus_int32_t i;
13242912Sartem
13252912Sartem udi = dbus_message_get_path (message);
13262912Sartem
13272912Sartem HAL_TRACE (("entering, udi=%s", udi));
13282912Sartem
13292912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
13302912Sartem if (d == NULL)
13312912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
13322912Sartem
13332912Sartem if (d == NULL) {
13342912Sartem raise_no_such_device (connection, message, udi);
13352912Sartem return DBUS_HANDLER_RESULT_HANDLED;
13362912Sartem }
13372912Sartem
13382912Sartem dbus_error_init (&error);
13392912Sartem if (!dbus_message_get_args (message, &error,
13402912Sartem DBUS_TYPE_STRING, &key,
13412912Sartem DBUS_TYPE_INVALID)) {
13422912Sartem raise_syntax (connection, message, "GetPropertyType");
13432912Sartem return DBUS_HANDLER_RESULT_HANDLED;
13442912Sartem }
13452912Sartem
13462912Sartem p = hal_device_property_find (d, key);
13472912Sartem if (p == NULL) {
13482912Sartem raise_no_such_property (connection, message, udi, key);
13492912Sartem return DBUS_HANDLER_RESULT_HANDLED;
13502912Sartem }
13512912Sartem
13522912Sartem reply = dbus_message_new_method_return (message);
13532912Sartem if (reply == NULL)
13542912Sartem DIE (("No memory"));
13552912Sartem
13562912Sartem i = hal_property_get_type (p);
13572912Sartem dbus_message_iter_init_append (reply, &iter);
13582912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &i);
13592912Sartem
13602912Sartem if (!dbus_connection_send (connection, reply, NULL))
13612912Sartem DIE (("No memory"));
13622912Sartem
13632912Sartem dbus_message_unref (reply);
13642912Sartem
13652912Sartem return DBUS_HANDLER_RESULT_HANDLED;
13662912Sartem }
13672912Sartem
13682912Sartem /** Set a property on a device.
13692912Sartem *
13702912Sartem * <pre>
13712912Sartem * void Device.SetProperty(string key, any value)
13722912Sartem * void Device.SetPropertyString(string key, string value)
13732912Sartem * void Device.SetPropertyInteger(string key, int value)
13742912Sartem * void Device.SetPropertyBoolean(string key, bool value)
13752912Sartem * void Device.SetPropertyDouble(string key, double value)
13762912Sartem *
13772912Sartem * raises org.freedesktop.Hal.NoSuchDevice,
13782912Sartem * org.freedesktop.Hal.NoSuchProperty
13792912Sartem * org.freedesktop.Hal.TypeMismatch
13802912Sartem * </pre>
13812912Sartem *
13822912Sartem * @param connection D-BUS connection
13832912Sartem * @param message Message
13842912Sartem * @return What to do with the message
13852912Sartem */
13862912Sartem DBusHandlerResult
device_set_property(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)13872912Sartem device_set_property (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
13882912Sartem {
13892912Sartem const char *udi;
13902912Sartem char *key;
13912912Sartem int type;
13922912Sartem dbus_bool_t rc;
13932912Sartem HalDevice *device;
13942912Sartem DBusMessageIter iter;
13952912Sartem DBusMessage *reply;
13962912Sartem
13972912Sartem HAL_TRACE (("entering"));
13982912Sartem
13992912Sartem udi = dbus_message_get_path (message);
14002912Sartem
14012912Sartem dbus_message_iter_init (message, &iter);
14022912Sartem type = dbus_message_iter_get_arg_type (&iter);
14032912Sartem if (type != DBUS_TYPE_STRING) {
14042912Sartem raise_syntax (connection, message, "SetProperty");
14052912Sartem return DBUS_HANDLER_RESULT_HANDLED;
14062912Sartem }
14072912Sartem dbus_message_iter_get_basic (&iter, &key);
14082912Sartem
14092912Sartem if (!local_interface && !sender_has_privileges (connection, message)) {
14102912Sartem raise_permission_denied (connection, message, "SetProperty: not privileged");
14112912Sartem return DBUS_HANDLER_RESULT_HANDLED;
14122912Sartem }
14132912Sartem
14142912Sartem HAL_DEBUG (("udi=%s, key=%s", udi, key));
14152912Sartem
14162912Sartem device = hal_device_store_find (hald_get_gdl (), udi);
14172912Sartem if (device == NULL)
14182912Sartem device = hal_device_store_find (hald_get_tdl (), udi);
14192912Sartem
14202912Sartem if (device == NULL) {
14212912Sartem raise_no_such_device (connection, message, udi);
14222912Sartem return DBUS_HANDLER_RESULT_HANDLED;
14232912Sartem }
14242912Sartem dbus_message_iter_next (&iter);
14252912Sartem
14262912Sartem /** @todo check permissions of the sender vs property to be modified */
14272912Sartem
14282912Sartem type = dbus_message_iter_get_arg_type (&iter);
14292912Sartem rc = FALSE;
14302912Sartem
14312912Sartem switch (type) {
14322912Sartem case DBUS_TYPE_STRING:
14332912Sartem {
14342912Sartem const char *v;
14352912Sartem dbus_message_iter_get_basic (&iter, &v);
14362912Sartem rc = hal_device_property_set_string (device, key, v);
14372912Sartem break;
14382912Sartem }
14392912Sartem case DBUS_TYPE_INT32:
14402912Sartem {
14412912Sartem dbus_int32_t v;
14422912Sartem dbus_message_iter_get_basic (&iter, &v);
14432912Sartem rc = hal_device_property_set_int (device, key, v);
14442912Sartem break;
14452912Sartem }
14462912Sartem case DBUS_TYPE_UINT64:
14472912Sartem {
14482912Sartem dbus_uint64_t v;
14492912Sartem dbus_message_iter_get_basic (&iter, &v);
14502912Sartem rc = hal_device_property_set_uint64 (device, key, v);
14512912Sartem break;
14522912Sartem }
14532912Sartem case DBUS_TYPE_DOUBLE:
14542912Sartem {
14552912Sartem double v;
14562912Sartem dbus_message_iter_get_basic (&iter, &v);
14572912Sartem rc = hal_device_property_set_double (device, key, v);
14582912Sartem break;
14592912Sartem }
14602912Sartem case DBUS_TYPE_BOOLEAN:
14612912Sartem {
14622912Sartem dbus_bool_t v;
14632912Sartem dbus_message_iter_get_basic (&iter, &v);
14642912Sartem rc = hal_device_property_set_bool (device, key, v);
14652912Sartem break;
14662912Sartem }
14672912Sartem default:
14682912Sartem HAL_WARNING (("Unsupported property type %d", type));
14692912Sartem break;
14702912Sartem }
14712912Sartem
14722912Sartem if (!rc) {
14732912Sartem raise_property_type_error (connection, message, udi, key);
14742912Sartem return DBUS_HANDLER_RESULT_HANDLED;
14752912Sartem }
14762912Sartem
14772912Sartem reply = dbus_message_new_method_return (message);
14782912Sartem if (reply == NULL)
14792912Sartem DIE (("No memory"));
14802912Sartem
14812912Sartem if (!dbus_connection_send (connection, reply, NULL))
14822912Sartem DIE (("No memory"));
14832912Sartem
14842912Sartem dbus_message_unref (reply);
14852912Sartem return DBUS_HANDLER_RESULT_HANDLED;
14862912Sartem }
14872912Sartem
14882912Sartem /** This function is used to modify the Capabilities property. The reason
14892912Sartem * for having a dedicated function is that the HAL daemon will broadcast
14902912Sartem * a signal on the Manager interface to tell applications that the device
14912912Sartem * have got a new capability.
14922912Sartem *
14932912Sartem * This is useful as capabilities can be merged after the device is created.
14942912Sartem * One example of this is networking cards under Linux 2.6; the net.ethernet
14952912Sartem * capability is not merged when the device is initially found by looking in
14962912Sartem * /sys/devices; it is merged when the /sys/classes tree is searched.
14972912Sartem *
14982912Sartem * Note that the signal is emitted every time this method is invoked even
14992912Sartem * though the capability already existed. This is useful in the above
15002912Sartem * scenario when the PCI class says ethernet networking card but we yet
15012912Sartem * don't have enough information to fill in the net.* and net.ethernet.*
15022912Sartem * fields since this only happens when we visit the /sys/classes tree.
15032912Sartem *
15042912Sartem * <pre>
15052912Sartem * void Device.AddCapability(string capability)
15062912Sartem *
15072912Sartem * raises org.freedesktop.Hal.NoSuchDevice,
15082912Sartem * raises org.freedesktop.Hal.PermissionDenied,
15092912Sartem * </pre>
15102912Sartem *
15112912Sartem * @param connection D-BUS connection
15122912Sartem * @param message Message
15132912Sartem * @return What to do with the message
15142912Sartem */
15152912Sartem DBusHandlerResult
device_add_capability(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)15162912Sartem device_add_capability (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
15172912Sartem {
15182912Sartem const char *udi;
15192912Sartem const char *capability;
15202912Sartem HalDevice *d;
15212912Sartem DBusMessage *reply;
15222912Sartem DBusError error;
15232912Sartem
15242912Sartem HAL_TRACE (("entering"));
15252912Sartem
15262912Sartem if (!local_interface && !sender_has_privileges (connection, message)) {
15272912Sartem raise_permission_denied (connection, message, "AddCapability: not privileged");
15282912Sartem return DBUS_HANDLER_RESULT_HANDLED;
15292912Sartem }
15302912Sartem
15312912Sartem udi = dbus_message_get_path (message);
15322912Sartem
15332912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
15342912Sartem if (d == NULL)
15352912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
15362912Sartem
15372912Sartem if (d == NULL) {
15382912Sartem raise_no_such_device (connection, message, udi);
15392912Sartem return DBUS_HANDLER_RESULT_HANDLED;
15402912Sartem }
15412912Sartem
15422912Sartem dbus_error_init (&error);
15432912Sartem if (!dbus_message_get_args (message, &error,
15442912Sartem DBUS_TYPE_STRING, &capability,
15452912Sartem DBUS_TYPE_INVALID)) {
15462912Sartem raise_syntax (connection, message, "AddCapability");
15472912Sartem return DBUS_HANDLER_RESULT_HANDLED;
15482912Sartem }
15492912Sartem
15502912Sartem
15512912Sartem hal_device_add_capability (d, capability);
15522912Sartem
15532912Sartem reply = dbus_message_new_method_return (message);
15542912Sartem if (reply == NULL)
15552912Sartem DIE (("No memory"));
15562912Sartem
15572912Sartem if (!dbus_connection_send (connection, reply, NULL))
15582912Sartem DIE (("No memory"));
15592912Sartem
15602912Sartem dbus_message_unref (reply);
15612912Sartem return DBUS_HANDLER_RESULT_HANDLED;
15622912Sartem }
15632912Sartem
15642912Sartem
15652912Sartem /* TODO: docs */
15662912Sartem static DBusHandlerResult
device_string_list_append_prepend(DBusConnection * connection,DBusMessage * message,dbus_bool_t do_prepend)15672912Sartem device_string_list_append_prepend (DBusConnection * connection, DBusMessage * message, dbus_bool_t do_prepend)
15682912Sartem {
15692912Sartem const char *udi;
15702912Sartem const char *key;
15712912Sartem const char *value;
15722912Sartem HalDevice *d;
15732912Sartem DBusMessage *reply;
15742912Sartem DBusError error;
15752912Sartem gboolean ret;
15762912Sartem
15772912Sartem HAL_TRACE (("entering"));
15782912Sartem
15792912Sartem udi = dbus_message_get_path (message);
15802912Sartem
15812912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
15822912Sartem if (d == NULL)
15832912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
15842912Sartem
15852912Sartem if (d == NULL) {
15862912Sartem raise_no_such_device (connection, message, udi);
15872912Sartem return DBUS_HANDLER_RESULT_HANDLED;
15882912Sartem }
15892912Sartem
15902912Sartem dbus_error_init (&error);
15912912Sartem if (!dbus_message_get_args (message, &error,
15922912Sartem DBUS_TYPE_STRING, &key,
15932912Sartem DBUS_TYPE_STRING, &value,
15942912Sartem DBUS_TYPE_INVALID)) {
15952912Sartem raise_syntax (connection, message, do_prepend ? "StringListPrepend" : "StringListAppend");
15962912Sartem return DBUS_HANDLER_RESULT_HANDLED;
15972912Sartem }
15982912Sartem
15992912Sartem if (do_prepend)
16002912Sartem ret = hal_device_property_strlist_prepend (d, key, value);
16012912Sartem else
16022912Sartem ret = hal_device_property_strlist_append (d, key, value);
16032912Sartem if (!ret) {
16042912Sartem raise_property_type_error (connection, message, udi, key);
16052912Sartem return DBUS_HANDLER_RESULT_HANDLED;
16062912Sartem }
16072912Sartem
16082912Sartem reply = dbus_message_new_method_return (message);
16092912Sartem if (reply == NULL)
16102912Sartem DIE (("No memory"));
16112912Sartem
16122912Sartem if (!dbus_connection_send (connection, reply, NULL))
16132912Sartem DIE (("No memory"));
16142912Sartem
16152912Sartem dbus_message_unref (reply);
16162912Sartem return DBUS_HANDLER_RESULT_HANDLED;
16172912Sartem }
16182912Sartem
16192912Sartem /* TODO: docs */
16202912Sartem static DBusHandlerResult
device_string_list_remove(DBusConnection * connection,DBusMessage * message)16212912Sartem device_string_list_remove (DBusConnection * connection, DBusMessage * message)
16222912Sartem {
16232912Sartem const char *udi;
16242912Sartem const char *key;
16252912Sartem const char *value;
16262912Sartem HalDevice *d;
16272912Sartem DBusMessage *reply;
16282912Sartem DBusError error;
16292912Sartem gboolean ret;
16302912Sartem
16312912Sartem HAL_TRACE (("entering"));
16322912Sartem
16332912Sartem udi = dbus_message_get_path (message);
16342912Sartem
16352912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
16362912Sartem if (d == NULL)
16372912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
16382912Sartem
16392912Sartem if (d == NULL) {
16402912Sartem raise_no_such_device (connection, message, udi);
16412912Sartem return DBUS_HANDLER_RESULT_HANDLED;
16422912Sartem }
16432912Sartem
16442912Sartem dbus_error_init (&error);
16452912Sartem if (!dbus_message_get_args (message, &error,
16462912Sartem DBUS_TYPE_STRING, &key,
16472912Sartem DBUS_TYPE_STRING, &value,
16482912Sartem DBUS_TYPE_INVALID)) {
16492912Sartem raise_syntax (connection, message, "StringListRemove");
16502912Sartem return DBUS_HANDLER_RESULT_HANDLED;
16512912Sartem }
16522912Sartem
16532912Sartem ret = hal_device_property_strlist_remove (d, key, value);
16542912Sartem if (!ret) {
16552912Sartem raise_property_type_error (connection, message, udi, key);
16562912Sartem return DBUS_HANDLER_RESULT_HANDLED;
16572912Sartem }
16582912Sartem
16592912Sartem reply = dbus_message_new_method_return (message);
16602912Sartem if (reply == NULL)
16612912Sartem DIE (("No memory"));
16622912Sartem
16632912Sartem if (!dbus_connection_send (connection, reply, NULL))
16642912Sartem DIE (("No memory"));
16652912Sartem
16662912Sartem dbus_message_unref (reply);
16672912Sartem return DBUS_HANDLER_RESULT_HANDLED;
16682912Sartem }
16692912Sartem
16702912Sartem
16712912Sartem
16722912Sartem /** Remove a property on a device.
16732912Sartem *
16742912Sartem * <pre>
16752912Sartem * void Device.RemoveProperty(string key)
16762912Sartem *
16772912Sartem * raises org.freedesktop.Hal.NoSuchDevice,
16782912Sartem * org.freedesktop.Hal.NoSuchProperty
16792912Sartem * org.freedesktop.Hal.PermissionDenied
16802912Sartem * </pre>
16812912Sartem *
16822912Sartem * @param connection D-BUS connection
16832912Sartem * @param message Message
16842912Sartem * @return What to do with the message
16852912Sartem */
16862912Sartem DBusHandlerResult
device_remove_property(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)16872912Sartem device_remove_property (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
16882912Sartem {
16892912Sartem const char *udi;
16902912Sartem char *key;
16912912Sartem HalDevice *d;
16922912Sartem DBusMessage *reply;
16932912Sartem DBusError error;
16942912Sartem
16952912Sartem HAL_TRACE (("entering"));
16962912Sartem
16972912Sartem udi = dbus_message_get_path (message);
16982912Sartem
16992912Sartem if (!local_interface && !sender_has_privileges (connection, message)) {
17002912Sartem raise_permission_denied (connection, message, "RemoveProperty: not privileged");
17012912Sartem return DBUS_HANDLER_RESULT_HANDLED;
17022912Sartem }
17032912Sartem
17042912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
17052912Sartem if (d == NULL)
17062912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
17072912Sartem
17082912Sartem if (d == NULL) {
17092912Sartem raise_no_such_device (connection, message, udi);
17102912Sartem return DBUS_HANDLER_RESULT_HANDLED;
17112912Sartem }
17122912Sartem
17132912Sartem dbus_error_init (&error);
17142912Sartem if (!dbus_message_get_args (message, &error,
17152912Sartem DBUS_TYPE_STRING, &key,
17162912Sartem DBUS_TYPE_INVALID)) {
17172912Sartem raise_syntax (connection, message, "RemoveProperty");
17182912Sartem return DBUS_HANDLER_RESULT_HANDLED;
17192912Sartem }
17202912Sartem
17212912Sartem if (!hal_device_property_remove (d, key)) {
17222912Sartem raise_no_such_property (connection, message, udi, key);
17232912Sartem return DBUS_HANDLER_RESULT_HANDLED;
17242912Sartem }
17252912Sartem
17262912Sartem
17272912Sartem reply = dbus_message_new_method_return (message);
17282912Sartem if (reply == NULL)
17292912Sartem DIE (("No memory"));
17302912Sartem
17312912Sartem if (!dbus_connection_send (connection, reply, NULL))
17322912Sartem DIE (("No memory"));
17332912Sartem
17342912Sartem dbus_message_unref (reply);
17352912Sartem return DBUS_HANDLER_RESULT_HANDLED;
17362912Sartem }
17372912Sartem
17382912Sartem
17392912Sartem /** Determine if a property exists
17402912Sartem *
17412912Sartem * <pre>
17422912Sartem * bool Device.PropertyExists(string key)
17432912Sartem *
17442912Sartem * raises org.freedesktop.Hal.NoSuchDevice,
17452912Sartem * </pre>
17462912Sartem *
17472912Sartem * @param connection D-BUS connection
17482912Sartem * @param message Message
17492912Sartem * @return What to do with the message
17502912Sartem */
17512912Sartem DBusHandlerResult
device_property_exists(DBusConnection * connection,DBusMessage * message)17522912Sartem device_property_exists (DBusConnection * connection, DBusMessage * message)
17532912Sartem {
17542912Sartem const char *udi;
17552912Sartem char *key;
17562912Sartem HalDevice *d;
17572912Sartem DBusMessage *reply;
17582912Sartem DBusError error;
17592912Sartem DBusMessageIter iter;
17602912Sartem dbus_bool_t b;
17612912Sartem
17622912Sartem HAL_TRACE (("entering"));
17632912Sartem
17642912Sartem udi = dbus_message_get_path (message);
17652912Sartem
17662912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
17672912Sartem if (d == NULL)
17682912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
17692912Sartem
17702912Sartem if (d == NULL) {
17712912Sartem raise_no_such_device (connection, message, udi);
17722912Sartem return DBUS_HANDLER_RESULT_HANDLED;
17732912Sartem }
17742912Sartem
17752912Sartem dbus_error_init (&error);
17762912Sartem if (!dbus_message_get_args (message, &error,
17772912Sartem DBUS_TYPE_STRING, &key,
17782912Sartem DBUS_TYPE_INVALID)) {
17792912Sartem raise_syntax (connection, message, "RemoveProperty");
17802912Sartem return DBUS_HANDLER_RESULT_HANDLED;
17812912Sartem }
17822912Sartem
17832912Sartem reply = dbus_message_new_method_return (message);
17842912Sartem if (reply == NULL)
17852912Sartem DIE (("No memory"));
17862912Sartem
17872912Sartem b = hal_device_has_property (d, key);
17882912Sartem dbus_message_iter_init_append (reply, &iter);
17892912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &b);
17902912Sartem
17912912Sartem if (!dbus_connection_send (connection, reply, NULL))
17922912Sartem DIE (("No memory"));
17932912Sartem
17942912Sartem dbus_message_unref (reply);
17952912Sartem return DBUS_HANDLER_RESULT_HANDLED;
17962912Sartem }
17972912Sartem
17982912Sartem
17992912Sartem /** Determine if a device has a capability
18002912Sartem *
18012912Sartem * <pre>
18022912Sartem * bool Device.QueryCapability(string capability_name)
18032912Sartem *
18042912Sartem * raises org.freedesktop.Hal.NoSuchDevice,
18052912Sartem * </pre>
18062912Sartem *
18072912Sartem * @param connection D-BUS connection
18082912Sartem * @param message Message
18092912Sartem * @return What to do with the message
18102912Sartem */
18112912Sartem DBusHandlerResult
device_query_capability(DBusConnection * connection,DBusMessage * message)18122912Sartem device_query_capability (DBusConnection * connection,
18132912Sartem DBusMessage * message)
18142912Sartem {
18152912Sartem dbus_bool_t rc;
18162912Sartem const char *udi;
18172912Sartem GSList *caps;
18182912Sartem char *capability;
18192912Sartem HalDevice *d;
18202912Sartem DBusMessage *reply;
18212912Sartem DBusError error;
18222912Sartem DBusMessageIter iter;
18232912Sartem
18242912Sartem HAL_TRACE (("entering"));
18252912Sartem
18262912Sartem udi = dbus_message_get_path (message);
18272912Sartem
18282912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
18292912Sartem if (d == NULL)
18302912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
18312912Sartem
18322912Sartem if (d == NULL) {
18332912Sartem raise_no_such_device (connection, message, udi);
18342912Sartem return DBUS_HANDLER_RESULT_HANDLED;
18352912Sartem }
18362912Sartem
18372912Sartem dbus_error_init (&error);
18382912Sartem if (!dbus_message_get_args (message, &error,
18392912Sartem DBUS_TYPE_STRING, &capability,
18402912Sartem DBUS_TYPE_INVALID)) {
18412912Sartem raise_syntax (connection, message, "QueryCapability");
18422912Sartem return DBUS_HANDLER_RESULT_HANDLED;
18432912Sartem }
18442912Sartem
18452912Sartem reply = dbus_message_new_method_return (message);
18462912Sartem if (reply == NULL)
18472912Sartem DIE (("No memory"));
18482912Sartem
18492912Sartem rc = FALSE;
18502912Sartem caps = hal_device_property_get_strlist (d, "info.capabilities");
18512912Sartem if (caps != NULL) {
18522912Sartem GSList *iter;
18532912Sartem
18542912Sartem for (iter = caps; iter != NULL; iter=g_slist_next(iter)) {
18552912Sartem if (strcmp (iter->data, capability) == 0) {
18562912Sartem rc = TRUE;
18572912Sartem break;
18582912Sartem }
18592912Sartem }
18602912Sartem }
18612912Sartem
18622912Sartem dbus_message_iter_init_append (reply, &iter);
18632912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &rc);
18642912Sartem
18652912Sartem if (!dbus_connection_send (connection, reply, NULL))
18662912Sartem DIE (("No memory"));
18672912Sartem
18682912Sartem dbus_message_unref (reply);
18692912Sartem return DBUS_HANDLER_RESULT_HANDLED;
18702912Sartem }
18712912Sartem
18722912Sartem static GHashTable *services_with_locks = NULL;
18732912Sartem
18742912Sartem /** Grab an advisory lock on a device.
18752912Sartem *
18762912Sartem * <pre>
18772912Sartem * bool Device.Lock(string reason)
18782912Sartem *
18792912Sartem * raises org.freedesktop.Hal.NoSuchDevice,
18802912Sartem * org.freedesktop.Hal.DeviceAlreadyLocked
18812912Sartem * </pre>
18822912Sartem *
18832912Sartem * @param connection D-BUS connection
18842912Sartem * @param message Message
18852912Sartem * @return What to do with the message
18862912Sartem */
18872912Sartem DBusHandlerResult
device_lock(DBusConnection * connection,DBusMessage * message)18882912Sartem device_lock (DBusConnection * connection,
18892912Sartem DBusMessage * message)
18902912Sartem {
18912912Sartem const char *udi;
18922912Sartem HalDevice *d;
18932912Sartem DBusMessage *reply;
18942912Sartem dbus_bool_t already_locked;
18952912Sartem DBusError error;
18962912Sartem char *reason;
18972912Sartem const char *sender;
18982912Sartem
18992912Sartem HAL_TRACE (("entering"));
19002912Sartem
19012912Sartem udi = dbus_message_get_path (message);
19022912Sartem
19032912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
19042912Sartem if (d == NULL)
19052912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
19062912Sartem
19072912Sartem if (d == NULL) {
19082912Sartem raise_no_such_device (connection, message, udi);
19092912Sartem return DBUS_HANDLER_RESULT_HANDLED;
19102912Sartem }
19112912Sartem
19122912Sartem already_locked = hal_device_property_get_bool (d, "info.locked");
19132912Sartem
19142912Sartem if (already_locked) {
19152912Sartem raise_device_already_locked (connection, message, d);
19162912Sartem return DBUS_HANDLER_RESULT_HANDLED;
19172912Sartem }
19182912Sartem
19192912Sartem dbus_error_init (&error);
19202912Sartem if (!dbus_message_get_args (message, &error,
19212912Sartem DBUS_TYPE_STRING, &reason,
19222912Sartem DBUS_TYPE_INVALID)) {
19232912Sartem raise_syntax (connection, message, "Lock");
19242912Sartem return DBUS_HANDLER_RESULT_HANDLED;
19252912Sartem }
19262912Sartem
19272912Sartem reply = dbus_message_new_method_return (message);
19282912Sartem if (reply == NULL)
19292912Sartem DIE (("No memory"));
19302912Sartem
19312912Sartem sender = dbus_message_get_sender (message);
19322912Sartem
19332912Sartem hal_device_property_set_bool (d, "info.locked", TRUE);
19342912Sartem hal_device_property_set_string (d, "info.locked.reason", reason);
19352912Sartem hal_device_property_set_string (d, "info.locked.dbus_name",
19362912Sartem sender);
19372912Sartem
19382912Sartem if (services_with_locks == NULL) {
19392912Sartem services_with_locks =
19402912Sartem g_hash_table_new_full (g_str_hash,
19412912Sartem g_str_equal,
19422912Sartem g_free,
19432912Sartem g_object_unref);
19442912Sartem }
19452912Sartem
19462912Sartem g_hash_table_insert (services_with_locks, g_strdup (sender),
19472912Sartem g_object_ref (d));
19482912Sartem
19492912Sartem if (!dbus_connection_send (connection, reply, NULL))
19502912Sartem DIE (("No memory"));
19512912Sartem
19522912Sartem dbus_message_unref (reply);
19532912Sartem return DBUS_HANDLER_RESULT_HANDLED;
19542912Sartem }
19552912Sartem
19562912Sartem /** Release an advisory lock on a device.
19572912Sartem *
19582912Sartem * <pre>
19592912Sartem * bool Device.Unlock()
19602912Sartem *
19612912Sartem * raises org.freedesktop.Hal.NoSuchDevice,
19622912Sartem * org.freedesktop.Hal.DeviceNotLocked,
19632912Sartem * org.freedesktop.Hal.PermissionDenied
19642912Sartem * </pre>
19652912Sartem *
19662912Sartem * @param connection D-BUS connection
19672912Sartem * @param message Message
19682912Sartem * @return What to do with the message
19692912Sartem */
19702912Sartem DBusHandlerResult
device_unlock(DBusConnection * connection,DBusMessage * message)19712912Sartem device_unlock (DBusConnection * connection,
19722912Sartem DBusMessage * message)
19732912Sartem {
19742912Sartem dbus_bool_t rc;
19752912Sartem const char *udi;
19762912Sartem HalDevice *d;
19772912Sartem DBusMessage *reply;
19782912Sartem DBusError error;
19792912Sartem const char *sender;
19802912Sartem
19812912Sartem HAL_TRACE (("entering"));
19822912Sartem
19832912Sartem udi = dbus_message_get_path (message);
19842912Sartem
19852912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
19862912Sartem if (d == NULL)
19872912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
19882912Sartem
19892912Sartem if (d == NULL) {
19902912Sartem raise_no_such_device (connection, message, udi);
19912912Sartem return DBUS_HANDLER_RESULT_HANDLED;
19922912Sartem }
19932912Sartem
19942912Sartem dbus_error_init (&error);
19952912Sartem if (!dbus_message_get_args (message, &error,
19962912Sartem DBUS_TYPE_INVALID)) {
19972912Sartem raise_syntax (connection, message, "Unlock");
19982912Sartem return DBUS_HANDLER_RESULT_HANDLED;
19992912Sartem }
20002912Sartem
20012912Sartem reply = dbus_message_new_method_return (message);
20022912Sartem if (reply == NULL)
20032912Sartem DIE (("No memory"));
20042912Sartem
20052912Sartem rc = hal_device_property_get_bool (d, "info.locked");
20062912Sartem
20072912Sartem if (!rc) {
20082912Sartem raise_device_not_locked (connection, message, d);
20092912Sartem return DBUS_HANDLER_RESULT_HANDLED;
20102912Sartem }
20112912Sartem
20122912Sartem sender = dbus_message_get_sender (message);
20132912Sartem
20142912Sartem if (strcmp (sender, hal_device_property_get_string (
20152912Sartem d, "info.locked.dbus_name")) != 0) {
20162912Sartem char *reason;
20172912Sartem
20182912Sartem reason = g_strdup_printf ("Service '%s' does not own the "
20192912Sartem "lock on %s", sender,
20202912Sartem hal_device_get_udi (d));
20212912Sartem
20222912Sartem raise_permission_denied (connection, message, reason);
20232912Sartem
20242912Sartem g_free (reason);
20252912Sartem
20262912Sartem return DBUS_HANDLER_RESULT_HANDLED;
20272912Sartem }
20282912Sartem
20292912Sartem if (g_hash_table_lookup (services_with_locks, sender))
20302912Sartem g_hash_table_remove (services_with_locks, sender);
20312912Sartem else {
20322912Sartem HAL_WARNING (("Service '%s' was not in the list of services "
20332912Sartem "with locks!", sender));
20342912Sartem }
20352912Sartem
20362912Sartem hal_device_property_remove (d, "info.locked");
20372912Sartem hal_device_property_remove (d, "info.locked.reason");
20382912Sartem hal_device_property_remove (d, "info.locked.dbus_name");
20392912Sartem
20402912Sartem /* FIXME? Pointless? */
20412912Sartem if (!dbus_connection_send (connection, reply, NULL))
20422912Sartem DIE (("No memory"));
20432912Sartem
20442912Sartem dbus_message_unref (reply);
20452912Sartem return DBUS_HANDLER_RESULT_HANDLED;
20462912Sartem }
20472912Sartem
20482912Sartem static GHashTable *services_with_claims = NULL;
20492912Sartem
20502912Sartem /** Claim a branch.
20512912Sartem *
20522912Sartem * <pre>
20532912Sartem * bool Manager.ClaimBranch(string udi, string claim_service)
20542912Sartem * </pre>
20552912Sartem *
20562912Sartem * @param connection D-BUS connection
20572912Sartem * @param message Message
20582912Sartem * @return What to do with the message
20592912Sartem */
20602912Sartem DBusHandlerResult
manager_claim_branch(DBusConnection * connection,DBusMessage * message)20612912Sartem manager_claim_branch (DBusConnection * connection, DBusMessage * message)
20622912Sartem {
20632912Sartem DBusMessage *reply;
20642912Sartem DBusMessageIter iter;
20652912Sartem DBusError error;
20662912Sartem HalDevice *d;
20672912Sartem const char *udi;
20682912Sartem const char *claim_service;
20692912Sartem const char *sender;
20702912Sartem dbus_bool_t already_claimed;
20712912Sartem unsigned long uid;
20722912Sartem
20732912Sartem dbus_error_init (&error);
20742912Sartem if (!dbus_message_get_args (message, &error,
20752912Sartem DBUS_TYPE_STRING, &udi,
20762912Sartem DBUS_TYPE_STRING, &claim_service,
20772912Sartem DBUS_TYPE_INVALID)) {
20782912Sartem raise_syntax (connection, message, "Manager.ClaimBranch");
20792912Sartem return DBUS_HANDLER_RESULT_HANDLED;
20802912Sartem }
20812912Sartem
20822912Sartem HAL_TRACE (("entering, udi=%s", udi));
20832912Sartem
20842912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
20852912Sartem
20862912Sartem if (d == NULL) {
20872912Sartem raise_no_such_device (connection, message, udi);
20882912Sartem return DBUS_HANDLER_RESULT_HANDLED;
20892912Sartem }
20902912Sartem
20912912Sartem already_claimed = hal_device_property_get_bool (d, "info.claimed");
20922912Sartem if (already_claimed) {
20932912Sartem raise_branch_already_claimed (connection, message, d);
20942912Sartem return DBUS_HANDLER_RESULT_HANDLED;
20952912Sartem }
20962912Sartem
20972912Sartem reply = dbus_message_new_method_return (message);
20982912Sartem if (reply == NULL)
20992912Sartem DIE (("No memory"));
21002912Sartem
21012912Sartem sender = dbus_message_get_sender (message);
21022912Sartem
21032912Sartem dbus_error_init (&error);
21042912Sartem uid = dbus_bus_get_unix_user (connection, sender, &error);
21052912Sartem if (uid == (unsigned long) -1 || dbus_error_is_set (&error)) {
21062912Sartem HAL_WARNING (("Could not get uid for connection: %s %s", error.name, error.message));
21072912Sartem dbus_error_free (&error);
21082912Sartem dbus_message_unref (reply);
21092912Sartem raise_no_such_device (connection, message, udi);
21102912Sartem return DBUS_HANDLER_RESULT_HANDLED;
21112912Sartem }
21122912Sartem
21132912Sartem hal_util_branch_claim (hald_get_gdl (), d, TRUE, claim_service, uid);
21142912Sartem hal_device_property_set_string (d, "info.claimed.dbus_name", sender);
21152912Sartem
21162912Sartem if (services_with_claims == NULL) {
21172912Sartem services_with_claims =
21182912Sartem g_hash_table_new_full (g_str_hash,
21192912Sartem g_str_equal,
21202912Sartem g_free,
21212912Sartem g_object_unref);
21222912Sartem }
21232912Sartem
21242912Sartem g_hash_table_insert (services_with_claims, g_strdup (sender),
21252912Sartem g_object_ref (d));
21262912Sartem
21272912Sartem if (!dbus_connection_send (connection, reply, NULL))
21282912Sartem DIE (("No memory"));
21292912Sartem
21302912Sartem dbus_message_unref (reply);
21312912Sartem return DBUS_HANDLER_RESULT_HANDLED;
21322912Sartem }
21332912Sartem
21342912Sartem /** Unclaim a branch.
21352912Sartem *
21362912Sartem * <pre>
21372912Sartem * bool Manager.UnclaimBranch(string udi)
21382912Sartem * </pre>
21392912Sartem *
21402912Sartem * @param connection D-BUS connection
21412912Sartem * @param message Message
21422912Sartem * @return What to do with the message
21432912Sartem */
21442912Sartem DBusHandlerResult
manager_unclaim_branch(DBusConnection * connection,DBusMessage * message)21452912Sartem manager_unclaim_branch (DBusConnection * connection, DBusMessage * message)
21462912Sartem {
21472912Sartem DBusMessage *reply;
21482912Sartem DBusMessageIter iter;
21492912Sartem DBusError error;
21502912Sartem HalDevice *d;
21512912Sartem const char *udi;
21522912Sartem const char *claim_service;
21532912Sartem const char *sender;
21542912Sartem dbus_bool_t already_claimed;
21552912Sartem
21562912Sartem dbus_error_init (&error);
21572912Sartem if (!dbus_message_get_args (message, &error,
21582912Sartem DBUS_TYPE_STRING, &udi,
21592912Sartem DBUS_TYPE_INVALID)) {
21602912Sartem raise_syntax (connection, message, "Manager.UnclaimBranch");
21612912Sartem return DBUS_HANDLER_RESULT_HANDLED;
21622912Sartem }
21632912Sartem
21642912Sartem HAL_TRACE (("entering, udi=%s", udi));
21652912Sartem
21662912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
21672912Sartem
21682912Sartem if (d == NULL) {
21692912Sartem raise_no_such_device (connection, message, udi);
21702912Sartem return DBUS_HANDLER_RESULT_HANDLED;
21712912Sartem }
21722912Sartem
21732912Sartem already_claimed = hal_device_property_get_bool (d, "info.claimed");
21742912Sartem if (!already_claimed) {
21752912Sartem raise_branch_not_claimed (connection, message, d);
21762912Sartem return DBUS_HANDLER_RESULT_HANDLED;
21772912Sartem }
21782912Sartem
21792912Sartem reply = dbus_message_new_method_return (message);
21802912Sartem if (reply == NULL)
21812912Sartem DIE (("No memory"));
21822912Sartem
21832912Sartem if (strcmp (sender, hal_device_property_get_string (
21842912Sartem d, "info.claimed.dbus_name")) != 0) {
21852912Sartem char *reason;
21862912Sartem
21872912Sartem reason = g_strdup_printf ("Service '%s' does not own the "
21882912Sartem "claim on %s", sender,
21892912Sartem hal_device_get_udi (d));
21902912Sartem
21912912Sartem raise_permission_denied (connection, message, reason);
21922912Sartem
21932912Sartem g_free (reason);
21942912Sartem
21952912Sartem return DBUS_HANDLER_RESULT_HANDLED;
21962912Sartem }
21972912Sartem
21982912Sartem if (g_hash_table_lookup (services_with_claims, sender))
21992912Sartem g_hash_table_remove (services_with_claims, sender);
22002912Sartem else {
22012912Sartem HAL_WARNING (("Service '%s' was not in the list of services "
22022912Sartem "with claims!", sender));
22032912Sartem }
22042912Sartem
22052912Sartem hal_util_branch_claim (hald_get_gdl (), d, FALSE, NULL, 0);
22062912Sartem hal_device_property_remove (d, "info.claimed.dbus_name");
22072912Sartem
22082912Sartem if (!dbus_connection_send (connection, reply, NULL))
22092912Sartem DIE (("No memory"));
22102912Sartem
22112912Sartem dbus_message_unref (reply);
22122912Sartem return DBUS_HANDLER_RESULT_HANDLED;
22132912Sartem }
22142912Sartem
22152912Sartem
22162912Sartem /** Counter for atomic updating */
22172912Sartem static int atomic_count = 0;
22182912Sartem
22192912Sartem /** Number of updates pending */
22202912Sartem static int num_pending_updates = 0;
22212912Sartem
22222912Sartem /** Structure for queing updates */
22232912Sartem typedef struct PendingUpdate_s {
22242912Sartem char *udi; /**< udi of device */
22252912Sartem char *key; /**< key of property; free when done */
22262912Sartem dbus_bool_t removed; /**< true iff property was removed */
22272912Sartem dbus_bool_t added; /**< true iff property was added */
22282912Sartem struct PendingUpdate_s *next; /**< next update or #NULL */
22292912Sartem } PendingUpdate;
22302912Sartem
22312912Sartem static PendingUpdate *pending_updates_head = NULL;
22322912Sartem
22332912Sartem /** Begin an atomic update - this is useful for updating several properties
22342912Sartem * in one go.
22352912Sartem *
22362912Sartem * Note that an atomic update is recursive - use with caution!
22372912Sartem */
22382912Sartem void
device_property_atomic_update_begin(void)22392912Sartem device_property_atomic_update_begin (void)
22402912Sartem {
22412912Sartem atomic_count++;
22422912Sartem }
22432912Sartem
22442912Sartem /** End an atomic update.
22452912Sartem *
22462912Sartem * Note that an atomic update is recursive - use with caution!
22472912Sartem */
22482912Sartem void
device_property_atomic_update_end(void)22492912Sartem device_property_atomic_update_end (void)
22502912Sartem {
22512912Sartem PendingUpdate *pu_iter = NULL;
22522912Sartem PendingUpdate *pu_iter_next = NULL;
22532912Sartem PendingUpdate *pu_iter2 = NULL;
22542912Sartem
22552912Sartem --atomic_count;
22562912Sartem
22572912Sartem if (atomic_count < 0) {
22582912Sartem HAL_WARNING (("*** atomic_count = %d < 0 !!", atomic_count));
22592912Sartem atomic_count = 0;
22602912Sartem }
22612912Sartem
22622912Sartem if (atomic_count == 0 && num_pending_updates > 0) {
22632912Sartem DBusMessage *message;
22642912Sartem DBusMessageIter iter;
22652912Sartem DBusMessageIter iter_array;
22662912Sartem
22672912Sartem for (pu_iter = pending_updates_head;
22682912Sartem pu_iter != NULL; pu_iter = pu_iter_next) {
22692912Sartem int num_updates_this;
22702912Sartem
22712912Sartem pu_iter_next = pu_iter->next;
22722912Sartem
22732912Sartem /* see if we've already processed this */
22742912Sartem if (pu_iter->udi == NULL)
22752912Sartem goto already_processed;
22762912Sartem
22772912Sartem /* count number of updates for this device */
22782912Sartem num_updates_this = 0;
22792912Sartem for (pu_iter2 = pu_iter; pu_iter2 != NULL; pu_iter2 = pu_iter2->next) {
22802912Sartem if (strcmp (pu_iter2->udi, pu_iter->udi) == 0)
22812912Sartem num_updates_this++;
22822912Sartem }
22832912Sartem
22842912Sartem /* prepare message */
22852912Sartem message = dbus_message_new_signal (pu_iter->udi,
22862912Sartem "org.freedesktop.Hal.Device",
22872912Sartem "PropertyModified");
22882912Sartem dbus_message_iter_init_append (message, &iter);
22892912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32,
22902912Sartem &num_updates_this);
22912912Sartem
22922912Sartem dbus_message_iter_open_container (&iter,
22932912Sartem DBUS_TYPE_ARRAY,
22942912Sartem DBUS_STRUCT_BEGIN_CHAR_AS_STRING
22952912Sartem DBUS_TYPE_STRING_AS_STRING
22962912Sartem DBUS_TYPE_BOOLEAN_AS_STRING
22972912Sartem DBUS_TYPE_BOOLEAN_AS_STRING
22982912Sartem DBUS_STRUCT_END_CHAR_AS_STRING,
22992912Sartem &iter_array);
23002912Sartem
23012912Sartem for (pu_iter2 = pu_iter; pu_iter2 != NULL;
23022912Sartem pu_iter2 = pu_iter2->next) {
23032912Sartem if (strcmp (pu_iter2->udi, pu_iter->udi) == 0) {
23042912Sartem DBusMessageIter iter_struct;
23052912Sartem dbus_message_iter_open_container (&iter_array,
23062912Sartem DBUS_TYPE_STRUCT,
23072912Sartem NULL,
23082912Sartem &iter_struct);
23092912Sartem dbus_message_iter_append_basic
23102912Sartem (&iter_struct,
23112912Sartem DBUS_TYPE_STRING,
23122912Sartem &(pu_iter2->key));
23132912Sartem dbus_message_iter_append_basic
23142912Sartem (&iter_struct,
23152912Sartem DBUS_TYPE_BOOLEAN,
23162912Sartem &(pu_iter2->removed));
23172912Sartem dbus_message_iter_append_basic
23182912Sartem (&iter_struct,
23192912Sartem DBUS_TYPE_BOOLEAN,
23202912Sartem &(pu_iter2->added));
23212912Sartem
23222912Sartem dbus_message_iter_close_container (&iter_array, &iter_struct);
23232912Sartem
23242912Sartem /* signal this is already processed */
23252912Sartem g_free (pu_iter2->key);
23262912Sartem if (pu_iter2 != pu_iter) {
23272912Sartem g_free (pu_iter2->udi);
23282912Sartem pu_iter2->udi = NULL;
23292912Sartem }
23302912Sartem }
23312912Sartem }
23322912Sartem
23332912Sartem g_free (pu_iter->udi);
23342912Sartem dbus_message_iter_close_container (&iter, &iter_array);
23352912Sartem
23362912Sartem if (dbus_connection != NULL) {
23372912Sartem if (!dbus_connection_send (dbus_connection, message, NULL))
23382912Sartem DIE (("error broadcasting message"));
23392912Sartem }
23402912Sartem
23412912Sartem dbus_message_unref (message);
23422912Sartem
23432912Sartem already_processed:
23442912Sartem g_free (pu_iter);
23452912Sartem
23462912Sartem } /* for all updates */
23472912Sartem
23482912Sartem num_pending_updates = 0;
23492912Sartem pending_updates_head = NULL;
23502912Sartem }
23512912Sartem }
23522912Sartem
23532912Sartem
23542912Sartem
23552912Sartem void
device_send_signal_property_modified(HalDevice * device,const char * key,dbus_bool_t added,dbus_bool_t removed)23562912Sartem device_send_signal_property_modified (HalDevice *device, const char *key,
23572912Sartem dbus_bool_t added, dbus_bool_t removed)
23582912Sartem {
23592912Sartem const char *udi = hal_device_get_udi (device);
23602912Sartem DBusMessage *message;
23612912Sartem DBusMessageIter iter;
23622912Sartem
23632912Sartem /*
23642912Sartem HAL_INFO(("Entering, udi=%s, key=%s, in_gdl=%s, removed=%s added=%s",
23652912Sartem device->udi, key,
23662912Sartem in_gdl ? "true" : "false",
23672912Sartem removed ? "true" : "false",
23682912Sartem added ? "true" : "false"));
23692912Sartem */
23702912Sartem
23712912Sartem if (atomic_count > 0) {
23722912Sartem PendingUpdate *pu;
23732912Sartem
23742912Sartem pu = g_new0 (PendingUpdate, 1);
23752912Sartem pu->udi = g_strdup (udi);
23762912Sartem pu->key = g_strdup (key);
23772912Sartem pu->removed = removed;
23782912Sartem pu->added = added;
23792912Sartem pu->next = pending_updates_head;
23802912Sartem
23812912Sartem pending_updates_head = pu;
23822912Sartem num_pending_updates++;
23832912Sartem } else {
23842912Sartem dbus_int32_t i;
23852912Sartem DBusMessageIter iter_struct;
23862912Sartem DBusMessageIter iter_array;
23872912Sartem
23882912Sartem if (dbus_connection == NULL)
23892912Sartem goto out;
23902912Sartem
23912912Sartem message = dbus_message_new_signal (udi,
23922912Sartem "org.freedesktop.Hal.Device",
23932912Sartem "PropertyModified");
23942912Sartem
23952912Sartem dbus_message_iter_init_append (message, &iter);
23962912Sartem i = 1;
23972912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &i);
23982912Sartem
23992912Sartem dbus_message_iter_open_container (&iter,
24002912Sartem DBUS_TYPE_ARRAY,
24012912Sartem DBUS_STRUCT_BEGIN_CHAR_AS_STRING
24022912Sartem DBUS_TYPE_STRING_AS_STRING
24032912Sartem DBUS_TYPE_BOOLEAN_AS_STRING
24042912Sartem DBUS_TYPE_BOOLEAN_AS_STRING
24052912Sartem DBUS_STRUCT_END_CHAR_AS_STRING,
24062912Sartem &iter_array);
24072912Sartem
24082912Sartem dbus_message_iter_open_container (&iter_array,
24092912Sartem DBUS_TYPE_STRUCT,
24102912Sartem NULL,
24112912Sartem &iter_struct);
24122912Sartem
24132912Sartem dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_STRING, &key);
24142912Sartem dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &removed);
24152912Sartem dbus_message_iter_append_basic (&iter_struct, DBUS_TYPE_BOOLEAN, &added);
24162912Sartem
24172912Sartem dbus_message_iter_close_container (&iter_array, &iter_struct);
24182912Sartem dbus_message_iter_close_container (&iter, &iter_array);
24192912Sartem
24202912Sartem if (!dbus_connection_send (dbus_connection, message, NULL))
24212912Sartem DIE (("error broadcasting message"));
24222912Sartem
24232912Sartem dbus_message_unref (message);
24242912Sartem }
24252912Sartem out:
24262912Sartem ;
24272912Sartem }
24282912Sartem
24292912Sartem /** Emits a condition on a device; the device has to be in the GDL for
24302912Sartem * this function to have effect.
24312912Sartem *
24322912Sartem * Is intended for non-continuous events on the device like
24332912Sartem * ProcesserOverheating, BlockDeviceGotDevice, e.g. conditions that
24342912Sartem * are exceptional and may not be inferred by looking at properties
24352912Sartem * (though some may).
24362912Sartem *
24372912Sartem * This function accepts a number of parameters that are passed along
24382912Sartem * in the D-BUS message. The recipient is supposed to extract the parameters
24392912Sartem * himself, by looking at the HAL specification.
24402912Sartem *
24412912Sartem * @param udi The UDI for this device
24422912Sartem * @param condition_name Name of condition
24432912Sartem * @param first_arg_type Type of the first argument
24442912Sartem * @param ... value of first argument, list of additional
24452912Sartem * type-value pairs. Must be terminated with
24462912Sartem * DBUS_TYPE_INVALID
24472912Sartem */
24482912Sartem void
device_send_signal_condition(HalDevice * device,const char * condition_name,const char * condition_details)24492912Sartem device_send_signal_condition (HalDevice *device, const char *condition_name, const char *condition_details)
24502912Sartem {
24512912Sartem const char *udi = hal_device_get_udi (device);
24522912Sartem DBusMessage *message;
24532912Sartem DBusMessageIter iter;
24542912Sartem
24552912Sartem if (dbus_connection == NULL)
24562912Sartem goto out;
24572912Sartem
24582912Sartem message = dbus_message_new_signal (udi,
24592912Sartem "org.freedesktop.Hal.Device",
24602912Sartem "Condition");
24612912Sartem dbus_message_iter_init_append (message, &iter);
24622912Sartem dbus_message_iter_append_basic (&iter,
24632912Sartem DBUS_TYPE_STRING,
24642912Sartem &condition_name);
24652912Sartem dbus_message_iter_append_basic (&iter,
24662912Sartem DBUS_TYPE_STRING,
24672912Sartem &condition_details);
24682912Sartem
24692912Sartem if (!dbus_connection_send (dbus_connection, message, NULL))
24702912Sartem DIE (("error broadcasting message"));
24712912Sartem
24722912Sartem dbus_message_unref (message);
24732912Sartem out:
24742912Sartem return;
24752912Sartem }
24762912Sartem
24772912Sartem
24782912Sartem
24792912Sartem static gboolean
reinit_dbus(gpointer user_data)24802912Sartem reinit_dbus (gpointer user_data)
24812912Sartem {
24822912Sartem HAL_INFO (("entering!"));
24832912Sartem if (hald_dbus_init ())
24842912Sartem return FALSE;
24852912Sartem else
24862912Sartem return TRUE;
24872912Sartem }
24882912Sartem
24892912Sartem static void
service_deleted(DBusMessage * message)24902912Sartem service_deleted (DBusMessage *message)
24912912Sartem {
24922912Sartem char *old_service_name;
24932912Sartem char *new_service_name;
24942912Sartem HalDevice *d;
24952912Sartem
24962912Sartem if (!dbus_message_get_args (message, NULL,
24972912Sartem DBUS_TYPE_STRING, &old_service_name,
24982912Sartem DBUS_TYPE_STRING, &new_service_name,
24992912Sartem DBUS_TYPE_INVALID)) {
25002912Sartem HAL_ERROR (("Invalid NameOwnerChanged signal from bus!"));
25012912Sartem return;
25022912Sartem }
25032912Sartem
25042912Sartem if (services_with_locks != NULL) {
25052912Sartem d = g_hash_table_lookup (services_with_locks, new_service_name);
25062912Sartem
25072912Sartem if (d != NULL) {
25082912Sartem hal_device_property_remove (d, "info.locked");
25092912Sartem hal_device_property_remove (d, "info.locked.reason");
25102912Sartem hal_device_property_remove (d, "info.locked.dbus_name");
25112912Sartem
25122912Sartem g_hash_table_remove (services_with_locks, new_service_name);
25132912Sartem }
25142912Sartem }
25152912Sartem
25162912Sartem if (services_with_claims != NULL) {
25172912Sartem d = g_hash_table_lookup (services_with_claims, new_service_name);
25182912Sartem
25192912Sartem if (d != NULL) {
25202912Sartem hal_util_branch_claim (hald_get_gdl (), d, FALSE, NULL, 0);
25212912Sartem hal_device_property_remove (d, "info.claimed.dbus_name");
25222912Sartem
25232912Sartem g_hash_table_remove (services_with_claims, new_service_name);
25242912Sartem }
25252912Sartem }
25262912Sartem }
25272912Sartem
25282912Sartem static DBusHandlerResult
device_rescan(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)25292912Sartem device_rescan (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
25302912Sartem {
25312912Sartem const char *udi;
25322912Sartem HalDevice *device;
25332912Sartem DBusMessage *reply;
25342912Sartem DBusMessageIter iter;
25352912Sartem gboolean res;
25362912Sartem
25372912Sartem HAL_INFO (("entering, local_interface=%d", local_interface));
25382912Sartem
25392912Sartem udi = dbus_message_get_path (message);
25402912Sartem
25412912Sartem if (!local_interface && !sender_has_privileges (connection, message)) {
25422912Sartem raise_permission_denied (connection, message, "Rescan: not privileged");
25432912Sartem return DBUS_HANDLER_RESULT_HANDLED;
25442912Sartem }
25452912Sartem
25462912Sartem HAL_DEBUG (("udi=%s", udi));
25472912Sartem
25482912Sartem device = hal_device_store_find (hald_get_gdl (), udi);
25492912Sartem if (device == NULL)
25502912Sartem device = hal_device_store_find (hald_get_tdl (), udi);
25512912Sartem
25522912Sartem if (device == NULL) {
25532912Sartem raise_no_such_device (connection, message, udi);
25542912Sartem return DBUS_HANDLER_RESULT_HANDLED;
25552912Sartem }
25562912Sartem
25572912Sartem res = osspec_device_rescan (device);
25582912Sartem
25592912Sartem reply = dbus_message_new_method_return (message);
25602912Sartem if (reply == NULL)
25612912Sartem DIE (("No memory"));
25622912Sartem dbus_message_iter_init_append (reply, &iter);
25632912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
25642912Sartem
25652912Sartem if (!dbus_connection_send (connection, reply, NULL))
25662912Sartem DIE (("No memory"));
25672912Sartem
25682912Sartem dbus_message_unref (reply);
25692912Sartem return DBUS_HANDLER_RESULT_HANDLED;
25702912Sartem }
25712912Sartem
25722912Sartem static DBusHandlerResult
device_reprobe(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)25732912Sartem device_reprobe (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
25742912Sartem {
25752912Sartem const char *udi;
25762912Sartem HalDevice *device;
25772912Sartem DBusMessageIter iter;
25782912Sartem DBusMessage *reply;
25792912Sartem gboolean res;
25802912Sartem
25812912Sartem HAL_TRACE (("entering"));
25822912Sartem
25832912Sartem udi = dbus_message_get_path (message);
25842912Sartem
25852912Sartem if (!local_interface && !sender_has_privileges (connection, message)) {
25862912Sartem raise_permission_denied (connection, message, "Reprobe: not privileged");
25872912Sartem return DBUS_HANDLER_RESULT_HANDLED;
25882912Sartem }
25892912Sartem
25902912Sartem HAL_DEBUG (("udi=%s", udi));
25912912Sartem
25922912Sartem device = hal_device_store_find (hald_get_gdl (), udi);
25932912Sartem if (device == NULL)
25942912Sartem device = hal_device_store_find (hald_get_tdl (), udi);
25952912Sartem
25962912Sartem if (device == NULL) {
25972912Sartem raise_no_such_device (connection, message, udi);
25982912Sartem return DBUS_HANDLER_RESULT_HANDLED;
25992912Sartem }
26002912Sartem
26012912Sartem res = osspec_device_reprobe (device);
26022912Sartem
26032912Sartem reply = dbus_message_new_method_return (message);
26042912Sartem if (reply == NULL)
26052912Sartem DIE (("No memory"));
26062912Sartem dbus_message_iter_init_append (reply, &iter);
26072912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
26082912Sartem
26092912Sartem if (!dbus_connection_send (connection, reply, NULL))
26102912Sartem DIE (("No memory"));
26112912Sartem
26122912Sartem dbus_message_unref (reply);
26132912Sartem return DBUS_HANDLER_RESULT_HANDLED;
26142912Sartem }
26152912Sartem
26162912Sartem
26172912Sartem static DBusHandlerResult
device_emit_condition(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)26182912Sartem device_emit_condition (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
26192912Sartem {
26202912Sartem const char *udi;
26212912Sartem HalDevice *device;
26222912Sartem DBusMessageIter iter;
26232912Sartem DBusMessage *reply;
26242912Sartem DBusError error;
26252912Sartem const char *condition_name;
26262912Sartem const char *condition_details;
26272912Sartem dbus_bool_t res;
26282912Sartem
26292912Sartem HAL_TRACE (("entering"));
26302912Sartem
26312912Sartem udi = dbus_message_get_path (message);
26322912Sartem
26332912Sartem if (!local_interface) {
26342912Sartem raise_permission_denied (connection, message, "EmitCondition: only allowed for helpers");
26352912Sartem return DBUS_HANDLER_RESULT_HANDLED;
26362912Sartem }
26372912Sartem
26382912Sartem HAL_DEBUG (("udi=%s", udi));
26392912Sartem
26402912Sartem dbus_error_init (&error);
26412912Sartem if (!dbus_message_get_args (message, &error,
26422912Sartem DBUS_TYPE_STRING, &condition_name,
26432912Sartem DBUS_TYPE_STRING, &condition_details,
26442912Sartem DBUS_TYPE_INVALID)) {
26452912Sartem raise_syntax (connection, message, "EmitCondition");
26462912Sartem return DBUS_HANDLER_RESULT_HANDLED;
26472912Sartem }
26482912Sartem
26492912Sartem
26502912Sartem device = hal_device_store_find (hald_get_gdl (), udi);
26512912Sartem if (device == NULL)
26522912Sartem device = hal_device_store_find (hald_get_tdl (), udi);
26532912Sartem
26542912Sartem if (device == NULL) {
26552912Sartem raise_no_such_device (connection, message, udi);
26562912Sartem return DBUS_HANDLER_RESULT_HANDLED;
26572912Sartem }
26582912Sartem
26592912Sartem device_send_signal_condition (device, condition_name, condition_details);
26602912Sartem
26612912Sartem res = TRUE;
26622912Sartem
26632912Sartem reply = dbus_message_new_method_return (message);
26642912Sartem if (reply == NULL)
26652912Sartem DIE (("No memory"));
26662912Sartem dbus_message_iter_init_append (reply, &iter);
26672912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
26682912Sartem
26692912Sartem if (!dbus_connection_send (connection, reply, NULL))
26702912Sartem DIE (("No memory"));
26712912Sartem
26722912Sartem dbus_message_unref (reply);
26732912Sartem return DBUS_HANDLER_RESULT_HANDLED;
26742912Sartem }
26752912Sartem
26762912Sartem typedef struct
26772912Sartem {
26782912Sartem DBusConnection *connection;
26792912Sartem char *interface_name;
26802912Sartem char *introspection_xml;
26812912Sartem char *udi;
26822912Sartem } HelperInterfaceHandler;
26832912Sartem
26842912Sartem static GSList *helper_interface_handlers = NULL;
26852912Sartem
26862912Sartem static DBusHandlerResult
device_claim_interface(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)26872912Sartem device_claim_interface (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
26882912Sartem {
26892912Sartem const char *udi;
26902912Sartem HalDevice *device;
26912912Sartem DBusMessageIter iter;
26922912Sartem DBusMessage *reply;
26932912Sartem DBusError error;
26942912Sartem const char *interface_name;
26952912Sartem const char *introspection_xml;
26962912Sartem dbus_bool_t res;
26972912Sartem
26982912Sartem HAL_TRACE (("entering"));
26992912Sartem
27002912Sartem udi = dbus_message_get_path (message);
27012912Sartem
27022912Sartem if (!local_interface) {
27032912Sartem raise_permission_denied (connection, message, "ClaimInterface: only allowed for helpers");
27042912Sartem return DBUS_HANDLER_RESULT_HANDLED;
27052912Sartem }
27062912Sartem
27072912Sartem HAL_DEBUG (("udi=%s", udi));
27082912Sartem
27092912Sartem dbus_error_init (&error);
27102912Sartem if (!dbus_message_get_args (message, &error,
27112912Sartem DBUS_TYPE_STRING, &interface_name,
27122912Sartem DBUS_TYPE_STRING, &introspection_xml,
27132912Sartem DBUS_TYPE_INVALID)) {
27142912Sartem raise_syntax (connection, message, "ClaimInterface");
27152912Sartem return DBUS_HANDLER_RESULT_HANDLED;
27162912Sartem }
27172912Sartem
27182912Sartem device = hal_device_store_find (hald_get_gdl (), udi);
27192912Sartem if (device == NULL)
27202912Sartem device = hal_device_store_find (hald_get_tdl (), udi);
27212912Sartem
27222912Sartem if (device == NULL) {
27232912Sartem raise_no_such_device (connection, message, udi);
27242912Sartem return DBUS_HANDLER_RESULT_HANDLED;
27252912Sartem }
27262912Sartem
27272912Sartem res = TRUE;
27282912Sartem
27292912Sartem HAL_INFO (("Local connection 0x%x to handle interface '%s' on udi '%s'",
27302912Sartem connection,
27312912Sartem interface_name,
27322912Sartem udi));
27332912Sartem
27342912Sartem hal_device_property_strlist_add (device, "info.interfaces", interface_name);
27352912Sartem
27362912Sartem HelperInterfaceHandler *hih = g_new0 (HelperInterfaceHandler, 1);
27372912Sartem hih->connection = connection;
27382912Sartem hih->interface_name = g_strdup (interface_name);
27392912Sartem hih->introspection_xml = g_strdup (introspection_xml);
27402912Sartem hih->udi = g_strdup (udi);
27412912Sartem helper_interface_handlers = g_slist_append (helper_interface_handlers, hih);
27422912Sartem
27432912Sartem
27442912Sartem reply = dbus_message_new_method_return (message);
27452912Sartem if (reply == NULL)
27462912Sartem DIE (("No memory"));
27472912Sartem dbus_message_iter_init_append (reply, &iter);
27482912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
27492912Sartem
27502912Sartem if (!dbus_connection_send (connection, reply, NULL))
27512912Sartem DIE (("No memory"));
27522912Sartem
27532912Sartem dbus_message_unref (reply);
27542912Sartem return DBUS_HANDLER_RESULT_HANDLED;
27552912Sartem }
27562912Sartem
27572912Sartem
27582912Sartem
27592912Sartem static DBusHandlerResult
addon_is_ready(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)27602912Sartem addon_is_ready (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
27612912Sartem {
27622912Sartem const char *udi;
27632912Sartem HalDevice *device;
27642912Sartem DBusMessageIter iter;
27652912Sartem DBusMessage *reply;
27662912Sartem DBusError error;
27672912Sartem dbus_bool_t res;
27682912Sartem
27692912Sartem HAL_TRACE (("entering"));
27702912Sartem
27712912Sartem udi = dbus_message_get_path (message);
27722912Sartem
27732912Sartem if (!local_interface) {
27742912Sartem raise_permission_denied (connection, message, "AddonIsReady: only allowed for helpers");
27752912Sartem return DBUS_HANDLER_RESULT_HANDLED;
27762912Sartem }
27772912Sartem
27782912Sartem HAL_DEBUG (("udi=%s", udi));
27792912Sartem
27802912Sartem dbus_error_init (&error);
27812912Sartem if (!dbus_message_get_args (message, &error,
27822912Sartem DBUS_TYPE_INVALID)) {
27832912Sartem raise_syntax (connection, message, "AddonIsReady");
27842912Sartem return DBUS_HANDLER_RESULT_HANDLED;
27852912Sartem }
27862912Sartem
27872912Sartem device = hal_device_store_find (hald_get_gdl (), udi);
27882912Sartem if (device == NULL)
27892912Sartem device = hal_device_store_find (hald_get_tdl (), udi);
27902912Sartem
27912912Sartem if (device == NULL) {
27922912Sartem raise_no_such_device (connection, message, udi);
27932912Sartem return DBUS_HANDLER_RESULT_HANDLED;
27942912Sartem }
27952912Sartem
27962912Sartem if (hal_device_inc_num_ready_addons (device)) {
27972912Sartem if (hal_device_are_all_addons_ready (device)) {
27982912Sartem manager_send_signal_device_added (device);
27992912Sartem }
28002912Sartem }
28012912Sartem
28022912Sartem res = TRUE;
28032912Sartem
28042912Sartem HAL_INFO (("AddonIsReady on udi '%s'", udi));
28052912Sartem
28062912Sartem reply = dbus_message_new_method_return (message);
28072912Sartem if (reply == NULL)
28082912Sartem DIE (("No memory"));
28092912Sartem dbus_message_iter_init_append (reply, &iter);
28102912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &res);
28112912Sartem
28122912Sartem if (!dbus_connection_send (connection, reply, NULL))
28132912Sartem DIE (("No memory"));
28142912Sartem
28152912Sartem dbus_message_unref (reply);
28162912Sartem return DBUS_HANDLER_RESULT_HANDLED;
28172912Sartem }
28182912Sartem
28192912Sartem
28202912Sartem /*
28212912Sartem * Create new device in tdl. Return temporary udi.
28222912Sartem */
28232912Sartem DBusHandlerResult
manager_new_device(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)28242912Sartem manager_new_device (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
28252912Sartem {
28262912Sartem DBusMessage *reply;
28272912Sartem DBusMessageIter iter;
28282912Sartem DBusError error;
28292912Sartem HalDevice *d;
28302912Sartem gchar *udi;
28312912Sartem int i;
28322912Sartem struct timeval tv;
28332912Sartem
28342912Sartem dbus_error_init (&error);
28352912Sartem
28362912Sartem if (!local_interface && !sender_has_privileges (connection, message)) {
28372912Sartem raise_permission_denied (connection, message, "NewDevice: not privileged");
28382912Sartem return DBUS_HANDLER_RESULT_HANDLED;
28392912Sartem }
28402912Sartem
28412912Sartem reply = dbus_message_new_method_return (message);
28422912Sartem if (reply == NULL)
28432912Sartem DIE (("No memory"));
28442912Sartem
28452912Sartem dbus_message_iter_init_append (reply, &iter);
28462912Sartem d = hal_device_new ();
28472912Sartem
28482912Sartem gettimeofday(&tv, NULL);
28492912Sartem for (i = 0; i < 1000000 ; i++) {
28502912Sartem udi = g_strdup_printf ("/org/freedesktop/Hal/devices/tmp%05x", ((unsigned) tv.tv_usec & 0xfffff)) + i;
28512912Sartem if (!hal_device_store_find (hald_get_tdl (), udi)) break;
28522912Sartem g_free (udi);
28532912Sartem udi = NULL;
28542912Sartem }
28552912Sartem
28562912Sartem if (!udi) {
28572912Sartem raise_error (connection, message, "org.freedesktop.Hal.NoSpace", "NewDevice: no space for device");
28582912Sartem return DBUS_HANDLER_RESULT_HANDLED;
28592912Sartem }
28602912Sartem
28612912Sartem hal_device_set_udi (d, udi);
28622912Sartem hal_device_property_set_string (d, "info.udi", udi);
28632912Sartem hal_device_store_add (hald_get_tdl (), d);
28642912Sartem dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
28652912Sartem g_free (udi);
28662912Sartem
28672912Sartem if (!dbus_connection_send (connection, reply, NULL))
28682912Sartem DIE (("No memory"));
28692912Sartem
28702912Sartem dbus_message_unref (reply);
28712912Sartem
28722912Sartem return DBUS_HANDLER_RESULT_HANDLED;
28732912Sartem }
28742912Sartem
28752912Sartem
28762912Sartem /*
28772912Sartem * Callout helper.
28782912Sartem */
28792912Sartem static void
manager_remove_done(HalDevice * d,gpointer userdata1,gpointer userdata2)28802912Sartem manager_remove_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
28812912Sartem {
28822912Sartem HAL_INFO (("Remove callouts completed udi=%s", d->udi));
28832912Sartem
28842912Sartem if (!hal_device_store_remove (hald_get_gdl (), d)) {
28852912Sartem HAL_WARNING (("Error removing device"));
28862912Sartem }
28872912Sartem }
28882912Sartem
28892912Sartem
28902912Sartem /*
28912912Sartem * Remove device. Looks in gdl and tdl.
28922912Sartem */
28932912Sartem DBusHandlerResult
manager_remove(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)28942912Sartem manager_remove (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
28952912Sartem {
28962912Sartem DBusMessage *reply;
28972912Sartem DBusMessageIter iter;
28982912Sartem DBusError error;
28992912Sartem HalDevice *d;
29002912Sartem char *udi;
29012912Sartem int in_tdl = 0;
29022912Sartem
29032912Sartem dbus_error_init (&error);
29042912Sartem
29052912Sartem if (!local_interface && !sender_has_privileges (connection, message)) {
29062912Sartem raise_permission_denied (connection, message, "Remove: not privileged");
29072912Sartem return DBUS_HANDLER_RESULT_HANDLED;
29082912Sartem }
29092912Sartem
29102912Sartem if (!dbus_message_get_args (message, &error,
29112912Sartem DBUS_TYPE_STRING, &udi,
29122912Sartem DBUS_TYPE_INVALID)) {
29132912Sartem raise_syntax (connection, message, "Remove");
29142912Sartem return DBUS_HANDLER_RESULT_HANDLED;
29152912Sartem }
29162912Sartem
29172912Sartem reply = dbus_message_new_method_return (message);
29182912Sartem if (reply == NULL)
29192912Sartem DIE (("No memory"));
29202912Sartem
29212912Sartem dbus_message_iter_init_append (reply, &iter);
29222912Sartem
29232912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
29242912Sartem if (d == NULL) {
29252912Sartem hal_device_store_find (hald_get_tdl (), udi);
29262912Sartem in_tdl = 1;
29272912Sartem }
29282912Sartem if (d == NULL) {
29292912Sartem raise_no_such_device (connection, message, udi);
29302912Sartem return DBUS_HANDLER_RESULT_HANDLED;
29312912Sartem }
29322912Sartem
29332912Sartem /* FIXME:
29342912Sartem * run "info.callouts.remove" ?
29352912Sartem * delete in gdl ?
29362912Sartem * (auto) stop "info.addons" ?
29372912Sartem */
29382912Sartem
29392912Sartem if (!in_tdl) {
29402912Sartem hal_util_callout_device_remove (d, manager_remove_done, NULL, NULL);
29412912Sartem }
29422912Sartem
29432912Sartem hal_device_store_remove (in_tdl ? hald_get_tdl () : hald_get_gdl (), d);
29442912Sartem g_object_unref (d);
29452912Sartem
29462912Sartem if (!dbus_connection_send (connection, reply, NULL))
29472912Sartem DIE (("No memory"));
29482912Sartem
29492912Sartem dbus_message_unref (reply);
29502912Sartem
29512912Sartem return DBUS_HANDLER_RESULT_HANDLED;
29522912Sartem }
29532912Sartem
29542912Sartem
29552912Sartem /*
29562912Sartem * Callout helper.
29572912Sartem */
29582912Sartem static void
manager_commit_done(HalDevice * d,gpointer userdata1,gpointer userdata2)29592912Sartem manager_commit_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
29602912Sartem {
29612912Sartem HAL_INFO (("Add callouts completed udi=%s", d->udi));
29622912Sartem }
29632912Sartem
29642912Sartem /*
29652912Sartem * Preprobing helper.
29662912Sartem */
29672912Sartem static void
manager_commit_preprobing_done(HalDevice * d,gpointer userdata1,gpointer userdata2)29682912Sartem manager_commit_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
29692912Sartem {
29702912Sartem if (hal_device_property_get_bool (d, "info.ignore")) {
29712912Sartem /* Leave the device here with info.ignore==TRUE so we won't pick up children
29722912Sartem * Also remove category and all capabilities
29732912Sartem */
29742912Sartem hal_device_property_remove (d, "info.category");
29752912Sartem hal_device_property_remove (d, "info.capabilities");
29762912Sartem hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
29772912Sartem hal_device_property_set_string (d, "info.product", "Ignored Device");
29782912Sartem
29792912Sartem HAL_INFO (("Preprobing merged info.ignore==TRUE"));
29802912Sartem
29812912Sartem return;
29822912Sartem }
29832912Sartem
29842912Sartem /* Merge properties from .fdi files */
29852912Sartem di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
29862912Sartem di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
29872912Sartem
29882912Sartem hal_util_callout_device_add (d, manager_commit_done, NULL, NULL);
29892912Sartem }
29902912Sartem
29912912Sartem
29922912Sartem /*
29932912Sartem * Move device from tdl to gdl. Runs helpers and callouts.
29942912Sartem */
29952912Sartem DBusHandlerResult
manager_commit_to_gdl(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)29962912Sartem manager_commit_to_gdl (DBusConnection * connection, DBusMessage * message, dbus_bool_t local_interface)
29972912Sartem {
29982912Sartem DBusMessage *reply;
29992912Sartem DBusMessageIter iter;
30002912Sartem DBusError error;
30012912Sartem HalDevice *d;
30022912Sartem char udi[256], *udi0, *tmp_udi;
30032912Sartem
30042912Sartem dbus_error_init (&error);
30052912Sartem
30062912Sartem if (!local_interface && !sender_has_privileges (connection, message)) {
30072912Sartem raise_permission_denied (connection, message, "CommitToGdl: not privileged");
30082912Sartem return DBUS_HANDLER_RESULT_HANDLED;
30092912Sartem }
30102912Sartem
30112912Sartem if (!dbus_message_get_args (message, &error,
30122912Sartem DBUS_TYPE_STRING, &tmp_udi,
30132912Sartem DBUS_TYPE_STRING, &udi0,
30142912Sartem DBUS_TYPE_INVALID)) {
30152912Sartem raise_syntax (connection, message, "CommitToGdl");
30162912Sartem return DBUS_HANDLER_RESULT_HANDLED;
30172912Sartem }
30182912Sartem
30192912Sartem reply = dbus_message_new_method_return (message);
30202912Sartem if (reply == NULL)
30212912Sartem DIE (("No memory"));
30222912Sartem
30232912Sartem dbus_message_iter_init_append (reply, &iter);
30242912Sartem
30252912Sartem /* look it up in tdl */
30262912Sartem
30272912Sartem d = hal_device_store_find (hald_get_tdl (), tmp_udi);
30282912Sartem if (d == NULL) {
30292912Sartem raise_no_such_device (connection, message, tmp_udi);
30302912Sartem return DBUS_HANDLER_RESULT_HANDLED;
30312912Sartem }
30322912Sartem
30332912Sartem /* sanity check & avoid races */
30342912Sartem hal_util_compute_udi (hald_get_gdl (), udi, sizeof udi, "%s", udi0);
30352912Sartem
30362912Sartem if (hal_device_store_find (hald_get_gdl (), udi)) {
30372912Sartem /* loose it */
30382912Sartem hal_device_store_remove (hald_get_tdl (), d);
30392912Sartem g_object_unref (d);
30402912Sartem raise_error (connection, message, "org.freedesktop.Hal.DeviceExists", "CommitToGdl: Device exists: %s", udi);
30412912Sartem return DBUS_HANDLER_RESULT_HANDLED;
30422912Sartem }
30432912Sartem
30442912Sartem /* set new udi */
30452912Sartem hal_device_property_remove (d, "info.udi");
30462912Sartem hal_device_set_udi (d, udi);
30472912Sartem hal_device_property_set_string (d, "info.udi", udi);
30482912Sartem
30492912Sartem /* FIXME:
30502912Sartem * 'RequireEnable' property?
30512912Sartem * fdi "preprobe"?
30522912Sartem * run "info.callouts.preprobe"?
30532912Sartem * remove "info.ignore" devices?
30542912Sartem * fdi "information"?
30552912Sartem * fdi "policy"?
30562912Sartem * run "info.callouts.add"?
30572912Sartem * tdl -> gdl?
30582912Sartem * (auto) start "info.addons"?
30592912Sartem */
30602912Sartem
30612912Sartem /* Process preprobe fdi files */
30622912Sartem di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
30632912Sartem hal_util_callout_device_preprobe (d, manager_commit_preprobing_done, NULL, NULL);
30642912Sartem
30652912Sartem /* move from tdl to gdl */
30662912Sartem hal_device_store_remove (hald_get_tdl (), d);
30672912Sartem hal_device_store_add (hald_get_gdl (), d);
30682912Sartem
30692912Sartem if (!dbus_connection_send (connection, reply, NULL))
30702912Sartem DIE (("No memory"));
30712912Sartem
30722912Sartem dbus_message_unref (reply);
30732912Sartem
30742912Sartem return DBUS_HANDLER_RESULT_HANDLED;
30752912Sartem }
30762912Sartem
30772912Sartem typedef struct {
30782912Sartem char *udi;
30792912Sartem char *execpath;
30802912Sartem char **extra_env;
30812912Sartem char *mstdin;
30822912Sartem char *member;
30832912Sartem char *interface;
30842912Sartem DBusMessage *message;
30852912Sartem DBusConnection *connection;
30862912Sartem } MethodInvocation;
30872912Sartem
30882912Sartem static void
30892912Sartem hald_exec_method_cb (HalDevice *d, guint32 exit_type,
30902912Sartem gint return_code, gchar **error,
30912912Sartem gpointer data1, gpointer data2);
30922912Sartem
30932912Sartem
30942912Sartem static void
hald_exec_method_free_mi(MethodInvocation * mi)30952912Sartem hald_exec_method_free_mi (MethodInvocation *mi)
30962912Sartem {
30972912Sartem /* hald_runner_run_method() assumes ownership of mi->message.. so we don't free it here */
30982912Sartem g_free (mi->udi);
30992912Sartem g_free (mi->execpath);
31002912Sartem g_strfreev (mi->extra_env);
31012912Sartem g_free (mi->mstdin);
31022912Sartem g_free (mi->member);
31032912Sartem g_free (mi->interface);
31042912Sartem g_free (mi);
31052912Sartem }
31062912Sartem
31072912Sartem /* returns FALSE if we don't actually invoke anything */
31082912Sartem static gboolean
hald_exec_method_do_invocation(MethodInvocation * mi)31092912Sartem hald_exec_method_do_invocation (MethodInvocation *mi)
31102912Sartem {
31112912Sartem gboolean ret;
31122912Sartem HalDevice *d;
31132912Sartem
31142912Sartem ret = FALSE;
31152912Sartem
31162912Sartem d = hal_device_store_find (hald_get_gdl (), mi->udi);
31172912Sartem if (d == NULL)
31182912Sartem d = hal_device_store_find (hald_get_tdl (), mi->udi);
31192912Sartem
31202912Sartem if (d != NULL) {
31212912Sartem /* no timeout */
31222912Sartem hald_runner_run_method(d,
31232912Sartem mi->execpath,
31242912Sartem mi->extra_env,
31252912Sartem mi->mstdin,
31262912Sartem TRUE,
31272912Sartem 0,
31282912Sartem hald_exec_method_cb,
31292912Sartem (gpointer) mi->message,
31302912Sartem (gpointer) mi->connection);
31312912Sartem
31322912Sartem ret = TRUE;
31332912Sartem } else {
31342912Sartem HAL_WARNING (("In-queue method call on non-existant device"));
31352912Sartem
31362912Sartem raise_no_such_device (mi->connection, mi->message, mi->udi);
31372912Sartem }
31382912Sartem
31392912Sartem return ret;
31402912Sartem }
31412912Sartem
31422912Sartem
31432912Sartem static GHashTable *udi_to_method_queue = NULL;
31442912Sartem
31452912Sartem
31462912Sartem gboolean
device_is_executing_method(HalDevice * d,const char * interface_name,const char * method_name)31472912Sartem device_is_executing_method (HalDevice *d, const char *interface_name, const char *method_name)
31482912Sartem {
31492912Sartem gpointer origkey;
31502912Sartem gboolean ret;
31512912Sartem GList *queue;
31522912Sartem
31532912Sartem ret = FALSE;
31542912Sartem
31552912Sartem if (g_hash_table_lookup_extended (udi_to_method_queue, d->udi, &origkey, (gpointer) &queue)) {
31562912Sartem
31572912Sartem if (queue != NULL) {
31582912Sartem MethodInvocation *mi;
31592912Sartem mi = (MethodInvocation *) queue->data;
31602912Sartem if ((strcmp (mi->interface, interface_name) == 0) &&
31612912Sartem (strcmp (mi->member, method_name) == 0)) {
31622912Sartem ret = TRUE;
31632912Sartem }
31642912Sartem }
31652912Sartem
31662912Sartem ret = TRUE;
31672912Sartem }
31682912Sartem return ret;
31692912Sartem }
31702912Sartem
31712912Sartem static void
31722912Sartem hald_exec_method_process_queue (const char *udi);
31732912Sartem
31742912Sartem static void
hald_exec_method_enqueue(MethodInvocation * mi)31752912Sartem hald_exec_method_enqueue (MethodInvocation *mi)
31762912Sartem {
31772912Sartem gpointer origkey;
31782912Sartem GList *queue;
31792912Sartem
31802912Sartem if (udi_to_method_queue == NULL) {
31812912Sartem udi_to_method_queue = g_hash_table_new_full (g_str_hash,
31822912Sartem g_str_equal,
31832912Sartem g_free,
31842912Sartem NULL);
31852912Sartem }
31862912Sartem
31872912Sartem if (g_hash_table_lookup_extended (udi_to_method_queue, mi->udi, &origkey, (gpointer) &queue)) {
31882912Sartem HAL_INFO (("enqueue"));
31892912Sartem queue = g_list_append (queue, mi);
31902912Sartem g_hash_table_replace (udi_to_method_queue, g_strdup (mi->udi), queue);
31912912Sartem } else {
31922912Sartem HAL_INFO (("no need to enqueue"));
31932912Sartem queue = g_list_append (NULL, mi);
31942912Sartem g_hash_table_insert (udi_to_method_queue, g_strdup (mi->udi), queue);
31952912Sartem
31962912Sartem hald_exec_method_do_invocation (mi);
31972912Sartem }
31982912Sartem }
31992912Sartem
32002912Sartem
32012912Sartem static void
hald_exec_method_process_queue(const char * udi)32022912Sartem hald_exec_method_process_queue (const char *udi)
32032912Sartem {
32042912Sartem gpointer origkey;
32052912Sartem GList *queue;
32062912Sartem MethodInvocation *mi;
32072912Sartem
32082912Sartem if (g_hash_table_lookup_extended (udi_to_method_queue, udi, &origkey, (gpointer) &queue)) {
32092912Sartem
32102912Sartem /* clean the top of the list */
32112912Sartem if (queue != NULL) {
32122912Sartem mi = (MethodInvocation *) queue->data;
32132912Sartem queue = g_list_delete_link (queue, queue);
32142912Sartem if (queue == NULL) {
32152912Sartem g_hash_table_remove (udi_to_method_queue, udi);
32162912Sartem HAL_INFO (("No more methods in queue"));
32172912Sartem }
32182912Sartem
32192912Sartem /* if method was Volume.Unmount() then refresh mount state */
32202912Sartem if (strcmp (mi->interface, "org.freedesktop.Hal.Device.Volume") == 0 &&
32212912Sartem strcmp (mi->member, "Unmount") == 0) {
32222912Sartem HalDevice *d;
32232912Sartem
32242912Sartem HAL_INFO (("Refreshing mount state for %s since Unmount() completed", mi->udi));
32252912Sartem
32262912Sartem d = hal_device_store_find (hald_get_gdl (), mi->udi);
32272912Sartem if (d == NULL) {
32282912Sartem d = hal_device_store_find (hald_get_tdl (), mi->udi);
32292912Sartem }
32302912Sartem
32312912Sartem if (d != NULL) {
32322912Sartem osspec_refresh_mount_state_for_block_device (d);
32332912Sartem } else {
32342912Sartem HAL_WARNING ((" Cannot find device object for %s", mi->udi));
32352912Sartem }
32362912Sartem }
32372912Sartem
32382912Sartem hald_exec_method_free_mi (mi);
32392912Sartem }
32402912Sartem
32412912Sartem /* process the rest of the list */
32422912Sartem if (queue != NULL) {
32432912Sartem HAL_INFO (("Execing next method in queue"));
32442912Sartem g_hash_table_replace (udi_to_method_queue, g_strdup (udi), queue);
32452912Sartem
32462912Sartem mi = (MethodInvocation *) queue->data;
32472912Sartem if (!hald_exec_method_do_invocation (mi)) {
32482912Sartem /* the device went away before we got to it... */
32492912Sartem hald_exec_method_process_queue (mi->udi);
32502912Sartem }
32512912Sartem }
32522912Sartem }
32532912Sartem }
32542912Sartem
32552912Sartem static void
hald_exec_method_cb(HalDevice * d,guint32 exit_type,gint return_code,gchar ** error,gpointer data1,gpointer data2)32562912Sartem hald_exec_method_cb (HalDevice *d, guint32 exit_type,
32572912Sartem gint return_code, gchar **error,
32582912Sartem gpointer data1, gpointer data2)
32592912Sartem {
32606573Sphitran dbus_int32_t result;
32612912Sartem DBusMessage *reply = NULL;
32622912Sartem DBusMessage *message;
32632912Sartem DBusMessageIter iter;
32642912Sartem DBusConnection *conn;
32652912Sartem gchar *exp_name = NULL;
32662912Sartem gchar *exp_detail = NULL;
3267*10659SXiao-Lin.Zhang@Sun.COM gboolean invalid_name = FALSE;
32682912Sartem
32692912Sartem hald_exec_method_process_queue (d->udi);
32702912Sartem
32712912Sartem message = (DBusMessage *) data1;
32722912Sartem conn = (DBusConnection *) data2;
32732912Sartem
32742912Sartem if (exit_type == HALD_RUN_SUCCESS && error != NULL &&
32752912Sartem error[0] != NULL && error[1] != NULL) {
32762912Sartem exp_name = error[0];
32772912Sartem if (error[0] != NULL) {
32782912Sartem exp_detail = error[1];
32792912Sartem }
32802912Sartem HAL_INFO (("failed with '%s' '%s'", exp_name, exp_detail));
32812912Sartem }
32822912Sartem
32832912Sartem if (exit_type != HALD_RUN_SUCCESS) {
32842912Sartem reply = dbus_message_new_error (message, "org.freedesktop.Hal.Device.UnknownError", "An unknown error occured");
32852912Sartem if (conn != NULL) {
32862912Sartem if (!dbus_connection_send (conn, reply, NULL))
32872912Sartem DIE (("No memory"));
32882912Sartem }
32892912Sartem dbus_message_unref (reply);
32902912Sartem } else if (exp_name != NULL && exp_detail != NULL) {
3291*10659SXiao-Lin.Zhang@Sun.COM if (!is_valid_interface_name (exp_name)) {
3292*10659SXiao-Lin.Zhang@Sun.COM /*
3293*10659SXiao-Lin.Zhang@Sun.COM * error name may be invalid,
3294*10659SXiao-Lin.Zhang@Sun.COM * if so we need a generic HAL error name;
3295*10659SXiao-Lin.Zhang@Sun.COM * otherwise, dbus will be messed up.
3296*10659SXiao-Lin.Zhang@Sun.COM */
3297*10659SXiao-Lin.Zhang@Sun.COM invalid_name = TRUE;
3298*10659SXiao-Lin.Zhang@Sun.COM exp_detail = g_strconcat (exp_name, " \n ", exp_detail, NULL);
3299*10659SXiao-Lin.Zhang@Sun.COM exp_name = "org.freedesktop.Hal.Device.UnknownError";
3300*10659SXiao-Lin.Zhang@Sun.COM }
33012912Sartem reply = dbus_message_new_error (message, exp_name, exp_detail);
33022912Sartem if (reply == NULL) {
33032912Sartem /* error name may be invalid - assume caller fucked up and use a generic HAL error name */
33042912Sartem reply = dbus_message_new_error (message, "org.freedesktop.Hal.Device.UnknownError", "An unknown error occured");
33052912Sartem if (reply == NULL) {
33062912Sartem DIE (("No memory"));
33072912Sartem }
33082912Sartem }
33092912Sartem if (conn != NULL) {
33102912Sartem if (!dbus_connection_send (conn, reply, NULL))
33112912Sartem DIE (("No memory"));
33122912Sartem }
33132912Sartem dbus_message_unref (reply);
33142912Sartem
33152912Sartem } else {
33166573Sphitran result = (dbus_int32_t) return_code;
33172912Sartem
33182912Sartem reply = dbus_message_new_method_return (message);
33192912Sartem if (reply == NULL)
33202912Sartem DIE (("No memory"));
33212912Sartem
33222912Sartem dbus_message_iter_init_append (reply, &iter);
33236573Sphitran dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &result);
33242912Sartem
33252912Sartem if (conn != NULL) {
33262912Sartem if (!dbus_connection_send (conn, reply, NULL))
33272912Sartem DIE (("No memory"));
33282912Sartem }
33292912Sartem
33302912Sartem dbus_message_unref (reply);
33312912Sartem }
33322912Sartem
3333*10659SXiao-Lin.Zhang@Sun.COM if (invalid_name)
3334*10659SXiao-Lin.Zhang@Sun.COM g_free (exp_detail);
33352912Sartem dbus_message_unref (message);
33362912Sartem }
33372912Sartem
33382912Sartem static DBusHandlerResult
hald_exec_method(HalDevice * d,DBusConnection * connection,dbus_bool_t local_interface,DBusMessage * message,const char * execpath)33392912Sartem hald_exec_method (HalDevice *d, DBusConnection *connection, dbus_bool_t local_interface,
33402912Sartem DBusMessage *message, const char *execpath)
33412912Sartem {
33422912Sartem int type;
33432912Sartem GString *stdin_str;
33442912Sartem DBusMessageIter iter;
33452912Sartem char *extra_env[3];
33462912Sartem char uid_export[128];
33472912Sartem char sender_export[128];
33482912Sartem MethodInvocation *mi;
33492912Sartem
33502912Sartem /* add calling uid */
33512912Sartem extra_env[0] = NULL;
33522912Sartem extra_env[1] = NULL;
33532912Sartem if (local_interface) {
33542912Sartem extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=0";
33552912Sartem extra_env[1] = "HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME=0";
33562912Sartem } else {
33572912Sartem const char *sender;
33582912Sartem
33592912Sartem sender = dbus_message_get_sender (message);
33602912Sartem if (sender != NULL) {
33612912Sartem DBusError error;
33622912Sartem unsigned long uid;
33632912Sartem
33642912Sartem dbus_error_init (&error);
33652912Sartem uid = dbus_bus_get_unix_user (connection, sender, &error);
33662912Sartem if (!dbus_error_is_set (&error)) {
33672912Sartem sprintf (uid_export, "HAL_METHOD_INVOKED_BY_UID=%lu", uid);
33682912Sartem extra_env[0] = uid_export;
33692912Sartem }
33702912Sartem snprintf (sender_export, sizeof (sender_export),
33712912Sartem "HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME=%s", sender);
33722912Sartem extra_env[1] = sender_export;
33732912Sartem }
33742912Sartem }
33752912Sartem
33762912Sartem if (extra_env[0] == NULL)
33772912Sartem extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=nobody";
33782912Sartem if (extra_env[1] == NULL)
33792912Sartem extra_env[1] = "HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME=0";
33802912Sartem
33812912Sartem
33822912Sartem extra_env[2] = NULL;
33832912Sartem
33842912Sartem /* prepare stdin with parameters */
33852912Sartem stdin_str = g_string_sized_new (256); /* default size for passing params; can grow */
33862912Sartem dbus_message_iter_init (message, &iter);
33872912Sartem while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) {
33882912Sartem switch (type) {
33892912Sartem case DBUS_TYPE_BYTE:
33902912Sartem {
33912912Sartem unsigned char value;
33922912Sartem dbus_message_iter_get_basic (&iter, &value);
33932912Sartem g_string_append_printf (stdin_str, "%u", value);
33942912Sartem break;
33952912Sartem }
33962912Sartem case DBUS_TYPE_INT16:
33972912Sartem {
33982912Sartem dbus_int16_t value;
33992912Sartem dbus_message_iter_get_basic (&iter, &value);
34002912Sartem g_string_append_printf (stdin_str, "%d", value);
34012912Sartem break;
34022912Sartem }
34032912Sartem case DBUS_TYPE_UINT16:
34042912Sartem {
34052912Sartem dbus_uint16_t value;
34062912Sartem dbus_message_iter_get_basic (&iter, &value);
34072912Sartem g_string_append_printf (stdin_str, "%u", value);
34082912Sartem break;
34092912Sartem }
34102912Sartem case DBUS_TYPE_INT32:
34112912Sartem {
34122912Sartem dbus_int32_t value;
34132912Sartem dbus_message_iter_get_basic (&iter, &value);
34142912Sartem g_string_append_printf (stdin_str, "%d", value);
34152912Sartem break;
34162912Sartem }
34172912Sartem case DBUS_TYPE_UINT32:
34182912Sartem {
34192912Sartem dbus_uint32_t value;
34202912Sartem dbus_message_iter_get_basic (&iter, &value);
34212912Sartem g_string_append_printf (stdin_str, "%u", value);
34222912Sartem break;
34232912Sartem }
34242912Sartem case DBUS_TYPE_INT64:
34252912Sartem {
34262912Sartem dbus_int64_t value;
34272912Sartem dbus_message_iter_get_basic (&iter, &value);
34282912Sartem g_string_append_printf (stdin_str, "%lld", (long long int) value);
34292912Sartem break;
34302912Sartem }
34312912Sartem case DBUS_TYPE_UINT64:
34322912Sartem {
34332912Sartem dbus_uint64_t value;
34342912Sartem dbus_message_iter_get_basic (&iter, &value);
34352912Sartem g_string_append_printf (stdin_str, "%llu", (long long unsigned int) value);
34362912Sartem break;
34372912Sartem }
34382912Sartem case DBUS_TYPE_DOUBLE:
34392912Sartem {
34402912Sartem double value;
34412912Sartem dbus_message_iter_get_basic (&iter, &value);
34422912Sartem g_string_append_printf (stdin_str, "%g", value);
34432912Sartem break;
34442912Sartem }
34452912Sartem case DBUS_TYPE_BOOLEAN:
34462912Sartem {
34472912Sartem dbus_bool_t value;
34482912Sartem dbus_message_iter_get_basic (&iter, &value);
34492912Sartem g_string_append (stdin_str, value ? "true" : "false");
34502912Sartem break;
34512912Sartem }
34522912Sartem case DBUS_TYPE_STRING:
34532912Sartem {
34542912Sartem char *value;
34552912Sartem dbus_message_iter_get_basic (&iter, &value);
34562912Sartem g_string_append (stdin_str, value);
34572912Sartem break;
34582912Sartem }
34592912Sartem
34602912Sartem case DBUS_TYPE_ARRAY:
34612912Sartem {
34622912Sartem DBusMessageIter iter_strlist;
34632912Sartem if (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING)
34642912Sartem goto error;
34652912Sartem
34662912Sartem dbus_message_iter_recurse (&iter, &iter_strlist);
34672912Sartem while (dbus_message_iter_get_arg_type (&iter_strlist) == DBUS_TYPE_STRING) {
34682912Sartem const char *value;
34692912Sartem dbus_message_iter_get_basic (&iter_strlist, &value);
34702912Sartem g_string_append (stdin_str, value);
34712912Sartem g_string_append (stdin_str, "\t");
34722912Sartem dbus_message_iter_next(&iter_strlist);
34732912Sartem }
34742912Sartem break;
34752912Sartem }
34762912Sartem
34772912Sartem default:
34782912Sartem goto error;
34792912Sartem }
34802912Sartem
34812912Sartem g_string_append_c (stdin_str, '\n');
34822912Sartem dbus_message_iter_next (&iter);
34832912Sartem }
34842912Sartem
34852912Sartem mi = g_new0 (MethodInvocation, 1);
34862912Sartem mi->udi = g_strdup (d->udi);
34872912Sartem mi->execpath = g_strdup (execpath);
34882912Sartem mi->extra_env = g_strdupv (extra_env);
34892912Sartem mi->mstdin = g_strdup (stdin_str->str);
34902912Sartem mi->message = message;
34912912Sartem mi->connection = connection;
34922912Sartem mi->member = g_strdup (dbus_message_get_member (message));
34932912Sartem mi->interface = g_strdup (dbus_message_get_interface (message));
34942912Sartem hald_exec_method_enqueue (mi);
34952912Sartem
34962912Sartem dbus_message_ref (message);
34972912Sartem g_string_free (stdin_str, TRUE);
34982912Sartem
34992912Sartem return DBUS_HANDLER_RESULT_HANDLED;
35002912Sartem
35012912Sartem error:
35022912Sartem g_string_free (stdin_str, TRUE);
35032912Sartem return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
35042912Sartem }
35052912Sartem
35062912Sartem static gboolean
foreach_device_get_xml_node(HalDeviceStore * store,HalDevice * device,gpointer user_data)35072912Sartem foreach_device_get_xml_node (HalDeviceStore *store, HalDevice *device,
35082912Sartem gpointer user_data)
35092912Sartem {
35102912Sartem GString *xml = user_data;
35112912Sartem const char *udi, *name;
35122912Sartem
35132912Sartem udi = hal_device_get_udi (device);
35142912Sartem name = strrchr(udi, '/')+1;
35152912Sartem
35162912Sartem xml = g_string_append(xml, " <node name=\"");
35172912Sartem xml = g_string_append(xml, name);
35182912Sartem xml = g_string_append(xml, "\"/>\n");
35192912Sartem
35202912Sartem return TRUE;
35212912Sartem }
35222912Sartem
35232912Sartem static DBusHandlerResult
do_introspect(DBusConnection * connection,DBusMessage * message,dbus_bool_t local_interface)35242912Sartem do_introspect (DBusConnection *connection,
35252912Sartem DBusMessage *message,
35262912Sartem dbus_bool_t local_interface)
35272912Sartem {
35282912Sartem const char *path;
35292912Sartem DBusMessage *reply;
35302912Sartem GString *xml;
35312912Sartem char *xml_string;
35322912Sartem
35332912Sartem HAL_TRACE (("entering do_introspect"));
35342912Sartem
35352912Sartem path = dbus_message_get_path (message);
35362912Sartem
35372912Sartem xml = g_string_new ("<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n"
35382912Sartem "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
35392912Sartem "<node>\n"
35402912Sartem " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
35412912Sartem " <method name=\"Introspect\">\n"
35422912Sartem " <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
35432912Sartem " </method>\n"
35442912Sartem " </interface>\n");
35452912Sartem
35462912Sartem if (strcmp (path, "/") == 0) {
35472912Sartem
35482912Sartem xml = g_string_append (xml,
35492912Sartem " <node name=\"org\"/>\n");
35502912Sartem
35512912Sartem } else if (strcmp (path, "/org") == 0) {
35522912Sartem
35532912Sartem xml = g_string_append (xml,
35542912Sartem " <node name=\"freedesktop\"/>\n");
35552912Sartem
35562912Sartem } else if (strcmp (path, "/org/freedesktop") == 0) {
35572912Sartem
35582912Sartem xml = g_string_append (xml,
35592912Sartem " <node name=\"Hal\"/>\n");
35602912Sartem
35612912Sartem } else if (strcmp (path, "/org/freedesktop/Hal") == 0) {
35622912Sartem
35632912Sartem xml = g_string_append (xml,
35642912Sartem " <node name=\"Manager\"/>\n"
35652912Sartem " <node name=\"devices\"/>\n");
35662912Sartem
35672912Sartem } else if (strcmp (path, "/org/freedesktop/Hal/devices") == 0) {
35682912Sartem
35692912Sartem hal_device_store_foreach (hald_get_gdl (),
35702912Sartem foreach_device_get_xml_node,
35712912Sartem xml);
35722912Sartem
35732912Sartem } else if (strcmp (path, "/org/freedesktop/Hal/Manager") == 0) {
35742912Sartem
35752912Sartem xml = g_string_append (xml,
35762912Sartem " <interface name=\"org.freedesktop.Hal.Manager\">\n"
35772912Sartem " <method name=\"GetAllDevices\">\n"
35782912Sartem " <arg name=\"devices\" direction=\"out\" type=\"ao\"/>\n"
35792912Sartem " </method>\n"
35802912Sartem " <method name=\"DeviceExists\">\n"
35812912Sartem " <arg name=\"does_it_exist\" direction=\"out\" type=\"b\"/>\n"
35822912Sartem " <arg name=\"udi\" direction=\"in\" type=\"o\"/>\n"
35832912Sartem " </method>\n"
35842912Sartem " <method name=\"FindDeviceStringMatch\">\n"
35852912Sartem " <arg name=\"devices\" direction=\"out\" type=\"ao\"/>\n"
35862912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
35872912Sartem " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
35882912Sartem " </method>\n"
35892912Sartem " <method name=\"FindDeviceByCapability\">\n"
35902912Sartem " <arg name=\"devices\" direction=\"out\" type=\"ao\"/>\n"
35912912Sartem " <arg name=\"capability\" direction=\"in\" type=\"s\"/>\n"
35922912Sartem " </method>\n"
35932912Sartem " <method name=\"ClaimBranch\">\n"
35942912Sartem " <arg name=\"udi\" direction=\"in\" type=\"o\"/>\n"
35952912Sartem " <arg name=\"claim_service\" direction=\"in\" type=\"s\"/>\n"
35962912Sartem " <arg name=\"result\" direction=\"out\" type=\"b\"/>\n"
35972912Sartem " </method>\n"
35982912Sartem " <method name=\"UnclaimBranch\">\n"
35992912Sartem " <arg name=\"udi\" direction=\"in\" type=\"o\"/>\n"
36002912Sartem " <arg name=\"result\" direction=\"out\" type=\"b\"/>\n"
36012912Sartem " </method>\n"
36022912Sartem " <method name=\"NewDevice\">\n"
36032912Sartem " <arg name=\"temporary_udi\" direction=\"out\" type=\"s\"/>\n"
36042912Sartem " </method>\n"
36052912Sartem " <method name=\"Remove\">\n"
36062912Sartem " <arg name=\"udi\" direction=\"in\" type=\"s\"/>\n"
36072912Sartem " </method>\n"
36082912Sartem " <method name=\"CommitToGdl\">\n"
36092912Sartem " <arg name=\"temporary_udi\" direction=\"in\" type=\"s\"/>\n"
36102912Sartem " <arg name=\"global_udi\" direction=\"in\" type=\"s\"/>\n"
36112912Sartem " </method>\n"
36122912Sartem " </interface>\n");
36132912Sartem } else {
36142912Sartem HalDevice *d;
36152912Sartem
36162912Sartem d = hal_device_store_find (hald_get_gdl (), path);
36172912Sartem if (d == NULL)
36182912Sartem d = hal_device_store_find (hald_get_tdl (), path);
36192912Sartem
36202912Sartem if (d == NULL) {
36212912Sartem raise_no_such_device (connection, message, path);
36222912Sartem return DBUS_HANDLER_RESULT_HANDLED;
36232912Sartem }
36242912Sartem
36252912Sartem xml = g_string_append (xml,
36262912Sartem " <interface name=\"org.freedesktop.Hal.Device\">\n"
36272912Sartem " <method name=\"GetAllProperties\">\n"
36282912Sartem " <arg name=\"properties\" direction=\"out\" type=\"a{sv}\"/>\n"
36292912Sartem " </method>\n"
36302912Sartem " <method name=\"SetMultipleProperties\">\n"
36312912Sartem " <arg name=\"properties\" direction=\"in\" type=\"a{sv}\"/>\n"
36322912Sartem " </method>\n"
36332912Sartem " <method name=\"GetProperty\">\n"
36342912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36352912Sartem " <arg name=\"value\" direction=\"out\" type=\"v\"/>\n"
36362912Sartem " </method>\n"
36372912Sartem " <method name=\"GetPropertyString\">\n"
36382912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36392912Sartem " <arg name=\"value\" direction=\"out\" type=\"s\"/>\n"
36402912Sartem " </method>\n"
36412912Sartem " <method name=\"GetPropertyStringList\">\n"
36422912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36432912Sartem " <arg name=\"value\" direction=\"out\" type=\"as\"/>\n"
36442912Sartem " </method>\n"
36452912Sartem " <method name=\"GetPropertyInteger\">\n"
36462912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36472912Sartem " <arg name=\"value\" direction=\"out\" type=\"i\"/>\n"
36482912Sartem " </method>\n"
36492912Sartem " <method name=\"GetPropertyBoolean\">\n"
36502912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36512912Sartem " <arg name=\"value\" direction=\"out\" type=\"b\"/>\n"
36522912Sartem " </method>\n"
36532912Sartem " <method name=\"GetPropertyDouble\">\n"
36542912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36552912Sartem " <arg name=\"value\" direction=\"out\" type=\"d\"/>\n"
36562912Sartem " </method>\n"
36572912Sartem " <method name=\"SetProperty\">\n"
36582912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36592912Sartem " <arg name=\"value\" direction=\"in\" type=\"v\"/>\n"
36602912Sartem " </method>\n"
36612912Sartem " <method name=\"SetPropertyString\">\n"
36622912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36632912Sartem " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
36642912Sartem " </method>\n"
36652912Sartem " <method name=\"SetPropertyStringList\">\n"
36662912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36672912Sartem " <arg name=\"value\" direction=\"in\" type=\"as\"/>\n"
36682912Sartem " </method>\n"
36692912Sartem " <method name=\"SetPropertyInteger\">\n"
36702912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36712912Sartem " <arg name=\"value\" direction=\"in\" type=\"i\"/>\n"
36722912Sartem " </method>\n"
36732912Sartem " <method name=\"SetPropertyBoolean\">\n"
36742912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36752912Sartem " <arg name=\"value\" direction=\"in\" type=\"b\"/>\n"
36762912Sartem " </method>\n"
36772912Sartem " <method name=\"SetPropertyDouble\">\n"
36782912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36792912Sartem " <arg name=\"value\" direction=\"in\" type=\"d\"/>\n"
36802912Sartem " </method>\n"
36812912Sartem
36822912Sartem " <method name=\"RemoveProperty\">\n"
36832912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36842912Sartem " </method>\n"
36852912Sartem " <method name=\"GetPropertyType\">\n"
36862912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36872912Sartem " <arg name=\"type\" direction=\"out\" type=\"i\"/>\n"
36882912Sartem " </method>\n"
36892912Sartem " <method name=\"PropertyExists\">\n"
36902912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
36912912Sartem " <arg name=\"does_it_exist\" direction=\"out\" type=\"b\"/>\n"
36922912Sartem " </method>\n"
36932912Sartem " <method name=\"AddCapability\">\n"
36942912Sartem " <arg name=\"capability\" direction=\"in\" type=\"s\"/>\n"
36952912Sartem " </method>\n"
36962912Sartem " <method name=\"QueryCapability\">\n"
36972912Sartem " <arg name=\"capability\" direction=\"in\" type=\"s\"/>\n"
36982912Sartem " <arg name=\"does_it_have_capability\" direction=\"out\" type=\"b\"/>\n"
36992912Sartem " </method>\n"
37002912Sartem " <method name=\"Lock\">\n"
37012912Sartem " <arg name=\"reason\" direction=\"in\" type=\"s\"/>\n"
37022912Sartem " <arg name=\"acquired_lock\" direction=\"out\" type=\"b\"/>\n"
37032912Sartem " </method>\n"
37042912Sartem " <method name=\"Unlock\">\n"
37052912Sartem " <arg name=\"released_lock\" direction=\"out\" type=\"b\"/>\n"
37062912Sartem " </method>\n"
37072912Sartem
37082912Sartem " <method name=\"StringListAppend\">\n"
37092912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
37102912Sartem " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
37112912Sartem " </method>\n"
37122912Sartem " <method name=\"StringListPrepend\">\n"
37132912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
37142912Sartem " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
37152912Sartem " </method>\n"
37162912Sartem " <method name=\"StringListRemove\">\n"
37172912Sartem " <arg name=\"key\" direction=\"in\" type=\"s\"/>\n"
37182912Sartem " <arg name=\"value\" direction=\"in\" type=\"s\"/>\n"
37192912Sartem " </method>\n"
37202912Sartem " <method name=\"EmitCondition\">\n"
37212912Sartem " <arg name=\"condition_name\" direction=\"in\" type=\"s\"/>\n"
37222912Sartem " <arg name=\"condition_details\" direction=\"in\" type=\"s\"/>\n"
37232912Sartem " <arg name=\"rc\" direction=\"out\" type=\"b\"/>\n"
37242912Sartem " </method>\n"
37252912Sartem
37262912Sartem " <method name=\"Rescan\">\n"
37272912Sartem " <arg name=\"call_had_sideeffect\" direction=\"out\" type=\"b\"/>\n"
37282912Sartem " </method>\n"
37292912Sartem " <method name=\"Reprobe\">\n"
37302912Sartem " <arg name=\"call_had_sideeffect\" direction=\"out\" type=\"b\"/>\n"
37312912Sartem " </method>\n"
37322912Sartem
37332912Sartem " <method name=\"ClaimInterface\">\n"
37342912Sartem " <arg name=\"interface_name\" direction=\"in\" type=\"s\"/>\n"
37352912Sartem " <arg name=\"introspection_xml\" direction=\"in\" type=\"s\"/>\n"
37362912Sartem " <arg name=\"rc\" direction=\"out\" type=\"b\"/>\n"
37372912Sartem " </method>\n"
37382912Sartem
37392912Sartem " <method name=\"AddonIsReady\">\n"
37402912Sartem " <arg name=\"rc\" direction=\"out\" type=\"b\"/>\n"
37412912Sartem " </method>\n"
37422912Sartem
37432912Sartem " </interface>\n");
37442912Sartem
37452912Sartem GSList *interfaces;
37462912Sartem GSList *i;
37472912Sartem
37482912Sartem interfaces = hal_device_property_get_strlist (d, "info.interfaces");
37492912Sartem for (i = interfaces; i != NULL; i = g_slist_next (i)) {
37502912Sartem const char *ifname = (const char *) i->data;
37512912Sartem char *method_names_prop;
37522912Sartem char *method_signatures_prop;
37532912Sartem char *method_argnames_prop;
37542912Sartem GSList *method_names;
37552912Sartem GSList *method_signatures;
37562912Sartem GSList *method_argnames;
37572912Sartem GSList *j;
37582912Sartem GSList *k;
37592912Sartem GSList *l;
37602912Sartem
37612912Sartem g_string_append_printf (xml, " <interface name=\"%s\">\n", ifname);
37622912Sartem
37632912Sartem method_names_prop = g_strdup_printf ("%s.method_names", ifname);
37642912Sartem method_signatures_prop = g_strdup_printf ("%s.method_signatures", ifname);
37652912Sartem method_argnames_prop = g_strdup_printf ("%s.method_argnames", ifname);
37662912Sartem
37672912Sartem method_names = hal_device_property_get_strlist (d, method_names_prop);
37682912Sartem method_signatures = hal_device_property_get_strlist (d, method_signatures_prop);
37692912Sartem method_argnames = hal_device_property_get_strlist (d, method_argnames_prop);
37702912Sartem
37712912Sartem /* consult local list */
37722912Sartem if (method_names == NULL) {
37732912Sartem GSList *i;
37742912Sartem
37752912Sartem for (i = helper_interface_handlers; i != NULL; i = g_slist_next (i)) {
37762912Sartem HelperInterfaceHandler *hih = i->data;
37772912Sartem if (strcmp (hih->udi, path) == 0) {
37782912Sartem xml = g_string_append (xml, hih->introspection_xml);
37792912Sartem }
37802912Sartem }
37812912Sartem
37822912Sartem }
37832912Sartem
37842912Sartem for (j = method_names, k = method_signatures, l = method_argnames;
37852912Sartem j != NULL && k != NULL && l != NULL;
37862912Sartem j = g_slist_next (j), k = g_slist_next (k), l = g_slist_next (l)) {
37872912Sartem const char *name;
37882912Sartem const char *sig;
37892912Sartem const char *argnames;
37902912Sartem char **args;
37912912Sartem unsigned int n;
37922912Sartem unsigned int m;
37932912Sartem
37942912Sartem name = j->data;
37952912Sartem sig = k->data;
37962912Sartem argnames = l->data;
37972912Sartem
37982912Sartem args = g_strsplit (argnames, " ", 0);
37992912Sartem
38002912Sartem g_string_append_printf (xml, " <method name=\"%s\">\n", name);
38012912Sartem
38022912Sartem for (n = 0, m = 0; n < strlen (sig) && args[m] != NULL; n++, m++) {
38032912Sartem switch (sig[n]) {
38042912Sartem case 'a':
38052912Sartem if (n == strlen (sig) - 1) {
38062912Sartem HAL_WARNING (("Broken signature for method %s "
38072912Sartem "on interface %s for object %s",
38082912Sartem name, ifname, path));
38092912Sartem continue;
38102912Sartem }
38112912Sartem g_string_append_printf (
38122912Sartem xml,
38132912Sartem " <arg name=\"%s\" direction=\"in\" type=\"a%c\"/>\n",
38142912Sartem args[m], sig[n + 1]);
38152912Sartem n++;
38162912Sartem break;
38172912Sartem
38182912Sartem default:
38192912Sartem g_string_append_printf (
38202912Sartem xml,
38212912Sartem " <arg name=\"%s\" direction=\"in\" type=\"%c\"/>\n",
38222912Sartem args[m], sig[n]);
38232912Sartem break;
38242912Sartem }
38252912Sartem }
38262912Sartem xml = g_string_append (
38272912Sartem xml,
38282912Sartem " <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n");
38292912Sartem xml = g_string_append (
38302912Sartem xml,
38312912Sartem " </method>\n");
38322912Sartem
38332912Sartem }
38342912Sartem
38352912Sartem
38362912Sartem xml = g_string_append (xml, " </interface>\n");
38372912Sartem
38382912Sartem g_free (method_names_prop);
38392912Sartem g_free (method_signatures_prop);
38402912Sartem g_free (method_argnames_prop);
38412912Sartem }
38422912Sartem
38432912Sartem }
38442912Sartem
38452912Sartem reply = dbus_message_new_method_return (message);
38462912Sartem
38472912Sartem xml = g_string_append (xml, "</node>\n");
38482912Sartem xml_string = g_string_free (xml, FALSE);
38492912Sartem
38502912Sartem dbus_message_append_args (reply,
38512912Sartem DBUS_TYPE_STRING, &xml_string,
38522912Sartem DBUS_TYPE_INVALID);
38532912Sartem
38542912Sartem g_free (xml_string);
38552912Sartem
38562912Sartem if (reply == NULL)
38572912Sartem DIE (("No memory"));
38582912Sartem
38592912Sartem if (!dbus_connection_send (connection, reply, NULL))
38602912Sartem DIE (("No memory"));
38612912Sartem
38622912Sartem dbus_message_unref (reply);
38632912Sartem return DBUS_HANDLER_RESULT_HANDLED;
38642912Sartem }
38652912Sartem
38662912Sartem static void
reply_from_fwd_message(DBusPendingCall * pending_call,void * user_data)38672912Sartem reply_from_fwd_message (DBusPendingCall *pending_call,
38682912Sartem void *user_data)
38692912Sartem {
38702912Sartem DBusMessage *reply_from_addon;
38712912Sartem DBusMessage *method_from_caller;
38722912Sartem DBusMessage *reply;
38732912Sartem
38742912Sartem /*HAL_INFO (("in reply_from_fwd_message : user_data = 0x%x", user_data));*/
38752912Sartem
38762912Sartem method_from_caller = (DBusMessage *) user_data;
38772912Sartem reply_from_addon = dbus_pending_call_steal_reply (pending_call);
38782912Sartem
38792912Sartem reply = dbus_message_copy (reply_from_addon);
38802912Sartem dbus_message_set_destination (reply, dbus_message_get_sender (method_from_caller));
38812912Sartem dbus_message_set_reply_serial (reply, dbus_message_get_serial (method_from_caller));
38822912Sartem
38832912Sartem if (dbus_connection != NULL)
38842912Sartem dbus_connection_send (dbus_connection, reply, NULL);
38852912Sartem
38862912Sartem dbus_message_unref (reply_from_addon);
38872912Sartem dbus_message_unref (reply);
38882912Sartem dbus_message_unref (method_from_caller);
38892912Sartem dbus_pending_call_unref (pending_call);
38902912Sartem }
38912912Sartem
38922912Sartem static DBusHandlerResult
hald_dbus_filter_handle_methods(DBusConnection * connection,DBusMessage * message,void * user_data,dbus_bool_t local_interface)38932912Sartem hald_dbus_filter_handle_methods (DBusConnection *connection, DBusMessage *message,
38942912Sartem void *user_data, dbus_bool_t local_interface)
38952912Sartem {
38962912Sartem /*HAL_INFO (("connection=0x%x obj_path=%s interface=%s method=%s local_interface=%d",
38972912Sartem connection,
38982912Sartem dbus_message_get_path (message),
38992912Sartem dbus_message_get_interface (message),
39002912Sartem dbus_message_get_member (message),
39012912Sartem local_interface));*/
39022912Sartem
39032912Sartem if (dbus_message_is_method_call (message,
39042912Sartem "org.freedesktop.Hal.Manager",
39052912Sartem "GetAllDevices") &&
39062912Sartem strcmp (dbus_message_get_path (message),
39072912Sartem "/org/freedesktop/Hal/Manager") == 0) {
39082912Sartem return manager_get_all_devices (connection, message);
39092912Sartem } else if (dbus_message_is_method_call (message,
39102912Sartem "org.freedesktop.Hal.Manager",
39112912Sartem "DeviceExists") &&
39122912Sartem strcmp (dbus_message_get_path (message),
39132912Sartem "/org/freedesktop/Hal/Manager") == 0) {
39142912Sartem return manager_device_exists (connection, message);
39152912Sartem } else if (dbus_message_is_method_call (message,
39162912Sartem "org.freedesktop.Hal.Manager",
39172912Sartem "FindDeviceStringMatch") &&
39182912Sartem strcmp (dbus_message_get_path (message),
39192912Sartem "/org/freedesktop/Hal/Manager") == 0) {
39202912Sartem return manager_find_device_string_match (connection,
39212912Sartem message);
39222912Sartem } else if (dbus_message_is_method_call
39232912Sartem (message, "org.freedesktop.Hal.Manager",
39242912Sartem "FindDeviceByCapability")
39252912Sartem && strcmp (dbus_message_get_path (message),
39262912Sartem "/org/freedesktop/Hal/Manager") == 0) {
39272912Sartem return manager_find_device_by_capability (connection,
39282912Sartem message);
39292912Sartem } else if (dbus_message_is_method_call (message,
39302912Sartem "org.freedesktop.Hal.Manager",
39312912Sartem "ClaimBranch") &&
39322912Sartem strcmp (dbus_message_get_path (message),
39332912Sartem "/org/freedesktop/Hal/Manager") == 0) {
39342912Sartem return manager_claim_branch (connection, message);
39352912Sartem } else if (dbus_message_is_method_call (message,
39362912Sartem "org.freedesktop.Hal.Manager",
39372912Sartem "UnclaimBranch") &&
39382912Sartem strcmp (dbus_message_get_path (message),
39392912Sartem "/org/freedesktop/Hal/Manager") == 0) {
39402912Sartem return manager_unclaim_branch (connection, message);
39412912Sartem } else if (dbus_message_is_method_call (message,
39422912Sartem "org.freedesktop.Hal.Manager",
39432912Sartem "NewDevice") &&
39442912Sartem strcmp (dbus_message_get_path (message),
39452912Sartem "/org/freedesktop/Hal/Manager") == 0) {
39462912Sartem return manager_new_device (connection, message, local_interface);
39472912Sartem } else if (dbus_message_is_method_call (message,
39482912Sartem "org.freedesktop.Hal.Manager",
39492912Sartem "Remove") &&
39502912Sartem strcmp (dbus_message_get_path (message),
39512912Sartem "/org/freedesktop/Hal/Manager") == 0) {
39522912Sartem return manager_remove (connection, message, local_interface);
39532912Sartem } else if (dbus_message_is_method_call (message,
39542912Sartem "org.freedesktop.Hal.Manager",
39552912Sartem "CommitToGdl") &&
39562912Sartem strcmp (dbus_message_get_path (message),
39572912Sartem "/org/freedesktop/Hal/Manager") == 0) {
39582912Sartem return manager_commit_to_gdl (connection, message, local_interface);
39592912Sartem } else if (dbus_message_is_method_call (message,
39602912Sartem "org.freedesktop.Hal.Device",
39612912Sartem "GetAllProperties")) {
39622912Sartem return device_get_all_properties (connection, message);
39632912Sartem } else if (dbus_message_is_method_call (message,
39642912Sartem "org.freedesktop.Hal.Device",
39652912Sartem "SetMultipleProperties")) {
39662912Sartem return device_set_multiple_properties (connection, message, local_interface);
39672912Sartem } else if (dbus_message_is_method_call (message,
39682912Sartem "org.freedesktop.Hal.Device",
39692912Sartem "GetProperty")) {
39702912Sartem return device_get_property (connection, message);
39712912Sartem } else if (dbus_message_is_method_call (message,
39722912Sartem "org.freedesktop.Hal.Device",
39732912Sartem "GetPropertyString")) {
39742912Sartem return device_get_property (connection, message);
39752912Sartem } else if (dbus_message_is_method_call (message,
39762912Sartem "org.freedesktop.Hal.Device",
39772912Sartem "GetPropertyStringList")) {
39782912Sartem return device_get_property (connection, message);
39792912Sartem } else if (dbus_message_is_method_call (message,
39802912Sartem "org.freedesktop.Hal.Device",
39812912Sartem "GetPropertyInteger")) {
39822912Sartem return device_get_property (connection, message);
39832912Sartem } else if (dbus_message_is_method_call (message,
39842912Sartem "org.freedesktop.Hal.Device",
39852912Sartem "GetPropertyBoolean")) {
39862912Sartem return device_get_property (connection, message);
39872912Sartem } else if (dbus_message_is_method_call (message,
39882912Sartem "org.freedesktop.Hal.Device",
39892912Sartem "GetPropertyDouble")) {
39902912Sartem return device_get_property (connection, message);
39912912Sartem } else if (dbus_message_is_method_call (message,
39922912Sartem "org.freedesktop.Hal.Device",
39932912Sartem "SetProperty")) {
39942912Sartem return device_set_property (connection, message, local_interface);
39952912Sartem } else if (dbus_message_is_method_call (message,
39962912Sartem "org.freedesktop.Hal.Device",
39972912Sartem "SetPropertyString")) {
39982912Sartem return device_set_property (connection, message, local_interface);
39992912Sartem } else if (dbus_message_is_method_call (message,
40002912Sartem "org.freedesktop.Hal.Device",
40012912Sartem "SetPropertyInteger")) {
40022912Sartem return device_set_property (connection, message, local_interface);
40032912Sartem } else if (dbus_message_is_method_call (message,
40042912Sartem "org.freedesktop.Hal.Device",
40052912Sartem "SetPropertyBoolean")) {
40062912Sartem return device_set_property (connection, message, local_interface);
40072912Sartem } else if (dbus_message_is_method_call (message,
40082912Sartem "org.freedesktop.Hal.Device",
40092912Sartem "SetPropertyDouble")) {
40102912Sartem return device_set_property (connection, message, local_interface);
40112912Sartem } else if (dbus_message_is_method_call (message,
40122912Sartem "org.freedesktop.Hal.Device",
40132912Sartem "RemoveProperty")) {
40142912Sartem return device_remove_property (connection, message, local_interface);
40152912Sartem } else if (dbus_message_is_method_call (message,
40162912Sartem "org.freedesktop.Hal.Device",
40172912Sartem "GetPropertyType")) {
40182912Sartem return device_get_property_type (connection, message);
40192912Sartem } else if (dbus_message_is_method_call (message,
40202912Sartem "org.freedesktop.Hal.Device",
40212912Sartem "PropertyExists")) {
40222912Sartem return device_property_exists (connection, message);
40232912Sartem } else if (dbus_message_is_method_call (message,
40242912Sartem "org.freedesktop.Hal.Device",
40252912Sartem "AddCapability")) {
40262912Sartem return device_add_capability (connection, message, local_interface);
40272912Sartem } else if (dbus_message_is_method_call (message,
40282912Sartem "org.freedesktop.Hal.Device",
40292912Sartem "QueryCapability")) {
40302912Sartem return device_query_capability (connection, message);
40312912Sartem } else if (dbus_message_is_method_call (message,
40322912Sartem "org.freedesktop.Hal.Device",
40332912Sartem "Lock")) {
40342912Sartem return device_lock (connection, message);
40352912Sartem } else if (dbus_message_is_method_call (message,
40362912Sartem "org.freedesktop.Hal.Device",
40372912Sartem "Unlock")) {
40382912Sartem return device_unlock (connection, message);
40392912Sartem } else if (dbus_message_is_method_call (message,
40402912Sartem "org.freedesktop.Hal.Device",
40412912Sartem "StringListAppend")) {
40422912Sartem return device_string_list_append_prepend (connection, message, FALSE);
40432912Sartem } else if (dbus_message_is_method_call (message,
40442912Sartem "org.freedesktop.Hal.Device",
40452912Sartem "StringListPrepend")) {
40462912Sartem return device_string_list_append_prepend (connection, message, TRUE);
40472912Sartem } else if (dbus_message_is_method_call (message,
40482912Sartem "org.freedesktop.Hal.Device",
40492912Sartem "StringListRemove")) {
40502912Sartem return device_string_list_remove (connection, message);
40512912Sartem } else if (dbus_message_is_method_call (message,
40522912Sartem "org.freedesktop.Hal.Device",
40532912Sartem "Rescan")) {
40542912Sartem return device_rescan (connection, message, local_interface);
40552912Sartem } else if (dbus_message_is_method_call (message,
40562912Sartem "org.freedesktop.Hal.Device",
40572912Sartem "Reprobe")) {
40582912Sartem return device_reprobe (connection, message, local_interface);
40592912Sartem } else if (dbus_message_is_method_call (message,
40602912Sartem "org.freedesktop.Hal.Device",
40612912Sartem "EmitCondition")) {
40622912Sartem return device_emit_condition (connection, message, local_interface);
40632912Sartem } else if (dbus_message_is_method_call (message,
40642912Sartem "org.freedesktop.Hal.Device",
40652912Sartem "ClaimInterface")) {
40662912Sartem return device_claim_interface (connection, message, local_interface);
40672912Sartem #if 0
40682912Sartem } else if (dbus_message_is_method_call (message,
40692912Sartem "org.freedesktop.Hal.Device",
40702912Sartem "ReleaseInterface")) {
40712912Sartem return device_release_interface (connection, message, local_interface);
40722912Sartem #endif
40732912Sartem } else if (dbus_message_is_method_call (message,
40742912Sartem "org.freedesktop.Hal.Device",
40752912Sartem "AddonIsReady")) {
40762912Sartem return addon_is_ready (connection, message, local_interface);
40772912Sartem } else if (dbus_message_is_method_call (message,
40782912Sartem "org.freedesktop.DBus.Introspectable",
40792912Sartem "Introspect")) {
40802912Sartem return do_introspect (connection, message, local_interface);
40812912Sartem } else {
40822912Sartem const char *interface;
40832912Sartem const char *udi;
40842912Sartem const char *method;
40852912Sartem const char *signature;
40862912Sartem HalDevice *d;
40872912Sartem
40882912Sartem /* check for device-specific interfaces that individual objects may support */
40892912Sartem
40902912Sartem udi = dbus_message_get_path (message);
40912912Sartem interface = dbus_message_get_interface (message);
40922912Sartem method = dbus_message_get_member (message);
40932912Sartem signature = dbus_message_get_signature (message);
40942912Sartem
40952912Sartem d = NULL;
40962912Sartem
40972912Sartem if (udi != NULL) {
40982912Sartem d = hal_device_store_find (hald_get_gdl (), udi);
40992912Sartem if (d == NULL)
41002912Sartem d = hal_device_store_find (hald_get_tdl (), udi);
41012912Sartem }
41022912Sartem
41032912Sartem if (d != NULL && interface != NULL) {
41042912Sartem GSList *i;
41052912Sartem
41062912Sartem for (i = helper_interface_handlers; i != NULL; i = g_slist_next (i)) {
41072912Sartem HelperInterfaceHandler *hih = i->data;
41082912Sartem if (strcmp (hih->udi, udi) == 0 &&
41092912Sartem strcmp (hih->interface_name, interface) == 0) {
41102912Sartem DBusPendingCall *pending_call;
41112912Sartem DBusMessage *copy;
41122912Sartem
41132912Sartem /*HAL_INFO (("forwarding method to connection 0x%x", hih->connection));*/
41142912Sartem
41152912Sartem dbus_message_ref (message);
41162912Sartem
41172912Sartem /* send a copy of the message */
41182912Sartem copy = dbus_message_copy (message);
41192912Sartem if (!dbus_connection_send_with_reply (hih->connection,
41202912Sartem copy,
41212912Sartem &pending_call,
41222912Sartem /*-1*/ 8000)) {
41232912Sartem /* TODO: handle error */
41242912Sartem } else {
41252912Sartem /*HAL_INFO (("connection=%x message=%x", connection, message));*/
41262912Sartem dbus_pending_call_set_notify (pending_call,
41272912Sartem reply_from_fwd_message,
41282912Sartem (void *) message,
41292912Sartem NULL);
41302912Sartem }
41312912Sartem
41322912Sartem dbus_message_unref (copy);
41332912Sartem
41342912Sartem return DBUS_HANDLER_RESULT_HANDLED;
41352912Sartem }
41362912Sartem }
41372912Sartem }
41382912Sartem
41392912Sartem if (d != NULL && interface != NULL && method != NULL && signature != NULL) {
41402912Sartem GSList *interfaces;
41412912Sartem GSList *i;
41422912Sartem
41432912Sartem interfaces = hal_device_property_get_strlist (d, "info.interfaces");
41442912Sartem for (i = interfaces; i != NULL; i = g_slist_next (i)) {
41452912Sartem const char *ifname = (const char *) i->data;
41462912Sartem
41472912Sartem if (strcmp (ifname, interface) == 0) {
41482912Sartem guint num;
41492912Sartem GSList *method_names;
41502912Sartem char *s;
41512912Sartem
41522912Sartem s = g_strdup_printf ("%s.method_names", interface);
41532912Sartem method_names = hal_device_property_get_strlist (d, s);
41542912Sartem g_free (s);
41552912Sartem for (i = method_names, num = 0; i != NULL; i = g_slist_next (i), num++) {
41562912Sartem const char *methodname = (const char *) i->data;
41572912Sartem if (strcmp (methodname, method) == 0) {
41582912Sartem const char *execpath;
41592912Sartem const char *sig;
41602912Sartem
41612912Sartem s = g_strdup_printf ("%s.method_execpaths", interface);
41622912Sartem execpath = hal_device_property_get_strlist_elem (d, s, num);
41632912Sartem g_free (s);
41642912Sartem s = g_strdup_printf ("%s.method_signatures", interface);
41652912Sartem sig = hal_device_property_get_strlist_elem (d, s, num);
41662912Sartem g_free (s);
41672912Sartem
41682912Sartem if (execpath != NULL && sig != NULL &&
41692912Sartem strcmp (sig, signature) == 0) {
41702912Sartem
41712912Sartem HAL_INFO (("OK for method '%s' with signature '%s' on interface '%s' for UDI '%s' and execpath '%s'", method, signature, interface, udi, execpath));
41722912Sartem
41732912Sartem return hald_exec_method (d, connection, local_interface,
41742912Sartem message, execpath);
41752912Sartem }
41762912Sartem
41772912Sartem }
41782912Sartem }
41792912Sartem }
41802912Sartem }
41812912Sartem
41822912Sartem }
41832912Sartem }
41842912Sartem
41852912Sartem return osspec_filter_function (connection, message, user_data);
41862912Sartem }
41872912Sartem
41882912Sartem
41892912Sartem /** Message handler for method invocations. All invocations on any object
41902912Sartem * or interface is routed through this function.
41912912Sartem *
41922912Sartem * @param connection D-BUS connection
41932912Sartem * @param message Message
41942912Sartem * @param user_data User data
41952912Sartem * @return What to do with the message
41962912Sartem */
41972912Sartem DBusHandlerResult
hald_dbus_filter_function(DBusConnection * connection,DBusMessage * message,void * user_data)41982912Sartem hald_dbus_filter_function (DBusConnection * connection,
41992912Sartem DBusMessage * message, void *user_data)
42002912Sartem {
42012912Sartem if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
42022912Sartem strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
42032912Sartem
42042912Sartem /* this is a local message; e.g. from libdbus in this process */
42052912Sartem
42062912Sartem HAL_INFO (("Got disconnected from the system message bus; "
42072912Sartem "retrying to reconnect every 3000 ms"));
42082912Sartem dbus_connection_unref (dbus_connection);
42092912Sartem dbus_connection = NULL;
42102912Sartem
42112912Sartem g_timeout_add (3000, reinit_dbus, NULL);
42122912Sartem
42132912Sartem } else if (dbus_message_is_signal (message,
42142912Sartem DBUS_INTERFACE_DBUS,
42152912Sartem "NameOwnerChanged")) {
42162912Sartem
42172912Sartem if (services_with_locks != NULL || services_with_claims != NULL)
42182912Sartem service_deleted (message);
42192912Sartem } else
42202912Sartem return hald_dbus_filter_handle_methods (connection, message, user_data, FALSE);
42212912Sartem
42222912Sartem return DBUS_HANDLER_RESULT_HANDLED;
42232912Sartem }
42242912Sartem
42252912Sartem
42262912Sartem
42272912Sartem static DBusHandlerResult
local_server_message_handler(DBusConnection * connection,DBusMessage * message,void * user_data)42282912Sartem local_server_message_handler (DBusConnection *connection,
42292912Sartem DBusMessage *message,
42302912Sartem void *user_data)
42312912Sartem {
42322912Sartem /*HAL_INFO (("local_server_message_handler: destination=%s obj_path=%s interface=%s method=%s",
42332912Sartem dbus_message_get_destination (message),
42342912Sartem dbus_message_get_path (message),
42352912Sartem dbus_message_get_interface (message),
42362912Sartem dbus_message_get_member (message)));*/
42372912Sartem
42382912Sartem if (dbus_message_is_method_call (message, "org.freedesktop.DBus", "AddMatch")) {
42392912Sartem DBusMessage *reply;
42402912Sartem
42412912Sartem /* cheat, and handle AddMatch since libhal will try to invoke this method */
42422912Sartem reply = dbus_message_new_method_return (message);
42432912Sartem if (reply == NULL)
42442912Sartem DIE (("No memory"));
42452912Sartem if (!dbus_connection_send (connection, reply, NULL))
42462912Sartem DIE (("No memory"));
42472912Sartem dbus_message_unref (reply);
42482912Sartem return DBUS_HANDLER_RESULT_HANDLED;
42492912Sartem } else if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
42502912Sartem strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
42512912Sartem GSList *i;
42522912Sartem GSList *j;
42532912Sartem
42542912Sartem HAL_INFO (("Client to local_server was disconnected"));
42552912Sartem
42562912Sartem for (i = helper_interface_handlers; i != NULL; i = j) {
42572912Sartem HelperInterfaceHandler *hih = i->data;
42582912Sartem
42592912Sartem j = g_slist_next (i);
42602912Sartem
42612912Sartem if (hih->connection == connection) {
42622912Sartem g_free (hih->interface_name);
42632912Sartem g_free (hih->introspection_xml);
42642912Sartem g_free (hih->udi);
42652912Sartem g_free (hih);
42663502Sartem helper_interface_handlers = g_slist_remove_link (helper_interface_handlers, i);
42672912Sartem }
42682912Sartem }
42692912Sartem
42702912Sartem dbus_connection_unref (connection);
42712912Sartem return DBUS_HANDLER_RESULT_HANDLED;
42722912Sartem } else if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL) {
42732912Sartem DBusMessage *copy;
42742912Sartem
42752912Sartem /* it's a signal, just forward it onto the system message bus */
42762912Sartem copy = dbus_message_copy (message);
42772912Sartem if (dbus_connection != NULL) {
42782912Sartem dbus_connection_send (dbus_connection, copy, NULL);
42792912Sartem }
42802912Sartem dbus_message_unref (copy);
42812912Sartem } else {
42822912Sartem return hald_dbus_filter_handle_methods (connection, message, user_data, TRUE);
42832912Sartem }
42842912Sartem
42852912Sartem return DBUS_HANDLER_RESULT_HANDLED;
42862912Sartem }
42872912Sartem
42882912Sartem static void
local_server_unregister_handler(DBusConnection * connection,void * user_data)42892912Sartem local_server_unregister_handler (DBusConnection *connection, void *user_data)
42902912Sartem {
42912912Sartem HAL_INFO (("unregistered"));
42922912Sartem }
42932912Sartem
42942912Sartem static void
local_server_handle_connection(DBusServer * server,DBusConnection * new_connection,void * data)42952912Sartem local_server_handle_connection (DBusServer *server,
42962912Sartem DBusConnection *new_connection,
42972912Sartem void *data)
42982912Sartem {
42992912Sartem DBusObjectPathVTable vtable = { &local_server_unregister_handler,
43002912Sartem &local_server_message_handler,
43012912Sartem NULL, NULL, NULL, NULL};
43022912Sartem
43032912Sartem HAL_INFO (("%d: Got a connection", getpid ()));
43042912Sartem HAL_INFO (("dbus_connection_get_is_connected = %d", dbus_connection_get_is_connected (new_connection)));
43052912Sartem
43062912Sartem /*dbus_connection_add_filter (new_connection, server_filter_function, NULL, NULL);*/
43072912Sartem
43082912Sartem dbus_connection_register_fallback (new_connection,
43092912Sartem "/org/freedesktop",
43102912Sartem &vtable,
43112912Sartem NULL);
43122912Sartem dbus_connection_ref (new_connection);
43132912Sartem dbus_connection_setup_with_g_main (new_connection, NULL);
43142912Sartem }
43152912Sartem
43162912Sartem
43172912Sartem static DBusServer *local_server = NULL;
43182912Sartem
43192912Sartem char *
hald_dbus_local_server_addr(void)43202912Sartem hald_dbus_local_server_addr (void)
43212912Sartem {
43222912Sartem if (local_server == NULL)
43232912Sartem return NULL;
43242912Sartem
43252912Sartem return dbus_server_get_address (local_server);
43262912Sartem }
43272912Sartem
43282912Sartem gboolean
hald_dbus_local_server_init(void)43292912Sartem hald_dbus_local_server_init (void)
43302912Sartem {
43312912Sartem gboolean ret;
43322912Sartem DBusError error;
43332912Sartem char *server_addr;
43342912Sartem
43352912Sartem ret = FALSE;
43362912Sartem
43372912Sartem /* setup a server listening on a socket so we can do point to point
43382912Sartem * connections for programs spawned by hald
43392912Sartem */
43402912Sartem dbus_error_init (&error);
43412912Sartem if ((local_server = dbus_server_listen (HALD_DBUS_ADDRESS, &error)) == NULL) {
43422912Sartem HAL_ERROR (("Cannot create D-BUS server"));
43432912Sartem goto out;
43442912Sartem }
43452912Sartem server_addr = dbus_server_get_address (local_server);
43462912Sartem HAL_INFO (("local server is listening at %s", server_addr));
43472912Sartem dbus_free (server_addr);
43482912Sartem dbus_server_setup_with_g_main (local_server, NULL);
43492912Sartem dbus_server_set_new_connection_function (local_server, local_server_handle_connection, NULL, NULL);
43502912Sartem
43512912Sartem ret = TRUE;
43522912Sartem
43532912Sartem out:
43542912Sartem return ret;
43552912Sartem }
43562912Sartem
43572912Sartem gboolean
hald_dbus_init(void)43582912Sartem hald_dbus_init (void)
43592912Sartem {
43602912Sartem DBusError dbus_error;
43612912Sartem
43622912Sartem HAL_INFO (("entering"));
43632912Sartem
43642912Sartem dbus_connection_set_change_sigpipe (TRUE);
43652912Sartem
43662912Sartem dbus_error_init (&dbus_error);
43672912Sartem dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error);
43682912Sartem if (dbus_connection == NULL) {
43692912Sartem HAL_ERROR (("dbus_bus_get(): %s", dbus_error.message));
43702912Sartem return FALSE;
43712912Sartem }
43722912Sartem
43732912Sartem dbus_connection_setup_with_g_main (dbus_connection, NULL);
43742912Sartem dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
43752912Sartem
43762912Sartem dbus_bus_request_name (dbus_connection, "org.freedesktop.Hal",
43772912Sartem 0, &dbus_error);
43782912Sartem if (dbus_error_is_set (&dbus_error)) {
43792912Sartem HAL_ERROR (("dbus_bus_request_name(): %s",
43802912Sartem dbus_error.message));
43812912Sartem return FALSE;
43822912Sartem }
43832912Sartem
43842912Sartem dbus_connection_add_filter (dbus_connection, hald_dbus_filter_function, NULL, NULL);
43852912Sartem
43862912Sartem dbus_bus_add_match (dbus_connection,
43872912Sartem "type='signal'"
43882912Sartem ",interface='"DBUS_INTERFACE_DBUS"'"
43892912Sartem ",sender='"DBUS_SERVICE_DBUS"'"
43902912Sartem ",member='NameOwnerChanged'",
43912912Sartem NULL);
43922912Sartem
43932912Sartem return TRUE;
43942912Sartem }
43952912Sartem
43962912Sartem /** @} */
4397