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