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