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