dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / hal / libhal / common / libhal.c
blob3d6f0ca2f05b517989e1fde0a15db0628b50b1aa
1 /***************************************************************************
2 * CVSID: $Id$
4 * libhal.c : HAL daemon C convenience library
6 * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
7 * Copyright (C) 2006 Sjoerd Simons, <sjoerd@luon.net>
8 * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor@codethink.co.uk>
10 * Licensed under the Academic Free License version 2.1
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 **************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <dbus/dbus.h>
37 #include "libhal.h"
39 #ifdef ENABLE_NLS
40 # include <libintl.h>
41 # define _(String) dgettext (GETTEXT_PACKAGE, String)
42 # ifdef gettext_noop
43 # define N_(String) gettext_noop (String)
44 # else
45 # define N_(String) (String)
46 # endif
47 #else
48 /* Stubs that do something close enough. */
49 # define textdomain(String) (String)
50 # define gettext(String) (String)
51 # define dgettext(Domain,Message) (Message)
52 # define dcgettext(Domain,Message,Type) (Message)
53 # define bindtextdomain(Domain,Directory) (Domain)
54 # define _(String)
55 # define N_(String) (String)
56 #endif
58 /**
59 * LIBHAL_CHECK_PARAM_VALID:
60 * @_param_: the prameter to check for
61 * @_name_: the name of the prameter (for debug output)
62 * @_ret_: what to use for return value if the prameter is NULL
64 * Handy macro for checking whether a parameter is valid and not NULL.
66 #define LIBHAL_CHECK_PARAM_VALID(_param_,_name_,_ret_) \
67 do { \
68 if (_param_ == NULL) { \
69 fprintf (stderr, \
70 "%s %d : invalid paramater. %s is NULL.\n", \
71 __FILE__, __LINE__, _name_); \
72 return _ret_; \
73 } \
74 } while(0)
76 /**
77 * LIBHAL_CHECK_UDI_VALID:
78 * @_udi_: the UID to check for
79 * @_ret_: what to use for return value if udi is invalid
81 * Handy macro for checking whether a UID is valid and not NULL.
83 #define LIBHAL_CHECK_UDI_VALID(_udi_,_ret_) \
84 do { \
85 if (_udi_ == NULL) { \
86 fprintf (stderr, \
87 "%s %d : invalid udi %s. udi is NULL.\n", \
88 __FILE__, __LINE__, _udi_); \
89 return _ret_; \
90 } else { \
91 if(strncmp(_udi_, "/org/freedesktop/Hal/devices/", 29) != 0) { \
92 fprintf (stderr, \
93 "%s %d : invalid udi: %s doesn't start" \
94 "with '/org/freedesktop/Hal/devices/'. \n", \
95 __FILE__, __LINE__, _udi_); \
96 return _ret_; \
97 } \
98 } \
99 } while(0)
101 static char **libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements);
103 static dbus_bool_t libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter);
107 * libhal_free_string_array:
108 * @str_array: the array to be freed
110 * Frees a NULL-terminated array of strings. If passed NULL, does nothing.
112 void
113 libhal_free_string_array (char **str_array)
115 if (str_array != NULL) {
116 int i;
118 for (i = 0; str_array[i] != NULL; i++) {
119 free (str_array[i]);
120 str_array[i] = NULL;
122 free (str_array);
123 str_array = NULL;
129 * libhal_get_string_array_from_iter:
130 * @iter: the message iterator to extract the strings from
131 * @num_elements: pointer to an integer where to store number of elements (can be NULL)
133 * Creates a NULL terminated array of strings from a dbus message iterator.
135 * Returns: pointer to the string array
137 static char **
138 libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements)
140 int count;
141 char **buffer;
142 char **t;
144 count = 0;
145 buffer = (char **)malloc (sizeof (char *) * 8);
147 if (buffer == NULL)
148 goto oom;
150 buffer[0] = NULL;
151 while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING) {
152 const char *value;
153 char *str;
155 if ((count % 8) == 0 && count != 0) {
156 t = reallocarray(buffer, count + 8, sizeof (char *));
157 if (t == NULL)
158 goto oom;
159 else
160 buffer = t;
163 dbus_message_iter_get_basic (iter, &value);
164 str = strdup (value);
165 if (str == NULL)
166 goto oom;
168 buffer[count] = str;
170 dbus_message_iter_next(iter);
171 count++;
174 if ((count % 8) == 0) {
175 t = reallocarray(buffer, (count + 1), sizeof(char *));
176 if (t == NULL)
177 goto oom;
178 else
179 buffer = t;
182 buffer[count] = NULL;
183 if (num_elements != NULL)
184 *num_elements = count;
185 return buffer;
187 oom:
188 free(buffer);
189 fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
190 return NULL;
195 * libhal_free_string:
196 * @str: the nul-terminated sting to free
198 * Used to free strings returned by libhal.
200 void
201 libhal_free_string (char *str)
203 if (str != NULL) {
204 free (str);
205 str = NULL;
211 * LibHalPropertySet:
213 * Represents a set of properties. Opaque; use the
214 * libhal_property_set_*() family of functions to access it.
216 struct LibHalPropertySet_s {
217 unsigned int num_properties; /**< Number of properties in set */
218 LibHalProperty *properties_head;
219 /**< Pointer to first property or NULL
220 * if there are no properties */
224 * LibHalProperty:
226 * Represents a property. Opaque.
228 struct LibHalProperty_s {
229 LibHalPropertyType type; /**< Type of property */
230 char *key; /**< ASCII string */
232 /** Possible values of the property */
233 union {
234 char *str_value; /**< UTF-8 zero-terminated string */
235 dbus_int32_t int_value;
236 /**< 32-bit signed integer */
237 dbus_uint64_t uint64_value;
238 /**< 64-bit unsigned integer */
239 double double_value; /**< IEEE754 double precision float */
240 dbus_bool_t bool_value;
241 /**< Truth value */
243 char **strlist_value; /**< List of UTF-8 zero-terminated strings */
244 } v;
246 LibHalProperty *next; /**< Next property or NULL if this is
247 * the last */
251 * LibHalContext:
253 * Context for connection to the HAL daemon. Opaque, use the
254 * libhal_ctx_*() family of functions to access it.
256 struct LibHalContext_s {
257 DBusConnection *connection; /**< D-BUS connection */
258 dbus_bool_t is_initialized; /**< Are we initialised */
259 dbus_bool_t is_shutdown; /**< Have we been shutdown */
260 dbus_bool_t cache_enabled; /**< Is the cache enabled */
261 dbus_bool_t is_direct; /**< Whether the connection to hald is direct */
263 /** Device added */
264 LibHalDeviceAdded device_added;
266 /** Device removed */
267 LibHalDeviceRemoved device_removed;
269 /** Device got a new capability */
270 LibHalDeviceNewCapability device_new_capability;
272 /** Device got a new capability */
273 LibHalDeviceLostCapability device_lost_capability;
275 /** A property of a device changed */
276 LibHalDevicePropertyModified device_property_modified;
278 /** A non-continous event on the device occured */
279 LibHalDeviceCondition device_condition;
281 void *user_data; /**< User data */
285 * libhal_ctx_set_user_data:
286 * @ctx: the context for the connection to hald
287 * @user_data: user data
289 * Set user data for the context.
291 * Returns: TRUE if user data was successfully set, FALSE if otherwise
293 dbus_bool_t
294 libhal_ctx_set_user_data(LibHalContext *ctx, void *user_data)
296 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
297 ctx->user_data = user_data;
298 return TRUE;
302 * libhal_ctx_get_user_data:
303 * @ctx: the context for the connection to hald
305 * Get user data for the context.
307 * Returns: opaque pointer stored through libhal_ctx_set_user_data() or NULL if not set.
309 void*
310 libhal_ctx_get_user_data(LibHalContext *ctx)
312 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
313 return ctx->user_data;
318 * libhal_property_fill_value_from_variant:
319 * @p: the property to fill in
320 * @var_iter: variant iterator to extract the value from
322 * Fills in the value for the LibHalProperty given a variant iterator.
324 * Returns: Whether the value was put in.
326 static dbus_bool_t
327 libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter)
329 DBusMessageIter iter_array;
331 LIBHAL_CHECK_PARAM_VALID(p, "LibHalProperty *p", FALSE);
332 LIBHAL_CHECK_PARAM_VALID(var_iter, "DBusMessageIter *var_iter", FALSE);
334 switch (p->type) {
335 case DBUS_TYPE_ARRAY:
336 if (dbus_message_iter_get_element_type (var_iter) != DBUS_TYPE_STRING)
337 return FALSE;
339 dbus_message_iter_recurse (var_iter, &iter_array);
340 p->v.strlist_value = libhal_get_string_array_from_iter (&iter_array, NULL);
342 p->type = LIBHAL_PROPERTY_TYPE_STRLIST;
344 break;
345 case DBUS_TYPE_STRING:
347 const char *v;
349 dbus_message_iter_get_basic (var_iter, &v);
351 p->v.str_value = strdup (v);
352 if (p->v.str_value == NULL)
353 return FALSE;
354 p->type = LIBHAL_PROPERTY_TYPE_STRING;
356 break;
358 case DBUS_TYPE_INT32:
360 dbus_int32_t v;
362 dbus_message_iter_get_basic (var_iter, &v);
364 p->v.int_value = v;
365 p->type = LIBHAL_PROPERTY_TYPE_INT32;
367 break;
369 case DBUS_TYPE_UINT64:
371 dbus_uint64_t v;
373 dbus_message_iter_get_basic (var_iter, &v);
375 p->v.uint64_value = v;
376 p->type = LIBHAL_PROPERTY_TYPE_UINT64;
378 break;
380 case DBUS_TYPE_DOUBLE:
382 double v;
384 dbus_message_iter_get_basic (var_iter, &v);
386 p->v.double_value = v;
387 p->type = LIBHAL_PROPERTY_TYPE_DOUBLE;
389 break;
391 case DBUS_TYPE_BOOLEAN:
393 double v;
395 dbus_message_iter_get_basic (var_iter, &v);
397 p->v.double_value = v;
398 p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
400 break;
402 default:
403 /** @todo report error */
404 break;
407 return TRUE;
411 * libhal_device_get_all_properties:
412 * @ctx: the context for the connection to hald
413 * @udi: the Unique id of device
414 * @error: pointer to an initialized dbus error object for returning errors or NULL
416 * Retrieve all the properties on a device.
418 * Returns: An object represent all properties. Must be freed with libhal_free_property_set().
420 LibHalPropertySet *
421 libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error)
423 DBusMessage *message;
424 DBusMessage *reply;
425 DBusMessageIter reply_iter;
426 DBusMessageIter dict_iter;
427 LibHalPropertySet *result;
428 LibHalProperty *p_last;
429 DBusError _error;
431 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
432 LIBHAL_CHECK_UDI_VALID(udi, NULL);
434 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
435 "org.freedesktop.Hal.Device",
436 "GetAllProperties");
438 if (message == NULL) {
439 fprintf (stderr,
440 "%s %d : Couldn't allocate D-BUS message\n",
441 __FILE__, __LINE__);
442 return NULL;
445 dbus_error_init (&_error);
446 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
447 message, -1,
448 &_error);
450 dbus_move_error (&_error, error);
451 if (error != NULL && dbus_error_is_set (error)) {
452 fprintf (stderr,
453 "%s %d : %s\n",
454 __FILE__, __LINE__, error->message);
456 dbus_message_unref (message);
457 return NULL;
460 if (reply == NULL) {
461 dbus_message_unref (message);
462 return NULL;
465 dbus_message_iter_init (reply, &reply_iter);
467 result = malloc (sizeof (LibHalPropertySet));
468 if (result == NULL)
469 goto oom;
472 result->properties = malloc(sizeof(LibHalProperty)*result->num_properties);
473 if( result->properties==NULL )
475 /// @todo cleanup
476 return NULL;
480 result->properties_head = NULL;
481 result->num_properties = 0;
483 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY &&
484 dbus_message_iter_get_element_type (&reply_iter) != DBUS_TYPE_DICT_ENTRY) {
485 fprintf (stderr, "%s %d : error, expecting an array of dict entries\n",
486 __FILE__, __LINE__);
487 dbus_message_unref (message);
488 dbus_message_unref (reply);
489 return NULL;
492 dbus_message_iter_recurse (&reply_iter, &dict_iter);
494 p_last = NULL;
496 while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
498 DBusMessageIter dict_entry_iter, var_iter;
499 const char *key;
500 LibHalProperty *p;
502 dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
504 dbus_message_iter_get_basic (&dict_entry_iter, &key);
506 p = malloc (sizeof (LibHalProperty));
507 if (p == NULL)
508 goto oom;
510 p->next = NULL;
512 if (result->num_properties == 0)
513 result->properties_head = p;
515 if (p_last != NULL)
516 p_last->next = p;
518 p_last = p;
520 p->key = strdup (key);
521 if (p->key == NULL)
522 goto oom;
524 dbus_message_iter_next (&dict_entry_iter);
526 dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
529 p->type = dbus_message_iter_get_arg_type (&var_iter);
531 result->num_properties++;
533 if(!libhal_property_fill_value_from_variant (p, &var_iter))
534 goto oom;
536 dbus_message_iter_next (&dict_iter);
539 dbus_message_unref (message);
540 dbus_message_unref (reply);
542 return result;
544 oom:
545 fprintf (stderr,
546 "%s %d : error allocating memory\n",
547 __FILE__, __LINE__);
548 /** @todo FIXME cleanup */
549 return NULL;
552 /**
553 * libhal_free_property_set:
554 * @set: property-set to free
556 * Free a property set earlier obtained with libhal_device_get_all_properties().
558 void
559 libhal_free_property_set (LibHalPropertySet * set)
561 LibHalProperty *p;
562 LibHalProperty *q;
564 if (set == NULL)
565 return;
567 for (p = set->properties_head; p != NULL; p = q) {
568 free (p->key);
569 if (p->type == DBUS_TYPE_STRING)
570 free (p->v.str_value);
571 if (p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
572 libhal_free_string_array (p->v.strlist_value);
573 q = p->next;
574 free (p);
576 free (set);
580 * libhal_property_set_get_num_elems:
581 * @set: property set to consider
583 * Get the number of properties in a property set.
585 * Returns: number of properties in given property set
587 unsigned int
588 libhal_property_set_get_num_elems (LibHalPropertySet *set)
590 unsigned int num_elems;
591 LibHalProperty *p;
593 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
595 num_elems = 0;
596 for (p = set->properties_head; p != NULL; p = p->next)
597 num_elems++;
599 return num_elems;
602 static LibHalProperty *
603 property_set_lookup (const LibHalPropertySet *set, const char *key)
605 LibHalProperty *p;
607 LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
608 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
610 for (p = set->properties_head; p != NULL; p = p->next)
611 if (strcmp (key, p->key) == 0)
612 return p;
614 return NULL;
618 * libhal_ps_get_type:
619 * @set: property set
620 * @key: name of property to inspect
622 * Get the type of a given property.
624 * Returns: the #LibHalPropertyType of the given property,
625 * LIBHAL_PROPERTY_TYPE_INVALID if property is not in the set
627 LibHalPropertyType
628 libhal_ps_get_type (const LibHalPropertySet *set, const char *key)
630 LibHalProperty *p;
632 LIBHAL_CHECK_PARAM_VALID(set, "*set", LIBHAL_PROPERTY_TYPE_INVALID);
633 LIBHAL_CHECK_PARAM_VALID(key, "*key", LIBHAL_PROPERTY_TYPE_INVALID);
635 p = property_set_lookup (set, key);
636 if (p) return p->type;
637 else return LIBHAL_PROPERTY_TYPE_INVALID;
641 * libhal_ps_get_string:
642 * @set: property set
643 * @key: name of property to inspect
645 * Get the value of a property of type string.
647 * Returns: UTF8 nul-terminated string. This pointer is only valid
648 * until libhal_free_property_set() is invoked on the property set
649 * this property belongs to. NULL if property is not in the set or not a string
651 const char *
652 libhal_ps_get_string (const LibHalPropertySet *set, const char *key)
654 LibHalProperty *p;
656 LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
657 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
659 p = property_set_lookup (set, key);
660 if (p && p->type == LIBHAL_PROPERTY_TYPE_STRING)
661 return p->v.str_value;
662 else return NULL;
666 * libhal_ps_get_int:
667 * @set: property set
668 * @key: name of property to inspect
670 * Get the value of a property of type signed integer.
672 * Returns: property value (32-bit signed integer)
674 dbus_int32_t
675 libhal_ps_get_int32 (const LibHalPropertySet *set, const char *key)
677 LibHalProperty *p;
679 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
680 LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
682 p = property_set_lookup (set, key);
683 if (p && p->type == LIBHAL_PROPERTY_TYPE_INT32)
684 return p->v.int_value;
685 else return 0;
689 * libhal_ps_get_uint64:
690 * @set: property set
691 * @key: name of property to inspect
693 * Get the value of a property of type unsigned integer.
695 * Returns: property value (64-bit unsigned integer)
697 dbus_uint64_t
698 libhal_ps_get_uint64 (const LibHalPropertySet *set, const char *key)
700 LibHalProperty *p;
702 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
703 LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
705 p = property_set_lookup (set, key);
706 if (p && p->type == LIBHAL_PROPERTY_TYPE_UINT64)
707 return p->v.uint64_value;
708 else return 0;
712 * libhal_ps_get_double:
713 * @set: property set
714 * @key: name of property to inspect
716 * Get the value of a property of type double.
718 * Returns: property value (IEEE754 double precision float)
720 double
721 libhal_ps_get_double (const LibHalPropertySet *set, const char *key)
723 LibHalProperty *p;
725 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0.0);
726 LIBHAL_CHECK_PARAM_VALID(key, "*key", 0.0);
728 p = property_set_lookup (set, key);
729 if (p && p->type == LIBHAL_PROPERTY_TYPE_DOUBLE)
730 return p->v.double_value;
731 else return 0.0;
735 * libhal_ps_get_bool:
736 * @set: property set
737 * @key: name of property to inspect
739 * Get the value of a property of type bool.
741 * Returns: property value (bool)
743 dbus_bool_t
744 libhal_ps_get_bool (const LibHalPropertySet *set, const char *key)
746 LibHalProperty *p;
748 LIBHAL_CHECK_PARAM_VALID(set, "*set", FALSE);
749 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
751 p = property_set_lookup (set, key);
752 if (p && p->type == LIBHAL_PROPERTY_TYPE_BOOLEAN)
753 return p->v.bool_value;
754 else return FALSE;
758 * libhal_ps_get_strlist:
759 * @set: property set
760 * @key: name of property to inspect
762 * Get the value of a property of type string list.
764 * Returns: pointer to array of strings, this is owned by the property set
766 const char *const *
767 libhal_ps_get_strlist (const LibHalPropertySet *set, const char *key)
769 LibHalProperty *p;
771 LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
772 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
774 p = property_set_lookup (set, key);
775 if (p && p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
776 return (const char *const *) p->v.strlist_value;
777 else return NULL;
782 * libhal_psi_init:
783 * @iter: iterator object
784 * @set: property set to iterate over
786 * Initialize a property set iterator.
789 void
790 libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
792 if (set == NULL)
793 return;
795 iter->set = set;
796 iter->idx = 0;
797 iter->cur_prop = set->properties_head;
802 * libhal_psi_has_more:
803 * @iter: iterator object
805 * Determine whether there are more properties to iterate over.
807 * Returns: TRUE if there are more properties, FALSE otherwise.
809 dbus_bool_t
810 libhal_psi_has_more (LibHalPropertySetIterator * iter)
812 return iter->idx < iter->set->num_properties;
816 * libhal_psi_next:
817 * @iter: iterator object
819 * Advance iterator to next property.
821 void
822 libhal_psi_next (LibHalPropertySetIterator * iter)
824 iter->idx++;
825 iter->cur_prop = iter->cur_prop->next;
829 * libhal_psi_get_type:
830 * @iter: iterator object
832 * Get type of property.
834 * Returns: the property type at the iterator's position
836 LibHalPropertyType
837 libhal_psi_get_type (LibHalPropertySetIterator * iter)
839 return iter->cur_prop->type;
843 * libhal_psi_get_key:
844 * @iter: iterator object
846 * Get the key of a property.
848 * Returns: ASCII nul-terminated string. This pointer is only valid
849 * until libhal_free_property_set() is invoked on the property set
850 * this property belongs to.
852 char *
853 libhal_psi_get_key (LibHalPropertySetIterator * iter)
855 return iter->cur_prop->key;
859 * libhal_psi_get_string:
860 * @iter: iterator object
862 * Get the value of a property of type string.
864 * Returns: UTF8 nul-terminated string. This pointer is only valid
865 * until libhal_free_property_set() is invoked on the property set
866 * this property belongs to.
868 char *
869 libhal_psi_get_string (LibHalPropertySetIterator * iter)
871 return iter->cur_prop->v.str_value;
875 * libhal_psi_get_int:
876 * @iter: iterator object
878 * Get the value of a property of type signed integer.
880 * Returns: property value (32-bit signed integer)
882 dbus_int32_t
883 libhal_psi_get_int (LibHalPropertySetIterator * iter)
885 return iter->cur_prop->v.int_value;
889 * libhal_psi_get_uint64:
890 * @iter: iterator object
892 * Get the value of a property of type unsigned integer.
894 * Returns: property value (64-bit unsigned integer)
896 dbus_uint64_t
897 libhal_psi_get_uint64 (LibHalPropertySetIterator * iter)
899 return iter->cur_prop->v.uint64_value;
903 * libhal_psi_get_double:
904 * @iter: iterator object
906 * Get the value of a property of type double.
908 * Returns: property value (IEEE754 double precision float)
910 double
911 libhal_psi_get_double (LibHalPropertySetIterator * iter)
913 return iter->cur_prop->v.double_value;
917 * libhal_psi_get_bool:
918 * @iter: iterator object
920 * Get the value of a property of type bool.
922 * Returns: property value (bool)
924 dbus_bool_t
925 libhal_psi_get_bool (LibHalPropertySetIterator * iter)
927 return iter->cur_prop->v.bool_value;
931 * libhal_psi_get_strlist:
932 * @iter: iterator object
934 * Get the value of a property of type string list.
936 * Returns: pointer to array of strings
938 char **
939 libhal_psi_get_strlist (LibHalPropertySetIterator * iter)
941 return iter->cur_prop->v.strlist_value;
945 static DBusHandlerResult
946 filter_func (DBusConnection * connection,
947 DBusMessage * message, void *user_data)
949 const char *object_path;
950 DBusError error;
951 LibHalContext *ctx = (LibHalContext *) user_data;
953 if (ctx->is_shutdown)
954 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
956 dbus_error_init (&error);
958 object_path = dbus_message_get_path (message);
960 /*fprintf (stderr, "*** libhal filer_func: connection=%p obj_path=%s interface=%s method=%s\n",
961 connection,
962 dbus_message_get_path (message),
963 dbus_message_get_interface (message),
964 dbus_message_get_member (message));
967 if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager",
968 "DeviceAdded")) {
969 char *udi;
970 if (dbus_message_get_args (message, &error,
971 DBUS_TYPE_STRING, &udi,
972 DBUS_TYPE_INVALID)) {
973 if (ctx->device_added != NULL) {
974 ctx->device_added (ctx, udi);
976 } else {
977 LIBHAL_FREE_DBUS_ERROR(&error);
979 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
980 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
981 char *udi;
982 if (dbus_message_get_args (message, &error,
983 DBUS_TYPE_STRING, &udi,
984 DBUS_TYPE_INVALID)) {
985 if (ctx->device_removed != NULL) {
986 ctx->device_removed (ctx, udi);
988 } else {
989 LIBHAL_FREE_DBUS_ERROR(&error);
991 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
992 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","NewCapability")) {
993 char *udi;
994 char *capability;
995 if (dbus_message_get_args (message, &error,
996 DBUS_TYPE_STRING, &udi,
997 DBUS_TYPE_STRING, &capability,
998 DBUS_TYPE_INVALID)) {
999 if (ctx->device_new_capability != NULL) {
1000 ctx->device_new_capability (ctx, udi, capability);
1002 } else {
1003 LIBHAL_FREE_DBUS_ERROR(&error);
1005 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1006 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) {
1007 char *condition_name;
1008 char *condition_detail;
1009 if (dbus_message_get_args (message, &error,
1010 DBUS_TYPE_STRING, &condition_name,
1011 DBUS_TYPE_STRING, &condition_detail,
1012 DBUS_TYPE_INVALID)) {
1013 if (ctx->device_condition != NULL) {
1014 ctx->device_condition (ctx, object_path, condition_name, condition_detail);
1016 } else {
1017 LIBHAL_FREE_DBUS_ERROR(&error);
1019 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1020 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) {
1021 if (ctx->device_property_modified != NULL) {
1022 int i;
1023 char *key;
1024 dbus_bool_t removed;
1025 dbus_bool_t added;
1026 int num_modifications;
1027 DBusMessageIter iter;
1028 DBusMessageIter iter_array;
1030 dbus_message_iter_init (message, &iter);
1031 dbus_message_iter_get_basic (&iter, &num_modifications);
1032 dbus_message_iter_next (&iter);
1034 dbus_message_iter_recurse (&iter, &iter_array);
1036 for (i = 0; i < num_modifications; i++) {
1037 DBusMessageIter iter_struct;
1039 dbus_message_iter_recurse (&iter_array, &iter_struct);
1041 dbus_message_iter_get_basic (&iter_struct, &key);
1042 dbus_message_iter_next (&iter_struct);
1043 dbus_message_iter_get_basic (&iter_struct, &removed);
1044 dbus_message_iter_next (&iter_struct);
1045 dbus_message_iter_get_basic (&iter_struct, &added);
1047 ctx->device_property_modified (ctx,
1048 object_path,
1049 key, removed,
1050 added);
1052 dbus_message_iter_next (&iter_array);
1056 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1059 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1062 /* for i18n purposes */
1063 static dbus_bool_t libhal_already_initialized_once = FALSE;
1067 * libhal_get_all_devices:
1068 * @ctx: the context for the connection to hald
1069 * @num_devices: the number of devices will be stored here
1070 * @error: pointer to an initialized dbus error object for returning errors or NULL
1072 * Get all devices in the Global Device List (GDL).
1074 * Returns: An array of device identifiers terminated with NULL. It is
1075 * the responsibility of the caller to free with
1076 * libhal_free_string_array(). If an error occurs NULL is returned.
1078 char **
1079 libhal_get_all_devices (LibHalContext *ctx, int *num_devices, DBusError *error)
1081 DBusMessage *message;
1082 DBusMessage *reply;
1083 DBusMessageIter iter_array, reply_iter;
1084 char **hal_device_names;
1085 DBusError _error;
1087 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
1089 *num_devices = 0;
1091 message = dbus_message_new_method_call ("org.freedesktop.Hal",
1092 "/org/freedesktop/Hal/Manager",
1093 "org.freedesktop.Hal.Manager",
1094 "GetAllDevices");
1095 if (message == NULL) {
1096 fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__);
1097 return NULL;
1100 dbus_error_init (&_error);
1101 reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error);
1103 dbus_message_unref (message);
1105 dbus_move_error (&_error, error);
1106 if (error != NULL && dbus_error_is_set (error)) {
1107 return NULL;
1109 if (reply == NULL) {
1110 return NULL;
1113 /* now analyze reply */
1114 dbus_message_iter_init (reply, &reply_iter);
1116 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
1117 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
1118 dbus_message_unref (reply);
1119 return NULL;
1122 dbus_message_iter_recurse (&reply_iter, &iter_array);
1124 hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
1126 dbus_message_unref (reply);
1127 return hal_device_names;
1131 * libhal_device_get_property_type:
1132 * @ctx: the context for the connection to hald
1133 * @udi: the Unique Device Id
1134 * @key: name of the property
1135 * @error: pointer to an initialized dbus error object for returning errors or NULL
1137 * Query a property type of a device.
1139 * Returns: A LibHalPropertyType. LIBHAL_PROPERTY_TYPE_INVALID is
1140 * return if the property doesn't exist.
1142 LibHalPropertyType
1143 libhal_device_get_property_type (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
1145 DBusMessage *message;
1146 DBusMessage *reply;
1147 DBusMessageIter iter, reply_iter;
1148 LibHalPropertyType type;
1149 DBusError _error;
1151 LIBHAL_CHECK_LIBHALCONTEXT(ctx, LIBHAL_PROPERTY_TYPE_INVALID); /* or return NULL? */
1152 LIBHAL_CHECK_UDI_VALID(udi, LIBHAL_PROPERTY_TYPE_INVALID);
1153 LIBHAL_CHECK_PARAM_VALID(key, "*key", LIBHAL_PROPERTY_TYPE_INVALID);
1155 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1156 "org.freedesktop.Hal.Device",
1157 "GetPropertyType");
1158 if (message == NULL) {
1159 fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
1160 return LIBHAL_PROPERTY_TYPE_INVALID;
1163 dbus_message_iter_init_append (message, &iter);
1164 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1166 dbus_error_init (&_error);
1167 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1168 message, -1,
1169 &_error);
1171 dbus_message_unref (message);
1173 dbus_move_error (&_error, error);
1174 if (error != NULL && dbus_error_is_set (error)) {
1175 return LIBHAL_PROPERTY_TYPE_INVALID;
1177 if (reply == NULL) {
1178 return LIBHAL_PROPERTY_TYPE_INVALID;
1181 dbus_message_iter_init (reply, &reply_iter);
1182 dbus_message_iter_get_basic (&reply_iter, &type);
1184 dbus_message_unref (reply);
1185 return type;
1189 * libhal_device_get_property_strlist:
1190 * @ctx: the context for the connection to hald
1191 * @udi: unique Device Id
1192 * @key: name of the property
1193 * @error: pointer to an initialized dbus error object for returning errors or NULL
1195 * Get the value of a property of type string list.
1197 * Returns: Array of pointers to UTF8 nul-terminated strings
1198 * terminated by NULL. The caller is responsible for freeing this
1199 * string array with the function libhal_free_string_array(). Returns
1200 * NULL if the property didn't exist or we are OOM
1202 char **
1203 libhal_device_get_property_strlist (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
1205 DBusMessage *message;
1206 DBusMessage *reply;
1207 DBusMessageIter iter, iter_array, reply_iter;
1208 char **our_strings;
1209 DBusError _error;
1211 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
1212 LIBHAL_CHECK_UDI_VALID(udi, NULL);
1213 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
1215 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1216 "org.freedesktop.Hal.Device",
1217 "GetPropertyStringList");
1218 if (message == NULL) {
1219 fprintf (stderr,
1220 "%s %d : Couldn't allocate D-BUS message\n",
1221 __FILE__, __LINE__);
1222 return NULL;
1225 dbus_message_iter_init_append (message, &iter);
1226 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1228 dbus_error_init (&_error);
1229 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1230 message, -1,
1231 &_error);
1233 dbus_message_unref (message);
1235 dbus_move_error (&_error, error);
1236 if (error != NULL && dbus_error_is_set (error)) {
1237 return NULL;
1239 if (reply == NULL) {
1240 return NULL;
1242 /* now analyse reply */
1243 dbus_message_iter_init (reply, &reply_iter);
1245 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
1246 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
1247 dbus_message_unref (reply);
1248 return NULL;
1251 dbus_message_iter_recurse (&reply_iter, &iter_array);
1253 our_strings = libhal_get_string_array_from_iter (&iter_array, NULL);
1255 dbus_message_unref (reply);
1256 return our_strings;
1260 * libhal_device_get_property_string:
1261 * @ctx: the context for the connection to hald
1262 * @udi: the Unique Device Id
1263 * @key: the name of the property
1264 * @error: pointer to an initialized dbus error object for returning errors or NULL
1266 * Get the value of a property of type string.
1268 * Returns: UTF8 nul-terminated string. The caller is responsible for
1269 * freeing this string with the function libhal_free_string(). Returns
1270 * NULL if the property didn't exist or we are OOM.
1272 char *
1273 libhal_device_get_property_string (LibHalContext *ctx,
1274 const char *udi, const char *key, DBusError *error)
1276 DBusMessage *message;
1277 DBusMessage *reply;
1278 DBusMessageIter iter, reply_iter;
1279 char *value;
1280 char *dbus_str;
1281 DBusError _error;
1283 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
1284 LIBHAL_CHECK_UDI_VALID(udi, NULL);
1285 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
1287 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1288 "org.freedesktop.Hal.Device",
1289 "GetPropertyString");
1291 if (message == NULL) {
1292 fprintf (stderr,
1293 "%s %d : Couldn't allocate D-BUS message\n",
1294 __FILE__, __LINE__);
1295 return NULL;
1298 dbus_message_iter_init_append (message, &iter);
1299 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1301 dbus_error_init (&_error);
1302 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1303 message, -1,
1304 &_error);
1306 dbus_message_unref (message);
1308 dbus_move_error (&_error, error);
1309 if (error != NULL && dbus_error_is_set (error)) {
1310 return NULL;
1312 if (reply == NULL) {
1313 return NULL;
1316 dbus_message_iter_init (reply, &reply_iter);
1318 /* now analyze reply */
1319 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1320 DBUS_TYPE_STRING) {
1321 dbus_message_unref (reply);
1322 return NULL;
1325 dbus_message_iter_get_basic (&reply_iter, &dbus_str);
1326 value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
1327 if (value == NULL) {
1328 fprintf (stderr, "%s %d : error allocating memory\n",
1329 __FILE__, __LINE__);
1332 dbus_message_unref (reply);
1333 return value;
1337 * libhal_device_get_property_int:
1338 * @ctx: the context for the connection to hald
1339 * @udi: the Unique Device Id
1340 * @key: name of the property
1341 * @error: pointer to an initialized dbus error object for returning errors or NULL
1343 * Get the value of a property of type integer.
1345 * Returns: Property value (32-bit signed integer)
1347 dbus_int32_t
1348 libhal_device_get_property_int (LibHalContext *ctx,
1349 const char *udi, const char *key, DBusError *error)
1351 DBusMessage *message;
1352 DBusMessage *reply;
1353 DBusMessageIter iter, reply_iter;
1354 dbus_int32_t value;
1355 DBusError _error;
1357 LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
1358 LIBHAL_CHECK_UDI_VALID(udi, -1);
1359 LIBHAL_CHECK_PARAM_VALID(key, "*key", -1);
1361 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1362 "org.freedesktop.Hal.Device",
1363 "GetPropertyInteger");
1364 if (message == NULL) {
1365 fprintf (stderr,
1366 "%s %d : Couldn't allocate D-BUS message\n",
1367 __FILE__, __LINE__);
1368 return -1;
1371 dbus_message_iter_init_append (message, &iter);
1372 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1374 dbus_error_init (&_error);
1375 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1376 message, -1,
1377 &_error);
1379 dbus_message_unref (message);
1381 dbus_move_error (&_error, error);
1382 if (error != NULL && dbus_error_is_set (error)) {
1383 return -1;
1385 if (reply == NULL) {
1386 return -1;
1389 dbus_message_iter_init (reply, &reply_iter);
1391 /* now analyze reply */
1392 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1393 DBUS_TYPE_INT32) {
1394 fprintf (stderr,
1395 "%s %d : property '%s' for device '%s' is not "
1396 "of type integer\n", __FILE__, __LINE__, key,
1397 udi);
1398 dbus_message_unref (reply);
1399 return -1;
1401 dbus_message_iter_get_basic (&reply_iter, &value);
1403 dbus_message_unref (reply);
1404 return value;
1408 * libhal_device_get_property_uint64:
1409 * @ctx: the context for the connection to hald
1410 * @udi: the Unique Device Id
1411 * @key: name of the property
1412 * @error: pointer to an initialized dbus error object for returning errors or NULL
1414 * Get the value of a property of type signed integer.
1416 * Returns: Property value (64-bit unsigned integer)
1418 dbus_uint64_t
1419 libhal_device_get_property_uint64 (LibHalContext *ctx,
1420 const char *udi, const char *key, DBusError *error)
1422 DBusMessage *message;
1423 DBusMessage *reply;
1424 DBusMessageIter iter, reply_iter;
1425 dbus_uint64_t value;
1426 DBusError _error;
1428 LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
1429 LIBHAL_CHECK_UDI_VALID(udi, -1);
1430 LIBHAL_CHECK_PARAM_VALID(key, "*key", -1);
1432 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1433 "org.freedesktop.Hal.Device",
1434 "GetPropertyInteger");
1435 if (message == NULL) {
1436 fprintf (stderr,
1437 "%s %d : Couldn't allocate D-BUS message\n",
1438 __FILE__, __LINE__);
1439 return -1;
1442 dbus_message_iter_init_append (message, &iter);
1443 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1445 dbus_error_init (&_error);
1446 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1447 message, -1,
1448 &_error);
1450 dbus_message_unref (message);
1452 dbus_move_error (&_error, error);
1453 if (error != NULL && dbus_error_is_set (error)) {
1454 return -1;
1456 if (reply == NULL) {
1457 return -1;
1460 dbus_message_iter_init (reply, &reply_iter);
1461 /* now analyze reply */
1462 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1463 DBUS_TYPE_UINT64) {
1464 fprintf (stderr,
1465 "%s %d : property '%s' for device '%s' is not "
1466 "of type integer\n", __FILE__, __LINE__, key,
1467 udi);
1468 dbus_message_unref (reply);
1469 return -1;
1471 dbus_message_iter_get_basic (&reply_iter, &value);
1473 dbus_message_unref (reply);
1474 return value;
1478 * libhal_device_get_property_double:
1479 * @ctx: the context for the connection to hald
1480 * @udi: the Unique Device Id
1481 * @key: name of the property
1482 * @error: pointer to an initialized dbus error object for returning errors or NULL
1484 * Get the value of a property of type double.
1486 * Returns: Property value (IEEE754 double precision float)
1488 double
1489 libhal_device_get_property_double (LibHalContext *ctx,
1490 const char *udi, const char *key, DBusError *error)
1492 DBusMessage *message;
1493 DBusMessage *reply;
1494 DBusMessageIter iter, reply_iter;
1495 double value;
1496 DBusError _error;
1498 LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1.0);
1499 LIBHAL_CHECK_UDI_VALID(udi, -1.0);
1500 LIBHAL_CHECK_PARAM_VALID(key, "*key", -1.0);
1502 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1503 "org.freedesktop.Hal.Device",
1504 "GetPropertyDouble");
1505 if (message == NULL) {
1506 fprintf (stderr,
1507 "%s %d : Couldn't allocate D-BUS message\n",
1508 __FILE__, __LINE__);
1509 return -1.0f;
1512 dbus_message_iter_init_append (message, &iter);
1513 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1515 dbus_error_init (&_error);
1516 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1517 message, -1,
1518 &_error);
1520 dbus_message_unref (message);
1522 dbus_move_error (&_error, error);
1523 if (error != NULL && dbus_error_is_set (error)) {
1524 return -1.0f;
1526 if (reply == NULL) {
1527 return -1.0f;
1530 dbus_message_iter_init (reply, &reply_iter);
1532 /* now analyze reply */
1533 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1534 DBUS_TYPE_DOUBLE) {
1535 fprintf (stderr,
1536 "%s %d : property '%s' for device '%s' is not "
1537 "of type double\n", __FILE__, __LINE__, key, udi);
1538 dbus_message_unref (reply);
1539 return -1.0f;
1541 dbus_message_iter_get_basic (&reply_iter, &value);
1543 dbus_message_unref (reply);
1544 return (double) value;
1548 * libhal_device_get_property_bool:
1549 * @ctx: the context for the connection to hald
1550 * @udi: the Unique Device Id
1551 * @key: name of the property
1552 * @error: pointer to an initialized dbus error object for returning errors or NULL
1554 * Get the value of a property of type bool.
1556 * Returns: Property value (boolean)
1558 dbus_bool_t
1559 libhal_device_get_property_bool (LibHalContext *ctx,
1560 const char *udi, const char *key, DBusError *error)
1562 DBusMessage *message;
1563 DBusMessage *reply;
1564 DBusMessageIter iter, reply_iter;
1565 dbus_bool_t value;
1566 DBusError _error;
1568 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1569 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1570 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1572 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1573 "org.freedesktop.Hal.Device",
1574 "GetPropertyBoolean");
1575 if (message == NULL) {
1576 fprintf (stderr,
1577 "%s %d : Couldn't allocate D-BUS message\n",
1578 __FILE__, __LINE__);
1579 return FALSE;
1582 dbus_message_iter_init_append (message, &iter);
1583 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1585 dbus_error_init (&_error);
1586 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1587 message, -1,
1588 &_error);
1590 dbus_message_unref (message);
1592 dbus_move_error (&_error, error);
1593 if (error != NULL && dbus_error_is_set (error)) {
1594 return FALSE;
1596 if (reply == NULL) {
1597 return FALSE;
1600 dbus_message_iter_init (reply, &reply_iter);
1602 /* now analyze reply */
1603 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1604 DBUS_TYPE_BOOLEAN) {
1605 fprintf (stderr,
1606 "%s %d : property '%s' for device '%s' is not "
1607 "of type bool\n", __FILE__, __LINE__, key, udi);
1608 dbus_message_unref (reply);
1609 return FALSE;
1611 dbus_message_iter_get_basic (&reply_iter, &value);
1613 dbus_message_unref (reply);
1614 return value;
1618 /* generic helper */
1619 static dbus_bool_t
1620 libhal_device_set_property_helper (LibHalContext *ctx,
1621 const char *udi,
1622 const char *key,
1623 int type,
1624 const char *str_value,
1625 dbus_int32_t int_value,
1626 dbus_uint64_t uint64_value,
1627 double double_value,
1628 dbus_bool_t bool_value,
1629 DBusError *error)
1631 DBusMessage *message;
1632 DBusMessage *reply;
1633 DBusMessageIter iter;
1634 char *method_name = NULL;
1636 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1637 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1638 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1640 /** @todo sanity check incoming params */
1641 switch (type) {
1642 case DBUS_TYPE_INVALID:
1643 method_name = "RemoveProperty";
1644 break;
1645 case DBUS_TYPE_STRING:
1646 method_name = "SetPropertyString";
1647 break;
1648 case DBUS_TYPE_INT32:
1649 case DBUS_TYPE_UINT64:
1650 method_name = "SetPropertyInteger";
1651 break;
1652 case DBUS_TYPE_DOUBLE:
1653 method_name = "SetPropertyDouble";
1654 break;
1655 case DBUS_TYPE_BOOLEAN:
1656 method_name = "SetPropertyBoolean";
1657 break;
1659 default:
1660 /* cannot happen; is not callable from outside this file */
1661 break;
1664 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1665 "org.freedesktop.Hal.Device",
1666 method_name);
1667 if (message == NULL) {
1668 fprintf (stderr,
1669 "%s %d : Couldn't allocate D-BUS message\n",
1670 __FILE__, __LINE__);
1671 return FALSE;
1674 dbus_message_iter_init_append (message, &iter);
1675 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1676 switch (type) {
1677 case DBUS_TYPE_STRING:
1678 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str_value);
1679 break;
1680 case DBUS_TYPE_INT32:
1681 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &int_value);
1682 break;
1683 case DBUS_TYPE_UINT64:
1684 dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &uint64_value);
1685 break;
1686 case DBUS_TYPE_DOUBLE:
1687 dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &double_value);
1688 break;
1689 case DBUS_TYPE_BOOLEAN:
1690 dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bool_value);
1691 break;
1695 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1696 message, -1,
1697 error);
1699 dbus_message_unref (message);
1701 if (error != NULL && dbus_error_is_set (error)) {
1702 return FALSE;
1704 if (reply == NULL) {
1705 return FALSE;
1708 dbus_message_unref (reply);
1710 return TRUE;
1714 * libhal_device_set_property_string:
1715 * @ctx: the context for the connection to hald
1716 * @udi: the Unique Device Id
1717 * @key: name of the property
1718 * @value: value of the property; a UTF8 string
1719 * @error: pointer to an initialized dbus error object for returning errors or NULL
1721 * Set a property of type string.
1723 * Returns: TRUE if the property was set, FALSE if the device didn't
1724 * exist or the property had a different type.
1726 dbus_bool_t
1727 libhal_device_set_property_string (LibHalContext *ctx,
1728 const char *udi,
1729 const char *key,
1730 const char *value,
1731 DBusError *error)
1733 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1734 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1735 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1736 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
1738 return libhal_device_set_property_helper (ctx, udi, key,
1739 DBUS_TYPE_STRING,
1740 value, 0, 0, 0.0f, FALSE, error);
1744 * libhal_device_set_property_int:
1745 * @ctx: the context for the connection to hald
1746 * @udi: the Unique Device Id
1747 * @key: name of the property
1748 * @value: value of the property
1749 * @error: pointer to an initialized dbus error object for returning errors or NULL
1751 * Set a property of type signed integer.
1753 * Returns: TRUE if the property was set, FALSE if the device didn't
1754 * exist or the property had a different type.
1756 dbus_bool_t
1757 libhal_device_set_property_int (LibHalContext *ctx, const char *udi,
1758 const char *key, dbus_int32_t value, DBusError *error)
1760 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1761 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1762 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1764 return libhal_device_set_property_helper (ctx, udi, key,
1765 DBUS_TYPE_INT32,
1766 NULL, value, 0, 0.0f, FALSE, error);
1770 * libhal_device_set_property_uint64:
1771 * @ctx: the context for the connection to hald
1772 * @udi: the Unique Device Id
1773 * @key: name of the property
1774 * @value: value of the property
1775 * @error: pointer to an initialized dbus error object for returning errors or NULL
1777 * Set a property of type unsigned integer.
1779 * Returns: TRUE if the property was set, FALSE if the device didn't
1780 * exist or the property had a different type.
1782 dbus_bool_t
1783 libhal_device_set_property_uint64 (LibHalContext *ctx, const char *udi,
1784 const char *key, dbus_uint64_t value, DBusError *error)
1786 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1787 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1788 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1790 return libhal_device_set_property_helper (ctx, udi, key,
1791 DBUS_TYPE_UINT64,
1792 NULL, 0, value, 0.0f, FALSE, error);
1796 * libhal_device_set_property_double:
1797 * @ctx: the context for the connection to hald
1798 * @udi: the Unique Device Id
1799 * @key: name of the property
1800 * @value: value of the property
1801 * @error: pointer to an initialized dbus error object for returning errors or NULL
1803 * Set a property of type double.
1805 * Returns: TRUE if the property was set, FALSE if the device didn't
1806 * exist or the property had a different type.
1808 dbus_bool_t
1809 libhal_device_set_property_double (LibHalContext *ctx, const char *udi,
1810 const char *key, double value, DBusError *error)
1812 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1813 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1814 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1816 return libhal_device_set_property_helper (ctx, udi, key,
1817 DBUS_TYPE_DOUBLE,
1818 NULL, 0, 0, value, FALSE, error);
1822 * libhal_device_set_property_bool:
1823 * @ctx: the context for the connection to hald
1824 * @udi: the Unique Device Id
1825 * @key: name of the property
1826 * @value: value of the property
1827 * @error: pointer to an initialized dbus error object for returning errors or NULL
1829 * Set a property of type bool.
1831 * Returns: TRUE if the property was set, FALSE if the device didn't
1832 * exist or the property had a different type.
1834 dbus_bool_t
1835 libhal_device_set_property_bool (LibHalContext *ctx, const char *udi,
1836 const char *key, dbus_bool_t value, DBusError *error)
1838 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1839 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1840 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1842 return libhal_device_set_property_helper (ctx, udi, key,
1843 DBUS_TYPE_BOOLEAN,
1844 NULL, 0, 0, 0.0f, value, error);
1849 * libhal_device_remove_property:
1850 * @ctx: the context for the connection to hald
1851 * @udi: the Unique Device Id
1852 * @key: name of the property
1853 * @error: pointer to an initialized dbus error object for returning errors or NULL
1855 * Remove a property.
1857 * Returns: TRUE if the property was set, FALSE if the device didn't
1858 * exist
1860 dbus_bool_t
1861 libhal_device_remove_property (LibHalContext *ctx,
1862 const char *udi, const char *key, DBusError *error)
1864 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1865 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1866 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1868 return libhal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_INVALID,
1869 /* DBUS_TYPE_INVALID means remove */
1870 NULL, 0, 0, 0.0f, FALSE, error);
1874 * libhal_device_property_strlist_append:
1875 * @ctx: the context for the connection to hald
1876 * @udi: the Unique Device Id
1877 * @key: name of the property
1878 * @value: value to append to property
1879 * @error: pointer to an initialized dbus error object for returning errors or NULL
1881 * Append to a property of type strlist.
1883 * Returns: TRUE if the value was appended, FALSE if the device didn't
1884 * exist or the property had a different type.
1886 dbus_bool_t
1887 libhal_device_property_strlist_append (LibHalContext *ctx,
1888 const char *udi,
1889 const char *key,
1890 const char *value,
1891 DBusError *error)
1893 DBusMessage *message;
1894 DBusMessage *reply;
1895 DBusMessageIter iter;
1897 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1898 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1899 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1900 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
1902 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1903 "org.freedesktop.Hal.Device",
1904 "StringListAppend");
1905 if (message == NULL) {
1906 fprintf (stderr,
1907 "%s %d : Couldn't allocate D-BUS message\n",
1908 __FILE__, __LINE__);
1909 return FALSE;
1911 dbus_message_iter_init_append (message, &iter);
1912 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1913 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
1915 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1916 message, -1,
1917 error);
1919 dbus_message_unref (message);
1921 if (error != NULL && dbus_error_is_set (error)) {
1922 return FALSE;
1924 if (reply == NULL) {
1925 return FALSE;
1928 dbus_message_unref (reply);
1929 return TRUE;
1933 * libhal_device_property_strlist_prepend:
1934 * @ctx: the context for the connection to hald
1935 * @udi: the Unique Device Id
1936 * @key: name of the property
1937 * @value: value to prepend to property
1938 * @error: pointer to an initialized dbus error object for returning errors or NULL
1940 * Prepend to a property of type strlist.
1942 * Returns: TRUE if the value was prepended, FALSE if the device
1943 * didn't exist or the property had a different type.
1945 dbus_bool_t
1946 libhal_device_property_strlist_prepend (LibHalContext *ctx,
1947 const char *udi,
1948 const char *key,
1949 const char *value,
1950 DBusError *error)
1952 DBusMessage *message;
1953 DBusMessage *reply;
1954 DBusMessageIter iter;
1956 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1957 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1958 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1959 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
1961 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1962 "org.freedesktop.Hal.Device",
1963 "StringListPrepend");
1964 if (message == NULL) {
1965 fprintf (stderr,
1966 "%s %d : Couldn't allocate D-BUS message\n",
1967 __FILE__, __LINE__);
1968 return FALSE;
1970 dbus_message_iter_init_append (message, &iter);
1971 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1972 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
1974 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1975 message, -1,
1976 error);
1978 dbus_message_unref (message);
1980 if (error != NULL && dbus_error_is_set (error)) {
1981 return FALSE;
1983 if (reply == NULL) {
1984 return FALSE;
1987 dbus_message_unref (reply);
1988 return TRUE;
1992 * libhal_device_property_strlist_remove_index:
1993 * @ctx: the context for the connection to hald
1994 * @udi: the Unique Device Id
1995 * @key: name of the property
1996 * @idx: index of string to remove in the strlist
1997 * @error: pointer to an initialized dbus error object for returning errors or NULL
1999 * Remove a specified string from a property of type strlist.
2001 * Returns: TRUE if the string was removed, FALSE if the device didn't
2002 * exist or the property had a different type.
2004 dbus_bool_t
2005 libhal_device_property_strlist_remove_index (LibHalContext *ctx,
2006 const char *udi,
2007 const char *key,
2008 unsigned int idx,
2009 DBusError *error)
2011 DBusMessage *message;
2012 DBusMessage *reply;
2013 DBusMessageIter iter;
2015 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2016 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2017 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
2019 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2020 "org.freedesktop.Hal.Device",
2021 "StringListRemoveIndex");
2022 if (message == NULL) {
2023 fprintf (stderr,
2024 "%s %d : Couldn't allocate D-BUS message\n",
2025 __FILE__, __LINE__);
2026 return FALSE;
2028 dbus_message_iter_init_append (message, &iter);
2029 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2030 dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &idx);
2032 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2033 message, -1,
2034 error);
2036 dbus_message_unref (message);
2038 if (error != NULL && dbus_error_is_set (error)) {
2039 return FALSE;
2041 if (reply == NULL) {
2042 return FALSE;
2045 dbus_message_unref (reply);
2046 return TRUE;
2050 * libhal_device_property_strlist_remove:
2051 * @ctx: the context for the connection to hald
2052 * @udi: the Unique Device Id
2053 * @key: name of the property
2054 * @value: the string to remove
2055 * @error: pointer to an initialized dbus error object for returning errors or NULL
2057 * Remove a specified string from a property of type strlist.
2059 * Returns: TRUE if the string was removed, FALSE if the device didn't
2060 * exist or the property had a different type.
2062 dbus_bool_t
2063 libhal_device_property_strlist_remove (LibHalContext *ctx,
2064 const char *udi,
2065 const char *key,
2066 const char *value, DBusError *error)
2068 DBusMessage *message;
2069 DBusMessage *reply;
2070 DBusMessageIter iter;
2072 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2073 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2074 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
2075 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
2077 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2078 "org.freedesktop.Hal.Device",
2079 "StringListRemove");
2080 if (message == NULL) {
2081 fprintf (stderr,
2082 "%s %d : Couldn't allocate D-BUS message\n",
2083 __FILE__, __LINE__);
2084 return FALSE;
2086 dbus_message_iter_init_append (message, &iter);
2087 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2088 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
2090 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2091 message, -1,
2092 error);
2094 dbus_message_unref (message);
2096 if (error != NULL && dbus_error_is_set (error)) {
2097 return FALSE;
2099 if (reply == NULL) {
2100 return FALSE;
2103 dbus_message_unref (reply);
2104 return TRUE;
2109 * libhal_device_lock:
2110 * @ctx: the context for the connection to hald
2111 * @udi: the Unique Device Id
2112 * @reason_to_lock: a user-presentable reason why the device is locked.
2113 * @reason_why_locked: a pointer to store the reason why the device cannot be locked on failure, or NULL
2114 * @error: pointer to an initialized dbus error object for returning errors or NULL
2116 * Take an advisory lock on the device.
2118 * Returns: TRUE if the lock was obtained, FALSE otherwise
2120 dbus_bool_t
2121 libhal_device_lock (LibHalContext *ctx,
2122 const char *udi,
2123 const char *reason_to_lock,
2124 char **reason_why_locked, DBusError *error)
2126 DBusMessage *message;
2127 DBusMessageIter iter;
2128 DBusMessage *reply;
2130 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2131 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2133 if (reason_why_locked != NULL)
2134 *reason_why_locked = NULL;
2136 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2137 udi,
2138 "org.freedesktop.Hal.Device",
2139 "Lock");
2141 if (message == NULL) {
2142 fprintf (stderr,
2143 "%s %d : Couldn't allocate D-BUS message\n",
2144 __FILE__, __LINE__);
2145 return FALSE;
2148 dbus_message_iter_init_append (message, &iter);
2149 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reason_to_lock);
2152 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2153 message, -1,
2154 error);
2156 dbus_message_unref (message);
2158 if (error != NULL && dbus_error_is_set (error)) {
2159 if (strcmp (error->name,
2160 "org.freedesktop.Hal.DeviceAlreadyLocked") == 0) {
2161 if (reason_why_locked != NULL) {
2162 *reason_why_locked =
2163 dbus_malloc0 (strlen (error->message) + 1);
2164 if (*reason_why_locked == NULL)
2165 return FALSE;
2166 strcpy (*reason_why_locked, error->message);
2170 return FALSE;
2172 if (reply == NULL)
2173 return FALSE;
2175 dbus_message_unref (reply);
2177 return TRUE;
2181 * libhal_device_unlock:
2182 * @ctx: the context for the connection to hald
2183 * @udi: the Unique Device Id
2184 * @error: pointer to an initialized dbus error object for returning errors or NULL
2186 * Release an advisory lock on the device.
2188 * Returns: TRUE if the device was successfully unlocked,
2189 * FALSE otherwise
2191 dbus_bool_t
2192 libhal_device_unlock (LibHalContext *ctx,
2193 const char *udi, DBusError *error)
2195 DBusMessage *message;
2196 DBusMessage *reply;
2198 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2199 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2201 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2202 udi,
2203 "org.freedesktop.Hal.Device",
2204 "Unlock");
2206 if (message == NULL) {
2207 fprintf (stderr,
2208 "%s %d : Couldn't allocate D-BUS message\n",
2209 __FILE__, __LINE__);
2210 return FALSE;
2214 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2215 message, -1,
2216 error);
2218 dbus_message_unref (message);
2220 if (error != NULL && dbus_error_is_set (error)) {
2221 return FALSE;
2223 if (reply == NULL)
2224 return FALSE;
2226 dbus_message_unref (reply);
2228 return TRUE;
2233 * libhal_new_device:
2234 * @ctx: the context for the connection to hald
2235 * @error: pointer to an initialized dbus error object for returning errors or NULL
2237 * Create a new device object which will be hidden from applications
2238 * until the CommitToGdl(), ie. libhal_device_commit_to_gdl(), method
2239 * is called. Note that the program invoking this method needs to run
2240 * with super user privileges.
2242 * Returns: Temporary device unique id or NULL if there was a
2243 * problem. This string must be freed by the caller.
2245 char *
2246 libhal_new_device (LibHalContext *ctx, DBusError *error)
2248 DBusMessage *message;
2249 DBusMessage *reply;
2250 DBusMessageIter reply_iter;
2251 char *value;
2252 char *dbus_str;
2254 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2256 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2257 "/org/freedesktop/Hal/Manager",
2258 "org.freedesktop.Hal.Manager",
2259 "NewDevice");
2260 if (message == NULL) {
2261 fprintf (stderr,
2262 "%s %d : Couldn't allocate D-BUS message\n",
2263 __FILE__, __LINE__);
2264 return NULL;
2268 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2269 message, -1,
2270 error);
2272 dbus_message_unref (message);
2274 if (error != NULL && dbus_error_is_set (error)) {
2275 return NULL;
2277 if (reply == NULL) {
2278 return NULL;
2281 dbus_message_iter_init (reply, &reply_iter);
2283 /* now analyze reply */
2284 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) {
2285 fprintf (stderr,
2286 "%s %d : expected a string in reply to NewDevice\n",
2287 __FILE__, __LINE__);
2288 dbus_message_unref (reply);
2289 return NULL;
2292 dbus_message_iter_get_basic (&reply_iter, &dbus_str);
2293 value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
2294 if (value == NULL) {
2295 fprintf (stderr, "%s %d : error allocating memory\n",
2296 __FILE__, __LINE__);
2299 dbus_message_unref (reply);
2300 return value;
2305 * libhal_device_commit_to_gdl:
2306 * @ctx: the context for the connection to hald
2307 * @temp_udi: the temporary unique device id as returned by libhal_new_device()
2308 * @udi: the new unique device id.
2309 * @error: pointer to an initialized dbus error object for returning errors or NULL
2311 * When a hidden device has been built using the NewDevice method,
2312 * ie. libhal_new_device(), and the org.freedesktop.Hal.Device
2313 * interface this function will commit it to the global device list.
2315 * This means that the device object will be visible to applications
2316 * and the HAL daemon will possibly attempt to boot the device
2317 * (depending on the property RequireEnable).
2319 * Note that the program invoking this method needs to run with super
2320 * user privileges.
2322 * Returns: FALSE if the given unique device id is already in use.
2324 dbus_bool_t
2325 libhal_device_commit_to_gdl (LibHalContext *ctx,
2326 const char *temp_udi, const char *udi, DBusError *error)
2328 DBusMessage *message;
2329 DBusMessage *reply;
2330 DBusMessageIter iter;
2332 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2333 LIBHAL_CHECK_UDI_VALID(temp_udi, FALSE);
2334 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2336 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2337 "/org/freedesktop/Hal/Manager",
2338 "org.freedesktop.Hal.Manager",
2339 "CommitToGdl");
2340 if (message == NULL) {
2341 fprintf (stderr,
2342 "%s %d : Couldn't allocate D-BUS message\n",
2343 __FILE__, __LINE__);
2344 return FALSE;
2347 dbus_message_iter_init_append (message, &iter);
2348 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &temp_udi);
2349 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
2352 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2353 message, -1,
2354 error);
2356 dbus_message_unref (message);
2358 if (error != NULL && dbus_error_is_set (error)) {
2359 return FALSE;
2361 if (reply == NULL) {
2362 return FALSE;
2365 dbus_message_unref (reply);
2366 return TRUE;
2370 * libhal_remove_device:
2371 * @ctx: the context for the connection to hald
2372 * @udi: the Unique device id.
2373 * @error: pointer to an initialized dbus error object for returning errors or NULL
2375 * This method can be invoked when a device is removed. The HAL daemon
2376 * will shut down the device. Note that the device may still be in the
2377 * device list if the Persistent property is set to true.
2379 * Note that the program invoking this method needs to run with super
2380 * user privileges.
2382 * Returns: TRUE if the device was removed, FALSE otherwise
2384 dbus_bool_t
2385 libhal_remove_device (LibHalContext *ctx, const char *udi, DBusError *error)
2387 DBusMessage *message;
2388 DBusMessage *reply;
2389 DBusMessageIter iter;
2391 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2392 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2394 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2395 "/org/freedesktop/Hal/Manager",
2396 "org.freedesktop.Hal.Manager",
2397 "Remove");
2398 if (message == NULL) {
2399 fprintf (stderr,
2400 "%s %d : Couldn't allocate D-BUS message\n",
2401 __FILE__, __LINE__);
2402 return FALSE;
2405 dbus_message_iter_init_append (message, &iter);
2406 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
2409 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2410 message, -1,
2411 error);
2413 dbus_message_unref (message);
2415 if (error != NULL && dbus_error_is_set (error)) {
2416 return FALSE;
2418 if (reply == NULL) {
2419 return FALSE;
2422 dbus_message_unref (reply);
2423 return TRUE;
2427 * libhal_device_exists:
2428 * @ctx: the context for the connection to hald
2429 * @udi: the Unique device id.
2430 * @error: pointer to an initialized dbus error object for returning errors or NULL
2432 * Determine if a device exists.
2434 * Returns: TRUE if the device exists
2436 dbus_bool_t
2437 libhal_device_exists (LibHalContext *ctx, const char *udi, DBusError *error)
2439 DBusMessage *message;
2440 DBusMessage *reply;
2441 DBusMessageIter iter, reply_iter;
2442 dbus_bool_t value;
2443 DBusError _error;
2445 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2446 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2448 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2449 "/org/freedesktop/Hal/Manager",
2450 "org.freedesktop.Hal.Manager",
2451 "DeviceExists");
2452 if (message == NULL) {
2453 fprintf (stderr,
2454 "%s %d : Couldn't allocate D-BUS message\n",
2455 __FILE__, __LINE__);
2456 return FALSE;
2459 dbus_message_iter_init_append (message, &iter);
2460 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
2462 dbus_error_init (&_error);
2463 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2464 message, -1,
2465 &_error);
2467 dbus_message_unref (message);
2469 dbus_move_error (&_error, error);
2470 if (error != NULL && dbus_error_is_set (error)) {
2471 return FALSE;
2473 if (reply == NULL) {
2474 return FALSE;
2477 dbus_message_iter_init (reply, &reply_iter);
2479 /* now analyze reply */
2480 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
2481 fprintf (stderr,
2482 "%s %d : expected a bool in reply to DeviceExists\n",
2483 __FILE__, __LINE__);
2484 dbus_message_unref (reply);
2485 return FALSE;
2488 dbus_message_iter_get_basic (&reply_iter, &value);
2490 dbus_message_unref (reply);
2491 return value;
2495 * libhal_device_property_exists:
2496 * @ctx: the context for the connection to hald
2497 * @udi: the Unique device id.
2498 * @key: name of the property
2499 * @error: pointer to an initialized dbus error object for returning errors or NULL
2501 * Determine if a property on a device exists.
2503 * Returns: TRUE if the device exists, FALSE otherwise
2505 dbus_bool_t
2506 libhal_device_property_exists (LibHalContext *ctx,
2507 const char *udi, const char *key, DBusError *error)
2509 DBusMessage *message;
2510 DBusMessage *reply;
2511 DBusMessageIter iter, reply_iter;
2512 dbus_bool_t value;
2513 DBusError _error;
2515 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2516 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2517 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
2519 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2520 "org.freedesktop.Hal.Device",
2521 "PropertyExists");
2522 if (message == NULL) {
2523 fprintf (stderr,
2524 "%s %d : Couldn't allocate D-BUS message\n",
2525 __FILE__, __LINE__);
2526 return FALSE;
2529 dbus_message_iter_init_append (message, &iter);
2530 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2532 dbus_error_init (&_error);
2533 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2534 message, -1,
2535 &_error);
2537 dbus_message_unref (message);
2539 dbus_move_error (&_error, error);
2540 if (error != NULL && dbus_error_is_set (error)) {
2541 return FALSE;
2543 if (reply == NULL) {
2544 return FALSE;
2547 dbus_message_iter_init (reply, &reply_iter);
2549 /* now analyse reply */
2550 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
2551 fprintf (stderr, "%s %d : expected a bool in reply to "
2552 "PropertyExists\n", __FILE__, __LINE__);
2553 dbus_message_unref (reply);
2554 return FALSE;
2557 dbus_message_iter_get_basic (&reply_iter, &value);
2559 dbus_message_unref (reply);
2560 return value;
2564 * libhal_merge_properties:
2565 * @ctx: the context for the connection to hald
2566 * @target_udi: the Unique device id of target device to merge to
2567 * @source_udi: the Unique device id of device to merge from
2568 * @error: pointer to an initialized dbus error object for returning errors or NULL
2570 * Merge properties from one device to another.
2572 * Returns: TRUE if the properties were merged, FALSE otherwise
2574 dbus_bool_t
2575 libhal_merge_properties (LibHalContext *ctx,
2576 const char *target_udi, const char *source_udi, DBusError *error)
2578 DBusMessage *message;
2579 DBusMessage *reply;
2580 DBusMessageIter iter;
2582 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2583 LIBHAL_CHECK_UDI_VALID(target_udi, FALSE);
2584 LIBHAL_CHECK_UDI_VALID(source_udi, FALSE);
2586 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2587 "/org/freedesktop/Hal/Manager",
2588 "org.freedesktop.Hal.Manager",
2589 "MergeProperties");
2590 if (message == NULL) {
2591 fprintf (stderr,
2592 "%s %d : Couldn't allocate D-BUS message\n",
2593 __FILE__, __LINE__);
2594 return FALSE;
2597 dbus_message_iter_init_append (message, &iter);
2598 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &target_udi);
2599 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &source_udi);
2602 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2603 message, -1,
2604 error);
2606 dbus_message_unref (message);
2608 if (error != NULL && dbus_error_is_set (error)) {
2609 return FALSE;
2611 if (reply == NULL) {
2612 return FALSE;
2615 dbus_message_unref (reply);
2616 return TRUE;
2620 * libhal_device_matches:
2621 * @ctx: the context for the connection to hald
2622 * @udi1: the Unique Device Id for device 1
2623 * @udi2: the Unique Device Id for device 2
2624 * @property_namespace: the namespace for set of devices, e.g. "usb"
2625 * @error: pointer to an initialized dbus error object for returning errors or NULL
2627 * Check a set of properties for two devices matches.
2629 * Checks that all properties where keys, starting with a given value
2630 * (namespace), of the first device is in the second device and that
2631 * they got the same value and type.
2633 * Note that the other inclusion isn't tested, so there could be
2634 * properties (from the given namespace) in the second device not
2635 * present in the first device.
2637 * Returns: TRUE if all properties starting with the given namespace
2638 * parameter from one device is in the other and have the same value.
2640 dbus_bool_t
2641 libhal_device_matches (LibHalContext *ctx,
2642 const char *udi1, const char *udi2,
2643 const char *property_namespace, DBusError *error)
2645 DBusMessage *message;
2646 DBusMessage *reply;
2647 DBusMessageIter iter, reply_iter;
2648 dbus_bool_t value;
2649 DBusError _error;
2651 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2652 LIBHAL_CHECK_UDI_VALID(udi1, FALSE);
2653 LIBHAL_CHECK_UDI_VALID(udi2, FALSE);
2654 LIBHAL_CHECK_PARAM_VALID(property_namespace, "*property_namespace", FALSE);
2656 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2657 "/org/freedesktop/Hal/Manager",
2658 "org.freedesktop.Hal.Manager",
2659 "DeviceMatches");
2660 if (message == NULL) {
2661 fprintf (stderr,
2662 "%s %d : Couldn't allocate D-BUS message\n",
2663 __FILE__, __LINE__);
2664 return FALSE;
2667 dbus_message_iter_init_append (message, &iter);
2668 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi1);
2669 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi2);
2670 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, property_namespace);
2672 dbus_error_init (&_error);
2673 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2674 message, -1,
2675 &_error);
2677 dbus_message_unref (message);
2679 dbus_move_error (&_error, error);
2680 if (error != NULL && dbus_error_is_set (error)) {
2681 return FALSE;
2683 if (reply == NULL) {
2684 return FALSE;
2686 /* now analyse reply */
2687 dbus_message_iter_init (reply, &reply_iter);
2689 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
2690 fprintf (stderr,
2691 "%s %d : expected a bool in reply to DeviceMatches\n",
2692 __FILE__, __LINE__);
2693 dbus_message_unref (reply);
2694 return FALSE;
2697 dbus_message_iter_get_basic (&reply_iter, &value);
2699 dbus_message_unref (reply);
2700 return value;
2704 * libhal_device_print:
2705 * @ctx: the context for the connection to hald
2706 * @udi: the Unique Device Id
2707 * @error: pointer to an initialized dbus error object for returning errors or NULL
2709 * Print a device to stdout; useful for debugging.
2711 * Returns: TRUE if device's information could be obtained, FALSE otherwise
2713 dbus_bool_t
2714 libhal_device_print (LibHalContext *ctx, const char *udi, DBusError *error)
2716 int type;
2717 char *key;
2718 LibHalPropertySet *pset;
2719 LibHalPropertySetIterator i;
2721 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2722 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2724 printf ("device_id = %s\n", udi);
2726 if ((pset = libhal_device_get_all_properties (ctx, udi, error)) == NULL)
2727 return FALSE;
2729 for (libhal_psi_init (&i, pset); libhal_psi_has_more (&i);
2730 libhal_psi_next (&i)) {
2731 type = libhal_psi_get_type (&i);
2732 key = libhal_psi_get_key (&i);
2734 switch (type) {
2735 case LIBHAL_PROPERTY_TYPE_STRING:
2736 printf (" %s = '%s' (string)\n", key,
2737 libhal_psi_get_string (&i));
2738 break;
2739 case LIBHAL_PROPERTY_TYPE_INT32:
2740 printf (" %s = %d = 0x%x (int)\n", key,
2741 libhal_psi_get_int (&i),
2742 libhal_psi_get_int (&i));
2743 break;
2744 case LIBHAL_PROPERTY_TYPE_UINT64:
2745 printf (" %s = %llu = 0x%llx (uint64)\n", key,
2746 (long long unsigned int) libhal_psi_get_uint64 (&i),
2747 (long long unsigned int) libhal_psi_get_uint64 (&i));
2748 break;
2749 case LIBHAL_PROPERTY_TYPE_BOOLEAN:
2750 printf (" %s = %s (bool)\n", key,
2751 (libhal_psi_get_bool (&i) ? "true" :
2752 "false"));
2753 break;
2754 case LIBHAL_PROPERTY_TYPE_DOUBLE:
2755 printf (" %s = %g (double)\n", key,
2756 libhal_psi_get_double (&i));
2757 break;
2758 case LIBHAL_PROPERTY_TYPE_STRLIST:
2760 unsigned int j;
2761 char **str_list;
2763 str_list = libhal_psi_get_strlist (&i);
2764 printf (" %s = [", key);
2765 for (j = 0; str_list[j] != NULL; j++) {
2766 printf ("'%s'", str_list[j]);
2767 if (str_list[j+1] != NULL)
2768 printf (", ");
2770 printf ("] (string list)\n");
2772 break;
2774 default:
2775 printf (" *** unknown type for key %s\n", key);
2776 break;
2780 libhal_free_property_set (pset);
2782 return TRUE;
2786 * libhal_manager_find_device_string_match:
2787 * @ctx: the context for the connection to hald
2788 * @key: name of the property
2789 * @value: the value to match
2790 * @num_devices: pointer to store number of devices
2791 * @error: pointer to an initialized dbus error object for returning errors or NULL
2793 * Find a device in the GDL where a single string property matches a
2794 * given value.
2796 * Returns: UDI of devices; free with libhal_free_string_array()
2798 char **
2799 libhal_manager_find_device_string_match (LibHalContext *ctx,
2800 const char *key,
2801 const char *value, int *num_devices, DBusError *error)
2803 DBusMessage *message;
2804 DBusMessage *reply;
2805 DBusMessageIter iter, iter_array, reply_iter;
2806 char **hal_device_names;
2807 DBusError _error;
2809 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2810 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
2811 LIBHAL_CHECK_PARAM_VALID(value, "*value", NULL);
2813 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2814 "/org/freedesktop/Hal/Manager",
2815 "org.freedesktop.Hal.Manager",
2816 "FindDeviceStringMatch");
2817 if (message == NULL) {
2818 fprintf (stderr,
2819 "%s %d : Couldn't allocate D-BUS message\n",
2820 __FILE__, __LINE__);
2821 return NULL;
2824 dbus_message_iter_init_append (message, &iter);
2825 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2826 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
2828 dbus_error_init (&_error);
2829 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2830 message, -1,
2831 &_error);
2833 dbus_message_unref (message);
2835 dbus_move_error (&_error, error);
2836 if (error != NULL && dbus_error_is_set (error)) {
2837 return NULL;
2839 if (reply == NULL) {
2840 return NULL;
2842 /* now analyse reply */
2843 dbus_message_iter_init (reply, &reply_iter);
2845 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
2846 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
2847 return NULL;
2850 dbus_message_iter_recurse (&reply_iter, &iter_array);
2852 hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
2854 dbus_message_unref (reply);
2855 return hal_device_names;
2860 * libhal_device_add_capability:
2861 * @ctx: the context for the connection to hald
2862 * @udi: the Unique Device Id
2863 * @capability: the capability name to add
2864 * @error: pointer to an initialized dbus error object for returning errors or NULL
2866 * Assign a capability to a device.
2868 * Returns: TRUE if the capability was added, FALSE if the device didn't exist
2870 dbus_bool_t
2871 libhal_device_add_capability (LibHalContext *ctx,
2872 const char *udi, const char *capability, DBusError *error)
2874 DBusMessage *message;
2875 DBusMessage *reply;
2876 DBusMessageIter iter;
2878 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2879 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2880 LIBHAL_CHECK_PARAM_VALID(capability, "*capability", FALSE);
2882 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2883 "org.freedesktop.Hal.Device",
2884 "AddCapability");
2885 if (message == NULL) {
2886 fprintf (stderr,
2887 "%s %d : Couldn't allocate D-BUS message\n",
2888 __FILE__, __LINE__);
2889 return FALSE;
2892 dbus_message_iter_init_append (message, &iter);
2893 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
2896 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2897 message, -1,
2898 error);
2900 dbus_message_unref (message);
2902 if (error != NULL && dbus_error_is_set (error)) {
2903 return FALSE;
2905 if (reply == NULL) {
2906 return FALSE;
2909 dbus_message_unref (reply);
2910 return TRUE;
2914 * libhal_device_query_capability:
2915 * @ctx: the context for the connection to hald
2916 * @udi: the Unique Device Id
2917 * @capability: the capability name
2918 * @error: pointer to an initialized dbus error object for returning errors or NULL
2920 * Check if a device has a capability. The result is undefined if the
2921 * device doesn't exist.
2923 * Returns: TRUE if the device has the capability, otherwise FALSE
2925 dbus_bool_t
2926 libhal_device_query_capability (LibHalContext *ctx, const char *udi, const char *capability, DBusError *error)
2928 char **caps;
2929 unsigned int i;
2930 dbus_bool_t ret;
2932 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2933 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2934 LIBHAL_CHECK_PARAM_VALID(capability, "*capability", FALSE);
2936 ret = FALSE;
2938 caps = libhal_device_get_property_strlist (ctx, udi, "info.capabilities", error);
2939 if (caps != NULL) {
2940 for (i = 0; caps[i] != NULL; i++) {
2941 if (strcmp (caps[i], capability) == 0) {
2942 ret = TRUE;
2943 break;
2946 libhal_free_string_array (caps);
2949 return ret;
2953 * libhal_find_device_by_capability:
2954 * @ctx: the context for the connection to hald
2955 * @capability: the capability name
2956 * @num_devices: pointer to store number of devices
2957 * @error: pointer to an initialized dbus error object for returning errors or NULL
2959 * Find devices with a given capability.
2961 * Returns: UDI of devices; free with libhal_free_string_array()
2963 char **
2964 libhal_find_device_by_capability (LibHalContext *ctx,
2965 const char *capability, int *num_devices, DBusError *error)
2967 DBusMessage *message;
2968 DBusMessage *reply;
2969 DBusMessageIter iter, iter_array, reply_iter;
2970 char **hal_device_names;
2971 DBusError _error;
2973 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2974 LIBHAL_CHECK_PARAM_VALID(capability, "*capability", NULL);
2976 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2977 "/org/freedesktop/Hal/Manager",
2978 "org.freedesktop.Hal.Manager",
2979 "FindDeviceByCapability");
2980 if (message == NULL) {
2981 fprintf (stderr,
2982 "%s %d : Couldn't allocate D-BUS message\n",
2983 __FILE__, __LINE__);
2984 return NULL;
2987 dbus_message_iter_init_append (message, &iter);
2988 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
2990 dbus_error_init (&_error);
2991 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2992 message, -1,
2993 &_error);
2995 dbus_message_unref (message);
2997 dbus_move_error (&_error, error);
2998 if (error != NULL && dbus_error_is_set (error)) {
2999 return NULL;
3001 if (reply == NULL) {
3002 return NULL;
3004 /* now analyse reply */
3005 dbus_message_iter_init (reply, &reply_iter);
3007 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
3008 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
3009 return NULL;
3012 dbus_message_iter_recurse (&reply_iter, &iter_array);
3014 hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
3016 dbus_message_unref (reply);
3017 return hal_device_names;
3021 * libhal_device_property_watch_all:
3022 * @ctx: the context for the connection to hald
3023 * @error: pointer to an initialized dbus error object for returning errors or NULL
3025 * Watch all devices, ie. the device_property_changed callback is
3026 * invoked when the properties on any device changes.
3028 * Returns: TRUE only if the operation succeeded
3030 dbus_bool_t
3031 libhal_device_property_watch_all (LibHalContext *ctx, DBusError *error)
3033 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3035 dbus_bus_add_match (ctx->connection,
3036 "type='signal',"
3037 "interface='org.freedesktop.Hal.Device',"
3038 "sender='org.freedesktop.Hal'", error);
3039 if (error != NULL && dbus_error_is_set (error)) {
3040 return FALSE;
3042 return TRUE;
3047 * libhal_device_add_property_watch:
3048 * @ctx: the context for the connection to hald
3049 * @udi: the Unique Device Id
3050 * @error: pointer to an initialized dbus error object for returning errors or NULL
3052 * Add a watch on a device, so the device_property_changed callback is
3053 * invoked when the properties on the given device changes.
3055 * The application itself is responsible for deleting the watch, using
3056 * libhal_device_remove_property_watch, if the device is removed.
3058 * Returns: TRUE only if the operation succeeded
3060 dbus_bool_t
3061 libhal_device_add_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
3063 char buf[512];
3065 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3066 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3068 snprintf (buf, 512,
3069 "type='signal',"
3070 "interface='org.freedesktop.Hal.Device',"
3071 "sender='org.freedesktop.Hal'," "path=%s", udi);
3073 dbus_bus_add_match (ctx->connection, buf, error);
3074 if (error != NULL && dbus_error_is_set (error)) {
3075 return FALSE;
3077 return TRUE;
3082 * libhal_device_remove_property_watch:
3083 * @ctx: the context for the connection to hald
3084 * @udi: the Unique Device Id
3085 * @error: pointer to an initialized dbus error object for returning errors or NULL
3087 * Remove a watch on a device.
3089 * Returns: TRUE only if the operation succeeded
3091 dbus_bool_t
3092 libhal_device_remove_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
3094 char buf[512];
3096 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3097 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3099 snprintf (buf, 512,
3100 "type='signal',"
3101 "interface='org.freedesktop.Hal.Device',"
3102 "sender='org.freedesktop.Hal'," "path=%s", udi);
3104 dbus_bus_remove_match (ctx->connection, buf, error);
3105 if (error != NULL && dbus_error_is_set (error)) {
3106 return FALSE;
3108 return TRUE;
3113 * libhal_ctx_new:
3115 * Create a new LibHalContext
3117 * Returns: a new uninitialized LibHalContext object
3119 LibHalContext *
3120 libhal_ctx_new (void)
3122 LibHalContext *ctx;
3124 if (!libhal_already_initialized_once) {
3125 bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
3126 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
3128 libhal_already_initialized_once = TRUE;
3131 ctx = calloc (1, sizeof (LibHalContext));
3132 if (ctx == NULL) {
3133 fprintf (stderr,
3134 "%s %d : Failed to allocate %lu bytes\n",
3135 __FILE__, __LINE__, (unsigned long) sizeof (LibHalContext));
3136 return NULL;
3139 ctx->is_initialized = FALSE;
3140 ctx->is_shutdown = FALSE;
3141 ctx->connection = NULL;
3142 ctx->is_direct = FALSE;
3144 return ctx;
3148 * libhal_ctx_set_cache:
3149 * @ctx: context to enable/disable cache for
3150 * @use_cache: whether or not to use cache
3152 * Enable or disable caching. Note: Caching is not actually
3153 * implemented yet.
3155 * Returns: TRUE if cache was successfully enabled/disabled, FALSE otherwise
3157 dbus_bool_t
3158 libhal_ctx_set_cache (LibHalContext *ctx, dbus_bool_t use_cache)
3160 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3162 ctx->cache_enabled = use_cache;
3163 return TRUE;
3167 * libhal_ctx_set_dbus_connection:
3168 * @ctx: context to set connection for
3169 * @conn: DBus connection to use
3171 * Set DBus connection to use to talk to hald.
3173 * Returns: TRUE if connection was successfully set, FALSE otherwise
3175 dbus_bool_t
3176 libhal_ctx_set_dbus_connection (LibHalContext *ctx, DBusConnection *conn)
3178 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3180 if (conn == NULL)
3181 return FALSE;
3183 ctx->connection = conn;
3184 return TRUE;
3188 * libhal_ctx_get_dbus_connection:
3189 * @ctx: context to get connection for
3191 * Get DBus connection used for talking to hald.
3193 * Returns: DBus connection to use or NULL
3195 DBusConnection *
3196 libhal_ctx_get_dbus_connection (LibHalContext *ctx)
3198 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
3200 return ctx->connection;
3205 * libhal_ctx_init:
3206 * @ctx: Context for connection to hald (D-BUS connection should be set with libhal_ctx_set_dbus_connection)
3207 * @error: pointer to an initialized dbus error object for returning errors or NULL
3209 * Initialize the connection to hald.
3211 * Returns: TRUE if initialization succeeds, FALSE otherwise
3213 dbus_bool_t
3214 libhal_ctx_init (LibHalContext *ctx, DBusError *error)
3216 DBusError _error;
3217 dbus_bool_t hald_exists;
3219 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3221 if (ctx->connection == NULL)
3222 return FALSE;
3224 dbus_error_init (&_error);
3225 hald_exists = dbus_bus_name_has_owner (ctx->connection, "org.freedesktop.Hal", &_error);
3226 dbus_move_error (&_error, error);
3227 if (error != NULL && dbus_error_is_set (error)) {
3228 return FALSE;
3231 if (!hald_exists) {
3232 return FALSE;
3236 if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) {
3237 return FALSE;
3240 dbus_bus_add_match (ctx->connection,
3241 "type='signal',"
3242 "interface='org.freedesktop.Hal.Manager',"
3243 "sender='org.freedesktop.Hal',"
3244 "path='/org/freedesktop/Hal/Manager'", &_error);
3245 dbus_move_error (&_error, error);
3246 if (error != NULL && dbus_error_is_set (error)) {
3247 return FALSE;
3249 ctx->is_initialized = TRUE;
3250 ctx->is_direct = FALSE;
3252 return TRUE;
3256 * libhal_ctx_init_direct:
3257 * @error: pointer to an initialized dbus error object for returning errors or NULL
3259 * Create an already initialized connection to hald. This function should only be used by HAL helpers.
3261 * Returns: A pointer to an already initialized LibHalContext
3263 LibHalContext *
3264 libhal_ctx_init_direct (DBusError *error)
3266 char *hald_addr;
3267 LibHalContext *ctx;
3268 DBusError _error;
3270 ctx = libhal_ctx_new ();
3271 if (ctx == NULL)
3272 goto out;
3274 if (((hald_addr = getenv ("HALD_DIRECT_ADDR"))) == NULL) {
3275 libhal_ctx_free (ctx);
3276 ctx = NULL;
3277 goto out;
3280 dbus_error_init (&_error);
3281 ctx->connection = dbus_connection_open (hald_addr, &_error);
3282 dbus_move_error (&_error, error);
3283 if (error != NULL && dbus_error_is_set (error)) {
3284 libhal_ctx_free (ctx);
3285 ctx = NULL;
3286 goto out;
3289 ctx->is_initialized = TRUE;
3290 ctx->is_direct = TRUE;
3292 out:
3293 return ctx;
3297 * libhal_ctx_shutdown:
3298 * @ctx: the context for the connection to hald
3299 * @error: pointer to an initialized dbus error object for returning errors or NULL
3301 * Shut down a connection to hald.
3303 * Returns: TRUE if connection successfully shut down, FALSE otherwise
3305 dbus_bool_t
3306 libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error)
3308 DBusError myerror;
3310 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3312 if (ctx->is_direct) {
3313 /* for some reason dbus_connection_set_exit_on_disconnect doesn't work yet so don't unref */
3314 /*dbus_connection_unref (ctx->connection);*/
3315 } else {
3316 dbus_error_init (&myerror);
3317 dbus_bus_remove_match (ctx->connection,
3318 "type='signal',"
3319 "interface='org.freedesktop.Hal.Manager',"
3320 "sender='org.freedesktop.Hal',"
3321 "path='/org/freedesktop/Hal/Manager'", &myerror);
3322 dbus_move_error (&myerror, error);
3323 if (error != NULL && dbus_error_is_set (error)) {
3324 fprintf (stderr, "%s %d : Error unsubscribing to signals, error=%s\n",
3325 __FILE__, __LINE__, error->message);
3326 /** @todo clean up */
3329 /* TODO: remove other matches */
3331 dbus_connection_remove_filter (ctx->connection, filter_func, ctx);
3334 ctx->is_initialized = FALSE;
3336 return TRUE;
3340 * libhal_ctx_free:
3341 * @ctx: pointer to a LibHalContext
3343 * Free a LibHalContext resource.
3345 * Returns: TRUE
3347 dbus_bool_t
3348 libhal_ctx_free (LibHalContext *ctx)
3350 free (ctx);
3351 return TRUE;
3355 * libhal_ctx_set_device_added:
3356 * @ctx: the context for the connection to hald
3357 * @callback: the function to call when a device is added
3359 * Set the callback for when a device is added
3361 * Returns: TRUE if callback was successfully set, FALSE otherwise
3363 dbus_bool_t
3364 libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback)
3366 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3368 ctx->device_added = callback;
3369 return TRUE;
3373 * libhal_ctx_set_device_removed:
3374 * @ctx: the context for the connection to hald
3375 * @callback: the function to call when a device is removed
3377 * Set the callback for when a device is removed.
3379 * Returns: TRUE if callback was successfully set, FALSE otherwise
3381 dbus_bool_t
3382 libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback)
3384 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3386 ctx->device_removed = callback;
3387 return TRUE;
3391 * libhal_ctx_set_device_new_capability:
3392 * @ctx: the context for the connection to hald
3393 * @callback: the function to call when a device gains a new capability
3395 * Set the callback for when a device gains a new capability.
3397 * Returns: TRUE if callback was successfully set, FALSE otherwise
3399 dbus_bool_t
3400 libhal_ctx_set_device_new_capability (LibHalContext *ctx, LibHalDeviceNewCapability callback)
3402 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3404 ctx->device_new_capability = callback;
3405 return TRUE;
3409 * libhal_ctx_set_device_lost_capability:
3410 * @ctx: the context for the connection to hald
3411 * @callback: the function to call when a device loses a capability
3413 * Set the callback for when a device loses a capability
3415 * Returns: TRUE if callback was successfully set, FALSE otherwise
3417 dbus_bool_t
3418 libhal_ctx_set_device_lost_capability (LibHalContext *ctx, LibHalDeviceLostCapability callback)
3420 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3422 ctx->device_lost_capability = callback;
3423 return TRUE;
3427 * libhal_ctx_set_device_property_modified:
3428 * @ctx: the context for the connection to hald
3429 * @callback: the function to call when a property is modified on a device
3431 * Set the callback for when a property is modified on a device.
3433 * Returns: TRUE if callback was successfully set, FALSE otherwise
3435 dbus_bool_t
3436 libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibHalDevicePropertyModified callback)
3438 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3440 ctx->device_property_modified = callback;
3441 return TRUE;
3445 * libhal_ctx_set_device_condition:
3446 * @ctx: the context for the connection to hald
3447 * @callback: the function to call when a device emits a condition
3449 * Set the callback for when a device emits a condition
3451 * Returns: TRUE if callback was successfully set, FALSE otherwise
3453 dbus_bool_t
3454 libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback)
3456 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3458 ctx->device_condition = callback;
3459 return TRUE;
3463 * libhal_string_array_length:
3464 * @str_array: array of strings to consider
3466 * Get the length of an array of strings.
3468 * Returns: Number of strings in array
3470 unsigned int
3471 libhal_string_array_length (char **str_array)
3473 unsigned int i;
3475 if (str_array == NULL)
3476 return 0;
3478 for (i = 0; str_array[i] != NULL; i++)
3481 return i;
3486 * libhal_device_rescan:
3487 * @ctx: the context for the connection to hald
3488 * @udi: the Unique id of device
3489 * @error: pointer to an initialized dbus error object for returning errors or NULL
3491 * TODO document me.
3493 * Returns: Whether the operation succeeded
3495 dbus_bool_t
3496 libhal_device_rescan (LibHalContext *ctx, const char *udi, DBusError *error)
3498 DBusMessage *message;
3499 DBusMessageIter reply_iter;
3500 DBusMessage *reply;
3501 dbus_bool_t result;
3503 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3504 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3506 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
3507 "org.freedesktop.Hal.Device",
3508 "Rescan");
3510 if (message == NULL) {
3511 fprintf (stderr,
3512 "%s %d : Couldn't allocate D-BUS message\n",
3513 __FILE__, __LINE__);
3514 return FALSE;
3517 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3518 message, -1,
3519 error);
3521 dbus_message_unref (message);
3523 if (error != NULL && dbus_error_is_set (error)) {
3524 return FALSE;
3526 if (reply == NULL)
3527 return FALSE;
3529 dbus_message_iter_init (reply, &reply_iter);
3530 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3531 DBUS_TYPE_BOOLEAN) {
3532 dbus_message_unref (reply);
3533 return FALSE;
3535 dbus_message_iter_get_basic (&reply_iter, &result);
3537 dbus_message_unref (reply);
3539 return result;
3543 * libhal_device_reprobe:
3544 * @ctx: the context for the connection to hald
3545 * @udi: the Unique id of device
3546 * @error: pointer to an initialized dbus error object for returning errors or NULL
3548 * TODO document me.
3550 * Returns: Whether the operation succeeded
3552 dbus_bool_t
3553 libhal_device_reprobe (LibHalContext *ctx, const char *udi, DBusError *error)
3555 DBusMessage *message;
3556 DBusMessageIter reply_iter;
3557 DBusMessage *reply;
3558 dbus_bool_t result;
3560 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3561 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3563 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3564 udi,
3565 "org.freedesktop.Hal.Device",
3566 "Reprobe");
3568 if (message == NULL) {
3569 fprintf (stderr,
3570 "%s %d : Couldn't allocate D-BUS message\n",
3571 __FILE__, __LINE__);
3572 return FALSE;
3575 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3576 message, -1,
3577 error);
3579 dbus_message_unref (message);
3581 if (error != NULL && dbus_error_is_set (error)) {
3582 return FALSE;
3584 if (reply == NULL)
3585 return FALSE;
3587 dbus_message_iter_init (reply, &reply_iter);
3588 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3589 DBUS_TYPE_BOOLEAN) {
3590 dbus_message_unref (reply);
3591 return FALSE;
3593 dbus_message_iter_get_basic (&reply_iter, &result);
3595 dbus_message_unref (reply);
3597 return result;
3601 * libhal_device_emit_condition:
3602 * @ctx: the context for the connection to hald
3603 * @udi: the Unique Device Id
3604 * @condition_name: user-readable name of condition
3605 * @condition_details: user-readable details of condition
3606 * @error: pointer to an initialized dbus error object for returning errors or NULL
3608 * Emit a condition from a device. Can only be used from hald helpers.
3610 * Returns: TRUE if condition successfully emitted,
3611 * FALSE otherwise
3613 dbus_bool_t libhal_device_emit_condition (LibHalContext *ctx,
3614 const char *udi,
3615 const char *condition_name,
3616 const char *condition_details,
3617 DBusError *error)
3619 DBusMessage *message;
3620 DBusMessageIter iter;
3621 DBusMessageIter reply_iter;
3622 DBusMessage *reply;
3623 dbus_bool_t result;
3625 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3626 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3627 LIBHAL_CHECK_PARAM_VALID(condition_name, "*condition_name", FALSE);
3628 LIBHAL_CHECK_PARAM_VALID(condition_details, "*condition_details", FALSE);
3630 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3631 udi,
3632 "org.freedesktop.Hal.Device",
3633 "EmitCondition");
3635 if (message == NULL) {
3636 fprintf (stderr,
3637 "%s %d : Couldn't allocate D-BUS message\n",
3638 __FILE__, __LINE__);
3639 return FALSE;
3642 dbus_message_iter_init_append (message, &iter);
3643 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_name);
3644 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_details);
3646 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3647 message, -1,
3648 error);
3650 dbus_message_unref (message);
3652 if (error != NULL && dbus_error_is_set (error)) {
3653 fprintf (stderr,
3654 "%s %d : Failure sending D-BUS message: %s: %s\n",
3655 __FILE__, __LINE__, error->name, error->message);
3656 return FALSE;
3659 if (reply == NULL) {
3660 fprintf (stderr,
3661 "%s %d : Got no reply\n",
3662 __FILE__, __LINE__);
3663 return FALSE;
3666 dbus_message_iter_init (reply, &reply_iter);
3667 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3668 DBUS_TYPE_BOOLEAN) {
3669 dbus_message_unref (reply);
3670 fprintf (stderr,
3671 "%s %d : Malformed reply\n",
3672 __FILE__, __LINE__);
3673 return FALSE;
3675 dbus_message_iter_get_basic (&reply_iter, &result);
3677 dbus_message_unref (reply);
3679 return result;
3682 /**
3683 * libhal_device_addon_is_ready:
3684 * @ctx: the context for the connection to hald
3685 * @udi: the Unique Device Id this addon is handling
3686 * @error: pointer to an initialized dbus error object for returning errors or NULL
3688 * HAL addon's must call this method when they are done initializing the device object. The HAL
3689 * daemon will wait for all addon's to call this.
3691 * Can only be used from hald helpers.
3693 * Returns: TRUE if the HAL daemon received the message, FALSE otherwise
3695 dbus_bool_t
3696 libhal_device_addon_is_ready (LibHalContext *ctx, const char *udi, DBusError *error)
3698 DBusMessage *message;
3699 DBusMessageIter iter;
3700 DBusMessageIter reply_iter;
3701 DBusMessage *reply;
3702 dbus_bool_t result;
3704 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3705 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3707 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3708 udi,
3709 "org.freedesktop.Hal.Device",
3710 "AddonIsReady");
3712 if (message == NULL) {
3713 fprintf (stderr,
3714 "%s %d : Couldn't allocate D-BUS message\n",
3715 __FILE__, __LINE__);
3716 return FALSE;
3719 dbus_message_iter_init_append (message, &iter);
3721 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3722 message, -1,
3723 error);
3725 dbus_message_unref (message);
3727 if (error != NULL && dbus_error_is_set (error)) {
3728 return FALSE;
3730 if (reply == NULL)
3731 return FALSE;
3733 dbus_message_iter_init (reply, &reply_iter);
3734 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
3735 dbus_message_unref (reply);
3736 return FALSE;
3738 dbus_message_iter_get_basic (&reply_iter, &result);
3740 dbus_message_unref (reply);
3741 return result;
3745 * libhal_device_claim_interface:
3746 * @ctx: the context for the connection to hald
3747 * @udi: the Unique Device Id
3748 * @interface_name: Name of interface to claim, e.g. org.freedesktop.Hal.Device.FoobarKindOfThing
3749 * @introspection_xml: Introspection XML containing what would be inside the interface XML tag
3750 * @error: pointer to an initialized dbus error object for returning errors or NULL
3752 * Claim an interface for a device. All messages to this interface
3753 * will be forwarded to the helper. Can only be used from hald
3754 * helpers.
3756 * Returns: TRUE if interface was claimed, FALSE otherwise
3758 dbus_bool_t
3759 libhal_device_claim_interface (LibHalContext *ctx,
3760 const char *udi,
3761 const char *interface_name,
3762 const char *introspection_xml,
3763 DBusError *error)
3765 DBusMessage *message;
3766 DBusMessageIter iter;
3767 DBusMessageIter reply_iter;
3768 DBusMessage *reply;
3769 dbus_bool_t result;
3771 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3772 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3773 LIBHAL_CHECK_PARAM_VALID(interface_name, "*interface_name", FALSE);
3775 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3776 udi,
3777 "org.freedesktop.Hal.Device",
3778 "ClaimInterface");
3780 if (message == NULL) {
3781 fprintf (stderr,
3782 "%s %d : Couldn't allocate D-BUS message\n",
3783 __FILE__, __LINE__);
3784 return FALSE;
3787 dbus_message_iter_init_append (message, &iter);
3788 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name);
3789 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &introspection_xml);
3791 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3792 message, -1,
3793 error);
3795 dbus_message_unref (message);
3797 if (error != NULL && dbus_error_is_set (error)) {
3798 return FALSE;
3800 if (reply == NULL)
3801 return FALSE;
3803 dbus_message_iter_init (reply, &reply_iter);
3804 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3805 DBUS_TYPE_BOOLEAN) {
3806 dbus_message_unref (reply);
3807 return FALSE;
3809 dbus_message_iter_get_basic (&reply_iter, &result);
3811 dbus_message_unref (reply);
3813 return result;
3818 struct LibHalChangeSetElement_s;
3820 typedef struct LibHalChangeSetElement_s LibHalChangeSetElement;
3822 struct LibHalChangeSetElement_s {
3823 char *key;
3824 int change_type;
3825 union {
3826 char *val_str;
3827 dbus_int32_t val_int;
3828 dbus_uint64_t val_uint64;
3829 double val_double;
3830 dbus_bool_t val_bool;
3831 char **val_strlist;
3832 } value;
3833 LibHalChangeSetElement *next;
3834 LibHalChangeSetElement *prev;
3837 struct LibHalChangeSet_s {
3838 char *udi;
3839 LibHalChangeSetElement *head;
3840 LibHalChangeSetElement *tail;
3844 * libhal_device_new_changeset:
3845 * @udi: unique device identifier
3847 * Request a new changeset object. Used for changing multiple properties at once. Useful when
3848 * performance is critical and also for atomically updating several properties.
3850 * Returns: A new changeset object or NULL on error
3852 LibHalChangeSet *
3853 libhal_device_new_changeset (const char *udi)
3855 LibHalChangeSet *changeset;
3857 LIBHAL_CHECK_UDI_VALID(udi, NULL);
3859 changeset = calloc (1, sizeof (LibHalChangeSet));
3860 if (changeset == NULL)
3861 goto out;
3863 changeset->udi = strdup (udi);
3864 if (changeset->udi == NULL) {
3865 free (changeset);
3866 changeset = NULL;
3867 goto out;
3870 changeset->head = NULL;
3871 changeset->tail = NULL;
3873 out:
3874 return changeset;
3877 static void
3878 libhal_changeset_append (LibHalChangeSet *changeset, LibHalChangeSetElement *elem)
3880 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", );
3881 LIBHAL_CHECK_PARAM_VALID(elem, "*elem", );
3883 if (changeset->head == NULL) {
3884 changeset->head = elem;
3885 changeset->tail = elem;
3886 elem->next = NULL;
3887 elem->prev = NULL;
3888 } else {
3889 elem->prev = changeset->tail;
3890 elem->next = NULL;
3891 elem->prev->next = elem;
3892 changeset->tail = elem;
3898 * libhal_changeset_set_property_string:
3899 * @changeset: the changeset
3900 * @key: key of property
3901 * @value: the value to set
3903 * Set a property.
3905 * Returns: FALSE on OOM
3907 dbus_bool_t
3908 libhal_changeset_set_property_string (LibHalChangeSet *changeset, const char *key, const char *value)
3910 LibHalChangeSetElement *elem;
3912 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
3913 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
3914 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
3916 elem = calloc (1, sizeof (LibHalChangeSetElement));
3917 if (elem == NULL)
3918 goto out;
3919 elem->key = strdup (key);
3920 if (elem->key == NULL) {
3921 free (elem);
3922 elem = NULL;
3923 goto out;
3926 elem->change_type = LIBHAL_PROPERTY_TYPE_STRING;
3927 elem->value.val_str = strdup (value);
3928 if (elem->value.val_str == NULL) {
3929 free (elem->key);
3930 free (elem);
3931 elem = NULL;
3932 goto out;
3935 libhal_changeset_append (changeset, elem);
3936 out:
3937 return elem != NULL;
3941 * libhal_changeset_set_property_int:
3942 * @changeset: the changeset
3943 * @key: key of property
3944 * @value: the value to set
3946 * Set a property.
3948 * Returns: FALSE on OOM
3950 dbus_bool_t
3951 libhal_changeset_set_property_int (LibHalChangeSet *changeset, const char *key, dbus_int32_t value)
3953 LibHalChangeSetElement *elem;
3955 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
3956 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
3958 elem = calloc (1, sizeof (LibHalChangeSetElement));
3959 if (elem == NULL)
3960 goto out;
3961 elem->key = strdup (key);
3962 if (elem->key == NULL) {
3963 free (elem);
3964 elem = NULL;
3965 goto out;
3968 elem->change_type = LIBHAL_PROPERTY_TYPE_INT32;
3969 elem->value.val_int = value;
3971 libhal_changeset_append (changeset, elem);
3972 out:
3973 return elem != NULL;
3977 * libhal_changeset_set_property_uint64:
3978 * @changeset: the changeset
3979 * @key: key of property
3980 * @value: the value to set
3982 * Set a property.
3984 * Returns: FALSE on OOM
3986 dbus_bool_t
3987 libhal_changeset_set_property_uint64 (LibHalChangeSet *changeset, const char *key, dbus_uint64_t value)
3989 LibHalChangeSetElement *elem;
3991 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
3992 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
3994 elem = calloc (1, sizeof (LibHalChangeSetElement));
3995 if (elem == NULL)
3996 goto out;
3997 elem->key = strdup (key);
3998 if (elem->key == NULL) {
3999 free (elem);
4000 elem = NULL;
4001 goto out;
4004 elem->change_type = LIBHAL_PROPERTY_TYPE_UINT64;
4005 elem->value.val_uint64 = value;
4007 libhal_changeset_append (changeset, elem);
4008 out:
4009 return elem != NULL;
4013 * libhal_changeset_set_property_double:
4014 * @changeset: the changeset
4015 * @key: key of property
4016 * @value: the value to set
4018 * Set a property.
4020 * Returns: FALSE on OOM
4022 dbus_bool_t
4023 libhal_changeset_set_property_double (LibHalChangeSet *changeset, const char *key, double value)
4025 LibHalChangeSetElement *elem;
4027 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
4028 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
4030 elem = calloc (1, sizeof (LibHalChangeSetElement));
4031 if (elem == NULL)
4032 goto out;
4033 elem->key = strdup (key);
4034 if (elem->key == NULL) {
4035 free (elem);
4036 elem = NULL;
4037 goto out;
4040 elem->change_type = LIBHAL_PROPERTY_TYPE_DOUBLE;
4041 elem->value.val_double = value;
4043 libhal_changeset_append (changeset, elem);
4044 out:
4045 return elem != NULL;
4049 * libhal_changeset_set_property_bool:
4050 * @changeset: the changeset
4051 * @key: key of property
4052 * @value: the value to set
4054 * Set a property.
4056 * Returns: FALSE on OOM
4058 dbus_bool_t
4059 libhal_changeset_set_property_bool (LibHalChangeSet *changeset, const char *key, dbus_bool_t value)
4061 LibHalChangeSetElement *elem;
4063 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
4064 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
4066 elem = calloc (1, sizeof (LibHalChangeSetElement));
4067 if (elem == NULL)
4068 goto out;
4069 elem->key = strdup (key);
4070 if (elem->key == NULL) {
4071 free (elem);
4072 elem = NULL;
4073 goto out;
4076 elem->change_type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
4077 elem->value.val_bool = value;
4079 libhal_changeset_append (changeset, elem);
4080 out:
4081 return elem != NULL;
4085 * libhal_changeset_set_property_strlist:
4086 * @changeset: the changeset
4087 * @key: key of property
4088 * @value: the value to set - NULL terminated array of strings
4090 * Set a property.
4092 * Returns: FALSE on OOM
4094 dbus_bool_t
4095 libhal_changeset_set_property_strlist (LibHalChangeSet *changeset, const char *key, const char **value)
4097 LibHalChangeSetElement *elem;
4098 char **value_copy;
4099 int len;
4100 int i, j;
4102 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
4103 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
4105 elem = calloc (1, sizeof (LibHalChangeSetElement));
4106 if (elem == NULL)
4107 goto out;
4108 elem->key = strdup (key);
4109 if (elem->key == NULL) {
4110 free (elem);
4111 elem = NULL;
4112 goto out;
4115 for (i = 0; value[i] != NULL; i++)
4117 len = i;
4119 value_copy = calloc (len + 1, sizeof (char *));
4120 if (value_copy == NULL) {
4121 free (elem->key);
4122 free (elem);
4123 elem = NULL;
4124 goto out;
4127 for (i = 0; i < len; i++) {
4128 value_copy[i] = strdup (value[i]);
4129 if (value_copy[i] == NULL) {
4130 for (j = 0; j < i; j++) {
4131 free (value_copy[j]);
4133 free (value_copy);
4134 free (elem->key);
4135 free (elem);
4136 elem = NULL;
4137 goto out;
4140 value_copy[i] = NULL;
4142 elem->change_type = LIBHAL_PROPERTY_TYPE_STRLIST;
4143 elem->value.val_strlist = value_copy;
4145 libhal_changeset_append (changeset, elem);
4146 out:
4147 return elem != NULL;
4151 * libhal_device_commit_changeset:
4152 * @ctx: the context for the connection to hald
4153 * @changeset: the changeset to commit
4154 * @error: pointer to an initialized dbus error object for returning errors or NULL
4156 * Commit a changeset to the daemon.
4158 * Returns: True if the changeset was committed on the daemon side
4160 dbus_bool_t
4161 libhal_device_commit_changeset (LibHalContext *ctx, LibHalChangeSet *changeset, DBusError *error)
4163 LibHalChangeSetElement *elem;
4164 DBusMessage *message;
4165 DBusMessage *reply;
4166 DBusError _error;
4167 DBusMessageIter iter;
4168 DBusMessageIter sub;
4169 DBusMessageIter sub2;
4170 DBusMessageIter sub3;
4171 DBusMessageIter sub4;
4172 int i;
4174 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
4175 LIBHAL_CHECK_UDI_VALID(changeset->udi, FALSE);
4177 if (changeset->head == NULL) {
4178 return TRUE;
4181 message = dbus_message_new_method_call ("org.freedesktop.Hal", changeset->udi,
4182 "org.freedesktop.Hal.Device",
4183 "SetMultipleProperties");
4185 if (message == NULL) {
4186 fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
4187 return FALSE;
4190 dbus_message_iter_init_append (message, &iter);
4192 dbus_message_iter_open_container (&iter,
4193 DBUS_TYPE_ARRAY,
4194 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
4195 DBUS_TYPE_STRING_AS_STRING
4196 DBUS_TYPE_VARIANT_AS_STRING
4197 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
4198 &sub);
4200 for (elem = changeset->head; elem != NULL; elem = elem->next) {
4201 dbus_message_iter_open_container (&sub,
4202 DBUS_TYPE_DICT_ENTRY,
4203 NULL,
4204 &sub2);
4205 dbus_message_iter_append_basic (&sub2, DBUS_TYPE_STRING, &(elem->key));
4207 switch (elem->change_type) {
4208 case LIBHAL_PROPERTY_TYPE_STRING:
4209 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub3);
4210 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_STRING, &(elem->value.val_str));
4211 dbus_message_iter_close_container (&sub2, &sub3);
4212 break;
4213 case LIBHAL_PROPERTY_TYPE_STRLIST:
4214 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT,
4215 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, &sub3);
4216 dbus_message_iter_open_container (&sub3, DBUS_TYPE_ARRAY,
4217 DBUS_TYPE_STRING_AS_STRING, &sub4);
4218 for (i = 0; elem->value.val_strlist[i] != NULL; i++) {
4219 dbus_message_iter_append_basic (&sub4, DBUS_TYPE_STRING,
4220 &(elem->value.val_strlist[i]));
4222 dbus_message_iter_close_container (&sub3, &sub4);
4223 dbus_message_iter_close_container (&sub2, &sub3);
4224 break;
4225 case LIBHAL_PROPERTY_TYPE_INT32:
4226 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub3);
4227 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_INT32, &(elem->value.val_int));
4228 dbus_message_iter_close_container (&sub2, &sub3);
4229 break;
4230 case LIBHAL_PROPERTY_TYPE_UINT64:
4231 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_UINT64_AS_STRING, &sub3);
4232 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_UINT64, &(elem->value.val_uint64));
4233 dbus_message_iter_close_container (&sub2, &sub3);
4234 break;
4235 case LIBHAL_PROPERTY_TYPE_DOUBLE:
4236 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub3);
4237 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_DOUBLE, &(elem->value.val_double));
4238 dbus_message_iter_close_container (&sub2, &sub3);
4239 break;
4240 case LIBHAL_PROPERTY_TYPE_BOOLEAN:
4241 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING,&sub3);
4242 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_BOOLEAN, &(elem->value.val_bool));
4243 dbus_message_iter_close_container (&sub2, &sub3);
4244 break;
4245 default:
4246 fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
4247 break;
4249 dbus_message_iter_close_container (&sub, &sub2);
4252 dbus_message_iter_close_container (&iter, &sub);
4255 dbus_error_init (&_error);
4256 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
4257 message, -1,
4258 &_error);
4260 dbus_message_unref (message);
4262 dbus_move_error (&_error, error);
4263 if (error != NULL && dbus_error_is_set (error)) {
4264 fprintf (stderr,
4265 "%s %d : %s\n",
4266 __FILE__, __LINE__, error->message);
4268 return FALSE;
4270 if (reply == NULL) {
4271 return FALSE;
4274 dbus_message_unref (reply);
4275 return TRUE;
4279 * libhal_device_free_changeset:
4280 * @changeset: the changeset to free
4282 * Free a changeset.
4284 void
4285 libhal_device_free_changeset (LibHalChangeSet *changeset)
4287 LibHalChangeSetElement *elem;
4288 LibHalChangeSetElement *elem2;
4290 for (elem = changeset->head; elem != NULL; elem = elem2) {
4291 elem2 = elem->next;
4293 switch (elem->change_type) {
4294 case LIBHAL_PROPERTY_TYPE_STRING:
4295 free (elem->value.val_str);
4296 break;
4297 case LIBHAL_PROPERTY_TYPE_STRLIST:
4298 libhal_free_string_array (elem->value.val_strlist);
4299 break;
4300 /* explicit fallthrough */
4301 case LIBHAL_PROPERTY_TYPE_INT32:
4302 case LIBHAL_PROPERTY_TYPE_UINT64:
4303 case LIBHAL_PROPERTY_TYPE_DOUBLE:
4304 case LIBHAL_PROPERTY_TYPE_BOOLEAN:
4305 break;
4306 default:
4307 fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
4308 break;
4310 free (elem->key);
4311 free (elem);
4314 free (changeset->udi);
4315 free (changeset);