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 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 ** 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 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 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* 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 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 * 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 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 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 * 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 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 * 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 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 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 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 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 * 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 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 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 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 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 * 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 * 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 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 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 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 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 ** 940 libhal_psi_get_strlist (LibHalPropertySetIterator * iter) 941 { 942 return iter->cur_prop->v.strlist_value; 943 } 944 945 946 static DBusHandlerResult 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 ** 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 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 ** 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 ** 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 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 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 ** 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 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 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 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 * 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 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 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 * 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 * 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 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 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 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 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 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 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 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 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 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