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
hal_device_finalize(GObject * obj)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
hal_device_class_init(HalDeviceClass * klass)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
hal_device_init(HalDevice * device)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
hal_device_get_type(void)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 *
hal_device_new(void)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
hal_device_merge_with_rewrite(HalDevice * target,HalDevice * source,const char * target_namespace,const char * source_namespace)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
hal_device_merge(HalDevice * target,HalDevice * source)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
hal_device_matches(HalDevice * device1,HalDevice * device2,const char * namespace)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 *
hal_device_get_udi(HalDevice * device)416 hal_device_get_udi (HalDevice *device)
417 {
418 return device->udi;
419 }
420
421 void
hal_device_set_udi(HalDevice * device,const char * udi)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
hal_device_add_capability(HalDevice * device,const char * capability)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
hal_device_has_capability(HalDevice * device,const char * capability)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
hal_device_has_property(HalDevice * device,const char * key)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
hal_device_num_properties(HalDevice * device)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 *
hal_device_property_find(HalDevice * device,const char * key)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 *
hal_device_property_to_string(HalDevice * device,const char * key)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
hal_device_property_foreach(HalDevice * device,HalDevicePropertyForeachFn callback,gpointer user_data)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
hal_device_property_get_type(HalDevice * device,const char * key)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 *
hal_device_property_get_string(HalDevice * device,const char * key)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 *
hal_device_property_get_as_string(HalDevice * device,const char * key,char * buf,size_t bufsize)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
hal_device_property_get_int(HalDevice * device,const char * key)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
hal_device_property_get_uint64(HalDevice * device,const char * key)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
hal_device_property_get_bool(HalDevice * device,const char * key)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
hal_device_property_get_double(HalDevice * device,const char * key)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
hal_device_property_set_string(HalDevice * device,const char * key,const char * value)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
hal_device_property_set_int(HalDevice * device,const char * key,dbus_int32_t value)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
hal_device_property_set_uint64(HalDevice * device,const char * key,dbus_uint64_t value)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
hal_device_property_set_bool(HalDevice * device,const char * key,dbus_bool_t value)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
hal_device_property_set_double(HalDevice * device,const char * key,double value)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
hal_device_copy_property(HalDevice * from_device,const char * from,HalDevice * to_device,const char * to)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
hal_device_property_remove(HalDevice * device,const char * key)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
hal_device_property_set_attribute(HalDevice * device,const char * key,enum PropertyAttribute attr,gboolean val)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
hal_device_print(HalDevice * device)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
destroy_async_match_info(AsyncMatchInfo * ai)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
prop_changed_cb(HalDevice * device,const char * key,gboolean removed,gboolean added,gpointer user_data)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
async_wait_timeout(gpointer user_data)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
hal_device_async_wait_property(HalDevice * device,const char * key,HalDeviceAsyncCallback callback,gpointer user_data,int timeout)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
hal_device_callouts_finished(HalDevice * device)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
hal_device_cancel(HalDevice * device)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 *
hal_device_property_get_strlist(HalDevice * device,const char * key)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 *
hal_device_property_get_strlist_elem(HalDevice * device,const char * key,guint index)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
hal_device_property_strlist_append(HalDevice * device,const char * key,const char * value)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
hal_device_property_strlist_prepend(HalDevice * device,const char * key,const char * value)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
hal_device_property_strlist_remove_elem(HalDevice * device,const char * key,guint index)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
hal_device_property_strlist_clear(HalDevice * device,const char * key)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
hal_device_property_strlist_add(HalDevice * device,const char * key,const char * value)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
hal_device_property_strlist_remove(HalDevice * device,const char * key,const char * value)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
hal_device_property_strlist_is_empty(HalDevice * device,const char * key)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
hal_device_inc_num_addons(HalDevice * device)1326 hal_device_inc_num_addons (HalDevice *device)
1327 {
1328 device->num_addons++;
1329 }
1330
1331 gboolean
hal_device_inc_num_ready_addons(HalDevice * device)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
hal_device_are_all_addons_ready(HalDevice * device)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