1 /*************************************************************************** 2 * CVSID: $Id$ 3 * 4 * device.c : HalDevice methods 5 * 6 * Copyright (C) 2003 David Zeuthen, <david@fubar.dk> 7 * Copyright (C) 2004 Novell, Inc. 8 * 9 * Licensed under the Academic Free License version 2.1 10 * 11 * This program is free software; you can redistribute it and/or modify 12 * it under the terms of the GNU General Public License as published by 13 * the Free Software Foundation; either version 2 of the License, or 14 * (at your option) any later version. 15 * 16 * This program is distributed in the hope that it will be useful, 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 * GNU General Public License for more details. 20 * 21 * You should have received a copy of the GNU General Public License 22 * along with this program; if not, write to the Free Software 23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24 * 25 **************************************************************************/ 26 27 #ifdef HAVE_CONFIG_H 28 # include <config.h> 29 #endif 30 31 #include <stdio.h> 32 #include <string.h> 33 34 #include "hald.h" 35 #include "device.h" 36 #include "hald_marshal.h" 37 #include "logger.h" 38 #include "hald_runner.h" 39 40 static GObjectClass *parent_class; 41 42 enum { 43 PROPERTY_CHANGED, 44 CAPABILITY_ADDED, 45 CALLOUTS_FINISHED, 46 CANCELLED, 47 LAST_SIGNAL 48 }; 49 50 static guint signals[LAST_SIGNAL] = { 0 }; 51 52 #ifdef HALD_MEMLEAK_DBG 53 int dbg_hal_device_object_delta = 0; 54 #endif 55 56 static void 57 hal_device_finalize (GObject *obj) 58 { 59 HalDevice *device = HAL_DEVICE (obj); 60 61 runner_device_finalized (device); 62 63 #ifdef HALD_MEMLEAK_DBG 64 dbg_hal_device_object_delta--; 65 printf ("************* in finalize for udi=%s\n", device->udi); 66 #endif 67 68 69 g_slist_foreach (device->properties, (GFunc) hal_property_free, NULL); 70 71 g_slist_free (device->properties); 72 73 g_free (device->udi); 74 75 if (parent_class->finalize) 76 parent_class->finalize (obj); 77 78 } 79 80 static void 81 hal_device_class_init (HalDeviceClass *klass) 82 { 83 GObjectClass *obj_class = (GObjectClass *) klass; 84 85 parent_class = g_type_class_peek_parent (klass); 86 87 obj_class->finalize = hal_device_finalize; 88 89 signals[PROPERTY_CHANGED] = 90 g_signal_new ("property_changed", 91 G_TYPE_FROM_CLASS (klass), 92 G_SIGNAL_RUN_LAST, 93 G_STRUCT_OFFSET (HalDeviceClass, 94 property_changed), 95 NULL, NULL, 96 hald_marshal_VOID__STRING_BOOL_BOOL, 97 G_TYPE_NONE, 3, 98 G_TYPE_STRING, 99 G_TYPE_BOOLEAN, 100 G_TYPE_BOOLEAN); 101 102 signals[CAPABILITY_ADDED] = 103 g_signal_new ("capability_added", 104 G_TYPE_FROM_CLASS (klass), 105 G_SIGNAL_RUN_LAST, 106 G_STRUCT_OFFSET (HalDeviceClass, 107 capability_added), 108 NULL, NULL, 109 hald_marshal_VOID__STRING, 110 G_TYPE_NONE, 1, 111 G_TYPE_STRING); 112 113 signals[CALLOUTS_FINISHED] = 114 g_signal_new ("callouts_finished", 115 G_TYPE_FROM_CLASS (klass), 116 G_SIGNAL_RUN_LAST, 117 G_STRUCT_OFFSET (HalDeviceClass, 118 callouts_finished), 119 NULL, NULL, 120 hald_marshal_VOID__VOID, 121 G_TYPE_NONE, 0); 122 123 signals[CANCELLED] = 124 g_signal_new ("cancelled", 125 G_TYPE_FROM_CLASS (klass), 126 G_SIGNAL_RUN_LAST, 127 G_STRUCT_OFFSET (HalDeviceClass, 128 cancelled), 129 NULL, NULL, 130 hald_marshal_VOID__VOID, 131 G_TYPE_NONE, 0); 132 } 133 134 static void 135 hal_device_init (HalDevice *device) 136 { 137 static int temp_device_counter = 0; 138 139 device->udi = g_strdup_printf ("/org/freedesktop/Hal/devices/temp/%d", 140 temp_device_counter++); 141 device->num_addons = 0; 142 device->num_addons_ready = 0; 143 } 144 145 GType 146 hal_device_get_type (void) 147 { 148 static GType type = 0; 149 150 if (!type) { 151 static GTypeInfo type_info = { 152 sizeof (HalDeviceClass), 153 NULL, NULL, 154 (GClassInitFunc) hal_device_class_init, 155 NULL, NULL, 156 sizeof (HalDevice), 157 0, 158 (GInstanceInitFunc) hal_device_init, 159 NULL 160 }; 161 162 type = g_type_register_static (G_TYPE_OBJECT, 163 "HalDevice", 164 &type_info, 165 0); 166 } 167 168 return type; 169 } 170 171 172 HalDevice * 173 hal_device_new (void) 174 { 175 HalDevice *device; 176 177 device = g_object_new (HAL_TYPE_DEVICE, NULL, NULL); 178 179 #ifdef HALD_MEMLEAK_DBG 180 dbg_hal_device_object_delta++; 181 #endif 182 return device; 183 } 184 185 /** Merge all properties from source where the key starts with 186 * source_namespace and put them onto target replacing source_namespace 187 * with target_namespace 188 * 189 * @param target Device to put properties onto 190 * @param source Device to retrieve properties from 191 * @param target_namespace Replace source namespace with this namespace 192 * @param source_namespace Source namespace that property keys must match 193 */ 194 void 195 hal_device_merge_with_rewrite (HalDevice *target, 196 HalDevice *source, 197 const char *target_namespace, 198 const char *source_namespace) 199 { 200 GSList *iter; 201 size_t source_ns_len; 202 203 source_ns_len = strlen (source_namespace); 204 205 /* doesn't handle info.capabilities */ 206 207 /* device_property_atomic_update_begin (); */ 208 209 for (iter = source->properties; iter != NULL; iter = iter->next) { 210 HalProperty *p = iter->data; 211 int type; 212 const char *key; 213 int target_type; 214 gchar *target_key; 215 216 key = hal_property_get_key (p); 217 218 /* only care about properties that match source namespace */ 219 if (strncmp(key, source_namespace, source_ns_len) != 0) 220 continue; 221 222 target_key = g_strdup_printf("%s%s", target_namespace, 223 key+source_ns_len); 224 225 type = hal_property_get_type (p); 226 227 /* only remove target if it exists with a different type */ 228 target_type = hal_device_property_get_type (target, key); 229 if (target_type != HAL_PROPERTY_TYPE_INVALID && target_type != type) 230 hal_device_property_remove (target, key); 231 232 switch (type) { 233 234 case HAL_PROPERTY_TYPE_STRING: 235 hal_device_property_set_string ( 236 target, target_key, 237 hal_property_get_string (p)); 238 break; 239 240 case HAL_PROPERTY_TYPE_INT32: 241 hal_device_property_set_int ( 242 target, target_key, 243 hal_property_get_int (p)); 244 break; 245 246 case HAL_PROPERTY_TYPE_UINT64: 247 hal_device_property_set_uint64 ( 248 target, target_key, 249 hal_property_get_uint64 (p)); 250 break; 251 252 case HAL_PROPERTY_TYPE_BOOLEAN: 253 hal_device_property_set_bool ( 254 target, target_key, 255 hal_property_get_bool (p)); 256 break; 257 258 case HAL_PROPERTY_TYPE_DOUBLE: 259 hal_device_property_set_double ( 260 target, target_key, 261 hal_property_get_double (p)); 262 break; 263 264 default: 265 HAL_WARNING (("Unknown property type %d", type)); 266 break; 267 } 268 269 g_free (target_key); 270 } 271 272 /* device_property_atomic_update_end (); */ 273 274 } 275 276 void 277 hal_device_merge (HalDevice *target, HalDevice *source) 278 { 279 GSList *iter; 280 GSList *caps; 281 282 /* device_property_atomic_update_begin (); */ 283 284 for (iter = source->properties; iter != NULL; iter = iter->next) { 285 HalProperty *p = iter->data; 286 int type; 287 const char *key; 288 int target_type; 289 290 key = hal_property_get_key (p); 291 type = hal_property_get_type (p); 292 293 /* handle info.capabilities in a special way */ 294 if (strcmp (key, "info.capabilities") == 0) 295 continue; 296 297 /* only remove target if it exists with a different type */ 298 target_type = hal_device_property_get_type (target, key); 299 if (target_type != HAL_PROPERTY_TYPE_INVALID && target_type != type) 300 hal_device_property_remove (target, key); 301 302 switch (type) { 303 304 case HAL_PROPERTY_TYPE_STRING: 305 hal_device_property_set_string ( 306 target, key, 307 hal_property_get_string (p)); 308 break; 309 310 case HAL_PROPERTY_TYPE_INT32: 311 hal_device_property_set_int ( 312 target, key, 313 hal_property_get_int (p)); 314 break; 315 316 case HAL_PROPERTY_TYPE_UINT64: 317 hal_device_property_set_uint64 ( 318 target, key, 319 hal_property_get_uint64 (p)); 320 break; 321 322 case HAL_PROPERTY_TYPE_BOOLEAN: 323 hal_device_property_set_bool ( 324 target, key, 325 hal_property_get_bool (p)); 326 break; 327 328 case HAL_PROPERTY_TYPE_DOUBLE: 329 hal_device_property_set_double ( 330 target, key, 331 hal_property_get_double (p)); 332 break; 333 334 default: 335 HAL_WARNING (("Unknown property type %d", type)); 336 break; 337 } 338 } 339 340 /* device_property_atomic_update_end (); */ 341 342 caps = hal_device_property_get_strlist (source, "info.capabilities"); 343 for (iter = caps; iter != NULL; iter = iter->next) { 344 if (!hal_device_has_capability (target, iter->data)) 345 hal_device_add_capability (target, iter->data); 346 } 347 } 348 349 gboolean 350 hal_device_matches (HalDevice *device1, HalDevice *device2, 351 const char *namespace) 352 { 353 int len; 354 GSList *iter; 355 356 len = strlen (namespace); 357 358 for (iter = device1->properties; iter != NULL; iter = iter->next) { 359 HalProperty *p; 360 const char *key; 361 int type; 362 363 p = (HalProperty *) iter->data; 364 key = hal_property_get_key (p); 365 type = hal_property_get_type (p); 366 367 if (strncmp (key, namespace, len) != 0) 368 continue; 369 370 if (!hal_device_has_property (device2, key)) 371 return FALSE; 372 373 switch (type) { 374 375 case HAL_PROPERTY_TYPE_STRING: 376 if (strcmp (hal_property_get_string (p), 377 hal_device_property_get_string (device2, 378 key)) != 0) 379 return FALSE; 380 break; 381 382 case HAL_PROPERTY_TYPE_INT32: 383 if (hal_property_get_int (p) != 384 hal_device_property_get_int (device2, key)) 385 return FALSE; 386 break; 387 388 case HAL_PROPERTY_TYPE_UINT64: 389 if (hal_property_get_uint64 (p) != 390 hal_device_property_get_uint64 (device2, key)) 391 return FALSE; 392 break; 393 394 case HAL_PROPERTY_TYPE_BOOLEAN: 395 if (hal_property_get_bool (p) != 396 hal_device_property_get_bool (device2, key)) 397 return FALSE; 398 break; 399 400 case HAL_PROPERTY_TYPE_DOUBLE: 401 if (hal_property_get_double (p) != 402 hal_device_property_get_double (device2, key)) 403 return FALSE; 404 break; 405 406 default: 407 HAL_WARNING (("Unknown property type %d", type)); 408 break; 409 } 410 } 411 412 return TRUE; 413 } 414 415 const char * 416 hal_device_get_udi (HalDevice *device) 417 { 418 return device->udi; 419 } 420 421 void 422 hal_device_set_udi (HalDevice *device, const char *udi) 423 { 424 if (device->udi != NULL) 425 g_free (device->udi); 426 device->udi = g_strdup (udi); 427 } 428 429 void 430 hal_device_add_capability (HalDevice *device, const char *capability) 431 { 432 if (hal_device_property_strlist_add (device, "info.capabilities", capability)) 433 g_signal_emit (device, signals[CAPABILITY_ADDED], 0, capability); 434 } 435 436 gboolean 437 hal_device_has_capability (HalDevice *device, const char *capability) 438 { 439 GSList *caps; 440 GSList *iter; 441 gboolean matched = FALSE; 442 443 caps = hal_device_property_get_strlist (device, "info.capabilities"); 444 445 if (caps == NULL) 446 return FALSE; 447 448 for (iter = caps; iter != NULL; iter = iter->next) { 449 if (strcmp (iter->data, capability) == 0) { 450 matched = TRUE; 451 break; 452 } 453 } 454 455 return matched; 456 } 457 458 gboolean 459 hal_device_has_property (HalDevice *device, const char *key) 460 { 461 g_return_val_if_fail (device != NULL, FALSE); 462 g_return_val_if_fail (key != NULL, FALSE); 463 464 return hal_device_property_find (device, key) != NULL; 465 } 466 467 int 468 hal_device_num_properties (HalDevice *device) 469 { 470 g_return_val_if_fail (device != NULL, -1); 471 472 return g_slist_length (device->properties); 473 } 474 475 HalProperty * 476 hal_device_property_find (HalDevice *device, const char *key) 477 { 478 GSList *iter; 479 480 g_return_val_if_fail (device != NULL, NULL); 481 g_return_val_if_fail (key != NULL, NULL); 482 483 for (iter = device->properties; iter != NULL; iter = iter->next) { 484 HalProperty *p = iter->data; 485 486 if (strcmp (hal_property_get_key (p), key) == 0) 487 return p; 488 } 489 490 return NULL; 491 } 492 493 char * 494 hal_device_property_to_string (HalDevice *device, const char *key) 495 { 496 HalProperty *prop; 497 498 prop = hal_device_property_find (device, key); 499 if (!prop) 500 return NULL; 501 502 return hal_property_to_string (prop); 503 } 504 505 void 506 hal_device_property_foreach (HalDevice *device, 507 HalDevicePropertyForeachFn callback, 508 gpointer user_data) 509 { 510 GSList *iter; 511 512 g_return_if_fail (device != NULL); 513 g_return_if_fail (callback != NULL); 514 515 for (iter = device->properties; iter != NULL; iter = iter->next) { 516 HalProperty *p = iter->data; 517 gboolean cont; 518 519 cont = callback (device, p, user_data); 520 521 if (cont == FALSE) 522 return; 523 } 524 } 525 526 int 527 hal_device_property_get_type (HalDevice *device, const char *key) 528 { 529 HalProperty *prop; 530 531 g_return_val_if_fail (device != NULL, HAL_PROPERTY_TYPE_INVALID); 532 g_return_val_if_fail (key != NULL, HAL_PROPERTY_TYPE_INVALID); 533 534 prop = hal_device_property_find (device, key); 535 536 if (prop != NULL) 537 return hal_property_get_type (prop); 538 else 539 return HAL_PROPERTY_TYPE_INVALID; 540 } 541 542 const char * 543 hal_device_property_get_string (HalDevice *device, const char *key) 544 { 545 HalProperty *prop; 546 547 g_return_val_if_fail (device != NULL, NULL); 548 g_return_val_if_fail (key != NULL, NULL); 549 550 prop = hal_device_property_find (device, key); 551 552 if (prop != NULL) 553 return hal_property_get_string (prop); 554 else 555 return NULL; 556 } 557 558 const char * 559 hal_device_property_get_as_string (HalDevice *device, const char *key, char *buf, size_t bufsize) 560 { 561 HalProperty *prop; 562 563 g_return_val_if_fail (device != NULL, NULL); 564 g_return_val_if_fail (key != NULL, NULL); 565 g_return_val_if_fail (buf != NULL, NULL); 566 567 prop = hal_device_property_find (device, key); 568 569 if (prop != NULL) { 570 switch (hal_property_get_type (prop)) { 571 case HAL_PROPERTY_TYPE_STRING: 572 strncpy (buf, hal_property_get_string (prop), bufsize); 573 break; 574 case HAL_PROPERTY_TYPE_INT32: 575 snprintf (buf, bufsize, "%d", hal_property_get_int (prop)); 576 break; 577 case HAL_PROPERTY_TYPE_UINT64: 578 snprintf (buf, bufsize, "%llu", (long long unsigned int) hal_property_get_uint64 (prop)); 579 break; 580 case HAL_PROPERTY_TYPE_DOUBLE: 581 snprintf (buf, bufsize, "%f", hal_property_get_double (prop)); 582 break; 583 case HAL_PROPERTY_TYPE_BOOLEAN: 584 strncpy (buf, hal_property_get_bool (prop) ? "true" : "false", bufsize); 585 break; 586 587 case HAL_PROPERTY_TYPE_STRLIST: 588 /* print out as "\tval1\tval2\val3\t" */ 589 { 590 GSList *iter; 591 guint i; 592 593 if (bufsize > 0) 594 buf[0] = '\t'; 595 i = 1; 596 for (iter = hal_property_get_strlist (prop); 597 iter != NULL && i < bufsize; 598 iter = g_slist_next (iter)) { 599 guint len; 600 const char *str; 601 602 str = (const char *) iter->data; 603 len = strlen (str); 604 strncpy (buf + i, str, bufsize - i); 605 i += len; 606 607 if (i < bufsize) { 608 buf[i] = '\t'; 609 i++; 610 } 611 } 612 } 613 break; 614 } 615 return buf; 616 } else { 617 buf[0] = '\0'; 618 return NULL; 619 } 620 } 621 622 dbus_int32_t 623 hal_device_property_get_int (HalDevice *device, const char *key) 624 { 625 HalProperty *prop; 626 627 g_return_val_if_fail (device != NULL, -1); 628 g_return_val_if_fail (key != NULL, -1); 629 630 prop = hal_device_property_find (device, key); 631 632 if (prop != NULL) 633 return hal_property_get_int (prop); 634 else 635 return -1; 636 } 637 638 dbus_uint64_t 639 hal_device_property_get_uint64 (HalDevice *device, const char *key) 640 { 641 HalProperty *prop; 642 643 g_return_val_if_fail (device != NULL, -1); 644 g_return_val_if_fail (key != NULL, -1); 645 646 prop = hal_device_property_find (device, key); 647 648 if (prop != NULL) 649 return hal_property_get_uint64 (prop); 650 else 651 return -1; 652 } 653 654 dbus_bool_t 655 hal_device_property_get_bool (HalDevice *device, const char *key) 656 { 657 HalProperty *prop; 658 659 g_return_val_if_fail (device != NULL, FALSE); 660 g_return_val_if_fail (key != NULL, FALSE); 661 662 prop = hal_device_property_find (device, key); 663 664 if (prop != NULL) 665 return hal_property_get_bool (prop); 666 else 667 return FALSE; 668 } 669 670 double 671 hal_device_property_get_double (HalDevice *device, const char *key) 672 { 673 HalProperty *prop; 674 675 g_return_val_if_fail (device != NULL, -1.0); 676 g_return_val_if_fail (key != NULL, -1.0); 677 678 prop = hal_device_property_find (device, key); 679 680 if (prop != NULL) 681 return hal_property_get_double (prop); 682 else 683 return -1.0; 684 } 685 686 gboolean 687 hal_device_property_set_string (HalDevice *device, const char *key, 688 const char *value) 689 { 690 HalProperty *prop; 691 692 /* check if property already exists */ 693 prop = hal_device_property_find (device, key); 694 695 if (prop != NULL) { 696 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRING) 697 return FALSE; 698 699 /* don't bother setting the same value */ 700 if (value != NULL && 701 strcmp (hal_property_get_string (prop), value) == 0) 702 return TRUE; 703 704 hal_property_set_string (prop, value); 705 706 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 707 key, FALSE, FALSE); 708 709 } else { 710 711 prop = hal_property_new_string (key, value); 712 713 device->properties = g_slist_prepend (device->properties, prop); 714 715 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 716 key, FALSE, TRUE); 717 } 718 719 return TRUE; 720 } 721 722 gboolean 723 hal_device_property_set_int (HalDevice *device, const char *key, 724 dbus_int32_t value) 725 { 726 HalProperty *prop; 727 728 /* check if property already exists */ 729 prop = hal_device_property_find (device, key); 730 731 if (prop != NULL) { 732 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_INT32) 733 return FALSE; 734 735 /* don't bother setting the same value */ 736 if (hal_property_get_int (prop) == value) 737 return TRUE; 738 739 hal_property_set_int (prop, value); 740 741 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 742 key, FALSE, FALSE); 743 744 } else { 745 prop = hal_property_new_int (key, value); 746 747 device->properties = g_slist_prepend (device->properties, prop); 748 749 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 750 key, FALSE, TRUE); 751 } 752 753 return TRUE; 754 } 755 756 gboolean 757 hal_device_property_set_uint64 (HalDevice *device, const char *key, 758 dbus_uint64_t value) 759 { 760 HalProperty *prop; 761 762 /* check if property already exists */ 763 prop = hal_device_property_find (device, key); 764 765 if (prop != NULL) { 766 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_UINT64) 767 return FALSE; 768 769 /* don't bother setting the same value */ 770 if (hal_property_get_uint64 (prop) == value) 771 return TRUE; 772 773 hal_property_set_uint64 (prop, value); 774 775 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 776 key, FALSE, FALSE); 777 778 } else { 779 prop = hal_property_new_uint64 (key, value); 780 781 device->properties = g_slist_prepend (device->properties, prop); 782 783 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 784 key, FALSE, TRUE); 785 } 786 787 return TRUE; 788 } 789 790 gboolean 791 hal_device_property_set_bool (HalDevice *device, const char *key, 792 dbus_bool_t value) 793 { 794 HalProperty *prop; 795 796 /* check if property already exists */ 797 prop = hal_device_property_find (device, key); 798 799 if (prop != NULL) { 800 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_BOOLEAN) 801 return FALSE; 802 803 /* don't bother setting the same value */ 804 if (hal_property_get_bool (prop) == value) 805 return TRUE; 806 807 hal_property_set_bool (prop, value); 808 809 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 810 key, FALSE, FALSE); 811 812 } else { 813 prop = hal_property_new_bool (key, value); 814 815 device->properties = g_slist_prepend (device->properties, prop); 816 817 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 818 key, FALSE, TRUE); 819 } 820 821 return TRUE; 822 } 823 824 gboolean 825 hal_device_property_set_double (HalDevice *device, const char *key, 826 double value) 827 { 828 HalProperty *prop; 829 830 /* check if property already exists */ 831 prop = hal_device_property_find (device, key); 832 833 if (prop != NULL) { 834 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_DOUBLE) 835 return FALSE; 836 837 /* don't bother setting the same value */ 838 if (hal_property_get_double (prop) == value) 839 return TRUE; 840 841 hal_property_set_double (prop, value); 842 843 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 844 key, FALSE, FALSE); 845 846 } else { 847 prop = hal_property_new_double (key, value); 848 849 device->properties = g_slist_prepend (device->properties, prop); 850 851 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 852 key, FALSE, TRUE); 853 } 854 855 return TRUE; 856 } 857 858 gboolean 859 hal_device_copy_property (HalDevice *from_device, const char *from, HalDevice *to_device, const char *to) 860 { 861 gboolean rc; 862 863 rc = FALSE; 864 865 if (hal_device_has_property (from_device, from)) { 866 switch (hal_device_property_get_type (from_device, from)) { 867 case HAL_PROPERTY_TYPE_STRING: 868 rc = hal_device_property_set_string ( 869 to_device, to, hal_device_property_get_string (from_device, from)); 870 break; 871 case HAL_PROPERTY_TYPE_INT32: 872 rc = hal_device_property_set_int ( 873 to_device, to, hal_device_property_get_int (from_device, from)); 874 break; 875 case HAL_PROPERTY_TYPE_UINT64: 876 rc = hal_device_property_set_uint64 ( 877 to_device, to, hal_device_property_get_uint64 (from_device, from)); 878 break; 879 case HAL_PROPERTY_TYPE_BOOLEAN: 880 rc = hal_device_property_set_bool ( 881 to_device, to, hal_device_property_get_bool (from_device, from)); 882 break; 883 case HAL_PROPERTY_TYPE_DOUBLE: 884 rc = hal_device_property_set_double ( 885 to_device, to, hal_device_property_get_double (from_device, from)); 886 break; 887 } 888 } 889 890 return rc; 891 } 892 893 gboolean 894 hal_device_property_remove (HalDevice *device, const char *key) 895 { 896 HalProperty *prop; 897 898 prop = hal_device_property_find (device, key); 899 900 if (prop == NULL) 901 return FALSE; 902 903 device->properties = g_slist_remove (device->properties, prop); 904 905 hal_property_free (prop); 906 907 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 908 key, TRUE, FALSE); 909 910 return TRUE; 911 } 912 913 gboolean 914 hal_device_property_set_attribute (HalDevice *device, 915 const char *key, 916 enum PropertyAttribute attr, 917 gboolean val) 918 { 919 HalProperty *prop; 920 921 prop = hal_device_property_find (device, key); 922 923 if (prop == NULL) 924 return FALSE; 925 926 return TRUE; 927 } 928 929 void 930 hal_device_print (HalDevice *device) 931 { 932 GSList *iter; 933 934 fprintf (stderr, "device udi = %s\n", hal_device_get_udi (device)); 935 936 for (iter = device->properties; iter != NULL; iter = iter->next) { 937 HalProperty *p = iter->data; 938 int type; 939 const char *key; 940 941 key = hal_property_get_key (p); 942 type = hal_property_get_type (p); 943 944 switch (type) { 945 case HAL_PROPERTY_TYPE_STRING: 946 fprintf (stderr, " %s = '%s' (string)\n", key, 947 hal_property_get_string (p)); 948 break; 949 950 case HAL_PROPERTY_TYPE_INT32: 951 fprintf (stderr, " %s = %d 0x%x (int)\n", key, 952 hal_property_get_int (p), 953 hal_property_get_int (p)); 954 break; 955 956 case HAL_PROPERTY_TYPE_UINT64: 957 fprintf (stderr, " %s = %llu 0x%llx (uint64)\n", key, 958 (long long unsigned int) hal_property_get_uint64 (p), 959 (long long unsigned int) hal_property_get_uint64 (p)); 960 break; 961 962 case HAL_PROPERTY_TYPE_DOUBLE: 963 fprintf (stderr, " %s = %g (double)\n", key, 964 hal_property_get_double (p)); 965 break; 966 967 case HAL_PROPERTY_TYPE_BOOLEAN: 968 fprintf (stderr, " %s = %s (bool)\n", key, 969 (hal_property_get_bool (p) ? "true" : 970 "false")); 971 break; 972 973 default: 974 HAL_WARNING (("Unknown property type %d", type)); 975 break; 976 } 977 } 978 fprintf (stderr, "\n"); 979 } 980 981 982 typedef struct { 983 char *key; 984 HalDevice *device; 985 HalDeviceAsyncCallback callback; 986 gpointer user_data; 987 988 guint prop_signal_id; 989 guint timeout_id; 990 } AsyncMatchInfo; 991 992 static void 993 destroy_async_match_info (AsyncMatchInfo *ai) 994 { 995 g_free (ai->key); 996 g_signal_handler_disconnect (ai->device, ai->prop_signal_id); 997 g_source_remove (ai->timeout_id); 998 g_object_unref (ai->device); 999 g_free (ai); 1000 } 1001 1002 static void 1003 prop_changed_cb (HalDevice *device, const char *key, 1004 gboolean removed, gboolean added, gpointer user_data) 1005 { 1006 AsyncMatchInfo *ai = user_data; 1007 1008 if (strcmp (key, ai->key) != 0) 1009 return; 1010 1011 /* the property is no longer there */ 1012 if (removed) 1013 goto cleanup; 1014 1015 1016 ai->callback (ai->device, ai->user_data, TRUE); 1017 1018 cleanup: 1019 destroy_async_match_info (ai); 1020 } 1021 1022 1023 static gboolean 1024 async_wait_timeout (gpointer user_data) 1025 { 1026 AsyncMatchInfo *ai = (AsyncMatchInfo *) user_data; 1027 1028 ai->callback (ai->device, ai->user_data, FALSE); 1029 1030 destroy_async_match_info (ai); 1031 1032 return FALSE; 1033 } 1034 1035 void 1036 hal_device_async_wait_property (HalDevice *device, 1037 const char *key, 1038 HalDeviceAsyncCallback callback, 1039 gpointer user_data, 1040 int timeout) 1041 { 1042 HalProperty *prop; 1043 AsyncMatchInfo *ai; 1044 1045 /* check if property already exists */ 1046 prop = hal_device_property_find (device, key); 1047 1048 if (prop != NULL || timeout==0) { 1049 callback (device, user_data, prop != NULL); 1050 return; 1051 } 1052 1053 ai = g_new0 (AsyncMatchInfo, 1); 1054 1055 ai->device = g_object_ref (device); 1056 ai->key = g_strdup (key); 1057 ai->callback = callback; 1058 ai->user_data = user_data; 1059 1060 ai->prop_signal_id = g_signal_connect (device, "property_changed", 1061 G_CALLBACK (prop_changed_cb), 1062 ai); 1063 1064 ai->timeout_id = g_timeout_add (timeout, async_wait_timeout, ai); 1065 } 1066 1067 void 1068 hal_device_callouts_finished (HalDevice *device) 1069 { 1070 g_signal_emit (device, signals[CALLOUTS_FINISHED], 0); 1071 } 1072 1073 /** Used when giving up on a device, e.g. if no device file appeared 1074 */ 1075 void 1076 hal_device_cancel (HalDevice *device) 1077 { 1078 HAL_INFO (("udi=%s", device->udi)); 1079 g_signal_emit (device, signals[CANCELLED], 0); 1080 } 1081 1082 1083 1084 1085 GSList * 1086 hal_device_property_get_strlist (HalDevice *device, 1087 const char *key) 1088 { 1089 HalProperty *prop; 1090 1091 g_return_val_if_fail (device != NULL, NULL); 1092 g_return_val_if_fail (key != NULL, NULL); 1093 1094 prop = hal_device_property_find (device, key); 1095 1096 if (prop != NULL) 1097 return hal_property_get_strlist (prop); 1098 else 1099 return NULL; 1100 } 1101 1102 const char * 1103 hal_device_property_get_strlist_elem (HalDevice *device, 1104 const char *key, 1105 guint index) 1106 { 1107 GSList *strlist; 1108 GSList *i; 1109 1110 strlist = hal_device_property_get_strlist (device, key); 1111 if (strlist == NULL) 1112 return NULL; 1113 1114 i = g_slist_nth (strlist, index); 1115 if (i == NULL) 1116 return NULL; 1117 1118 return (const char *) i->data; 1119 } 1120 1121 gboolean 1122 hal_device_property_strlist_append (HalDevice *device, 1123 const char *key, 1124 const char *value) 1125 { 1126 HalProperty *prop; 1127 1128 /* check if property already exists */ 1129 prop = hal_device_property_find (device, key); 1130 1131 if (prop != NULL) { 1132 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST) 1133 return FALSE; 1134 1135 hal_property_strlist_append (prop, value); 1136 1137 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1138 key, FALSE, FALSE); 1139 1140 } else { 1141 prop = hal_property_new_strlist (key); 1142 hal_property_strlist_append (prop, value); 1143 1144 device->properties = g_slist_prepend (device->properties, prop); 1145 1146 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1147 key, FALSE, TRUE); 1148 } 1149 1150 return TRUE; 1151 } 1152 1153 gboolean 1154 hal_device_property_strlist_prepend (HalDevice *device, 1155 const char *key, 1156 const char *value) 1157 { 1158 HalProperty *prop; 1159 1160 /* check if property already exists */ 1161 prop = hal_device_property_find (device, key); 1162 1163 if (prop != NULL) { 1164 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST) 1165 return FALSE; 1166 1167 hal_property_strlist_prepend (prop, value); 1168 1169 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1170 key, FALSE, FALSE); 1171 1172 } else { 1173 prop = hal_property_new_strlist (key); 1174 hal_property_strlist_prepend (prop, value); 1175 1176 device->properties = g_slist_prepend (device->properties, prop); 1177 1178 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1179 key, FALSE, TRUE); 1180 } 1181 1182 return TRUE; 1183 } 1184 1185 gboolean 1186 hal_device_property_strlist_remove_elem (HalDevice *device, 1187 const char *key, 1188 guint index) 1189 { 1190 HalProperty *prop; 1191 1192 /* check if property already exists */ 1193 prop = hal_device_property_find (device, key); 1194 1195 if (prop == NULL) 1196 return FALSE; 1197 1198 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST) 1199 return FALSE; 1200 1201 if (hal_property_strlist_remove_elem (prop, index)) { 1202 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1203 key, FALSE, FALSE); 1204 return TRUE; 1205 } 1206 1207 return FALSE; 1208 } 1209 1210 gboolean 1211 hal_device_property_strlist_clear (HalDevice *device, 1212 const char *key) 1213 { 1214 HalProperty *prop; 1215 1216 /* check if property already exists */ 1217 prop = hal_device_property_find (device, key); 1218 1219 if (prop == NULL) { 1220 prop = hal_property_new_strlist (key); 1221 1222 device->properties = g_slist_prepend (device->properties, prop); 1223 1224 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1225 key, FALSE, TRUE); 1226 1227 return TRUE; 1228 } 1229 1230 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST) 1231 return FALSE; 1232 1233 if (hal_property_strlist_clear (prop)) { 1234 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1235 key, FALSE, FALSE); 1236 return TRUE; 1237 } 1238 1239 return FALSE; 1240 } 1241 1242 1243 gboolean 1244 hal_device_property_strlist_add (HalDevice *device, 1245 const char *key, 1246 const char *value) 1247 { 1248 HalProperty *prop; 1249 gboolean res; 1250 1251 res = FALSE; 1252 1253 /* check if property already exists */ 1254 prop = hal_device_property_find (device, key); 1255 1256 if (prop != NULL) { 1257 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST) 1258 goto out; 1259 1260 res = hal_property_strlist_add (prop, value); 1261 if (res) { 1262 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1263 key, FALSE, FALSE); 1264 } 1265 1266 } else { 1267 prop = hal_property_new_strlist (key); 1268 hal_property_strlist_prepend (prop, value); 1269 1270 device->properties = g_slist_prepend (device->properties, prop); 1271 1272 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1273 key, FALSE, TRUE); 1274 1275 res = TRUE; 1276 } 1277 1278 out: 1279 return res; 1280 } 1281 1282 gboolean 1283 hal_device_property_strlist_remove (HalDevice *device, 1284 const char *key, 1285 const char *value) 1286 { 1287 HalProperty *prop; 1288 1289 /* check if property already exists */ 1290 prop = hal_device_property_find (device, key); 1291 1292 if (prop == NULL) 1293 return FALSE; 1294 1295 if (hal_property_get_type (prop) != HAL_PROPERTY_TYPE_STRLIST) 1296 return FALSE; 1297 1298 if (hal_property_strlist_remove (prop, value)) { 1299 g_signal_emit (device, signals[PROPERTY_CHANGED], 0, 1300 key, FALSE, FALSE); 1301 } 1302 1303 return TRUE; 1304 } 1305 1306 gboolean 1307 hal_device_property_strlist_is_empty (HalDevice *device, 1308 const char *key) 1309 { 1310 GSList *strlist; 1311 1312 if ( hal_device_has_property (device, key)) { 1313 strlist = hal_device_property_get_strlist (device, key); 1314 if (strlist == NULL ) 1315 return TRUE; 1316 1317 if (g_slist_length (strlist) > 0) 1318 return FALSE; 1319 else 1320 return TRUE; 1321 } 1322 return FALSE; 1323 } 1324 1325 void 1326 hal_device_inc_num_addons (HalDevice *device) 1327 { 1328 device->num_addons++; 1329 } 1330 1331 gboolean 1332 hal_device_inc_num_ready_addons (HalDevice *device) 1333 { 1334 if (hal_device_are_all_addons_ready (device)) { 1335 HAL_ERROR (("In hal_device_inc_num_ready_addons for udi=%s but all addons are already ready!", 1336 device->udi)); 1337 return FALSE; 1338 } 1339 1340 device->num_addons_ready++; 1341 return TRUE; 1342 } 1343 1344 gboolean 1345 hal_device_are_all_addons_ready (HalDevice *device) 1346 { 1347 if (device->num_addons_ready == device->num_addons) { 1348 return TRUE; 1349 } else { 1350 return FALSE; 1351 } 1352 } 1353