1#include "qemu/osdep.h"
2#include "hw/qdev-properties.h"
3#include "qapi/error.h"
4#include "qapi/qapi-types-misc.h"
5#include "qapi/qmp/qerror.h"
6#include "qemu/ctype.h"
7#include "qemu/error-report.h"
8#include "qapi/visitor.h"
9#include "qemu/units.h"
10#include "qemu/cutils.h"
11#include "qdev-prop-internal.h"
12
13void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
14 Error **errp)
15{
16 if (dev->id) {
17 error_setg(errp, "Attempt to set property '%s' on device '%s' "
18 "(type '%s') after it was realized", name, dev->id,
19 object_get_typename(OBJECT(dev)));
20 } else {
21 error_setg(errp, "Attempt to set property '%s' on anonymous device "
22 "(type '%s') after it was realized", name,
23 object_get_typename(OBJECT(dev)));
24 }
25}
26
27
28static bool qdev_prop_allow_set(Object *obj, const char *name,
29 Error **errp)
30{
31 DeviceState *dev = DEVICE(obj);
32
33 if (dev->realized) {
34 qdev_prop_set_after_realize(dev, name, errp);
35 return false;
36 }
37 return true;
38}
39
40void qdev_prop_allow_set_link_before_realize(const Object *obj,
41 const char *name,
42 Object *val, Error **errp)
43{
44 DeviceState *dev = DEVICE(obj);
45
46 if (dev->realized) {
47 error_setg(errp, "Attempt to set link property '%s' on device '%s' "
48 "(type '%s') after it was realized",
49 name, dev->id, object_get_typename(obj));
50 }
51}
52
53void *object_field_prop_ptr(Object *obj, Property *prop)
54{
55 void *ptr = obj;
56 ptr += prop->offset;
57 return ptr;
58}
59
60static void field_prop_get(Object *obj, Visitor *v, const char *name,
61 void *opaque, Error **errp)
62{
63 Property *prop = opaque;
64 return prop->info->get(obj, v, name, opaque, errp);
65}
66
67
68
69
70
71
72static ObjectPropertyAccessor *field_prop_getter(const PropertyInfo *info)
73{
74 return info->get ? field_prop_get : NULL;
75}
76
77static void field_prop_set(Object *obj, Visitor *v, const char *name,
78 void *opaque, Error **errp)
79{
80 Property *prop = opaque;
81
82 if (!qdev_prop_allow_set(obj, name, errp)) {
83 return;
84 }
85
86 return prop->info->set(obj, v, name, opaque, errp);
87}
88
89
90
91
92
93
94static ObjectPropertyAccessor *field_prop_setter(const PropertyInfo *info)
95{
96 return info->set ? field_prop_set : NULL;
97}
98
99void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
100 void *opaque, Error **errp)
101{
102 Property *prop = opaque;
103 int *ptr = object_field_prop_ptr(obj, prop);
104
105 visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
106}
107
108void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
109 void *opaque, Error **errp)
110{
111 Property *prop = opaque;
112 int *ptr = object_field_prop_ptr(obj, prop);
113
114 visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
115}
116
117void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
118 const Property *prop)
119{
120 object_property_set_default_str(op,
121 qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
122}
123
124const PropertyInfo qdev_prop_enum = {
125 .name = "enum",
126 .get = qdev_propinfo_get_enum,
127 .set = qdev_propinfo_set_enum,
128 .set_default_value = qdev_propinfo_set_default_value_enum,
129};
130
131
132
133static uint32_t qdev_get_prop_mask(Property *prop)
134{
135 assert(prop->info == &qdev_prop_bit);
136 return 0x1 << prop->bitnr;
137}
138
139static void bit_prop_set(Object *obj, Property *props, bool val)
140{
141 uint32_t *p = object_field_prop_ptr(obj, props);
142 uint32_t mask = qdev_get_prop_mask(props);
143 if (val) {
144 *p |= mask;
145 } else {
146 *p &= ~mask;
147 }
148}
149
150static void prop_get_bit(Object *obj, Visitor *v, const char *name,
151 void *opaque, Error **errp)
152{
153 Property *prop = opaque;
154 uint32_t *p = object_field_prop_ptr(obj, prop);
155 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
156
157 visit_type_bool(v, name, &value, errp);
158}
159
160static void prop_set_bit(Object *obj, Visitor *v, const char *name,
161 void *opaque, Error **errp)
162{
163 Property *prop = opaque;
164 bool value;
165
166 if (!visit_type_bool(v, name, &value, errp)) {
167 return;
168 }
169 bit_prop_set(obj, prop, value);
170}
171
172static void set_default_value_bool(ObjectProperty *op, const Property *prop)
173{
174 object_property_set_default_bool(op, prop->defval.u);
175}
176
177const PropertyInfo qdev_prop_bit = {
178 .name = "bool",
179 .description = "on/off",
180 .get = prop_get_bit,
181 .set = prop_set_bit,
182 .set_default_value = set_default_value_bool,
183};
184
185
186
187static uint64_t qdev_get_prop_mask64(Property *prop)
188{
189 assert(prop->info == &qdev_prop_bit64);
190 return 0x1ull << prop->bitnr;
191}
192
193static void bit64_prop_set(Object *obj, Property *props, bool val)
194{
195 uint64_t *p = object_field_prop_ptr(obj, props);
196 uint64_t mask = qdev_get_prop_mask64(props);
197 if (val) {
198 *p |= mask;
199 } else {
200 *p &= ~mask;
201 }
202}
203
204static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
205 void *opaque, Error **errp)
206{
207 Property *prop = opaque;
208 uint64_t *p = object_field_prop_ptr(obj, prop);
209 bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
210
211 visit_type_bool(v, name, &value, errp);
212}
213
214static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
215 void *opaque, Error **errp)
216{
217 Property *prop = opaque;
218 bool value;
219
220 if (!visit_type_bool(v, name, &value, errp)) {
221 return;
222 }
223 bit64_prop_set(obj, prop, value);
224}
225
226const PropertyInfo qdev_prop_bit64 = {
227 .name = "bool",
228 .description = "on/off",
229 .get = prop_get_bit64,
230 .set = prop_set_bit64,
231 .set_default_value = set_default_value_bool,
232};
233
234
235
236static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
237 Error **errp)
238{
239 Property *prop = opaque;
240 bool *ptr = object_field_prop_ptr(obj, prop);
241
242 visit_type_bool(v, name, ptr, errp);
243}
244
245static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
246 Error **errp)
247{
248 Property *prop = opaque;
249 bool *ptr = object_field_prop_ptr(obj, prop);
250
251 visit_type_bool(v, name, ptr, errp);
252}
253
254const PropertyInfo qdev_prop_bool = {
255 .name = "bool",
256 .get = get_bool,
257 .set = set_bool,
258 .set_default_value = set_default_value_bool,
259};
260
261
262
263static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
264 Error **errp)
265{
266 Property *prop = opaque;
267 uint8_t *ptr = object_field_prop_ptr(obj, prop);
268
269 visit_type_uint8(v, name, ptr, errp);
270}
271
272static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
273 Error **errp)
274{
275 Property *prop = opaque;
276 uint8_t *ptr = object_field_prop_ptr(obj, prop);
277
278 visit_type_uint8(v, name, ptr, errp);
279}
280
281void qdev_propinfo_set_default_value_int(ObjectProperty *op,
282 const Property *prop)
283{
284 object_property_set_default_int(op, prop->defval.i);
285}
286
287void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
288 const Property *prop)
289{
290 object_property_set_default_uint(op, prop->defval.u);
291}
292
293const PropertyInfo qdev_prop_uint8 = {
294 .name = "uint8",
295 .get = get_uint8,
296 .set = set_uint8,
297 .set_default_value = qdev_propinfo_set_default_value_uint,
298};
299
300
301
302static void get_uint16(Object *obj, Visitor *v, const char *name,
303 void *opaque, Error **errp)
304{
305 Property *prop = opaque;
306 uint16_t *ptr = object_field_prop_ptr(obj, prop);
307
308 visit_type_uint16(v, name, ptr, errp);
309}
310
311static void set_uint16(Object *obj, Visitor *v, const char *name,
312 void *opaque, Error **errp)
313{
314 Property *prop = opaque;
315 uint16_t *ptr = object_field_prop_ptr(obj, prop);
316
317 visit_type_uint16(v, name, ptr, errp);
318}
319
320const PropertyInfo qdev_prop_uint16 = {
321 .name = "uint16",
322 .get = get_uint16,
323 .set = set_uint16,
324 .set_default_value = qdev_propinfo_set_default_value_uint,
325};
326
327
328
329static void get_uint32(Object *obj, Visitor *v, const char *name,
330 void *opaque, Error **errp)
331{
332 Property *prop = opaque;
333 uint32_t *ptr = object_field_prop_ptr(obj, prop);
334
335 visit_type_uint32(v, name, ptr, errp);
336}
337
338static void set_uint32(Object *obj, Visitor *v, const char *name,
339 void *opaque, Error **errp)
340{
341 Property *prop = opaque;
342 uint32_t *ptr = object_field_prop_ptr(obj, prop);
343
344 visit_type_uint32(v, name, ptr, errp);
345}
346
347void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
348 void *opaque, Error **errp)
349{
350 Property *prop = opaque;
351 int32_t *ptr = object_field_prop_ptr(obj, prop);
352
353 visit_type_int32(v, name, ptr, errp);
354}
355
356static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
357 Error **errp)
358{
359 Property *prop = opaque;
360 int32_t *ptr = object_field_prop_ptr(obj, prop);
361
362 visit_type_int32(v, name, ptr, errp);
363}
364
365const PropertyInfo qdev_prop_uint32 = {
366 .name = "uint32",
367 .get = get_uint32,
368 .set = set_uint32,
369 .set_default_value = qdev_propinfo_set_default_value_uint,
370};
371
372const PropertyInfo qdev_prop_int32 = {
373 .name = "int32",
374 .get = qdev_propinfo_get_int32,
375 .set = set_int32,
376 .set_default_value = qdev_propinfo_set_default_value_int,
377};
378
379
380
381static void get_uint64(Object *obj, Visitor *v, const char *name,
382 void *opaque, Error **errp)
383{
384 Property *prop = opaque;
385 uint64_t *ptr = object_field_prop_ptr(obj, prop);
386
387 visit_type_uint64(v, name, ptr, errp);
388}
389
390static void set_uint64(Object *obj, Visitor *v, const char *name,
391 void *opaque, Error **errp)
392{
393 Property *prop = opaque;
394 uint64_t *ptr = object_field_prop_ptr(obj, prop);
395
396 visit_type_uint64(v, name, ptr, errp);
397}
398
399static void get_int64(Object *obj, Visitor *v, const char *name,
400 void *opaque, Error **errp)
401{
402 Property *prop = opaque;
403 int64_t *ptr = object_field_prop_ptr(obj, prop);
404
405 visit_type_int64(v, name, ptr, errp);
406}
407
408static void set_int64(Object *obj, Visitor *v, const char *name,
409 void *opaque, Error **errp)
410{
411 Property *prop = opaque;
412 int64_t *ptr = object_field_prop_ptr(obj, prop);
413
414 visit_type_int64(v, name, ptr, errp);
415}
416
417const PropertyInfo qdev_prop_uint64 = {
418 .name = "uint64",
419 .get = get_uint64,
420 .set = set_uint64,
421 .set_default_value = qdev_propinfo_set_default_value_uint,
422};
423
424const PropertyInfo qdev_prop_int64 = {
425 .name = "int64",
426 .get = get_int64,
427 .set = set_int64,
428 .set_default_value = qdev_propinfo_set_default_value_int,
429};
430
431
432
433static void release_string(Object *obj, const char *name, void *opaque)
434{
435 Property *prop = opaque;
436 g_free(*(char **)object_field_prop_ptr(obj, prop));
437}
438
439static void get_string(Object *obj, Visitor *v, const char *name,
440 void *opaque, Error **errp)
441{
442 Property *prop = opaque;
443 char **ptr = object_field_prop_ptr(obj, prop);
444
445 if (!*ptr) {
446 char *str = (char *)"";
447 visit_type_str(v, name, &str, errp);
448 } else {
449 visit_type_str(v, name, ptr, errp);
450 }
451}
452
453static void set_string(Object *obj, Visitor *v, const char *name,
454 void *opaque, Error **errp)
455{
456 Property *prop = opaque;
457 char **ptr = object_field_prop_ptr(obj, prop);
458 char *str;
459
460 if (!visit_type_str(v, name, &str, errp)) {
461 return;
462 }
463 g_free(*ptr);
464 *ptr = str;
465}
466
467const PropertyInfo qdev_prop_string = {
468 .name = "str",
469 .release = release_string,
470 .get = get_string,
471 .set = set_string,
472};
473
474
475
476const PropertyInfo qdev_prop_on_off_auto = {
477 .name = "OnOffAuto",
478 .description = "on/off/auto",
479 .enum_table = &OnOffAuto_lookup,
480 .get = qdev_propinfo_get_enum,
481 .set = qdev_propinfo_set_enum,
482 .set_default_value = qdev_propinfo_set_default_value_enum,
483};
484
485
486
487void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
488 void *opaque, Error **errp)
489{
490 Property *prop = opaque;
491 uint32_t *ptr = object_field_prop_ptr(obj, prop);
492 uint64_t value = *ptr;
493
494 visit_type_size(v, name, &value, errp);
495}
496
497static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
498 Error **errp)
499{
500 Property *prop = opaque;
501 uint32_t *ptr = object_field_prop_ptr(obj, prop);
502 uint64_t value;
503
504 if (!visit_type_size(v, name, &value, errp)) {
505 return;
506 }
507
508 if (value > UINT32_MAX) {
509 error_setg(errp,
510 "Property %s.%s doesn't take value %" PRIu64
511 " (maximum: %u)",
512 object_get_typename(obj), name, value, UINT32_MAX);
513 return;
514 }
515
516 *ptr = value;
517}
518
519const PropertyInfo qdev_prop_size32 = {
520 .name = "size",
521 .get = qdev_propinfo_get_size32,
522 .set = set_size32,
523 .set_default_value = qdev_propinfo_set_default_value_uint,
524};
525
526
527
528
529
530
531
532
533
534typedef struct {
535 struct Property prop;
536 char *propname;
537 ObjectPropertyRelease *release;
538} ArrayElementProperty;
539
540
541
542
543
544static void array_element_release(Object *obj, const char *name, void *opaque)
545{
546 ArrayElementProperty *p = opaque;
547 if (p->release) {
548 p->release(obj, name, opaque);
549 }
550 g_free(p->propname);
551 g_free(p);
552}
553
554static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
555 void *opaque, Error **errp)
556{
557
558
559
560
561
562 Property *prop = opaque;
563 uint32_t *alenptr = object_field_prop_ptr(obj, prop);
564 void **arrayptr = (void *)obj + prop->arrayoffset;
565 void *eltptr;
566 const char *arrayname;
567 int i;
568
569 if (*alenptr) {
570 error_setg(errp, "array size property %s may not be set more than once",
571 name);
572 return;
573 }
574 if (!visit_type_uint32(v, name, alenptr, errp)) {
575 return;
576 }
577 if (!*alenptr) {
578 return;
579 }
580
581
582
583
584 assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
585 strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
586 arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
587
588
589
590
591 *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
592 for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
593 char *propname = g_strdup_printf("%s[%d]", arrayname, i);
594 ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
595 arrayprop->release = prop->arrayinfo->release;
596 arrayprop->propname = propname;
597 arrayprop->prop.info = prop->arrayinfo;
598 arrayprop->prop.name = propname;
599
600
601
602
603
604 arrayprop->prop.offset = eltptr - (void *)obj;
605 assert(object_field_prop_ptr(obj, &arrayprop->prop) == eltptr);
606 object_property_add(obj, propname,
607 arrayprop->prop.info->name,
608 field_prop_getter(arrayprop->prop.info),
609 field_prop_setter(arrayprop->prop.info),
610 array_element_release,
611 arrayprop);
612 }
613}
614
615const PropertyInfo qdev_prop_arraylen = {
616 .name = "uint32",
617 .get = get_uint32,
618 .set = set_prop_arraylen,
619 .set_default_value = qdev_propinfo_set_default_value_uint,
620};
621
622
623
624static Property *qdev_prop_walk(Property *props, const char *name)
625{
626 if (!props) {
627 return NULL;
628 }
629 while (props->name) {
630 if (strcmp(props->name, name) == 0) {
631 return props;
632 }
633 props++;
634 }
635 return NULL;
636}
637
638static Property *qdev_prop_find(DeviceState *dev, const char *name)
639{
640 ObjectClass *class;
641 Property *prop;
642
643
644 class = object_get_class(OBJECT(dev));
645 do {
646 prop = qdev_prop_walk(DEVICE_CLASS(class)->props_, name);
647 if (prop) {
648 return prop;
649 }
650 class = object_class_get_parent(class);
651 } while (class != object_class_by_name(TYPE_DEVICE));
652
653 return NULL;
654}
655
656void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj,
657 const char *name, const char *value)
658{
659 switch (ret) {
660 case -EEXIST:
661 error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
662 object_get_typename(obj), name, value);
663 break;
664 default:
665 case -EINVAL:
666 error_setg(errp, QERR_PROPERTY_VALUE_BAD,
667 object_get_typename(obj), name, value);
668 break;
669 case -ENOENT:
670 error_setg(errp, "Property '%s.%s' can't find value '%s'",
671 object_get_typename(obj), name, value);
672 break;
673 case 0:
674 break;
675 }
676}
677
678void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
679{
680 object_property_set_bool(OBJECT(dev), name, value, &error_abort);
681}
682
683void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
684{
685 object_property_set_int(OBJECT(dev), name, value, &error_abort);
686}
687
688void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
689{
690 object_property_set_int(OBJECT(dev), name, value, &error_abort);
691}
692
693void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
694{
695 object_property_set_int(OBJECT(dev), name, value, &error_abort);
696}
697
698void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
699{
700 object_property_set_int(OBJECT(dev), name, value, &error_abort);
701}
702
703void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
704{
705 object_property_set_int(OBJECT(dev), name, value, &error_abort);
706}
707
708void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
709{
710 object_property_set_str(OBJECT(dev), name, value, &error_abort);
711}
712
713void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
714{
715 Property *prop;
716
717 prop = qdev_prop_find(dev, name);
718 object_property_set_str(OBJECT(dev), name,
719 qapi_enum_lookup(prop->info->enum_table, value),
720 &error_abort);
721}
722
723static GPtrArray *global_props(void)
724{
725 static GPtrArray *gp;
726
727 if (!gp) {
728 gp = g_ptr_array_new();
729 }
730
731 return gp;
732}
733
734void qdev_prop_register_global(GlobalProperty *prop)
735{
736 g_ptr_array_add(global_props(), prop);
737}
738
739const GlobalProperty *qdev_find_global_prop(Object *obj,
740 const char *name)
741{
742 GPtrArray *props = global_props();
743 const GlobalProperty *p;
744 int i;
745
746 for (i = 0; i < props->len; i++) {
747 p = g_ptr_array_index(props, i);
748 if (object_dynamic_cast(obj, p->driver)
749 && !strcmp(p->property, name)) {
750 return p;
751 }
752 }
753 return NULL;
754}
755
756int qdev_prop_check_globals(void)
757{
758 int i, ret = 0;
759
760 for (i = 0; i < global_props()->len; i++) {
761 GlobalProperty *prop;
762 ObjectClass *oc;
763 DeviceClass *dc;
764
765 prop = g_ptr_array_index(global_props(), i);
766 if (prop->used) {
767 continue;
768 }
769 oc = object_class_by_name(prop->driver);
770 oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
771 if (!oc) {
772 warn_report("global %s.%s has invalid class name",
773 prop->driver, prop->property);
774 ret = 1;
775 continue;
776 }
777 dc = DEVICE_CLASS(oc);
778 if (!dc->hotpluggable && !prop->used) {
779 warn_report("global %s.%s=%s not used",
780 prop->driver, prop->property, prop->value);
781 ret = 1;
782 continue;
783 }
784 }
785 return ret;
786}
787
788void qdev_prop_set_globals(DeviceState *dev)
789{
790 object_apply_global_props(OBJECT(dev), global_props(),
791 dev->hotplugged ? NULL : &error_fatal);
792}
793
794
795
796static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
797 Error **errp)
798{
799 Property *prop = opaque;
800 uint64_t *ptr = object_field_prop_ptr(obj, prop);
801
802 visit_type_size(v, name, ptr, errp);
803}
804
805static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
806 Error **errp)
807{
808 Property *prop = opaque;
809 uint64_t *ptr = object_field_prop_ptr(obj, prop);
810
811 visit_type_size(v, name, ptr, errp);
812}
813
814const PropertyInfo qdev_prop_size = {
815 .name = "size",
816 .get = get_size,
817 .set = set_size,
818 .set_default_value = qdev_propinfo_set_default_value_uint,
819};
820
821
822
823static ObjectProperty *create_link_property(ObjectClass *oc, const char *name,
824 Property *prop)
825{
826 return object_class_property_add_link(oc, name, prop->link_type,
827 prop->offset,
828 qdev_prop_allow_set_link_before_realize,
829 OBJ_PROP_LINK_STRONG);
830}
831
832const PropertyInfo qdev_prop_link = {
833 .name = "link",
834 .create = create_link_property,
835};
836
837void qdev_property_add_static(DeviceState *dev, Property *prop)
838{
839 Object *obj = OBJECT(dev);
840 ObjectProperty *op;
841
842 assert(!prop->info->create);
843
844 op = object_property_add(obj, prop->name, prop->info->name,
845 field_prop_getter(prop->info),
846 field_prop_setter(prop->info),
847 prop->info->release,
848 prop);
849
850 object_property_set_description(obj, prop->name,
851 prop->info->description);
852
853 if (prop->set_default) {
854 prop->info->set_default_value(op, prop);
855 if (op->init) {
856 op->init(obj, op);
857 }
858 }
859}
860
861static void qdev_class_add_property(DeviceClass *klass, const char *name,
862 Property *prop)
863{
864 ObjectClass *oc = OBJECT_CLASS(klass);
865 ObjectProperty *op;
866
867 if (prop->info->create) {
868 op = prop->info->create(oc, name, prop);
869 } else {
870 op = object_class_property_add(oc,
871 name, prop->info->name,
872 field_prop_getter(prop->info),
873 field_prop_setter(prop->info),
874 prop->info->release,
875 prop);
876 }
877 if (prop->set_default) {
878 prop->info->set_default_value(op, prop);
879 }
880 object_class_property_set_description(oc, name, prop->info->description);
881}
882
883
884
885
886
887static void qdev_get_legacy_property(Object *obj, Visitor *v,
888 const char *name, void *opaque,
889 Error **errp)
890{
891 Property *prop = opaque;
892
893 char buffer[1024];
894 char *ptr = buffer;
895
896 prop->info->print(obj, prop, buffer, sizeof(buffer));
897 visit_type_str(v, name, &ptr, errp);
898}
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914static void qdev_class_add_legacy_property(DeviceClass *dc, Property *prop)
915{
916 g_autofree char *name = NULL;
917
918
919 if (!prop->info->print && prop->info->get) {
920 return;
921 }
922
923 name = g_strdup_printf("legacy-%s", prop->name);
924 object_class_property_add(OBJECT_CLASS(dc), name, "str",
925 prop->info->print ? qdev_get_legacy_property : prop->info->get,
926 NULL, NULL, prop);
927}
928
929void device_class_set_props(DeviceClass *dc, Property *props)
930{
931 Property *prop;
932
933 dc->props_ = props;
934 for (prop = props; prop && prop->name; prop++) {
935 qdev_class_add_legacy_property(dc, prop);
936 qdev_class_add_property(dc, prop->name, prop);
937 }
938}
939
940void qdev_alias_all_properties(DeviceState *target, Object *source)
941{
942 ObjectClass *class;
943 Property *prop;
944
945 class = object_get_class(OBJECT(target));
946 do {
947 DeviceClass *dc = DEVICE_CLASS(class);
948
949 for (prop = dc->props_; prop && prop->name; prop++) {
950 object_property_add_alias(source, prop->name,
951 OBJECT(target), prop->name);
952 }
953 class = object_class_get_parent(class);
954 } while (class != object_class_by_name(TYPE_DEVICE));
955}
956