1 /***************************************************************************
2 * CVSID: $Id$
3 *
4 * libhal.c : HAL daemon C convenience library
5 *
6 * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
7 * Copyright (C) 2007 Codethink Ltd. Author Rob Taylor <rob.taylor@codethink.co.uk>
8 *
9 * Licensed under the Academic Free License version 2.1
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 *
25 **************************************************************************/
26
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <dbus/dbus.h>
35
36 #include "libhal.h"
37
38 #ifdef ENABLE_NLS
39 # include <libintl.h>
40 # define _(String) dgettext (GETTEXT_PACKAGE, String)
41 # ifdef gettext_noop
42 # define N_(String) gettext_noop (String)
43 # else
44 # define N_(String) (String)
45 # endif
46 #else
47 /* Stubs that do something close enough. */
48 # define textdomain(String) (String)
49 # define gettext(String) (String)
50 # define dgettext(Domain,Message) (Message)
51 # define dcgettext(Domain,Message,Type) (Message)
52 # define bindtextdomain(Domain,Directory) (Domain)
53 # define _(String)
54 # define N_(String) (String)
55 #endif
56
57 /**
58 * LIBHAL_CHECK_PARAM_VALID:
59 * @_param_: the prameter to check for
60 * @_name_: the name of the prameter (for debug output)
61 * @_ret_: what to use for return value if the prameter is NULL
62 *
63 * Handy macro for checking whether a parameter is valid and not NULL.
64 */
65 #define LIBHAL_CHECK_PARAM_VALID(_param_,_name_,_ret_) \
66 do { \
67 if (_param_ == NULL) { \
68 fprintf (stderr, \
69 "%s %d : invalid paramater. %s is NULL.\n", \
70 __FILE__, __LINE__, _name_); \
71 return _ret_; \
72 } \
73 } while(0)
74
75
76 static char **libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements);
77
78 static dbus_bool_t libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter);
79
80
81
82 /**
83 * libhal_free_string_array:
84 * @str_array: the array to be freed
85 *
86 * Frees a NULL-terminated array of strings. If passed NULL, does nothing.
87 */
88 void
libhal_free_string_array(char ** str_array)89 libhal_free_string_array (char **str_array)
90 {
91 if (str_array != NULL) {
92 int i;
93
94 for (i = 0; str_array[i] != NULL; i++) {
95 free (str_array[i]);
96 str_array[i] = NULL;
97 }
98 free (str_array);
99 str_array = NULL;
100 }
101 }
102
103
104 /**
105 * libhal_get_string_array_from_iter:
106 * @iter: the message iterator to extract the strings from
107 * @num_elements: pointer to an integer where to store number of elements (can be NULL)
108 *
109 * Creates a NULL terminated array of strings from a dbus message iterator.
110 *
111 * Returns: pointer to the string array
112 */
113 static char **
libhal_get_string_array_from_iter(DBusMessageIter * iter,int * num_elements)114 libhal_get_string_array_from_iter (DBusMessageIter *iter, int *num_elements)
115 {
116 int count;
117 char **buffer;
118
119 count = 0;
120 buffer = (char **)malloc (sizeof (char *) * 8);
121
122 if (buffer == NULL)
123 goto oom;
124
125 buffer[0] = NULL;
126 while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING) {
127 const char *value;
128 char *str;
129
130 if ((count % 8) == 0 && count != 0) {
131 buffer = realloc (buffer, sizeof (char *) * (count + 8));
132 if (buffer == NULL)
133 goto oom;
134 }
135
136 dbus_message_iter_get_basic (iter, &value);
137 str = strdup (value);
138 if (str == NULL)
139 goto oom;
140
141 buffer[count] = str;
142
143 dbus_message_iter_next(iter);
144 count++;
145 }
146
147 if ((count % 8) == 0) {
148 buffer = realloc (buffer, sizeof (char *) * (count + 1));
149 if (buffer == NULL)
150 goto oom;
151 }
152
153 buffer[count] = NULL;
154 if (num_elements != NULL)
155 *num_elements = count;
156 return buffer;
157
158 oom:
159 fprintf (stderr, "%s %d : error allocating memory\n", __FILE__, __LINE__);
160 return NULL;
161
162 }
163
164 /**
165 * libhal_free_string:
166 * @str: the nul-terminated sting to free
167 *
168 * Used to free strings returned by libhal.
169 */
170 void
libhal_free_string(char * str)171 libhal_free_string (char *str)
172 {
173 if (str != NULL) {
174 free (str);
175 str = NULL;
176 }
177 }
178
179
180 /**
181 * LibHalPropertySet:
182 *
183 * Represents a set of properties. Opaque; use the
184 * libhal_property_set_*() family of functions to access it.
185 */
186 struct LibHalPropertySet_s {
187 unsigned int num_properties; /**< Number of properties in set */
188 LibHalProperty *properties_head;
189 /**< Pointer to first property or NULL
190 * if there are no properties */
191 };
192
193 /**
194 * LibHalProperty:
195 *
196 * Represents a property. Opaque.
197 */
198 struct LibHalProperty_s {
199 int type; /**< Type of property */
200 char *key; /**< ASCII string */
201
202 /** Possible values of the property */
203 union {
204 char *str_value; /**< UTF-8 zero-terminated string */
205 dbus_int32_t int_value;
206 /**< 32-bit signed integer */
207 dbus_uint64_t uint64_value;
208 /**< 64-bit unsigned integer */
209 double double_value; /**< IEEE754 double precision float */
210 dbus_bool_t bool_value;
211 /**< Truth value */
212
213 char **strlist_value; /**< List of UTF-8 zero-terminated strings */
214 } v;
215
216 LibHalProperty *next; /**< Next property or NULL if this is
217 * the last */
218 };
219
220 /**
221 * LibHalContext:
222 *
223 * Context for connection to the HAL daemon. Opaque, use the
224 * libhal_ctx_*() family of functions to access it.
225 */
226 struct LibHalContext_s {
227 DBusConnection *connection; /**< D-BUS connection */
228 dbus_bool_t is_initialized; /**< Are we initialised */
229 dbus_bool_t is_shutdown; /**< Have we been shutdown */
230 dbus_bool_t cache_enabled; /**< Is the cache enabled */
231 dbus_bool_t is_direct; /**< Whether the connection to hald is direct */
232
233 /** Device added */
234 LibHalDeviceAdded device_added;
235
236 /** Device removed */
237 LibHalDeviceRemoved device_removed;
238
239 /** Device got a new capability */
240 LibHalDeviceNewCapability device_new_capability;
241
242 /** Device got a new capability */
243 LibHalDeviceLostCapability device_lost_capability;
244
245 /** A property of a device changed */
246 LibHalDevicePropertyModified device_property_modified;
247
248 /** A non-continous event on the device occured */
249 LibHalDeviceCondition device_condition;
250
251 void *user_data; /**< User data */
252 };
253
254 /**
255 * libhal_ctx_set_user_data:
256 * @ctx: the context for the connection to hald
257 * @user_data: user data
258 *
259 * Set user data for the context.
260 *
261 * Returns: TRUE if user data was successfully set, FALSE if otherwise
262 */
263 dbus_bool_t
libhal_ctx_set_user_data(LibHalContext * ctx,void * user_data)264 libhal_ctx_set_user_data(LibHalContext *ctx, void *user_data)
265 {
266 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
267 ctx->user_data = user_data;
268 return TRUE;
269 }
270
271 /**
272 * libhal_ctx_get_user_data:
273 * @ctx: the context for the connection to hald
274 *
275 * Get user data for the context.
276 *
277 * Returns: opaque pointer stored through libhal_ctx_set_user_data() or NULL if not set.
278 */
279 void*
libhal_ctx_get_user_data(LibHalContext * ctx)280 libhal_ctx_get_user_data(LibHalContext *ctx)
281 {
282 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
283 return ctx->user_data;
284 }
285
286
287 /**
288 * libhal_property_fill_value_from_variant:
289 * @p: the property to fill in
290 * @var_iter: variant iterator to extract the value from
291 *
292 * Fills in the value for the LibHalProperty given a variant iterator.
293 *
294 * Returns: Whether the value was put in.
295 */
296 static dbus_bool_t
libhal_property_fill_value_from_variant(LibHalProperty * p,DBusMessageIter * var_iter)297 libhal_property_fill_value_from_variant (LibHalProperty *p, DBusMessageIter *var_iter)
298 {
299 DBusMessageIter iter_array;
300 switch (p->type) {
301 case DBUS_TYPE_ARRAY:
302 if (dbus_message_iter_get_element_type (var_iter) != DBUS_TYPE_STRING)
303 return FALSE;
304
305 dbus_message_iter_recurse (var_iter, &iter_array);
306 p->v.strlist_value = libhal_get_string_array_from_iter (&iter_array, NULL);
307
308 p->type = LIBHAL_PROPERTY_TYPE_STRLIST;
309
310 break;
311 case DBUS_TYPE_STRING:
312 {
313 const char *v;
314
315 dbus_message_iter_get_basic (var_iter, &v);
316
317 p->v.str_value = strdup (v);
318 if (p->v.str_value == NULL)
319 return FALSE;
320 p->type = LIBHAL_PROPERTY_TYPE_STRING;
321
322 break;
323 }
324 case DBUS_TYPE_INT32:
325 {
326 dbus_int32_t v;
327
328 dbus_message_iter_get_basic (var_iter, &v);
329
330 p->v.int_value = v;
331 p->type = LIBHAL_PROPERTY_TYPE_INT32;
332
333 break;
334 }
335 case DBUS_TYPE_UINT64:
336 {
337 dbus_uint64_t v;
338
339 dbus_message_iter_get_basic (var_iter, &v);
340
341 p->v.uint64_value = v;
342 p->type = LIBHAL_PROPERTY_TYPE_UINT64;
343
344 break;
345 }
346 case DBUS_TYPE_DOUBLE:
347 {
348 double v;
349
350 dbus_message_iter_get_basic (var_iter, &v);
351
352 p->v.double_value = v;
353 p->type = LIBHAL_PROPERTY_TYPE_DOUBLE;
354
355 break;
356 }
357 case DBUS_TYPE_BOOLEAN:
358 {
359 double v;
360
361 dbus_message_iter_get_basic (var_iter, &v);
362
363 p->v.double_value = v;
364 p->type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
365
366 break;
367 }
368 default:
369 /** @todo report error */
370 break;
371 }
372
373 return TRUE;
374 }
375
376 /**
377 * libhal_device_get_all_properties:
378 * @ctx: the context for the connection to hald
379 * @udi: the Unique id of device
380 * @error: pointer to an initialized dbus error object for returning errors or NULL
381 *
382 * Retrieve all the properties on a device.
383 *
384 * Returns: An object represent all properties. Must be freed with libhal_free_property_set().
385 */
386 LibHalPropertySet *
libhal_device_get_all_properties(LibHalContext * ctx,const char * udi,DBusError * error)387 libhal_device_get_all_properties (LibHalContext *ctx, const char *udi, DBusError *error)
388 {
389 DBusMessage *message;
390 DBusMessage *reply;
391 DBusMessageIter reply_iter;
392 DBusMessageIter dict_iter;
393 LibHalPropertySet *result;
394 LibHalProperty *p_last;
395 DBusError _error;
396
397 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
398
399 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
400 "org.freedesktop.Hal.Device",
401 "GetAllProperties");
402
403 if (message == NULL) {
404 fprintf (stderr,
405 "%s %d : Couldn't allocate D-BUS message\n",
406 __FILE__, __LINE__);
407 return NULL;
408 }
409
410 dbus_error_init (&_error);
411 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
412 message, -1,
413 &_error);
414
415 dbus_move_error (&_error, error);
416 if (error != NULL && dbus_error_is_set (error)) {
417 fprintf (stderr,
418 "%s %d : %s\n",
419 __FILE__, __LINE__, error->message);
420
421 dbus_message_unref (message);
422 return NULL;
423 }
424
425 if (reply == NULL) {
426 dbus_message_unref (message);
427 return NULL;
428 }
429
430 dbus_message_iter_init (reply, &reply_iter);
431
432 result = malloc (sizeof (LibHalPropertySet));
433 if (result == NULL)
434 goto oom;
435 /*
436 result->properties = malloc(sizeof(LibHalProperty)*result->num_properties);
437 if( result->properties==NULL )
438 {
439 /// @todo cleanup
440 return NULL;
441 }
442 */
443
444 result->properties_head = NULL;
445 result->num_properties = 0;
446
447 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY &&
448 dbus_message_iter_get_element_type (&reply_iter) != DBUS_TYPE_DICT_ENTRY) {
449 fprintf (stderr, "%s %d : error, expecting an array of dict entries\n",
450 __FILE__, __LINE__);
451 dbus_message_unref (message);
452 dbus_message_unref (reply);
453 return NULL;
454 }
455
456 dbus_message_iter_recurse (&reply_iter, &dict_iter);
457
458 p_last = NULL;
459
460 while (dbus_message_iter_get_arg_type (&dict_iter) == DBUS_TYPE_DICT_ENTRY)
461 {
462 DBusMessageIter dict_entry_iter, var_iter;
463 const char *key;
464 LibHalProperty *p;
465
466 dbus_message_iter_recurse (&dict_iter, &dict_entry_iter);
467
468 dbus_message_iter_get_basic (&dict_entry_iter, &key);
469
470 p = malloc (sizeof (LibHalProperty));
471 if (p == NULL)
472 goto oom;
473
474 p->next = NULL;
475
476 if (result->num_properties == 0)
477 result->properties_head = p;
478
479 if (p_last != NULL)
480 p_last->next = p;
481
482 p_last = p;
483
484 p->key = strdup (key);
485 if (p->key == NULL)
486 goto oom;
487
488 dbus_message_iter_next (&dict_entry_iter);
489
490 dbus_message_iter_recurse (&dict_entry_iter, &var_iter);
491
492
493 p->type = dbus_message_iter_get_arg_type (&var_iter);
494
495 result->num_properties++;
496
497 if(!libhal_property_fill_value_from_variant (p, &var_iter))
498 goto oom;
499
500 dbus_message_iter_next (&dict_iter);
501 }
502
503 dbus_message_unref (message);
504 dbus_message_unref (reply);
505
506 return result;
507
508 oom:
509 fprintf (stderr,
510 "%s %d : error allocating memory\n",
511 __FILE__, __LINE__);
512 /** @todo FIXME cleanup */
513 return NULL;
514 }
515
516 /**
517 * libhal_free_property_set:
518 * @set: property-set to free
519 *
520 * Free a property set earlier obtained with libhal_device_get_all_properties().
521 */
522 void
libhal_free_property_set(LibHalPropertySet * set)523 libhal_free_property_set (LibHalPropertySet * set)
524 {
525 LibHalProperty *p;
526 LibHalProperty *q;
527
528 if (set == NULL)
529 return;
530
531 for (p = set->properties_head; p != NULL; p = q) {
532 free (p->key);
533 if (p->type == DBUS_TYPE_STRING)
534 free (p->v.str_value);
535 if (p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
536 libhal_free_string_array (p->v.strlist_value);
537 q = p->next;
538 free (p);
539 }
540 free (set);
541 }
542
543 /**
544 * libhal_property_set_get_num_elems:
545 * @set: property set to consider
546 *
547 * Get the number of properties in a property set.
548 *
549 * Returns: number of properties in given property set
550 */
551 unsigned int
libhal_property_set_get_num_elems(LibHalPropertySet * set)552 libhal_property_set_get_num_elems (LibHalPropertySet *set)
553 {
554 unsigned int num_elems;
555 LibHalProperty *p;
556
557 if (set == NULL)
558 return 0;
559
560 num_elems = 0;
561 for (p = set->properties_head; p != NULL; p = p->next)
562 num_elems++;
563
564 return num_elems;
565 }
566
567 static LibHalProperty *
property_set_lookup(const LibHalPropertySet * set,const char * key)568 property_set_lookup (const LibHalPropertySet *set, const char *key)
569 {
570 LibHalProperty *p;
571
572 LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
573 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
574
575 for (p = set->properties_head; p != NULL; p = p->next)
576 if (strcmp (key, p->key) == 0)
577 return p;
578
579 return NULL;
580 }
581
582 /**
583 * libhal_ps_get_type:
584 * @set: property set
585 * @key: name of property to inspect
586 *
587 * Get the type of a given property.
588 *
589 * Returns: the #LibHalPropertyType of the given property,
590 * LIBHAL_PROPERTY_TYPE_INVALID if property is not in the set
591 */
592 LibHalPropertyType
libhal_ps_get_type(const LibHalPropertySet * set,const char * key)593 libhal_ps_get_type (const LibHalPropertySet *set, const char *key)
594 {
595 LibHalProperty *p = property_set_lookup (set, key);
596
597 LIBHAL_CHECK_PARAM_VALID(set, "*set", LIBHAL_PROPERTY_TYPE_INVALID);
598 LIBHAL_CHECK_PARAM_VALID(key, "*key", LIBHAL_PROPERTY_TYPE_INVALID);
599
600 p = property_set_lookup (set, key);
601 if (p) return p->type;
602 else return LIBHAL_PROPERTY_TYPE_INVALID;
603 }
604
605 /**
606 * libhal_ps_get_string:
607 * @set: property set
608 * @key: name of property to inspect
609 *
610 * Get the value of a property of type string.
611 *
612 * Returns: UTF8 nul-terminated string. This pointer is only valid
613 * until libhal_free_property_set() is invoked on the property set
614 * this property belongs to. NULL if property is not in the set or not a string
615 */
616 const char *
libhal_ps_get_string(const LibHalPropertySet * set,const char * key)617 libhal_ps_get_string (const LibHalPropertySet *set, const char *key)
618 {
619 LibHalProperty *p;
620
621 LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
622 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
623
624 p = property_set_lookup (set, key);
625 if (p && p->type == LIBHAL_PROPERTY_TYPE_STRING)
626 return p->v.str_value;
627 else return NULL;
628 }
629
630 /**
631 * libhal_ps_get_int:
632 * @set: property set
633 * @key: name of property to inspect
634 *
635 * Get the value of a property of type signed integer.
636 *
637 * Returns: property value (32-bit signed integer)
638 */
639 dbus_int32_t
libhal_ps_get_int32(const LibHalPropertySet * set,const char * key)640 libhal_ps_get_int32 (const LibHalPropertySet *set, const char *key)
641 {
642 LibHalProperty *p;
643
644 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
645 LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
646
647 p = property_set_lookup (set, key);
648 if (p && p->type == LIBHAL_PROPERTY_TYPE_INT32)
649 return p->v.int_value;
650 else return 0;
651 }
652
653 /**
654 * libhal_ps_get_uint64:
655 * @set: property set
656 * @key: name of property to inspect
657 *
658 * Get the value of a property of type unsigned integer.
659 *
660 * Returns: property value (64-bit unsigned integer)
661 */
662 dbus_uint64_t
libhal_ps_get_uint64(const LibHalPropertySet * set,const char * key)663 libhal_ps_get_uint64 (const LibHalPropertySet *set, const char *key)
664 {
665 LibHalProperty *p;
666
667 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0);
668 LIBHAL_CHECK_PARAM_VALID(key, "*key", 0);
669
670 p = property_set_lookup (set, key);
671 if (p && p->type == LIBHAL_PROPERTY_TYPE_UINT64)
672 return p->v.uint64_value;
673 else return 0;
674 }
675
676 /**
677 * libhal_ps_get_double:
678 * @set: property set
679 * @key: name of property to inspect
680 *
681 * Get the value of a property of type double.
682 *
683 * Returns: property value (IEEE754 double precision float)
684 */
685 double
libhal_ps_get_double(const LibHalPropertySet * set,const char * key)686 libhal_ps_get_double (const LibHalPropertySet *set, const char *key)
687 {
688 LibHalProperty *p;
689
690 LIBHAL_CHECK_PARAM_VALID(set, "*set", 0.0);
691 LIBHAL_CHECK_PARAM_VALID(key, "*key", 0.0);
692
693 p = property_set_lookup (set, key);
694 if (p && p->type == LIBHAL_PROPERTY_TYPE_DOUBLE)
695 return p->v.double_value;
696 else return 0.0;
697 }
698
699 /**
700 * libhal_ps_get_bool:
701 * @set: property set
702 * @key: name of property to inspect
703 *
704 * Get the value of a property of type bool.
705 *
706 * Returns: property value (bool)
707 */
708 dbus_bool_t
libhal_ps_get_bool(const LibHalPropertySet * set,const char * key)709 libhal_ps_get_bool (const LibHalPropertySet *set, const char *key)
710 {
711 LibHalProperty *p;
712
713 LIBHAL_CHECK_PARAM_VALID(set, "*set", FALSE);
714 LIBHAL_CHECK_PARAM_VALID(key, "*key", FALSE);
715
716 p = property_set_lookup (set, key);
717 if (p && p->type == LIBHAL_PROPERTY_TYPE_BOOLEAN)
718 return p->v.bool_value;
719 else return FALSE;
720 }
721
722 /**
723 * libhal_ps_get_strlist:
724 * @set: property set
725 * @key: name of property to inspect
726 *
727 * Get the value of a property of type string list.
728 *
729 * Returns: pointer to array of strings, this is owned by the property set
730 */
731 const char *const *
libhal_ps_get_strlist(const LibHalPropertySet * set,const char * key)732 libhal_ps_get_strlist (const LibHalPropertySet *set, const char *key)
733 {
734 LibHalProperty *p;
735
736 LIBHAL_CHECK_PARAM_VALID(set, "*set", NULL);
737 LIBHAL_CHECK_PARAM_VALID(key, "*key", NULL);
738
739 p = property_set_lookup (set, key);
740 if (p && p->type == LIBHAL_PROPERTY_TYPE_STRLIST)
741 return (const char *const *) p->v.strlist_value;
742 else return NULL;
743 }
744
745
746 /**
747 * libhal_psi_init:
748 * @iter: iterator object
749 * @set: property set to iterate over
750 *
751 * Initialize a property set iterator.
752 *
753 */
754 void
libhal_psi_init(LibHalPropertySetIterator * iter,LibHalPropertySet * set)755 libhal_psi_init (LibHalPropertySetIterator * iter, LibHalPropertySet * set)
756 {
757 if (set == NULL)
758 return;
759
760 iter->set = set;
761 iter->idx = 0;
762 iter->cur_prop = set->properties_head;
763 }
764
765
766 /**
767 * libhal_psi_has_more:
768 * @iter: iterator object
769 *
770 * Determine whether there are more properties to iterate over.
771 *
772 * Returns: TRUE if there are more properties, FALSE otherwise.
773 */
774 dbus_bool_t
libhal_psi_has_more(LibHalPropertySetIterator * iter)775 libhal_psi_has_more (LibHalPropertySetIterator * iter)
776 {
777 return iter->idx < iter->set->num_properties;
778 }
779
780 /**
781 * libhal_psi_next:
782 * @iter: iterator object
783 *
784 * Advance iterator to next property.
785 */
786 void
libhal_psi_next(LibHalPropertySetIterator * iter)787 libhal_psi_next (LibHalPropertySetIterator * iter)
788 {
789 iter->idx++;
790 iter->cur_prop = iter->cur_prop->next;
791 }
792
793 /**
794 * libhal_psi_get_type:
795 * @iter: iterator object
796 *
797 * Get type of property.
798 *
799 * Returns: the property type at the iterator's position
800 */
801 LibHalPropertyType
libhal_psi_get_type(LibHalPropertySetIterator * iter)802 libhal_psi_get_type (LibHalPropertySetIterator * iter)
803 {
804 return iter->cur_prop->type;
805 }
806
807 /**
808 * libhal_psi_get_key:
809 * @iter: iterator object
810 *
811 * Get the key of a property.
812 *
813 * Returns: ASCII nul-terminated string. This pointer is only valid
814 * until libhal_free_property_set() is invoked on the property set
815 * this property belongs to.
816 */
817 char *
libhal_psi_get_key(LibHalPropertySetIterator * iter)818 libhal_psi_get_key (LibHalPropertySetIterator * iter)
819 {
820 return iter->cur_prop->key;
821 }
822
823 /**
824 * libhal_psi_get_string:
825 * @iter: iterator object
826 *
827 * Get the value of a property of type string.
828 *
829 * Returns: UTF8 nul-terminated string. This pointer is only valid
830 * until libhal_free_property_set() is invoked on the property set
831 * this property belongs to.
832 */
833 char *
libhal_psi_get_string(LibHalPropertySetIterator * iter)834 libhal_psi_get_string (LibHalPropertySetIterator * iter)
835 {
836 return iter->cur_prop->v.str_value;
837 }
838
839 /**
840 * libhal_psi_get_int:
841 * @iter: iterator object
842 *
843 * Get the value of a property of type signed integer.
844 *
845 * Returns: property value (32-bit signed integer)
846 */
847 dbus_int32_t
libhal_psi_get_int(LibHalPropertySetIterator * iter)848 libhal_psi_get_int (LibHalPropertySetIterator * iter)
849 {
850 return iter->cur_prop->v.int_value;
851 }
852
853 /**
854 * libhal_psi_get_uint64:
855 * @iter: iterator object
856 *
857 * Get the value of a property of type unsigned integer.
858 *
859 * Returns: property value (64-bit unsigned integer)
860 */
861 dbus_uint64_t
libhal_psi_get_uint64(LibHalPropertySetIterator * iter)862 libhal_psi_get_uint64 (LibHalPropertySetIterator * iter)
863 {
864 return iter->cur_prop->v.uint64_value;
865 }
866
867 /**
868 * libhal_psi_get_double:
869 * @iter: iterator object
870 *
871 * Get the value of a property of type double.
872 *
873 * Returns: property value (IEEE754 double precision float)
874 */
875 double
libhal_psi_get_double(LibHalPropertySetIterator * iter)876 libhal_psi_get_double (LibHalPropertySetIterator * iter)
877 {
878 return iter->cur_prop->v.double_value;
879 }
880
881 /**
882 * libhal_psi_get_bool:
883 * @iter: iterator object
884 *
885 * Get the value of a property of type bool.
886 *
887 * Returns: property value (bool)
888 */
889 dbus_bool_t
libhal_psi_get_bool(LibHalPropertySetIterator * iter)890 libhal_psi_get_bool (LibHalPropertySetIterator * iter)
891 {
892 return iter->cur_prop->v.bool_value;
893 }
894
895 /**
896 * libhal_psi_get_strlist:
897 * @iter: iterator object
898 *
899 * Get the value of a property of type string list.
900 *
901 * Returns: pointer to array of strings
902 */
903 char **
libhal_psi_get_strlist(LibHalPropertySetIterator * iter)904 libhal_psi_get_strlist (LibHalPropertySetIterator * iter)
905 {
906 return iter->cur_prop->v.strlist_value;
907 }
908
909
910 static DBusHandlerResult
filter_func(DBusConnection * connection,DBusMessage * message,void * user_data)911 filter_func (DBusConnection * connection,
912 DBusMessage * message, void *user_data)
913 {
914 const char *object_path;
915 DBusError error;
916 LibHalContext *ctx = (LibHalContext *) user_data;
917
918 if (ctx->is_shutdown)
919 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
920
921 dbus_error_init (&error);
922
923 object_path = dbus_message_get_path (message);
924
925 /*printf("*** in filter_func, object_path=%s\n", object_path);*/
926
927 if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager",
928 "DeviceAdded")) {
929 char *udi;
930 if (dbus_message_get_args (message, &error,
931 DBUS_TYPE_STRING, &udi,
932 DBUS_TYPE_INVALID)) {
933 if (ctx->device_added != NULL) {
934 ctx->device_added (ctx, udi);
935 }
936 } else {
937 LIBHAL_FREE_DBUS_ERROR(&error);
938 }
939 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
940 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager", "DeviceRemoved")) {
941 char *udi;
942 if (dbus_message_get_args (message, &error,
943 DBUS_TYPE_STRING, &udi,
944 DBUS_TYPE_INVALID)) {
945 if (ctx->device_removed != NULL) {
946 ctx->device_removed (ctx, udi);
947 }
948 } else {
949 LIBHAL_FREE_DBUS_ERROR(&error);
950 }
951 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
952 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Manager","NewCapability")) {
953 char *udi;
954 char *capability;
955 if (dbus_message_get_args (message, &error,
956 DBUS_TYPE_STRING, &udi,
957 DBUS_TYPE_STRING, &capability,
958 DBUS_TYPE_INVALID)) {
959 if (ctx->device_new_capability != NULL) {
960 ctx->device_new_capability (ctx, udi, capability);
961 }
962 } else {
963 LIBHAL_FREE_DBUS_ERROR(&error);
964 }
965 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
966 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "Condition")) {
967 char *condition_name;
968 char *condition_detail;
969 if (dbus_message_get_args (message, &error,
970 DBUS_TYPE_STRING, &condition_name,
971 DBUS_TYPE_STRING, &condition_detail,
972 DBUS_TYPE_INVALID)) {
973 if (ctx->device_condition != NULL) {
974 ctx->device_condition (ctx, object_path, condition_name, condition_detail);
975 }
976 } else {
977 LIBHAL_FREE_DBUS_ERROR(&error);
978 }
979 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
980 } else if (dbus_message_is_signal (message, "org.freedesktop.Hal.Device", "PropertyModified")) {
981 if (ctx->device_property_modified != NULL) {
982 int i;
983 char *key;
984 dbus_bool_t removed;
985 dbus_bool_t added;
986 int num_modifications;
987 DBusMessageIter iter;
988 DBusMessageIter iter_array;
989
990 dbus_message_iter_init (message, &iter);
991 dbus_message_iter_get_basic (&iter, &num_modifications);
992 dbus_message_iter_next (&iter);
993
994 dbus_message_iter_recurse (&iter, &iter_array);
995
996 for (i = 0; i < num_modifications; i++) {
997 DBusMessageIter iter_struct;
998
999 dbus_message_iter_recurse (&iter_array, &iter_struct);
1000
1001 dbus_message_iter_get_basic (&iter_struct, &key);
1002 dbus_message_iter_next (&iter_struct);
1003 dbus_message_iter_get_basic (&iter_struct, &removed);
1004 dbus_message_iter_next (&iter_struct);
1005 dbus_message_iter_get_basic (&iter_struct, &added);
1006
1007 ctx->device_property_modified (ctx,
1008 object_path,
1009 key, removed,
1010 added);
1011
1012 dbus_message_iter_next (&iter_array);
1013 }
1014
1015 }
1016 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1017 }
1018
1019 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1020 }
1021
1022 /* for i18n purposes */
1023 static dbus_bool_t libhal_already_initialized_once = FALSE;
1024
1025
1026 /**
1027 * libhal_get_all_devices:
1028 * @ctx: the context for the connection to hald
1029 * @num_devices: the number of devices will be stored here
1030 * @error: pointer to an initialized dbus error object for returning errors or NULL
1031 *
1032 * Get all devices in the Global Device List (GDL).
1033 *
1034 * Returns: An array of device identifiers terminated with NULL. It is
1035 * the responsibility of the caller to free with
1036 * libhal_free_string_array(). If an error occurs NULL is returned.
1037 */
1038 char **
libhal_get_all_devices(LibHalContext * ctx,int * num_devices,DBusError * error)1039 libhal_get_all_devices (LibHalContext *ctx, int *num_devices, DBusError *error)
1040 {
1041 DBusMessage *message;
1042 DBusMessage *reply;
1043 DBusMessageIter iter_array, reply_iter;
1044 char **hal_device_names;
1045 DBusError _error;
1046
1047 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
1048
1049 *num_devices = 0;
1050
1051 message = dbus_message_new_method_call ("org.freedesktop.Hal",
1052 "/org/freedesktop/Hal/Manager",
1053 "org.freedesktop.Hal.Manager",
1054 "GetAllDevices");
1055 if (message == NULL) {
1056 fprintf (stderr, "%s %d : Could not allocate D-BUS message\n", __FILE__, __LINE__);
1057 return NULL;
1058 }
1059
1060 dbus_error_init (&_error);
1061 reply = dbus_connection_send_with_reply_and_block (ctx->connection, message, -1, &_error);
1062
1063 dbus_move_error (&_error, error);
1064 if (error != NULL && dbus_error_is_set (error)) {
1065 dbus_message_unref (message);
1066 return NULL;
1067 }
1068 if (reply == NULL) {
1069 dbus_message_unref (message);
1070 return NULL;
1071 }
1072
1073 /* now analyze reply */
1074 dbus_message_iter_init (reply, &reply_iter);
1075
1076 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
1077 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
1078 return NULL;
1079 }
1080
1081 dbus_message_iter_recurse (&reply_iter, &iter_array);
1082
1083 hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
1084
1085 dbus_message_unref (reply);
1086 dbus_message_unref (message);
1087
1088 return hal_device_names;
1089 }
1090
1091 /**
1092 * libhal_device_get_property_type:
1093 * @ctx: the context for the connection to hald
1094 * @udi: the Unique Device Id
1095 * @key: name of the property
1096 * @error: pointer to an initialized dbus error object for returning errors or NULL
1097 *
1098 * Query a property type of a device.
1099 *
1100 * Returns: A LibHalPropertyType. LIBHAL_PROPERTY_TYPE_INVALID is
1101 * return if the property doesn't exist.
1102 */
1103 LibHalPropertyType
libhal_device_get_property_type(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)1104 libhal_device_get_property_type (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
1105 {
1106 DBusMessage *message;
1107 DBusMessage *reply;
1108 DBusMessageIter iter, reply_iter;
1109 int type;
1110 DBusError _error;
1111
1112 LIBHAL_CHECK_LIBHALCONTEXT(ctx, LIBHAL_PROPERTY_TYPE_INVALID); /* or return NULL? */
1113
1114 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1115 "org.freedesktop.Hal.Device",
1116 "GetPropertyType");
1117 if (message == NULL) {
1118 fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
1119 return LIBHAL_PROPERTY_TYPE_INVALID;
1120 }
1121
1122 dbus_message_iter_init_append (message, &iter);
1123 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1124
1125 dbus_error_init (&_error);
1126 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1127 message, -1,
1128 &_error);
1129
1130 dbus_move_error (&_error, error);
1131 if (error != NULL && dbus_error_is_set (error)) {
1132 dbus_message_unref (message);
1133 return LIBHAL_PROPERTY_TYPE_INVALID;
1134 }
1135 if (reply == NULL) {
1136 dbus_message_unref (message);
1137 return LIBHAL_PROPERTY_TYPE_INVALID;
1138 }
1139
1140 dbus_message_iter_init (reply, &reply_iter);
1141 dbus_message_iter_get_basic (&reply_iter, &type);
1142
1143 dbus_message_unref (message);
1144 dbus_message_unref (reply);
1145
1146 return type;
1147 }
1148
1149 /**
1150 * libhal_device_get_property_strlist:
1151 * @ctx: the context for the connection to hald
1152 * @udi: unique Device Id
1153 * @key: name of the property
1154 * @error: pointer to an initialized dbus error object for returning errors or NULL
1155 *
1156 * Get the value of a property of type string list.
1157 *
1158 * Returns: Array of pointers to UTF8 nul-terminated strings
1159 * terminated by NULL. The caller is responsible for freeing this
1160 * string array with the function libhal_free_string_array(). Returns
1161 * NULL if the property didn't exist or we are OOM
1162 */
1163 char **
libhal_device_get_property_strlist(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)1164 libhal_device_get_property_strlist (LibHalContext *ctx, const char *udi, const char *key, DBusError *error)
1165 {
1166 DBusMessage *message;
1167 DBusMessage *reply;
1168 DBusMessageIter iter, iter_array, reply_iter;
1169 char **our_strings;
1170 DBusError _error;
1171
1172 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
1173
1174 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1175 "org.freedesktop.Hal.Device",
1176 "GetPropertyStringList");
1177 if (message == NULL) {
1178 fprintf (stderr,
1179 "%s %d : Couldn't allocate D-BUS message\n",
1180 __FILE__, __LINE__);
1181 return NULL;
1182 }
1183
1184 dbus_message_iter_init_append (message, &iter);
1185 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1186
1187 dbus_error_init (&_error);
1188 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1189 message, -1,
1190 &_error);
1191
1192 dbus_move_error (&_error, error);
1193 if (error != NULL && dbus_error_is_set (error)) {
1194 dbus_message_unref (message);
1195 return NULL;
1196 }
1197 if (reply == NULL) {
1198 dbus_message_unref (message);
1199 return NULL;
1200 }
1201 /* now analyse reply */
1202 dbus_message_iter_init (reply, &reply_iter);
1203
1204 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
1205 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
1206 return NULL;
1207 }
1208
1209 dbus_message_iter_recurse (&reply_iter, &iter_array);
1210
1211 our_strings = libhal_get_string_array_from_iter (&iter_array, NULL);
1212
1213 dbus_message_unref (reply);
1214 dbus_message_unref (message);
1215
1216 return our_strings;
1217 }
1218
1219 /**
1220 * libhal_device_get_property_string:
1221 * @ctx: the context for the connection to hald
1222 * @udi: the Unique Device Id
1223 * @key: the name of the property
1224 * @error: pointer to an initialized dbus error object for returning errors or NULL
1225 *
1226 * Get the value of a property of type string.
1227 *
1228 * Returns: UTF8 nul-terminated string. The caller is responsible for
1229 * freeing this string with the function libhal_free_string(). Returns
1230 * NULL if the property didn't exist or we are OOM.
1231 */
1232 char *
libhal_device_get_property_string(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)1233 libhal_device_get_property_string (LibHalContext *ctx,
1234 const char *udi, const char *key, DBusError *error)
1235 {
1236 DBusMessage *message;
1237 DBusMessage *reply;
1238 DBusMessageIter iter, reply_iter;
1239 char *value;
1240 char *dbus_str;
1241 DBusError _error;
1242
1243 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
1244
1245 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1246 "org.freedesktop.Hal.Device",
1247 "GetPropertyString");
1248
1249 if (message == NULL) {
1250 fprintf (stderr,
1251 "%s %d : Couldn't allocate D-BUS message\n",
1252 __FILE__, __LINE__);
1253 return NULL;
1254 }
1255
1256 dbus_message_iter_init_append (message, &iter);
1257 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1258
1259 dbus_error_init (&_error);
1260 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1261 message, -1,
1262 &_error);
1263
1264 dbus_move_error (&_error, error);
1265 if (error != NULL && dbus_error_is_set (error)) {
1266 dbus_message_unref (message);
1267 return NULL;
1268 }
1269 if (reply == NULL) {
1270 dbus_message_unref (message);
1271 return NULL;
1272 }
1273
1274 dbus_message_iter_init (reply, &reply_iter);
1275
1276 /* now analyze reply */
1277 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1278 DBUS_TYPE_STRING) {
1279 dbus_message_unref (message);
1280 dbus_message_unref (reply);
1281 return NULL;
1282 }
1283
1284 dbus_message_iter_get_basic (&reply_iter, &dbus_str);
1285 value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
1286 if (value == NULL) {
1287 fprintf (stderr, "%s %d : error allocating memory\n",
1288 __FILE__, __LINE__);
1289 /** @todo FIXME cleanup */
1290 return NULL;
1291 }
1292
1293 dbus_message_unref (message);
1294 dbus_message_unref (reply);
1295 return value;
1296 }
1297
1298 /**
1299 * libhal_device_get_property_int:
1300 * @ctx: the context for the connection to hald
1301 * @udi: the Unique Device Id
1302 * @key: name of the property
1303 * @error: pointer to an initialized dbus error object for returning errors or NULL
1304 *
1305 * Get the value of a property of type integer.
1306 *
1307 * Returns: Property value (32-bit signed integer)
1308 */
1309 dbus_int32_t
libhal_device_get_property_int(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)1310 libhal_device_get_property_int (LibHalContext *ctx,
1311 const char *udi, const char *key, DBusError *error)
1312 {
1313 DBusMessage *message;
1314 DBusMessage *reply;
1315 DBusMessageIter iter, reply_iter;
1316 dbus_int32_t value;
1317 DBusError _error;
1318
1319 LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
1320
1321 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1322 "org.freedesktop.Hal.Device",
1323 "GetPropertyInteger");
1324 if (message == NULL) {
1325 fprintf (stderr,
1326 "%s %d : Couldn't allocate D-BUS message\n",
1327 __FILE__, __LINE__);
1328 return -1;
1329 }
1330
1331 dbus_message_iter_init_append (message, &iter);
1332 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1333
1334 dbus_error_init (&_error);
1335 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1336 message, -1,
1337 &_error);
1338
1339 dbus_move_error (&_error, error);
1340 if (error != NULL && dbus_error_is_set (error)) {
1341 dbus_message_unref (message);
1342 return -1;
1343 }
1344 if (reply == NULL) {
1345 dbus_message_unref (message);
1346 return -1;
1347 }
1348
1349 dbus_message_iter_init (reply, &reply_iter);
1350
1351 /* now analyze reply */
1352 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1353 DBUS_TYPE_INT32) {
1354 fprintf (stderr,
1355 "%s %d : property '%s' for device '%s' is not "
1356 "of type integer\n", __FILE__, __LINE__, key,
1357 udi);
1358 dbus_message_unref (message);
1359 dbus_message_unref (reply);
1360 return -1;
1361 }
1362 dbus_message_iter_get_basic (&reply_iter, &value);
1363
1364 dbus_message_unref (message);
1365 dbus_message_unref (reply);
1366 return value;
1367 }
1368
1369 /**
1370 * libhal_device_get_property_uint64:
1371 * @ctx: the context for the connection to hald
1372 * @udi: the Unique Device Id
1373 * @key: name of the property
1374 * @error: pointer to an initialized dbus error object for returning errors or NULL
1375 *
1376 * Get the value of a property of type signed integer.
1377 *
1378 * Returns: Property value (64-bit unsigned integer)
1379 */
1380 dbus_uint64_t
libhal_device_get_property_uint64(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)1381 libhal_device_get_property_uint64 (LibHalContext *ctx,
1382 const char *udi, const char *key, DBusError *error)
1383 {
1384 DBusMessage *message;
1385 DBusMessage *reply;
1386 DBusMessageIter iter, reply_iter;
1387 dbus_uint64_t value;
1388 DBusError _error;
1389
1390 LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1);
1391
1392 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1393 "org.freedesktop.Hal.Device",
1394 "GetPropertyInteger");
1395 if (message == NULL) {
1396 fprintf (stderr,
1397 "%s %d : Couldn't allocate D-BUS message\n",
1398 __FILE__, __LINE__);
1399 return -1;
1400 }
1401
1402 dbus_message_iter_init_append (message, &iter);
1403 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1404
1405 dbus_error_init (&_error);
1406 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1407 message, -1,
1408 &_error);
1409
1410 dbus_move_error (&_error, error);
1411 if (error != NULL && dbus_error_is_set (error)) {
1412 dbus_message_unref (message);
1413 return -1;
1414 }
1415 if (reply == NULL) {
1416 dbus_message_unref (message);
1417 return -1;
1418 }
1419
1420 dbus_message_iter_init (reply, &reply_iter);
1421 /* now analyze reply */
1422 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1423 DBUS_TYPE_UINT64) {
1424 fprintf (stderr,
1425 "%s %d : property '%s' for device '%s' is not "
1426 "of type integer\n", __FILE__, __LINE__, key,
1427 udi);
1428 dbus_message_unref (message);
1429 dbus_message_unref (reply);
1430 return -1;
1431 }
1432 dbus_message_iter_get_basic (&reply_iter, &value);
1433
1434 dbus_message_unref (message);
1435 dbus_message_unref (reply);
1436 return value;
1437 }
1438
1439 /**
1440 * libhal_device_get_property_double:
1441 * @ctx: the context for the connection to hald
1442 * @udi: the Unique Device Id
1443 * @key: name of the property
1444 * @error: pointer to an initialized dbus error object for returning errors or NULL
1445 *
1446 * Get the value of a property of type double.
1447 *
1448 * Returns: Property value (IEEE754 double precision float)
1449 */
1450 double
libhal_device_get_property_double(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)1451 libhal_device_get_property_double (LibHalContext *ctx,
1452 const char *udi, const char *key, DBusError *error)
1453 {
1454 DBusMessage *message;
1455 DBusMessage *reply;
1456 DBusMessageIter iter, reply_iter;
1457 double value;
1458 DBusError _error;
1459
1460 LIBHAL_CHECK_LIBHALCONTEXT(ctx, -1.0);
1461
1462 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1463 "org.freedesktop.Hal.Device",
1464 "GetPropertyDouble");
1465 if (message == NULL) {
1466 fprintf (stderr,
1467 "%s %d : Couldn't allocate D-BUS message\n",
1468 __FILE__, __LINE__);
1469 return -1.0f;
1470 }
1471
1472 dbus_message_iter_init_append (message, &iter);
1473 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1474
1475 dbus_error_init (&_error);
1476 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1477 message, -1,
1478 &_error);
1479
1480 dbus_move_error (&_error, error);
1481 if (error != NULL && dbus_error_is_set (error)) {
1482 dbus_message_unref (message);
1483 return -1.0f;
1484 }
1485 if (reply == NULL) {
1486 dbus_message_unref (message);
1487 return -1.0f;
1488 }
1489
1490 dbus_message_iter_init (reply, &reply_iter);
1491
1492 /* now analyze reply */
1493 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1494 DBUS_TYPE_DOUBLE) {
1495 fprintf (stderr,
1496 "%s %d : property '%s' for device '%s' is not "
1497 "of type double\n", __FILE__, __LINE__, key, udi);
1498 dbus_message_unref (message);
1499 dbus_message_unref (reply);
1500 return -1.0f;
1501 }
1502 dbus_message_iter_get_basic (&reply_iter, &value);
1503
1504 dbus_message_unref (message);
1505 dbus_message_unref (reply);
1506 return (double) value;
1507 }
1508
1509 /**
1510 * libhal_device_get_property_bool:
1511 * @ctx: the context for the connection to hald
1512 * @udi: the Unique Device Id
1513 * @key: name of the property
1514 * @error: pointer to an initialized dbus error object for returning errors or NULL
1515 *
1516 * Get the value of a property of type bool.
1517 *
1518 * Returns: Property value (boolean)
1519 */
1520 dbus_bool_t
libhal_device_get_property_bool(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)1521 libhal_device_get_property_bool (LibHalContext *ctx,
1522 const char *udi, const char *key, DBusError *error)
1523 {
1524 DBusMessage *message;
1525 DBusMessage *reply;
1526 DBusMessageIter iter, reply_iter;
1527 dbus_bool_t value;
1528 DBusError _error;
1529
1530 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1531
1532 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1533 "org.freedesktop.Hal.Device",
1534 "GetPropertyBoolean");
1535 if (message == NULL) {
1536 fprintf (stderr,
1537 "%s %d : Couldn't allocate D-BUS message\n",
1538 __FILE__, __LINE__);
1539 return FALSE;
1540 }
1541
1542 dbus_message_iter_init_append (message, &iter);
1543 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1544
1545 dbus_error_init (&_error);
1546 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1547 message, -1,
1548 &_error);
1549
1550 dbus_move_error (&_error, error);
1551 if (error != NULL && dbus_error_is_set (error)) {
1552 dbus_message_unref (message);
1553 return FALSE;
1554 }
1555 if (reply == NULL) {
1556 dbus_message_unref (message);
1557 return FALSE;
1558 }
1559
1560 dbus_message_iter_init (reply, &reply_iter);
1561
1562 /* now analyze reply */
1563 if (dbus_message_iter_get_arg_type (&reply_iter) !=
1564 DBUS_TYPE_BOOLEAN) {
1565 fprintf (stderr,
1566 "%s %d : property '%s' for device '%s' is not "
1567 "of type bool\n", __FILE__, __LINE__, key, udi);
1568 dbus_message_unref (message);
1569 dbus_message_unref (reply);
1570 return FALSE;
1571 }
1572 dbus_message_iter_get_basic (&reply_iter, &value);
1573
1574 dbus_message_unref (message);
1575 dbus_message_unref (reply);
1576 return value;
1577 }
1578
1579
1580 /* generic helper */
1581 static dbus_bool_t
libhal_device_set_property_helper(LibHalContext * ctx,const char * udi,const char * key,int type,const char * str_value,dbus_int32_t int_value,dbus_uint64_t uint64_value,double double_value,dbus_bool_t bool_value,DBusError * error)1582 libhal_device_set_property_helper (LibHalContext *ctx,
1583 const char *udi,
1584 const char *key,
1585 int type,
1586 const char *str_value,
1587 dbus_int32_t int_value,
1588 dbus_uint64_t uint64_value,
1589 double double_value,
1590 dbus_bool_t bool_value,
1591 DBusError *error)
1592 {
1593 DBusMessage *message;
1594 DBusMessage *reply;
1595 DBusMessageIter iter;
1596 char *method_name = NULL;
1597
1598 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1599
1600 /** @todo sanity check incoming params */
1601 switch (type) {
1602 case DBUS_TYPE_INVALID:
1603 method_name = "RemoveProperty";
1604 break;
1605 case DBUS_TYPE_STRING:
1606 method_name = "SetPropertyString";
1607 break;
1608 case DBUS_TYPE_INT32:
1609 case DBUS_TYPE_UINT64:
1610 method_name = "SetPropertyInteger";
1611 break;
1612 case DBUS_TYPE_DOUBLE:
1613 method_name = "SetPropertyDouble";
1614 break;
1615 case DBUS_TYPE_BOOLEAN:
1616 method_name = "SetPropertyBoolean";
1617 break;
1618
1619 default:
1620 /* cannot happen; is not callable from outside this file */
1621 break;
1622 }
1623
1624 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1625 "org.freedesktop.Hal.Device",
1626 method_name);
1627 if (message == NULL) {
1628 fprintf (stderr,
1629 "%s %d : Couldn't allocate D-BUS message\n",
1630 __FILE__, __LINE__);
1631 return FALSE;
1632 }
1633
1634 dbus_message_iter_init_append (message, &iter);
1635 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1636 switch (type) {
1637 case DBUS_TYPE_STRING:
1638 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &str_value);
1639 break;
1640 case DBUS_TYPE_INT32:
1641 dbus_message_iter_append_basic (&iter, DBUS_TYPE_INT32, &int_value);
1642 break;
1643 case DBUS_TYPE_UINT64:
1644 dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT64, &uint64_value);
1645 break;
1646 case DBUS_TYPE_DOUBLE:
1647 dbus_message_iter_append_basic (&iter, DBUS_TYPE_DOUBLE, &double_value);
1648 break;
1649 case DBUS_TYPE_BOOLEAN:
1650 dbus_message_iter_append_basic (&iter, DBUS_TYPE_BOOLEAN, &bool_value);
1651 break;
1652 }
1653
1654
1655 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1656 message, -1,
1657 error);
1658 if (error != NULL && dbus_error_is_set (error)) {
1659 dbus_message_unref (message);
1660 return FALSE;
1661 }
1662
1663 if (reply == NULL) {
1664 dbus_message_unref (message);
1665 return FALSE;
1666 }
1667
1668 dbus_message_unref (message);
1669 dbus_message_unref (reply);
1670
1671 return TRUE;
1672 }
1673
1674 /**
1675 * libhal_device_set_property_string:
1676 * @ctx: the context for the connection to hald
1677 * @udi: the Unique Device Id
1678 * @key: name of the property
1679 * @value: value of the property; a UTF8 string
1680 * @error: pointer to an initialized dbus error object for returning errors or NULL
1681 *
1682 * Set a property of type string.
1683 *
1684 * Returns: TRUE if the property was set, FALSE if the device didn't
1685 * exist or the property had a different type.
1686 */
1687 dbus_bool_t
libhal_device_set_property_string(LibHalContext * ctx,const char * udi,const char * key,const char * value,DBusError * error)1688 libhal_device_set_property_string (LibHalContext *ctx,
1689 const char *udi,
1690 const char *key,
1691 const char *value,
1692 DBusError *error)
1693 {
1694 return libhal_device_set_property_helper (ctx, udi, key,
1695 DBUS_TYPE_STRING,
1696 value, 0, 0, 0.0f, FALSE, error);
1697 }
1698
1699 /**
1700 * libhal_device_set_property_int:
1701 * @ctx: the context for the connection to hald
1702 * @udi: the Unique Device Id
1703 * @key: name of the property
1704 * @value: value of the property
1705 * @error: pointer to an initialized dbus error object for returning errors or NULL
1706 *
1707 * Set a property of type signed integer.
1708 *
1709 * Returns: TRUE if the property was set, FALSE if the device didn't
1710 * exist or the property had a different type.
1711 */
1712 dbus_bool_t
libhal_device_set_property_int(LibHalContext * ctx,const char * udi,const char * key,dbus_int32_t value,DBusError * error)1713 libhal_device_set_property_int (LibHalContext *ctx, const char *udi,
1714 const char *key, dbus_int32_t value, DBusError *error)
1715 {
1716 return libhal_device_set_property_helper (ctx, udi, key,
1717 DBUS_TYPE_INT32,
1718 NULL, value, 0, 0.0f, FALSE, error);
1719 }
1720
1721 /**
1722 * libhal_device_set_property_uint64:
1723 * @ctx: the context for the connection to hald
1724 * @udi: the Unique Device Id
1725 * @key: name of the property
1726 * @value: value of the property
1727 * @error: pointer to an initialized dbus error object for returning errors or NULL
1728 *
1729 * Set a property of type unsigned integer.
1730 *
1731 * Returns: TRUE if the property was set, FALSE if the device didn't
1732 * exist or the property had a different type.
1733 */
1734 dbus_bool_t
libhal_device_set_property_uint64(LibHalContext * ctx,const char * udi,const char * key,dbus_uint64_t value,DBusError * error)1735 libhal_device_set_property_uint64 (LibHalContext *ctx, const char *udi,
1736 const char *key, dbus_uint64_t value, DBusError *error)
1737 {
1738 return libhal_device_set_property_helper (ctx, udi, key,
1739 DBUS_TYPE_UINT64,
1740 NULL, 0, value, 0.0f, FALSE, error);
1741 }
1742
1743 /**
1744 * libhal_device_set_property_double:
1745 * @ctx: the context for the connection to hald
1746 * @udi: the Unique Device Id
1747 * @key: name of the property
1748 * @value: value of the property
1749 * @error: pointer to an initialized dbus error object for returning errors or NULL
1750 *
1751 * Set a property of type double.
1752 *
1753 * Returns: TRUE if the property was set, FALSE if the device didn't
1754 * exist or the property had a different type.
1755 */
1756 dbus_bool_t
libhal_device_set_property_double(LibHalContext * ctx,const char * udi,const char * key,double value,DBusError * error)1757 libhal_device_set_property_double (LibHalContext *ctx, const char *udi,
1758 const char *key, double value, DBusError *error)
1759 {
1760 return libhal_device_set_property_helper (ctx, udi, key,
1761 DBUS_TYPE_DOUBLE,
1762 NULL, 0, 0, value, FALSE, error);
1763 }
1764
1765 /**
1766 * libhal_device_set_property_bool:
1767 * @ctx: the context for the connection to hald
1768 * @udi: the Unique Device Id
1769 * @key: name of the property
1770 * @value: value of the property
1771 * @error: pointer to an initialized dbus error object for returning errors or NULL
1772 *
1773 * Set a property of type bool.
1774 *
1775 * Returns: TRUE if the property was set, FALSE if the device didn't
1776 * exist or the property had a different type.
1777 */
1778 dbus_bool_t
libhal_device_set_property_bool(LibHalContext * ctx,const char * udi,const char * key,dbus_bool_t value,DBusError * error)1779 libhal_device_set_property_bool (LibHalContext *ctx, const char *udi,
1780 const char *key, dbus_bool_t value, DBusError *error)
1781 {
1782 return libhal_device_set_property_helper (ctx, udi, key,
1783 DBUS_TYPE_BOOLEAN,
1784 NULL, 0, 0, 0.0f, value, error);
1785 }
1786
1787
1788 /**
1789 * libhal_device_remove_property:
1790 * @ctx: the context for the connection to hald
1791 * @udi: the Unique Device Id
1792 * @key: name of the property
1793 * @error: pointer to an initialized dbus error object for returning errors or NULL
1794 *
1795 * Remove a property.
1796 *
1797 * Returns: TRUE if the property was set, FALSE if the device didn't
1798 * exist
1799 */
1800 dbus_bool_t
libhal_device_remove_property(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)1801 libhal_device_remove_property (LibHalContext *ctx,
1802 const char *udi, const char *key, DBusError *error)
1803 {
1804 return libhal_device_set_property_helper (ctx, udi, key, DBUS_TYPE_INVALID,
1805 /* DBUS_TYPE_INVALID means remove */
1806 NULL, 0, 0, 0.0f, FALSE, error);
1807 }
1808
1809 /**
1810 * libhal_device_property_strlist_append:
1811 * @ctx: the context for the connection to hald
1812 * @udi: the Unique Device Id
1813 * @key: name of the property
1814 * @value: value to append to property
1815 * @error: pointer to an initialized dbus error object for returning errors or NULL
1816 *
1817 * Append to a property of type strlist.
1818 *
1819 * Returns: TRUE if the value was appended, FALSE if the device didn't
1820 * exist or the property had a different type.
1821 */
1822 dbus_bool_t
libhal_device_property_strlist_append(LibHalContext * ctx,const char * udi,const char * key,const char * value,DBusError * error)1823 libhal_device_property_strlist_append (LibHalContext *ctx,
1824 const char *udi,
1825 const char *key,
1826 const char *value,
1827 DBusError *error)
1828 {
1829 DBusMessage *message;
1830 DBusMessage *reply;
1831 DBusMessageIter iter;
1832
1833 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1834
1835 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1836 "org.freedesktop.Hal.Device",
1837 "StringListAppend");
1838 if (message == NULL) {
1839 fprintf (stderr,
1840 "%s %d : Couldn't allocate D-BUS message\n",
1841 __FILE__, __LINE__);
1842 return FALSE;
1843 }
1844 dbus_message_iter_init_append (message, &iter);
1845 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1846 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
1847
1848 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1849 message, -1,
1850 error);
1851 if (error != NULL && dbus_error_is_set (error)) {
1852 dbus_message_unref (message);
1853 return FALSE;
1854 }
1855 if (reply == NULL) {
1856 dbus_message_unref (message);
1857 return FALSE;
1858 }
1859 return TRUE;
1860 }
1861
1862 /**
1863 * libhal_device_property_strlist_prepend:
1864 * @ctx: the context for the connection to hald
1865 * @udi: the Unique Device Id
1866 * @key: name of the property
1867 * @value: value to prepend to property
1868 * @error: pointer to an initialized dbus error object for returning errors or NULL
1869 *
1870 * Prepend to a property of type strlist.
1871 *
1872 * Returns: TRUE if the value was prepended, FALSE if the device
1873 * didn't exist or the property had a different type.
1874 */
1875 dbus_bool_t
libhal_device_property_strlist_prepend(LibHalContext * ctx,const char * udi,const char * key,const char * value,DBusError * error)1876 libhal_device_property_strlist_prepend (LibHalContext *ctx,
1877 const char *udi,
1878 const char *key,
1879 const char *value,
1880 DBusError *error)
1881 {
1882 DBusMessage *message;
1883 DBusMessage *reply;
1884 DBusMessageIter iter;
1885
1886 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1887
1888 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1889 "org.freedesktop.Hal.Device",
1890 "StringListPrepend");
1891 if (message == NULL) {
1892 fprintf (stderr,
1893 "%s %d : Couldn't allocate D-BUS message\n",
1894 __FILE__, __LINE__);
1895 return FALSE;
1896 }
1897 dbus_message_iter_init_append (message, &iter);
1898 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1899 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
1900
1901 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1902 message, -1,
1903 error);
1904 if (error != NULL && dbus_error_is_set (error)) {
1905 dbus_message_unref (message);
1906 return FALSE;
1907 }
1908 if (reply == NULL) {
1909 dbus_message_unref (message);
1910 return FALSE;
1911 }
1912 return TRUE;
1913 }
1914
1915 /**
1916 * libhal_device_property_strlist_remove_index:
1917 * @ctx: the context for the connection to hald
1918 * @udi: the Unique Device Id
1919 * @key: name of the property
1920 * @idx: index of string to remove in the strlist
1921 * @error: pointer to an initialized dbus error object for returning errors or NULL
1922 *
1923 * Remove a specified string from a property of type strlist.
1924 *
1925 * Returns: TRUE if the string was removed, FALSE if the device didn't
1926 * exist or the property had a different type.
1927 */
1928 dbus_bool_t
libhal_device_property_strlist_remove_index(LibHalContext * ctx,const char * udi,const char * key,unsigned int idx,DBusError * error)1929 libhal_device_property_strlist_remove_index (LibHalContext *ctx,
1930 const char *udi,
1931 const char *key,
1932 unsigned int idx,
1933 DBusError *error)
1934 {
1935 DBusMessage *message;
1936 DBusMessage *reply;
1937 DBusMessageIter iter;
1938
1939 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1940
1941 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1942 "org.freedesktop.Hal.Device",
1943 "StringListRemoveIndex");
1944 if (message == NULL) {
1945 fprintf (stderr,
1946 "%s %d : Couldn't allocate D-BUS message\n",
1947 __FILE__, __LINE__);
1948 return FALSE;
1949 }
1950 dbus_message_iter_init_append (message, &iter);
1951 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
1952 dbus_message_iter_append_basic (&iter, DBUS_TYPE_UINT32, &idx);
1953
1954 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
1955 message, -1,
1956 error);
1957 if (error != NULL && dbus_error_is_set (error)) {
1958 dbus_message_unref (message);
1959 return FALSE;
1960 }
1961 if (reply == NULL) {
1962 dbus_message_unref (message);
1963 return FALSE;
1964 }
1965 return TRUE;
1966 }
1967
1968 /**
1969 * libhal_device_property_strlist_remove:
1970 * @ctx: the context for the connection to hald
1971 * @udi: the Unique Device Id
1972 * @key: name of the property
1973 * @value: the string to remove
1974 * @error: pointer to an initialized dbus error object for returning errors or NULL
1975 *
1976 * Remove a specified string from a property of type strlist.
1977 *
1978 * Returns: TRUE if the string was removed, FALSE if the device didn't
1979 * exist or the property had a different type.
1980 */
1981 dbus_bool_t
libhal_device_property_strlist_remove(LibHalContext * ctx,const char * udi,const char * key,const char * value,DBusError * error)1982 libhal_device_property_strlist_remove (LibHalContext *ctx,
1983 const char *udi,
1984 const char *key,
1985 const char *value, DBusError *error)
1986 {
1987 DBusMessage *message;
1988 DBusMessage *reply;
1989 DBusMessageIter iter;
1990
1991 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
1992
1993 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
1994 "org.freedesktop.Hal.Device",
1995 "StringListRemove");
1996 if (message == NULL) {
1997 fprintf (stderr,
1998 "%s %d : Couldn't allocate D-BUS message\n",
1999 __FILE__, __LINE__);
2000 return FALSE;
2001 }
2002 dbus_message_iter_init_append (message, &iter);
2003 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2004 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
2005
2006 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2007 message, -1,
2008 error);
2009 if (error != NULL && dbus_error_is_set (error)) {
2010 dbus_message_unref (message);
2011 return FALSE;
2012 }
2013 if (reply == NULL) {
2014 dbus_message_unref (message);
2015 return FALSE;
2016 }
2017 return TRUE;
2018 }
2019
2020
2021 /**
2022 * libhal_device_lock:
2023 * @ctx: the context for the connection to hald
2024 * @udi: the Unique Device Id
2025 * @reason_to_lock: a user-presentable reason why the device is locked.
2026 * @reason_why_locked: a pointer to store the reason why the device cannot be locked on failure, or NULL
2027 * @error: pointer to an initialized dbus error object for returning errors or NULL
2028 *
2029 * Take an advisory lock on the device.
2030 *
2031 * Returns: TRUE if the lock was obtained, FALSE otherwise
2032 */
2033 dbus_bool_t
libhal_device_lock(LibHalContext * ctx,const char * udi,const char * reason_to_lock,char ** reason_why_locked,DBusError * error)2034 libhal_device_lock (LibHalContext *ctx,
2035 const char *udi,
2036 const char *reason_to_lock,
2037 char **reason_why_locked, DBusError *error)
2038 {
2039 DBusMessage *message;
2040 DBusMessageIter iter;
2041 DBusMessage *reply;
2042
2043 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2044
2045 if (reason_why_locked != NULL)
2046 *reason_why_locked = NULL;
2047
2048 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2049 udi,
2050 "org.freedesktop.Hal.Device",
2051 "Lock");
2052
2053 if (message == NULL) {
2054 fprintf (stderr,
2055 "%s %d : Couldn't allocate D-BUS message\n",
2056 __FILE__, __LINE__);
2057 return FALSE;
2058 }
2059
2060 dbus_message_iter_init_append (message, &iter);
2061 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &reason_to_lock);
2062
2063
2064 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2065 message, -1,
2066 error);
2067
2068 if (error != NULL && dbus_error_is_set (error)) {
2069 if (strcmp (error->name,
2070 "org.freedesktop.Hal.DeviceAlreadyLocked") == 0) {
2071 if (reason_why_locked != NULL) {
2072 *reason_why_locked =
2073 dbus_malloc0 (strlen (error->message) + 1);
2074 strcpy (*reason_why_locked, error->message);
2075 }
2076 }
2077
2078 dbus_message_unref (message);
2079 return FALSE;
2080 }
2081
2082 dbus_message_unref (message);
2083
2084 if (reply == NULL)
2085 return FALSE;
2086
2087 dbus_message_unref (reply);
2088
2089 return TRUE;
2090 }
2091
2092 /**
2093 * libhal_device_unlock:
2094 * @ctx: the context for the connection to hald
2095 * @udi: the Unique Device Id
2096 * @error: pointer to an initialized dbus error object for returning errors or NULL
2097 *
2098 * Release an advisory lock on the device.
2099 *
2100 * Returns: TRUE if the device was successfully unlocked,
2101 * FALSE otherwise
2102 */
2103 dbus_bool_t
libhal_device_unlock(LibHalContext * ctx,const char * udi,DBusError * error)2104 libhal_device_unlock (LibHalContext *ctx,
2105 const char *udi, DBusError *error)
2106 {
2107 DBusMessage *message;
2108 DBusMessage *reply;
2109
2110 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2111
2112 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2113 udi,
2114 "org.freedesktop.Hal.Device",
2115 "Unlock");
2116
2117 if (message == NULL) {
2118 fprintf (stderr,
2119 "%s %d : Couldn't allocate D-BUS message\n",
2120 __FILE__, __LINE__);
2121 return FALSE;
2122 }
2123
2124
2125 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2126 message, -1,
2127 error);
2128
2129 if (error != NULL && dbus_error_is_set (error)) {
2130 dbus_message_unref (message);
2131 return FALSE;
2132 }
2133
2134 dbus_message_unref (message);
2135
2136 if (reply == NULL)
2137 return FALSE;
2138
2139 dbus_message_unref (reply);
2140
2141 return TRUE;
2142 }
2143
2144
2145 /**
2146 * libhal_new_device:
2147 * @ctx: the context for the connection to hald
2148 * @error: pointer to an initialized dbus error object for returning errors or NULL
2149 *
2150 * Create a new device object which will be hidden from applications
2151 * until the CommitToGdl(), ie. libhal_device_commit_to_gdl(), method
2152 * is called. Note that the program invoking this method needs to run
2153 * with super user privileges.
2154 *
2155 * Returns: Temporary device unique id or NULL if there was a
2156 * problem. This string must be freed by the caller.
2157 */
2158 char *
libhal_new_device(LibHalContext * ctx,DBusError * error)2159 libhal_new_device (LibHalContext *ctx, DBusError *error)
2160 {
2161 DBusMessage *message;
2162 DBusMessage *reply;
2163 DBusMessageIter reply_iter;
2164 char *value;
2165 char *dbus_str;
2166
2167 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2168
2169 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2170 "/org/freedesktop/Hal/Manager",
2171 "org.freedesktop.Hal.Manager",
2172 "NewDevice");
2173 if (message == NULL) {
2174 fprintf (stderr,
2175 "%s %d : Couldn't allocate D-BUS message\n",
2176 __FILE__, __LINE__);
2177 return NULL;
2178 }
2179
2180
2181 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2182 message, -1,
2183 error);
2184 if (error != NULL && dbus_error_is_set (error)) {
2185 dbus_message_unref (message);
2186 return NULL;
2187 }
2188 if (reply == NULL) {
2189 dbus_message_unref (message);
2190 return NULL;
2191 }
2192
2193 dbus_message_iter_init (reply, &reply_iter);
2194
2195 /* now analyze reply */
2196 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_STRING) {
2197 fprintf (stderr,
2198 "%s %d : expected a string in reply to NewDevice\n",
2199 __FILE__, __LINE__);
2200 dbus_message_unref (message);
2201 dbus_message_unref (reply);
2202 return NULL;
2203 }
2204
2205 dbus_message_iter_get_basic (&reply_iter, &dbus_str);
2206 value = (char *) ((dbus_str != NULL) ? strdup (dbus_str) : NULL);
2207 if (value == NULL) {
2208 fprintf (stderr, "%s %d : error allocating memory\n",
2209 __FILE__, __LINE__);
2210 }
2211
2212 dbus_message_unref (message);
2213 dbus_message_unref (reply);
2214 return value;
2215 }
2216
2217
2218 /**
2219 * libhal_device_commit_to_gdl:
2220 * @ctx: the context for the connection to hald
2221 * @temp_udi: the temporary unique device id as returned by libhal_new_device()
2222 * @udi: the new unique device id.
2223 * @error: pointer to an initialized dbus error object for returning errors or NULL
2224 *
2225 * When a hidden device has been built using the NewDevice method,
2226 * ie. libhal_new_device(), and the org.freedesktop.Hal.Device
2227 * interface this function will commit it to the global device list.
2228 *
2229 * This means that the device object will be visible to applications
2230 * and the HAL daemon will possibly attempt to boot the device
2231 * (depending on the property RequireEnable).
2232 *
2233 * Note that the program invoking this method needs to run with super
2234 * user privileges.
2235 *
2236 * Returns: FALSE if the given unique device id is already in use.
2237 */
2238 dbus_bool_t
libhal_device_commit_to_gdl(LibHalContext * ctx,const char * temp_udi,const char * udi,DBusError * error)2239 libhal_device_commit_to_gdl (LibHalContext *ctx,
2240 const char *temp_udi, const char *udi, DBusError *error)
2241 {
2242 DBusMessage *message;
2243 DBusMessage *reply;
2244 DBusMessageIter iter;
2245
2246 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2247
2248 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2249 "/org/freedesktop/Hal/Manager",
2250 "org.freedesktop.Hal.Manager",
2251 "CommitToGdl");
2252 if (message == NULL) {
2253 fprintf (stderr,
2254 "%s %d : Couldn't allocate D-BUS message\n",
2255 __FILE__, __LINE__);
2256 return FALSE;
2257 }
2258
2259 dbus_message_iter_init_append (message, &iter);
2260 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &temp_udi);
2261 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
2262
2263
2264 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2265 message, -1,
2266 error);
2267 if (error != NULL && dbus_error_is_set (error)) {
2268 dbus_message_unref (message);
2269 return FALSE;
2270 }
2271 if (reply == NULL) {
2272 dbus_message_unref (message);
2273 return FALSE;
2274 }
2275
2276 dbus_message_unref (message);
2277 dbus_message_unref (reply);
2278 return TRUE;
2279 }
2280
2281 /**
2282 * libhal_remove_device:
2283 * @ctx: the context for the connection to hald
2284 * @udi: the Unique device id.
2285 * @error: pointer to an initialized dbus error object for returning errors or NULL
2286 *
2287 * This method can be invoked when a device is removed. The HAL daemon
2288 * will shut down the device. Note that the device may still be in the
2289 * device list if the Persistent property is set to true.
2290 *
2291 * Note that the program invoking this method needs to run with super
2292 * user privileges.
2293 *
2294 * Returns: TRUE if the device was removed, FALSE otherwise
2295 */
2296 dbus_bool_t
libhal_remove_device(LibHalContext * ctx,const char * udi,DBusError * error)2297 libhal_remove_device (LibHalContext *ctx, const char *udi, DBusError *error)
2298 {
2299 DBusMessage *message;
2300 DBusMessage *reply;
2301 DBusMessageIter iter;
2302
2303 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2304
2305 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2306 "/org/freedesktop/Hal/Manager",
2307 "org.freedesktop.Hal.Manager",
2308 "Remove");
2309 if (message == NULL) {
2310 fprintf (stderr,
2311 "%s %d : Couldn't allocate D-BUS message\n",
2312 __FILE__, __LINE__);
2313 return FALSE;
2314 }
2315
2316 dbus_message_iter_init_append (message, &iter);
2317 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
2318
2319
2320 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2321 message, -1,
2322 error);
2323 if (error != NULL && dbus_error_is_set (error)) {
2324 dbus_message_unref (message);
2325 return FALSE;
2326 }
2327 if (reply == NULL) {
2328 dbus_message_unref (message);
2329 return FALSE;
2330 }
2331
2332 dbus_message_unref (message);
2333 dbus_message_unref (reply);
2334 return TRUE;
2335 }
2336
2337 /**
2338 * libhal_device_exists:
2339 * @ctx: the context for the connection to hald
2340 * @udi: the Unique device id.
2341 * @error: pointer to an initialized dbus error object for returning errors or NULL
2342 *
2343 * Determine if a device exists.
2344 *
2345 * Returns: TRUE if the device exists
2346 */
2347 dbus_bool_t
libhal_device_exists(LibHalContext * ctx,const char * udi,DBusError * error)2348 libhal_device_exists (LibHalContext *ctx, const char *udi, DBusError *error)
2349 {
2350 DBusMessage *message;
2351 DBusMessage *reply;
2352 DBusMessageIter iter, reply_iter;
2353 dbus_bool_t value;
2354 DBusError _error;
2355
2356 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2357
2358 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2359 "/org/freedesktop/Hal/Manager",
2360 "org.freedesktop.Hal.Manager",
2361 "DeviceExists");
2362 if (message == NULL) {
2363 fprintf (stderr,
2364 "%s %d : Couldn't allocate D-BUS message\n",
2365 __FILE__, __LINE__);
2366 return FALSE;
2367 }
2368
2369 dbus_message_iter_init_append (message, &iter);
2370 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &udi);
2371
2372 dbus_error_init (&_error);
2373 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2374 message, -1,
2375 &_error);
2376
2377 dbus_move_error (&_error, error);
2378 if (error != NULL && dbus_error_is_set (error)) {
2379 dbus_message_unref (message);
2380 return FALSE;
2381 }
2382 if (reply == NULL) {
2383 dbus_message_unref (message);
2384 return FALSE;
2385 }
2386
2387 dbus_message_iter_init (reply, &reply_iter);
2388
2389 /* now analyze reply */
2390 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
2391 fprintf (stderr,
2392 "%s %d : expected a bool in reply to DeviceExists\n",
2393 __FILE__, __LINE__);
2394 dbus_message_unref (message);
2395 dbus_message_unref (reply);
2396 return FALSE;
2397 }
2398
2399 dbus_message_iter_get_basic (&reply_iter, &value);
2400
2401 dbus_message_unref (message);
2402 dbus_message_unref (reply);
2403 return value;
2404 }
2405
2406 /**
2407 * libhal_device_property_exists:
2408 * @ctx: the context for the connection to hald
2409 * @udi: the Unique device id.
2410 * @key: name of the property
2411 * @error: pointer to an initialized dbus error object for returning errors or NULL
2412 *
2413 * Determine if a property on a device exists.
2414 *
2415 * Returns: TRUE if the device exists, FALSE otherwise
2416 */
2417 dbus_bool_t
libhal_device_property_exists(LibHalContext * ctx,const char * udi,const char * key,DBusError * error)2418 libhal_device_property_exists (LibHalContext *ctx,
2419 const char *udi, const char *key, DBusError *error)
2420 {
2421 DBusMessage *message;
2422 DBusMessage *reply;
2423 DBusMessageIter iter, reply_iter;
2424 dbus_bool_t value;
2425 DBusError _error;
2426
2427 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2428
2429 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2430 "org.freedesktop.Hal.Device",
2431 "PropertyExists");
2432 if (message == NULL) {
2433 fprintf (stderr,
2434 "%s %d : Couldn't allocate D-BUS message\n",
2435 __FILE__, __LINE__);
2436 return FALSE;
2437 }
2438
2439 dbus_message_iter_init_append (message, &iter);
2440 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2441
2442 dbus_error_init (&_error);
2443 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2444 message, -1,
2445 &_error);
2446
2447 dbus_move_error (&_error, error);
2448 if (error != NULL && dbus_error_is_set (error)) {
2449 dbus_message_unref (message);
2450 return FALSE;
2451 }
2452 if (reply == NULL) {
2453 dbus_message_unref (message);
2454 return FALSE;
2455 }
2456
2457 dbus_message_iter_init (reply, &reply_iter);
2458
2459 /* now analyse reply */
2460 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
2461 fprintf (stderr, "%s %d : expected a bool in reply to "
2462 "PropertyExists\n", __FILE__, __LINE__);
2463 dbus_message_unref (message);
2464 dbus_message_unref (reply);
2465 return FALSE;
2466 }
2467
2468 dbus_message_iter_get_basic (&reply_iter, &value);
2469
2470 dbus_message_unref (message);
2471 dbus_message_unref (reply);
2472 return value;
2473 }
2474
2475 /**
2476 * libhal_merge_properties:
2477 * @ctx: the context for the connection to hald
2478 * @target_udi: the Unique device id of target device to merge to
2479 * @source_udi: the Unique device id of device to merge from
2480 * @error: pointer to an initialized dbus error object for returning errors or NULL
2481 *
2482 * Merge properties from one device to another.
2483 *
2484 * Returns: TRUE if the properties were merged, FALSE otherwise
2485 */
2486 dbus_bool_t
libhal_merge_properties(LibHalContext * ctx,const char * target_udi,const char * source_udi,DBusError * error)2487 libhal_merge_properties (LibHalContext *ctx,
2488 const char *target_udi, const char *source_udi, DBusError *error)
2489 {
2490 DBusMessage *message;
2491 DBusMessage *reply;
2492 DBusMessageIter iter;
2493
2494 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2495
2496 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2497 "/org/freedesktop/Hal/Manager",
2498 "org.freedesktop.Hal.Manager",
2499 "MergeProperties");
2500 if (message == NULL) {
2501 fprintf (stderr,
2502 "%s %d : Couldn't allocate D-BUS message\n",
2503 __FILE__, __LINE__);
2504 return FALSE;
2505 }
2506
2507 dbus_message_iter_init_append (message, &iter);
2508 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &target_udi);
2509 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &source_udi);
2510
2511
2512 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2513 message, -1,
2514 error);
2515 if (error != NULL && dbus_error_is_set (error)) {
2516 dbus_message_unref (message);
2517 return FALSE;
2518 }
2519 if (reply == NULL) {
2520 dbus_message_unref (message);
2521 return FALSE;
2522 }
2523
2524 dbus_message_unref (message);
2525 dbus_message_unref (reply);
2526 return TRUE;
2527 }
2528
2529 /**
2530 * libhal_device_matches:
2531 * @ctx: the context for the connection to hald
2532 * @udi1: the Unique Device Id for device 1
2533 * @udi2: the Unique Device Id for device 2
2534 * @property_namespace: the namespace for set of devices, e.g. "usb"
2535 * @error: pointer to an initialized dbus error object for returning errors or NULL
2536 *
2537 * Check a set of properties for two devices matches.
2538 *
2539 * Checks that all properties where keys, starting with a given value
2540 * (namespace), of the first device is in the second device and that
2541 * they got the same value and type.
2542 *
2543 * Note that the other inclusion isn't tested, so there could be
2544 * properties (from the given namespace) in the second device not
2545 * present in the first device.
2546 *
2547 * Returns: TRUE if all properties starting with the given namespace
2548 * parameter from one device is in the other and have the same value.
2549 */
2550 dbus_bool_t
libhal_device_matches(LibHalContext * ctx,const char * udi1,const char * udi2,const char * property_namespace,DBusError * error)2551 libhal_device_matches (LibHalContext *ctx,
2552 const char *udi1, const char *udi2,
2553 const char *property_namespace, DBusError *error)
2554 {
2555 DBusMessage *message;
2556 DBusMessage *reply;
2557 DBusMessageIter iter, reply_iter;
2558 dbus_bool_t value;
2559 DBusError _error;
2560
2561 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2562
2563 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2564 "/org/freedesktop/Hal/Manager",
2565 "org.freedesktop.Hal.Manager",
2566 "DeviceMatches");
2567 if (message == NULL) {
2568 fprintf (stderr,
2569 "%s %d : Couldn't allocate D-BUS message\n",
2570 __FILE__, __LINE__);
2571 return FALSE;
2572 }
2573
2574 dbus_message_iter_init_append (message, &iter);
2575 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi1);
2576 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, udi2);
2577 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, property_namespace);
2578
2579 dbus_error_init (&_error);
2580 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2581 message, -1,
2582 &_error);
2583
2584 dbus_move_error (&_error, error);
2585 if (error != NULL && dbus_error_is_set (error)) {
2586 dbus_message_unref (message);
2587 return FALSE;
2588 }
2589 if (reply == NULL) {
2590 dbus_message_unref (message);
2591 return FALSE;
2592 }
2593 /* now analyse reply */
2594 dbus_message_iter_init (reply, &reply_iter);
2595
2596 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
2597 fprintf (stderr,
2598 "%s %d : expected a bool in reply to DeviceMatches\n",
2599 __FILE__, __LINE__);
2600 dbus_message_unref (message);
2601 dbus_message_unref (reply);
2602 return FALSE;
2603 }
2604
2605 dbus_message_iter_get_basic (&reply_iter, &value);
2606
2607 dbus_message_unref (message);
2608 dbus_message_unref (reply);
2609 return value;
2610 }
2611
2612 /**
2613 * libhal_device_print:
2614 * @ctx: the context for the connection to hald
2615 * @udi: the Unique Device Id
2616 * @error: pointer to an initialized dbus error object for returning errors or NULL
2617 *
2618 * Print a device to stdout; useful for debugging.
2619 *
2620 * Returns: TRUE if device's information could be obtained, FALSE otherwise
2621 */
2622 dbus_bool_t
libhal_device_print(LibHalContext * ctx,const char * udi,DBusError * error)2623 libhal_device_print (LibHalContext *ctx, const char *udi, DBusError *error)
2624 {
2625 int type;
2626 char *key;
2627 LibHalPropertySet *pset;
2628 LibHalPropertySetIterator i;
2629
2630 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2631
2632 printf ("device_id = %s\n", udi);
2633
2634 if ((pset = libhal_device_get_all_properties (ctx, udi, error)) == NULL)
2635 return FALSE;
2636
2637 for (libhal_psi_init (&i, pset); libhal_psi_has_more (&i);
2638 libhal_psi_next (&i)) {
2639 type = libhal_psi_get_type (&i);
2640 key = libhal_psi_get_key (&i);
2641
2642 switch (type) {
2643 case LIBHAL_PROPERTY_TYPE_STRING:
2644 printf (" %s = '%s' (string)\n", key,
2645 libhal_psi_get_string (&i));
2646 break;
2647 case LIBHAL_PROPERTY_TYPE_INT32:
2648 printf (" %s = %d = 0x%x (int)\n", key,
2649 libhal_psi_get_int (&i),
2650 libhal_psi_get_int (&i));
2651 break;
2652 case LIBHAL_PROPERTY_TYPE_UINT64:
2653 printf (" %s = %llu = 0x%llx (uint64)\n", key,
2654 (long long unsigned int) libhal_psi_get_uint64 (&i),
2655 (long long unsigned int) libhal_psi_get_uint64 (&i));
2656 break;
2657 case LIBHAL_PROPERTY_TYPE_BOOLEAN:
2658 printf (" %s = %s (bool)\n", key,
2659 (libhal_psi_get_bool (&i) ? "true" :
2660 "false"));
2661 break;
2662 case LIBHAL_PROPERTY_TYPE_DOUBLE:
2663 printf (" %s = %g (double)\n", key,
2664 libhal_psi_get_double (&i));
2665 break;
2666 case LIBHAL_PROPERTY_TYPE_STRLIST:
2667 {
2668 unsigned int j;
2669 char **str_list;
2670
2671 str_list = libhal_psi_get_strlist (&i);
2672 printf (" %s = [", key);
2673 for (j = 0; str_list[j] != NULL; j++) {
2674 printf ("'%s'", str_list[j]);
2675 if (str_list[j+1] != NULL)
2676 printf (", ");
2677 }
2678 printf ("] (string list)\n");
2679
2680 break;
2681 }
2682 default:
2683 printf (" *** unknown type for key %s\n", key);
2684 break;
2685 }
2686 }
2687
2688 libhal_free_property_set (pset);
2689
2690 return TRUE;
2691 }
2692
2693 /**
2694 * libhal_manager_find_device_string_match:
2695 * @ctx: the context for the connection to hald
2696 * @key: name of the property
2697 * @value: the value to match
2698 * @num_devices: pointer to store number of devices
2699 * @error: pointer to an initialized dbus error object for returning errors or NULL
2700 *
2701 * Find a device in the GDL where a single string property matches a
2702 * given value.
2703 *
2704 * Returns: UDI of devices; free with libhal_free_string_array()
2705 */
2706 char **
libhal_manager_find_device_string_match(LibHalContext * ctx,const char * key,const char * value,int * num_devices,DBusError * error)2707 libhal_manager_find_device_string_match (LibHalContext *ctx,
2708 const char *key,
2709 const char *value, int *num_devices, DBusError *error)
2710 {
2711 DBusMessage *message;
2712 DBusMessage *reply;
2713 DBusMessageIter iter, iter_array, reply_iter;
2714 char **hal_device_names;
2715 DBusError _error;
2716
2717 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2718
2719 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2720 "/org/freedesktop/Hal/Manager",
2721 "org.freedesktop.Hal.Manager",
2722 "FindDeviceStringMatch");
2723 if (message == NULL) {
2724 fprintf (stderr,
2725 "%s %d : Couldn't allocate D-BUS message\n",
2726 __FILE__, __LINE__);
2727 return NULL;
2728 }
2729
2730 dbus_message_iter_init_append (message, &iter);
2731 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &key);
2732 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &value);
2733
2734 dbus_error_init (&_error);
2735 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2736 message, -1,
2737 &_error);
2738
2739 dbus_move_error (&_error, error);
2740 if (error != NULL && dbus_error_is_set (error)) {
2741 dbus_message_unref (message);
2742 return NULL;
2743 }
2744 if (reply == NULL) {
2745 dbus_message_unref (message);
2746 return NULL;
2747 }
2748 /* now analyse reply */
2749 dbus_message_iter_init (reply, &reply_iter);
2750
2751 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
2752 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
2753 return NULL;
2754 }
2755
2756 dbus_message_iter_recurse (&reply_iter, &iter_array);
2757
2758 hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
2759
2760 dbus_message_unref (reply);
2761 dbus_message_unref (message);
2762
2763 return hal_device_names;
2764 }
2765
2766
2767 /**
2768 * libhal_device_add_capability:
2769 * @ctx: the context for the connection to hald
2770 * @udi: the Unique Device Id
2771 * @capability: the capability name to add
2772 * @error: pointer to an initialized dbus error object for returning errors or NULL
2773 *
2774 * Assign a capability to a device.
2775 *
2776 * Returns: TRUE if the capability was added, FALSE if the device didn't exist
2777 */
2778 dbus_bool_t
libhal_device_add_capability(LibHalContext * ctx,const char * udi,const char * capability,DBusError * error)2779 libhal_device_add_capability (LibHalContext *ctx,
2780 const char *udi, const char *capability, DBusError *error)
2781 {
2782 DBusMessage *message;
2783 DBusMessage *reply;
2784 DBusMessageIter iter;
2785
2786 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2787
2788 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
2789 "org.freedesktop.Hal.Device",
2790 "AddCapability");
2791 if (message == NULL) {
2792 fprintf (stderr,
2793 "%s %d : Couldn't allocate D-BUS message\n",
2794 __FILE__, __LINE__);
2795 return FALSE;
2796 }
2797
2798 dbus_message_iter_init_append (message, &iter);
2799 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
2800
2801
2802 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2803 message, -1,
2804 error);
2805 if (error != NULL && dbus_error_is_set (error)) {
2806 dbus_message_unref (message);
2807 return FALSE;
2808 }
2809
2810 if (reply == NULL) {
2811 dbus_message_unref (message);
2812 return FALSE;
2813 }
2814
2815 dbus_message_unref (reply);
2816 dbus_message_unref (message);
2817 return TRUE;
2818 }
2819
2820 /**
2821 * libhal_device_query_capability:
2822 * @ctx: the context for the connection to hald
2823 * @udi: the Unique Device Id
2824 * @capability: the capability name
2825 * @error: pointer to an initialized dbus error object for returning errors or NULL
2826 *
2827 * Check if a device has a capability. The result is undefined if the
2828 * device doesn't exist.
2829 *
2830 * Returns: TRUE if the device has the capability, otherwise FALSE
2831 */
2832 dbus_bool_t
libhal_device_query_capability(LibHalContext * ctx,const char * udi,const char * capability,DBusError * error)2833 libhal_device_query_capability (LibHalContext *ctx, const char *udi, const char *capability, DBusError *error)
2834 {
2835 char **caps;
2836 unsigned int i;
2837 dbus_bool_t ret;
2838
2839 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2840
2841 ret = FALSE;
2842
2843 caps = libhal_device_get_property_strlist (ctx, udi, "info.capabilities", error);
2844 if (caps != NULL) {
2845 for (i = 0; caps[i] != NULL; i++) {
2846 if (strcmp (caps[i], capability) == 0) {
2847 ret = TRUE;
2848 break;
2849 }
2850 }
2851 libhal_free_string_array (caps);
2852 }
2853
2854 return ret;
2855 }
2856
2857 /**
2858 * libhal_find_device_by_capability:
2859 * @ctx: the context for the connection to hald
2860 * @capability: the capability name
2861 * @num_devices: pointer to store number of devices
2862 * @error: pointer to an initialized dbus error object for returning errors or NULL
2863 *
2864 * Find devices with a given capability.
2865 *
2866 * Returns: UDI of devices; free with libhal_free_string_array()
2867 */
2868 char **
libhal_find_device_by_capability(LibHalContext * ctx,const char * capability,int * num_devices,DBusError * error)2869 libhal_find_device_by_capability (LibHalContext *ctx,
2870 const char *capability, int *num_devices, DBusError *error)
2871 {
2872 DBusMessage *message;
2873 DBusMessage *reply;
2874 DBusMessageIter iter, iter_array, reply_iter;
2875 char **hal_device_names;
2876 DBusError _error;
2877
2878 LIBHAL_CHECK_LIBHALCONTEXT(ctx, NULL);
2879
2880 message = dbus_message_new_method_call ("org.freedesktop.Hal",
2881 "/org/freedesktop/Hal/Manager",
2882 "org.freedesktop.Hal.Manager",
2883 "FindDeviceByCapability");
2884 if (message == NULL) {
2885 fprintf (stderr,
2886 "%s %d : Couldn't allocate D-BUS message\n",
2887 __FILE__, __LINE__);
2888 return NULL;
2889 }
2890
2891 dbus_message_iter_init_append (message, &iter);
2892 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &capability);
2893
2894 dbus_error_init (&_error);
2895 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
2896 message, -1,
2897 &_error);
2898
2899 dbus_move_error (&_error, error);
2900 if (error != NULL && dbus_error_is_set (error)) {
2901 dbus_message_unref (message);
2902 return NULL;
2903 }
2904 if (reply == NULL) {
2905 dbus_message_unref (message);
2906 return NULL;
2907 }
2908 /* now analyse reply */
2909 dbus_message_iter_init (reply, &reply_iter);
2910
2911 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_ARRAY) {
2912 fprintf (stderr, "%s %d : wrong reply from hald. Expecting an array.\n", __FILE__, __LINE__);
2913 return NULL;
2914 }
2915
2916 dbus_message_iter_recurse (&reply_iter, &iter_array);
2917
2918 hal_device_names = libhal_get_string_array_from_iter (&iter_array, num_devices);
2919
2920 dbus_message_unref (reply);
2921 dbus_message_unref (message);
2922
2923 return hal_device_names;
2924 }
2925
2926 /**
2927 * libhal_device_property_watch_all:
2928 * @ctx: the context for the connection to hald
2929 * @error: pointer to an initialized dbus error object for returning errors or NULL
2930 *
2931 * Watch all devices, ie. the device_property_changed callback is
2932 * invoked when the properties on any device changes.
2933 *
2934 * Returns: TRUE only if the operation succeeded
2935 */
2936 dbus_bool_t
libhal_device_property_watch_all(LibHalContext * ctx,DBusError * error)2937 libhal_device_property_watch_all (LibHalContext *ctx, DBusError *error)
2938 {
2939 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2940
2941 dbus_bus_add_match (ctx->connection,
2942 "type='signal',"
2943 "interface='org.freedesktop.Hal.Device',"
2944 "sender='org.freedesktop.Hal'", error);
2945 if (error != NULL && dbus_error_is_set (error)) {
2946 return FALSE;
2947 }
2948 return TRUE;
2949 }
2950
2951
2952 /**
2953 * libhal_device_add_property_watch:
2954 * @ctx: the context for the connection to hald
2955 * @udi: the Unique Device Id
2956 * @error: pointer to an initialized dbus error object for returning errors or NULL
2957 *
2958 * Add a watch on a device, so the device_property_changed callback is
2959 * invoked when the properties on the given device changes.
2960 *
2961 * The application itself is responsible for deleting the watch, using
2962 * libhal_device_remove_property_watch, if the device is removed.
2963 *
2964 * Returns: TRUE only if the operation succeeded
2965 */
2966 dbus_bool_t
libhal_device_add_property_watch(LibHalContext * ctx,const char * udi,DBusError * error)2967 libhal_device_add_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
2968 {
2969 char buf[512];
2970
2971 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
2972
2973 snprintf (buf, 512,
2974 "type='signal',"
2975 "interface='org.freedesktop.Hal.Device',"
2976 "sender='org.freedesktop.Hal'," "path=%s", udi);
2977
2978 dbus_bus_add_match (ctx->connection, buf, error);
2979 if (error != NULL && dbus_error_is_set (error)) {
2980 return FALSE;
2981 }
2982 return TRUE;
2983 }
2984
2985
2986 /**
2987 * libhal_device_remove_property_watch:
2988 * @ctx: the context for the connection to hald
2989 * @udi: the Unique Device Id
2990 * @error: pointer to an initialized dbus error object for returning errors or NULL
2991 *
2992 * Remove a watch on a device.
2993 *
2994 * Returns: TRUE only if the operation succeeded
2995 */
2996 dbus_bool_t
libhal_device_remove_property_watch(LibHalContext * ctx,const char * udi,DBusError * error)2997 libhal_device_remove_property_watch (LibHalContext *ctx, const char *udi, DBusError *error)
2998 {
2999 char buf[512];
3000
3001 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3002
3003 snprintf (buf, 512,
3004 "type='signal',"
3005 "interface='org.freedesktop.Hal.Device',"
3006 "sender='org.freedesktop.Hal'," "path=%s", udi);
3007
3008 dbus_bus_remove_match (ctx->connection, buf, error);
3009 if (error != NULL && dbus_error_is_set (error)) {
3010 return FALSE;
3011 }
3012 return TRUE;
3013 }
3014
3015
3016 /**
3017 * libhal_ctx_new:
3018 *
3019 * Create a new LibHalContext
3020 *
3021 * Returns: a new uninitialized LibHalContext object
3022 */
3023 LibHalContext *
libhal_ctx_new(void)3024 libhal_ctx_new (void)
3025 {
3026 LibHalContext *ctx;
3027
3028 if (!libhal_already_initialized_once) {
3029 bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
3030 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
3031
3032 libhal_already_initialized_once = TRUE;
3033 }
3034
3035 ctx = calloc (1, sizeof (LibHalContext));
3036 if (ctx == NULL) {
3037 fprintf (stderr,
3038 "%s %d : Failed to allocate %d bytes\n",
3039 __FILE__, __LINE__, sizeof (LibHalContext));
3040 return NULL;
3041 }
3042
3043 ctx->is_initialized = FALSE;
3044 ctx->is_shutdown = FALSE;
3045 ctx->connection = NULL;
3046 ctx->is_direct = FALSE;
3047
3048 return ctx;
3049 }
3050
3051 /**
3052 * libhal_ctx_set_cache:
3053 * @ctx: context to enable/disable cache for
3054 * @use_cache: whether or not to use cache
3055 *
3056 * Enable or disable caching. Note: Caching is not actually
3057 * implemented yet.
3058 *
3059 * Returns: TRUE if cache was successfully enabled/disabled, FALSE otherwise
3060 */
3061 dbus_bool_t
libhal_ctx_set_cache(LibHalContext * ctx,dbus_bool_t use_cache)3062 libhal_ctx_set_cache (LibHalContext *ctx, dbus_bool_t use_cache)
3063 {
3064 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3065
3066 ctx->cache_enabled = use_cache;
3067 return TRUE;
3068 }
3069
3070 /**
3071 * libhal_ctx_set_dbus_connection:
3072 * @ctx: context to set connection for
3073 * @conn: DBus connection to use
3074 *
3075 * Set DBus connection to use to talk to hald.
3076 *
3077 * Returns: TRUE if connection was successfully set, FALSE otherwise
3078 */
3079 dbus_bool_t
libhal_ctx_set_dbus_connection(LibHalContext * ctx,DBusConnection * conn)3080 libhal_ctx_set_dbus_connection (LibHalContext *ctx, DBusConnection *conn)
3081 {
3082 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3083
3084 if (conn == NULL)
3085 return FALSE;
3086
3087 ctx->connection = conn;
3088 return TRUE;
3089 }
3090
3091 /**
3092 * libhal_ctx_get_dbus_connection:
3093 * @ctx: context to get connection for
3094 *
3095 * Get DBus connection used for talking to hald.
3096 *
3097 * Returns: DBus connection to use or NULL
3098 */
3099 DBusConnection *
libhal_ctx_get_dbus_connection(LibHalContext * ctx)3100 libhal_ctx_get_dbus_connection (LibHalContext *ctx)
3101 {
3102 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3103
3104 return ctx->connection;
3105 }
3106
3107
3108 /**
3109 * libhal_ctx_init:
3110 * @ctx: Context for connection to hald (D-BUS connection should be set with libhal_ctx_set_dbus_connection)
3111 * @error: pointer to an initialized dbus error object for returning errors or NULL
3112 *
3113 * Initialize the connection to hald.
3114 *
3115 * Returns: TRUE if initialization succeeds, FALSE otherwise
3116 */
3117 dbus_bool_t
libhal_ctx_init(LibHalContext * ctx,DBusError * error)3118 libhal_ctx_init (LibHalContext *ctx, DBusError *error)
3119 {
3120 DBusError _error;
3121 dbus_bool_t hald_exists;
3122
3123 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3124
3125 if (ctx->connection == NULL)
3126 return FALSE;
3127
3128 dbus_error_init (&_error);
3129 hald_exists = dbus_bus_name_has_owner (ctx->connection, "org.freedesktop.Hal", &_error);
3130 dbus_move_error (&_error, error);
3131 if (error != NULL && dbus_error_is_set (error)) {
3132 return FALSE;
3133 }
3134
3135 if (!hald_exists) {
3136 return FALSE;
3137 }
3138
3139
3140 if (!dbus_connection_add_filter (ctx->connection, filter_func, ctx, NULL)) {
3141 return FALSE;
3142 }
3143
3144 dbus_bus_add_match (ctx->connection,
3145 "type='signal',"
3146 "interface='org.freedesktop.Hal.Manager',"
3147 "sender='org.freedesktop.Hal',"
3148 "path='/org/freedesktop/Hal/Manager'", &_error);
3149 dbus_move_error (&_error, error);
3150 if (error != NULL && dbus_error_is_set (error)) {
3151 return FALSE;
3152 }
3153 ctx->is_initialized = TRUE;
3154 ctx->is_direct = FALSE;
3155
3156 return TRUE;
3157 }
3158
3159 /**
3160 * libhal_ctx_init_direct:
3161 * @error: pointer to an initialized dbus error object for returning errors or NULL
3162 *
3163 * Create an already initialized connection to hald. This function should only be used by HAL helpers.
3164 *
3165 * Returns: A pointer to an already initialized LibHalContext
3166 */
3167 LibHalContext *
libhal_ctx_init_direct(DBusError * error)3168 libhal_ctx_init_direct (DBusError *error)
3169 {
3170 char *hald_addr;
3171 LibHalContext *ctx;
3172 DBusError _error;
3173
3174 ctx = libhal_ctx_new ();
3175 if (ctx == NULL)
3176 goto out;
3177
3178 if (((hald_addr = getenv ("HALD_DIRECT_ADDR"))) == NULL) {
3179 libhal_ctx_free (ctx);
3180 ctx = NULL;
3181 goto out;
3182 }
3183
3184 dbus_error_init (&_error);
3185 ctx->connection = dbus_connection_open (hald_addr, &_error);
3186 dbus_move_error (&_error, error);
3187 if (error != NULL && dbus_error_is_set (error)) {
3188 libhal_ctx_free (ctx);
3189 ctx = NULL;
3190 goto out;
3191 }
3192
3193 ctx->is_initialized = TRUE;
3194 ctx->is_direct = TRUE;
3195
3196 out:
3197 return ctx;
3198 }
3199
3200 /**
3201 * libhal_ctx_shutdown:
3202 * @ctx: the context for the connection to hald
3203 * @error: pointer to an initialized dbus error object for returning errors or NULL
3204 *
3205 * Shut down a connection to hald.
3206 *
3207 * Returns: TRUE if connection successfully shut down, FALSE otherwise
3208 */
3209 dbus_bool_t
libhal_ctx_shutdown(LibHalContext * ctx,DBusError * error)3210 libhal_ctx_shutdown (LibHalContext *ctx, DBusError *error)
3211 {
3212 DBusError myerror;
3213
3214 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3215
3216 if (ctx->is_direct) {
3217 /* for some reason dbus_connection_set_exit_on_disconnect doesn't work yet so don't unref */
3218 /*dbus_connection_unref (ctx->connection);*/
3219 } else {
3220 dbus_error_init (&myerror);
3221 dbus_bus_remove_match (ctx->connection,
3222 "type='signal',"
3223 "interface='org.freedesktop.Hal.Manager',"
3224 "sender='org.freedesktop.Hal',"
3225 "path='/org/freedesktop/Hal/Manager'", &myerror);
3226 dbus_move_error(&myerror, error);
3227 if (error != NULL && dbus_error_is_set(error)) {
3228 fprintf (stderr, "%s %d : Error unsubscribing to signals, error=%s\n",
3229 __FILE__, __LINE__, error->message);
3230 /** @todo clean up */
3231 }
3232
3233 /* TODO: remove other matches */
3234
3235 dbus_connection_remove_filter (ctx->connection, filter_func, ctx);
3236 }
3237
3238 ctx->is_initialized = FALSE;
3239
3240 return TRUE;
3241 }
3242
3243 /**
3244 * libhal_ctx_free:
3245 * @ctx: pointer to a LibHalContext
3246 *
3247 * Free a LibHalContext resource.
3248 *
3249 * Returns: TRUE
3250 */
3251 dbus_bool_t
libhal_ctx_free(LibHalContext * ctx)3252 libhal_ctx_free (LibHalContext *ctx)
3253 {
3254 free (ctx);
3255 return TRUE;
3256 }
3257
3258 /**
3259 * libhal_ctx_set_device_added:
3260 * @ctx: the context for the connection to hald
3261 * @callback: the function to call when a device is added
3262 *
3263 * Set the callback for when a device is added
3264 *
3265 * Returns: TRUE if callback was successfully set, FALSE otherwise
3266 */
3267 dbus_bool_t
libhal_ctx_set_device_added(LibHalContext * ctx,LibHalDeviceAdded callback)3268 libhal_ctx_set_device_added (LibHalContext *ctx, LibHalDeviceAdded callback)
3269 {
3270 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3271
3272 ctx->device_added = callback;
3273 return TRUE;
3274 }
3275
3276 /**
3277 * libhal_ctx_set_device_removed:
3278 * @ctx: the context for the connection to hald
3279 * @callback: the function to call when a device is removed
3280 *
3281 * Set the callback for when a device is removed.
3282 *
3283 * Returns: TRUE if callback was successfully set, FALSE otherwise
3284 */
3285 dbus_bool_t
libhal_ctx_set_device_removed(LibHalContext * ctx,LibHalDeviceRemoved callback)3286 libhal_ctx_set_device_removed (LibHalContext *ctx, LibHalDeviceRemoved callback)
3287 {
3288 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3289
3290 ctx->device_removed = callback;
3291 return TRUE;
3292 }
3293
3294 /**
3295 * libhal_ctx_set_device_new_capability:
3296 * @ctx: the context for the connection to hald
3297 * @callback: the function to call when a device gains a new capability
3298 *
3299 * Set the callback for when a device gains a new capability.
3300 *
3301 * Returns: TRUE if callback was successfully set, FALSE otherwise
3302 */
3303 dbus_bool_t
libhal_ctx_set_device_new_capability(LibHalContext * ctx,LibHalDeviceNewCapability callback)3304 libhal_ctx_set_device_new_capability (LibHalContext *ctx, LibHalDeviceNewCapability callback)
3305 {
3306 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3307
3308 ctx->device_new_capability = callback;
3309 return TRUE;
3310 }
3311
3312 /**
3313 * libhal_ctx_set_device_lost_capability:
3314 * @ctx: the context for the connection to hald
3315 * @callback: the function to call when a device loses a capability
3316 *
3317 * Set the callback for when a device loses a capability
3318 *
3319 * Returns: TRUE if callback was successfully set, FALSE otherwise
3320 */
3321 dbus_bool_t
libhal_ctx_set_device_lost_capability(LibHalContext * ctx,LibHalDeviceLostCapability callback)3322 libhal_ctx_set_device_lost_capability (LibHalContext *ctx, LibHalDeviceLostCapability callback)
3323 {
3324 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3325
3326 ctx->device_lost_capability = callback;
3327 return TRUE;
3328 }
3329
3330 /**
3331 * libhal_ctx_set_device_property_modified:
3332 * @ctx: the context for the connection to hald
3333 * @callback: the function to call when a property is modified on a device
3334 *
3335 * Set the callback for when a property is modified on a device.
3336 *
3337 * Returns: TRUE if callback was successfully set, FALSE otherwise
3338 */
3339 dbus_bool_t
libhal_ctx_set_device_property_modified(LibHalContext * ctx,LibHalDevicePropertyModified callback)3340 libhal_ctx_set_device_property_modified (LibHalContext *ctx, LibHalDevicePropertyModified callback)
3341 {
3342 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3343
3344 ctx->device_property_modified = callback;
3345 return TRUE;
3346 }
3347
3348 /**
3349 * libhal_ctx_set_device_condition:
3350 * @ctx: the context for the connection to hald
3351 * @callback: the function to call when a device emits a condition
3352 *
3353 * Set the callback for when a device emits a condition
3354 *
3355 * Returns: TRUE if callback was successfully set, FALSE otherwise
3356 */
3357 dbus_bool_t
libhal_ctx_set_device_condition(LibHalContext * ctx,LibHalDeviceCondition callback)3358 libhal_ctx_set_device_condition (LibHalContext *ctx, LibHalDeviceCondition callback)
3359 {
3360 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3361
3362 ctx->device_condition = callback;
3363 return TRUE;
3364 }
3365
3366 /**
3367 * libhal_string_array_length:
3368 * @str_array: array of strings to consider
3369 *
3370 * Get the length of an array of strings.
3371 *
3372 * Returns: Number of strings in array
3373 */
3374 unsigned int
libhal_string_array_length(char ** str_array)3375 libhal_string_array_length (char **str_array)
3376 {
3377 unsigned int i;
3378
3379 if (str_array == NULL)
3380 return 0;
3381
3382 for (i = 0; str_array[i] != NULL; i++)
3383 ;
3384
3385 return i;
3386 }
3387
3388
3389 /**
3390 * libhal_device_rescan:
3391 * @ctx: the context for the connection to hald
3392 * @udi: the Unique id of device
3393 * @error: pointer to an initialized dbus error object for returning errors or NULL
3394 *
3395 * TODO document me.
3396 *
3397 * Returns: Whether the operation succeeded
3398 */
3399 dbus_bool_t
libhal_device_rescan(LibHalContext * ctx,const char * udi,DBusError * error)3400 libhal_device_rescan (LibHalContext *ctx, const char *udi, DBusError *error)
3401 {
3402 DBusMessage *message;
3403 DBusMessageIter reply_iter;
3404 DBusMessage *reply;
3405 dbus_bool_t result;
3406
3407 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3408
3409 message = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
3410 "org.freedesktop.Hal.Device",
3411 "Rescan");
3412
3413 if (message == NULL) {
3414 fprintf (stderr,
3415 "%s %d : Couldn't allocate D-BUS message\n",
3416 __FILE__, __LINE__);
3417 return FALSE;
3418 }
3419
3420 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3421 message, -1,
3422 error);
3423
3424 if (error != NULL && dbus_error_is_set (error)) {
3425 dbus_message_unref (message);
3426 return FALSE;
3427 }
3428
3429 dbus_message_unref (message);
3430
3431 if (reply == NULL)
3432 return FALSE;
3433
3434 dbus_message_iter_init (reply, &reply_iter);
3435 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3436 DBUS_TYPE_BOOLEAN) {
3437 dbus_message_unref (message);
3438 dbus_message_unref (reply);
3439 return FALSE;
3440 }
3441 dbus_message_iter_get_basic (&reply_iter, &result);
3442
3443 dbus_message_unref (reply);
3444
3445 return result;
3446 }
3447
3448 /**
3449 * libhal_device_reprobe:
3450 * @ctx: the context for the connection to hald
3451 * @udi: the Unique id of device
3452 * @error: pointer to an initialized dbus error object for returning errors or NULL
3453 *
3454 * TODO document me.
3455 *
3456 * Returns: Whether the operation succeeded
3457 */
3458 dbus_bool_t
libhal_device_reprobe(LibHalContext * ctx,const char * udi,DBusError * error)3459 libhal_device_reprobe (LibHalContext *ctx, const char *udi, DBusError *error)
3460 {
3461 DBusMessage *message;
3462 DBusMessageIter reply_iter;
3463 DBusMessage *reply;
3464 dbus_bool_t result;
3465
3466 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3467
3468 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3469 udi,
3470 "org.freedesktop.Hal.Device",
3471 "Reprobe");
3472
3473 if (message == NULL) {
3474 fprintf (stderr,
3475 "%s %d : Couldn't allocate D-BUS message\n",
3476 __FILE__, __LINE__);
3477 return FALSE;
3478 }
3479
3480 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3481 message, -1,
3482 error);
3483
3484 if (error != NULL && dbus_error_is_set (error)) {
3485 dbus_message_unref (message);
3486 return FALSE;
3487 }
3488
3489 dbus_message_unref (message);
3490
3491 if (reply == NULL)
3492 return FALSE;
3493
3494 dbus_message_iter_init (reply, &reply_iter);
3495 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3496 DBUS_TYPE_BOOLEAN) {
3497 dbus_message_unref (message);
3498 dbus_message_unref (reply);
3499 return FALSE;
3500 }
3501 dbus_message_iter_get_basic (&reply_iter, &result);
3502
3503 dbus_message_unref (reply);
3504
3505 return result;
3506 }
3507
3508 /**
3509 * libhal_device_emit_condition:
3510 * @ctx: the context for the connection to hald
3511 * @udi: the Unique Device Id
3512 * @condition_name: user-readable name of condition
3513 * @condition_details: user-readable details of condition
3514 * @error: pointer to an initialized dbus error object for returning errors or NULL
3515 *
3516 * Emit a condition from a device. Can only be used from hald helpers.
3517 *
3518 * Returns: TRUE if condition successfully emitted,
3519 * FALSE otherwise
3520 */
libhal_device_emit_condition(LibHalContext * ctx,const char * udi,const char * condition_name,const char * condition_details,DBusError * error)3521 dbus_bool_t libhal_device_emit_condition (LibHalContext *ctx,
3522 const char *udi,
3523 const char *condition_name,
3524 const char *condition_details,
3525 DBusError *error)
3526 {
3527 DBusMessage *message;
3528 DBusMessageIter iter;
3529 DBusMessageIter reply_iter;
3530 DBusMessage *reply;
3531 dbus_bool_t result;
3532
3533 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3534
3535 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3536 udi,
3537 "org.freedesktop.Hal.Device",
3538 "EmitCondition");
3539
3540 if (message == NULL) {
3541 fprintf (stderr,
3542 "%s %d : Couldn't allocate D-BUS message\n",
3543 __FILE__, __LINE__);
3544 return FALSE;
3545 }
3546
3547 dbus_message_iter_init_append (message, &iter);
3548 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_name);
3549 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &condition_details);
3550
3551 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3552 message, -1,
3553 error);
3554
3555 if (error != NULL && dbus_error_is_set (error)) {
3556 dbus_message_unref (message);
3557 return FALSE;
3558 }
3559
3560 dbus_message_unref (message);
3561
3562 if (reply == NULL)
3563 return FALSE;
3564
3565 dbus_message_iter_init (reply, &reply_iter);
3566 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3567 DBUS_TYPE_BOOLEAN) {
3568 dbus_message_unref (message);
3569 dbus_message_unref (reply);
3570 return FALSE;
3571 }
3572 dbus_message_iter_get_basic (&reply_iter, &result);
3573
3574 dbus_message_unref (reply);
3575
3576 return result;
3577 }
3578
3579 /**
3580 * libhal_device_addon_is_ready:
3581 * @ctx: the context for the connection to hald
3582 * @udi: the Unique Device Id
3583 * @error: pointer to an initialized dbus error object for returning errors or NULL
3584 *
3585 * HAL addon's must call this method when they are done initializing the device object. The HAL
3586 * daemon will wait for all addon's to call this.
3587 *
3588 * Can only be used from hald helpers.
3589 *
3590 * Returns: TRUE if the HAL daemon received the message, FALSE otherwise
3591 */
3592 dbus_bool_t
libhal_device_addon_is_ready(LibHalContext * ctx,const char * udi,DBusError * error)3593 libhal_device_addon_is_ready (LibHalContext *ctx, const char *udi, DBusError *error)
3594 {
3595 DBusMessage *message;
3596 DBusMessageIter iter;
3597 DBusMessageIter reply_iter;
3598 DBusMessage *reply;
3599 dbus_bool_t result;
3600
3601 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3602
3603 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3604 udi,
3605 "org.freedesktop.Hal.Device",
3606 "AddonIsReady");
3607
3608 if (message == NULL) {
3609 fprintf (stderr,
3610 "%s %d : Couldn't allocate D-BUS message\n",
3611 __FILE__, __LINE__);
3612 return FALSE;
3613 }
3614
3615 dbus_message_iter_init_append (message, &iter);
3616
3617 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3618 message, -1,
3619 error);
3620
3621 if (error != NULL && dbus_error_is_set (error)) {
3622 dbus_message_unref (message);
3623 return FALSE;
3624 }
3625
3626 dbus_message_unref (message);
3627
3628 if (reply == NULL)
3629 return FALSE;
3630
3631 dbus_message_iter_init (reply, &reply_iter);
3632 if (dbus_message_iter_get_arg_type (&reply_iter) != DBUS_TYPE_BOOLEAN) {
3633 dbus_message_unref (message);
3634 dbus_message_unref (reply);
3635 return FALSE;
3636 }
3637 dbus_message_iter_get_basic (&reply_iter, &result);
3638
3639 dbus_message_unref (reply);
3640 return result;
3641 }
3642
3643 /**
3644 * libhal_device_claim_interface:
3645 * @ctx: the context for the connection to hald
3646 * @udi: the Unique Device Id
3647 * @interface_name: Name of interface to claim, e.g. org.freedesktop.Hal.Device.FoobarKindOfThing
3648 * @introspection_xml: Introspection XML containing what would be inside the interface XML tag
3649 * @error: pointer to an initialized dbus error object for returning errors or NULL
3650 *
3651 * Claim an interface for a device. All messages to this interface
3652 * will be forwarded to the helper. Can only be used from hald
3653 * helpers.
3654 *
3655 * Returns: TRUE if interface was claimed, FALSE otherwise
3656 */
3657 dbus_bool_t
libhal_device_claim_interface(LibHalContext * ctx,const char * udi,const char * interface_name,const char * introspection_xml,DBusError * error)3658 libhal_device_claim_interface (LibHalContext *ctx,
3659 const char *udi,
3660 const char *interface_name,
3661 const char *introspection_xml,
3662 DBusError *error)
3663 {
3664 DBusMessage *message;
3665 DBusMessageIter iter;
3666 DBusMessageIter reply_iter;
3667 DBusMessage *reply;
3668 dbus_bool_t result;
3669
3670 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
3671
3672 message = dbus_message_new_method_call ("org.freedesktop.Hal",
3673 udi,
3674 "org.freedesktop.Hal.Device",
3675 "ClaimInterface");
3676
3677 if (message == NULL) {
3678 fprintf (stderr,
3679 "%s %d : Couldn't allocate D-BUS message\n",
3680 __FILE__, __LINE__);
3681 return FALSE;
3682 }
3683
3684 dbus_message_iter_init_append (message, &iter);
3685 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &interface_name);
3686 dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &introspection_xml);
3687
3688 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
3689 message, -1,
3690 error);
3691
3692 if (error != NULL && dbus_error_is_set (error)) {
3693 dbus_message_unref (message);
3694 return FALSE;
3695 }
3696
3697 dbus_message_unref (message);
3698
3699 if (reply == NULL)
3700 return FALSE;
3701
3702 dbus_message_iter_init (reply, &reply_iter);
3703 if (dbus_message_iter_get_arg_type (&reply_iter) !=
3704 DBUS_TYPE_BOOLEAN) {
3705 dbus_message_unref (message);
3706 dbus_message_unref (reply);
3707 return FALSE;
3708 }
3709 dbus_message_iter_get_basic (&reply_iter, &result);
3710
3711 dbus_message_unref (reply);
3712
3713 return result;
3714 }
3715
3716
3717
3718 struct LibHalChangeSetElement_s;
3719
3720 typedef struct LibHalChangeSetElement_s LibHalChangeSetElement;
3721
3722 struct LibHalChangeSetElement_s {
3723 char *key;
3724 int change_type;
3725 union {
3726 char *val_str;
3727 dbus_int32_t val_int;
3728 dbus_uint64_t val_uint64;
3729 double val_double;
3730 dbus_bool_t val_bool;
3731 char **val_strlist;
3732 } value;
3733 LibHalChangeSetElement *next;
3734 LibHalChangeSetElement *prev;
3735 };
3736
3737 struct LibHalChangeSet_s {
3738 char *udi;
3739 LibHalChangeSetElement *head;
3740 LibHalChangeSetElement *tail;
3741 };
3742
3743 /**
3744 * libhal_device_new_changeset:
3745 * @udi: unique device identifier
3746 *
3747 * Request a new changeset object. Used for changing multiple properties at once. Useful when
3748 * performance is critical and also for atomically updating several properties.
3749 *
3750 * Returns: A new changeset object or NULL on error
3751 */
3752 LibHalChangeSet *
libhal_device_new_changeset(const char * udi)3753 libhal_device_new_changeset (const char *udi)
3754 {
3755 LibHalChangeSet *changeset;
3756
3757 changeset = calloc (1, sizeof (LibHalChangeSet));
3758 if (changeset == NULL)
3759 goto out;
3760
3761 changeset->udi = strdup (udi);
3762 if (changeset->udi == NULL) {
3763 free (changeset);
3764 changeset = NULL;
3765 goto out;
3766 }
3767
3768 changeset->head = NULL;
3769 changeset->tail = NULL;
3770
3771 out:
3772 return changeset;
3773 }
3774
3775 static void
libhal_changeset_append(LibHalChangeSet * changeset,LibHalChangeSetElement * elem)3776 libhal_changeset_append (LibHalChangeSet *changeset, LibHalChangeSetElement *elem)
3777 {
3778 if (changeset->head == NULL) {
3779 changeset->head = elem;
3780 changeset->tail = elem;
3781 elem->next = NULL;
3782 elem->prev = NULL;
3783 } else {
3784 elem->prev = changeset->tail;
3785 elem->next = NULL;
3786 elem->prev->next = elem;
3787 changeset->tail = elem;
3788 }
3789 }
3790
3791
3792 /**
3793 * libhal_device_set_property_string:
3794 * @changeset: the changeset
3795 * @key: key of property
3796 * @value: the value to set
3797 *
3798 * Set a property.
3799 *
3800 * Returns: FALSE on OOM
3801 */
3802 dbus_bool_t
libhal_changeset_set_property_string(LibHalChangeSet * changeset,const char * key,const char * value)3803 libhal_changeset_set_property_string (LibHalChangeSet *changeset, const char *key, const char *value)
3804 {
3805 LibHalChangeSetElement *elem;
3806
3807 elem = calloc (1, sizeof (LibHalChangeSetElement));
3808 if (elem == NULL)
3809 goto out;
3810 elem->key = strdup (key);
3811 if (elem->key == NULL) {
3812 free (elem);
3813 elem = NULL;
3814 goto out;
3815 }
3816
3817 elem->change_type = LIBHAL_PROPERTY_TYPE_STRING;
3818 elem->value.val_str = strdup (value);
3819 if (elem->value.val_str == NULL) {
3820 free (elem->key);
3821 free (elem);
3822 elem = NULL;
3823 goto out;
3824 }
3825
3826 libhal_changeset_append (changeset, elem);
3827 out:
3828 return elem != NULL;
3829 }
3830
3831 /**
3832 * libhal_device_set_property_int:
3833 * @changeset: the changeset
3834 * @key: key of property
3835 * @value: the value to set
3836 *
3837 * Set a property.
3838 *
3839 * Returns: FALSE on OOM
3840 */
3841 dbus_bool_t
libhal_changeset_set_property_int(LibHalChangeSet * changeset,const char * key,dbus_int32_t value)3842 libhal_changeset_set_property_int (LibHalChangeSet *changeset, const char *key, dbus_int32_t value)
3843 {
3844 LibHalChangeSetElement *elem;
3845
3846 elem = calloc (1, sizeof (LibHalChangeSetElement));
3847 if (elem == NULL)
3848 goto out;
3849 elem->key = strdup (key);
3850 if (elem->key == NULL) {
3851 free (elem);
3852 elem = NULL;
3853 goto out;
3854 }
3855
3856 elem->change_type = LIBHAL_PROPERTY_TYPE_INT32;
3857 elem->value.val_int = value;
3858
3859 libhal_changeset_append (changeset, elem);
3860 out:
3861 return elem != NULL;
3862 }
3863
3864 /**
3865 * libhal_device_set_property_uint64:
3866 * @changeset: the changeset
3867 * @key: key of property
3868 * @value: the value to set
3869 *
3870 * Set a property.
3871 *
3872 * Returns: FALSE on OOM
3873 */
3874 dbus_bool_t
libhal_changeset_set_property_uint64(LibHalChangeSet * changeset,const char * key,dbus_uint64_t value)3875 libhal_changeset_set_property_uint64 (LibHalChangeSet *changeset, const char *key, dbus_uint64_t value)
3876 {
3877 LibHalChangeSetElement *elem;
3878
3879 elem = calloc (1, sizeof (LibHalChangeSetElement));
3880 if (elem == NULL)
3881 goto out;
3882 elem->key = strdup (key);
3883 if (elem->key == NULL) {
3884 free (elem);
3885 elem = NULL;
3886 goto out;
3887 }
3888
3889 elem->change_type = LIBHAL_PROPERTY_TYPE_UINT64;
3890 elem->value.val_uint64 = value;
3891
3892 libhal_changeset_append (changeset, elem);
3893 out:
3894 return elem != NULL;
3895 }
3896
3897 /**
3898 * libhal_device_set_property_double:
3899 * @changeset: the changeset
3900 * @key: key of property
3901 * @value: the value to set
3902 *
3903 * Set a property.
3904 *
3905 * Returns: FALSE on OOM
3906 */
3907 dbus_bool_t
libhal_changeset_set_property_double(LibHalChangeSet * changeset,const char * key,double value)3908 libhal_changeset_set_property_double (LibHalChangeSet *changeset, const char *key, double value)
3909 {
3910 LibHalChangeSetElement *elem;
3911
3912 elem = calloc (1, sizeof (LibHalChangeSetElement));
3913 if (elem == NULL)
3914 goto out;
3915 elem->key = strdup (key);
3916 if (elem->key == NULL) {
3917 free (elem);
3918 elem = NULL;
3919 goto out;
3920 }
3921
3922 elem->change_type = LIBHAL_PROPERTY_TYPE_DOUBLE;
3923 elem->value.val_double = value;
3924
3925 libhal_changeset_append (changeset, elem);
3926 out:
3927 return elem != NULL;
3928 }
3929
3930 /**
3931 * libhal_device_set_property_bool:
3932 * @changeset: the changeset
3933 * @key: key of property
3934 * @value: the value to set
3935 *
3936 * Set a property.
3937 *
3938 * Returns: FALSE on OOM
3939 */
3940 dbus_bool_t
libhal_changeset_set_property_bool(LibHalChangeSet * changeset,const char * key,dbus_bool_t value)3941 libhal_changeset_set_property_bool (LibHalChangeSet *changeset, const char *key, dbus_bool_t value)
3942 {
3943 LibHalChangeSetElement *elem;
3944
3945 elem = calloc (1, sizeof (LibHalChangeSetElement));
3946 if (elem == NULL)
3947 goto out;
3948 elem->key = strdup (key);
3949 if (elem->key == NULL) {
3950 free (elem);
3951 elem = NULL;
3952 goto out;
3953 }
3954
3955 elem->change_type = LIBHAL_PROPERTY_TYPE_BOOLEAN;
3956 elem->value.val_bool = value;
3957
3958 libhal_changeset_append (changeset, elem);
3959 out:
3960 return elem != NULL;
3961 }
3962
3963 /**
3964 * libhal_device_set_property_strlist:
3965 * @changeset: the changeset
3966 * @key: key of property
3967 * @value: the value to set - NULL terminated array of strings
3968 *
3969 * Set a property.
3970 *
3971 * Returns: FALSE on OOM
3972 */
3973 dbus_bool_t
libhal_changeset_set_property_strlist(LibHalChangeSet * changeset,const char * key,const char ** value)3974 libhal_changeset_set_property_strlist (LibHalChangeSet *changeset, const char *key, const char **value)
3975 {
3976 LibHalChangeSetElement *elem;
3977 char **value_copy;
3978 int len;
3979 int i, j;
3980
3981 elem = calloc (1, sizeof (LibHalChangeSetElement));
3982 if (elem == NULL)
3983 goto out;
3984 elem->key = strdup (key);
3985 if (elem->key == NULL) {
3986 free (elem);
3987 elem = NULL;
3988 goto out;
3989 }
3990
3991 for (i = 0; value[i] != NULL; i++)
3992 ;
3993 len = i;
3994
3995 value_copy = calloc (len + 1, sizeof (char *));
3996 if (value_copy == NULL) {
3997 free (elem->key);
3998 free (elem);
3999 elem = NULL;
4000 goto out;
4001 }
4002
4003 for (i = 0; i < len; i++) {
4004 value_copy[i] = strdup (value[i]);
4005 if (value_copy[i] == NULL) {
4006 for (j = 0; j < i; j++) {
4007 free (value_copy[j]);
4008 }
4009 free (value_copy);
4010 free (elem->key);
4011 free (elem);
4012 elem = NULL;
4013 goto out;
4014 }
4015 }
4016 value_copy[i] = NULL;
4017
4018 elem->change_type = LIBHAL_PROPERTY_TYPE_STRLIST;
4019 elem->value.val_strlist = value_copy;
4020
4021 libhal_changeset_append (changeset, elem);
4022 out:
4023 return elem != NULL;
4024 }
4025
4026 /**
4027 * libhal_device_commit_changeset:
4028 * @ctx: the context for the connection to hald
4029 * @changeset: the changeset to commit
4030 * @error: pointer to an initialized dbus error object for returning errors or NULL
4031 *
4032 * Commit a changeset to the daemon.
4033 *
4034 * Returns: True if the changeset was committed on the daemon side
4035 */
4036 dbus_bool_t
libhal_device_commit_changeset(LibHalContext * ctx,LibHalChangeSet * changeset,DBusError * error)4037 libhal_device_commit_changeset (LibHalContext *ctx, LibHalChangeSet *changeset, DBusError *error)
4038 {
4039 LibHalChangeSetElement *elem;
4040 DBusMessage *message;
4041 DBusMessage *reply;
4042 DBusError _error;
4043 DBusMessageIter iter;
4044 DBusMessageIter sub;
4045 DBusMessageIter sub2;
4046 DBusMessageIter sub3;
4047 DBusMessageIter sub4;
4048 int i;
4049
4050 LIBHAL_CHECK_LIBHALCONTEXT(ctx, FALSE);
4051
4052 if (changeset->head == NULL) {
4053 return TRUE;
4054 }
4055
4056 message = dbus_message_new_method_call ("org.freedesktop.Hal", changeset->udi,
4057 "org.freedesktop.Hal.Device",
4058 "SetMultipleProperties");
4059
4060 if (message == NULL) {
4061 fprintf (stderr, "%s %d : Couldn't allocate D-BUS message\n", __FILE__, __LINE__);
4062 return FALSE;
4063 }
4064
4065 dbus_message_iter_init_append (message, &iter);
4066
4067 dbus_message_iter_open_container (&iter,
4068 DBUS_TYPE_ARRAY,
4069 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
4070 DBUS_TYPE_STRING_AS_STRING
4071 DBUS_TYPE_VARIANT_AS_STRING
4072 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
4073 &sub);
4074
4075 for (elem = changeset->head; elem != NULL; elem = elem->next) {
4076 dbus_message_iter_open_container (&sub,
4077 DBUS_TYPE_DICT_ENTRY,
4078 NULL,
4079 &sub2);
4080 dbus_message_iter_append_basic (&sub2, DBUS_TYPE_STRING, &(elem->key));
4081
4082 switch (elem->change_type) {
4083 case LIBHAL_PROPERTY_TYPE_STRING:
4084 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub3);
4085 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_STRING, &(elem->value.val_str));
4086 dbus_message_iter_close_container (&sub2, &sub3);
4087 break;
4088 case LIBHAL_PROPERTY_TYPE_STRLIST:
4089 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT,
4090 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING, &sub3);
4091 dbus_message_iter_open_container (&sub3, DBUS_TYPE_ARRAY,
4092 DBUS_TYPE_STRING_AS_STRING, &sub4);
4093 for (i = 0; elem->value.val_strlist[i] != NULL; i++) {
4094 dbus_message_iter_append_basic (&sub4, DBUS_TYPE_STRING,
4095 &(elem->value.val_strlist[i]));
4096 }
4097 dbus_message_iter_close_container (&sub3, &sub4);
4098 dbus_message_iter_close_container (&sub2, &sub3);
4099 break;
4100 case LIBHAL_PROPERTY_TYPE_INT32:
4101 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub3);
4102 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_INT32, &(elem->value.val_int));
4103 dbus_message_iter_close_container (&sub2, &sub3);
4104 break;
4105 case LIBHAL_PROPERTY_TYPE_UINT64:
4106 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_UINT64_AS_STRING, &sub3);
4107 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_UINT64, &(elem->value.val_uint64));
4108 dbus_message_iter_close_container (&sub2, &sub3);
4109 break;
4110 case LIBHAL_PROPERTY_TYPE_DOUBLE:
4111 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub3);
4112 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_DOUBLE, &(elem->value.val_double));
4113 dbus_message_iter_close_container (&sub2, &sub3);
4114 break;
4115 case LIBHAL_PROPERTY_TYPE_BOOLEAN:
4116 dbus_message_iter_open_container (&sub2, DBUS_TYPE_VARIANT, DBUS_TYPE_BOOLEAN_AS_STRING,&sub3);
4117 dbus_message_iter_append_basic (&sub3, DBUS_TYPE_BOOLEAN, &(elem->value.val_bool));
4118 dbus_message_iter_close_container (&sub2, &sub3);
4119 break;
4120 default:
4121 fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
4122 break;
4123 }
4124 dbus_message_iter_close_container (&sub, &sub2);
4125 }
4126
4127 dbus_message_iter_close_container (&iter, &sub);
4128
4129
4130 dbus_error_init (&_error);
4131 reply = dbus_connection_send_with_reply_and_block (ctx->connection,
4132 message, -1,
4133 &_error);
4134
4135 dbus_move_error (&_error, error);
4136 if (error != NULL && dbus_error_is_set (error)) {
4137 fprintf (stderr,
4138 "%s %d : %s\n",
4139 __FILE__, __LINE__, error->message);
4140
4141 dbus_message_unref (message);
4142 return FALSE;
4143 }
4144
4145 if (reply == NULL) {
4146 dbus_message_unref (message);
4147 return FALSE;
4148 }
4149
4150 return TRUE;
4151 }
4152
4153 /**
4154 * libhal_device_free_changeset:
4155 * @changeset: the changeset to free
4156 *
4157 * Free a changeset.
4158 */
4159 void
libhal_device_free_changeset(LibHalChangeSet * changeset)4160 libhal_device_free_changeset (LibHalChangeSet *changeset)
4161 {
4162 LibHalChangeSetElement *elem;
4163 LibHalChangeSetElement *elem2;
4164
4165 for (elem = changeset->head; elem != NULL; elem = elem2) {
4166 elem2 = elem->next;
4167
4168 switch (elem->change_type) {
4169 case LIBHAL_PROPERTY_TYPE_STRING:
4170 free (elem->value.val_str);
4171 break;
4172 case LIBHAL_PROPERTY_TYPE_STRLIST:
4173 libhal_free_string_array (elem->value.val_strlist);
4174 break;
4175 /* explicit fallthrough */
4176 case LIBHAL_PROPERTY_TYPE_INT32:
4177 case LIBHAL_PROPERTY_TYPE_UINT64:
4178 case LIBHAL_PROPERTY_TYPE_DOUBLE:
4179 case LIBHAL_PROPERTY_TYPE_BOOLEAN:
4180 break;
4181 default:
4182 fprintf (stderr, "%s %d : unknown change_type %d\n", __FILE__, __LINE__, elem->change_type);
4183 break;
4184 }
4185 free (elem);
4186 }
4187
4188 free (changeset->udi);
4189 free (changeset);
4190 }
4191