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