xref: /onnv-gate/usr/src/lib/hal/libhal/common/libhal.c (revision 11992:497d0af7535c)
12912Sartem /***************************************************************************
22912Sartem  * CVSID: $Id$
32912Sartem  *
42912Sartem  * libhal.c : HAL daemon C convenience library
52912Sartem  *
62912Sartem  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
76293Sartem  * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor@codethink.co.uk>
82912Sartem  *
92912Sartem  * Licensed under the Academic Free License version 2.1
102912Sartem  *
112912Sartem  * This program is free software; you can redistribute it and/or modify
122912Sartem  * it under the terms of the GNU General Public License as published by
132912Sartem  * the Free Software Foundation; either version 2 of the License, or
142912Sartem  * (at your option) any later version.
152912Sartem  *
162912Sartem  * This program is distributed in the hope that it will be useful,
172912Sartem  * but WITHOUT ANY WARRANTY; without even the implied warranty of
182912Sartem  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
192912Sartem  * GNU General Public License for more details.
202912Sartem  *
212912Sartem  * You should have received a copy of the GNU General Public License
222912Sartem  * along with this program; if not, write to the Free Software
232912Sartem  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA
242912Sartem  *
252912Sartem  **************************************************************************/
262912Sartem 
272912Sartem #ifdef HAVE_CONFIG_H
282912Sartem #  include <config.h>
292912Sartem #endif
302912Sartem 
312912Sartem #include <stdio.h>
322912Sartem #include <stdlib.h>
332912Sartem #include <string.h>
342912Sartem #include <dbus/dbus.h>
352912Sartem 
362912Sartem #include "libhal.h"
372912Sartem 
382912Sartem #ifdef ENABLE_NLS
392912Sartem # include <libintl.h>
402912Sartem # define _(String) dgettext (GETTEXT_PACKAGE, String)
412912Sartem # ifdef gettext_noop
422912Sartem #   define N_(String) gettext_noop (String)
432912Sartem # else
442912Sartem #   define N_(String) (String)
452912Sartem # endif
462912Sartem #else
472912Sartem /* Stubs that do something close enough.  */
482912Sartem # define textdomain(String) (String)
492912Sartem # define gettext(String) (String)
502912Sartem # define dgettext(Domain,Message) (Message)
512912Sartem # define dcgettext(Domain,Message,Type) (Message)
522912Sartem # define bindtextdomain(Domain,Directory) (Domain)
532912Sartem # define _(String)
542912Sartem # define N_(String) (String)
552912Sartem #endif
562912Sartem 
576293Sartem /**
586293Sartem  * LIBHAL_CHECK_PARAM_VALID:
596293Sartem  * @_param_: the prameter to check for
606293Sartem  * @_name_:  the name of the prameter (for debug output)
616293Sartem  * @_ret_:   what to use for return value if the prameter is NULL
626293Sartem  *
636293Sartem  * Handy macro for checking whether a parameter is valid and not NULL.
646293Sartem  */
656293Sartem #define LIBHAL_CHECK_PARAM_VALID(_param_,_name_,_ret_)				\
666293Sartem 	do {									\
676293Sartem 		if (_param_ == NULL) {						\
686293Sartem 			fprintf (stderr,					\
696293Sartem 				 "%s %d : invalid paramater. %s is NULL.\n",  	\
706293Sartem 				 __FILE__, __LINE__, _name_);	 		\
716293Sartem 			return _ret_;						\
726293Sartem 		}								\
736293Sartem 	} while(0)
746293Sartem 
756293Sartem 
762912Sartem static char **libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements);
772912Sartem 
782912Sartem static dbus_bool_t libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter);
792912Sartem 
802912Sartem 
812912Sartem 
822912Sartem /**
832912Sartem  * libhal_free_string_array:
842912Sartem  * @str_array: the array to be freed
852912Sartem  *
862912Sartem  * Frees a NULL-terminated array of strings. If passed NULL, does nothing.
872912Sartem  */
882912Sartem void
libhal_free_string_array(char ** str_array)892912Sartem libhal_free_string_array (char **str_array)
902912Sartem {
912912Sartem 	if (str_array != NULL) {
922912Sartem 		int i;
932912Sartem 
942912Sartem 		for (i = 0; str_array[i] != NULL; i++) {
952912Sartem 			free (str_array[i]);
962912Sartem 			str_array[i] = NULL;
972912Sartem 		}
982912Sartem 		free (str_array);
992912Sartem 		str_array = NULL;
1002912Sartem 	}
1012912Sartem }
1022912Sartem 
1032912Sartem 
1042912Sartem /**
1052912Sartem  * libhal_get_string_array_from_iter:
1062912Sartem  * @iter: the message iterator to extract the strings from
1072912Sartem  * @num_elements: pointer to an integer where to store number of elements (can be NULL)
1082912Sartem  *
1092912Sartem  * Creates a NULL terminated array of strings from a dbus message iterator.
1102912Sartem  *
1112912Sartem  * Returns: pointer to the string array
1122912Sartem  */
1132912Sartem static char **
libhal_get_string_array_from_iter(DBusMessageIter * iter,int * num_elements)1142912Sartem libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements)
1152912Sartem {
1162912Sartem 	int count;
1172912Sartem 	char **buffer;
1182912Sartem 
1192912Sartem 	count = 0;
1202912Sartem 	buffer = (char **)malloc (sizeof (char *) * 8);
1212912Sartem 
1222912Sartem 	if (buffer == NULL)
1232912Sartem 		goto oom;
1242912Sartem 
1252912Sartem 	buffer[0] = NULL;
1262912Sartem 	while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING) {
1272912Sartem 		const char *value;
1282912Sartem 		char *str;
1292912Sartem 
1302912Sartem 		if ((count % 8) == 0 && count != 0) {
1312912Sartem 			buffer = realloc (buffer, sizeof (char *) * (count + 8));
1322912Sartem 			if (buffer == NULL)
1332912Sartem 				goto oom;
1342912Sartem 		}
1352912Sartem 
1362912Sartem 		dbus_message_iter_get_basic (iter, &value);
1372912Sartem 		str = strdup (value);
1382912Sartem 		if (str == NULL)
1392912Sartem 			goto oom;
1402912Sartem 
1412912Sartem 		buffer[count] = str;
1422912Sartem 
1432912Sartem 		dbus_message_iter_next(iter);
1442912Sartem 		count++;
1452912Sartem 	}
1462912Sartem 
1472912Sartem 	if ((count % 8) == 0) {
1482912Sartem 		buffer = realloc (buffer, sizeof (char *) * (count + 1));
1492912Sartem 		if (buffer == NULL)
1502912Sartem 			goto oom;
1512912Sartem 	}
1522912Sartem 
1532912Sartem 	buffer[count] = NULL;
1542912Sartem 	if (num_elements != NULL)
1552912Sartem 		*num_elements = count;
1562912Sartem 	return buffer;
1572912Sartem 
1582912Sartem oom:
1592912Sartem 	fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
1602912Sartem 	return NULL;
1612912Sartem 
1622912Sartem }
1632912Sartem 
1642912Sartem /**
1652912Sartem  * libhal_free_string:
1662912Sartem  * @str: the nul-terminated sting to free
1672912Sartem  *
1682912Sartem  * Used to free strings returned by libhal.
1692912Sartem  */
1702912Sartem void
libhal_free_string(char * str)1712912Sartem libhal_free_string (char *str)
1722912Sartem {
1732912Sartem 	if (str != NULL) {
1742912Sartem 		free (str);
1752912Sartem 		str = NULL;
1762912Sartem 	}
1772912Sartem }
1782912Sartem 
1792912Sartem 
1802912Sartem /**
1812912Sartem  * LibHalPropertySet:
1822912Sartem  *
1832912Sartem  * Represents a set of properties. Opaque; use the
1842912Sartem  * libhal_property_set_*() family of functions to access it.
1852912Sartem  */
1862912Sartem struct LibHalPropertySet_s {
1872912Sartem 	unsigned int num_properties; /**< Number of properties in set */
1882912Sartem 	LibHalProperty *properties_head;
1892912Sartem 				     /**< Pointer to first property or NULL
1902912Sartem 				      *	  if there are no properties */
1912912Sartem };
1922912Sartem 
1932912Sartem /**
1942912Sartem  * LibHalProperty:
1952912Sartem  *
1962912Sartem  * Represents a property. Opaque.
1972912Sartem  */
1982912Sartem struct LibHalProperty_s {
1992912Sartem 	int type;		     /**< Type of property */
2002912Sartem 	char *key;		     /**< ASCII string */
2012912Sartem 
2022912Sartem 	/** Possible values of the property */
2032912Sartem 	union {
2042912Sartem 		char *str_value;     /**< UTF-8 zero-terminated string */
2052912Sartem 		dbus_int32_t int_value;
2062912Sartem 				     /**< 32-bit signed integer */
2072912Sartem 		dbus_uint64_t uint64_value;
2082912Sartem 				     /**< 64-bit unsigned integer */
2092912Sartem 		double double_value; /**< IEEE754 double precision float */
2102912Sartem 		dbus_bool_t bool_value;
2112912Sartem 				     /**< Truth value */
2122912Sartem 
2132912Sartem 		char **strlist_value; /**< List of UTF-8 zero-terminated strings */
2142912Sartem 	} v;
2152912Sartem 
2162912Sartem 	LibHalProperty *next;	     /**< Next property or NULL if this is
2172912Sartem 				      *	  the last */
2182912Sartem };
2192912Sartem 
2202912Sartem /**
2212912Sartem  * LibHalContext:
2222912Sartem  *
2232912Sartem  * Context for connection to the HAL daemon. Opaque, use the
2242912Sartem  * libhal_ctx_*() family of functions to access it.
2252912Sartem  */
2262912Sartem struct LibHalContext_s {
2272912Sartem 	DBusConnection *connection;           /**< D-BUS connection */
2282912Sartem 	dbus_bool_t is_initialized;           /**< Are we initialised */
2292912Sartem 	dbus_bool_t is_shutdown;              /**< Have we been shutdown */
2302912Sartem 	dbus_bool_t cache_enabled;            /**< Is the cache enabled */
2312912Sartem 	dbus_bool_t is_direct;                /**< Whether the connection to hald is direct */
2322912Sartem 
2332912Sartem 	/** Device added */
2342912Sartem 	LibHalDeviceAdded device_added;
2352912Sartem 
2362912Sartem 	/** Device removed */
2372912Sartem 	LibHalDeviceRemoved device_removed;
2382912Sartem 
2392912Sartem 	/** Device got a new capability */
2402912Sartem 	LibHalDeviceNewCapability device_new_capability;
2412912Sartem 
2422912Sartem 	/** Device got a new capability */
2432912Sartem 	LibHalDeviceLostCapability device_lost_capability;
2442912Sartem 
2452912Sartem 	/** A property of a device changed  */
2462912Sartem 	LibHalDevicePropertyModified device_property_modified;
2472912Sartem 
2482912Sartem 	/** A non-continous event on the device occured  */
2492912Sartem 	LibHalDeviceCondition device_condition;
2502912Sartem 
2512912Sartem 	void *user_data;                      /**< User data */
2522912Sartem };
2532912Sartem 
2542912Sartem /**
2552912Sartem  * libhal_ctx_set_user_data:
2562912Sartem  * @ctx: the context for the connection to hald
2572912Sartem  * @user_data: user data
2582912Sartem  *
2592912Sartem  * Set user data for the context.
2602912Sartem  *
2612912Sartem  * Returns: TRUE if user data was successfully set, FALSE if otherwise
2622912Sartem  */
2632912Sartem dbus_bool_t
libhal_ctx_set_user_data(LibHalContext * ctx,void * user_data)2642912Sartem libhal_ctx_set_user_data(LibHalContext *ctx, void *user_data)
2652912Sartem {
2662912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2672912Sartem 	ctx->user_data = user_data;
2682912Sartem 	return TRUE;
2692912Sartem }
2702912Sartem 
2712912Sartem /**
2722912Sartem  * libhal_ctx_get_user_data:
2732912Sartem  * @ctx: the context for the connection to hald
2742912Sartem  *
2752912Sartem  * Get user data for the context.
2762912Sartem  *
2772912Sartem  * Returns: opaque pointer stored through libhal_ctx_set_user_data() or NULL if not set.
2782912Sartem  */
2792912Sartem void*
libhal_ctx_get_user_data(LibHalContext * ctx)2802912Sartem libhal_ctx_get_user_data(LibHalContext *ctx)
2812912Sartem {
2822912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2832912Sartem 	return ctx->user_data;
2842912Sartem }
2852912Sartem 
2862912Sartem 
2872912Sartem /**
2882912Sartem  * libhal_property_fill_value_from_variant:
2892912Sartem  * @p: the property to fill in
2902912Sartem  * @var_iter: variant iterator to extract the value from
2912912Sartem  *
2922912Sartem  * Fills in the value for the LibHalProperty given a variant iterator.
2932912Sartem  *
2942912Sartem  * Returns: Whether the value was put in.
2952912Sartem  */
2962912Sartem static dbus_bool_t
libhal_property_fill_value_from_variant(LibHalProperty * p,DBusMessageIter * var_iter)2972912Sartem libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter)
2982912Sartem {
2992912Sartem 	DBusMessageIter iter_array;
3002912Sartem 	switch (p->type) {
3012912Sartem 	case DBUS_TYPE_ARRAY:
3022912Sartem 		if (dbus_message_iter_get_element_type (var_iter) != DBUS_TYPE_STRING)
3032912Sartem 			return FALSE;
3042912Sartem 
3052912Sartem 		dbus_message_iter_recurse (var_iter, &iter_array);
3062912Sartem 		p->v.strlist_value = libhal_get_string_array_from_iter (&iter_array, NULL);
3072912Sartem 
3082912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_STRLIST;
3092912Sartem 
3102912Sartem 		break;
3112912Sartem 	case DBUS_TYPE_STRING:
3122912Sartem 	{
3132912Sartem 		const char *v;
3142912Sartem 
3152912Sartem 		dbus_message_iter_get_basic (var_iter, &v);
3162912Sartem 
3172912Sartem 		p->v.str_value = strdup (v);
3182912Sartem 		if (p->v.str_value == NULL)
3192912Sartem 			return FALSE;
3202912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_STRING;
3212912Sartem 
3222912Sartem 		break;
3232912Sartem 	}
3242912Sartem 	case DBUS_TYPE_INT32:
3252912Sartem 	{
3262912Sartem 		dbus_int32_t v;
3272912Sartem 
3282912Sartem 		dbus_message_iter_get_basic (var_iter, &v);
3292912Sartem 
3302912Sartem 		p->v.int_value = v;
3312912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_INT32;
3322912Sartem 
3332912Sartem 		break;
3342912Sartem 	}
3352912Sartem 	case DBUS_TYPE_UINT64:
3362912Sartem 	{
3372912Sartem 		dbus_uint64_t v;
3382912Sartem 
3392912Sartem 		dbus_message_iter_get_basic (var_iter, &v);
3402912Sartem 
3412912Sartem 		p->v.uint64_value = v;
3422912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_UINT64;
3432912Sartem 
3442912Sartem 		break;
3452912Sartem 	}
3462912Sartem 	case DBUS_TYPE_DOUBLE:
3472912Sartem 	{
3482912Sartem 		double v;
3492912Sartem 
3502912Sartem 		dbus_message_iter_get_basic (var_iter, &v);
3512912Sartem 
3522912Sartem 		p->v.double_value = v;
3532912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_DOUBLE;
3542912Sartem 
3552912Sartem 		break;
3562912Sartem 	}
3572912Sartem 	case DBUS_TYPE_BOOLEAN:
3582912Sartem 	{
3592912Sartem 		double v;
3602912Sartem 
3612912Sartem 		dbus_message_iter_get_basic (var_iter, &v);
3622912Sartem 
3632912Sartem 		p->v.double_value = v;
3642912Sartem 		p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
3652912Sartem 
3662912Sartem 		break;
3672912Sartem 	}
3682912Sartem 	default:
3692912Sartem 		/** @todo  report error */
3702912Sartem 		break;
3712912Sartem 	}
3722912Sartem 
3732912Sartem 	return TRUE;
3742912Sartem }
3752912Sartem 
3762912Sartem /**
3772912Sartem  * libhal_device_get_all_properties:
3782912Sartem  * @ctx: the context for the connection to hald
3792912Sartem  * @udi: the Unique id of device
3802912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
3812912Sartem  *
3822912Sartem  * Retrieve all the properties on a device.
3832912Sartem  *
3842912Sartem  * Returns: An object represent all properties. Must be freed with libhal_free_property_set().
3852912Sartem  */
3862912Sartem LibHalPropertySet *
libhal_device_get_all_properties(LibHalContext * ctx,const char * udi,DBusError * error)3872912Sartem libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error)
3882912Sartem {
3892912Sartem 	DBusMessage *message;
3902912Sartem 	DBusMessage *reply;
3912912Sartem 	DBusMessageIter reply_iter;
3922912Sartem 	DBusMessageIter dict_iter;
3932912Sartem 	LibHalPropertySet *result;
3942912Sartem 	LibHalProperty *p_last;
3952912Sartem 	DBusError _error;
3962912Sartem 
3972912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
3982912Sartem 
3992912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
4002912Sartem 						"org.freedesktop.Hal.Device",
4012912Sartem 						"GetAllProperties");
4022912Sartem 
4032912Sartem 	if (message == NULL) {
4042912Sartem 		fprintf (stderr,
4052912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
4062912Sartem 			 __FILE__, __LINE__);
4072912Sartem 		return NULL;
4082912Sartem 	}
4092912Sartem 
4102912Sartem 	dbus_error_init (&_error);
4112912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
4122912Sartem 							   message, -1,
4132912Sartem 							   &_error);
4142912Sartem 
4152912Sartem 	dbus_move_error (&_error, error);
4162912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
4172912Sartem 		fprintf (stderr,
4182912Sartem 			 "%s %d : %s\n",
4192912Sartem 			 __FILE__, __LINE__, error->message);
4202912Sartem 
4212912Sartem 		dbus_message_unref (message);
4222912Sartem 		return NULL;
4232912Sartem 	}
4242912Sartem 
4252912Sartem 	if (reply == NULL) {
4262912Sartem 		dbus_message_unref (message);
4272912Sartem 		return NULL;
4282912Sartem 	}
4292912Sartem 
4302912Sartem 	dbus_message_iter_init (reply, &reply_iter);
4312912Sartem 
4322912Sartem 	result = malloc (sizeof (LibHalPropertySet));
4332912Sartem 	if (result == NULL)
4342912Sartem 		goto oom;
4352912Sartem /*
4362912Sartem     result->properties = malloc(sizeof(LibHalProperty)*result->num_properties);
4372912Sartem     if( result->properties==NULL )
4382912Sartem     {
4392912Sartem     /// @todo  cleanup
4402912Sartem 	return NULL;
4412912Sartem     }
4422912Sartem */
4432912Sartem 
4442912Sartem 	result->properties_head = NULL;
4452912Sartem 	result->num_properties = 0;
4462912Sartem 
4472912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY  &&
4482912Sartem 	    dbus_message_iter_get_element_type (&reply_iter) != DBUS_TYPE_DICT_ENTRY) {
4492912Sartem 		fprintf (stderr, "%s %d : error, expecting an array of dict entries\n",
4502912Sartem 			 __FILE__, __LINE__);
4512912Sartem 		dbus_message_unref (message);
4522912Sartem 		dbus_message_unref (reply);
4532912Sartem 		return NULL;
4542912Sartem 	}
4552912Sartem 
4562912Sartem 	dbus_message_iter_recurse (&reply_iter, &dict_iter);
4572912Sartem 
4582912Sartem 	p_last = NULL;
4592912Sartem 
4602912Sartem 	while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
4612912Sartem 	{
4622912Sartem 		DBusMessageIter dict_entry_iter, var_iter;
4632912Sartem 		const char *key;
4642912Sartem 		LibHalProperty *p;
4652912Sartem 
4662912Sartem 		dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
4672912Sartem 
4682912Sartem 		dbus_message_iter_get_basic (&dict_entry_iter, &key);
4692912Sartem 
4702912Sartem 		p = malloc (sizeof (LibHalProperty));
4712912Sartem 		if (p == NULL)
4722912Sartem 			goto oom;
4732912Sartem 
4742912Sartem 		p->next = NULL;
4752912Sartem 
4762912Sartem 		if (result->num_properties == 0)
4772912Sartem 			result->properties_head = p;
4782912Sartem 
4792912Sartem 		if (p_last != NULL)
4802912Sartem 			p_last->next = p;
4812912Sartem 
4822912Sartem 		p_last = p;
4832912Sartem 
4842912Sartem 		p->key = strdup (key);
4852912Sartem 		if (p->key == NULL)
4862912Sartem 			goto oom;
4872912Sartem 
4882912Sartem 		dbus_message_iter_next (&dict_entry_iter);
4892912Sartem 
4902912Sartem 		dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
4912912Sartem 
4922912Sartem 
4932912Sartem 		p->type = dbus_message_iter_get_arg_type (&var_iter);
4942912Sartem 
4952912Sartem 		result->num_properties++;
4962912Sartem 
4972912Sartem 		if(!libhal_property_fill_value_from_variant (p, &var_iter))
4982912Sartem 			goto oom;
4992912Sartem 
5002912Sartem 		dbus_message_iter_next (&dict_iter);
5012912Sartem 	}
5022912Sartem 
5032912Sartem 	dbus_message_unref (message);
5042912Sartem 	dbus_message_unref (reply);
5052912Sartem 
5062912Sartem 	return result;
5072912Sartem 
5082912Sartem oom:
5092912Sartem 	fprintf (stderr,
5102912Sartem 		"%s %d : error allocating memory\n",
5112912Sartem 		 __FILE__, __LINE__);
5122912Sartem 		/** @todo FIXME cleanup */
5132912Sartem 	return NULL;
5142912Sartem }
5152912Sartem 
5162912Sartem /**
5172912Sartem  * libhal_free_property_set:
5182912Sartem  * @set: property-set to free
5192912Sartem  *
5202912Sartem  * Free a property set earlier obtained with libhal_device_get_all_properties().
5212912Sartem  */
5222912Sartem void
libhal_free_property_set(LibHalPropertySet * set)5232912Sartem libhal_free_property_set (LibHalPropertySet * set)
5242912Sartem {
5252912Sartem 	LibHalProperty *p;
5262912Sartem 	LibHalProperty *q;
5272912Sartem 
5282912Sartem 	if (set == NULL)
5292912Sartem 		return;
5302912Sartem 
5312912Sartem 	for (p = set->properties_head; p != NULL; p = q) {
5322912Sartem 		free (p->key);
5332912Sartem 		if (p->type == DBUS_TYPE_STRING)
5342912Sartem 			free (p->v.str_value);
5352912Sartem 		if (p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
5362912Sartem 			libhal_free_string_array (p->v.strlist_value);
5372912Sartem 		q = p->next;
5382912Sartem 		free (p);
5392912Sartem 	}
5402912Sartem 	free (set);
5412912Sartem }
5422912Sartem 
5432912Sartem /**
5442912Sartem  * libhal_property_set_get_num_elems:
5452912Sartem  * @set: property set to consider
5462912Sartem  *
5472912Sartem  * Get the number of properties in a property set.
5482912Sartem  *
5492912Sartem  * Returns: number of properties in given property set
5502912Sartem  */
5512912Sartem unsigned int
libhal_property_set_get_num_elems(LibHalPropertySet * set)5522912Sartem libhal_property_set_get_num_elems (LibHalPropertySet *set)
5532912Sartem {
5542912Sartem 	unsigned int num_elems;
5552912Sartem 	LibHalProperty *p;
5562912Sartem 
5572912Sartem 	if (set == NULL)
5582912Sartem 		return 0;
5592912Sartem 
5602912Sartem 	num_elems = 0;
5612912Sartem 	for (p = set->properties_head; p != NULL; p = p->next)
5622912Sartem 		num_elems++;
5632912Sartem 
5642912Sartem 	return num_elems;
5652912Sartem }
5662912Sartem 
5676293Sartem static LibHalProperty *
property_set_lookup(const LibHalPropertySet * set,const char * key)5686293Sartem property_set_lookup (const LibHalPropertySet *set, const char *key)
5696293Sartem {
5706293Sartem 	LibHalProperty *p;
5716293Sartem 
5726293Sartem 	LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
5736293Sartem 	LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
5746293Sartem 
5756293Sartem 	for (p = set->properties_head; p != NULL; p = p->next)
5766293Sartem 		if (strcmp (key, p->key) == 0)
5776293Sartem 			return p;
5786293Sartem 
5796293Sartem 	return NULL;
5806293Sartem }
5816293Sartem 
5826293Sartem /**
5836293Sartem  * libhal_ps_get_type:
5846293Sartem  * @set: property set
5856293Sartem  * @key: name of property to inspect
5866293Sartem  *
5876293Sartem  * Get the type of a given property.
5886293Sartem  *
5896293Sartem  * Returns: the #LibHalPropertyType of the given property,
5906293Sartem  * LIBHAL_PROPERTY_TYPE_INVALID if property is not in the set
5916293Sartem  */
5926293Sartem LibHalPropertyType
libhal_ps_get_type(const LibHalPropertySet * set,const char * key)5936293Sartem libhal_ps_get_type (const LibHalPropertySet *set, const char *key)
5946293Sartem {
5956293Sartem 	LibHalProperty *p = property_set_lookup (set, key);
5966293Sartem 
5976293Sartem 	LIBHAL_CHECK_PARAM_VALID(set, "*set", LIBHAL_PROPERTY_TYPE_INVALID);
5986293Sartem 	LIBHAL_CHECK_PARAM_VALID(key, "*key", LIBHAL_PROPERTY_TYPE_INVALID);
5996293Sartem 
6006293Sartem 	p = property_set_lookup (set, key);
6016293Sartem 	if (p) return p->type;
6026293Sartem 	else return LIBHAL_PROPERTY_TYPE_INVALID;
6036293Sartem }
6046293Sartem 
6056293Sartem /**
6066293Sartem  * libhal_ps_get_string:
6076293Sartem  * @set: property set
6086293Sartem  * @key: name of property to inspect
6096293Sartem  *
6106293Sartem  * Get the value of a property of type string.
6116293Sartem  *
6126293Sartem  * Returns: UTF8 nul-terminated string. This pointer is only valid
6136293Sartem  * until libhal_free_property_set() is invoked on the property set
6146293Sartem  * this property belongs to. NULL if property is not in the set or not a string
6156293Sartem  */
6166293Sartem const char *
libhal_ps_get_string(const LibHalPropertySet * set,const char * key)6176293Sartem libhal_ps_get_string  (const LibHalPropertySet *set, const char *key)
6186293Sartem {
6196293Sartem 	LibHalProperty *p;
6206293Sartem 
6216293Sartem 	LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
6226293Sartem 	LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
6236293Sartem 
6246293Sartem 	p = property_set_lookup (set, key);
6256293Sartem 	if (p && p->type == LIBHAL_PROPERTY_TYPE_STRING)
6266293Sartem 		return p->v.str_value;
6276293Sartem 	else return NULL;
6286293Sartem }
6296293Sartem 
6306293Sartem /**
6316293Sartem  * libhal_ps_get_int:
6326293Sartem  * @set: property set
6336293Sartem  * @key: name of property to inspect
6346293Sartem  *
6356293Sartem  * Get the value of a property of type signed integer.
6366293Sartem  *
6376293Sartem  * Returns: property value (32-bit signed integer)
6386293Sartem  */
6396293Sartem dbus_int32_t
libhal_ps_get_int32(const LibHalPropertySet * set,const char * key)6406293Sartem libhal_ps_get_int32 (const LibHalPropertySet *set, const char *key)
6416293Sartem {
6426293Sartem 	LibHalProperty *p;
6436293Sartem 
6446293Sartem 	LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
6456293Sartem 	LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
6466293Sartem 
6476293Sartem 	p = property_set_lookup (set, key);
6486293Sartem 	if (p && p->type == LIBHAL_PROPERTY_TYPE_INT32)
6496293Sartem 		return p->v.int_value;
6506293Sartem 	else return 0;
6516293Sartem }
6526293Sartem 
6536293Sartem /**
6546293Sartem  * libhal_ps_get_uint64:
6556293Sartem  * @set: property set
6566293Sartem  * @key: name of property to inspect
6576293Sartem  *
6586293Sartem  * Get the value of a property of type unsigned integer.
6596293Sartem  *
6606293Sartem  * Returns: property value (64-bit unsigned integer)
6616293Sartem  */
6626293Sartem dbus_uint64_t
libhal_ps_get_uint64(const LibHalPropertySet * set,const char * key)6636293Sartem libhal_ps_get_uint64 (const LibHalPropertySet *set, const char *key)
6646293Sartem {
6656293Sartem 	LibHalProperty *p;
6666293Sartem 
6676293Sartem 	LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
6686293Sartem 	LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
6696293Sartem 
6706293Sartem 	p = property_set_lookup (set, key);
6716293Sartem 	if (p && p->type == LIBHAL_PROPERTY_TYPE_UINT64)
6726293Sartem 		return p->v.uint64_value;
6736293Sartem 	else return 0;
6746293Sartem }
6756293Sartem 
6766293Sartem /**
6776293Sartem  * libhal_ps_get_double:
6786293Sartem  * @set: property set
6796293Sartem  * @key: name of property to inspect
6806293Sartem  *
6816293Sartem  * Get the value of a property of type double.
6826293Sartem  *
6836293Sartem  * Returns: property value (IEEE754 double precision float)
6846293Sartem  */
6856293Sartem double
libhal_ps_get_double(const LibHalPropertySet * set,const char * key)6866293Sartem libhal_ps_get_double (const LibHalPropertySet *set, const char *key)
6876293Sartem {
6886293Sartem 	LibHalProperty *p;
6896293Sartem 
6906293Sartem 	LIBHAL_CHECK_PARAM_VALID(set, "*set", 0.0);
6916293Sartem 	LIBHAL_CHECK_PARAM_VALID(key, "*key", 0.0);
6926293Sartem 
6936293Sartem 	p = property_set_lookup (set, key);
6946293Sartem 	if (p && p->type == LIBHAL_PROPERTY_TYPE_DOUBLE)
6956293Sartem 		return p->v.double_value;
6966293Sartem 	else return 0.0;
6976293Sartem }
6986293Sartem 
6996293Sartem /**
7006293Sartem  * libhal_ps_get_bool:
7016293Sartem  * @set: property set
7026293Sartem  * @key: name of property to inspect
7036293Sartem  *
7046293Sartem  * Get the value of a property of type bool.
7056293Sartem  *
7066293Sartem  * Returns: property value (bool)
7076293Sartem  */
7086293Sartem dbus_bool_t
libhal_ps_get_bool(const LibHalPropertySet * set,const char * key)7096293Sartem libhal_ps_get_bool (const LibHalPropertySet *set, const char *key)
7106293Sartem {
7116293Sartem 	LibHalProperty *p;
7126293Sartem 
7136293Sartem 	LIBHAL_CHECK_PARAM_VALID(set, "*set", FALSE);
7146293Sartem 	LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
7156293Sartem 
7166293Sartem 	p = property_set_lookup (set, key);
7176293Sartem 	if (p && p->type == LIBHAL_PROPERTY_TYPE_BOOLEAN)
7186293Sartem 		return p->v.bool_value;
7196293Sartem 	else return FALSE;
7206293Sartem }
7216293Sartem 
7226293Sartem /**
7236293Sartem  * libhal_ps_get_strlist:
7246293Sartem  * @set: property set
7256293Sartem  * @key: name of property to inspect
7266293Sartem  *
7276293Sartem  * Get the value of a property of type string list.
7286293Sartem  *
7296293Sartem  * Returns: pointer to array of strings, this is owned by the property set
7306293Sartem  */
7316293Sartem const char *const *
libhal_ps_get_strlist(const LibHalPropertySet * set,const char * key)7326293Sartem libhal_ps_get_strlist (const LibHalPropertySet *set, const char *key)
7336293Sartem {
7346293Sartem 	LibHalProperty *p;
7356293Sartem 
7366293Sartem 	LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
7376293Sartem 	LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
7386293Sartem 
7396293Sartem 	p = property_set_lookup (set, key);
7406293Sartem 	if (p && p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
7416293Sartem 		return (const char *const *) p->v.strlist_value;
7426293Sartem 	else return NULL;
7436293Sartem }
7446293Sartem 
7452912Sartem 
7462912Sartem /**
7472912Sartem  * libhal_psi_init:
7482912Sartem  * @iter: iterator object
7492912Sartem  * @set: property set to iterate over
7502912Sartem  *
7512912Sartem  * Initialize a property set iterator.
7522912Sartem  *
7532912Sartem  */
7542912Sartem void
libhal_psi_init(LibHalPropertySetIterator * iter,LibHalPropertySet * set)7552912Sartem libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
7562912Sartem {
7572912Sartem 	if (set == NULL)
7582912Sartem 		return;
7592912Sartem 
7602912Sartem 	iter->set = set;
7612912Sartem 	iter->idx = 0;
7622912Sartem 	iter->cur_prop = set->properties_head;
7632912Sartem }
7642912Sartem 
7652912Sartem 
7662912Sartem /**
7672912Sartem  * libhal_psi_has_more:
7682912Sartem  * @iter: iterator object
7692912Sartem  *
7702912Sartem  * Determine whether there are more properties to iterate over.
7712912Sartem  *
7722912Sartem  * Returns: TRUE if there are more properties, FALSE otherwise.
7732912Sartem  */
7742912Sartem dbus_bool_t
libhal_psi_has_more(LibHalPropertySetIterator * iter)7752912Sartem libhal_psi_has_more (LibHalPropertySetIterator * iter)
7762912Sartem {
7772912Sartem 	return iter->idx < iter->set->num_properties;
7782912Sartem }
7792912Sartem 
7802912Sartem /**
7812912Sartem  * libhal_psi_next:
7822912Sartem  * @iter: iterator object
7832912Sartem  *
7842912Sartem  * Advance iterator to next property.
7852912Sartem  */
7862912Sartem void
libhal_psi_next(LibHalPropertySetIterator * iter)7872912Sartem libhal_psi_next (LibHalPropertySetIterator * iter)
7882912Sartem {
7892912Sartem 	iter->idx++;
7902912Sartem 	iter->cur_prop = iter->cur_prop->next;
7912912Sartem }
7922912Sartem 
7932912Sartem /**
7942912Sartem  * libhal_psi_get_type:
7952912Sartem  * @iter: iterator object
7962912Sartem  *
7972912Sartem  * Get type of property.
7982912Sartem  *
7992912Sartem  * Returns: the property type at the iterator's position
8002912Sartem  */
8012912Sartem LibHalPropertyType
libhal_psi_get_type(LibHalPropertySetIterator * iter)8022912Sartem libhal_psi_get_type (LibHalPropertySetIterator * iter)
8032912Sartem {
8042912Sartem 	return iter->cur_prop->type;
8052912Sartem }
8062912Sartem 
8072912Sartem /**
8082912Sartem  * libhal_psi_get_key:
8092912Sartem  * @iter: iterator object
8102912Sartem  *
8112912Sartem  * Get the key of a property.
8122912Sartem  *
8132912Sartem  * Returns: ASCII nul-terminated string. This pointer is only valid
8142912Sartem  * until libhal_free_property_set() is invoked on the property set
8152912Sartem  * this property belongs to.
8162912Sartem  */
8172912Sartem char *
libhal_psi_get_key(LibHalPropertySetIterator * iter)8182912Sartem libhal_psi_get_key (LibHalPropertySetIterator * iter)
8192912Sartem {
8202912Sartem 	return iter->cur_prop->key;
8212912Sartem }
8222912Sartem 
8232912Sartem /**
8242912Sartem  * libhal_psi_get_string:
8252912Sartem  * @iter: iterator object
8262912Sartem  *
8272912Sartem  * Get the value of a property of type string.
8282912Sartem  *
8292912Sartem  * Returns: UTF8 nul-terminated string. This pointer is only valid
8302912Sartem  * until libhal_free_property_set() is invoked on the property set
8312912Sartem  * this property belongs to.
8322912Sartem  */
8332912Sartem char *
libhal_psi_get_string(LibHalPropertySetIterator * iter)8342912Sartem libhal_psi_get_string (LibHalPropertySetIterator * iter)
8352912Sartem {
8362912Sartem 	return iter->cur_prop->v.str_value;
8372912Sartem }
8382912Sartem 
8392912Sartem /**
8402912Sartem  * libhal_psi_get_int:
8412912Sartem  * @iter: iterator object
8422912Sartem  *
8432912Sartem  * Get the value of a property of type signed integer.
8442912Sartem  *
8452912Sartem  * Returns: property value (32-bit signed integer)
8462912Sartem  */
8472912Sartem dbus_int32_t
libhal_psi_get_int(LibHalPropertySetIterator * iter)8482912Sartem libhal_psi_get_int (LibHalPropertySetIterator * iter)
8492912Sartem {
8502912Sartem 	return iter->cur_prop->v.int_value;
8512912Sartem }
8522912Sartem 
8532912Sartem /**
8542912Sartem  * libhal_psi_get_uint64:
8552912Sartem  * @iter: iterator object
8562912Sartem  *
8572912Sartem  * Get the value of a property of type unsigned integer.
8582912Sartem  *
8592912Sartem  * Returns: property value (64-bit unsigned integer)
8602912Sartem  */
8612912Sartem dbus_uint64_t
libhal_psi_get_uint64(LibHalPropertySetIterator * iter)8622912Sartem libhal_psi_get_uint64 (LibHalPropertySetIterator * iter)
8632912Sartem {
8642912Sartem 	return iter->cur_prop->v.uint64_value;
8652912Sartem }
8662912Sartem 
8672912Sartem /**
8682912Sartem  * libhal_psi_get_double:
8692912Sartem  * @iter: iterator object
8702912Sartem  *
8712912Sartem  * Get the value of a property of type double.
8722912Sartem  *
8732912Sartem  * Returns: property value (IEEE754 double precision float)
8742912Sartem  */
8752912Sartem double
libhal_psi_get_double(LibHalPropertySetIterator * iter)8762912Sartem libhal_psi_get_double (LibHalPropertySetIterator * iter)
8772912Sartem {
8782912Sartem 	return iter->cur_prop->v.double_value;
8792912Sartem }
8802912Sartem 
8812912Sartem /**
8822912Sartem  * libhal_psi_get_bool:
8832912Sartem  * @iter: iterator object
8842912Sartem  *
8852912Sartem  * Get the value of a property of type bool.
8862912Sartem  *
8872912Sartem  * Returns: property value (bool)
8882912Sartem  */
8892912Sartem dbus_bool_t
libhal_psi_get_bool(LibHalPropertySetIterator * iter)8902912Sartem libhal_psi_get_bool (LibHalPropertySetIterator * iter)
8912912Sartem {
8922912Sartem 	return iter->cur_prop->v.bool_value;
8932912Sartem }
8942912Sartem 
8952912Sartem /**
8962912Sartem  * libhal_psi_get_strlist:
8972912Sartem  * @iter: iterator object
8982912Sartem  *
8992912Sartem  * Get the value of a property of type string list.
9002912Sartem  *
9012912Sartem  * Returns: pointer to array of strings
9022912Sartem  */
9032912Sartem char **
libhal_psi_get_strlist(LibHalPropertySetIterator * iter)9042912Sartem libhal_psi_get_strlist (LibHalPropertySetIterator * iter)
9052912Sartem {
9062912Sartem 	return iter->cur_prop->v.strlist_value;
9072912Sartem }
9082912Sartem 
9092912Sartem 
9102912Sartem static DBusHandlerResult
filter_func(DBusConnection * connection,DBusMessage * message,void * user_data)9112912Sartem filter_func (DBusConnection * connection,
9122912Sartem 	     DBusMessage * message, void *user_data)
9132912Sartem {
9142912Sartem 	const char *object_path;
9152912Sartem 	DBusError error;
9162912Sartem 	LibHalContext *ctx = (LibHalContext *) user_data;
9172912Sartem 
9182912Sartem 	if (ctx->is_shutdown)
9192912Sartem 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
9202912Sartem 
9212912Sartem 	dbus_error_init (&error);
9222912Sartem 
9232912Sartem 	object_path = dbus_message_get_path (message);
9242912Sartem 
9252912Sartem 	/*printf("*** in filter_func, object_path=%s\n", object_path);*/
9262912Sartem 
9272912Sartem 	if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager",
9282912Sartem 				    "DeviceAdded")) {
9292912Sartem 		char *udi;
9302912Sartem 		if (dbus_message_get_args (message, &error,
9312912Sartem 					   DBUS_TYPE_STRING, &udi,
9322912Sartem 					   DBUS_TYPE_INVALID)) {
9332912Sartem 			if (ctx->device_added != NULL) {
9342912Sartem 				ctx->device_added (ctx, udi);
9352912Sartem 			}
9362912Sartem 		} else {
9372912Sartem 			LIBHAL_FREE_DBUS_ERROR(&error);
9382912Sartem 		}
9392912Sartem 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
9402912Sartem 	} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
9412912Sartem 		char *udi;
9422912Sartem 		if (dbus_message_get_args (message, &error,
9432912Sartem 					   DBUS_TYPE_STRING, &udi,
9442912Sartem 					   DBUS_TYPE_INVALID)) {
9452912Sartem 			if (ctx->device_removed != NULL) {
9462912Sartem 				ctx->device_removed (ctx, udi);
9472912Sartem 			}
9482912Sartem 		} else {
9492912Sartem 			LIBHAL_FREE_DBUS_ERROR(&error);
9502912Sartem 		}
9512912Sartem 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
9522912Sartem 	} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","NewCapability")) {
9532912Sartem 		char *udi;
9542912Sartem 		char *capability;
9552912Sartem 		if (dbus_message_get_args (message, &error,
9562912Sartem 					   DBUS_TYPE_STRING, &udi,
9572912Sartem 					   DBUS_TYPE_STRING, &capability,
9582912Sartem 					   DBUS_TYPE_INVALID)) {
9592912Sartem 			if (ctx->device_new_capability != NULL) {
9602912Sartem 				ctx->device_new_capability (ctx, udi, capability);
9612912Sartem 			}
9622912Sartem 		} else {
9632912Sartem 			LIBHAL_FREE_DBUS_ERROR(&error);
9642912Sartem 		}
9652912Sartem 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
9662912Sartem 	} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) {
9672912Sartem 		char *condition_name;
9682912Sartem 		char *condition_detail;
9692912Sartem 		if (dbus_message_get_args (message, &error,
9702912Sartem 					   DBUS_TYPE_STRING, &condition_name,
9712912Sartem 					   DBUS_TYPE_STRING, &condition_detail,
9722912Sartem 					   DBUS_TYPE_INVALID)) {
9732912Sartem 			if (ctx->device_condition != NULL) {
9742912Sartem 				ctx->device_condition (ctx, object_path, condition_name, condition_detail);
9752912Sartem 			}
9762912Sartem 		} else {
9772912Sartem 			LIBHAL_FREE_DBUS_ERROR(&error);
9782912Sartem 		}
9792912Sartem 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
9802912Sartem 	} else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) {
9812912Sartem 		if (ctx->device_property_modified != NULL) {
9822912Sartem 			int i;
9832912Sartem 			char *key;
9842912Sartem 			dbus_bool_t removed;
9852912Sartem 			dbus_bool_t added;
9862912Sartem 			int num_modifications;
9872912Sartem 			DBusMessageIter iter;
9882912Sartem 			DBusMessageIter iter_array;
9892912Sartem 
9902912Sartem 			dbus_message_iter_init (message, &iter);
9912912Sartem 			dbus_message_iter_get_basic (&iter, &num_modifications);
9922912Sartem 			dbus_message_iter_next (&iter);
9932912Sartem 
9942912Sartem 			dbus_message_iter_recurse (&iter, &iter_array);
9952912Sartem 
9962912Sartem 			for (i = 0; i < num_modifications; i++) {
9972912Sartem 				DBusMessageIter iter_struct;
9982912Sartem 
9992912Sartem 				dbus_message_iter_recurse (&iter_array, &iter_struct);
10002912Sartem 
10012912Sartem 				dbus_message_iter_get_basic (&iter_struct, &key);
10022912Sartem 				dbus_message_iter_next (&iter_struct);
10032912Sartem 				dbus_message_iter_get_basic (&iter_struct, &removed);
10042912Sartem 				dbus_message_iter_next (&iter_struct);
10052912Sartem 				dbus_message_iter_get_basic (&iter_struct, &added);
10062912Sartem 
10072912Sartem 				ctx->device_property_modified (ctx,
10082912Sartem 							       object_path,
10092912Sartem 							       key, removed,
10102912Sartem 							       added);
10112912Sartem 
10122912Sartem 				dbus_message_iter_next (&iter_array);
10132912Sartem 			}
10142912Sartem 
10152912Sartem 		}
10162912Sartem 		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
10172912Sartem 	}
10182912Sartem 
10192912Sartem 	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
10202912Sartem }
10212912Sartem 
10222912Sartem /* for i18n purposes */
10232912Sartem static dbus_bool_t libhal_already_initialized_once = FALSE;
10242912Sartem 
10252912Sartem 
10262912Sartem /**
10272912Sartem  * libhal_get_all_devices:
10282912Sartem  * @ctx: the context for the connection to hald
10292912Sartem  * @num_devices: the number of devices will be stored here
10302912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
10312912Sartem  *
10322912Sartem  * Get all devices in the Global Device List (GDL).
10332912Sartem  *
10342912Sartem  * Returns: An array of device identifiers terminated with NULL. It is
10352912Sartem  * the responsibility of the caller to free with
10362912Sartem  * libhal_free_string_array(). If an error occurs NULL is returned.
10372912Sartem  */
10382912Sartem char **
libhal_get_all_devices(LibHalContext * ctx,int * num_devices,DBusError * error)10392912Sartem libhal_get_all_devices (LibHalContext *ctx, int *num_devices, DBusError *error)
10402912Sartem {
10412912Sartem 	DBusMessage *message;
10422912Sartem 	DBusMessage *reply;
10432912Sartem 	DBusMessageIter iter_array, reply_iter;
10442912Sartem 	char **hal_device_names;
10452912Sartem 	DBusError _error;
10462912Sartem 
10472912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
10482912Sartem 
10492912Sartem 	*num_devices = 0;
10502912Sartem 
10512912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
10522912Sartem 						"/org/freedesktop/Hal/Manager",
10532912Sartem 						"org.freedesktop.Hal.Manager",
10542912Sartem 						"GetAllDevices");
10552912Sartem 	if (message == NULL) {
10562912Sartem 		fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__);
10572912Sartem 		return NULL;
10582912Sartem 	}
10592912Sartem 
10602912Sartem 	dbus_error_init (&_error);
10612912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error);
10622912Sartem 
10632912Sartem 	dbus_move_error (&_error, error);
10642912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
10652912Sartem 		dbus_message_unref (message);
10662912Sartem 		return NULL;
10672912Sartem 	}
10682912Sartem 	if (reply == NULL) {
10692912Sartem 		dbus_message_unref (message);
10702912Sartem 		return NULL;
10712912Sartem 	}
10722912Sartem 
10732912Sartem 	/* now analyze reply */
10742912Sartem 	dbus_message_iter_init (reply, &reply_iter);
10752912Sartem 
10762912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
10772912Sartem 		fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
10782912Sartem 		return NULL;
10792912Sartem 	}
10802912Sartem 
10812912Sartem 	dbus_message_iter_recurse (&reply_iter, &iter_array);
10822912Sartem 
10832912Sartem 	hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
10842912Sartem 
10852912Sartem 	dbus_message_unref (reply);
10862912Sartem 	dbus_message_unref (message);
10872912Sartem 
10882912Sartem 	return hal_device_names;
10892912Sartem }
10902912Sartem 
10912912Sartem /**
10922912Sartem  * libhal_device_get_property_type:
10932912Sartem  * @ctx: the context for the connection to hald
10942912Sartem  * @udi: the Unique Device Id
10952912Sartem  * @key: name of the property
10962912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
10972912Sartem  *
10982912Sartem  * Query a property type of a device.
10992912Sartem  *
11002912Sartem  * Returns: A LibHalPropertyType. LIBHAL_PROPERTY_TYPE_INVALID is
11012912Sartem  * return if the property doesn't exist.
11022912Sartem  */
11032912Sartem LibHalPropertyType
libhal_device_get_property_type(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)11042912Sartem libhal_device_get_property_type (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
11052912Sartem {
11062912Sartem 	DBusMessage *message;
11072912Sartem 	DBusMessage *reply;
11082912Sartem 	DBusMessageIter iter, reply_iter;
11092912Sartem 	int type;
11102912Sartem 	DBusError _error;
11112912Sartem 
11122912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, LIBHAL_PROPERTY_TYPE_INVALID); /* or return NULL? */
11132912Sartem 
11142912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
11152912Sartem 						"org.freedesktop.Hal.Device",
11162912Sartem 						"GetPropertyType");
11172912Sartem 	if (message == NULL) {
11182912Sartem 		fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
11192912Sartem 		return LIBHAL_PROPERTY_TYPE_INVALID;
11202912Sartem 	}
11212912Sartem 
11222912Sartem 	dbus_message_iter_init_append (message, &iter);
11232912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
11242912Sartem 
11252912Sartem 	dbus_error_init (&_error);
11262912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
11272912Sartem 							   message, -1,
11282912Sartem 							   &_error);
11292912Sartem 
11302912Sartem 	dbus_move_error (&_error, error);
11312912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
11322912Sartem 		dbus_message_unref (message);
11332912Sartem 		return LIBHAL_PROPERTY_TYPE_INVALID;
11342912Sartem 	}
11352912Sartem 	if (reply == NULL) {
11362912Sartem 		dbus_message_unref (message);
11372912Sartem 		return LIBHAL_PROPERTY_TYPE_INVALID;
11382912Sartem 	}
11392912Sartem 
11402912Sartem 	dbus_message_iter_init (reply, &reply_iter);
11412912Sartem 	dbus_message_iter_get_basic (&reply_iter, &type);
11422912Sartem 
11432912Sartem 	dbus_message_unref (message);
11442912Sartem 	dbus_message_unref (reply);
11452912Sartem 
11462912Sartem 	return type;
11472912Sartem }
11482912Sartem 
11492912Sartem /**
11502912Sartem  * libhal_device_get_property_strlist:
11512912Sartem  * @ctx: the context for the connection to hald
11522912Sartem  * @udi: unique Device Id
11532912Sartem  * @key: name of the property
11542912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
11552912Sartem  *
11562912Sartem  * Get the value of a property of type string list.
11572912Sartem  *
11582912Sartem  * Returns: Array of pointers to UTF8 nul-terminated strings
11592912Sartem  * terminated by NULL. The caller is responsible for freeing this
11602912Sartem  * string array with the function libhal_free_string_array(). Returns
11612912Sartem  * NULL if the property didn't exist or we are OOM
11622912Sartem  */
11632912Sartem char **
libhal_device_get_property_strlist(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)11642912Sartem libhal_device_get_property_strlist (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
11652912Sartem {
11662912Sartem 	DBusMessage *message;
11672912Sartem 	DBusMessage *reply;
11682912Sartem 	DBusMessageIter iter, iter_array, reply_iter;
11692912Sartem 	char **our_strings;
11702912Sartem 	DBusError _error;
11712912Sartem 
11722912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
11732912Sartem 
11742912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
11752912Sartem 						"org.freedesktop.Hal.Device",
11762912Sartem 						"GetPropertyStringList");
11772912Sartem 	if (message == NULL) {
11782912Sartem 		fprintf (stderr,
11792912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
11802912Sartem 			 __FILE__, __LINE__);
11812912Sartem 		return NULL;
11822912Sartem 	}
11832912Sartem 
11842912Sartem 	dbus_message_iter_init_append (message, &iter);
11852912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
11862912Sartem 
11872912Sartem 	dbus_error_init (&_error);
11882912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
11892912Sartem 							   message, -1,
11902912Sartem 							   &_error);
11912912Sartem 
11922912Sartem 	dbus_move_error (&_error, error);
11932912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
11942912Sartem 		dbus_message_unref (message);
11952912Sartem 		return NULL;
11962912Sartem 	}
11972912Sartem 	if (reply == NULL) {
11982912Sartem 		dbus_message_unref (message);
11992912Sartem 		return NULL;
12002912Sartem 	}
12012912Sartem 	/* now analyse reply */
12022912Sartem 	dbus_message_iter_init (reply, &reply_iter);
12032912Sartem 
12042912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
12052912Sartem 		fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
12062912Sartem 		return NULL;
12072912Sartem 	}
12082912Sartem 
12092912Sartem 	dbus_message_iter_recurse (&reply_iter, &iter_array);
12102912Sartem 
12112912Sartem 	our_strings = libhal_get_string_array_from_iter (&iter_array, NULL);
12122912Sartem 
12132912Sartem 	dbus_message_unref (reply);
12142912Sartem 	dbus_message_unref (message);
12152912Sartem 
12162912Sartem 	return our_strings;
12172912Sartem }
12182912Sartem 
12192912Sartem /**
12202912Sartem  * libhal_device_get_property_string:
12212912Sartem  * @ctx: the context for the connection to hald
12222912Sartem  * @udi: the Unique Device Id
12232912Sartem  * @key: the name of the property
12242912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
12252912Sartem  *
12262912Sartem  * Get the value of a property of type string.
12272912Sartem  *
12282912Sartem  * Returns: UTF8 nul-terminated string. The caller is responsible for
12292912Sartem  * freeing this string with the function libhal_free_string(). Returns
12302912Sartem  * NULL if the property didn't exist or we are OOM.
12312912Sartem  */
12322912Sartem char *
libhal_device_get_property_string(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)12332912Sartem libhal_device_get_property_string (LibHalContext *ctx,
12342912Sartem 				   const char *udi, const char *key, DBusError *error)
12352912Sartem {
12362912Sartem 	DBusMessage *message;
12372912Sartem 	DBusMessage *reply;
12382912Sartem 	DBusMessageIter iter, reply_iter;
12392912Sartem 	char *value;
12402912Sartem 	char *dbus_str;
12412912Sartem 	DBusError _error;
12422912Sartem 
12432912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
12442912Sartem 
12452912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
12462912Sartem 						"org.freedesktop.Hal.Device",
12472912Sartem 						"GetPropertyString");
12482912Sartem 
12492912Sartem 	if (message == NULL) {
12502912Sartem 		fprintf (stderr,
12512912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
12522912Sartem 			 __FILE__, __LINE__);
12532912Sartem 		return NULL;
12542912Sartem 	}
12552912Sartem 
12562912Sartem 	dbus_message_iter_init_append (message, &iter);
12572912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
12582912Sartem 
12592912Sartem 	dbus_error_init (&_error);
12602912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
12612912Sartem 							   message, -1,
12622912Sartem 							   &_error);
12632912Sartem 
12642912Sartem 	dbus_move_error (&_error, error);
12652912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
12662912Sartem 		dbus_message_unref (message);
12672912Sartem 		return NULL;
12682912Sartem 	}
12692912Sartem 	if (reply == NULL) {
12702912Sartem 		dbus_message_unref (message);
12712912Sartem 		return NULL;
12722912Sartem 	}
12732912Sartem 
12742912Sartem 	dbus_message_iter_init (reply, &reply_iter);
12752912Sartem 
12762912Sartem 	/* now analyze reply */
12772912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) !=
12782912Sartem 		   DBUS_TYPE_STRING) {
12792912Sartem 		dbus_message_unref (message);
12802912Sartem 		dbus_message_unref (reply);
12812912Sartem 		return NULL;
12822912Sartem 	}
12832912Sartem 
12842912Sartem 	dbus_message_iter_get_basic (&reply_iter, &dbus_str);
12852912Sartem 	value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
12862912Sartem 	if (value == NULL) {
12872912Sartem 		fprintf (stderr, "%s %d : error allocating memory\n",
12882912Sartem 			 __FILE__, __LINE__);
12892912Sartem 		/** @todo FIXME cleanup */
12902912Sartem 		return NULL;
12912912Sartem 	}
12922912Sartem 
12932912Sartem 	dbus_message_unref (message);
12942912Sartem 	dbus_message_unref (reply);
12952912Sartem 	return value;
12962912Sartem }
12972912Sartem 
12982912Sartem /**
12992912Sartem  * libhal_device_get_property_int:
13002912Sartem  * @ctx: the context for the connection to hald
13012912Sartem  * @udi: the Unique Device Id
13022912Sartem  * @key: name of the property
13032912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
13042912Sartem  *
13052912Sartem  * Get the value of a property of type integer.
13062912Sartem  *
13072912Sartem  * Returns: Property value (32-bit signed integer)
13082912Sartem  */
13092912Sartem dbus_int32_t
libhal_device_get_property_int(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)13102912Sartem libhal_device_get_property_int (LibHalContext *ctx,
13112912Sartem 				const char *udi, const char *key, DBusError *error)
13122912Sartem {
13132912Sartem 	DBusMessage *message;
13142912Sartem 	DBusMessage *reply;
13152912Sartem 	DBusMessageIter iter, reply_iter;
13162912Sartem 	dbus_int32_t value;
13172912Sartem 	DBusError _error;
13182912Sartem 
13192912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
13202912Sartem 
13212912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
13222912Sartem 						"org.freedesktop.Hal.Device",
13232912Sartem 						"GetPropertyInteger");
13242912Sartem 	if (message == NULL) {
13252912Sartem 		fprintf (stderr,
13262912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
13272912Sartem 			 __FILE__, __LINE__);
13282912Sartem 		return -1;
13292912Sartem 	}
13302912Sartem 
13312912Sartem 	dbus_message_iter_init_append (message, &iter);
13322912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
13332912Sartem 
13342912Sartem 	dbus_error_init (&_error);
13352912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
13362912Sartem 							   message, -1,
13372912Sartem 							   &_error);
13382912Sartem 
13392912Sartem 	dbus_move_error (&_error, error);
13402912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
13412912Sartem 		dbus_message_unref (message);
13422912Sartem 		return -1;
13432912Sartem 	}
13442912Sartem 	if (reply == NULL) {
13452912Sartem 		dbus_message_unref (message);
13462912Sartem 		return -1;
13472912Sartem 	}
13482912Sartem 
13492912Sartem 	dbus_message_iter_init (reply, &reply_iter);
13502912Sartem 
13512912Sartem 	/* now analyze reply */
13522912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) !=
13532912Sartem 		   DBUS_TYPE_INT32) {
13542912Sartem 		fprintf (stderr,
13552912Sartem 			 "%s %d : property '%s' for device '%s' is not "
13562912Sartem 			 "of type integer\n", __FILE__, __LINE__, key,
13572912Sartem 			 udi);
13582912Sartem 		dbus_message_unref (message);
13592912Sartem 		dbus_message_unref (reply);
13602912Sartem 		return -1;
13612912Sartem 	}
13622912Sartem 	dbus_message_iter_get_basic (&reply_iter, &value);
13632912Sartem 
13642912Sartem 	dbus_message_unref (message);
13652912Sartem 	dbus_message_unref (reply);
13662912Sartem 	return value;
13672912Sartem }
13682912Sartem 
13692912Sartem /**
13702912Sartem  * libhal_device_get_property_uint64:
13712912Sartem  * @ctx: the context for the connection to hald
13722912Sartem  * @udi: the Unique Device Id
13732912Sartem  * @key: name of the property
13742912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
13752912Sartem  *
13762912Sartem  * Get the value of a property of type signed integer.
13772912Sartem  *
13782912Sartem  * Returns: Property value (64-bit unsigned integer)
13792912Sartem  */
13802912Sartem dbus_uint64_t
libhal_device_get_property_uint64(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)13812912Sartem libhal_device_get_property_uint64 (LibHalContext *ctx,
13822912Sartem 				   const char *udi, const char *key, DBusError *error)
13832912Sartem {
13842912Sartem 	DBusMessage *message;
13852912Sartem 	DBusMessage *reply;
13862912Sartem 	DBusMessageIter iter, reply_iter;
13872912Sartem 	dbus_uint64_t value;
13882912Sartem 	DBusError _error;
13892912Sartem 
13902912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
13912912Sartem 
13922912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
13932912Sartem 						"org.freedesktop.Hal.Device",
13942912Sartem 						"GetPropertyInteger");
13952912Sartem 	if (message == NULL) {
13962912Sartem 		fprintf (stderr,
13972912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
13982912Sartem 			 __FILE__, __LINE__);
13992912Sartem 		return -1;
14002912Sartem 	}
14012912Sartem 
14022912Sartem 	dbus_message_iter_init_append (message, &iter);
14032912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
14042912Sartem 
14052912Sartem 	dbus_error_init (&_error);
14062912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
14072912Sartem 							   message, -1,
14082912Sartem 							   &_error);
14092912Sartem 
14102912Sartem 	dbus_move_error (&_error, error);
14112912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
14122912Sartem 		dbus_message_unref (message);
14132912Sartem 		return -1;
14142912Sartem 	}
14152912Sartem 	if (reply == NULL) {
14162912Sartem 		dbus_message_unref (message);
14172912Sartem 		return -1;
14182912Sartem 	}
14192912Sartem 
14202912Sartem 	dbus_message_iter_init (reply, &reply_iter);
14212912Sartem 	/* now analyze reply */
14222912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) !=
14232912Sartem 		   DBUS_TYPE_UINT64) {
14242912Sartem 		fprintf (stderr,
14252912Sartem 			 "%s %d : property '%s' for device '%s' is not "
14262912Sartem 			 "of type integer\n", __FILE__, __LINE__, key,
14272912Sartem 			 udi);
14282912Sartem 		dbus_message_unref (message);
14292912Sartem 		dbus_message_unref (reply);
14302912Sartem 		return -1;
14312912Sartem 	}
14322912Sartem 	dbus_message_iter_get_basic (&reply_iter, &value);
14332912Sartem 
14342912Sartem 	dbus_message_unref (message);
14352912Sartem 	dbus_message_unref (reply);
14362912Sartem 	return value;
14372912Sartem }
14382912Sartem 
14392912Sartem /**
14402912Sartem  * libhal_device_get_property_double:
14412912Sartem  * @ctx: the context for the connection to hald
14422912Sartem  * @udi: the Unique Device Id
14432912Sartem  * @key: name of the property
14442912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
14452912Sartem  *
14462912Sartem  * Get the value of a property of type double.
14472912Sartem  *
14482912Sartem  * Returns: Property value (IEEE754 double precision float)
14492912Sartem  */
14502912Sartem double
libhal_device_get_property_double(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)14512912Sartem libhal_device_get_property_double (LibHalContext *ctx,
14522912Sartem 				   const char *udi, const char *key, DBusError *error)
14532912Sartem {
14542912Sartem 	DBusMessage *message;
14552912Sartem 	DBusMessage *reply;
14562912Sartem 	DBusMessageIter iter, reply_iter;
14572912Sartem 	double value;
14582912Sartem 	DBusError _error;
14592912Sartem 
14602912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1.0);
14612912Sartem 
14622912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
14632912Sartem 						"org.freedesktop.Hal.Device",
14642912Sartem 						"GetPropertyDouble");
14652912Sartem 	if (message == NULL) {
14662912Sartem 		fprintf (stderr,
14672912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
14682912Sartem 			 __FILE__, __LINE__);
14692912Sartem 		return -1.0f;
14702912Sartem 	}
14712912Sartem 
14722912Sartem 	dbus_message_iter_init_append (message, &iter);
14732912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
14742912Sartem 
14752912Sartem 	dbus_error_init (&_error);
14762912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
14772912Sartem 							   message, -1,
14782912Sartem 							   &_error);
14792912Sartem 
14802912Sartem 	dbus_move_error (&_error, error);
14812912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
14822912Sartem 		dbus_message_unref (message);
14832912Sartem 		return -1.0f;
14842912Sartem 	}
14852912Sartem 	if (reply == NULL) {
14862912Sartem 		dbus_message_unref (message);
14872912Sartem 		return -1.0f;
14882912Sartem 	}
14892912Sartem 
14902912Sartem 	dbus_message_iter_init (reply, &reply_iter);
14912912Sartem 
14922912Sartem 	/* now analyze reply */
14932912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) !=
14942912Sartem 		   DBUS_TYPE_DOUBLE) {
14952912Sartem 		fprintf (stderr,
14962912Sartem 			 "%s %d : property '%s' for device '%s' is not "
14972912Sartem 			 "of type double\n", __FILE__, __LINE__, key, udi);
14982912Sartem 		dbus_message_unref (message);
14992912Sartem 		dbus_message_unref (reply);
15002912Sartem 		return -1.0f;
15012912Sartem 	}
15022912Sartem 	dbus_message_iter_get_basic (&reply_iter, &value);
15032912Sartem 
15042912Sartem 	dbus_message_unref (message);
15052912Sartem 	dbus_message_unref (reply);
15062912Sartem 	return (double) value;
15072912Sartem }
15082912Sartem 
15092912Sartem /**
15102912Sartem  * libhal_device_get_property_bool:
15112912Sartem  * @ctx: the context for the connection to hald
15122912Sartem  * @udi: the Unique Device Id
15132912Sartem  * @key: name of the property
15142912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
15152912Sartem  *
15162912Sartem  * Get the value of a property of type bool.
15172912Sartem  *
15182912Sartem  * Returns: Property value (boolean)
15192912Sartem  */
15202912Sartem dbus_bool_t
libhal_device_get_property_bool(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)15212912Sartem libhal_device_get_property_bool (LibHalContext *ctx,
15222912Sartem 				 const char *udi, const char *key, DBusError *error)
15232912Sartem {
15242912Sartem 	DBusMessage *message;
15252912Sartem 	DBusMessage *reply;
15262912Sartem 	DBusMessageIter iter, reply_iter;
15272912Sartem 	dbus_bool_t value;
15282912Sartem 	DBusError _error;
15292912Sartem 
15302912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
15312912Sartem 
15322912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
15332912Sartem 						"org.freedesktop.Hal.Device",
15342912Sartem 						"GetPropertyBoolean");
15352912Sartem 	if (message == NULL) {
15362912Sartem 		fprintf (stderr,
15372912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
15382912Sartem 			 __FILE__, __LINE__);
15392912Sartem 		return FALSE;
15402912Sartem 	}
15412912Sartem 
15422912Sartem 	dbus_message_iter_init_append (message, &iter);
15432912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
15442912Sartem 
15452912Sartem 	dbus_error_init (&_error);
15462912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
15472912Sartem 							   message, -1,
15482912Sartem 							   &_error);
15492912Sartem 
15502912Sartem 	dbus_move_error (&_error, error);
15512912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
15522912Sartem 		dbus_message_unref (message);
15532912Sartem 		return FALSE;
15542912Sartem 	}
15552912Sartem 	if (reply == NULL) {
15562912Sartem 		dbus_message_unref (message);
15572912Sartem 		return FALSE;
15582912Sartem 	}
15592912Sartem 
15602912Sartem 	dbus_message_iter_init (reply, &reply_iter);
15612912Sartem 
15622912Sartem 	/* now analyze reply */
15632912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) !=
15642912Sartem 		   DBUS_TYPE_BOOLEAN) {
15652912Sartem 		fprintf (stderr,
15662912Sartem 			 "%s %d : property '%s' for device '%s' is not "
15672912Sartem 			 "of type bool\n", __FILE__, __LINE__, key, udi);
15682912Sartem 		dbus_message_unref (message);
15692912Sartem 		dbus_message_unref (reply);
15702912Sartem 		return FALSE;
15712912Sartem 	}
15722912Sartem 	dbus_message_iter_get_basic (&reply_iter, &value);
15732912Sartem 
15742912Sartem 	dbus_message_unref (message);
15752912Sartem 	dbus_message_unref (reply);
15762912Sartem 	return value;
15772912Sartem }
15782912Sartem 
15792912Sartem 
15802912Sartem /* generic helper */
15812912Sartem static dbus_bool_t
libhal_device_set_property_helper(LibHalContext * ctx,const char * udi,const char * key,int type,const char * str_value,dbus_int32_t int_value,dbus_uint64_t uint64_value,double double_value,dbus_bool_t bool_value,DBusError * error)15822912Sartem libhal_device_set_property_helper (LibHalContext *ctx,
15832912Sartem 				   const char *udi,
15842912Sartem 				   const char *key,
15852912Sartem 				   int type,
15862912Sartem 				   const char *str_value,
15872912Sartem 				   dbus_int32_t int_value,
15882912Sartem 				   dbus_uint64_t uint64_value,
15892912Sartem 				   double double_value,
15902912Sartem 				   dbus_bool_t bool_value,
15912912Sartem 				   DBusError *error)
15922912Sartem {
15932912Sartem 	DBusMessage *message;
15942912Sartem 	DBusMessage *reply;
15952912Sartem 	DBusMessageIter iter;
15962912Sartem 	char *method_name = NULL;
15972912Sartem 
15982912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
15992912Sartem 
16002912Sartem 	/** @todo  sanity check incoming params */
16012912Sartem 	switch (type) {
16022912Sartem 	case DBUS_TYPE_INVALID:
16032912Sartem 		method_name = "RemoveProperty";
16042912Sartem 		break;
16052912Sartem 	case DBUS_TYPE_STRING:
16062912Sartem 		method_name = "SetPropertyString";
16072912Sartem 		break;
16082912Sartem 	case DBUS_TYPE_INT32:
16092912Sartem 	case DBUS_TYPE_UINT64:
16102912Sartem 		method_name = "SetPropertyInteger";
16112912Sartem 		break;
16122912Sartem 	case DBUS_TYPE_DOUBLE:
16132912Sartem 		method_name = "SetPropertyDouble";
16142912Sartem 		break;
16152912Sartem 	case DBUS_TYPE_BOOLEAN:
16162912Sartem 		method_name = "SetPropertyBoolean";
16172912Sartem 		break;
16182912Sartem 
16192912Sartem 	default:
16202912Sartem 		/* cannot happen; is not callable from outside this file */
16212912Sartem 		break;
16222912Sartem 	}
16232912Sartem 
16242912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
16252912Sartem 						"org.freedesktop.Hal.Device",
16262912Sartem 						method_name);
16272912Sartem 	if (message == NULL) {
16282912Sartem 		fprintf (stderr,
16292912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
16302912Sartem 			 __FILE__, __LINE__);
16312912Sartem 		return FALSE;
16322912Sartem 	}
16332912Sartem 
16342912Sartem 	dbus_message_iter_init_append (message, &iter);
16352912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
16362912Sartem 	switch (type) {
16372912Sartem 	case DBUS_TYPE_STRING:
16382912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str_value);
16392912Sartem 		break;
16402912Sartem 	case DBUS_TYPE_INT32:
16412912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &int_value);
16422912Sartem 		break;
16432912Sartem 	case DBUS_TYPE_UINT64:
16442912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &uint64_value);
16452912Sartem 		break;
16462912Sartem 	case DBUS_TYPE_DOUBLE:
16472912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &double_value);
16482912Sartem 		break;
16492912Sartem 	case DBUS_TYPE_BOOLEAN:
16502912Sartem 		dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bool_value);
16512912Sartem 		break;
16522912Sartem 	}
16532912Sartem 
16542912Sartem 
16552912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
16562912Sartem 							   message, -1,
16572912Sartem 							   error);
1658*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
16592912Sartem 		dbus_message_unref (message);
16602912Sartem 		return FALSE;
16612912Sartem 	}
16622912Sartem 
16632912Sartem 	if (reply == NULL) {
16642912Sartem 		dbus_message_unref (message);
16652912Sartem 		return FALSE;
16662912Sartem 	}
16672912Sartem 
16682912Sartem 	dbus_message_unref (message);
16692912Sartem 	dbus_message_unref (reply);
16702912Sartem 
16712912Sartem 	return TRUE;
16722912Sartem }
16732912Sartem 
16742912Sartem /**
16752912Sartem  * libhal_device_set_property_string:
16762912Sartem  * @ctx: the context for the connection to hald
16772912Sartem  * @udi: the Unique Device Id
16782912Sartem  * @key: name of the property
16792912Sartem  * @value: value of the property; a UTF8 string
16802912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
16812912Sartem  *
16822912Sartem  * Set a property of type string.
16832912Sartem  *
16842912Sartem  * Returns: TRUE if the property was set, FALSE if the device didn't
16852912Sartem  * exist or the property had a different type.
16862912Sartem  */
16872912Sartem dbus_bool_t
libhal_device_set_property_string(LibHalContext * ctx,const char * udi,const char * key,const char * value,DBusError * error)16882912Sartem libhal_device_set_property_string (LibHalContext *ctx,
16892912Sartem 				   const char *udi,
16902912Sartem 				   const char *key,
16912912Sartem 				   const char *value,
16922912Sartem 				   DBusError *error)
16932912Sartem {
16942912Sartem 	return libhal_device_set_property_helper (ctx, udi, key,
16952912Sartem 						  DBUS_TYPE_STRING,
16962912Sartem 						  value, 0, 0, 0.0f, FALSE, error);
16972912Sartem }
16982912Sartem 
16992912Sartem /**
17002912Sartem  * libhal_device_set_property_int:
17012912Sartem  * @ctx: the context for the connection to hald
17022912Sartem  * @udi: the Unique Device Id
17032912Sartem  * @key: name of the property
17042912Sartem  * @value: value of the property
17052912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
17062912Sartem  *
17072912Sartem  * Set a property of type signed integer.
17082912Sartem  *
17092912Sartem  * Returns: TRUE if the property was set, FALSE if the device didn't
17102912Sartem  * exist or the property had a different type.
17112912Sartem  */
17122912Sartem dbus_bool_t
libhal_device_set_property_int(LibHalContext * ctx,const char * udi,const char * key,dbus_int32_t value,DBusError * error)17132912Sartem libhal_device_set_property_int (LibHalContext *ctx, const char *udi,
17142912Sartem 				const char *key, dbus_int32_t value, DBusError *error)
17152912Sartem {
17162912Sartem 	return libhal_device_set_property_helper (ctx, udi, key,
17172912Sartem 						  DBUS_TYPE_INT32,
17182912Sartem 						  NULL, value, 0, 0.0f, FALSE, error);
17192912Sartem }
17202912Sartem 
17212912Sartem /**
17222912Sartem  * libhal_device_set_property_uint64:
17232912Sartem  * @ctx: the context for the connection to hald
17242912Sartem  * @udi: the Unique Device Id
17252912Sartem  * @key: name of the property
17262912Sartem  * @value: value of the property
17272912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
17282912Sartem  *
17292912Sartem  * Set a property of type unsigned integer.
17302912Sartem  *
17312912Sartem  * Returns: TRUE if the property was set, FALSE if the device didn't
17322912Sartem  * exist or the property had a different type.
17332912Sartem  */
17342912Sartem dbus_bool_t
libhal_device_set_property_uint64(LibHalContext * ctx,const char * udi,const char * key,dbus_uint64_t value,DBusError * error)17352912Sartem libhal_device_set_property_uint64 (LibHalContext *ctx, const char *udi,
17362912Sartem 				   const char *key, dbus_uint64_t value, DBusError *error)
17372912Sartem {
17382912Sartem 	return libhal_device_set_property_helper (ctx, udi, key,
17392912Sartem 						  DBUS_TYPE_UINT64,
17402912Sartem 						  NULL, 0, value, 0.0f, FALSE, error);
17412912Sartem }
17422912Sartem 
17432912Sartem /**
17442912Sartem  * libhal_device_set_property_double:
17452912Sartem  * @ctx: the context for the connection to hald
17462912Sartem  * @udi: the Unique Device Id
17472912Sartem  * @key: name of the property
17482912Sartem  * @value: value of the property
17492912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
17502912Sartem  *
17512912Sartem  * Set a property of type double.
17522912Sartem  *
17532912Sartem  * Returns: TRUE if the property was set, FALSE if the device didn't
17542912Sartem  * exist or the property had a different type.
17552912Sartem  */
17562912Sartem dbus_bool_t
libhal_device_set_property_double(LibHalContext * ctx,const char * udi,const char * key,double value,DBusError * error)17572912Sartem libhal_device_set_property_double (LibHalContext *ctx, const char *udi,
17582912Sartem 				   const char *key, double value, DBusError *error)
17592912Sartem {
17602912Sartem 	return libhal_device_set_property_helper (ctx, udi, key,
17612912Sartem 						  DBUS_TYPE_DOUBLE,
17622912Sartem 						  NULL, 0, 0, value, FALSE, error);
17632912Sartem }
17642912Sartem 
17652912Sartem /**
17662912Sartem  * libhal_device_set_property_bool:
17672912Sartem  * @ctx: the context for the connection to hald
17682912Sartem  * @udi: the Unique Device Id
17692912Sartem  * @key: name of the property
17702912Sartem  * @value: value of the property
17712912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
17722912Sartem  *
17732912Sartem  * Set a property of type bool.
17742912Sartem  *
17752912Sartem  * Returns: TRUE if the property was set, FALSE if the device didn't
17762912Sartem  * exist or the property had a different type.
17772912Sartem  */
17782912Sartem dbus_bool_t
libhal_device_set_property_bool(LibHalContext * ctx,const char * udi,const char * key,dbus_bool_t value,DBusError * error)17792912Sartem libhal_device_set_property_bool (LibHalContext *ctx, const char *udi,
17802912Sartem 				 const char *key, dbus_bool_t value, DBusError *error)
17812912Sartem {
17822912Sartem 	return libhal_device_set_property_helper (ctx, udi, key,
17832912Sartem 						  DBUS_TYPE_BOOLEAN,
17842912Sartem 						  NULL, 0, 0, 0.0f, value, error);
17852912Sartem }
17862912Sartem 
17872912Sartem 
17882912Sartem /**
17892912Sartem  * libhal_device_remove_property:
17902912Sartem  * @ctx: the context for the connection to hald
17912912Sartem  * @udi: the Unique Device Id
17922912Sartem  * @key: name of the property
17932912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
17942912Sartem  *
17952912Sartem  * Remove a property.
17962912Sartem  *
17972912Sartem  * Returns: TRUE if the property was set, FALSE if the device didn't
17982912Sartem  * exist
17992912Sartem  */
18002912Sartem dbus_bool_t
libhal_device_remove_property(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)18012912Sartem libhal_device_remove_property (LibHalContext *ctx,
18022912Sartem 			       const char *udi, const char *key, DBusError *error)
18032912Sartem {
18042912Sartem 	return libhal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_INVALID,
18052912Sartem 						  /* DBUS_TYPE_INVALID means remove */
18062912Sartem 						  NULL, 0, 0, 0.0f, FALSE, error);
18072912Sartem }
18082912Sartem 
18092912Sartem /**
18102912Sartem  * libhal_device_property_strlist_append:
18112912Sartem  * @ctx: the context for the connection to hald
18122912Sartem  * @udi: the Unique Device Id
18132912Sartem  * @key: name of the property
18142912Sartem  * @value: value to append to property
18152912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
18162912Sartem  *
18172912Sartem  * Append to a property of type strlist.
18182912Sartem  *
18192912Sartem  * Returns: TRUE if the value was appended, FALSE if the device didn't
18202912Sartem  * exist or the property had a different type.
18212912Sartem  */
18222912Sartem dbus_bool_t
libhal_device_property_strlist_append(LibHalContext * ctx,const char * udi,const char * key,const char * value,DBusError * error)18232912Sartem libhal_device_property_strlist_append (LibHalContext *ctx,
18242912Sartem 				       const char *udi,
18252912Sartem 				       const char *key,
18262912Sartem 				       const char *value,
18272912Sartem 				       DBusError *error)
18282912Sartem {
18292912Sartem 	DBusMessage *message;
18302912Sartem 	DBusMessage *reply;
18312912Sartem 	DBusMessageIter iter;
18322912Sartem 
18332912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
18342912Sartem 
18352912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
18362912Sartem 						"org.freedesktop.Hal.Device",
18372912Sartem 						"StringListAppend");
18382912Sartem 	if (message == NULL) {
18392912Sartem 		fprintf (stderr,
18402912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
18412912Sartem 			 __FILE__, __LINE__);
18422912Sartem 		return FALSE;
18432912Sartem 	}
18442912Sartem 	dbus_message_iter_init_append (message, &iter);
18452912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
18462912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
18472912Sartem 
18482912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
18492912Sartem 							   message, -1,
18502912Sartem 							   error);
1851*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
18522912Sartem 		dbus_message_unref (message);
18532912Sartem 		return FALSE;
18542912Sartem 	}
18552912Sartem 	if (reply == NULL) {
18562912Sartem 		dbus_message_unref (message);
18572912Sartem 		return FALSE;
18582912Sartem 	}
18592912Sartem 	return TRUE;
18602912Sartem }
18612912Sartem 
18622912Sartem /**
18632912Sartem  * libhal_device_property_strlist_prepend:
18642912Sartem  * @ctx: the context for the connection to hald
18652912Sartem  * @udi: the Unique Device Id
18662912Sartem  * @key: name of the property
18672912Sartem  * @value: value to prepend to property
18682912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
18692912Sartem  *
18702912Sartem  * Prepend to a property of type strlist.
18712912Sartem  *
18722912Sartem  * Returns: TRUE if the value was prepended, FALSE if the device
18732912Sartem  * didn't exist or the property had a different type.
18742912Sartem  */
18752912Sartem dbus_bool_t
libhal_device_property_strlist_prepend(LibHalContext * ctx,const char * udi,const char * key,const char * value,DBusError * error)18762912Sartem libhal_device_property_strlist_prepend (LibHalContext *ctx,
18772912Sartem 					const char *udi,
18782912Sartem 					const char *key,
18792912Sartem 					const char *value,
18802912Sartem 					DBusError *error)
18812912Sartem {
18822912Sartem 	DBusMessage *message;
18832912Sartem 	DBusMessage *reply;
18842912Sartem 	DBusMessageIter iter;
18852912Sartem 
18862912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
18872912Sartem 
18882912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
18892912Sartem 						"org.freedesktop.Hal.Device",
18902912Sartem 						"StringListPrepend");
18912912Sartem 	if (message == NULL) {
18922912Sartem 		fprintf (stderr,
18932912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
18942912Sartem 			 __FILE__, __LINE__);
18952912Sartem 		return FALSE;
18962912Sartem 	}
18972912Sartem 	dbus_message_iter_init_append (message, &iter);
18982912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
18992912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
19002912Sartem 
19012912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
19022912Sartem 							   message, -1,
19032912Sartem 							   error);
1904*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
19052912Sartem 		dbus_message_unref (message);
19062912Sartem 		return FALSE;
19072912Sartem 	}
19082912Sartem 	if (reply == NULL) {
19092912Sartem 		dbus_message_unref (message);
19102912Sartem 		return FALSE;
19112912Sartem 	}
19122912Sartem 	return TRUE;
19132912Sartem }
19142912Sartem 
19152912Sartem /**
19162912Sartem  * libhal_device_property_strlist_remove_index:
19172912Sartem  * @ctx: the context for the connection to hald
19182912Sartem  * @udi: the Unique Device Id
19192912Sartem  * @key: name of the property
19202912Sartem  * @idx: index of string to remove in the strlist
19212912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
19222912Sartem  *
19232912Sartem  * Remove a specified string from a property of type strlist.
19242912Sartem  *
19252912Sartem  * Returns: TRUE if the string was removed, FALSE if the device didn't
19262912Sartem  * exist or the property had a different type.
19272912Sartem  */
19282912Sartem dbus_bool_t
libhal_device_property_strlist_remove_index(LibHalContext * ctx,const char * udi,const char * key,unsigned int idx,DBusError * error)19292912Sartem libhal_device_property_strlist_remove_index (LibHalContext *ctx,
19302912Sartem 					     const char *udi,
19312912Sartem 					     const char *key,
19322912Sartem 					     unsigned int idx,
19332912Sartem 					     DBusError *error)
19342912Sartem {
19352912Sartem 	DBusMessage *message;
19362912Sartem 	DBusMessage *reply;
19372912Sartem 	DBusMessageIter iter;
19382912Sartem 
19392912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
19402912Sartem 
19412912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
19422912Sartem 						"org.freedesktop.Hal.Device",
19432912Sartem 						"StringListRemoveIndex");
19442912Sartem 	if (message == NULL) {
19452912Sartem 		fprintf (stderr,
19462912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
19472912Sartem 			 __FILE__, __LINE__);
19482912Sartem 		return FALSE;
19492912Sartem 	}
19502912Sartem 	dbus_message_iter_init_append (message, &iter);
19512912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
19522912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &idx);
19532912Sartem 
19542912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
19552912Sartem 							   message, -1,
19562912Sartem 							   error);
1957*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
19582912Sartem 		dbus_message_unref (message);
19592912Sartem 		return FALSE;
19602912Sartem 	}
19612912Sartem 	if (reply == NULL) {
19622912Sartem 		dbus_message_unref (message);
19632912Sartem 		return FALSE;
19642912Sartem 	}
19652912Sartem 	return TRUE;
19662912Sartem }
19672912Sartem 
19682912Sartem /**
19692912Sartem  * libhal_device_property_strlist_remove:
19702912Sartem  * @ctx: the context for the connection to hald
19712912Sartem  * @udi: the Unique Device Id
19722912Sartem  * @key: name of the property
19732912Sartem  * @value: the string to remove
19742912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
19752912Sartem  *
19762912Sartem  * Remove a specified string from a property of type strlist.
19772912Sartem  *
19782912Sartem  * Returns: TRUE if the string was removed, FALSE if the device didn't
19792912Sartem  * exist or the property had a different type.
19802912Sartem  */
19812912Sartem dbus_bool_t
libhal_device_property_strlist_remove(LibHalContext * ctx,const char * udi,const char * key,const char * value,DBusError * error)19822912Sartem libhal_device_property_strlist_remove (LibHalContext *ctx,
19832912Sartem 				       const char *udi,
19842912Sartem 				       const char *key,
19852912Sartem 				       const char *value, DBusError *error)
19862912Sartem {
19872912Sartem 	DBusMessage *message;
19882912Sartem 	DBusMessage *reply;
19892912Sartem 	DBusMessageIter iter;
19902912Sartem 
19912912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
19922912Sartem 
19932912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
19942912Sartem 						"org.freedesktop.Hal.Device",
19952912Sartem 						"StringListRemove");
19962912Sartem 	if (message == NULL) {
19972912Sartem 		fprintf (stderr,
19982912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
19992912Sartem 			 __FILE__, __LINE__);
20002912Sartem 		return FALSE;
20012912Sartem 	}
20022912Sartem 	dbus_message_iter_init_append (message, &iter);
20032912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
20042912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
20052912Sartem 
20062912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
20072912Sartem 							   message, -1,
20082912Sartem 							   error);
2009*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
20102912Sartem 		dbus_message_unref (message);
20112912Sartem 		return FALSE;
20122912Sartem 	}
20132912Sartem 	if (reply == NULL) {
20142912Sartem 		dbus_message_unref (message);
20152912Sartem 		return FALSE;
20162912Sartem 	}
20172912Sartem 	return TRUE;
20182912Sartem }
20192912Sartem 
20202912Sartem 
20212912Sartem /**
20222912Sartem  * libhal_device_lock:
20232912Sartem  * @ctx: the context for the connection to hald
20242912Sartem  * @udi: the Unique Device Id
20252912Sartem  * @reason_to_lock: a user-presentable reason why the device is locked.
20262912Sartem  * @reason_why_locked: a pointer to store the reason why the device cannot be locked on failure, or NULL
20272912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
20282912Sartem  *
20292912Sartem  * Take an advisory lock on the device.
20302912Sartem  *
20312912Sartem  * Returns: TRUE if the lock was obtained, FALSE otherwise
20322912Sartem  */
20332912Sartem dbus_bool_t
libhal_device_lock(LibHalContext * ctx,const char * udi,const char * reason_to_lock,char ** reason_why_locked,DBusError * error)20342912Sartem libhal_device_lock (LibHalContext *ctx,
20352912Sartem 		    const char *udi,
20362912Sartem 		    const char *reason_to_lock,
20372912Sartem 		    char **reason_why_locked, DBusError *error)
20382912Sartem {
20392912Sartem 	DBusMessage *message;
20402912Sartem 	DBusMessageIter iter;
20412912Sartem 	DBusMessage *reply;
20422912Sartem 
20432912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
20442912Sartem 
20452912Sartem 	if (reason_why_locked != NULL)
20462912Sartem 		*reason_why_locked = NULL;
20472912Sartem 
20482912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
20492912Sartem 						udi,
20502912Sartem 						"org.freedesktop.Hal.Device",
20512912Sartem 						"Lock");
20522912Sartem 
20532912Sartem 	if (message == NULL) {
20542912Sartem 		fprintf (stderr,
20552912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
20562912Sartem 			 __FILE__, __LINE__);
20572912Sartem 		return FALSE;
20582912Sartem 	}
20592912Sartem 
20602912Sartem 	dbus_message_iter_init_append (message, &iter);
20612912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reason_to_lock);
20622912Sartem 
20632912Sartem 
20642912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
20652912Sartem 							   message, -1,
20662912Sartem 							   error);
20672912Sartem 
2068*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
20692912Sartem 		if (strcmp (error->name,
20702912Sartem 			    "org.freedesktop.Hal.DeviceAlreadyLocked") == 0) {
20712912Sartem 			if (reason_why_locked != NULL) {
20722912Sartem 				*reason_why_locked =
20732912Sartem 					dbus_malloc0 (strlen (error->message) + 1);
20742912Sartem 				strcpy (*reason_why_locked, error->message);
20752912Sartem 			}
20762912Sartem 		}
20772912Sartem 
20782912Sartem 		dbus_message_unref (message);
20792912Sartem 		return FALSE;
20802912Sartem 	}
20812912Sartem 
20822912Sartem 	dbus_message_unref (message);
20832912Sartem 
20842912Sartem 	if (reply == NULL)
20852912Sartem 		return FALSE;
20862912Sartem 
20872912Sartem 	dbus_message_unref (reply);
20882912Sartem 
20892912Sartem 	return TRUE;
20902912Sartem }
20912912Sartem 
20922912Sartem /**
20932912Sartem  * libhal_device_unlock:
20942912Sartem  * @ctx: the context for the connection to hald
20952912Sartem  * @udi: the Unique Device Id
20962912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
20972912Sartem  *
20982912Sartem  * Release an advisory lock on the device.
20992912Sartem  *
21002912Sartem  * Returns: TRUE if the device was successfully unlocked,
21012912Sartem  *                              FALSE otherwise
21022912Sartem  */
21032912Sartem dbus_bool_t
libhal_device_unlock(LibHalContext * ctx,const char * udi,DBusError * error)21042912Sartem libhal_device_unlock (LibHalContext *ctx,
21052912Sartem 		      const char *udi, DBusError *error)
21062912Sartem {
21072912Sartem 	DBusMessage *message;
21082912Sartem 	DBusMessage *reply;
21092912Sartem 
21102912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
21112912Sartem 
21122912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
21132912Sartem 						udi,
21142912Sartem 						"org.freedesktop.Hal.Device",
21152912Sartem 						"Unlock");
21162912Sartem 
21172912Sartem 	if (message == NULL) {
21182912Sartem 		fprintf (stderr,
21192912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
21202912Sartem 			 __FILE__, __LINE__);
21212912Sartem 		return FALSE;
21222912Sartem 	}
21232912Sartem 
21242912Sartem 
21252912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
21262912Sartem 							   message, -1,
21272912Sartem 							   error);
21282912Sartem 
2129*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
21302912Sartem 		dbus_message_unref (message);
21312912Sartem 		return FALSE;
21322912Sartem 	}
21332912Sartem 
21342912Sartem 	dbus_message_unref (message);
21352912Sartem 
21362912Sartem 	if (reply == NULL)
21372912Sartem 		return FALSE;
21382912Sartem 
21392912Sartem 	dbus_message_unref (reply);
21402912Sartem 
21412912Sartem 	return TRUE;
21422912Sartem }
21432912Sartem 
21442912Sartem 
21452912Sartem /**
21462912Sartem  * libhal_new_device:
21472912Sartem  * @ctx: the context for the connection to hald
21482912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
21492912Sartem  *
21502912Sartem  * Create a new device object which will be hidden from applications
21512912Sartem  * until the CommitToGdl(), ie. libhal_device_commit_to_gdl(), method
21522912Sartem  * is called. Note that the program invoking this method needs to run
21532912Sartem  * with super user privileges.
21542912Sartem  *
21552912Sartem  * Returns: Temporary device unique id or NULL if there was a
21562912Sartem  * problem. This string must be freed by the caller.
21572912Sartem  */
21582912Sartem char *
libhal_new_device(LibHalContext * ctx,DBusError * error)21592912Sartem libhal_new_device (LibHalContext *ctx, DBusError *error)
21602912Sartem {
21612912Sartem 	DBusMessage *message;
21622912Sartem 	DBusMessage *reply;
21632912Sartem 	DBusMessageIter reply_iter;
21642912Sartem 	char *value;
21652912Sartem 	char *dbus_str;
21662912Sartem 
21672912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
21682912Sartem 
21692912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
21702912Sartem 						"/org/freedesktop/Hal/Manager",
21712912Sartem 						"org.freedesktop.Hal.Manager",
21722912Sartem 						"NewDevice");
21732912Sartem 	if (message == NULL) {
21742912Sartem 		fprintf (stderr,
21752912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
21762912Sartem 			 __FILE__, __LINE__);
21772912Sartem 		return NULL;
21782912Sartem 	}
21792912Sartem 
21802912Sartem 
21812912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
21822912Sartem 							   message, -1,
21832912Sartem 							   error);
2184*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
21852912Sartem 		dbus_message_unref (message);
21862912Sartem 		return NULL;
21872912Sartem 	}
21882912Sartem 	if (reply == NULL) {
21892912Sartem 		dbus_message_unref (message);
21902912Sartem 		return NULL;
21912912Sartem 	}
21922912Sartem 
21932912Sartem 	dbus_message_iter_init (reply, &reply_iter);
21942912Sartem 
21952912Sartem 	/* now analyze reply */
21962912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) {
21972912Sartem 		fprintf (stderr,
21982912Sartem 			 "%s %d : expected a string in reply to NewDevice\n",
21992912Sartem 			 __FILE__, __LINE__);
22002912Sartem 		dbus_message_unref (message);
22012912Sartem 		dbus_message_unref (reply);
22022912Sartem 		return NULL;
22032912Sartem 	}
22042912Sartem 
22052912Sartem 	dbus_message_iter_get_basic (&reply_iter, &dbus_str);
22062912Sartem 	value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
22072912Sartem 	if (value == NULL) {
22082912Sartem 		fprintf (stderr, "%s %d : error allocating memory\n",
22092912Sartem 			 __FILE__, __LINE__);
22102912Sartem 	}
22112912Sartem 
22122912Sartem 	dbus_message_unref (message);
22132912Sartem 	dbus_message_unref (reply);
22142912Sartem 	return value;
22152912Sartem }
22162912Sartem 
22172912Sartem 
22182912Sartem /**
22192912Sartem  * libhal_device_commit_to_gdl:
22202912Sartem  * @ctx: the context for the connection to hald
22212912Sartem  * @temp_udi: the temporary unique device id as returned by libhal_new_device()
22222912Sartem  * @udi: the new unique device id.
22232912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
22242912Sartem  *
22252912Sartem  * When a hidden device has been built using the NewDevice method,
22262912Sartem  * ie. libhal_new_device(), and the org.freedesktop.Hal.Device
22272912Sartem  * interface this function will commit it to the global device list.
22282912Sartem  *
22292912Sartem  * This means that the device object will be visible to applications
22302912Sartem  * and the HAL daemon will possibly attempt to boot the device
22312912Sartem  * (depending on the property RequireEnable).
22322912Sartem  *
22332912Sartem  * Note that the program invoking this method needs to run with super
22342912Sartem  * user privileges.
22352912Sartem  *
22362912Sartem  * Returns: FALSE if the given unique device id is already in use.
22372912Sartem  */
22382912Sartem dbus_bool_t
libhal_device_commit_to_gdl(LibHalContext * ctx,const char * temp_udi,const char * udi,DBusError * error)22392912Sartem libhal_device_commit_to_gdl (LibHalContext *ctx,
22402912Sartem 			     const char *temp_udi, const char *udi, DBusError *error)
22412912Sartem {
22422912Sartem 	DBusMessage *message;
22432912Sartem 	DBusMessage *reply;
22442912Sartem 	DBusMessageIter iter;
22452912Sartem 
22462912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
22472912Sartem 
22482912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
22492912Sartem 						"/org/freedesktop/Hal/Manager",
22502912Sartem 						"org.freedesktop.Hal.Manager",
22512912Sartem 						"CommitToGdl");
22522912Sartem 	if (message == NULL) {
22532912Sartem 		fprintf (stderr,
22542912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
22552912Sartem 			 __FILE__, __LINE__);
22562912Sartem 		return FALSE;
22572912Sartem 	}
22582912Sartem 
22592912Sartem 	dbus_message_iter_init_append (message, &iter);
22602912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &temp_udi);
22612912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
22622912Sartem 
22632912Sartem 
22642912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
22652912Sartem 							   message, -1,
22662912Sartem 							   error);
2267*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
22682912Sartem 		dbus_message_unref (message);
22692912Sartem 		return FALSE;
22702912Sartem 	}
22712912Sartem 	if (reply == NULL) {
22722912Sartem 		dbus_message_unref (message);
22732912Sartem 		return FALSE;
22742912Sartem 	}
22752912Sartem 
22762912Sartem 	dbus_message_unref (message);
22772912Sartem 	dbus_message_unref (reply);
22782912Sartem 	return TRUE;
22792912Sartem }
22802912Sartem 
22812912Sartem /**
22822912Sartem  * libhal_remove_device:
22832912Sartem  * @ctx: the context for the connection to hald
22842912Sartem  * @udi: the Unique device id.
22852912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
22862912Sartem  *
22872912Sartem  * This method can be invoked when a device is removed. The HAL daemon
22882912Sartem  * will shut down the device. Note that the device may still be in the
22892912Sartem  * device list if the Persistent property is set to true.
22902912Sartem  *
22912912Sartem  * Note that the program invoking this method needs to run with super
22922912Sartem  * user privileges.
22932912Sartem  *
22942912Sartem  * Returns: TRUE if the device was removed, FALSE otherwise
22952912Sartem  */
22962912Sartem dbus_bool_t
libhal_remove_device(LibHalContext * ctx,const char * udi,DBusError * error)22972912Sartem libhal_remove_device (LibHalContext *ctx, const char *udi, DBusError *error)
22982912Sartem {
22992912Sartem 	DBusMessage *message;
23002912Sartem 	DBusMessage *reply;
23012912Sartem 	DBusMessageIter iter;
23022912Sartem 
23032912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
23042912Sartem 
23052912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
23062912Sartem 						"/org/freedesktop/Hal/Manager",
23072912Sartem 						"org.freedesktop.Hal.Manager",
23082912Sartem 						"Remove");
23092912Sartem 	if (message == NULL) {
23102912Sartem 		fprintf (stderr,
23112912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
23122912Sartem 			 __FILE__, __LINE__);
23132912Sartem 		return FALSE;
23142912Sartem 	}
23152912Sartem 
23162912Sartem 	dbus_message_iter_init_append (message, &iter);
23172912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
23182912Sartem 
23192912Sartem 
23202912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
23212912Sartem 							   message, -1,
23222912Sartem 							   error);
2323*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
23242912Sartem 		dbus_message_unref (message);
23252912Sartem 		return FALSE;
23262912Sartem 	}
23272912Sartem 	if (reply == NULL) {
23282912Sartem 		dbus_message_unref (message);
23292912Sartem 		return FALSE;
23302912Sartem 	}
23312912Sartem 
23322912Sartem 	dbus_message_unref (message);
23332912Sartem 	dbus_message_unref (reply);
23342912Sartem 	return TRUE;
23352912Sartem }
23362912Sartem 
23372912Sartem /**
23382912Sartem  * libhal_device_exists:
23392912Sartem  * @ctx: the context for the connection to hald
23402912Sartem  * @udi: the Unique device id.
23412912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
23422912Sartem  *
23432912Sartem  * Determine if a device exists.
23442912Sartem  *
23452912Sartem  * Returns: TRUE if the device exists
23462912Sartem  */
23472912Sartem dbus_bool_t
libhal_device_exists(LibHalContext * ctx,const char * udi,DBusError * error)23482912Sartem libhal_device_exists (LibHalContext *ctx, const char *udi, DBusError *error)
23492912Sartem {
23502912Sartem 	DBusMessage *message;
23512912Sartem 	DBusMessage *reply;
23522912Sartem 	DBusMessageIter iter, reply_iter;
23532912Sartem 	dbus_bool_t value;
23542912Sartem 	DBusError _error;
23552912Sartem 
23562912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
23572912Sartem 
23582912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
23592912Sartem 						"/org/freedesktop/Hal/Manager",
23602912Sartem 						"org.freedesktop.Hal.Manager",
23612912Sartem 						"DeviceExists");
23622912Sartem 	if (message == NULL) {
23632912Sartem 		fprintf (stderr,
23642912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
23652912Sartem 			 __FILE__, __LINE__);
23662912Sartem 		return FALSE;
23672912Sartem 	}
23682912Sartem 
23692912Sartem 	dbus_message_iter_init_append (message, &iter);
23702912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
23712912Sartem 
23722912Sartem 	dbus_error_init (&_error);
23732912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
23742912Sartem 							   message, -1,
23752912Sartem 							   &_error);
23762912Sartem 
23772912Sartem 	dbus_move_error (&_error, error);
23782912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
23792912Sartem 		dbus_message_unref (message);
23802912Sartem 		return FALSE;
23812912Sartem 	}
23822912Sartem 	if (reply == NULL) {
23832912Sartem 		dbus_message_unref (message);
23842912Sartem 		return FALSE;
23852912Sartem 	}
23862912Sartem 
23872912Sartem 	dbus_message_iter_init (reply, &reply_iter);
23882912Sartem 
23892912Sartem 	/* now analyze reply */
23902912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
23912912Sartem 		fprintf (stderr,
23922912Sartem 			 "%s %d : expected a bool in reply to DeviceExists\n",
23932912Sartem 			 __FILE__, __LINE__);
23942912Sartem 		dbus_message_unref (message);
23952912Sartem 		dbus_message_unref (reply);
23962912Sartem 		return FALSE;
23972912Sartem 	}
23982912Sartem 
23992912Sartem 	dbus_message_iter_get_basic (&reply_iter, &value);
24002912Sartem 
24012912Sartem 	dbus_message_unref (message);
24022912Sartem 	dbus_message_unref (reply);
24032912Sartem 	return value;
24042912Sartem }
24052912Sartem 
24062912Sartem /**
24072912Sartem  * libhal_device_property_exists:
24082912Sartem  * @ctx: the context for the connection to hald
24092912Sartem  * @udi: the Unique device id.
24102912Sartem  * @key: name of the property
24112912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
24122912Sartem  *
24132912Sartem  * Determine if a property on a device exists.
24142912Sartem  *
24152912Sartem  * Returns: TRUE if the device exists, FALSE otherwise
24162912Sartem  */
24172912Sartem dbus_bool_t
libhal_device_property_exists(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)24182912Sartem libhal_device_property_exists (LibHalContext *ctx,
24192912Sartem 			       const char *udi, const char *key, DBusError *error)
24202912Sartem {
24212912Sartem 	DBusMessage *message;
24222912Sartem 	DBusMessage *reply;
24232912Sartem 	DBusMessageIter iter, reply_iter;
24242912Sartem 	dbus_bool_t value;
24252912Sartem 	DBusError _error;
24262912Sartem 
24272912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
24282912Sartem 
24292912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
24302912Sartem 						"org.freedesktop.Hal.Device",
24312912Sartem 						"PropertyExists");
24322912Sartem 	if (message == NULL) {
24332912Sartem 		fprintf (stderr,
24342912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
24352912Sartem 			 __FILE__, __LINE__);
24362912Sartem 		return FALSE;
24372912Sartem 	}
24382912Sartem 
24392912Sartem 	dbus_message_iter_init_append (message, &iter);
24402912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
24412912Sartem 
24422912Sartem 	dbus_error_init (&_error);
24432912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
24442912Sartem 							   message, -1,
24452912Sartem 							   &_error);
24462912Sartem 
24472912Sartem 	dbus_move_error (&_error, error);
24482912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
24492912Sartem 		dbus_message_unref (message);
24502912Sartem 		return FALSE;
24512912Sartem 	}
24522912Sartem 	if (reply == NULL) {
24532912Sartem 		dbus_message_unref (message);
24542912Sartem 		return FALSE;
24552912Sartem 	}
24562912Sartem 
24572912Sartem 	dbus_message_iter_init (reply, &reply_iter);
24582912Sartem 
24592912Sartem 	/* now analyse reply */
24602912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
24612912Sartem 		fprintf (stderr, "%s %d : expected a bool in reply to "
24622912Sartem 			 "PropertyExists\n", __FILE__, __LINE__);
24632912Sartem 		dbus_message_unref (message);
24642912Sartem 		dbus_message_unref (reply);
24652912Sartem 		return FALSE;
24662912Sartem 	}
24672912Sartem 
24682912Sartem 	dbus_message_iter_get_basic (&reply_iter, &value);
24692912Sartem 
24702912Sartem 	dbus_message_unref (message);
24712912Sartem 	dbus_message_unref (reply);
24722912Sartem 	return value;
24732912Sartem }
24742912Sartem 
24752912Sartem /**
24762912Sartem  * libhal_merge_properties:
24772912Sartem  * @ctx: the context for the connection to hald
24782912Sartem  * @target_udi: the Unique device id of target device to merge to
24792912Sartem  * @source_udi: the Unique device id of device to merge from
24802912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
24812912Sartem  *
24822912Sartem  * Merge properties from one device to another.
24832912Sartem  *
24842912Sartem  * Returns: TRUE if the properties were merged, FALSE otherwise
24852912Sartem  */
24862912Sartem dbus_bool_t
libhal_merge_properties(LibHalContext * ctx,const char * target_udi,const char * source_udi,DBusError * error)24872912Sartem libhal_merge_properties (LibHalContext *ctx,
24882912Sartem 			 const char *target_udi, const char *source_udi, DBusError *error)
24892912Sartem {
24902912Sartem 	DBusMessage *message;
24912912Sartem 	DBusMessage *reply;
24922912Sartem 	DBusMessageIter iter;
24932912Sartem 
24942912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
24952912Sartem 
24962912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
24972912Sartem 						"/org/freedesktop/Hal/Manager",
24982912Sartem 						"org.freedesktop.Hal.Manager",
24992912Sartem 						"MergeProperties");
25002912Sartem 	if (message == NULL) {
25012912Sartem 		fprintf (stderr,
25022912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
25032912Sartem 			 __FILE__, __LINE__);
25042912Sartem 		return FALSE;
25052912Sartem 	}
25062912Sartem 
25072912Sartem 	dbus_message_iter_init_append (message, &iter);
25082912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &target_udi);
25092912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &source_udi);
25102912Sartem 
25112912Sartem 
25122912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
25132912Sartem 							   message, -1,
25142912Sartem 							   error);
2515*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
25162912Sartem 		dbus_message_unref (message);
25172912Sartem 		return FALSE;
25182912Sartem 	}
25192912Sartem 	if (reply == NULL) {
25202912Sartem 		dbus_message_unref (message);
25212912Sartem 		return FALSE;
25222912Sartem 	}
25232912Sartem 
25242912Sartem 	dbus_message_unref (message);
25252912Sartem 	dbus_message_unref (reply);
25262912Sartem 	return TRUE;
25272912Sartem }
25282912Sartem 
25292912Sartem /**
25302912Sartem  * libhal_device_matches:
25312912Sartem  * @ctx: the context for the connection to hald
25322912Sartem  * @udi1: the Unique Device Id for device 1
25332912Sartem  * @udi2: the Unique Device Id for device 2
25342912Sartem  * @property_namespace: the namespace for set of devices, e.g. "usb"
25352912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
25362912Sartem  *
25372912Sartem  * Check a set of properties for two devices matches.
25382912Sartem  *
25392912Sartem  * Checks that all properties where keys, starting with a given value
25402912Sartem  * (namespace), of the first device is in the second device and that
25412912Sartem  * they got the same value and type.
25422912Sartem  *
25432912Sartem  * Note that the other inclusion isn't tested, so there could be
25442912Sartem  * properties (from the given namespace) in the second device not
25452912Sartem  * present in the first device.
25462912Sartem  *
25472912Sartem  * Returns: TRUE if all properties starting with the given namespace
25482912Sartem  * parameter from one device is in the other and have the same value.
25492912Sartem  */
25502912Sartem dbus_bool_t
libhal_device_matches(LibHalContext * ctx,const char * udi1,const char * udi2,const char * property_namespace,DBusError * error)25512912Sartem libhal_device_matches (LibHalContext *ctx,
25522912Sartem 		       const char *udi1, const char *udi2,
25532912Sartem 		       const char *property_namespace, DBusError *error)
25542912Sartem {
25552912Sartem 	DBusMessage *message;
25562912Sartem 	DBusMessage *reply;
25572912Sartem 	DBusMessageIter iter, reply_iter;
25582912Sartem 	dbus_bool_t value;
25592912Sartem 	DBusError _error;
25602912Sartem 
25612912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
25622912Sartem 
25632912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
25642912Sartem 						"/org/freedesktop/Hal/Manager",
25652912Sartem 						"org.freedesktop.Hal.Manager",
25662912Sartem 						"DeviceMatches");
25672912Sartem 	if (message == NULL) {
25682912Sartem 		fprintf (stderr,
25692912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
25702912Sartem 			 __FILE__, __LINE__);
25712912Sartem 		return FALSE;
25722912Sartem 	}
25732912Sartem 
25742912Sartem 	dbus_message_iter_init_append (message, &iter);
25752912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi1);
25762912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi2);
25772912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, property_namespace);
25782912Sartem 
25792912Sartem 	dbus_error_init (&_error);
25802912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
25812912Sartem 							   message, -1,
25822912Sartem 							   &_error);
25832912Sartem 
25842912Sartem 	dbus_move_error (&_error, error);
25852912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
25862912Sartem 		dbus_message_unref (message);
25872912Sartem 		return FALSE;
25882912Sartem 	}
25892912Sartem 	if (reply == NULL) {
25902912Sartem 		dbus_message_unref (message);
25912912Sartem 		return FALSE;
25922912Sartem 	}
25932912Sartem 	/* now analyse reply */
25942912Sartem 	dbus_message_iter_init (reply, &reply_iter);
25952912Sartem 
25962912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
25972912Sartem 		fprintf (stderr,
25982912Sartem 			 "%s %d : expected a bool in reply to DeviceMatches\n",
25992912Sartem 			 __FILE__, __LINE__);
26002912Sartem 		dbus_message_unref (message);
26012912Sartem 		dbus_message_unref (reply);
26022912Sartem 		return FALSE;
26032912Sartem 	}
26042912Sartem 
26052912Sartem 	dbus_message_iter_get_basic (&reply_iter, &value);
26062912Sartem 
26072912Sartem 	dbus_message_unref (message);
26082912Sartem 	dbus_message_unref (reply);
26092912Sartem 	return value;
26102912Sartem }
26112912Sartem 
26122912Sartem /**
26132912Sartem  * libhal_device_print:
26142912Sartem  * @ctx: the context for the connection to hald
26152912Sartem  * @udi: the Unique Device Id
26162912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
26172912Sartem  *
26182912Sartem  * Print a device to stdout; useful for debugging.
26192912Sartem  *
26202912Sartem  * Returns: TRUE if device's information could be obtained, FALSE otherwise
26212912Sartem  */
26222912Sartem dbus_bool_t
libhal_device_print(LibHalContext * ctx,const char * udi,DBusError * error)26232912Sartem libhal_device_print (LibHalContext *ctx, const char *udi, DBusError *error)
26242912Sartem {
26252912Sartem 	int type;
26262912Sartem 	char *key;
26272912Sartem 	LibHalPropertySet *pset;
26282912Sartem 	LibHalPropertySetIterator i;
26292912Sartem 
26302912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
26312912Sartem 
26322912Sartem 	printf ("device_id = %s\n", udi);
26332912Sartem 
26342912Sartem 	if ((pset = libhal_device_get_all_properties (ctx, udi, error)) == NULL)
26352912Sartem 		return FALSE;
26362912Sartem 
26372912Sartem 	for (libhal_psi_init (&i, pset); libhal_psi_has_more (&i);
26382912Sartem 	     libhal_psi_next (&i)) {
26392912Sartem 		type = libhal_psi_get_type (&i);
26402912Sartem 		key = libhal_psi_get_key (&i);
26412912Sartem 
26422912Sartem 		switch (type) {
26432912Sartem 		case LIBHAL_PROPERTY_TYPE_STRING:
26442912Sartem 			printf ("    %s = '%s' (string)\n", key,
26452912Sartem 				libhal_psi_get_string (&i));
26462912Sartem 			break;
26472912Sartem 		case LIBHAL_PROPERTY_TYPE_INT32:
26482912Sartem 			printf ("    %s = %d = 0x%x (int)\n", key,
26492912Sartem 				libhal_psi_get_int (&i),
26502912Sartem 				libhal_psi_get_int (&i));
26512912Sartem 			break;
26522912Sartem 		case LIBHAL_PROPERTY_TYPE_UINT64:
26532912Sartem 			printf ("    %s = %llu = 0x%llx (uint64)\n", key,
26542912Sartem 				(long long unsigned int) libhal_psi_get_uint64 (&i),
26552912Sartem 				(long long unsigned int) libhal_psi_get_uint64 (&i));
26562912Sartem 			break;
26572912Sartem 		case LIBHAL_PROPERTY_TYPE_BOOLEAN:
26582912Sartem 			printf ("    %s = %s (bool)\n", key,
26592912Sartem 				(libhal_psi_get_bool (&i) ? "true" :
26602912Sartem 				 "false"));
26612912Sartem 			break;
26622912Sartem 		case LIBHAL_PROPERTY_TYPE_DOUBLE:
26632912Sartem 			printf ("    %s = %g (double)\n", key,
26642912Sartem 				libhal_psi_get_double (&i));
26652912Sartem 			break;
26662912Sartem 		case LIBHAL_PROPERTY_TYPE_STRLIST:
26672912Sartem 		{
26682912Sartem 			unsigned int j;
26692912Sartem 			char **str_list;
26702912Sartem 
26712912Sartem 			str_list = libhal_psi_get_strlist (&i);
26722912Sartem 			printf ("    %s = [", key);
26732912Sartem 			for (j = 0; str_list[j] != NULL; j++) {
26742912Sartem 				printf ("'%s'", str_list[j]);
26752912Sartem 				if (str_list[j+1] != NULL)
26762912Sartem 					printf (", ");
26772912Sartem 			}
26782912Sartem 			printf ("] (string list)\n");
26792912Sartem 
26802912Sartem 			break;
26812912Sartem 		}
26822912Sartem 		default:
26832912Sartem 			printf ("    *** unknown type for key %s\n", key);
26842912Sartem 			break;
26852912Sartem 		}
26862912Sartem 	}
26872912Sartem 
26882912Sartem 	libhal_free_property_set (pset);
26892912Sartem 
26902912Sartem 	return TRUE;
26912912Sartem }
26922912Sartem 
26932912Sartem /**
26942912Sartem  * libhal_manager_find_device_string_match:
26952912Sartem  * @ctx: the context for the connection to hald
26962912Sartem  * @key: name of the property
26972912Sartem  * @value: the value to match
26982912Sartem  * @num_devices: pointer to store number of devices
26992912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
27002912Sartem  *
27012912Sartem  * Find a device in the GDL where a single string property matches a
27022912Sartem  * given value.
27032912Sartem  *
27042912Sartem  * Returns: UDI of devices; free with libhal_free_string_array()
27052912Sartem  */
27062912Sartem char **
libhal_manager_find_device_string_match(LibHalContext * ctx,const char * key,const char * value,int * num_devices,DBusError * error)27072912Sartem libhal_manager_find_device_string_match (LibHalContext *ctx,
27082912Sartem 					 const char *key,
27092912Sartem 					 const char *value, int *num_devices, DBusError *error)
27102912Sartem {
27112912Sartem 	DBusMessage *message;
27122912Sartem 	DBusMessage *reply;
27132912Sartem 	DBusMessageIter iter, iter_array, reply_iter;
27142912Sartem 	char **hal_device_names;
27152912Sartem 	DBusError _error;
27162912Sartem 
27172912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
27182912Sartem 
27192912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
27202912Sartem 						"/org/freedesktop/Hal/Manager",
27212912Sartem 						"org.freedesktop.Hal.Manager",
27222912Sartem 						"FindDeviceStringMatch");
27232912Sartem 	if (message == NULL) {
27242912Sartem 		fprintf (stderr,
27252912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
27262912Sartem 			 __FILE__, __LINE__);
27272912Sartem 		return NULL;
27282912Sartem 	}
27292912Sartem 
27302912Sartem 	dbus_message_iter_init_append (message, &iter);
27312912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
27322912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
27332912Sartem 
27342912Sartem 	dbus_error_init (&_error);
27352912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
27362912Sartem 							   message, -1,
27372912Sartem 							   &_error);
27382912Sartem 
27392912Sartem 	dbus_move_error (&_error, error);
27402912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
27412912Sartem 		dbus_message_unref (message);
27422912Sartem 		return NULL;
27432912Sartem 	}
27442912Sartem 	if (reply == NULL) {
27452912Sartem 		dbus_message_unref (message);
27462912Sartem 		return NULL;
27472912Sartem 	}
27482912Sartem 	/* now analyse reply */
27492912Sartem 	dbus_message_iter_init (reply, &reply_iter);
27502912Sartem 
27512912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
27522912Sartem 		fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
27532912Sartem 		return NULL;
27542912Sartem 	}
27552912Sartem 
27562912Sartem 	dbus_message_iter_recurse (&reply_iter, &iter_array);
27572912Sartem 
27582912Sartem 	hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
27592912Sartem 
27602912Sartem 	dbus_message_unref (reply);
27612912Sartem 	dbus_message_unref (message);
27622912Sartem 
27632912Sartem 	return hal_device_names;
27642912Sartem }
27652912Sartem 
27662912Sartem 
27672912Sartem /**
27682912Sartem  * libhal_device_add_capability:
27692912Sartem  * @ctx: the context for the connection to hald
27702912Sartem  * @udi: the Unique Device Id
27712912Sartem  * @capability: the capability name to add
27722912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
27732912Sartem  *
27742912Sartem  * Assign a capability to a device.
27752912Sartem  *
27762912Sartem  * Returns: TRUE if the capability was added, FALSE if the device didn't exist
27772912Sartem  */
27782912Sartem dbus_bool_t
libhal_device_add_capability(LibHalContext * ctx,const char * udi,const char * capability,DBusError * error)27792912Sartem libhal_device_add_capability (LibHalContext *ctx,
27802912Sartem 			      const char *udi, const char *capability, DBusError *error)
27812912Sartem {
27822912Sartem 	DBusMessage *message;
27832912Sartem 	DBusMessage *reply;
27842912Sartem 	DBusMessageIter iter;
27852912Sartem 
27862912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
27872912Sartem 
27882912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
27892912Sartem 						"org.freedesktop.Hal.Device",
27902912Sartem 						"AddCapability");
27912912Sartem 	if (message == NULL) {
27922912Sartem 		fprintf (stderr,
27932912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
27942912Sartem 			 __FILE__, __LINE__);
27952912Sartem 		return FALSE;
27962912Sartem 	}
27972912Sartem 
27982912Sartem 	dbus_message_iter_init_append (message, &iter);
27992912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
28002912Sartem 
28012912Sartem 
28022912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
28032912Sartem 							   message, -1,
28042912Sartem 							   error);
2805*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
28062912Sartem 		dbus_message_unref (message);
28072912Sartem 		return FALSE;
28082912Sartem 	}
28092912Sartem 
28102912Sartem 	if (reply == NULL) {
28112912Sartem 		dbus_message_unref (message);
28122912Sartem 		return FALSE;
28132912Sartem 	}
28142912Sartem 
28152912Sartem 	dbus_message_unref (reply);
28162912Sartem 	dbus_message_unref (message);
28172912Sartem 	return TRUE;
28182912Sartem }
28192912Sartem 
28202912Sartem /**
28212912Sartem  * libhal_device_query_capability:
28222912Sartem  * @ctx: the context for the connection to hald
28232912Sartem  * @udi: the Unique Device Id
28242912Sartem  * @capability: the capability name
28252912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
28262912Sartem  *
28272912Sartem  * Check if a device has a capability. The result is undefined if the
28282912Sartem  * device doesn't exist.
28292912Sartem  *
28302912Sartem  * Returns: TRUE if the device has the capability, otherwise FALSE
28312912Sartem  */
28322912Sartem dbus_bool_t
libhal_device_query_capability(LibHalContext * ctx,const char * udi,const char * capability,DBusError * error)28332912Sartem libhal_device_query_capability (LibHalContext *ctx, const char *udi, const char *capability, DBusError *error)
28342912Sartem {
28352912Sartem 	char **caps;
28362912Sartem 	unsigned int i;
28372912Sartem 	dbus_bool_t ret;
28382912Sartem 
28392912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
28402912Sartem 
28412912Sartem 	ret = FALSE;
28422912Sartem 
28432912Sartem 	caps = libhal_device_get_property_strlist (ctx, udi, "info.capabilities", error);
28442912Sartem 	if (caps != NULL) {
28452912Sartem 		for (i = 0; caps[i] != NULL; i++) {
28462912Sartem 			if (strcmp (caps[i], capability) == 0) {
28472912Sartem 				ret = TRUE;
28482912Sartem 				break;
28492912Sartem 			}
28502912Sartem 		}
28512912Sartem 		libhal_free_string_array (caps);
28522912Sartem 	}
28532912Sartem 
28542912Sartem 	return ret;
28552912Sartem }
28562912Sartem 
28572912Sartem /**
28582912Sartem  * libhal_find_device_by_capability:
28592912Sartem  * @ctx: the context for the connection to hald
28602912Sartem  * @capability: the capability name
28612912Sartem  * @num_devices: pointer to store number of devices
28622912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
28632912Sartem  *
28642912Sartem  * Find devices with a given capability.
28652912Sartem  *
28662912Sartem  * Returns: UDI of devices; free with libhal_free_string_array()
28672912Sartem  */
28682912Sartem char **
libhal_find_device_by_capability(LibHalContext * ctx,const char * capability,int * num_devices,DBusError * error)28692912Sartem libhal_find_device_by_capability (LibHalContext *ctx,
28702912Sartem 				  const char *capability, int *num_devices, DBusError *error)
28712912Sartem {
28722912Sartem 	DBusMessage *message;
28732912Sartem 	DBusMessage *reply;
28742912Sartem 	DBusMessageIter iter, iter_array, reply_iter;
28752912Sartem 	char **hal_device_names;
28762912Sartem 	DBusError _error;
28772912Sartem 
28782912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
28792912Sartem 
28802912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
28812912Sartem 						"/org/freedesktop/Hal/Manager",
28822912Sartem 						"org.freedesktop.Hal.Manager",
28832912Sartem 						"FindDeviceByCapability");
28842912Sartem 	if (message == NULL) {
28852912Sartem 		fprintf (stderr,
28862912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
28872912Sartem 			 __FILE__, __LINE__);
28882912Sartem 		return NULL;
28892912Sartem 	}
28902912Sartem 
28912912Sartem 	dbus_message_iter_init_append (message, &iter);
28922912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
28932912Sartem 
28942912Sartem 	dbus_error_init (&_error);
28952912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
28962912Sartem 							   message, -1,
28972912Sartem 							   &_error);
28982912Sartem 
28992912Sartem 	dbus_move_error (&_error, error);
29002912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
29012912Sartem 		dbus_message_unref (message);
29022912Sartem 		return NULL;
29032912Sartem 	}
29042912Sartem 	if (reply == NULL) {
29052912Sartem 		dbus_message_unref (message);
29062912Sartem 		return NULL;
29072912Sartem 	}
29082912Sartem 	/* now analyse reply */
29092912Sartem 	dbus_message_iter_init (reply, &reply_iter);
29102912Sartem 
29112912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
29122912Sartem 		fprintf (stderr, "%s %d : wrong reply from hald.  Expecting an array.\n", __FILE__, __LINE__);
29132912Sartem 		return NULL;
29142912Sartem 	}
29152912Sartem 
29162912Sartem 	dbus_message_iter_recurse (&reply_iter, &iter_array);
29172912Sartem 
29182912Sartem 	hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
29192912Sartem 
29202912Sartem 	dbus_message_unref (reply);
29212912Sartem 	dbus_message_unref (message);
29222912Sartem 
29232912Sartem 	return hal_device_names;
29242912Sartem }
29252912Sartem 
29262912Sartem /**
29272912Sartem  * libhal_device_property_watch_all:
29282912Sartem  * @ctx: the context for the connection to hald
29292912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
29302912Sartem  *
29312912Sartem  * Watch all devices, ie. the device_property_changed callback is
29322912Sartem  * invoked when the properties on any device changes.
29332912Sartem  *
29342912Sartem  * Returns: TRUE only if the operation succeeded
29352912Sartem  */
29362912Sartem dbus_bool_t
libhal_device_property_watch_all(LibHalContext * ctx,DBusError * error)29372912Sartem libhal_device_property_watch_all (LibHalContext *ctx, DBusError *error)
29382912Sartem {
29392912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
29402912Sartem 
29412912Sartem 	dbus_bus_add_match (ctx->connection,
29422912Sartem 			    "type='signal',"
29432912Sartem 			    "interface='org.freedesktop.Hal.Device',"
29442912Sartem 			    "sender='org.freedesktop.Hal'", error);
2945*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
29462912Sartem 		return FALSE;
29472912Sartem 	}
29482912Sartem 	return TRUE;
29492912Sartem }
29502912Sartem 
29512912Sartem 
29522912Sartem /**
29532912Sartem  * libhal_device_add_property_watch:
29542912Sartem  * @ctx: the context for the connection to hald
29552912Sartem  * @udi: the Unique Device Id
29562912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
29572912Sartem  *
29582912Sartem  * Add a watch on a device, so the device_property_changed callback is
29592912Sartem  * invoked when the properties on the given device changes.
29602912Sartem  *
29612912Sartem  * The application itself is responsible for deleting the watch, using
29622912Sartem  * libhal_device_remove_property_watch, if the device is removed.
29632912Sartem  *
29642912Sartem  * Returns: TRUE only if the operation succeeded
29652912Sartem  */
29662912Sartem dbus_bool_t
libhal_device_add_property_watch(LibHalContext * ctx,const char * udi,DBusError * error)29672912Sartem libhal_device_add_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
29682912Sartem {
29692912Sartem 	char buf[512];
29702912Sartem 
29712912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
29722912Sartem 
29732912Sartem 	snprintf (buf, 512,
29742912Sartem 		  "type='signal',"
29752912Sartem 		  "interface='org.freedesktop.Hal.Device',"
29762912Sartem 		  "sender='org.freedesktop.Hal'," "path=%s", udi);
29772912Sartem 
29782912Sartem 	dbus_bus_add_match (ctx->connection, buf, error);
2979*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
29802912Sartem 		return FALSE;
29812912Sartem 	}
29822912Sartem 	return TRUE;
29832912Sartem }
29842912Sartem 
29852912Sartem 
29862912Sartem /**
29872912Sartem  * libhal_device_remove_property_watch:
29882912Sartem  * @ctx: the context for the connection to hald
29892912Sartem  * @udi: the Unique Device Id
29902912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
29912912Sartem  *
29922912Sartem  * Remove a watch on a device.
29932912Sartem  *
29942912Sartem  * Returns: TRUE only if the operation succeeded
29952912Sartem  */
29962912Sartem dbus_bool_t
libhal_device_remove_property_watch(LibHalContext * ctx,const char * udi,DBusError * error)29972912Sartem libhal_device_remove_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
29982912Sartem {
29992912Sartem 	char buf[512];
30002912Sartem 
30012912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
30022912Sartem 
30032912Sartem 	snprintf (buf, 512,
30042912Sartem 		  "type='signal',"
30052912Sartem 		  "interface='org.freedesktop.Hal.Device',"
30062912Sartem 		  "sender='org.freedesktop.Hal'," "path=%s", udi);
30072912Sartem 
30082912Sartem 	dbus_bus_remove_match (ctx->connection, buf, error);
3009*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
30102912Sartem 		return FALSE;
30112912Sartem 	}
30122912Sartem 	return TRUE;
30132912Sartem }
30142912Sartem 
30152912Sartem 
30162912Sartem /**
30172912Sartem  * libhal_ctx_new:
30182912Sartem  *
30192912Sartem  * Create a new LibHalContext
30202912Sartem  *
30212912Sartem  * Returns: a new uninitialized LibHalContext object
30222912Sartem  */
30232912Sartem LibHalContext *
libhal_ctx_new(void)30242912Sartem libhal_ctx_new (void)
30252912Sartem {
30262912Sartem 	LibHalContext *ctx;
30272912Sartem 
30282912Sartem 	if (!libhal_already_initialized_once) {
30292912Sartem 		bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
30302912Sartem 		bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
30312912Sartem 
30322912Sartem 		libhal_already_initialized_once = TRUE;
30332912Sartem 	}
30342912Sartem 
30352912Sartem 	ctx = calloc (1, sizeof (LibHalContext));
30362912Sartem 	if (ctx == NULL) {
30372912Sartem 		fprintf (stderr,
30382912Sartem 			 "%s %d : Failed to allocate %d bytes\n",
30392912Sartem 			 __FILE__, __LINE__, sizeof (LibHalContext));
30402912Sartem 		return NULL;
30412912Sartem 	}
30422912Sartem 
30432912Sartem 	ctx->is_initialized = FALSE;
30442912Sartem 	ctx->is_shutdown = FALSE;
30452912Sartem 	ctx->connection = NULL;
30462912Sartem 	ctx->is_direct = FALSE;
30472912Sartem 
30482912Sartem 	return ctx;
30492912Sartem }
30502912Sartem 
30512912Sartem /**
30522912Sartem  * libhal_ctx_set_cache:
30532912Sartem  * @ctx: context to enable/disable cache for
30542912Sartem  * @use_cache: whether or not to use cache
30552912Sartem  *
30562912Sartem  * Enable or disable caching. Note: Caching is not actually
30572912Sartem  * implemented yet.
30582912Sartem  *
30592912Sartem  * Returns: TRUE if cache was successfully enabled/disabled, FALSE otherwise
30602912Sartem  */
30612912Sartem dbus_bool_t
libhal_ctx_set_cache(LibHalContext * ctx,dbus_bool_t use_cache)30622912Sartem libhal_ctx_set_cache (LibHalContext *ctx, dbus_bool_t use_cache)
30632912Sartem {
30642912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
30652912Sartem 
30662912Sartem 	ctx->cache_enabled = use_cache;
30672912Sartem 	return TRUE;
30682912Sartem }
30692912Sartem 
30702912Sartem /**
30712912Sartem  * libhal_ctx_set_dbus_connection:
30722912Sartem  * @ctx: context to set connection for
30732912Sartem  * @conn: DBus connection to use
30742912Sartem  *
30752912Sartem  * Set DBus connection to use to talk to hald.
30762912Sartem  *
30772912Sartem  * Returns: TRUE if connection was successfully set, FALSE otherwise
30782912Sartem  */
30792912Sartem dbus_bool_t
libhal_ctx_set_dbus_connection(LibHalContext * ctx,DBusConnection * conn)30802912Sartem libhal_ctx_set_dbus_connection (LibHalContext *ctx, DBusConnection *conn)
30812912Sartem {
30822912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
30832912Sartem 
30842912Sartem 	if (conn == NULL)
30852912Sartem 		return FALSE;
30862912Sartem 
30872912Sartem 	ctx->connection = conn;
30882912Sartem 	return TRUE;
30892912Sartem }
30902912Sartem 
30912912Sartem /**
30922912Sartem  * libhal_ctx_get_dbus_connection:
30932912Sartem  * @ctx: context to get connection for
30942912Sartem  *
30952912Sartem  * Get DBus connection used for talking to hald.
30962912Sartem  *
30972912Sartem  * Returns: DBus connection to use or NULL
30982912Sartem  */
30992912Sartem DBusConnection *
libhal_ctx_get_dbus_connection(LibHalContext * ctx)31002912Sartem libhal_ctx_get_dbus_connection (LibHalContext *ctx)
31012912Sartem {
31022912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
31032912Sartem 
31042912Sartem 	return ctx->connection;
31052912Sartem }
31062912Sartem 
31072912Sartem 
31082912Sartem /**
31092912Sartem  * libhal_ctx_init:
31102912Sartem  * @ctx: Context for connection to hald (D-BUS connection should be set with libhal_ctx_set_dbus_connection)
31112912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
31122912Sartem  *
31132912Sartem  * Initialize the connection to hald.
31142912Sartem  *
31152912Sartem  * Returns: TRUE if initialization succeeds, FALSE otherwise
31162912Sartem  */
31172912Sartem dbus_bool_t
libhal_ctx_init(LibHalContext * ctx,DBusError * error)31182912Sartem libhal_ctx_init (LibHalContext *ctx, DBusError *error)
31192912Sartem {
31202912Sartem 	DBusError _error;
31212912Sartem 	dbus_bool_t hald_exists;
31222912Sartem 
31232912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
31242912Sartem 
31252912Sartem 	if (ctx->connection == NULL)
31262912Sartem 		return FALSE;
31272912Sartem 
31282912Sartem 	dbus_error_init (&_error);
31292912Sartem 	hald_exists = dbus_bus_name_has_owner (ctx->connection, "org.freedesktop.Hal", &_error);
31302912Sartem 	dbus_move_error (&_error, error);
31312912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
31322912Sartem 		return FALSE;
31332912Sartem 	}
31342912Sartem 
31352912Sartem 	if (!hald_exists) {
31362912Sartem 		return FALSE;
31372912Sartem 	}
31382912Sartem 
31392912Sartem 
31402912Sartem 	if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) {
31412912Sartem 		return FALSE;
31422912Sartem 	}
31432912Sartem 
31442912Sartem 	dbus_bus_add_match (ctx->connection,
31452912Sartem 			    "type='signal',"
31462912Sartem 			    "interface='org.freedesktop.Hal.Manager',"
31472912Sartem 			    "sender='org.freedesktop.Hal',"
31482912Sartem 			    "path='/org/freedesktop/Hal/Manager'", &_error);
31492912Sartem 	dbus_move_error (&_error, error);
31502912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
31512912Sartem 		return FALSE;
31522912Sartem 	}
31532912Sartem 	ctx->is_initialized = TRUE;
31542912Sartem 	ctx->is_direct = FALSE;
31552912Sartem 
31562912Sartem 	return TRUE;
31572912Sartem }
31582912Sartem 
31592912Sartem /**
31602912Sartem  * libhal_ctx_init_direct:
31612912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
31622912Sartem  *
31632912Sartem  * Create an already initialized connection to hald. This function should only be used by HAL helpers.
31642912Sartem  *
31652912Sartem  * Returns: A pointer to an already initialized LibHalContext
31662912Sartem  */
31672912Sartem LibHalContext *
libhal_ctx_init_direct(DBusError * error)31682912Sartem libhal_ctx_init_direct (DBusError *error)
31692912Sartem {
31702912Sartem 	char *hald_addr;
31712912Sartem 	LibHalContext *ctx;
31722912Sartem 	DBusError _error;
31732912Sartem 
31742912Sartem 	ctx = libhal_ctx_new ();
31752912Sartem 	if (ctx == NULL)
31762912Sartem 		goto out;
31772912Sartem 
31782912Sartem 	if (((hald_addr = getenv ("HALD_DIRECT_ADDR"))) == NULL) {
31792912Sartem 		libhal_ctx_free (ctx);
31802912Sartem 		ctx = NULL;
31812912Sartem 		goto out;
31822912Sartem 	}
31832912Sartem 
31842912Sartem 	dbus_error_init (&_error);
31852912Sartem 	ctx->connection = dbus_connection_open (hald_addr, &_error);
31862912Sartem 	dbus_move_error (&_error, error);
31872912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
31882912Sartem 		libhal_ctx_free (ctx);
31892912Sartem 		ctx = NULL;
31902912Sartem 		goto out;
31912912Sartem 	}
31922912Sartem 
31932912Sartem 	ctx->is_initialized = TRUE;
31942912Sartem 	ctx->is_direct = TRUE;
31952912Sartem 
31962912Sartem out:
31972912Sartem 	return ctx;
31982912Sartem }
31992912Sartem 
32002912Sartem /**
32012912Sartem  * libhal_ctx_shutdown:
32022912Sartem  * @ctx: the context for the connection to hald
32032912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
32042912Sartem  *
32052912Sartem  * Shut down a connection to hald.
32062912Sartem  *
32072912Sartem  * Returns: TRUE if connection successfully shut down, FALSE otherwise
32082912Sartem  */
32092912Sartem dbus_bool_t
libhal_ctx_shutdown(LibHalContext * ctx,DBusError * error)32102912Sartem libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error)
32112912Sartem {
32122912Sartem 	DBusError myerror;
32132912Sartem 
32142912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
32152912Sartem 
32162912Sartem 	if (ctx->is_direct) {
32172912Sartem 		/* for some reason dbus_connection_set_exit_on_disconnect doesn't work yet so don't unref */
32182912Sartem 		/*dbus_connection_unref (ctx->connection);*/
32192912Sartem 	} else {
32202912Sartem 		dbus_error_init (&myerror);
32212912Sartem 		dbus_bus_remove_match (ctx->connection,
32222912Sartem 				       "type='signal',"
32232912Sartem 				       "interface='org.freedesktop.Hal.Manager',"
32242912Sartem 				       "sender='org.freedesktop.Hal',"
32252912Sartem 				       "path='/org/freedesktop/Hal/Manager'", &myerror);
322611283SFei.Feng@Sun.COM 		dbus_move_error(&myerror, error);
322711283SFei.Feng@Sun.COM 		if (error != NULL && dbus_error_is_set(error)) {
32282912Sartem 			fprintf (stderr, "%s %d : Error unsubscribing to signals, error=%s\n",
32292912Sartem 				 __FILE__, __LINE__, error->message);
32302912Sartem 			/** @todo  clean up */
32312912Sartem 		}
32322912Sartem 
32332912Sartem 		/* TODO: remove other matches */
32342912Sartem 
32352912Sartem 		dbus_connection_remove_filter (ctx->connection, filter_func, ctx);
32362912Sartem 	}
32372912Sartem 
32382912Sartem 	ctx->is_initialized = FALSE;
32392912Sartem 
32402912Sartem 	return TRUE;
32412912Sartem }
32422912Sartem 
32432912Sartem /**
32442912Sartem  * libhal_ctx_free:
32452912Sartem  * @ctx: pointer to a LibHalContext
32462912Sartem  *
32472912Sartem  * Free a LibHalContext resource.
32482912Sartem  *
32492912Sartem  * Returns: TRUE
32502912Sartem  */
32512912Sartem dbus_bool_t
libhal_ctx_free(LibHalContext * ctx)32522912Sartem libhal_ctx_free (LibHalContext *ctx)
32532912Sartem {
32542912Sartem 	free (ctx);
32552912Sartem 	return TRUE;
32562912Sartem }
32572912Sartem 
32582912Sartem /**
32592912Sartem  * libhal_ctx_set_device_added:
32602912Sartem  * @ctx: the context for the connection to hald
32612912Sartem  * @callback: the function to call when a device is added
32622912Sartem  *
32632912Sartem  * Set the callback for when a device is added
32642912Sartem  *
32652912Sartem  * Returns: TRUE if callback was successfully set, FALSE otherwise
32662912Sartem  */
32672912Sartem dbus_bool_t
libhal_ctx_set_device_added(LibHalContext * ctx,LibHalDeviceAdded callback)32682912Sartem libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback)
32692912Sartem {
32702912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
32712912Sartem 
32722912Sartem 	ctx->device_added = callback;
32732912Sartem 	return TRUE;
32742912Sartem }
32752912Sartem 
32762912Sartem /**
32772912Sartem  * libhal_ctx_set_device_removed:
32782912Sartem  * @ctx: the context for the connection to hald
32792912Sartem  * @callback: the function to call when a device is removed
32802912Sartem  *
32812912Sartem  * Set the callback for when a device is removed.
32822912Sartem  *
32832912Sartem  * Returns: TRUE if callback was successfully set, FALSE otherwise
32842912Sartem  */
32852912Sartem dbus_bool_t
libhal_ctx_set_device_removed(LibHalContext * ctx,LibHalDeviceRemoved callback)32862912Sartem libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback)
32872912Sartem {
32882912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
32892912Sartem 
32902912Sartem 	ctx->device_removed = callback;
32912912Sartem 	return TRUE;
32922912Sartem }
32932912Sartem 
32942912Sartem /**
32952912Sartem  * libhal_ctx_set_device_new_capability:
32962912Sartem  * @ctx: the context for the connection to hald
32972912Sartem  * @callback: the function to call when a device gains a new capability
32982912Sartem  *
32992912Sartem  * Set the callback for when a device gains a new capability.
33002912Sartem  *
33012912Sartem  * Returns: TRUE if callback was successfully set, FALSE otherwise
33022912Sartem  */
33032912Sartem dbus_bool_t
libhal_ctx_set_device_new_capability(LibHalContext * ctx,LibHalDeviceNewCapability callback)33042912Sartem libhal_ctx_set_device_new_capability (LibHalContext *ctx, LibHalDeviceNewCapability callback)
33052912Sartem {
33062912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
33072912Sartem 
33082912Sartem 	ctx->device_new_capability = callback;
33092912Sartem 	return TRUE;
33102912Sartem }
33112912Sartem 
33122912Sartem /**
33132912Sartem  * libhal_ctx_set_device_lost_capability:
33142912Sartem  * @ctx: the context for the connection to hald
33152912Sartem  * @callback: the function to call when a device loses a capability
33162912Sartem  *
33172912Sartem  * Set the callback for when a device loses a capability
33182912Sartem  *
33192912Sartem  * Returns: TRUE if callback was successfully set, FALSE otherwise
33202912Sartem  */
33212912Sartem dbus_bool_t
libhal_ctx_set_device_lost_capability(LibHalContext * ctx,LibHalDeviceLostCapability callback)33222912Sartem libhal_ctx_set_device_lost_capability (LibHalContext *ctx, LibHalDeviceLostCapability callback)
33232912Sartem {
33242912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
33252912Sartem 
33262912Sartem 	ctx->device_lost_capability = callback;
33272912Sartem 	return TRUE;
33282912Sartem }
33292912Sartem 
33302912Sartem /**
33312912Sartem  * libhal_ctx_set_device_property_modified:
33322912Sartem  * @ctx: the context for the connection to hald
33332912Sartem  * @callback: the function to call when a property is modified on a device
33342912Sartem  *
33352912Sartem  * Set the callback for when a property is modified on a device.
33362912Sartem  *
33372912Sartem  * Returns: TRUE if callback was successfully set, FALSE otherwise
33382912Sartem  */
33392912Sartem dbus_bool_t
libhal_ctx_set_device_property_modified(LibHalContext * ctx,LibHalDevicePropertyModified callback)33402912Sartem libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibHalDevicePropertyModified callback)
33412912Sartem {
33422912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
33432912Sartem 
33442912Sartem 	ctx->device_property_modified = callback;
33452912Sartem 	return TRUE;
33462912Sartem }
33472912Sartem 
33482912Sartem /**
33492912Sartem  * libhal_ctx_set_device_condition:
33502912Sartem  * @ctx: the context for the connection to hald
33512912Sartem  * @callback: the function to call when a device emits a condition
33522912Sartem  *
33532912Sartem  * Set the callback for when a device emits a condition
33542912Sartem  *
33552912Sartem  * Returns: TRUE if callback was successfully set, FALSE otherwise
33562912Sartem  */
33572912Sartem dbus_bool_t
libhal_ctx_set_device_condition(LibHalContext * ctx,LibHalDeviceCondition callback)33582912Sartem libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback)
33592912Sartem {
33602912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
33612912Sartem 
33622912Sartem 	ctx->device_condition = callback;
33632912Sartem 	return TRUE;
33642912Sartem }
33652912Sartem 
33662912Sartem /**
33672912Sartem  * libhal_string_array_length:
33682912Sartem  * @str_array: array of strings to consider
33692912Sartem  *
33702912Sartem  * Get the length of an array of strings.
33712912Sartem  *
33722912Sartem  * Returns: Number of strings in array
33732912Sartem  */
33742912Sartem unsigned int
libhal_string_array_length(char ** str_array)33752912Sartem libhal_string_array_length (char **str_array)
33762912Sartem {
33772912Sartem 	unsigned int i;
33782912Sartem 
33792912Sartem 	if (str_array == NULL)
33802912Sartem 		return 0;
33812912Sartem 
33822912Sartem 	for (i = 0; str_array[i] != NULL; i++)
33832912Sartem 		;
33842912Sartem 
33852912Sartem 	return i;
33862912Sartem }
33872912Sartem 
33882912Sartem 
33892912Sartem /**
33902912Sartem  * libhal_device_rescan:
33912912Sartem  * @ctx: the context for the connection to hald
33922912Sartem  * @udi: the Unique id of device
33932912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
33942912Sartem  *
33952912Sartem  * TODO document me.
33962912Sartem  *
33972912Sartem  * Returns: Whether the operation succeeded
33982912Sartem  */
33992912Sartem dbus_bool_t
libhal_device_rescan(LibHalContext * ctx,const char * udi,DBusError * error)34002912Sartem libhal_device_rescan (LibHalContext *ctx, const char *udi, DBusError *error)
34012912Sartem {
34022912Sartem 	DBusMessage *message;
34032912Sartem 	DBusMessageIter reply_iter;
34042912Sartem 	DBusMessage *reply;
34052912Sartem 	dbus_bool_t result;
34062912Sartem 
34072912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
34082912Sartem 
34092912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
34102912Sartem 						"org.freedesktop.Hal.Device",
34112912Sartem 						"Rescan");
34122912Sartem 
34132912Sartem 	if (message == NULL) {
34142912Sartem 		fprintf (stderr,
34152912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
34162912Sartem 			 __FILE__, __LINE__);
34172912Sartem 		return FALSE;
34182912Sartem 	}
34192912Sartem 
34202912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
34212912Sartem 							   message, -1,
34222912Sartem 							   error);
34232912Sartem 
3424*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
34252912Sartem 		dbus_message_unref (message);
34262912Sartem 		return FALSE;
34272912Sartem 	}
34282912Sartem 
34292912Sartem 	dbus_message_unref (message);
34302912Sartem 
34312912Sartem 	if (reply == NULL)
34322912Sartem 		return FALSE;
34332912Sartem 
34342912Sartem 	dbus_message_iter_init (reply, &reply_iter);
34352912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) !=
34362912Sartem 		   DBUS_TYPE_BOOLEAN) {
34372912Sartem 		dbus_message_unref (message);
34382912Sartem 		dbus_message_unref (reply);
34392912Sartem 		return FALSE;
34402912Sartem 	}
34412912Sartem 	dbus_message_iter_get_basic (&reply_iter, &result);
34422912Sartem 
34432912Sartem 	dbus_message_unref (reply);
34442912Sartem 
34452912Sartem 	return result;
34462912Sartem }
34472912Sartem 
34482912Sartem /**
34492912Sartem  * libhal_device_reprobe:
34502912Sartem  * @ctx: the context for the connection to hald
34512912Sartem  * @udi: the Unique id of device
34522912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
34532912Sartem  *
34542912Sartem  * TODO document me.
34552912Sartem  *
34562912Sartem  * Returns: Whether the operation succeeded
34572912Sartem  */
34582912Sartem dbus_bool_t
libhal_device_reprobe(LibHalContext * ctx,const char * udi,DBusError * error)34592912Sartem libhal_device_reprobe (LibHalContext *ctx, const char *udi, DBusError *error)
34602912Sartem {
34612912Sartem 	DBusMessage *message;
34622912Sartem 	DBusMessageIter reply_iter;
34632912Sartem 	DBusMessage *reply;
34642912Sartem 	dbus_bool_t result;
34652912Sartem 
34662912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
34672912Sartem 
34682912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
34692912Sartem 						udi,
34702912Sartem 						"org.freedesktop.Hal.Device",
34712912Sartem 						"Reprobe");
34722912Sartem 
34732912Sartem 	if (message == NULL) {
34742912Sartem 		fprintf (stderr,
34752912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
34762912Sartem 			 __FILE__, __LINE__);
34772912Sartem 		return FALSE;
34782912Sartem 	}
34792912Sartem 
34802912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
34812912Sartem 							   message, -1,
34822912Sartem 							   error);
34832912Sartem 
3484*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
34852912Sartem 		dbus_message_unref (message);
34862912Sartem 		return FALSE;
34872912Sartem 	}
34882912Sartem 
34892912Sartem 	dbus_message_unref (message);
34902912Sartem 
34912912Sartem 	if (reply == NULL)
34922912Sartem 		return FALSE;
34932912Sartem 
34942912Sartem 	dbus_message_iter_init (reply, &reply_iter);
34952912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) !=
34962912Sartem 		   DBUS_TYPE_BOOLEAN) {
34972912Sartem 		dbus_message_unref (message);
34982912Sartem 		dbus_message_unref (reply);
34992912Sartem 		return FALSE;
35002912Sartem 	}
35012912Sartem 	dbus_message_iter_get_basic (&reply_iter, &result);
35022912Sartem 
35032912Sartem 	dbus_message_unref (reply);
35042912Sartem 
35052912Sartem 	return result;
35062912Sartem }
35072912Sartem 
35082912Sartem /**
35092912Sartem  * libhal_device_emit_condition:
35102912Sartem  * @ctx: the context for the connection to hald
35112912Sartem  * @udi: the Unique Device Id
35122912Sartem  * @condition_name: user-readable name of condition
35132912Sartem  * @condition_details: user-readable details of condition
35142912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
35152912Sartem  *
35162912Sartem  * Emit a condition from a device. Can only be used from hald helpers.
35172912Sartem  *
35182912Sartem  * Returns: TRUE if condition successfully emitted,
35192912Sartem  *                              FALSE otherwise
35202912Sartem  */
libhal_device_emit_condition(LibHalContext * ctx,const char * udi,const char * condition_name,const char * condition_details,DBusError * error)35212912Sartem dbus_bool_t libhal_device_emit_condition (LibHalContext *ctx,
35222912Sartem 					  const char *udi,
35232912Sartem 					  const char *condition_name,
35242912Sartem 					  const char *condition_details,
35252912Sartem 					  DBusError *error)
35262912Sartem {
35272912Sartem 	DBusMessage *message;
35282912Sartem 	DBusMessageIter iter;
35292912Sartem 	DBusMessageIter reply_iter;
35302912Sartem 	DBusMessage *reply;
35312912Sartem 	dbus_bool_t result;
35322912Sartem 
35332912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
35342912Sartem 
35352912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
35362912Sartem 						udi,
35372912Sartem 						"org.freedesktop.Hal.Device",
35382912Sartem 						"EmitCondition");
35392912Sartem 
35402912Sartem 	if (message == NULL) {
35412912Sartem 		fprintf (stderr,
35422912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
35432912Sartem 			 __FILE__, __LINE__);
35442912Sartem 		return FALSE;
35452912Sartem 	}
35462912Sartem 
35472912Sartem 	dbus_message_iter_init_append (message, &iter);
35482912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_name);
35492912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_details);
35502912Sartem 
35512912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
35522912Sartem 							   message, -1,
35532912Sartem 							   error);
35542912Sartem 
3555*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
35562912Sartem 		dbus_message_unref (message);
35572912Sartem 		return FALSE;
35582912Sartem 	}
35592912Sartem 
35602912Sartem 	dbus_message_unref (message);
35612912Sartem 
35622912Sartem 	if (reply == NULL)
35632912Sartem 		return FALSE;
35642912Sartem 
35652912Sartem 	dbus_message_iter_init (reply, &reply_iter);
35662912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) !=
35672912Sartem 		   DBUS_TYPE_BOOLEAN) {
35682912Sartem 		dbus_message_unref (message);
35692912Sartem 		dbus_message_unref (reply);
35702912Sartem 		return FALSE;
35712912Sartem 	}
35722912Sartem 	dbus_message_iter_get_basic (&reply_iter, &result);
35732912Sartem 
35742912Sartem 	dbus_message_unref (reply);
35752912Sartem 
35762912Sartem 	return result;
35772912Sartem }
35782912Sartem 
35792912Sartem /**
35802912Sartem  * libhal_device_addon_is_ready:
35812912Sartem  * @ctx: the context for the connection to hald
35822912Sartem  * @udi: the Unique Device Id
35832912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
35842912Sartem  *
35852912Sartem  * HAL addon's must call this method when they are done initializing the device object. The HAL
35862912Sartem  * daemon will wait for all addon's to call this.
35872912Sartem  *
35882912Sartem  * Can only be used from hald helpers.
35892912Sartem  *
35902912Sartem  * Returns: TRUE if the HAL daemon received the message, FALSE otherwise
35912912Sartem  */
35922912Sartem dbus_bool_t
libhal_device_addon_is_ready(LibHalContext * ctx,const char * udi,DBusError * error)35932912Sartem libhal_device_addon_is_ready (LibHalContext *ctx, const char *udi, DBusError *error)
35942912Sartem {
35952912Sartem 	DBusMessage *message;
35962912Sartem 	DBusMessageIter iter;
35972912Sartem 	DBusMessageIter reply_iter;
35982912Sartem 	DBusMessage *reply;
35992912Sartem 	dbus_bool_t result;
36002912Sartem 
36012912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
36022912Sartem 
36032912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
36042912Sartem 						udi,
36052912Sartem 						"org.freedesktop.Hal.Device",
36062912Sartem 						"AddonIsReady");
36072912Sartem 
36082912Sartem 	if (message == NULL) {
36092912Sartem 		fprintf (stderr,
36102912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
36112912Sartem 			 __FILE__, __LINE__);
36122912Sartem 		return FALSE;
36132912Sartem 	}
36142912Sartem 
36152912Sartem 	dbus_message_iter_init_append (message, &iter);
36162912Sartem 
36172912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
36182912Sartem 							   message, -1,
36192912Sartem 							   error);
36202912Sartem 
3621*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
36222912Sartem 		dbus_message_unref (message);
36232912Sartem 		return FALSE;
36242912Sartem 	}
36252912Sartem 
36262912Sartem 	dbus_message_unref (message);
36272912Sartem 
36282912Sartem 	if (reply == NULL)
36292912Sartem 		return FALSE;
36302912Sartem 
36312912Sartem 	dbus_message_iter_init (reply, &reply_iter);
36322912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
36332912Sartem 		dbus_message_unref (message);
36342912Sartem 		dbus_message_unref (reply);
36352912Sartem 		return FALSE;
36362912Sartem 	}
36372912Sartem 	dbus_message_iter_get_basic (&reply_iter, &result);
36382912Sartem 
36392912Sartem 	dbus_message_unref (reply);
36402912Sartem 	return result;
36412912Sartem }
36422912Sartem 
36432912Sartem /**
36442912Sartem  * libhal_device_claim_interface:
36452912Sartem  * @ctx: the context for the connection to hald
36462912Sartem  * @udi: the Unique Device Id
36472912Sartem  * @interface_name: Name of interface to claim, e.g. org.freedesktop.Hal.Device.FoobarKindOfThing
36482912Sartem  * @introspection_xml: Introspection XML containing what would be inside the interface XML tag
36492912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
36502912Sartem  *
36512912Sartem  * Claim an interface for a device. All messages to this interface
36522912Sartem  * will be forwarded to the helper. Can only be used from hald
36532912Sartem  * helpers.
36542912Sartem  *
36552912Sartem  * Returns: TRUE if interface was claimed, FALSE otherwise
36562912Sartem  */
36572912Sartem dbus_bool_t
libhal_device_claim_interface(LibHalContext * ctx,const char * udi,const char * interface_name,const char * introspection_xml,DBusError * error)36582912Sartem libhal_device_claim_interface (LibHalContext *ctx,
36592912Sartem 			       const char *udi,
36602912Sartem 			       const char *interface_name,
36612912Sartem 			       const char *introspection_xml,
36622912Sartem 			       DBusError *error)
36632912Sartem {
36642912Sartem 	DBusMessage *message;
36652912Sartem 	DBusMessageIter iter;
36662912Sartem 	DBusMessageIter reply_iter;
36672912Sartem 	DBusMessage *reply;
36682912Sartem 	dbus_bool_t result;
36692912Sartem 
36702912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
36712912Sartem 
36722912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal",
36732912Sartem 						udi,
36742912Sartem 						"org.freedesktop.Hal.Device",
36752912Sartem 						"ClaimInterface");
36762912Sartem 
36772912Sartem 	if (message == NULL) {
36782912Sartem 		fprintf (stderr,
36792912Sartem 			 "%s %d : Couldn't allocate D-BUS message\n",
36802912Sartem 			 __FILE__, __LINE__);
36812912Sartem 		return FALSE;
36822912Sartem 	}
36832912Sartem 
36842912Sartem 	dbus_message_iter_init_append (message, &iter);
36852912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name);
36862912Sartem 	dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &introspection_xml);
36872912Sartem 
36882912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
36892912Sartem 							   message, -1,
36902912Sartem 							   error);
36912912Sartem 
3692*11992SLin.Guo@Sun.COM 	if (error != NULL && dbus_error_is_set (error)) {
36932912Sartem 		dbus_message_unref (message);
36942912Sartem 		return FALSE;
36952912Sartem 	}
36962912Sartem 
36972912Sartem 	dbus_message_unref (message);
36982912Sartem 
36992912Sartem 	if (reply == NULL)
37002912Sartem 		return FALSE;
37012912Sartem 
37022912Sartem 	dbus_message_iter_init (reply, &reply_iter);
37032912Sartem 	if (dbus_message_iter_get_arg_type (&reply_iter) !=
37042912Sartem 		   DBUS_TYPE_BOOLEAN) {
37052912Sartem 		dbus_message_unref (message);
37062912Sartem 		dbus_message_unref (reply);
37072912Sartem 		return FALSE;
37082912Sartem 	}
37092912Sartem 	dbus_message_iter_get_basic (&reply_iter, &result);
37102912Sartem 
37112912Sartem 	dbus_message_unref (reply);
37122912Sartem 
37132912Sartem 	return result;
37142912Sartem }
37152912Sartem 
37162912Sartem 
37172912Sartem 
37182912Sartem struct LibHalChangeSetElement_s;
37192912Sartem 
37202912Sartem typedef struct LibHalChangeSetElement_s LibHalChangeSetElement;
37212912Sartem 
37222912Sartem struct LibHalChangeSetElement_s {
37232912Sartem 	char *key;
37242912Sartem 	int change_type;
37252912Sartem 	union {
37262912Sartem 		char *val_str;
37272912Sartem 		dbus_int32_t val_int;
37282912Sartem 		dbus_uint64_t val_uint64;
37292912Sartem 		double val_double;
37302912Sartem 		dbus_bool_t val_bool;
37312912Sartem 		char **val_strlist;
37322912Sartem 	} value;
37332912Sartem 	LibHalChangeSetElement *next;
37342912Sartem 	LibHalChangeSetElement *prev;
37352912Sartem };
37362912Sartem 
37372912Sartem struct LibHalChangeSet_s {
37382912Sartem 	char *udi;
37392912Sartem 	LibHalChangeSetElement *head;
37402912Sartem 	LibHalChangeSetElement *tail;
37412912Sartem };
37422912Sartem 
37432912Sartem /**
37442912Sartem  * libhal_device_new_changeset:
37452912Sartem  * @udi: unique device identifier
37462912Sartem  *
37472912Sartem  * Request a new changeset object. Used for changing multiple properties at once. Useful when
37482912Sartem  * performance is critical and also for atomically updating several properties.
37492912Sartem  *
37502912Sartem  * Returns: A new changeset object or NULL on error
37512912Sartem  */
37522912Sartem LibHalChangeSet *
libhal_device_new_changeset(const char * udi)37532912Sartem libhal_device_new_changeset (const char *udi)
37542912Sartem {
37552912Sartem 	LibHalChangeSet *changeset;
37562912Sartem 
37572912Sartem 	changeset = calloc (1, sizeof (LibHalChangeSet));
37582912Sartem 	if (changeset == NULL)
37592912Sartem 		goto out;
37602912Sartem 
37612912Sartem 	changeset->udi = strdup (udi);
37622912Sartem 	if (changeset->udi == NULL) {
37632912Sartem 		free (changeset);
37642912Sartem 		changeset = NULL;
37652912Sartem 		goto out;
37662912Sartem 	}
37672912Sartem 
37682912Sartem 	changeset->head = NULL;
37692912Sartem 	changeset->tail = NULL;
37702912Sartem 
37712912Sartem out:
37722912Sartem 	return changeset;
37732912Sartem }
37742912Sartem 
37752912Sartem static void
libhal_changeset_append(LibHalChangeSet * changeset,LibHalChangeSetElement * elem)37762912Sartem libhal_changeset_append (LibHalChangeSet *changeset, LibHalChangeSetElement *elem)
37772912Sartem {
37782912Sartem 	if (changeset->head == NULL) {
37792912Sartem 		changeset->head = elem;
37802912Sartem 		changeset->tail = elem;
37812912Sartem 		elem->next = NULL;
37822912Sartem 		elem->prev = NULL;
37832912Sartem 	} else {
37842912Sartem 		elem->prev = changeset->tail;
37852912Sartem 		elem->next = NULL;
37862912Sartem 		elem->prev->next = elem;
37872912Sartem 		changeset->tail = elem;
37882912Sartem 	}
37892912Sartem }
37902912Sartem 
37912912Sartem 
37922912Sartem /**
37932912Sartem  * libhal_device_set_property_string:
37942912Sartem  * @changeset: the changeset
37952912Sartem  * @key: key of property
37962912Sartem  * @value: the value to set
37972912Sartem  *
37982912Sartem  * Set a property.
37992912Sartem  *
38002912Sartem  * Returns: FALSE on OOM
38012912Sartem  */
38022912Sartem dbus_bool_t
libhal_changeset_set_property_string(LibHalChangeSet * changeset,const char * key,const char * value)38032912Sartem libhal_changeset_set_property_string (LibHalChangeSet *changeset, const char *key, const char *value)
38042912Sartem {
38052912Sartem 	LibHalChangeSetElement *elem;
38062912Sartem 
38072912Sartem 	elem = calloc (1, sizeof (LibHalChangeSetElement));
38082912Sartem 	if (elem == NULL)
38092912Sartem 		goto out;
38102912Sartem 	elem->key = strdup (key);
38112912Sartem 	if (elem->key == NULL) {
38122912Sartem 		free (elem);
38132912Sartem 		elem = NULL;
38142912Sartem 		goto out;
38152912Sartem 	}
38162912Sartem 
38172912Sartem 	elem->change_type = LIBHAL_PROPERTY_TYPE_STRING;
38182912Sartem 	elem->value.val_str = strdup (value);
38192912Sartem 	if (elem->value.val_str == NULL) {
38202912Sartem 		free (elem->key);
38212912Sartem 		free (elem);
38222912Sartem 		elem = NULL;
38232912Sartem 		goto out;
38242912Sartem 	}
38252912Sartem 
38262912Sartem 	libhal_changeset_append (changeset, elem);
38272912Sartem out:
38282912Sartem 	return elem != NULL;
38292912Sartem }
38302912Sartem 
38312912Sartem /**
38322912Sartem  * libhal_device_set_property_int:
38332912Sartem  * @changeset: the changeset
38342912Sartem  * @key: key of property
38352912Sartem  * @value: the value to set
38362912Sartem  *
38372912Sartem  * Set a property.
38382912Sartem  *
38392912Sartem  * Returns: FALSE on OOM
38402912Sartem  */
38412912Sartem dbus_bool_t
libhal_changeset_set_property_int(LibHalChangeSet * changeset,const char * key,dbus_int32_t value)38422912Sartem libhal_changeset_set_property_int (LibHalChangeSet *changeset, const char *key, dbus_int32_t value)
38432912Sartem {
38442912Sartem 	LibHalChangeSetElement *elem;
38452912Sartem 
38462912Sartem 	elem = calloc (1, sizeof (LibHalChangeSetElement));
38472912Sartem 	if (elem == NULL)
38482912Sartem 		goto out;
38492912Sartem 	elem->key = strdup (key);
38502912Sartem 	if (elem->key == NULL) {
38512912Sartem 		free (elem);
38522912Sartem 		elem = NULL;
38532912Sartem 		goto out;
38542912Sartem 	}
38552912Sartem 
38562912Sartem 	elem->change_type = LIBHAL_PROPERTY_TYPE_INT32;
38572912Sartem 	elem->value.val_int = value;
38582912Sartem 
38592912Sartem 	libhal_changeset_append (changeset, elem);
38602912Sartem out:
38612912Sartem 	return elem != NULL;
38622912Sartem }
38632912Sartem 
38642912Sartem /**
38652912Sartem  * libhal_device_set_property_uint64:
38662912Sartem  * @changeset: the changeset
38672912Sartem  * @key: key of property
38682912Sartem  * @value: the value to set
38692912Sartem  *
38702912Sartem  * Set a property.
38712912Sartem  *
38722912Sartem  * Returns: FALSE on OOM
38732912Sartem  */
38742912Sartem dbus_bool_t
libhal_changeset_set_property_uint64(LibHalChangeSet * changeset,const char * key,dbus_uint64_t value)38752912Sartem libhal_changeset_set_property_uint64 (LibHalChangeSet *changeset, const char *key, dbus_uint64_t value)
38762912Sartem {
38772912Sartem 	LibHalChangeSetElement *elem;
38782912Sartem 
38792912Sartem 	elem = calloc (1, sizeof (LibHalChangeSetElement));
38802912Sartem 	if (elem == NULL)
38812912Sartem 		goto out;
38822912Sartem 	elem->key = strdup (key);
38832912Sartem 	if (elem->key == NULL) {
38842912Sartem 		free (elem);
38852912Sartem 		elem = NULL;
38862912Sartem 		goto out;
38872912Sartem 	}
38882912Sartem 
38892912Sartem 	elem->change_type = LIBHAL_PROPERTY_TYPE_UINT64;
38902912Sartem 	elem->value.val_uint64 = value;
38912912Sartem 
38922912Sartem 	libhal_changeset_append (changeset, elem);
38932912Sartem out:
38942912Sartem 	return elem != NULL;
38952912Sartem }
38962912Sartem 
38972912Sartem /**
38982912Sartem  * libhal_device_set_property_double:
38992912Sartem  * @changeset: the changeset
39002912Sartem  * @key: key of property
39012912Sartem  * @value: the value to set
39022912Sartem  *
39032912Sartem  * Set a property.
39042912Sartem  *
39052912Sartem  * Returns: FALSE on OOM
39062912Sartem  */
39072912Sartem dbus_bool_t
libhal_changeset_set_property_double(LibHalChangeSet * changeset,const char * key,double value)39082912Sartem libhal_changeset_set_property_double (LibHalChangeSet *changeset, const char *key, double value)
39092912Sartem {
39102912Sartem 	LibHalChangeSetElement *elem;
39112912Sartem 
39122912Sartem 	elem = calloc (1, sizeof (LibHalChangeSetElement));
39132912Sartem 	if (elem == NULL)
39142912Sartem 		goto out;
39152912Sartem 	elem->key = strdup (key);
39162912Sartem 	if (elem->key == NULL) {
39172912Sartem 		free (elem);
39182912Sartem 		elem = NULL;
39192912Sartem 		goto out;
39202912Sartem 	}
39212912Sartem 
39222912Sartem 	elem->change_type = LIBHAL_PROPERTY_TYPE_DOUBLE;
39232912Sartem 	elem->value.val_double = value;
39242912Sartem 
39252912Sartem 	libhal_changeset_append (changeset, elem);
39262912Sartem out:
39272912Sartem 	return elem != NULL;
39282912Sartem }
39292912Sartem 
39302912Sartem /**
39312912Sartem  * libhal_device_set_property_bool:
39322912Sartem  * @changeset: the changeset
39332912Sartem  * @key: key of property
39342912Sartem  * @value: the value to set
39352912Sartem  *
39362912Sartem  * Set a property.
39372912Sartem  *
39382912Sartem  * Returns: FALSE on OOM
39392912Sartem  */
39402912Sartem dbus_bool_t
libhal_changeset_set_property_bool(LibHalChangeSet * changeset,const char * key,dbus_bool_t value)39412912Sartem libhal_changeset_set_property_bool (LibHalChangeSet *changeset, const char *key, dbus_bool_t value)
39422912Sartem {
39432912Sartem 	LibHalChangeSetElement *elem;
39442912Sartem 
39452912Sartem 	elem = calloc (1, sizeof (LibHalChangeSetElement));
39462912Sartem 	if (elem == NULL)
39472912Sartem 		goto out;
39482912Sartem 	elem->key = strdup (key);
39492912Sartem 	if (elem->key == NULL) {
39502912Sartem 		free (elem);
39512912Sartem 		elem = NULL;
39522912Sartem 		goto out;
39532912Sartem 	}
39542912Sartem 
39552912Sartem 	elem->change_type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
39562912Sartem 	elem->value.val_bool = value;
39572912Sartem 
39582912Sartem 	libhal_changeset_append (changeset, elem);
39592912Sartem out:
39602912Sartem 	return elem != NULL;
39612912Sartem }
39622912Sartem 
39632912Sartem /**
39642912Sartem  * libhal_device_set_property_strlist:
39652912Sartem  * @changeset: the changeset
39662912Sartem  * @key: key of property
39672912Sartem  * @value: the value to set - NULL terminated array of strings
39682912Sartem  *
39692912Sartem  * Set a property.
39702912Sartem  *
39712912Sartem  * Returns: FALSE on OOM
39722912Sartem  */
39732912Sartem dbus_bool_t
libhal_changeset_set_property_strlist(LibHalChangeSet * changeset,const char * key,const char ** value)39742912Sartem libhal_changeset_set_property_strlist (LibHalChangeSet *changeset, const char *key, const char **value)
39752912Sartem {
39762912Sartem 	LibHalChangeSetElement *elem;
39772912Sartem 	char **value_copy;
39782912Sartem 	int len;
39792912Sartem 	int i, j;
39802912Sartem 
39812912Sartem 	elem = calloc (1, sizeof (LibHalChangeSetElement));
39822912Sartem 	if (elem == NULL)
39832912Sartem 		goto out;
39842912Sartem 	elem->key = strdup (key);
39852912Sartem 	if (elem->key == NULL) {
39862912Sartem 		free (elem);
39872912Sartem 		elem = NULL;
39882912Sartem 		goto out;
39892912Sartem 	}
39902912Sartem 
39912912Sartem 	for (i = 0; value[i] != NULL; i++)
39922912Sartem 		;
39932912Sartem 	len = i;
39942912Sartem 
39952912Sartem 	value_copy = calloc (len + 1, sizeof (char *));
39962912Sartem 	if (value_copy == NULL) {
39972912Sartem 		free (elem->key);
39982912Sartem 		free (elem);
39992912Sartem 		elem = NULL;
40002912Sartem 		goto out;
40012912Sartem 	}
40022912Sartem 
40032912Sartem 	for (i = 0; i < len; i++) {
40042912Sartem 		value_copy[i] = strdup (value[i]);
40052912Sartem 		if (value_copy[i] == NULL) {
40062912Sartem 			for (j = 0; j < i; j++) {
40072912Sartem 				free (value_copy[j]);
40082912Sartem 			}
40092912Sartem 			free (value_copy);
40102912Sartem 			free (elem->key);
40112912Sartem 			free (elem);
40122912Sartem 			elem = NULL;
40132912Sartem 			goto out;
40142912Sartem 		}
40152912Sartem 	}
40162912Sartem 	value_copy[i] = NULL;
40172912Sartem 
40182912Sartem 	elem->change_type = LIBHAL_PROPERTY_TYPE_STRLIST;
40192912Sartem 	elem->value.val_strlist = value_copy;
40202912Sartem 
40212912Sartem 	libhal_changeset_append (changeset, elem);
40222912Sartem out:
40232912Sartem 	return elem != NULL;
40242912Sartem }
40252912Sartem 
40262912Sartem /**
40272912Sartem  * libhal_device_commit_changeset:
40282912Sartem  * @ctx: the context for the connection to hald
40292912Sartem  * @changeset: the changeset to commit
40302912Sartem  * @error: pointer to an initialized dbus error object for returning errors or NULL
40312912Sartem  *
40322912Sartem  * Commit a changeset to the daemon.
40332912Sartem  *
40342912Sartem  * Returns: True if the changeset was committed on the daemon side
40352912Sartem  */
40362912Sartem dbus_bool_t
libhal_device_commit_changeset(LibHalContext * ctx,LibHalChangeSet * changeset,DBusError * error)40372912Sartem libhal_device_commit_changeset (LibHalContext *ctx, LibHalChangeSet *changeset, DBusError *error)
40382912Sartem {
40392912Sartem 	LibHalChangeSetElement *elem;
40402912Sartem 	DBusMessage *message;
40412912Sartem 	DBusMessage *reply;
40422912Sartem 	DBusError _error;
40432912Sartem 	DBusMessageIter iter;
40442912Sartem 	DBusMessageIter sub;
40452912Sartem 	DBusMessageIter sub2;
40462912Sartem 	DBusMessageIter sub3;
40472912Sartem 	DBusMessageIter sub4;
40482912Sartem 	int i;
40492912Sartem 
40502912Sartem 	LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
40512912Sartem 
40522912Sartem 	if (changeset->head == NULL) {
40532912Sartem 		return TRUE;
40542912Sartem 	}
40552912Sartem 
40562912Sartem 	message = dbus_message_new_method_call ("org.freedesktop.Hal", changeset->udi,
40572912Sartem 						"org.freedesktop.Hal.Device",
40582912Sartem 						"SetMultipleProperties");
40592912Sartem 
40602912Sartem 	if (message == NULL) {
40612912Sartem 		fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
40622912Sartem 		return FALSE;
40632912Sartem 	}
40642912Sartem 
40652912Sartem 	dbus_message_iter_init_append (message, &iter);
40662912Sartem 
40672912Sartem 	dbus_message_iter_open_container (&iter,
40682912Sartem 					  DBUS_TYPE_ARRAY,
40692912Sartem 					  DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
40702912Sartem 					  DBUS_TYPE_STRING_AS_STRING
40712912Sartem 					  DBUS_TYPE_VARIANT_AS_STRING
40722912Sartem 					  DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
40732912Sartem 					  &sub);
40742912Sartem 
40752912Sartem 	for (elem = changeset->head; elem != NULL; elem = elem->next) {
40762912Sartem 		dbus_message_iter_open_container (&sub,
40772912Sartem 						  DBUS_TYPE_DICT_ENTRY,
40782912Sartem 						  NULL,
40792912Sartem 						  &sub2);
40802912Sartem 		dbus_message_iter_append_basic (&sub2, DBUS_TYPE_STRING, &(elem->key));
40812912Sartem 
40822912Sartem 		switch (elem->change_type) {
40832912Sartem 		case LIBHAL_PROPERTY_TYPE_STRING:
40842912Sartem 			dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub3);
40852912Sartem 			dbus_message_iter_append_basic (&sub3, DBUS_TYPE_STRING, &(elem->value.val_str));
40862912Sartem 			dbus_message_iter_close_container (&sub2, &sub3);
40872912Sartem 			break;
40882912Sartem 		case LIBHAL_PROPERTY_TYPE_STRLIST:
40892912Sartem 			dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT,
40902912Sartem 							  DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, &sub3);
40912912Sartem 			dbus_message_iter_open_container (&sub3, DBUS_TYPE_ARRAY,
40922912Sartem 							  DBUS_TYPE_STRING_AS_STRING, &sub4);
40932912Sartem 			for (i = 0; elem->value.val_strlist[i] != NULL; i++) {
40942912Sartem 				dbus_message_iter_append_basic (&sub4, DBUS_TYPE_STRING,
40952912Sartem 								&(elem->value.val_strlist[i]));
40962912Sartem 			}
40972912Sartem 			dbus_message_iter_close_container (&sub3, &sub4);
40982912Sartem 			dbus_message_iter_close_container (&sub2, &sub3);
40992912Sartem 			break;
41002912Sartem 		case LIBHAL_PROPERTY_TYPE_INT32:
41012912Sartem 			dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub3);
41022912Sartem 			dbus_message_iter_append_basic (&sub3, DBUS_TYPE_INT32, &(elem->value.val_int));
41032912Sartem 			dbus_message_iter_close_container (&sub2, &sub3);
41042912Sartem 			break;
41052912Sartem 		case LIBHAL_PROPERTY_TYPE_UINT64:
41062912Sartem 			dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_UINT64_AS_STRING, &sub3);
41072912Sartem 			dbus_message_iter_append_basic (&sub3, DBUS_TYPE_UINT64, &(elem->value.val_uint64));
41082912Sartem 			dbus_message_iter_close_container (&sub2, &sub3);
41092912Sartem 			break;
41102912Sartem 		case LIBHAL_PROPERTY_TYPE_DOUBLE:
41112912Sartem 			dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub3);
41122912Sartem 			dbus_message_iter_append_basic (&sub3, DBUS_TYPE_DOUBLE, &(elem->value.val_double));
41132912Sartem 			dbus_message_iter_close_container (&sub2, &sub3);
41142912Sartem 			break;
41152912Sartem 		case LIBHAL_PROPERTY_TYPE_BOOLEAN:
41162912Sartem 			dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING,&sub3);
41172912Sartem 			dbus_message_iter_append_basic (&sub3, DBUS_TYPE_BOOLEAN, &(elem->value.val_bool));
41182912Sartem 			dbus_message_iter_close_container (&sub2, &sub3);
41192912Sartem 			break;
41202912Sartem 		default:
41212912Sartem 			fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
41222912Sartem 			break;
41232912Sartem 		}
41242912Sartem 		dbus_message_iter_close_container (&sub, &sub2);
41252912Sartem 	}
41262912Sartem 
41272912Sartem 	dbus_message_iter_close_container (&iter, &sub);
41282912Sartem 
41292912Sartem 
41302912Sartem 	dbus_error_init (&_error);
41312912Sartem 	reply = dbus_connection_send_with_reply_and_block (ctx->connection,
41322912Sartem 							   message, -1,
41332912Sartem 							   &_error);
41342912Sartem 
41352912Sartem 	dbus_move_error (&_error, error);
41362912Sartem 	if (error != NULL && dbus_error_is_set (error)) {
41372912Sartem 		fprintf (stderr,
41382912Sartem 			 "%s %d : %s\n",
41392912Sartem 			 __FILE__, __LINE__, error->message);
41402912Sartem 
41412912Sartem 		dbus_message_unref (message);
41422912Sartem 		return FALSE;
41432912Sartem 	}
41442912Sartem 
41452912Sartem 	if (reply == NULL) {
41462912Sartem 		dbus_message_unref (message);
41472912Sartem 		return FALSE;
41482912Sartem 	}
41492912Sartem 
41502912Sartem 	return TRUE;
41512912Sartem }
41522912Sartem 
41532912Sartem /**
41542912Sartem  * libhal_device_free_changeset:
41552912Sartem  * @changeset: the changeset to free
41562912Sartem  *
41572912Sartem  * Free a changeset.
41582912Sartem  */
41592912Sartem void
libhal_device_free_changeset(LibHalChangeSet * changeset)41602912Sartem libhal_device_free_changeset (LibHalChangeSet *changeset)
41612912Sartem {
41622912Sartem 	LibHalChangeSetElement *elem;
41632912Sartem 	LibHalChangeSetElement *elem2;
41642912Sartem 
41652912Sartem 	for (elem = changeset->head; elem != NULL; elem = elem2) {
41662912Sartem 		elem2 = elem->next;
41672912Sartem 
41682912Sartem 		switch (elem->change_type) {
41692912Sartem 		case LIBHAL_PROPERTY_TYPE_STRING:
41702912Sartem 			free (elem->value.val_str);
41712912Sartem 			break;
41722912Sartem 		case LIBHAL_PROPERTY_TYPE_STRLIST:
41732912Sartem 			libhal_free_string_array (elem->value.val_strlist);
41742912Sartem 			break;
41752912Sartem                 /* explicit fallthrough */
41762912Sartem 		case LIBHAL_PROPERTY_TYPE_INT32:
41772912Sartem 		case LIBHAL_PROPERTY_TYPE_UINT64:
41782912Sartem 		case LIBHAL_PROPERTY_TYPE_DOUBLE:
41792912Sartem 		case LIBHAL_PROPERTY_TYPE_BOOLEAN:
41802912Sartem 			break;
41812912Sartem 		default:
41822912Sartem 			fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
41832912Sartem 			break;
41842912Sartem 		}
41852912Sartem 		free (elem);
41862912Sartem 	}
41872912Sartem 
41882912Sartem 	free (changeset->udi);
41892912Sartem 	free (changeset);
41902912Sartem }
4191