8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / hal / libhal / common / libhal.c
blobfa8765ef49b46d38fb585d341c6e14bc53c7c382
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 = realloc (buffer, sizeof (char *) * (count + 8));
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 = realloc (buffer, sizeof (char *) * (count + 1));
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 if (buffer != NULL)
189 free (buffer);
190 fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
191 return NULL;
196 * libhal_free_string:
197 * @str: the nul-terminated sting to free
199 * Used to free strings returned by libhal.
201 void
202 libhal_free_string (char *str)
204 if (str != NULL) {
205 free (str);
206 str = NULL;
212 * LibHalPropertySet:
214 * Represents a set of properties. Opaque; use the
215 * libhal_property_set_*() family of functions to access it.
217 struct LibHalPropertySet_s {
218 unsigned int num_properties; /**< Number of properties in set */
219 LibHalProperty *properties_head;
220 /**< Pointer to first property or NULL
221 * if there are no properties */
225 * LibHalProperty:
227 * Represents a property. Opaque.
229 struct LibHalProperty_s {
230 LibHalPropertyType type; /**< Type of property */
231 char *key; /**< ASCII string */
233 /** Possible values of the property */
234 union {
235 char *str_value; /**< UTF-8 zero-terminated string */
236 dbus_int32_t int_value;
237 /**< 32-bit signed integer */
238 dbus_uint64_t uint64_value;
239 /**< 64-bit unsigned integer */
240 double double_value; /**< IEEE754 double precision float */
241 dbus_bool_t bool_value;
242 /**< Truth value */
244 char **strlist_value; /**< List of UTF-8 zero-terminated strings */
245 } v;
247 LibHalProperty *next; /**< Next property or NULL if this is
248 * the last */
252 * LibHalContext:
254 * Context for connection to the HAL daemon. Opaque, use the
255 * libhal_ctx_*() family of functions to access it.
257 struct LibHalContext_s {
258 DBusConnection *connection; /**< D-BUS connection */
259 dbus_bool_t is_initialized; /**< Are we initialised */
260 dbus_bool_t is_shutdown; /**< Have we been shutdown */
261 dbus_bool_t cache_enabled; /**< Is the cache enabled */
262 dbus_bool_t is_direct; /**< Whether the connection to hald is direct */
264 /** Device added */
265 LibHalDeviceAdded device_added;
267 /** Device removed */
268 LibHalDeviceRemoved device_removed;
270 /** Device got a new capability */
271 LibHalDeviceNewCapability device_new_capability;
273 /** Device got a new capability */
274 LibHalDeviceLostCapability device_lost_capability;
276 /** A property of a device changed */
277 LibHalDevicePropertyModified device_property_modified;
279 /** A non-continous event on the device occured */
280 LibHalDeviceCondition device_condition;
282 void *user_data; /**< User data */
286 * libhal_ctx_set_user_data:
287 * @ctx: the context for the connection to hald
288 * @user_data: user data
290 * Set user data for the context.
292 * Returns: TRUE if user data was successfully set, FALSE if otherwise
294 dbus_bool_t
295 libhal_ctx_set_user_data(LibHalContext *ctx, void *user_data)
297 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
298 ctx->user_data = user_data;
299 return TRUE;
303 * libhal_ctx_get_user_data:
304 * @ctx: the context for the connection to hald
306 * Get user data for the context.
308 * Returns: opaque pointer stored through libhal_ctx_set_user_data() or NULL if not set.
310 void*
311 libhal_ctx_get_user_data(LibHalContext *ctx)
313 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
314 return ctx->user_data;
319 * libhal_property_fill_value_from_variant:
320 * @p: the property to fill in
321 * @var_iter: variant iterator to extract the value from
323 * Fills in the value for the LibHalProperty given a variant iterator.
325 * Returns: Whether the value was put in.
327 static dbus_bool_t
328 libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter)
330 DBusMessageIter iter_array;
332 LIBHAL_CHECK_PARAM_VALID(p, "LibHalProperty *p", FALSE);
333 LIBHAL_CHECK_PARAM_VALID(var_iter, "DBusMessageIter *var_iter", FALSE);
335 switch (p->type) {
336 case DBUS_TYPE_ARRAY:
337 if (dbus_message_iter_get_element_type (var_iter) != DBUS_TYPE_STRING)
338 return FALSE;
340 dbus_message_iter_recurse (var_iter, &iter_array);
341 p->v.strlist_value = libhal_get_string_array_from_iter (&iter_array, NULL);
343 p->type = LIBHAL_PROPERTY_TYPE_STRLIST;
345 break;
346 case DBUS_TYPE_STRING:
348 const char *v;
350 dbus_message_iter_get_basic (var_iter, &v);
352 p->v.str_value = strdup (v);
353 if (p->v.str_value == NULL)
354 return FALSE;
355 p->type = LIBHAL_PROPERTY_TYPE_STRING;
357 break;
359 case DBUS_TYPE_INT32:
361 dbus_int32_t v;
363 dbus_message_iter_get_basic (var_iter, &v);
365 p->v.int_value = v;
366 p->type = LIBHAL_PROPERTY_TYPE_INT32;
368 break;
370 case DBUS_TYPE_UINT64:
372 dbus_uint64_t v;
374 dbus_message_iter_get_basic (var_iter, &v);
376 p->v.uint64_value = v;
377 p->type = LIBHAL_PROPERTY_TYPE_UINT64;
379 break;
381 case DBUS_TYPE_DOUBLE:
383 double v;
385 dbus_message_iter_get_basic (var_iter, &v);
387 p->v.double_value = v;
388 p->type = LIBHAL_PROPERTY_TYPE_DOUBLE;
390 break;
392 case DBUS_TYPE_BOOLEAN:
394 double v;
396 dbus_message_iter_get_basic (var_iter, &v);
398 p->v.double_value = v;
399 p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
401 break;
403 default:
404 /** @todo report error */
405 break;
408 return TRUE;
412 * libhal_device_get_all_properties:
413 * @ctx: the context for the connection to hald
414 * @udi: the Unique id of device
415 * @error: pointer to an initialized dbus error object for returning errors or NULL
417 * Retrieve all the properties on a device.
419 * Returns: An object represent all properties. Must be freed with libhal_free_property_set().
421 LibHalPropertySet *
422 libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error)
424 DBusMessage *message;
425 DBusMessage *reply;
426 DBusMessageIter reply_iter;
427 DBusMessageIter dict_iter;
428 LibHalPropertySet *result;
429 LibHalProperty *p_last;
430 DBusError _error;
432 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
433 LIBHAL_CHECK_UDI_VALID(udi, NULL);
435 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
436 "org.freedesktop.Hal.Device",
437 "GetAllProperties");
439 if (message == NULL) {
440 fprintf (stderr,
441 "%s %d : Couldn't allocate D-BUS message\n",
442 __FILE__, __LINE__);
443 return NULL;
446 dbus_error_init (&_error);
447 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
448 message, -1,
449 &_error);
451 dbus_move_error (&_error, error);
452 if (error != NULL && dbus_error_is_set (error)) {
453 fprintf (stderr,
454 "%s %d : %s\n",
455 __FILE__, __LINE__, error->message);
457 dbus_message_unref (message);
458 return NULL;
461 if (reply == NULL) {
462 dbus_message_unref (message);
463 return NULL;
466 dbus_message_iter_init (reply, &reply_iter);
468 result = malloc (sizeof (LibHalPropertySet));
469 if (result == NULL)
470 goto oom;
473 result->properties = malloc(sizeof(LibHalProperty)*result->num_properties);
474 if( result->properties==NULL )
476 /// @todo cleanup
477 return NULL;
481 result->properties_head = NULL;
482 result->num_properties = 0;
484 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY &&
485 dbus_message_iter_get_element_type (&reply_iter) != DBUS_TYPE_DICT_ENTRY) {
486 fprintf (stderr, "%s %d : error, expecting an array of dict entries\n",
487 __FILE__, __LINE__);
488 dbus_message_unref (message);
489 dbus_message_unref (reply);
490 return NULL;
493 dbus_message_iter_recurse (&reply_iter, &dict_iter);
495 p_last = NULL;
497 while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
499 DBusMessageIter dict_entry_iter, var_iter;
500 const char *key;
501 LibHalProperty *p;
503 dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
505 dbus_message_iter_get_basic (&dict_entry_iter, &key);
507 p = malloc (sizeof (LibHalProperty));
508 if (p == NULL)
509 goto oom;
511 p->next = NULL;
513 if (result->num_properties == 0)
514 result->properties_head = p;
516 if (p_last != NULL)
517 p_last->next = p;
519 p_last = p;
521 p->key = strdup (key);
522 if (p->key == NULL)
523 goto oom;
525 dbus_message_iter_next (&dict_entry_iter);
527 dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
530 p->type = dbus_message_iter_get_arg_type (&var_iter);
532 result->num_properties++;
534 if(!libhal_property_fill_value_from_variant (p, &var_iter))
535 goto oom;
537 dbus_message_iter_next (&dict_iter);
540 dbus_message_unref (message);
541 dbus_message_unref (reply);
543 return result;
545 oom:
546 fprintf (stderr,
547 "%s %d : error allocating memory\n",
548 __FILE__, __LINE__);
549 /** @todo FIXME cleanup */
550 return NULL;
553 /**
554 * libhal_free_property_set:
555 * @set: property-set to free
557 * Free a property set earlier obtained with libhal_device_get_all_properties().
559 void
560 libhal_free_property_set (LibHalPropertySet * set)
562 LibHalProperty *p;
563 LibHalProperty *q;
565 if (set == NULL)
566 return;
568 for (p = set->properties_head; p != NULL; p = q) {
569 free (p->key);
570 if (p->type == DBUS_TYPE_STRING)
571 free (p->v.str_value);
572 if (p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
573 libhal_free_string_array (p->v.strlist_value);
574 q = p->next;
575 free (p);
577 free (set);
581 * libhal_property_set_get_num_elems:
582 * @set: property set to consider
584 * Get the number of properties in a property set.
586 * Returns: number of properties in given property set
588 unsigned int
589 libhal_property_set_get_num_elems (LibHalPropertySet *set)
591 unsigned int num_elems;
592 LibHalProperty *p;
594 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
596 num_elems = 0;
597 for (p = set->properties_head; p != NULL; p = p->next)
598 num_elems++;
600 return num_elems;
603 static LibHalProperty *
604 property_set_lookup (const LibHalPropertySet *set, const char *key)
606 LibHalProperty *p;
608 LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
609 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
611 for (p = set->properties_head; p != NULL; p = p->next)
612 if (strcmp (key, p->key) == 0)
613 return p;
615 return NULL;
619 * libhal_ps_get_type:
620 * @set: property set
621 * @key: name of property to inspect
623 * Get the type of a given property.
625 * Returns: the #LibHalPropertyType of the given property,
626 * LIBHAL_PROPERTY_TYPE_INVALID if property is not in the set
628 LibHalPropertyType
629 libhal_ps_get_type (const LibHalPropertySet *set, const char *key)
631 LibHalProperty *p;
633 LIBHAL_CHECK_PARAM_VALID(set, "*set", LIBHAL_PROPERTY_TYPE_INVALID);
634 LIBHAL_CHECK_PARAM_VALID(key, "*key", LIBHAL_PROPERTY_TYPE_INVALID);
636 p = property_set_lookup (set, key);
637 if (p) return p->type;
638 else return LIBHAL_PROPERTY_TYPE_INVALID;
642 * libhal_ps_get_string:
643 * @set: property set
644 * @key: name of property to inspect
646 * Get the value of a property of type string.
648 * Returns: UTF8 nul-terminated string. This pointer is only valid
649 * until libhal_free_property_set() is invoked on the property set
650 * this property belongs to. NULL if property is not in the set or not a string
652 const char *
653 libhal_ps_get_string (const LibHalPropertySet *set, const char *key)
655 LibHalProperty *p;
657 LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
658 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
660 p = property_set_lookup (set, key);
661 if (p && p->type == LIBHAL_PROPERTY_TYPE_STRING)
662 return p->v.str_value;
663 else return NULL;
667 * libhal_ps_get_int:
668 * @set: property set
669 * @key: name of property to inspect
671 * Get the value of a property of type signed integer.
673 * Returns: property value (32-bit signed integer)
675 dbus_int32_t
676 libhal_ps_get_int32 (const LibHalPropertySet *set, const char *key)
678 LibHalProperty *p;
680 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
681 LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
683 p = property_set_lookup (set, key);
684 if (p && p->type == LIBHAL_PROPERTY_TYPE_INT32)
685 return p->v.int_value;
686 else return 0;
690 * libhal_ps_get_uint64:
691 * @set: property set
692 * @key: name of property to inspect
694 * Get the value of a property of type unsigned integer.
696 * Returns: property value (64-bit unsigned integer)
698 dbus_uint64_t
699 libhal_ps_get_uint64 (const LibHalPropertySet *set, const char *key)
701 LibHalProperty *p;
703 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
704 LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
706 p = property_set_lookup (set, key);
707 if (p && p->type == LIBHAL_PROPERTY_TYPE_UINT64)
708 return p->v.uint64_value;
709 else return 0;
713 * libhal_ps_get_double:
714 * @set: property set
715 * @key: name of property to inspect
717 * Get the value of a property of type double.
719 * Returns: property value (IEEE754 double precision float)
721 double
722 libhal_ps_get_double (const LibHalPropertySet *set, const char *key)
724 LibHalProperty *p;
726 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0.0);
727 LIBHAL_CHECK_PARAM_VALID(key, "*key", 0.0);
729 p = property_set_lookup (set, key);
730 if (p && p->type == LIBHAL_PROPERTY_TYPE_DOUBLE)
731 return p->v.double_value;
732 else return 0.0;
736 * libhal_ps_get_bool:
737 * @set: property set
738 * @key: name of property to inspect
740 * Get the value of a property of type bool.
742 * Returns: property value (bool)
744 dbus_bool_t
745 libhal_ps_get_bool (const LibHalPropertySet *set, const char *key)
747 LibHalProperty *p;
749 LIBHAL_CHECK_PARAM_VALID(set, "*set", FALSE);
750 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
752 p = property_set_lookup (set, key);
753 if (p && p->type == LIBHAL_PROPERTY_TYPE_BOOLEAN)
754 return p->v.bool_value;
755 else return FALSE;
759 * libhal_ps_get_strlist:
760 * @set: property set
761 * @key: name of property to inspect
763 * Get the value of a property of type string list.
765 * Returns: pointer to array of strings, this is owned by the property set
767 const char *const *
768 libhal_ps_get_strlist (const LibHalPropertySet *set, const char *key)
770 LibHalProperty *p;
772 LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
773 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
775 p = property_set_lookup (set, key);
776 if (p && p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
777 return (const char *const *) p->v.strlist_value;
778 else return NULL;
783 * libhal_psi_init:
784 * @iter: iterator object
785 * @set: property set to iterate over
787 * Initialize a property set iterator.
790 void
791 libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
793 if (set == NULL)
794 return;
796 iter->set = set;
797 iter->idx = 0;
798 iter->cur_prop = set->properties_head;
803 * libhal_psi_has_more:
804 * @iter: iterator object
806 * Determine whether there are more properties to iterate over.
808 * Returns: TRUE if there are more properties, FALSE otherwise.
810 dbus_bool_t
811 libhal_psi_has_more (LibHalPropertySetIterator * iter)
813 return iter->idx < iter->set->num_properties;
817 * libhal_psi_next:
818 * @iter: iterator object
820 * Advance iterator to next property.
822 void
823 libhal_psi_next (LibHalPropertySetIterator * iter)
825 iter->idx++;
826 iter->cur_prop = iter->cur_prop->next;
830 * libhal_psi_get_type:
831 * @iter: iterator object
833 * Get type of property.
835 * Returns: the property type at the iterator's position
837 LibHalPropertyType
838 libhal_psi_get_type (LibHalPropertySetIterator * iter)
840 return iter->cur_prop->type;
844 * libhal_psi_get_key:
845 * @iter: iterator object
847 * Get the key of a property.
849 * Returns: ASCII nul-terminated string. This pointer is only valid
850 * until libhal_free_property_set() is invoked on the property set
851 * this property belongs to.
853 char *
854 libhal_psi_get_key (LibHalPropertySetIterator * iter)
856 return iter->cur_prop->key;
860 * libhal_psi_get_string:
861 * @iter: iterator object
863 * Get the value of a property of type string.
865 * Returns: UTF8 nul-terminated string. This pointer is only valid
866 * until libhal_free_property_set() is invoked on the property set
867 * this property belongs to.
869 char *
870 libhal_psi_get_string (LibHalPropertySetIterator * iter)
872 return iter->cur_prop->v.str_value;
876 * libhal_psi_get_int:
877 * @iter: iterator object
879 * Get the value of a property of type signed integer.
881 * Returns: property value (32-bit signed integer)
883 dbus_int32_t
884 libhal_psi_get_int (LibHalPropertySetIterator * iter)
886 return iter->cur_prop->v.int_value;
890 * libhal_psi_get_uint64:
891 * @iter: iterator object
893 * Get the value of a property of type unsigned integer.
895 * Returns: property value (64-bit unsigned integer)
897 dbus_uint64_t
898 libhal_psi_get_uint64 (LibHalPropertySetIterator * iter)
900 return iter->cur_prop->v.uint64_value;
904 * libhal_psi_get_double:
905 * @iter: iterator object
907 * Get the value of a property of type double.
909 * Returns: property value (IEEE754 double precision float)
911 double
912 libhal_psi_get_double (LibHalPropertySetIterator * iter)
914 return iter->cur_prop->v.double_value;
918 * libhal_psi_get_bool:
919 * @iter: iterator object
921 * Get the value of a property of type bool.
923 * Returns: property value (bool)
925 dbus_bool_t
926 libhal_psi_get_bool (LibHalPropertySetIterator * iter)
928 return iter->cur_prop->v.bool_value;
932 * libhal_psi_get_strlist:
933 * @iter: iterator object
935 * Get the value of a property of type string list.
937 * Returns: pointer to array of strings
939 char **
940 libhal_psi_get_strlist (LibHalPropertySetIterator * iter)
942 return iter->cur_prop->v.strlist_value;
946 static DBusHandlerResult
947 filter_func (DBusConnection * connection,
948 DBusMessage * message, void *user_data)
950 const char *object_path;
951 DBusError error;
952 LibHalContext *ctx = (LibHalContext *) user_data;
954 if (ctx->is_shutdown)
955 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
957 dbus_error_init (&error);
959 object_path = dbus_message_get_path (message);
961 /*fprintf (stderr, "*** libhal filer_func: connection=%p obj_path=%s interface=%s method=%s\n",
962 connection,
963 dbus_message_get_path (message),
964 dbus_message_get_interface (message),
965 dbus_message_get_member (message));
968 if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager",
969 "DeviceAdded")) {
970 char *udi;
971 if (dbus_message_get_args (message, &error,
972 DBUS_TYPE_STRING, &udi,
973 DBUS_TYPE_INVALID)) {
974 if (ctx->device_added != NULL) {
975 ctx->device_added (ctx, udi);
977 } else {
978 LIBHAL_FREE_DBUS_ERROR(&error);
980 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
981 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
982 char *udi;
983 if (dbus_message_get_args (message, &error,
984 DBUS_TYPE_STRING, &udi,
985 DBUS_TYPE_INVALID)) {
986 if (ctx->device_removed != NULL) {
987 ctx->device_removed (ctx, udi);
989 } else {
990 LIBHAL_FREE_DBUS_ERROR(&error);
992 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
993 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","NewCapability")) {
994 char *udi;
995 char *capability;
996 if (dbus_message_get_args (message, &error,
997 DBUS_TYPE_STRING, &udi,
998 DBUS_TYPE_STRING, &capability,
999 DBUS_TYPE_INVALID)) {
1000 if (ctx->device_new_capability != NULL) {
1001 ctx->device_new_capability (ctx, udi, capability);
1003 } else {
1004 LIBHAL_FREE_DBUS_ERROR(&error);
1006 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1007 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) {
1008 char *condition_name;
1009 char *condition_detail;
1010 if (dbus_message_get_args (message, &error,
1011 DBUS_TYPE_STRING, &condition_name,
1012 DBUS_TYPE_STRING, &condition_detail,
1013 DBUS_TYPE_INVALID)) {
1014 if (ctx->device_condition != NULL) {
1015 ctx->device_condition (ctx, object_path, condition_name, condition_detail);
1017 } else {
1018 LIBHAL_FREE_DBUS_ERROR(&error);
1020 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1021 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) {
1022 if (ctx->device_property_modified != NULL) {
1023 int i;
1024 char *key;
1025 dbus_bool_t removed;
1026 dbus_bool_t added;
1027 int num_modifications;
1028 DBusMessageIter iter;
1029 DBusMessageIter iter_array;
1031 dbus_message_iter_init (message, &iter);
1032 dbus_message_iter_get_basic (&iter, &num_modifications);
1033 dbus_message_iter_next (&iter);
1035 dbus_message_iter_recurse (&iter, &iter_array);
1037 for (i = 0; i < num_modifications; i++) {
1038 DBusMessageIter iter_struct;
1040 dbus_message_iter_recurse (&iter_array, &iter_struct);
1042 dbus_message_iter_get_basic (&iter_struct, &key);
1043 dbus_message_iter_next (&iter_struct);
1044 dbus_message_iter_get_basic (&iter_struct, &removed);
1045 dbus_message_iter_next (&iter_struct);
1046 dbus_message_iter_get_basic (&iter_struct, &added);
1048 ctx->device_property_modified (ctx,
1049 object_path,
1050 key, removed,
1051 added);
1053 dbus_message_iter_next (&iter_array);
1057 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1060 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1063 /* for i18n purposes */
1064 static dbus_bool_t libhal_already_initialized_once = FALSE;
1068 * libhal_get_all_devices:
1069 * @ctx: the context for the connection to hald
1070 * @num_devices: the number of devices will be stored here
1071 * @error: pointer to an initialized dbus error object for returning errors or NULL
1073 * Get all devices in the Global Device List (GDL).
1075 * Returns: An array of device identifiers terminated with NULL. It is
1076 * the responsibility of the caller to free with
1077 * libhal_free_string_array(). If an error occurs NULL is returned.
1079 char **
1080 libhal_get_all_devices (LibHalContext *ctx, int *num_devices, DBusError *error)
1082 DBusMessage *message;
1083 DBusMessage *reply;
1084 DBusMessageIter iter_array, reply_iter;
1085 char **hal_device_names;
1086 DBusError _error;
1088 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
1090 *num_devices = 0;
1092 message = dbus_message_new_method_call ("org.freedesktop.Hal",
1093 "/org/freedesktop/Hal/Manager",
1094 "org.freedesktop.Hal.Manager",
1095 "GetAllDevices");
1096 if (message == NULL) {
1097 fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__);
1098 return NULL;
1101 dbus_error_init (&_error);
1102 reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error);
1104 dbus_message_unref (message);
1106 dbus_move_error (&_error, error);
1107 if (error != NULL && dbus_error_is_set (error)) {
1108 return NULL;
1110 if (reply == NULL) {
1111 return NULL;
1114 /* now analyze reply */
1115 dbus_message_iter_init (reply, &reply_iter);
1117 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
1118 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
1119 dbus_message_unref (reply);
1120 return NULL;
1123 dbus_message_iter_recurse (&reply_iter, &iter_array);
1125 hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
1127 dbus_message_unref (reply);
1128 return hal_device_names;
1132 * libhal_device_get_property_type:
1133 * @ctx: the context for the connection to hald
1134 * @udi: the Unique Device Id
1135 * @key: name of the property
1136 * @error: pointer to an initialized dbus error object for returning errors or NULL
1138 * Query a property type of a device.
1140 * Returns: A LibHalPropertyType. LIBHAL_PROPERTY_TYPE_INVALID is
1141 * return if the property doesn't exist.
1143 LibHalPropertyType
1144 libhal_device_get_property_type (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
1146 DBusMessage *message;
1147 DBusMessage *reply;
1148 DBusMessageIter iter, reply_iter;
1149 LibHalPropertyType type;
1150 DBusError _error;
1152 LIBHAL_CHECK_LIBHALCONTEXT(ctx, LIBHAL_PROPERTY_TYPE_INVALID); /* or return NULL? */
1153 LIBHAL_CHECK_UDI_VALID(udi, LIBHAL_PROPERTY_TYPE_INVALID);
1154 LIBHAL_CHECK_PARAM_VALID(key, "*key", LIBHAL_PROPERTY_TYPE_INVALID);
1156 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1157 "org.freedesktop.Hal.Device",
1158 "GetPropertyType");
1159 if (message == NULL) {
1160 fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
1161 return LIBHAL_PROPERTY_TYPE_INVALID;
1164 dbus_message_iter_init_append (message, &iter);
1165 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1167 dbus_error_init (&_error);
1168 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1169 message, -1,
1170 &_error);
1172 dbus_message_unref (message);
1174 dbus_move_error (&_error, error);
1175 if (error != NULL && dbus_error_is_set (error)) {
1176 return LIBHAL_PROPERTY_TYPE_INVALID;
1178 if (reply == NULL) {
1179 return LIBHAL_PROPERTY_TYPE_INVALID;
1182 dbus_message_iter_init (reply, &reply_iter);
1183 dbus_message_iter_get_basic (&reply_iter, &type);
1185 dbus_message_unref (reply);
1186 return type;
1190 * libhal_device_get_property_strlist:
1191 * @ctx: the context for the connection to hald
1192 * @udi: unique Device Id
1193 * @key: name of the property
1194 * @error: pointer to an initialized dbus error object for returning errors or NULL
1196 * Get the value of a property of type string list.
1198 * Returns: Array of pointers to UTF8 nul-terminated strings
1199 * terminated by NULL. The caller is responsible for freeing this
1200 * string array with the function libhal_free_string_array(). Returns
1201 * NULL if the property didn't exist or we are OOM
1203 char **
1204 libhal_device_get_property_strlist (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
1206 DBusMessage *message;
1207 DBusMessage *reply;
1208 DBusMessageIter iter, iter_array, reply_iter;
1209 char **our_strings;
1210 DBusError _error;
1212 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
1213 LIBHAL_CHECK_UDI_VALID(udi, NULL);
1214 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
1216 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1217 "org.freedesktop.Hal.Device",
1218 "GetPropertyStringList");
1219 if (message == NULL) {
1220 fprintf (stderr,
1221 "%s %d : Couldn't allocate D-BUS message\n",
1222 __FILE__, __LINE__);
1223 return NULL;
1226 dbus_message_iter_init_append (message, &iter);
1227 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1229 dbus_error_init (&_error);
1230 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1231 message, -1,
1232 &_error);
1234 dbus_message_unref (message);
1236 dbus_move_error (&_error, error);
1237 if (error != NULL && dbus_error_is_set (error)) {
1238 return NULL;
1240 if (reply == NULL) {
1241 return NULL;
1243 /* now analyse reply */
1244 dbus_message_iter_init (reply, &reply_iter);
1246 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
1247 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
1248 dbus_message_unref (reply);
1249 return NULL;
1252 dbus_message_iter_recurse (&reply_iter, &iter_array);
1254 our_strings = libhal_get_string_array_from_iter (&iter_array, NULL);
1256 dbus_message_unref (reply);
1257 return our_strings;
1261 * libhal_device_get_property_string:
1262 * @ctx: the context for the connection to hald
1263 * @udi: the Unique Device Id
1264 * @key: the name of the property
1265 * @error: pointer to an initialized dbus error object for returning errors or NULL
1267 * Get the value of a property of type string.
1269 * Returns: UTF8 nul-terminated string. The caller is responsible for
1270 * freeing this string with the function libhal_free_string(). Returns
1271 * NULL if the property didn't exist or we are OOM.
1273 char *
1274 libhal_device_get_property_string (LibHalContext *ctx,
1275 const char *udi, const char *key, DBusError *error)
1277 DBusMessage *message;
1278 DBusMessage *reply;
1279 DBusMessageIter iter, reply_iter;
1280 char *value;
1281 char *dbus_str;
1282 DBusError _error;
1284 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
1285 LIBHAL_CHECK_UDI_VALID(udi, NULL);
1286 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
1288 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1289 "org.freedesktop.Hal.Device",
1290 "GetPropertyString");
1292 if (message == NULL) {
1293 fprintf (stderr,
1294 "%s %d : Couldn't allocate D-BUS message\n",
1295 __FILE__, __LINE__);
1296 return NULL;
1299 dbus_message_iter_init_append (message, &iter);
1300 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1302 dbus_error_init (&_error);
1303 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1304 message, -1,
1305 &_error);
1307 dbus_message_unref (message);
1309 dbus_move_error (&_error, error);
1310 if (error != NULL && dbus_error_is_set (error)) {
1311 return NULL;
1313 if (reply == NULL) {
1314 return NULL;
1317 dbus_message_iter_init (reply, &reply_iter);
1319 /* now analyze reply */
1320 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1321 DBUS_TYPE_STRING) {
1322 dbus_message_unref (reply);
1323 return NULL;
1326 dbus_message_iter_get_basic (&reply_iter, &dbus_str);
1327 value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
1328 if (value == NULL) {
1329 fprintf (stderr, "%s %d : error allocating memory\n",
1330 __FILE__, __LINE__);
1333 dbus_message_unref (reply);
1334 return value;
1338 * libhal_device_get_property_int:
1339 * @ctx: the context for the connection to hald
1340 * @udi: the Unique Device Id
1341 * @key: name of the property
1342 * @error: pointer to an initialized dbus error object for returning errors or NULL
1344 * Get the value of a property of type integer.
1346 * Returns: Property value (32-bit signed integer)
1348 dbus_int32_t
1349 libhal_device_get_property_int (LibHalContext *ctx,
1350 const char *udi, const char *key, DBusError *error)
1352 DBusMessage *message;
1353 DBusMessage *reply;
1354 DBusMessageIter iter, reply_iter;
1355 dbus_int32_t value;
1356 DBusError _error;
1358 LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
1359 LIBHAL_CHECK_UDI_VALID(udi, -1);
1360 LIBHAL_CHECK_PARAM_VALID(key, "*key", -1);
1362 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1363 "org.freedesktop.Hal.Device",
1364 "GetPropertyInteger");
1365 if (message == NULL) {
1366 fprintf (stderr,
1367 "%s %d : Couldn't allocate D-BUS message\n",
1368 __FILE__, __LINE__);
1369 return -1;
1372 dbus_message_iter_init_append (message, &iter);
1373 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1375 dbus_error_init (&_error);
1376 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1377 message, -1,
1378 &_error);
1380 dbus_message_unref (message);
1382 dbus_move_error (&_error, error);
1383 if (error != NULL && dbus_error_is_set (error)) {
1384 return -1;
1386 if (reply == NULL) {
1387 return -1;
1390 dbus_message_iter_init (reply, &reply_iter);
1392 /* now analyze reply */
1393 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1394 DBUS_TYPE_INT32) {
1395 fprintf (stderr,
1396 "%s %d : property '%s' for device '%s' is not "
1397 "of type integer\n", __FILE__, __LINE__, key,
1398 udi);
1399 dbus_message_unref (reply);
1400 return -1;
1402 dbus_message_iter_get_basic (&reply_iter, &value);
1404 dbus_message_unref (reply);
1405 return value;
1409 * libhal_device_get_property_uint64:
1410 * @ctx: the context for the connection to hald
1411 * @udi: the Unique Device Id
1412 * @key: name of the property
1413 * @error: pointer to an initialized dbus error object for returning errors or NULL
1415 * Get the value of a property of type signed integer.
1417 * Returns: Property value (64-bit unsigned integer)
1419 dbus_uint64_t
1420 libhal_device_get_property_uint64 (LibHalContext *ctx,
1421 const char *udi, const char *key, DBusError *error)
1423 DBusMessage *message;
1424 DBusMessage *reply;
1425 DBusMessageIter iter, reply_iter;
1426 dbus_uint64_t value;
1427 DBusError _error;
1429 LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
1430 LIBHAL_CHECK_UDI_VALID(udi, -1);
1431 LIBHAL_CHECK_PARAM_VALID(key, "*key", -1);
1433 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1434 "org.freedesktop.Hal.Device",
1435 "GetPropertyInteger");
1436 if (message == NULL) {
1437 fprintf (stderr,
1438 "%s %d : Couldn't allocate D-BUS message\n",
1439 __FILE__, __LINE__);
1440 return -1;
1443 dbus_message_iter_init_append (message, &iter);
1444 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1446 dbus_error_init (&_error);
1447 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1448 message, -1,
1449 &_error);
1451 dbus_message_unref (message);
1453 dbus_move_error (&_error, error);
1454 if (error != NULL && dbus_error_is_set (error)) {
1455 return -1;
1457 if (reply == NULL) {
1458 return -1;
1461 dbus_message_iter_init (reply, &reply_iter);
1462 /* now analyze reply */
1463 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1464 DBUS_TYPE_UINT64) {
1465 fprintf (stderr,
1466 "%s %d : property '%s' for device '%s' is not "
1467 "of type integer\n", __FILE__, __LINE__, key,
1468 udi);
1469 dbus_message_unref (reply);
1470 return -1;
1472 dbus_message_iter_get_basic (&reply_iter, &value);
1474 dbus_message_unref (reply);
1475 return value;
1479 * libhal_device_get_property_double:
1480 * @ctx: the context for the connection to hald
1481 * @udi: the Unique Device Id
1482 * @key: name of the property
1483 * @error: pointer to an initialized dbus error object for returning errors or NULL
1485 * Get the value of a property of type double.
1487 * Returns: Property value (IEEE754 double precision float)
1489 double
1490 libhal_device_get_property_double (LibHalContext *ctx,
1491 const char *udi, const char *key, DBusError *error)
1493 DBusMessage *message;
1494 DBusMessage *reply;
1495 DBusMessageIter iter, reply_iter;
1496 double value;
1497 DBusError _error;
1499 LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1.0);
1500 LIBHAL_CHECK_UDI_VALID(udi, -1.0);
1501 LIBHAL_CHECK_PARAM_VALID(key, "*key", -1.0);
1503 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1504 "org.freedesktop.Hal.Device",
1505 "GetPropertyDouble");
1506 if (message == NULL) {
1507 fprintf (stderr,
1508 "%s %d : Couldn't allocate D-BUS message\n",
1509 __FILE__, __LINE__);
1510 return -1.0f;
1513 dbus_message_iter_init_append (message, &iter);
1514 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1516 dbus_error_init (&_error);
1517 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1518 message, -1,
1519 &_error);
1521 dbus_message_unref (message);
1523 dbus_move_error (&_error, error);
1524 if (error != NULL && dbus_error_is_set (error)) {
1525 return -1.0f;
1527 if (reply == NULL) {
1528 return -1.0f;
1531 dbus_message_iter_init (reply, &reply_iter);
1533 /* now analyze reply */
1534 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1535 DBUS_TYPE_DOUBLE) {
1536 fprintf (stderr,
1537 "%s %d : property '%s' for device '%s' is not "
1538 "of type double\n", __FILE__, __LINE__, key, udi);
1539 dbus_message_unref (reply);
1540 return -1.0f;
1542 dbus_message_iter_get_basic (&reply_iter, &value);
1544 dbus_message_unref (reply);
1545 return (double) value;
1549 * libhal_device_get_property_bool:
1550 * @ctx: the context for the connection to hald
1551 * @udi: the Unique Device Id
1552 * @key: name of the property
1553 * @error: pointer to an initialized dbus error object for returning errors or NULL
1555 * Get the value of a property of type bool.
1557 * Returns: Property value (boolean)
1559 dbus_bool_t
1560 libhal_device_get_property_bool (LibHalContext *ctx,
1561 const char *udi, const char *key, DBusError *error)
1563 DBusMessage *message;
1564 DBusMessage *reply;
1565 DBusMessageIter iter, reply_iter;
1566 dbus_bool_t value;
1567 DBusError _error;
1569 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1570 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1571 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1573 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1574 "org.freedesktop.Hal.Device",
1575 "GetPropertyBoolean");
1576 if (message == NULL) {
1577 fprintf (stderr,
1578 "%s %d : Couldn't allocate D-BUS message\n",
1579 __FILE__, __LINE__);
1580 return FALSE;
1583 dbus_message_iter_init_append (message, &iter);
1584 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1586 dbus_error_init (&_error);
1587 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1588 message, -1,
1589 &_error);
1591 dbus_message_unref (message);
1593 dbus_move_error (&_error, error);
1594 if (error != NULL && dbus_error_is_set (error)) {
1595 return FALSE;
1597 if (reply == NULL) {
1598 return FALSE;
1601 dbus_message_iter_init (reply, &reply_iter);
1603 /* now analyze reply */
1604 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1605 DBUS_TYPE_BOOLEAN) {
1606 fprintf (stderr,
1607 "%s %d : property '%s' for device '%s' is not "
1608 "of type bool\n", __FILE__, __LINE__, key, udi);
1609 dbus_message_unref (reply);
1610 return FALSE;
1612 dbus_message_iter_get_basic (&reply_iter, &value);
1614 dbus_message_unref (reply);
1615 return value;
1619 /* generic helper */
1620 static dbus_bool_t
1621 libhal_device_set_property_helper (LibHalContext *ctx,
1622 const char *udi,
1623 const char *key,
1624 int type,
1625 const char *str_value,
1626 dbus_int32_t int_value,
1627 dbus_uint64_t uint64_value,
1628 double double_value,
1629 dbus_bool_t bool_value,
1630 DBusError *error)
1632 DBusMessage *message;
1633 DBusMessage *reply;
1634 DBusMessageIter iter;
1635 char *method_name = NULL;
1637 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1638 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1639 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1641 /** @todo sanity check incoming params */
1642 switch (type) {
1643 case DBUS_TYPE_INVALID:
1644 method_name = "RemoveProperty";
1645 break;
1646 case DBUS_TYPE_STRING:
1647 method_name = "SetPropertyString";
1648 break;
1649 case DBUS_TYPE_INT32:
1650 case DBUS_TYPE_UINT64:
1651 method_name = "SetPropertyInteger";
1652 break;
1653 case DBUS_TYPE_DOUBLE:
1654 method_name = "SetPropertyDouble";
1655 break;
1656 case DBUS_TYPE_BOOLEAN:
1657 method_name = "SetPropertyBoolean";
1658 break;
1660 default:
1661 /* cannot happen; is not callable from outside this file */
1662 break;
1665 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1666 "org.freedesktop.Hal.Device",
1667 method_name);
1668 if (message == NULL) {
1669 fprintf (stderr,
1670 "%s %d : Couldn't allocate D-BUS message\n",
1671 __FILE__, __LINE__);
1672 return FALSE;
1675 dbus_message_iter_init_append (message, &iter);
1676 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1677 switch (type) {
1678 case DBUS_TYPE_STRING:
1679 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str_value);
1680 break;
1681 case DBUS_TYPE_INT32:
1682 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &int_value);
1683 break;
1684 case DBUS_TYPE_UINT64:
1685 dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &uint64_value);
1686 break;
1687 case DBUS_TYPE_DOUBLE:
1688 dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &double_value);
1689 break;
1690 case DBUS_TYPE_BOOLEAN:
1691 dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bool_value);
1692 break;
1696 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1697 message, -1,
1698 error);
1700 dbus_message_unref (message);
1702 if (error != NULL && dbus_error_is_set (error)) {
1703 return FALSE;
1705 if (reply == NULL) {
1706 return FALSE;
1709 dbus_message_unref (reply);
1711 return TRUE;
1715 * libhal_device_set_property_string:
1716 * @ctx: the context for the connection to hald
1717 * @udi: the Unique Device Id
1718 * @key: name of the property
1719 * @value: value of the property; a UTF8 string
1720 * @error: pointer to an initialized dbus error object for returning errors or NULL
1722 * Set a property of type string.
1724 * Returns: TRUE if the property was set, FALSE if the device didn't
1725 * exist or the property had a different type.
1727 dbus_bool_t
1728 libhal_device_set_property_string (LibHalContext *ctx,
1729 const char *udi,
1730 const char *key,
1731 const char *value,
1732 DBusError *error)
1734 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1735 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1736 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1737 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
1739 return libhal_device_set_property_helper (ctx, udi, key,
1740 DBUS_TYPE_STRING,
1741 value, 0, 0, 0.0f, FALSE, error);
1745 * libhal_device_set_property_int:
1746 * @ctx: the context for the connection to hald
1747 * @udi: the Unique Device Id
1748 * @key: name of the property
1749 * @value: value of the property
1750 * @error: pointer to an initialized dbus error object for returning errors or NULL
1752 * Set a property of type signed integer.
1754 * Returns: TRUE if the property was set, FALSE if the device didn't
1755 * exist or the property had a different type.
1757 dbus_bool_t
1758 libhal_device_set_property_int (LibHalContext *ctx, const char *udi,
1759 const char *key, dbus_int32_t value, DBusError *error)
1761 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1762 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1763 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1765 return libhal_device_set_property_helper (ctx, udi, key,
1766 DBUS_TYPE_INT32,
1767 NULL, value, 0, 0.0f, FALSE, error);
1771 * libhal_device_set_property_uint64:
1772 * @ctx: the context for the connection to hald
1773 * @udi: the Unique Device Id
1774 * @key: name of the property
1775 * @value: value of the property
1776 * @error: pointer to an initialized dbus error object for returning errors or NULL
1778 * Set a property of type unsigned integer.
1780 * Returns: TRUE if the property was set, FALSE if the device didn't
1781 * exist or the property had a different type.
1783 dbus_bool_t
1784 libhal_device_set_property_uint64 (LibHalContext *ctx, const char *udi,
1785 const char *key, dbus_uint64_t value, DBusError *error)
1787 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1788 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1789 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1791 return libhal_device_set_property_helper (ctx, udi, key,
1792 DBUS_TYPE_UINT64,
1793 NULL, 0, value, 0.0f, FALSE, error);
1797 * libhal_device_set_property_double:
1798 * @ctx: the context for the connection to hald
1799 * @udi: the Unique Device Id
1800 * @key: name of the property
1801 * @value: value of the property
1802 * @error: pointer to an initialized dbus error object for returning errors or NULL
1804 * Set a property of type double.
1806 * Returns: TRUE if the property was set, FALSE if the device didn't
1807 * exist or the property had a different type.
1809 dbus_bool_t
1810 libhal_device_set_property_double (LibHalContext *ctx, const char *udi,
1811 const char *key, double value, DBusError *error)
1813 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1814 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1815 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1817 return libhal_device_set_property_helper (ctx, udi, key,
1818 DBUS_TYPE_DOUBLE,
1819 NULL, 0, 0, value, FALSE, error);
1823 * libhal_device_set_property_bool:
1824 * @ctx: the context for the connection to hald
1825 * @udi: the Unique Device Id
1826 * @key: name of the property
1827 * @value: value of the property
1828 * @error: pointer to an initialized dbus error object for returning errors or NULL
1830 * Set a property of type bool.
1832 * Returns: TRUE if the property was set, FALSE if the device didn't
1833 * exist or the property had a different type.
1835 dbus_bool_t
1836 libhal_device_set_property_bool (LibHalContext *ctx, const char *udi,
1837 const char *key, dbus_bool_t value, DBusError *error)
1839 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1840 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1841 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1843 return libhal_device_set_property_helper (ctx, udi, key,
1844 DBUS_TYPE_BOOLEAN,
1845 NULL, 0, 0, 0.0f, value, error);
1850 * libhal_device_remove_property:
1851 * @ctx: the context for the connection to hald
1852 * @udi: the Unique Device Id
1853 * @key: name of the property
1854 * @error: pointer to an initialized dbus error object for returning errors or NULL
1856 * Remove a property.
1858 * Returns: TRUE if the property was set, FALSE if the device didn't
1859 * exist
1861 dbus_bool_t
1862 libhal_device_remove_property (LibHalContext *ctx,
1863 const char *udi, const char *key, DBusError *error)
1865 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1866 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1867 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1869 return libhal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_INVALID,
1870 /* DBUS_TYPE_INVALID means remove */
1871 NULL, 0, 0, 0.0f, FALSE, error);
1875 * libhal_device_property_strlist_append:
1876 * @ctx: the context for the connection to hald
1877 * @udi: the Unique Device Id
1878 * @key: name of the property
1879 * @value: value to append to property
1880 * @error: pointer to an initialized dbus error object for returning errors or NULL
1882 * Append to a property of type strlist.
1884 * Returns: TRUE if the value was appended, FALSE if the device didn't
1885 * exist or the property had a different type.
1887 dbus_bool_t
1888 libhal_device_property_strlist_append (LibHalContext *ctx,
1889 const char *udi,
1890 const char *key,
1891 const char *value,
1892 DBusError *error)
1894 DBusMessage *message;
1895 DBusMessage *reply;
1896 DBusMessageIter iter;
1898 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1899 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1900 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1901 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
1903 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1904 "org.freedesktop.Hal.Device",
1905 "StringListAppend");
1906 if (message == NULL) {
1907 fprintf (stderr,
1908 "%s %d : Couldn't allocate D-BUS message\n",
1909 __FILE__, __LINE__);
1910 return FALSE;
1912 dbus_message_iter_init_append (message, &iter);
1913 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1914 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
1916 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1917 message, -1,
1918 error);
1920 dbus_message_unref (message);
1922 if (error != NULL && dbus_error_is_set (error)) {
1923 return FALSE;
1925 if (reply == NULL) {
1926 return FALSE;
1929 dbus_message_unref (reply);
1930 return TRUE;
1934 * libhal_device_property_strlist_prepend:
1935 * @ctx: the context for the connection to hald
1936 * @udi: the Unique Device Id
1937 * @key: name of the property
1938 * @value: value to prepend to property
1939 * @error: pointer to an initialized dbus error object for returning errors or NULL
1941 * Prepend to a property of type strlist.
1943 * Returns: TRUE if the value was prepended, FALSE if the device
1944 * didn't exist or the property had a different type.
1946 dbus_bool_t
1947 libhal_device_property_strlist_prepend (LibHalContext *ctx,
1948 const char *udi,
1949 const char *key,
1950 const char *value,
1951 DBusError *error)
1953 DBusMessage *message;
1954 DBusMessage *reply;
1955 DBusMessageIter iter;
1957 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1958 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
1959 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
1960 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
1962 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1963 "org.freedesktop.Hal.Device",
1964 "StringListPrepend");
1965 if (message == NULL) {
1966 fprintf (stderr,
1967 "%s %d : Couldn't allocate D-BUS message\n",
1968 __FILE__, __LINE__);
1969 return FALSE;
1971 dbus_message_iter_init_append (message, &iter);
1972 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1973 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
1975 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1976 message, -1,
1977 error);
1979 dbus_message_unref (message);
1981 if (error != NULL && dbus_error_is_set (error)) {
1982 return FALSE;
1984 if (reply == NULL) {
1985 return FALSE;
1988 dbus_message_unref (reply);
1989 return TRUE;
1993 * libhal_device_property_strlist_remove_index:
1994 * @ctx: the context for the connection to hald
1995 * @udi: the Unique Device Id
1996 * @key: name of the property
1997 * @idx: index of string to remove in the strlist
1998 * @error: pointer to an initialized dbus error object for returning errors or NULL
2000 * Remove a specified string from a property of type strlist.
2002 * Returns: TRUE if the string was removed, FALSE if the device didn't
2003 * exist or the property had a different type.
2005 dbus_bool_t
2006 libhal_device_property_strlist_remove_index (LibHalContext *ctx,
2007 const char *udi,
2008 const char *key,
2009 unsigned int idx,
2010 DBusError *error)
2012 DBusMessage *message;
2013 DBusMessage *reply;
2014 DBusMessageIter iter;
2016 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2017 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2018 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
2020 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2021 "org.freedesktop.Hal.Device",
2022 "StringListRemoveIndex");
2023 if (message == NULL) {
2024 fprintf (stderr,
2025 "%s %d : Couldn't allocate D-BUS message\n",
2026 __FILE__, __LINE__);
2027 return FALSE;
2029 dbus_message_iter_init_append (message, &iter);
2030 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2031 dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &idx);
2033 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2034 message, -1,
2035 error);
2037 dbus_message_unref (message);
2039 if (error != NULL && dbus_error_is_set (error)) {
2040 return FALSE;
2042 if (reply == NULL) {
2043 return FALSE;
2046 dbus_message_unref (reply);
2047 return TRUE;
2051 * libhal_device_property_strlist_remove:
2052 * @ctx: the context for the connection to hald
2053 * @udi: the Unique Device Id
2054 * @key: name of the property
2055 * @value: the string to remove
2056 * @error: pointer to an initialized dbus error object for returning errors or NULL
2058 * Remove a specified string from a property of type strlist.
2060 * Returns: TRUE if the string was removed, FALSE if the device didn't
2061 * exist or the property had a different type.
2063 dbus_bool_t
2064 libhal_device_property_strlist_remove (LibHalContext *ctx,
2065 const char *udi,
2066 const char *key,
2067 const char *value, DBusError *error)
2069 DBusMessage *message;
2070 DBusMessage *reply;
2071 DBusMessageIter iter;
2073 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2074 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2075 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
2076 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
2078 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2079 "org.freedesktop.Hal.Device",
2080 "StringListRemove");
2081 if (message == NULL) {
2082 fprintf (stderr,
2083 "%s %d : Couldn't allocate D-BUS message\n",
2084 __FILE__, __LINE__);
2085 return FALSE;
2087 dbus_message_iter_init_append (message, &iter);
2088 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2089 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
2091 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2092 message, -1,
2093 error);
2095 dbus_message_unref (message);
2097 if (error != NULL && dbus_error_is_set (error)) {
2098 return FALSE;
2100 if (reply == NULL) {
2101 return FALSE;
2104 dbus_message_unref (reply);
2105 return TRUE;
2110 * libhal_device_lock:
2111 * @ctx: the context for the connection to hald
2112 * @udi: the Unique Device Id
2113 * @reason_to_lock: a user-presentable reason why the device is locked.
2114 * @reason_why_locked: a pointer to store the reason why the device cannot be locked on failure, or NULL
2115 * @error: pointer to an initialized dbus error object for returning errors or NULL
2117 * Take an advisory lock on the device.
2119 * Returns: TRUE if the lock was obtained, FALSE otherwise
2121 dbus_bool_t
2122 libhal_device_lock (LibHalContext *ctx,
2123 const char *udi,
2124 const char *reason_to_lock,
2125 char **reason_why_locked, DBusError *error)
2127 DBusMessage *message;
2128 DBusMessageIter iter;
2129 DBusMessage *reply;
2131 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2132 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2134 if (reason_why_locked != NULL)
2135 *reason_why_locked = NULL;
2137 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2138 udi,
2139 "org.freedesktop.Hal.Device",
2140 "Lock");
2142 if (message == NULL) {
2143 fprintf (stderr,
2144 "%s %d : Couldn't allocate D-BUS message\n",
2145 __FILE__, __LINE__);
2146 return FALSE;
2149 dbus_message_iter_init_append (message, &iter);
2150 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reason_to_lock);
2153 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2154 message, -1,
2155 error);
2157 dbus_message_unref (message);
2159 if (error != NULL && dbus_error_is_set (error)) {
2160 if (strcmp (error->name,
2161 "org.freedesktop.Hal.DeviceAlreadyLocked") == 0) {
2162 if (reason_why_locked != NULL) {
2163 *reason_why_locked =
2164 dbus_malloc0 (strlen (error->message) + 1);
2165 if (*reason_why_locked == NULL)
2166 return FALSE;
2167 strcpy (*reason_why_locked, error->message);
2171 return FALSE;
2173 if (reply == NULL)
2174 return FALSE;
2176 dbus_message_unref (reply);
2178 return TRUE;
2182 * libhal_device_unlock:
2183 * @ctx: the context for the connection to hald
2184 * @udi: the Unique Device Id
2185 * @error: pointer to an initialized dbus error object for returning errors or NULL
2187 * Release an advisory lock on the device.
2189 * Returns: TRUE if the device was successfully unlocked,
2190 * FALSE otherwise
2192 dbus_bool_t
2193 libhal_device_unlock (LibHalContext *ctx,
2194 const char *udi, DBusError *error)
2196 DBusMessage *message;
2197 DBusMessage *reply;
2199 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2200 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2202 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2203 udi,
2204 "org.freedesktop.Hal.Device",
2205 "Unlock");
2207 if (message == NULL) {
2208 fprintf (stderr,
2209 "%s %d : Couldn't allocate D-BUS message\n",
2210 __FILE__, __LINE__);
2211 return FALSE;
2215 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2216 message, -1,
2217 error);
2219 dbus_message_unref (message);
2221 if (error != NULL && dbus_error_is_set (error)) {
2222 return FALSE;
2224 if (reply == NULL)
2225 return FALSE;
2227 dbus_message_unref (reply);
2229 return TRUE;
2234 * libhal_new_device:
2235 * @ctx: the context for the connection to hald
2236 * @error: pointer to an initialized dbus error object for returning errors or NULL
2238 * Create a new device object which will be hidden from applications
2239 * until the CommitToGdl(), ie. libhal_device_commit_to_gdl(), method
2240 * is called. Note that the program invoking this method needs to run
2241 * with super user privileges.
2243 * Returns: Temporary device unique id or NULL if there was a
2244 * problem. This string must be freed by the caller.
2246 char *
2247 libhal_new_device (LibHalContext *ctx, DBusError *error)
2249 DBusMessage *message;
2250 DBusMessage *reply;
2251 DBusMessageIter reply_iter;
2252 char *value;
2253 char *dbus_str;
2255 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2257 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2258 "/org/freedesktop/Hal/Manager",
2259 "org.freedesktop.Hal.Manager",
2260 "NewDevice");
2261 if (message == NULL) {
2262 fprintf (stderr,
2263 "%s %d : Couldn't allocate D-BUS message\n",
2264 __FILE__, __LINE__);
2265 return NULL;
2269 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2270 message, -1,
2271 error);
2273 dbus_message_unref (message);
2275 if (error != NULL && dbus_error_is_set (error)) {
2276 return NULL;
2278 if (reply == NULL) {
2279 return NULL;
2282 dbus_message_iter_init (reply, &reply_iter);
2284 /* now analyze reply */
2285 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) {
2286 fprintf (stderr,
2287 "%s %d : expected a string in reply to NewDevice\n",
2288 __FILE__, __LINE__);
2289 dbus_message_unref (reply);
2290 return NULL;
2293 dbus_message_iter_get_basic (&reply_iter, &dbus_str);
2294 value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
2295 if (value == NULL) {
2296 fprintf (stderr, "%s %d : error allocating memory\n",
2297 __FILE__, __LINE__);
2300 dbus_message_unref (reply);
2301 return value;
2306 * libhal_device_commit_to_gdl:
2307 * @ctx: the context for the connection to hald
2308 * @temp_udi: the temporary unique device id as returned by libhal_new_device()
2309 * @udi: the new unique device id.
2310 * @error: pointer to an initialized dbus error object for returning errors or NULL
2312 * When a hidden device has been built using the NewDevice method,
2313 * ie. libhal_new_device(), and the org.freedesktop.Hal.Device
2314 * interface this function will commit it to the global device list.
2316 * This means that the device object will be visible to applications
2317 * and the HAL daemon will possibly attempt to boot the device
2318 * (depending on the property RequireEnable).
2320 * Note that the program invoking this method needs to run with super
2321 * user privileges.
2323 * Returns: FALSE if the given unique device id is already in use.
2325 dbus_bool_t
2326 libhal_device_commit_to_gdl (LibHalContext *ctx,
2327 const char *temp_udi, const char *udi, DBusError *error)
2329 DBusMessage *message;
2330 DBusMessage *reply;
2331 DBusMessageIter iter;
2333 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2334 LIBHAL_CHECK_UDI_VALID(temp_udi, FALSE);
2335 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2337 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2338 "/org/freedesktop/Hal/Manager",
2339 "org.freedesktop.Hal.Manager",
2340 "CommitToGdl");
2341 if (message == NULL) {
2342 fprintf (stderr,
2343 "%s %d : Couldn't allocate D-BUS message\n",
2344 __FILE__, __LINE__);
2345 return FALSE;
2348 dbus_message_iter_init_append (message, &iter);
2349 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &temp_udi);
2350 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
2353 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2354 message, -1,
2355 error);
2357 dbus_message_unref (message);
2359 if (error != NULL && dbus_error_is_set (error)) {
2360 return FALSE;
2362 if (reply == NULL) {
2363 return FALSE;
2366 dbus_message_unref (reply);
2367 return TRUE;
2371 * libhal_remove_device:
2372 * @ctx: the context for the connection to hald
2373 * @udi: the Unique device id.
2374 * @error: pointer to an initialized dbus error object for returning errors or NULL
2376 * This method can be invoked when a device is removed. The HAL daemon
2377 * will shut down the device. Note that the device may still be in the
2378 * device list if the Persistent property is set to true.
2380 * Note that the program invoking this method needs to run with super
2381 * user privileges.
2383 * Returns: TRUE if the device was removed, FALSE otherwise
2385 dbus_bool_t
2386 libhal_remove_device (LibHalContext *ctx, const char *udi, DBusError *error)
2388 DBusMessage *message;
2389 DBusMessage *reply;
2390 DBusMessageIter iter;
2392 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2393 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2395 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2396 "/org/freedesktop/Hal/Manager",
2397 "org.freedesktop.Hal.Manager",
2398 "Remove");
2399 if (message == NULL) {
2400 fprintf (stderr,
2401 "%s %d : Couldn't allocate D-BUS message\n",
2402 __FILE__, __LINE__);
2403 return FALSE;
2406 dbus_message_iter_init_append (message, &iter);
2407 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
2410 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2411 message, -1,
2412 error);
2414 dbus_message_unref (message);
2416 if (error != NULL && dbus_error_is_set (error)) {
2417 return FALSE;
2419 if (reply == NULL) {
2420 return FALSE;
2423 dbus_message_unref (reply);
2424 return TRUE;
2428 * libhal_device_exists:
2429 * @ctx: the context for the connection to hald
2430 * @udi: the Unique device id.
2431 * @error: pointer to an initialized dbus error object for returning errors or NULL
2433 * Determine if a device exists.
2435 * Returns: TRUE if the device exists
2437 dbus_bool_t
2438 libhal_device_exists (LibHalContext *ctx, const char *udi, DBusError *error)
2440 DBusMessage *message;
2441 DBusMessage *reply;
2442 DBusMessageIter iter, reply_iter;
2443 dbus_bool_t value;
2444 DBusError _error;
2446 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2447 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2449 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2450 "/org/freedesktop/Hal/Manager",
2451 "org.freedesktop.Hal.Manager",
2452 "DeviceExists");
2453 if (message == NULL) {
2454 fprintf (stderr,
2455 "%s %d : Couldn't allocate D-BUS message\n",
2456 __FILE__, __LINE__);
2457 return FALSE;
2460 dbus_message_iter_init_append (message, &iter);
2461 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
2463 dbus_error_init (&_error);
2464 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2465 message, -1,
2466 &_error);
2468 dbus_message_unref (message);
2470 dbus_move_error (&_error, error);
2471 if (error != NULL && dbus_error_is_set (error)) {
2472 return FALSE;
2474 if (reply == NULL) {
2475 return FALSE;
2478 dbus_message_iter_init (reply, &reply_iter);
2480 /* now analyze reply */
2481 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
2482 fprintf (stderr,
2483 "%s %d : expected a bool in reply to DeviceExists\n",
2484 __FILE__, __LINE__);
2485 dbus_message_unref (reply);
2486 return FALSE;
2489 dbus_message_iter_get_basic (&reply_iter, &value);
2491 dbus_message_unref (reply);
2492 return value;
2496 * libhal_device_property_exists:
2497 * @ctx: the context for the connection to hald
2498 * @udi: the Unique device id.
2499 * @key: name of the property
2500 * @error: pointer to an initialized dbus error object for returning errors or NULL
2502 * Determine if a property on a device exists.
2504 * Returns: TRUE if the device exists, FALSE otherwise
2506 dbus_bool_t
2507 libhal_device_property_exists (LibHalContext *ctx,
2508 const char *udi, const char *key, DBusError *error)
2510 DBusMessage *message;
2511 DBusMessage *reply;
2512 DBusMessageIter iter, reply_iter;
2513 dbus_bool_t value;
2514 DBusError _error;
2516 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2517 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2518 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
2520 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2521 "org.freedesktop.Hal.Device",
2522 "PropertyExists");
2523 if (message == NULL) {
2524 fprintf (stderr,
2525 "%s %d : Couldn't allocate D-BUS message\n",
2526 __FILE__, __LINE__);
2527 return FALSE;
2530 dbus_message_iter_init_append (message, &iter);
2531 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2533 dbus_error_init (&_error);
2534 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2535 message, -1,
2536 &_error);
2538 dbus_message_unref (message);
2540 dbus_move_error (&_error, error);
2541 if (error != NULL && dbus_error_is_set (error)) {
2542 return FALSE;
2544 if (reply == NULL) {
2545 return FALSE;
2548 dbus_message_iter_init (reply, &reply_iter);
2550 /* now analyse reply */
2551 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
2552 fprintf (stderr, "%s %d : expected a bool in reply to "
2553 "PropertyExists\n", __FILE__, __LINE__);
2554 dbus_message_unref (reply);
2555 return FALSE;
2558 dbus_message_iter_get_basic (&reply_iter, &value);
2560 dbus_message_unref (reply);
2561 return value;
2565 * libhal_merge_properties:
2566 * @ctx: the context for the connection to hald
2567 * @target_udi: the Unique device id of target device to merge to
2568 * @source_udi: the Unique device id of device to merge from
2569 * @error: pointer to an initialized dbus error object for returning errors or NULL
2571 * Merge properties from one device to another.
2573 * Returns: TRUE if the properties were merged, FALSE otherwise
2575 dbus_bool_t
2576 libhal_merge_properties (LibHalContext *ctx,
2577 const char *target_udi, const char *source_udi, DBusError *error)
2579 DBusMessage *message;
2580 DBusMessage *reply;
2581 DBusMessageIter iter;
2583 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2584 LIBHAL_CHECK_UDI_VALID(target_udi, FALSE);
2585 LIBHAL_CHECK_UDI_VALID(source_udi, FALSE);
2587 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2588 "/org/freedesktop/Hal/Manager",
2589 "org.freedesktop.Hal.Manager",
2590 "MergeProperties");
2591 if (message == NULL) {
2592 fprintf (stderr,
2593 "%s %d : Couldn't allocate D-BUS message\n",
2594 __FILE__, __LINE__);
2595 return FALSE;
2598 dbus_message_iter_init_append (message, &iter);
2599 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &target_udi);
2600 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &source_udi);
2603 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2604 message, -1,
2605 error);
2607 dbus_message_unref (message);
2609 if (error != NULL && dbus_error_is_set (error)) {
2610 return FALSE;
2612 if (reply == NULL) {
2613 return FALSE;
2616 dbus_message_unref (reply);
2617 return TRUE;
2621 * libhal_device_matches:
2622 * @ctx: the context for the connection to hald
2623 * @udi1: the Unique Device Id for device 1
2624 * @udi2: the Unique Device Id for device 2
2625 * @property_namespace: the namespace for set of devices, e.g. "usb"
2626 * @error: pointer to an initialized dbus error object for returning errors or NULL
2628 * Check a set of properties for two devices matches.
2630 * Checks that all properties where keys, starting with a given value
2631 * (namespace), of the first device is in the second device and that
2632 * they got the same value and type.
2634 * Note that the other inclusion isn't tested, so there could be
2635 * properties (from the given namespace) in the second device not
2636 * present in the first device.
2638 * Returns: TRUE if all properties starting with the given namespace
2639 * parameter from one device is in the other and have the same value.
2641 dbus_bool_t
2642 libhal_device_matches (LibHalContext *ctx,
2643 const char *udi1, const char *udi2,
2644 const char *property_namespace, DBusError *error)
2646 DBusMessage *message;
2647 DBusMessage *reply;
2648 DBusMessageIter iter, reply_iter;
2649 dbus_bool_t value;
2650 DBusError _error;
2652 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2653 LIBHAL_CHECK_UDI_VALID(udi1, FALSE);
2654 LIBHAL_CHECK_UDI_VALID(udi2, FALSE);
2655 LIBHAL_CHECK_PARAM_VALID(property_namespace, "*property_namespace", FALSE);
2657 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2658 "/org/freedesktop/Hal/Manager",
2659 "org.freedesktop.Hal.Manager",
2660 "DeviceMatches");
2661 if (message == NULL) {
2662 fprintf (stderr,
2663 "%s %d : Couldn't allocate D-BUS message\n",
2664 __FILE__, __LINE__);
2665 return FALSE;
2668 dbus_message_iter_init_append (message, &iter);
2669 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi1);
2670 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi2);
2671 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, property_namespace);
2673 dbus_error_init (&_error);
2674 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2675 message, -1,
2676 &_error);
2678 dbus_message_unref (message);
2680 dbus_move_error (&_error, error);
2681 if (error != NULL && dbus_error_is_set (error)) {
2682 return FALSE;
2684 if (reply == NULL) {
2685 return FALSE;
2687 /* now analyse reply */
2688 dbus_message_iter_init (reply, &reply_iter);
2690 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
2691 fprintf (stderr,
2692 "%s %d : expected a bool in reply to DeviceMatches\n",
2693 __FILE__, __LINE__);
2694 dbus_message_unref (reply);
2695 return FALSE;
2698 dbus_message_iter_get_basic (&reply_iter, &value);
2700 dbus_message_unref (reply);
2701 return value;
2705 * libhal_device_print:
2706 * @ctx: the context for the connection to hald
2707 * @udi: the Unique Device Id
2708 * @error: pointer to an initialized dbus error object for returning errors or NULL
2710 * Print a device to stdout; useful for debugging.
2712 * Returns: TRUE if device's information could be obtained, FALSE otherwise
2714 dbus_bool_t
2715 libhal_device_print (LibHalContext *ctx, const char *udi, DBusError *error)
2717 int type;
2718 char *key;
2719 LibHalPropertySet *pset;
2720 LibHalPropertySetIterator i;
2722 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2723 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2725 printf ("device_id = %s\n", udi);
2727 if ((pset = libhal_device_get_all_properties (ctx, udi, error)) == NULL)
2728 return FALSE;
2730 for (libhal_psi_init (&i, pset); libhal_psi_has_more (&i);
2731 libhal_psi_next (&i)) {
2732 type = libhal_psi_get_type (&i);
2733 key = libhal_psi_get_key (&i);
2735 switch (type) {
2736 case LIBHAL_PROPERTY_TYPE_STRING:
2737 printf (" %s = '%s' (string)\n", key,
2738 libhal_psi_get_string (&i));
2739 break;
2740 case LIBHAL_PROPERTY_TYPE_INT32:
2741 printf (" %s = %d = 0x%x (int)\n", key,
2742 libhal_psi_get_int (&i),
2743 libhal_psi_get_int (&i));
2744 break;
2745 case LIBHAL_PROPERTY_TYPE_UINT64:
2746 printf (" %s = %llu = 0x%llx (uint64)\n", key,
2747 (long long unsigned int) libhal_psi_get_uint64 (&i),
2748 (long long unsigned int) libhal_psi_get_uint64 (&i));
2749 break;
2750 case LIBHAL_PROPERTY_TYPE_BOOLEAN:
2751 printf (" %s = %s (bool)\n", key,
2752 (libhal_psi_get_bool (&i) ? "true" :
2753 "false"));
2754 break;
2755 case LIBHAL_PROPERTY_TYPE_DOUBLE:
2756 printf (" %s = %g (double)\n", key,
2757 libhal_psi_get_double (&i));
2758 break;
2759 case LIBHAL_PROPERTY_TYPE_STRLIST:
2761 unsigned int j;
2762 char **str_list;
2764 str_list = libhal_psi_get_strlist (&i);
2765 printf (" %s = [", key);
2766 for (j = 0; str_list[j] != NULL; j++) {
2767 printf ("'%s'", str_list[j]);
2768 if (str_list[j+1] != NULL)
2769 printf (", ");
2771 printf ("] (string list)\n");
2773 break;
2775 default:
2776 printf (" *** unknown type for key %s\n", key);
2777 break;
2781 libhal_free_property_set (pset);
2783 return TRUE;
2787 * libhal_manager_find_device_string_match:
2788 * @ctx: the context for the connection to hald
2789 * @key: name of the property
2790 * @value: the value to match
2791 * @num_devices: pointer to store number of devices
2792 * @error: pointer to an initialized dbus error object for returning errors or NULL
2794 * Find a device in the GDL where a single string property matches a
2795 * given value.
2797 * Returns: UDI of devices; free with libhal_free_string_array()
2799 char **
2800 libhal_manager_find_device_string_match (LibHalContext *ctx,
2801 const char *key,
2802 const char *value, int *num_devices, DBusError *error)
2804 DBusMessage *message;
2805 DBusMessage *reply;
2806 DBusMessageIter iter, iter_array, reply_iter;
2807 char **hal_device_names;
2808 DBusError _error;
2810 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2811 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
2812 LIBHAL_CHECK_PARAM_VALID(value, "*value", NULL);
2814 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2815 "/org/freedesktop/Hal/Manager",
2816 "org.freedesktop.Hal.Manager",
2817 "FindDeviceStringMatch");
2818 if (message == NULL) {
2819 fprintf (stderr,
2820 "%s %d : Couldn't allocate D-BUS message\n",
2821 __FILE__, __LINE__);
2822 return NULL;
2825 dbus_message_iter_init_append (message, &iter);
2826 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2827 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
2829 dbus_error_init (&_error);
2830 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2831 message, -1,
2832 &_error);
2834 dbus_message_unref (message);
2836 dbus_move_error (&_error, error);
2837 if (error != NULL && dbus_error_is_set (error)) {
2838 return NULL;
2840 if (reply == NULL) {
2841 return NULL;
2843 /* now analyse reply */
2844 dbus_message_iter_init (reply, &reply_iter);
2846 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
2847 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
2848 return NULL;
2851 dbus_message_iter_recurse (&reply_iter, &iter_array);
2853 hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
2855 dbus_message_unref (reply);
2856 return hal_device_names;
2861 * libhal_device_add_capability:
2862 * @ctx: the context for the connection to hald
2863 * @udi: the Unique Device Id
2864 * @capability: the capability name to add
2865 * @error: pointer to an initialized dbus error object for returning errors or NULL
2867 * Assign a capability to a device.
2869 * Returns: TRUE if the capability was added, FALSE if the device didn't exist
2871 dbus_bool_t
2872 libhal_device_add_capability (LibHalContext *ctx,
2873 const char *udi, const char *capability, DBusError *error)
2875 DBusMessage *message;
2876 DBusMessage *reply;
2877 DBusMessageIter iter;
2879 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2880 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2881 LIBHAL_CHECK_PARAM_VALID(capability, "*capability", FALSE);
2883 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2884 "org.freedesktop.Hal.Device",
2885 "AddCapability");
2886 if (message == NULL) {
2887 fprintf (stderr,
2888 "%s %d : Couldn't allocate D-BUS message\n",
2889 __FILE__, __LINE__);
2890 return FALSE;
2893 dbus_message_iter_init_append (message, &iter);
2894 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
2897 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2898 message, -1,
2899 error);
2901 dbus_message_unref (message);
2903 if (error != NULL && dbus_error_is_set (error)) {
2904 return FALSE;
2906 if (reply == NULL) {
2907 return FALSE;
2910 dbus_message_unref (reply);
2911 return TRUE;
2915 * libhal_device_query_capability:
2916 * @ctx: the context for the connection to hald
2917 * @udi: the Unique Device Id
2918 * @capability: the capability name
2919 * @error: pointer to an initialized dbus error object for returning errors or NULL
2921 * Check if a device has a capability. The result is undefined if the
2922 * device doesn't exist.
2924 * Returns: TRUE if the device has the capability, otherwise FALSE
2926 dbus_bool_t
2927 libhal_device_query_capability (LibHalContext *ctx, const char *udi, const char *capability, DBusError *error)
2929 char **caps;
2930 unsigned int i;
2931 dbus_bool_t ret;
2933 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2934 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
2935 LIBHAL_CHECK_PARAM_VALID(capability, "*capability", FALSE);
2937 ret = FALSE;
2939 caps = libhal_device_get_property_strlist (ctx, udi, "info.capabilities", error);
2940 if (caps != NULL) {
2941 for (i = 0; caps[i] != NULL; i++) {
2942 if (strcmp (caps[i], capability) == 0) {
2943 ret = TRUE;
2944 break;
2947 libhal_free_string_array (caps);
2950 return ret;
2954 * libhal_find_device_by_capability:
2955 * @ctx: the context for the connection to hald
2956 * @capability: the capability name
2957 * @num_devices: pointer to store number of devices
2958 * @error: pointer to an initialized dbus error object for returning errors or NULL
2960 * Find devices with a given capability.
2962 * Returns: UDI of devices; free with libhal_free_string_array()
2964 char **
2965 libhal_find_device_by_capability (LibHalContext *ctx,
2966 const char *capability, int *num_devices, DBusError *error)
2968 DBusMessage *message;
2969 DBusMessage *reply;
2970 DBusMessageIter iter, iter_array, reply_iter;
2971 char **hal_device_names;
2972 DBusError _error;
2974 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2975 LIBHAL_CHECK_PARAM_VALID(capability, "*capability", NULL);
2977 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2978 "/org/freedesktop/Hal/Manager",
2979 "org.freedesktop.Hal.Manager",
2980 "FindDeviceByCapability");
2981 if (message == NULL) {
2982 fprintf (stderr,
2983 "%s %d : Couldn't allocate D-BUS message\n",
2984 __FILE__, __LINE__);
2985 return NULL;
2988 dbus_message_iter_init_append (message, &iter);
2989 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
2991 dbus_error_init (&_error);
2992 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2993 message, -1,
2994 &_error);
2996 dbus_message_unref (message);
2998 dbus_move_error (&_error, error);
2999 if (error != NULL && dbus_error_is_set (error)) {
3000 return NULL;
3002 if (reply == NULL) {
3003 return NULL;
3005 /* now analyse reply */
3006 dbus_message_iter_init (reply, &reply_iter);
3008 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
3009 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
3010 return NULL;
3013 dbus_message_iter_recurse (&reply_iter, &iter_array);
3015 hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
3017 dbus_message_unref (reply);
3018 return hal_device_names;
3022 * libhal_device_property_watch_all:
3023 * @ctx: the context for the connection to hald
3024 * @error: pointer to an initialized dbus error object for returning errors or NULL
3026 * Watch all devices, ie. the device_property_changed callback is
3027 * invoked when the properties on any device changes.
3029 * Returns: TRUE only if the operation succeeded
3031 dbus_bool_t
3032 libhal_device_property_watch_all (LibHalContext *ctx, DBusError *error)
3034 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3036 dbus_bus_add_match (ctx->connection,
3037 "type='signal',"
3038 "interface='org.freedesktop.Hal.Device',"
3039 "sender='org.freedesktop.Hal'", error);
3040 if (error != NULL && dbus_error_is_set (error)) {
3041 return FALSE;
3043 return TRUE;
3048 * libhal_device_add_property_watch:
3049 * @ctx: the context for the connection to hald
3050 * @udi: the Unique Device Id
3051 * @error: pointer to an initialized dbus error object for returning errors or NULL
3053 * Add a watch on a device, so the device_property_changed callback is
3054 * invoked when the properties on the given device changes.
3056 * The application itself is responsible for deleting the watch, using
3057 * libhal_device_remove_property_watch, if the device is removed.
3059 * Returns: TRUE only if the operation succeeded
3061 dbus_bool_t
3062 libhal_device_add_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
3064 char buf[512];
3066 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3067 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3069 snprintf (buf, 512,
3070 "type='signal',"
3071 "interface='org.freedesktop.Hal.Device',"
3072 "sender='org.freedesktop.Hal'," "path=%s", udi);
3074 dbus_bus_add_match (ctx->connection, buf, error);
3075 if (error != NULL && dbus_error_is_set (error)) {
3076 return FALSE;
3078 return TRUE;
3083 * libhal_device_remove_property_watch:
3084 * @ctx: the context for the connection to hald
3085 * @udi: the Unique Device Id
3086 * @error: pointer to an initialized dbus error object for returning errors or NULL
3088 * Remove a watch on a device.
3090 * Returns: TRUE only if the operation succeeded
3092 dbus_bool_t
3093 libhal_device_remove_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
3095 char buf[512];
3097 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3098 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3100 snprintf (buf, 512,
3101 "type='signal',"
3102 "interface='org.freedesktop.Hal.Device',"
3103 "sender='org.freedesktop.Hal'," "path=%s", udi);
3105 dbus_bus_remove_match (ctx->connection, buf, error);
3106 if (error != NULL && dbus_error_is_set (error)) {
3107 return FALSE;
3109 return TRUE;
3114 * libhal_ctx_new:
3116 * Create a new LibHalContext
3118 * Returns: a new uninitialized LibHalContext object
3120 LibHalContext *
3121 libhal_ctx_new (void)
3123 LibHalContext *ctx;
3125 if (!libhal_already_initialized_once) {
3126 bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
3127 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
3129 libhal_already_initialized_once = TRUE;
3132 ctx = calloc (1, sizeof (LibHalContext));
3133 if (ctx == NULL) {
3134 fprintf (stderr,
3135 "%s %d : Failed to allocate %lu bytes\n",
3136 __FILE__, __LINE__, (unsigned long) sizeof (LibHalContext));
3137 return NULL;
3140 ctx->is_initialized = FALSE;
3141 ctx->is_shutdown = FALSE;
3142 ctx->connection = NULL;
3143 ctx->is_direct = FALSE;
3145 return ctx;
3149 * libhal_ctx_set_cache:
3150 * @ctx: context to enable/disable cache for
3151 * @use_cache: whether or not to use cache
3153 * Enable or disable caching. Note: Caching is not actually
3154 * implemented yet.
3156 * Returns: TRUE if cache was successfully enabled/disabled, FALSE otherwise
3158 dbus_bool_t
3159 libhal_ctx_set_cache (LibHalContext *ctx, dbus_bool_t use_cache)
3161 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3163 ctx->cache_enabled = use_cache;
3164 return TRUE;
3168 * libhal_ctx_set_dbus_connection:
3169 * @ctx: context to set connection for
3170 * @conn: DBus connection to use
3172 * Set DBus connection to use to talk to hald.
3174 * Returns: TRUE if connection was successfully set, FALSE otherwise
3176 dbus_bool_t
3177 libhal_ctx_set_dbus_connection (LibHalContext *ctx, DBusConnection *conn)
3179 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3181 if (conn == NULL)
3182 return FALSE;
3184 ctx->connection = conn;
3185 return TRUE;
3189 * libhal_ctx_get_dbus_connection:
3190 * @ctx: context to get connection for
3192 * Get DBus connection used for talking to hald.
3194 * Returns: DBus connection to use or NULL
3196 DBusConnection *
3197 libhal_ctx_get_dbus_connection (LibHalContext *ctx)
3199 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
3201 return ctx->connection;
3206 * libhal_ctx_init:
3207 * @ctx: Context for connection to hald (D-BUS connection should be set with libhal_ctx_set_dbus_connection)
3208 * @error: pointer to an initialized dbus error object for returning errors or NULL
3210 * Initialize the connection to hald.
3212 * Returns: TRUE if initialization succeeds, FALSE otherwise
3214 dbus_bool_t
3215 libhal_ctx_init (LibHalContext *ctx, DBusError *error)
3217 DBusError _error;
3218 dbus_bool_t hald_exists;
3220 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3222 if (ctx->connection == NULL)
3223 return FALSE;
3225 dbus_error_init (&_error);
3226 hald_exists = dbus_bus_name_has_owner (ctx->connection, "org.freedesktop.Hal", &_error);
3227 dbus_move_error (&_error, error);
3228 if (error != NULL && dbus_error_is_set (error)) {
3229 return FALSE;
3232 if (!hald_exists) {
3233 return FALSE;
3237 if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) {
3238 return FALSE;
3241 dbus_bus_add_match (ctx->connection,
3242 "type='signal',"
3243 "interface='org.freedesktop.Hal.Manager',"
3244 "sender='org.freedesktop.Hal',"
3245 "path='/org/freedesktop/Hal/Manager'", &_error);
3246 dbus_move_error (&_error, error);
3247 if (error != NULL && dbus_error_is_set (error)) {
3248 return FALSE;
3250 ctx->is_initialized = TRUE;
3251 ctx->is_direct = FALSE;
3253 return TRUE;
3257 * libhal_ctx_init_direct:
3258 * @error: pointer to an initialized dbus error object for returning errors or NULL
3260 * Create an already initialized connection to hald. This function should only be used by HAL helpers.
3262 * Returns: A pointer to an already initialized LibHalContext
3264 LibHalContext *
3265 libhal_ctx_init_direct (DBusError *error)
3267 char *hald_addr;
3268 LibHalContext *ctx;
3269 DBusError _error;
3271 ctx = libhal_ctx_new ();
3272 if (ctx == NULL)
3273 goto out;
3275 if (((hald_addr = getenv ("HALD_DIRECT_ADDR"))) == NULL) {
3276 libhal_ctx_free (ctx);
3277 ctx = NULL;
3278 goto out;
3281 dbus_error_init (&_error);
3282 ctx->connection = dbus_connection_open (hald_addr, &_error);
3283 dbus_move_error (&_error, error);
3284 if (error != NULL && dbus_error_is_set (error)) {
3285 libhal_ctx_free (ctx);
3286 ctx = NULL;
3287 goto out;
3290 ctx->is_initialized = TRUE;
3291 ctx->is_direct = TRUE;
3293 out:
3294 return ctx;
3298 * libhal_ctx_shutdown:
3299 * @ctx: the context for the connection to hald
3300 * @error: pointer to an initialized dbus error object for returning errors or NULL
3302 * Shut down a connection to hald.
3304 * Returns: TRUE if connection successfully shut down, FALSE otherwise
3306 dbus_bool_t
3307 libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error)
3309 DBusError myerror;
3311 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3313 if (ctx->is_direct) {
3314 /* for some reason dbus_connection_set_exit_on_disconnect doesn't work yet so don't unref */
3315 /*dbus_connection_unref (ctx->connection);*/
3316 } else {
3317 dbus_error_init (&myerror);
3318 dbus_bus_remove_match (ctx->connection,
3319 "type='signal',"
3320 "interface='org.freedesktop.Hal.Manager',"
3321 "sender='org.freedesktop.Hal',"
3322 "path='/org/freedesktop/Hal/Manager'", &myerror);
3323 dbus_move_error (&myerror, error);
3324 if (error != NULL && dbus_error_is_set (error)) {
3325 fprintf (stderr, "%s %d : Error unsubscribing to signals, error=%s\n",
3326 __FILE__, __LINE__, error->message);
3327 /** @todo clean up */
3330 /* TODO: remove other matches */
3332 dbus_connection_remove_filter (ctx->connection, filter_func, ctx);
3335 ctx->is_initialized = FALSE;
3337 return TRUE;
3341 * libhal_ctx_free:
3342 * @ctx: pointer to a LibHalContext
3344 * Free a LibHalContext resource.
3346 * Returns: TRUE
3348 dbus_bool_t
3349 libhal_ctx_free (LibHalContext *ctx)
3351 free (ctx);
3352 return TRUE;
3356 * libhal_ctx_set_device_added:
3357 * @ctx: the context for the connection to hald
3358 * @callback: the function to call when a device is added
3360 * Set the callback for when a device is added
3362 * Returns: TRUE if callback was successfully set, FALSE otherwise
3364 dbus_bool_t
3365 libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback)
3367 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3369 ctx->device_added = callback;
3370 return TRUE;
3374 * libhal_ctx_set_device_removed:
3375 * @ctx: the context for the connection to hald
3376 * @callback: the function to call when a device is removed
3378 * Set the callback for when a device is removed.
3380 * Returns: TRUE if callback was successfully set, FALSE otherwise
3382 dbus_bool_t
3383 libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback)
3385 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3387 ctx->device_removed = callback;
3388 return TRUE;
3392 * libhal_ctx_set_device_new_capability:
3393 * @ctx: the context for the connection to hald
3394 * @callback: the function to call when a device gains a new capability
3396 * Set the callback for when a device gains a new capability.
3398 * Returns: TRUE if callback was successfully set, FALSE otherwise
3400 dbus_bool_t
3401 libhal_ctx_set_device_new_capability (LibHalContext *ctx, LibHalDeviceNewCapability callback)
3403 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3405 ctx->device_new_capability = callback;
3406 return TRUE;
3410 * libhal_ctx_set_device_lost_capability:
3411 * @ctx: the context for the connection to hald
3412 * @callback: the function to call when a device loses a capability
3414 * Set the callback for when a device loses a capability
3416 * Returns: TRUE if callback was successfully set, FALSE otherwise
3418 dbus_bool_t
3419 libhal_ctx_set_device_lost_capability (LibHalContext *ctx, LibHalDeviceLostCapability callback)
3421 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3423 ctx->device_lost_capability = callback;
3424 return TRUE;
3428 * libhal_ctx_set_device_property_modified:
3429 * @ctx: the context for the connection to hald
3430 * @callback: the function to call when a property is modified on a device
3432 * Set the callback for when a property is modified on a device.
3434 * Returns: TRUE if callback was successfully set, FALSE otherwise
3436 dbus_bool_t
3437 libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibHalDevicePropertyModified callback)
3439 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3441 ctx->device_property_modified = callback;
3442 return TRUE;
3446 * libhal_ctx_set_device_condition:
3447 * @ctx: the context for the connection to hald
3448 * @callback: the function to call when a device emits a condition
3450 * Set the callback for when a device emits a condition
3452 * Returns: TRUE if callback was successfully set, FALSE otherwise
3454 dbus_bool_t
3455 libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback)
3457 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3459 ctx->device_condition = callback;
3460 return TRUE;
3464 * libhal_string_array_length:
3465 * @str_array: array of strings to consider
3467 * Get the length of an array of strings.
3469 * Returns: Number of strings in array
3471 unsigned int
3472 libhal_string_array_length (char **str_array)
3474 unsigned int i;
3476 if (str_array == NULL)
3477 return 0;
3479 for (i = 0; str_array[i] != NULL; i++)
3482 return i;
3487 * libhal_device_rescan:
3488 * @ctx: the context for the connection to hald
3489 * @udi: the Unique id of device
3490 * @error: pointer to an initialized dbus error object for returning errors or NULL
3492 * TODO document me.
3494 * Returns: Whether the operation succeeded
3496 dbus_bool_t
3497 libhal_device_rescan (LibHalContext *ctx, const char *udi, DBusError *error)
3499 DBusMessage *message;
3500 DBusMessageIter reply_iter;
3501 DBusMessage *reply;
3502 dbus_bool_t result;
3504 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3505 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3507 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
3508 "org.freedesktop.Hal.Device",
3509 "Rescan");
3511 if (message == NULL) {
3512 fprintf (stderr,
3513 "%s %d : Couldn't allocate D-BUS message\n",
3514 __FILE__, __LINE__);
3515 return FALSE;
3518 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3519 message, -1,
3520 error);
3522 dbus_message_unref (message);
3524 if (error != NULL && dbus_error_is_set (error)) {
3525 return FALSE;
3527 if (reply == NULL)
3528 return FALSE;
3530 dbus_message_iter_init (reply, &reply_iter);
3531 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3532 DBUS_TYPE_BOOLEAN) {
3533 dbus_message_unref (reply);
3534 return FALSE;
3536 dbus_message_iter_get_basic (&reply_iter, &result);
3538 dbus_message_unref (reply);
3540 return result;
3544 * libhal_device_reprobe:
3545 * @ctx: the context for the connection to hald
3546 * @udi: the Unique id of device
3547 * @error: pointer to an initialized dbus error object for returning errors or NULL
3549 * TODO document me.
3551 * Returns: Whether the operation succeeded
3553 dbus_bool_t
3554 libhal_device_reprobe (LibHalContext *ctx, const char *udi, DBusError *error)
3556 DBusMessage *message;
3557 DBusMessageIter reply_iter;
3558 DBusMessage *reply;
3559 dbus_bool_t result;
3561 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3562 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3564 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3565 udi,
3566 "org.freedesktop.Hal.Device",
3567 "Reprobe");
3569 if (message == NULL) {
3570 fprintf (stderr,
3571 "%s %d : Couldn't allocate D-BUS message\n",
3572 __FILE__, __LINE__);
3573 return FALSE;
3576 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3577 message, -1,
3578 error);
3580 dbus_message_unref (message);
3582 if (error != NULL && dbus_error_is_set (error)) {
3583 return FALSE;
3585 if (reply == NULL)
3586 return FALSE;
3588 dbus_message_iter_init (reply, &reply_iter);
3589 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3590 DBUS_TYPE_BOOLEAN) {
3591 dbus_message_unref (reply);
3592 return FALSE;
3594 dbus_message_iter_get_basic (&reply_iter, &result);
3596 dbus_message_unref (reply);
3598 return result;
3602 * libhal_device_emit_condition:
3603 * @ctx: the context for the connection to hald
3604 * @udi: the Unique Device Id
3605 * @condition_name: user-readable name of condition
3606 * @condition_details: user-readable details of condition
3607 * @error: pointer to an initialized dbus error object for returning errors or NULL
3609 * Emit a condition from a device. Can only be used from hald helpers.
3611 * Returns: TRUE if condition successfully emitted,
3612 * FALSE otherwise
3614 dbus_bool_t libhal_device_emit_condition (LibHalContext *ctx,
3615 const char *udi,
3616 const char *condition_name,
3617 const char *condition_details,
3618 DBusError *error)
3620 DBusMessage *message;
3621 DBusMessageIter iter;
3622 DBusMessageIter reply_iter;
3623 DBusMessage *reply;
3624 dbus_bool_t result;
3626 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3627 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3628 LIBHAL_CHECK_PARAM_VALID(condition_name, "*condition_name", FALSE);
3629 LIBHAL_CHECK_PARAM_VALID(condition_details, "*condition_details", FALSE);
3631 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3632 udi,
3633 "org.freedesktop.Hal.Device",
3634 "EmitCondition");
3636 if (message == NULL) {
3637 fprintf (stderr,
3638 "%s %d : Couldn't allocate D-BUS message\n",
3639 __FILE__, __LINE__);
3640 return FALSE;
3643 dbus_message_iter_init_append (message, &iter);
3644 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_name);
3645 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_details);
3647 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3648 message, -1,
3649 error);
3651 dbus_message_unref (message);
3653 if (error != NULL && dbus_error_is_set (error)) {
3654 fprintf (stderr,
3655 "%s %d : Failure sending D-BUS message: %s: %s\n",
3656 __FILE__, __LINE__, error->name, error->message);
3657 return FALSE;
3660 if (reply == NULL) {
3661 fprintf (stderr,
3662 "%s %d : Got no reply\n",
3663 __FILE__, __LINE__);
3664 return FALSE;
3667 dbus_message_iter_init (reply, &reply_iter);
3668 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3669 DBUS_TYPE_BOOLEAN) {
3670 dbus_message_unref (reply);
3671 fprintf (stderr,
3672 "%s %d : Malformed reply\n",
3673 __FILE__, __LINE__);
3674 return FALSE;
3676 dbus_message_iter_get_basic (&reply_iter, &result);
3678 dbus_message_unref (reply);
3680 return result;
3683 /**
3684 * libhal_device_addon_is_ready:
3685 * @ctx: the context for the connection to hald
3686 * @udi: the Unique Device Id this addon is handling
3687 * @error: pointer to an initialized dbus error object for returning errors or NULL
3689 * HAL addon's must call this method when they are done initializing the device object. The HAL
3690 * daemon will wait for all addon's to call this.
3692 * Can only be used from hald helpers.
3694 * Returns: TRUE if the HAL daemon received the message, FALSE otherwise
3696 dbus_bool_t
3697 libhal_device_addon_is_ready (LibHalContext *ctx, const char *udi, DBusError *error)
3699 DBusMessage *message;
3700 DBusMessageIter iter;
3701 DBusMessageIter reply_iter;
3702 DBusMessage *reply;
3703 dbus_bool_t result;
3705 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3706 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3708 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3709 udi,
3710 "org.freedesktop.Hal.Device",
3711 "AddonIsReady");
3713 if (message == NULL) {
3714 fprintf (stderr,
3715 "%s %d : Couldn't allocate D-BUS message\n",
3716 __FILE__, __LINE__);
3717 return FALSE;
3720 dbus_message_iter_init_append (message, &iter);
3722 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3723 message, -1,
3724 error);
3726 dbus_message_unref (message);
3728 if (error != NULL && dbus_error_is_set (error)) {
3729 return FALSE;
3731 if (reply == NULL)
3732 return FALSE;
3734 dbus_message_iter_init (reply, &reply_iter);
3735 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
3736 dbus_message_unref (reply);
3737 return FALSE;
3739 dbus_message_iter_get_basic (&reply_iter, &result);
3741 dbus_message_unref (reply);
3742 return result;
3746 * libhal_device_claim_interface:
3747 * @ctx: the context for the connection to hald
3748 * @udi: the Unique Device Id
3749 * @interface_name: Name of interface to claim, e.g. org.freedesktop.Hal.Device.FoobarKindOfThing
3750 * @introspection_xml: Introspection XML containing what would be inside the interface XML tag
3751 * @error: pointer to an initialized dbus error object for returning errors or NULL
3753 * Claim an interface for a device. All messages to this interface
3754 * will be forwarded to the helper. Can only be used from hald
3755 * helpers.
3757 * Returns: TRUE if interface was claimed, FALSE otherwise
3759 dbus_bool_t
3760 libhal_device_claim_interface (LibHalContext *ctx,
3761 const char *udi,
3762 const char *interface_name,
3763 const char *introspection_xml,
3764 DBusError *error)
3766 DBusMessage *message;
3767 DBusMessageIter iter;
3768 DBusMessageIter reply_iter;
3769 DBusMessage *reply;
3770 dbus_bool_t result;
3772 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3773 LIBHAL_CHECK_UDI_VALID(udi, FALSE);
3774 LIBHAL_CHECK_PARAM_VALID(interface_name, "*interface_name", FALSE);
3776 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3777 udi,
3778 "org.freedesktop.Hal.Device",
3779 "ClaimInterface");
3781 if (message == NULL) {
3782 fprintf (stderr,
3783 "%s %d : Couldn't allocate D-BUS message\n",
3784 __FILE__, __LINE__);
3785 return FALSE;
3788 dbus_message_iter_init_append (message, &iter);
3789 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name);
3790 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &introspection_xml);
3792 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3793 message, -1,
3794 error);
3796 dbus_message_unref (message);
3798 if (error != NULL && dbus_error_is_set (error)) {
3799 return FALSE;
3801 if (reply == NULL)
3802 return FALSE;
3804 dbus_message_iter_init (reply, &reply_iter);
3805 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3806 DBUS_TYPE_BOOLEAN) {
3807 dbus_message_unref (reply);
3808 return FALSE;
3810 dbus_message_iter_get_basic (&reply_iter, &result);
3812 dbus_message_unref (reply);
3814 return result;
3819 struct LibHalChangeSetElement_s;
3821 typedef struct LibHalChangeSetElement_s LibHalChangeSetElement;
3823 struct LibHalChangeSetElement_s {
3824 char *key;
3825 int change_type;
3826 union {
3827 char *val_str;
3828 dbus_int32_t val_int;
3829 dbus_uint64_t val_uint64;
3830 double val_double;
3831 dbus_bool_t val_bool;
3832 char **val_strlist;
3833 } value;
3834 LibHalChangeSetElement *next;
3835 LibHalChangeSetElement *prev;
3838 struct LibHalChangeSet_s {
3839 char *udi;
3840 LibHalChangeSetElement *head;
3841 LibHalChangeSetElement *tail;
3845 * libhal_device_new_changeset:
3846 * @udi: unique device identifier
3848 * Request a new changeset object. Used for changing multiple properties at once. Useful when
3849 * performance is critical and also for atomically updating several properties.
3851 * Returns: A new changeset object or NULL on error
3853 LibHalChangeSet *
3854 libhal_device_new_changeset (const char *udi)
3856 LibHalChangeSet *changeset;
3858 LIBHAL_CHECK_UDI_VALID(udi, NULL);
3860 changeset = calloc (1, sizeof (LibHalChangeSet));
3861 if (changeset == NULL)
3862 goto out;
3864 changeset->udi = strdup (udi);
3865 if (changeset->udi == NULL) {
3866 free (changeset);
3867 changeset = NULL;
3868 goto out;
3871 changeset->head = NULL;
3872 changeset->tail = NULL;
3874 out:
3875 return changeset;
3878 static void
3879 libhal_changeset_append (LibHalChangeSet *changeset, LibHalChangeSetElement *elem)
3881 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", );
3882 LIBHAL_CHECK_PARAM_VALID(elem, "*elem", );
3884 if (changeset->head == NULL) {
3885 changeset->head = elem;
3886 changeset->tail = elem;
3887 elem->next = NULL;
3888 elem->prev = NULL;
3889 } else {
3890 elem->prev = changeset->tail;
3891 elem->next = NULL;
3892 elem->prev->next = elem;
3893 changeset->tail = elem;
3899 * libhal_changeset_set_property_string:
3900 * @changeset: the changeset
3901 * @key: key of property
3902 * @value: the value to set
3904 * Set a property.
3906 * Returns: FALSE on OOM
3908 dbus_bool_t
3909 libhal_changeset_set_property_string (LibHalChangeSet *changeset, const char *key, const char *value)
3911 LibHalChangeSetElement *elem;
3913 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
3914 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
3915 LIBHAL_CHECK_PARAM_VALID(value, "*value", FALSE);
3917 elem = calloc (1, sizeof (LibHalChangeSetElement));
3918 if (elem == NULL)
3919 goto out;
3920 elem->key = strdup (key);
3921 if (elem->key == NULL) {
3922 free (elem);
3923 elem = NULL;
3924 goto out;
3927 elem->change_type = LIBHAL_PROPERTY_TYPE_STRING;
3928 elem->value.val_str = strdup (value);
3929 if (elem->value.val_str == NULL) {
3930 free (elem->key);
3931 free (elem);
3932 elem = NULL;
3933 goto out;
3936 libhal_changeset_append (changeset, elem);
3937 out:
3938 return elem != NULL;
3942 * libhal_changeset_set_property_int:
3943 * @changeset: the changeset
3944 * @key: key of property
3945 * @value: the value to set
3947 * Set a property.
3949 * Returns: FALSE on OOM
3951 dbus_bool_t
3952 libhal_changeset_set_property_int (LibHalChangeSet *changeset, const char *key, dbus_int32_t value)
3954 LibHalChangeSetElement *elem;
3956 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
3957 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
3959 elem = calloc (1, sizeof (LibHalChangeSetElement));
3960 if (elem == NULL)
3961 goto out;
3962 elem->key = strdup (key);
3963 if (elem->key == NULL) {
3964 free (elem);
3965 elem = NULL;
3966 goto out;
3969 elem->change_type = LIBHAL_PROPERTY_TYPE_INT32;
3970 elem->value.val_int = value;
3972 libhal_changeset_append (changeset, elem);
3973 out:
3974 return elem != NULL;
3978 * libhal_changeset_set_property_uint64:
3979 * @changeset: the changeset
3980 * @key: key of property
3981 * @value: the value to set
3983 * Set a property.
3985 * Returns: FALSE on OOM
3987 dbus_bool_t
3988 libhal_changeset_set_property_uint64 (LibHalChangeSet *changeset, const char *key, dbus_uint64_t value)
3990 LibHalChangeSetElement *elem;
3992 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
3993 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
3995 elem = calloc (1, sizeof (LibHalChangeSetElement));
3996 if (elem == NULL)
3997 goto out;
3998 elem->key = strdup (key);
3999 if (elem->key == NULL) {
4000 free (elem);
4001 elem = NULL;
4002 goto out;
4005 elem->change_type = LIBHAL_PROPERTY_TYPE_UINT64;
4006 elem->value.val_uint64 = value;
4008 libhal_changeset_append (changeset, elem);
4009 out:
4010 return elem != NULL;
4014 * libhal_changeset_set_property_double:
4015 * @changeset: the changeset
4016 * @key: key of property
4017 * @value: the value to set
4019 * Set a property.
4021 * Returns: FALSE on OOM
4023 dbus_bool_t
4024 libhal_changeset_set_property_double (LibHalChangeSet *changeset, const char *key, double value)
4026 LibHalChangeSetElement *elem;
4028 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
4029 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
4031 elem = calloc (1, sizeof (LibHalChangeSetElement));
4032 if (elem == NULL)
4033 goto out;
4034 elem->key = strdup (key);
4035 if (elem->key == NULL) {
4036 free (elem);
4037 elem = NULL;
4038 goto out;
4041 elem->change_type = LIBHAL_PROPERTY_TYPE_DOUBLE;
4042 elem->value.val_double = value;
4044 libhal_changeset_append (changeset, elem);
4045 out:
4046 return elem != NULL;
4050 * libhal_changeset_set_property_bool:
4051 * @changeset: the changeset
4052 * @key: key of property
4053 * @value: the value to set
4055 * Set a property.
4057 * Returns: FALSE on OOM
4059 dbus_bool_t
4060 libhal_changeset_set_property_bool (LibHalChangeSet *changeset, const char *key, dbus_bool_t value)
4062 LibHalChangeSetElement *elem;
4064 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
4065 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
4067 elem = calloc (1, sizeof (LibHalChangeSetElement));
4068 if (elem == NULL)
4069 goto out;
4070 elem->key = strdup (key);
4071 if (elem->key == NULL) {
4072 free (elem);
4073 elem = NULL;
4074 goto out;
4077 elem->change_type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
4078 elem->value.val_bool = value;
4080 libhal_changeset_append (changeset, elem);
4081 out:
4082 return elem != NULL;
4086 * libhal_changeset_set_property_strlist:
4087 * @changeset: the changeset
4088 * @key: key of property
4089 * @value: the value to set - NULL terminated array of strings
4091 * Set a property.
4093 * Returns: FALSE on OOM
4095 dbus_bool_t
4096 libhal_changeset_set_property_strlist (LibHalChangeSet *changeset, const char *key, const char **value)
4098 LibHalChangeSetElement *elem;
4099 char **value_copy;
4100 int len;
4101 int i, j;
4103 LIBHAL_CHECK_PARAM_VALID(changeset, "*changeset", FALSE);
4104 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
4106 elem = calloc (1, sizeof (LibHalChangeSetElement));
4107 if (elem == NULL)
4108 goto out;
4109 elem->key = strdup (key);
4110 if (elem->key == NULL) {
4111 free (elem);
4112 elem = NULL;
4113 goto out;
4116 for (i = 0; value[i] != NULL; i++)
4118 len = i;
4120 value_copy = calloc (len + 1, sizeof (char *));
4121 if (value_copy == NULL) {
4122 free (elem->key);
4123 free (elem);
4124 elem = NULL;
4125 goto out;
4128 for (i = 0; i < len; i++) {
4129 value_copy[i] = strdup (value[i]);
4130 if (value_copy[i] == NULL) {
4131 for (j = 0; j < i; j++) {
4132 free (value_copy[j]);
4134 free (value_copy);
4135 free (elem->key);
4136 free (elem);
4137 elem = NULL;
4138 goto out;
4141 value_copy[i] = NULL;
4143 elem->change_type = LIBHAL_PROPERTY_TYPE_STRLIST;
4144 elem->value.val_strlist = value_copy;
4146 libhal_changeset_append (changeset, elem);
4147 out:
4148 return elem != NULL;
4152 * libhal_device_commit_changeset:
4153 * @ctx: the context for the connection to hald
4154 * @changeset: the changeset to commit
4155 * @error: pointer to an initialized dbus error object for returning errors or NULL
4157 * Commit a changeset to the daemon.
4159 * Returns: True if the changeset was committed on the daemon side
4161 dbus_bool_t
4162 libhal_device_commit_changeset (LibHalContext *ctx, LibHalChangeSet *changeset, DBusError *error)
4164 LibHalChangeSetElement *elem;
4165 DBusMessage *message;
4166 DBusMessage *reply;
4167 DBusError _error;
4168 DBusMessageIter iter;
4169 DBusMessageIter sub;
4170 DBusMessageIter sub2;
4171 DBusMessageIter sub3;
4172 DBusMessageIter sub4;
4173 int i;
4175 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
4176 LIBHAL_CHECK_UDI_VALID(changeset->udi, FALSE);
4178 if (changeset->head == NULL) {
4179 return TRUE;
4182 message = dbus_message_new_method_call ("org.freedesktop.Hal", changeset->udi,
4183 "org.freedesktop.Hal.Device",
4184 "SetMultipleProperties");
4186 if (message == NULL) {
4187 fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
4188 return FALSE;
4191 dbus_message_iter_init_append (message, &iter);
4193 dbus_message_iter_open_container (&iter,
4194 DBUS_TYPE_ARRAY,
4195 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
4196 DBUS_TYPE_STRING_AS_STRING
4197 DBUS_TYPE_VARIANT_AS_STRING
4198 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
4199 &sub);
4201 for (elem = changeset->head; elem != NULL; elem = elem->next) {
4202 dbus_message_iter_open_container (&sub,
4203 DBUS_TYPE_DICT_ENTRY,
4204 NULL,
4205 &sub2);
4206 dbus_message_iter_append_basic (&sub2, DBUS_TYPE_STRING, &(elem->key));
4208 switch (elem->change_type) {
4209 case LIBHAL_PROPERTY_TYPE_STRING:
4210 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub3);
4211 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_STRING, &(elem->value.val_str));
4212 dbus_message_iter_close_container (&sub2, &sub3);
4213 break;
4214 case LIBHAL_PROPERTY_TYPE_STRLIST:
4215 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT,
4216 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, &sub3);
4217 dbus_message_iter_open_container (&sub3, DBUS_TYPE_ARRAY,
4218 DBUS_TYPE_STRING_AS_STRING, &sub4);
4219 for (i = 0; elem->value.val_strlist[i] != NULL; i++) {
4220 dbus_message_iter_append_basic (&sub4, DBUS_TYPE_STRING,
4221 &(elem->value.val_strlist[i]));
4223 dbus_message_iter_close_container (&sub3, &sub4);
4224 dbus_message_iter_close_container (&sub2, &sub3);
4225 break;
4226 case LIBHAL_PROPERTY_TYPE_INT32:
4227 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub3);
4228 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_INT32, &(elem->value.val_int));
4229 dbus_message_iter_close_container (&sub2, &sub3);
4230 break;
4231 case LIBHAL_PROPERTY_TYPE_UINT64:
4232 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_UINT64_AS_STRING, &sub3);
4233 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_UINT64, &(elem->value.val_uint64));
4234 dbus_message_iter_close_container (&sub2, &sub3);
4235 break;
4236 case LIBHAL_PROPERTY_TYPE_DOUBLE:
4237 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub3);
4238 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_DOUBLE, &(elem->value.val_double));
4239 dbus_message_iter_close_container (&sub2, &sub3);
4240 break;
4241 case LIBHAL_PROPERTY_TYPE_BOOLEAN:
4242 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING,&sub3);
4243 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_BOOLEAN, &(elem->value.val_bool));
4244 dbus_message_iter_close_container (&sub2, &sub3);
4245 break;
4246 default:
4247 fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
4248 break;
4250 dbus_message_iter_close_container (&sub, &sub2);
4253 dbus_message_iter_close_container (&iter, &sub);
4256 dbus_error_init (&_error);
4257 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
4258 message, -1,
4259 &_error);
4261 dbus_message_unref (message);
4263 dbus_move_error (&_error, error);
4264 if (error != NULL && dbus_error_is_set (error)) {
4265 fprintf (stderr,
4266 "%s %d : %s\n",
4267 __FILE__, __LINE__, error->message);
4269 return FALSE;
4271 if (reply == NULL) {
4272 return FALSE;
4275 dbus_message_unref (reply);
4276 return TRUE;
4280 * libhal_device_free_changeset:
4281 * @changeset: the changeset to free
4283 * Free a changeset.
4285 void
4286 libhal_device_free_changeset (LibHalChangeSet *changeset)
4288 LibHalChangeSetElement *elem;
4289 LibHalChangeSetElement *elem2;
4291 for (elem = changeset->head; elem != NULL; elem = elem2) {
4292 elem2 = elem->next;
4294 switch (elem->change_type) {
4295 case LIBHAL_PROPERTY_TYPE_STRING:
4296 free (elem->value.val_str);
4297 break;
4298 case LIBHAL_PROPERTY_TYPE_STRLIST:
4299 libhal_free_string_array (elem->value.val_strlist);
4300 break;
4301 /* explicit fallthrough */
4302 case LIBHAL_PROPERTY_TYPE_INT32:
4303 case LIBHAL_PROPERTY_TYPE_UINT64:
4304 case LIBHAL_PROPERTY_TYPE_DOUBLE:
4305 case LIBHAL_PROPERTY_TYPE_BOOLEAN:
4306 break;
4307 default:
4308 fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
4309 break;
4311 free (elem->key);
4312 free (elem);
4315 free (changeset->udi);
4316 free (changeset);