]> git.proxmox.com Git - mirror_qemu.git/blame - hw/core/qdev-properties.c
qdev: Move dev->realized check to qdev_property_set()
[mirror_qemu.git] / hw / core / qdev-properties.c
CommitLineData
18c86e2b 1#include "qemu/osdep.h"
a27bd6c7 2#include "hw/qdev-properties.h"
da34e65c 3#include "qapi/error.h"
2ae16a6a 4#include "qapi/qapi-types-misc.h"
7b1b5d19 5#include "qapi/qmp/qerror.h"
856dfd8a 6#include "qemu/ctype.h"
d49b6836 7#include "qemu/error-report.h"
7b1b5d19 8#include "qapi/visitor.h"
645b55d1 9#include "qemu/units.h"
f7806925 10#include "qemu/cutils.h"
a2974439 11#include "qdev-prop-internal.h"
ee6847d1 12
b000dfbd
PM
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
ea7c1e5c
EH
27/* returns: true if property is allowed to be set, false otherwise */
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
8f5d58ef
IM
40void qdev_prop_allow_set_link_before_realize(const Object *obj,
41 const char *name,
39f72ef9
SH
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
828ade86 53void *qdev_get_prop_ptr(Object *obj, Property *prop)
ee6847d1 54{
828ade86 55 void *ptr = obj;
ee6847d1
GH
56 ptr += prop->offset;
57 return ptr;
58}
59
7ed854af
EH
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 * field_prop_getter: Return getter function to be used for property
69 *
70 * Return value can be NULL if @info has no getter function.
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;
ea7c1e5c
EH
81
82 if (!qdev_prop_allow_set(obj, name, errp)) {
83 return;
84 }
85
7ed854af
EH
86 return prop->info->set(obj, v, name, opaque, errp);
87}
88
89/**
90 * field_prop_setter: Return setter function to be used for property
91 *
92 * Return value can be NULL if @info has not setter function.
93 */
94static ObjectPropertyAccessor *field_prop_setter(const PropertyInfo *info)
95{
96 return info->set ? field_prop_set : NULL;
97}
98
a2974439
PMD
99void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name,
100 void *opaque, Error **errp)
d4d34b0d 101{
d4d34b0d 102 Property *prop = opaque;
828ade86 103 int *ptr = qdev_get_prop_ptr(obj, prop);
d4d34b0d 104
991f0ac9 105 visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
d4d34b0d
MA
106}
107
a2974439
PMD
108void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name,
109 void *opaque, Error **errp)
d4d34b0d 110{
d4d34b0d 111 Property *prop = opaque;
828ade86 112 int *ptr = qdev_get_prop_ptr(obj, prop);
d4d34b0d 113
991f0ac9 114 visit_type_enum(v, name, ptr, prop->info->enum_table, errp);
d4d34b0d
MA
115}
116
a2974439
PMD
117void qdev_propinfo_set_default_value_enum(ObjectProperty *op,
118 const Property *prop)
a2740ad5 119{
77b06bba
MAL
120 object_property_set_default_str(op,
121 qapi_enum_lookup(prop->info->enum_table, prop->defval.i));
a2740ad5
MAL
122}
123
79bdf29c
PMD
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
d4d34b0d
MA
131/* Bit */
132
d2364ee4
MT
133static uint32_t qdev_get_prop_mask(Property *prop)
134{
a3d4a1b0 135 assert(prop->info == &qdev_prop_bit);
d2364ee4
MT
136 return 0x1 << prop->bitnr;
137}
138
605d9fc0 139static void bit_prop_set(Object *obj, Property *props, bool val)
d2364ee4 140{
828ade86 141 uint32_t *p = qdev_get_prop_ptr(obj, props);
d2364ee4 142 uint32_t mask = qdev_get_prop_mask(props);
04a2d61e 143 if (val) {
dbd48324 144 *p |= mask;
04a2d61e 145 } else {
d2364ee4 146 *p &= ~mask;
04a2d61e 147 }
d2364ee4
MT
148}
149
d7bce999
EB
150static void prop_get_bit(Object *obj, Visitor *v, const char *name,
151 void *opaque, Error **errp)
80e555c2
PB
152{
153 Property *prop = opaque;
828ade86 154 uint32_t *p = qdev_get_prop_ptr(obj, prop);
80e555c2
PB
155 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
156
51e72bc1 157 visit_type_bool(v, name, &value, errp);
80e555c2
PB
158}
159
d7bce999
EB
160static void prop_set_bit(Object *obj, Visitor *v, const char *name,
161 void *opaque, Error **errp)
80e555c2
PB
162{
163 Property *prop = opaque;
80e555c2
PB
164 bool value;
165
668f62ec 166 if (!visit_type_bool(v, name, &value, errp)) {
80e555c2
PB
167 return;
168 }
605d9fc0 169 bit_prop_set(obj, prop, value);
80e555c2
PB
170}
171
77b06bba 172static void set_default_value_bool(ObjectProperty *op, const Property *prop)
a2740ad5 173{
77b06bba 174 object_property_set_default_bool(op, prop->defval.u);
a2740ad5
MAL
175}
176
1b6b7d10 177const PropertyInfo qdev_prop_bit = {
85ca1202 178 .name = "bool",
51b2e8c3 179 .description = "on/off",
949fc823
MA
180 .get = prop_get_bit,
181 .set = prop_set_bit,
a2740ad5 182 .set_default_value = set_default_value_bool,
d2364ee4
MT
183};
184
fdba6d96
GH
185/* Bit64 */
186
187static uint64_t qdev_get_prop_mask64(Property *prop)
188{
8aedc369 189 assert(prop->info == &qdev_prop_bit64);
1fa795a8 190 return 0x1ull << prop->bitnr;
fdba6d96
GH
191}
192
605d9fc0 193static void bit64_prop_set(Object *obj, Property *props, bool val)
fdba6d96 194{
828ade86 195 uint64_t *p = qdev_get_prop_ptr(obj, props);
fdba6d96
GH
196 uint64_t mask = qdev_get_prop_mask64(props);
197 if (val) {
198 *p |= mask;
199 } else {
200 *p &= ~mask;
201 }
202}
203
d7bce999
EB
204static void prop_get_bit64(Object *obj, Visitor *v, const char *name,
205 void *opaque, Error **errp)
fdba6d96 206{
fdba6d96 207 Property *prop = opaque;
828ade86 208 uint64_t *p = qdev_get_prop_ptr(obj, prop);
fdba6d96
GH
209 bool value = (*p & qdev_get_prop_mask64(prop)) != 0;
210
51e72bc1 211 visit_type_bool(v, name, &value, errp);
fdba6d96
GH
212}
213
d7bce999
EB
214static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
215 void *opaque, Error **errp)
fdba6d96 216{
fdba6d96 217 Property *prop = opaque;
fdba6d96
GH
218 bool value;
219
668f62ec 220 if (!visit_type_bool(v, name, &value, errp)) {
fdba6d96
GH
221 return;
222 }
605d9fc0 223 bit64_prop_set(obj, prop, value);
fdba6d96
GH
224}
225
1b6b7d10 226const PropertyInfo qdev_prop_bit64 = {
fdba6d96
GH
227 .name = "bool",
228 .description = "on/off",
229 .get = prop_get_bit64,
230 .set = prop_set_bit64,
a2740ad5 231 .set_default_value = set_default_value_bool,
fdba6d96
GH
232};
233
72cc5137
IM
234/* --- bool --- */
235
d7bce999
EB
236static void get_bool(Object *obj, Visitor *v, const char *name, void *opaque,
237 Error **errp)
72cc5137 238{
72cc5137 239 Property *prop = opaque;
828ade86 240 bool *ptr = qdev_get_prop_ptr(obj, prop);
72cc5137 241
51e72bc1 242 visit_type_bool(v, name, ptr, errp);
72cc5137
IM
243}
244
d7bce999
EB
245static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
246 Error **errp)
72cc5137 247{
72cc5137 248 Property *prop = opaque;
828ade86 249 bool *ptr = qdev_get_prop_ptr(obj, prop);
72cc5137 250
51e72bc1 251 visit_type_bool(v, name, ptr, errp);
72cc5137
IM
252}
253
1b6b7d10 254const PropertyInfo qdev_prop_bool = {
85ca1202 255 .name = "bool",
72cc5137
IM
256 .get = get_bool,
257 .set = set_bool,
a2740ad5 258 .set_default_value = set_default_value_bool,
72cc5137
IM
259};
260
c7cc172d
JQ
261/* --- 8bit integer --- */
262
d7bce999
EB
263static void get_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
264 Error **errp)
80e555c2
PB
265{
266 Property *prop = opaque;
828ade86 267 uint8_t *ptr = qdev_get_prop_ptr(obj, prop);
80e555c2 268
51e72bc1 269 visit_type_uint8(v, name, ptr, errp);
80e555c2
PB
270}
271
d7bce999
EB
272static void set_uint8(Object *obj, Visitor *v, const char *name, void *opaque,
273 Error **errp)
80e555c2
PB
274{
275 Property *prop = opaque;
828ade86 276 uint8_t *ptr = qdev_get_prop_ptr(obj, prop);
80e555c2 277
51e72bc1 278 visit_type_uint8(v, name, ptr, errp);
80e555c2
PB
279}
280
93e163e4
PMD
281void qdev_propinfo_set_default_value_int(ObjectProperty *op,
282 const Property *prop)
a2740ad5 283{
77b06bba 284 object_property_set_default_int(op, prop->defval.i);
a2740ad5
MAL
285}
286
93e163e4
PMD
287void qdev_propinfo_set_default_value_uint(ObjectProperty *op,
288 const Property *prop)
3fb2111f 289{
77b06bba 290 object_property_set_default_uint(op, prop->defval.u);
3fb2111f
MAL
291}
292
1b6b7d10 293const PropertyInfo qdev_prop_uint8 = {
c7cc172d 294 .name = "uint8",
c08fb2ac
MR
295 .get = get_uint8,
296 .set = set_uint8,
93e163e4 297 .set_default_value = qdev_propinfo_set_default_value_uint,
c7cc172d
JQ
298};
299
ee6847d1
GH
300/* --- 16bit integer --- */
301
364f7e83
EH
302static void get_uint16(Object *obj, Visitor *v, const char *name,
303 void *opaque, Error **errp)
80e555c2
PB
304{
305 Property *prop = opaque;
828ade86 306 uint16_t *ptr = qdev_get_prop_ptr(obj, prop);
80e555c2 307
51e72bc1 308 visit_type_uint16(v, name, ptr, errp);
80e555c2
PB
309}
310
d7bce999
EB
311static void set_uint16(Object *obj, Visitor *v, const char *name,
312 void *opaque, Error **errp)
80e555c2
PB
313{
314 Property *prop = opaque;
828ade86 315 uint16_t *ptr = qdev_get_prop_ptr(obj, prop);
80e555c2 316
51e72bc1 317 visit_type_uint16(v, name, ptr, errp);
80e555c2
PB
318}
319
1b6b7d10 320const PropertyInfo qdev_prop_uint16 = {
ee6847d1 321 .name = "uint16",
364f7e83 322 .get = get_uint16,
c08fb2ac 323 .set = set_uint16,
93e163e4 324 .set_default_value = qdev_propinfo_set_default_value_uint,
ee6847d1
GH
325};
326
327/* --- 32bit integer --- */
328
d7bce999
EB
329static void get_uint32(Object *obj, Visitor *v, const char *name,
330 void *opaque, Error **errp)
c08fb2ac 331{
c08fb2ac 332 Property *prop = opaque;
828ade86 333 uint32_t *ptr = qdev_get_prop_ptr(obj, prop);
c08fb2ac 334
51e72bc1 335 visit_type_uint32(v, name, ptr, errp);
c08fb2ac
MR
336}
337
d7bce999
EB
338static void set_uint32(Object *obj, Visitor *v, const char *name,
339 void *opaque, Error **errp)
c08fb2ac 340{
c08fb2ac 341 Property *prop = opaque;
828ade86 342 uint32_t *ptr = qdev_get_prop_ptr(obj, prop);
c08fb2ac 343
51e72bc1 344 visit_type_uint32(v, name, ptr, errp);
c08fb2ac
MR
345}
346
93e163e4
PMD
347void qdev_propinfo_get_int32(Object *obj, Visitor *v, const char *name,
348 void *opaque, Error **errp)
80e555c2
PB
349{
350 Property *prop = opaque;
828ade86 351 int32_t *ptr = qdev_get_prop_ptr(obj, prop);
80e555c2 352
51e72bc1 353 visit_type_int32(v, name, ptr, errp);
80e555c2
PB
354}
355
d7bce999
EB
356static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
357 Error **errp)
80e555c2
PB
358{
359 Property *prop = opaque;
828ade86 360 int32_t *ptr = qdev_get_prop_ptr(obj, prop);
80e555c2 361
51e72bc1 362 visit_type_int32(v, name, ptr, errp);
80e555c2
PB
363}
364
1b6b7d10 365const PropertyInfo qdev_prop_uint32 = {
ee6847d1 366 .name = "uint32",
c08fb2ac
MR
367 .get = get_uint32,
368 .set = set_uint32,
93e163e4 369 .set_default_value = qdev_propinfo_set_default_value_uint,
ee6847d1
GH
370};
371
1b6b7d10 372const PropertyInfo qdev_prop_int32 = {
316940b0 373 .name = "int32",
93e163e4 374 .get = qdev_propinfo_get_int32,
80e555c2 375 .set = set_int32,
93e163e4 376 .set_default_value = qdev_propinfo_set_default_value_int,
316940b0
GH
377};
378
5a053d1f
BS
379/* --- 64bit integer --- */
380
d7bce999
EB
381static void get_uint64(Object *obj, Visitor *v, const char *name,
382 void *opaque, Error **errp)
80e555c2
PB
383{
384 Property *prop = opaque;
828ade86 385 uint64_t *ptr = qdev_get_prop_ptr(obj, prop);
80e555c2 386
51e72bc1 387 visit_type_uint64(v, name, ptr, errp);
80e555c2
PB
388}
389
d7bce999
EB
390static void set_uint64(Object *obj, Visitor *v, const char *name,
391 void *opaque, Error **errp)
80e555c2
PB
392{
393 Property *prop = opaque;
828ade86 394 uint64_t *ptr = qdev_get_prop_ptr(obj, prop);
80e555c2 395
51e72bc1 396 visit_type_uint64(v, name, ptr, errp);
80e555c2
PB
397}
398
07d1d063
PX
399static void get_int64(Object *obj, Visitor *v, const char *name,
400 void *opaque, Error **errp)
401{
07d1d063 402 Property *prop = opaque;
828ade86 403 int64_t *ptr = qdev_get_prop_ptr(obj, prop);
07d1d063
PX
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{
07d1d063 411 Property *prop = opaque;
828ade86 412 int64_t *ptr = qdev_get_prop_ptr(obj, prop);
07d1d063 413
07d1d063
PX
414 visit_type_int64(v, name, ptr, errp);
415}
416
1b6b7d10 417const PropertyInfo qdev_prop_uint64 = {
5a053d1f 418 .name = "uint64",
c08fb2ac
MR
419 .get = get_uint64,
420 .set = set_uint64,
93e163e4 421 .set_default_value = qdev_propinfo_set_default_value_uint,
5a053d1f
BS
422};
423
07d1d063
PX
424const PropertyInfo qdev_prop_int64 = {
425 .name = "int64",
426 .get = get_int64,
427 .set = set_int64,
93e163e4 428 .set_default_value = qdev_propinfo_set_default_value_int,
07d1d063
PX
429};
430
59419663
GH
431/* --- string --- */
432
dd0ba250 433static void release_string(Object *obj, const char *name, void *opaque)
d21357df 434{
dd0ba250 435 Property *prop = opaque;
828ade86 436 g_free(*(char **)qdev_get_prop_ptr(obj, prop));
d21357df
MA
437}
438
d7bce999
EB
439static void get_string(Object *obj, Visitor *v, const char *name,
440 void *opaque, Error **errp)
80e555c2
PB
441{
442 Property *prop = opaque;
828ade86 443 char **ptr = qdev_get_prop_ptr(obj, prop);
80e555c2
PB
444
445 if (!*ptr) {
446 char *str = (char *)"";
51e72bc1 447 visit_type_str(v, name, &str, errp);
80e555c2 448 } else {
51e72bc1 449 visit_type_str(v, name, ptr, errp);
80e555c2
PB
450 }
451}
452
d7bce999
EB
453static void set_string(Object *obj, Visitor *v, const char *name,
454 void *opaque, Error **errp)
80e555c2
PB
455{
456 Property *prop = opaque;
828ade86 457 char **ptr = qdev_get_prop_ptr(obj, prop);
80e555c2
PB
458 char *str;
459
668f62ec 460 if (!visit_type_str(v, name, &str, errp)) {
80e555c2
PB
461 return;
462 }
ef1e1e07 463 g_free(*ptr);
80e555c2
PB
464 *ptr = str;
465}
466
1b6b7d10 467const PropertyInfo qdev_prop_string = {
85ca1202 468 .name = "str",
dd0ba250 469 .release = release_string,
80e555c2
PB
470 .get = get_string,
471 .set = set_string,
59419663
GH
472};
473
55e8a154
MA
474/* --- on/off/auto --- */
475
1b6b7d10 476const PropertyInfo qdev_prop_on_off_auto = {
55e8a154
MA
477 .name = "OnOffAuto",
478 .description = "on/off/auto",
f7abe0ec 479 .enum_table = &OnOffAuto_lookup,
a2974439
PMD
480 .get = qdev_propinfo_get_enum,
481 .set = qdev_propinfo_set_enum,
482 .set_default_value = qdev_propinfo_set_default_value_enum,
55e8a154
MA
483};
484
914e74cd
RK
485/* --- 32bit unsigned int 'size' type --- */
486
93e163e4
PMD
487void qdev_propinfo_get_size32(Object *obj, Visitor *v, const char *name,
488 void *opaque, Error **errp)
031ffd9a 489{
031ffd9a 490 Property *prop = opaque;
828ade86 491 uint32_t *ptr = qdev_get_prop_ptr(obj, prop);
031ffd9a
RK
492 uint64_t value = *ptr;
493
494 visit_type_size(v, name, &value, errp);
495}
496
914e74cd
RK
497static void set_size32(Object *obj, Visitor *v, const char *name, void *opaque,
498 Error **errp)
499{
914e74cd 500 Property *prop = opaque;
828ade86 501 uint32_t *ptr = qdev_get_prop_ptr(obj, prop);
914e74cd 502 uint64_t value;
914e74cd 503
668f62ec 504 if (!visit_type_size(v, name, &value, errp)) {
914e74cd
RK
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)",
5eb32b21 512 object_get_typename(obj), name, value, UINT32_MAX);
914e74cd
RK
513 return;
514 }
515
516 *ptr = value;
517}
518
519const PropertyInfo qdev_prop_size32 = {
520 .name = "size",
93e163e4 521 .get = qdev_propinfo_get_size32,
914e74cd 522 .set = set_size32,
93e163e4 523 .set_default_value = qdev_propinfo_set_default_value_uint,
914e74cd
RK
524};
525
0be6bfac
PM
526/* --- support for array properties --- */
527
528/* Used as an opaque for the object properties we add for each
529 * array element. Note that the struct Property must be first
530 * in the struct so that a pointer to this works as the opaque
531 * for the underlying element's property hooks as well as for
532 * our own release callback.
533 */
534typedef struct {
535 struct Property prop;
536 char *propname;
537 ObjectPropertyRelease *release;
538} ArrayElementProperty;
539
540/* object property release callback for array element properties:
541 * we call the underlying element's property release hook, and
542 * then free the memory we allocated when we added the property.
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
d7bce999
EB
554static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
555 void *opaque, Error **errp)
0be6bfac
PM
556{
557 /* Setter for the property which defines the length of a
558 * variable-sized property array. As well as actually setting the
559 * array-length field in the device struct, we have to create the
560 * array itself and dynamically add the corresponding properties.
561 */
562 DeviceState *dev = DEVICE(obj);
563 Property *prop = opaque;
828ade86 564 uint32_t *alenptr = qdev_get_prop_ptr(obj, prop);
0be6bfac
PM
565 void **arrayptr = (void *)dev + prop->arrayoffset;
566 void *eltptr;
567 const char *arrayname;
568 int i;
569
0be6bfac
PM
570 if (*alenptr) {
571 error_setg(errp, "array size property %s may not be set more than once",
572 name);
573 return;
574 }
668f62ec 575 if (!visit_type_uint32(v, name, alenptr, errp)) {
0be6bfac
PM
576 return;
577 }
578 if (!*alenptr) {
579 return;
580 }
581
582 /* DEFINE_PROP_ARRAY guarantees that name should start with this prefix;
583 * strip it off so we can get the name of the array itself.
584 */
585 assert(strncmp(name, PROP_ARRAY_LEN_PREFIX,
586 strlen(PROP_ARRAY_LEN_PREFIX)) == 0);
587 arrayname = name + strlen(PROP_ARRAY_LEN_PREFIX);
588
589 /* Note that it is the responsibility of the individual device's deinit
590 * to free the array proper.
591 */
592 *arrayptr = eltptr = g_malloc0(*alenptr * prop->arrayfieldsize);
593 for (i = 0; i < *alenptr; i++, eltptr += prop->arrayfieldsize) {
594 char *propname = g_strdup_printf("%s[%d]", arrayname, i);
595 ArrayElementProperty *arrayprop = g_new0(ArrayElementProperty, 1);
596 arrayprop->release = prop->arrayinfo->release;
597 arrayprop->propname = propname;
598 arrayprop->prop.info = prop->arrayinfo;
599 arrayprop->prop.name = propname;
600 /* This ugly piece of pointer arithmetic sets up the offset so
601 * that when the underlying get/set hooks call qdev_get_prop_ptr
602 * they get the right answer despite the array element not actually
603 * being inside the device struct.
604 */
605 arrayprop->prop.offset = eltptr - (void *)dev;
828ade86 606 assert(qdev_get_prop_ptr(obj, &arrayprop->prop) == eltptr);
0be6bfac
PM
607 object_property_add(obj, propname,
608 arrayprop->prop.info->name,
7ed854af
EH
609 field_prop_getter(arrayprop->prop.info),
610 field_prop_setter(arrayprop->prop.info),
0be6bfac 611 array_element_release,
d2623129 612 arrayprop);
0be6bfac
PM
613 }
614}
615
1b6b7d10 616const PropertyInfo qdev_prop_arraylen = {
0be6bfac
PM
617 .name = "uint32",
618 .get = get_uint32,
619 .set = set_prop_arraylen,
93e163e4 620 .set_default_value = qdev_propinfo_set_default_value_uint,
0be6bfac
PM
621};
622
ee6847d1
GH
623/* --- public helpers --- */
624
625static Property *qdev_prop_walk(Property *props, const char *name)
626{
04a2d61e 627 if (!props) {
ee6847d1 628 return NULL;
04a2d61e 629 }
ee6847d1 630 while (props->name) {
04a2d61e 631 if (strcmp(props->name, name) == 0) {
ee6847d1 632 return props;
04a2d61e 633 }
ee6847d1
GH
634 props++;
635 }
636 return NULL;
637}
638
639static Property *qdev_prop_find(DeviceState *dev, const char *name)
640{
bce54474 641 ObjectClass *class;
ee6847d1
GH
642 Property *prop;
643
644 /* device properties */
bce54474
PB
645 class = object_get_class(OBJECT(dev));
646 do {
385d8f22 647 prop = qdev_prop_walk(DEVICE_CLASS(class)->props_, name);
bce54474
PB
648 if (prop) {
649 return prop;
650 }
651 class = object_class_get_parent(class);
652 } while (class != object_class_by_name(TYPE_DEVICE));
ee6847d1
GH
653
654 return NULL;
655}
656
c7525b18 657void error_set_from_qdev_prop_error(Error **errp, int ret, Object *obj,
e68c2cb7 658 const char *name, const char *value)
7db4c4e8
PB
659{
660 switch (ret) {
661 case -EEXIST:
f231b88d 662 error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
e68c2cb7 663 object_get_typename(obj), name, value);
7db4c4e8
PB
664 break;
665 default:
666 case -EINVAL:
c6bd8c70 667 error_setg(errp, QERR_PROPERTY_VALUE_BAD,
e68c2cb7 668 object_get_typename(obj), name, value);
7db4c4e8
PB
669 break;
670 case -ENOENT:
f231b88d 671 error_setg(errp, "Property '%s.%s' can't find value '%s'",
e68c2cb7 672 object_get_typename(obj), name, value);
7db4c4e8
PB
673 break;
674 case 0:
675 break;
676 }
677}
678
f4594a3b
IY
679void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
680{
5325cc34 681 object_property_set_bool(OBJECT(dev), name, value, &error_abort);
f4594a3b
IY
682}
683
c7cc172d
JQ
684void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
685{
5325cc34 686 object_property_set_int(OBJECT(dev), name, value, &error_abort);
c7cc172d
JQ
687}
688
ee6847d1
GH
689void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
690{
5325cc34 691 object_property_set_int(OBJECT(dev), name, value, &error_abort);
ee6847d1
GH
692}
693
694void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
695{
5325cc34 696 object_property_set_int(OBJECT(dev), name, value, &error_abort);
ee6847d1
GH
697}
698
316940b0
GH
699void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
700{
5325cc34 701 object_property_set_int(OBJECT(dev), name, value, &error_abort);
316940b0
GH
702}
703
5a053d1f
BS
704void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
705{
5325cc34 706 object_property_set_int(OBJECT(dev), name, value, &error_abort);
5a053d1f
BS
707}
708
3b25597b 709void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
cc984673 710{
5325cc34 711 object_property_set_str(OBJECT(dev), name, value, &error_abort);
cc984673
MA
712}
713
9b170e60 714void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
4e4fa398 715{
9b170e60 716 Property *prop;
9b170e60
PB
717
718 prop = qdev_prop_find(dev, name);
5325cc34 719 object_property_set_str(OBJECT(dev), name,
788b305c 720 qapi_enum_lookup(prop->info->enum_table, value),
5325cc34 721 &error_abort);
4e4fa398
JK
722}
723
e12ca3ce
MAL
724static GPtrArray *global_props(void)
725{
726 static GPtrArray *gp;
727
728 if (!gp) {
729 gp = g_ptr_array_new();
730 }
731
732 return gp;
733}
b6b61144 734
a404b612 735void qdev_prop_register_global(GlobalProperty *prop)
b6b61144 736{
e12ca3ce 737 g_ptr_array_add(global_props(), prop);
b6b61144
GH
738}
739
39501275 740const GlobalProperty *qdev_find_global_prop(Object *obj,
1bc13336
MA
741 const char *name)
742{
743 GPtrArray *props = global_props();
744 const GlobalProperty *p;
745 int i;
746
747 for (i = 0; i < props->len; i++) {
748 p = g_ptr_array_index(props, i);
39501275 749 if (object_dynamic_cast(obj, p->driver)
1bc13336
MA
750 && !strcmp(p->property, name)) {
751 return p;
752 }
753 }
754 return NULL;
755}
756
d828c430 757int qdev_prop_check_globals(void)
9f9260a3 758{
e12ca3ce 759 int i, ret = 0;
9f9260a3 760
e12ca3ce
MAL
761 for (i = 0; i < global_props()->len; i++) {
762 GlobalProperty *prop;
b3ce84fe
EH
763 ObjectClass *oc;
764 DeviceClass *dc;
e12ca3ce
MAL
765
766 prop = g_ptr_array_index(global_props(), i);
b3ce84fe
EH
767 if (prop->used) {
768 continue;
769 }
b3ce84fe
EH
770 oc = object_class_by_name(prop->driver);
771 oc = object_class_dynamic_cast(oc, TYPE_DEVICE);
772 if (!oc) {
3dc6f869
AF
773 warn_report("global %s.%s has invalid class name",
774 prop->driver, prop->property);
b3ce84fe
EH
775 ret = 1;
776 continue;
777 }
778 dc = DEVICE_CLASS(oc);
779 if (!dc->hotpluggable && !prop->used) {
3dc6f869
AF
780 warn_report("global %s.%s=%s not used",
781 prop->driver, prop->property, prop->value);
b3ce84fe 782 ret = 1;
9f9260a3
DS
783 continue;
784 }
9f9260a3
DS
785 }
786 return ret;
787}
788
5eb6a3c5 789void qdev_prop_set_globals(DeviceState *dev)
868d378b 790{
50545b2c
MAL
791 object_apply_global_props(OBJECT(dev), global_props(),
792 dev->hotplugged ? NULL : &error_fatal);
868d378b
AF
793}
794
e8cd45c7
VL
795/* --- 64bit unsigned int 'size' type --- */
796
d7bce999
EB
797static void get_size(Object *obj, Visitor *v, const char *name, void *opaque,
798 Error **errp)
e8cd45c7 799{
e8cd45c7 800 Property *prop = opaque;
828ade86 801 uint64_t *ptr = qdev_get_prop_ptr(obj, prop);
e8cd45c7 802
51e72bc1 803 visit_type_size(v, name, ptr, errp);
e8cd45c7
VL
804}
805
d7bce999
EB
806static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
807 Error **errp)
e8cd45c7 808{
e8cd45c7 809 Property *prop = opaque;
828ade86 810 uint64_t *ptr = qdev_get_prop_ptr(obj, prop);
e8cd45c7 811
51e72bc1 812 visit_type_size(v, name, ptr, errp);
e8cd45c7
VL
813}
814
1b6b7d10 815const PropertyInfo qdev_prop_size = {
e8cd45c7 816 .name = "size",
e8cd45c7
VL
817 .get = get_size,
818 .set = set_size,
93e163e4 819 .set_default_value = qdev_propinfo_set_default_value_uint,
e8cd45c7 820};
5b4ff3c6
FZ
821
822/* --- object link property --- */
823
c80fab0b
EH
824static void create_link_property(ObjectClass *oc, const char *name,
825 Property *prop)
5b4ff3c6 826{
c80fab0b 827 object_class_property_add_link(oc, name, prop->link_type,
77b06bba
MAL
828 prop->offset,
829 qdev_prop_allow_set_link_before_realize,
d2623129 830 OBJ_PROP_LINK_STRONG);
5b4ff3c6
FZ
831}
832
1b6b7d10 833const PropertyInfo qdev_prop_link = {
5b4ff3c6
FZ
834 .name = "link",
835 .create = create_link_property,
836};
d3fd6e73
EH
837
838void qdev_property_add_static(DeviceState *dev, Property *prop)
839{
840 Object *obj = OBJECT(dev);
841 ObjectProperty *op;
842
843 assert(!prop->info->create);
844
845 op = object_property_add(obj, prop->name, prop->info->name,
7ed854af
EH
846 field_prop_getter(prop->info),
847 field_prop_setter(prop->info),
d3fd6e73
EH
848 prop->info->release,
849 prop);
850
851 object_property_set_description(obj, prop->name,
852 prop->info->description);
853
854 if (prop->set_default) {
855 prop->info->set_default_value(op, prop);
856 if (op->init) {
857 op->init(obj, op);
858 }
859 }
860}
861
23a1dae8
EH
862static void qdev_class_add_property(DeviceClass *klass, const char *name,
863 Property *prop)
d3fd6e73
EH
864{
865 ObjectClass *oc = OBJECT_CLASS(klass);
866
867 if (prop->info->create) {
c80fab0b 868 prop->info->create(oc, name, prop);
d3fd6e73
EH
869 } else {
870 ObjectProperty *op;
871
872 op = object_class_property_add(oc,
23a1dae8 873 name, prop->info->name,
7ed854af
EH
874 field_prop_getter(prop->info),
875 field_prop_setter(prop->info),
d3fd6e73
EH
876 prop->info->release,
877 prop);
878 if (prop->set_default) {
879 prop->info->set_default_value(op, prop);
880 }
881 }
23a1dae8 882 object_class_property_set_description(oc, name,
d3fd6e73
EH
883 prop->info->description);
884}
885
886/**
887 * Legacy property handling
888 */
889
890static void qdev_get_legacy_property(Object *obj, Visitor *v,
891 const char *name, void *opaque,
892 Error **errp)
893{
d3fd6e73
EH
894 Property *prop = opaque;
895
896 char buffer[1024];
897 char *ptr = buffer;
898
40ea00b0 899 prop->info->print(obj, prop, buffer, sizeof(buffer));
d3fd6e73
EH
900 visit_type_str(v, name, &ptr, errp);
901}
902
903/**
904 * qdev_class_add_legacy_property:
905 * @dev: Device to add the property to.
906 * @prop: The qdev property definition.
907 *
908 * Add a legacy QOM property to @dev for qdev property @prop.
909 *
910 * Legacy properties are string versions of QOM properties. The format of
911 * the string depends on the property type. Legacy properties are only
912 * needed for "info qtree".
913 *
914 * Do not use this in new code! QOM Properties added through this interface
915 * will be given names in the "legacy" namespace.
916 */
917static void qdev_class_add_legacy_property(DeviceClass *dc, Property *prop)
918{
919 g_autofree char *name = NULL;
920
921 /* Register pointer properties as legacy properties */
922 if (!prop->info->print && prop->info->get) {
923 return;
924 }
925
926 name = g_strdup_printf("legacy-%s", prop->name);
927 object_class_property_add(OBJECT_CLASS(dc), name, "str",
928 prop->info->print ? qdev_get_legacy_property : prop->info->get,
929 NULL, NULL, prop);
930}
931
932void device_class_set_props(DeviceClass *dc, Property *props)
933{
934 Property *prop;
935
936 dc->props_ = props;
937 for (prop = props; prop && prop->name; prop++) {
938 qdev_class_add_legacy_property(dc, prop);
23a1dae8 939 qdev_class_add_property(dc, prop->name, prop);
d3fd6e73
EH
940 }
941}
942
943void qdev_alias_all_properties(DeviceState *target, Object *source)
944{
945 ObjectClass *class;
946 Property *prop;
947
948 class = object_get_class(OBJECT(target));
949 do {
950 DeviceClass *dc = DEVICE_CLASS(class);
951
952 for (prop = dc->props_; prop && prop->name; prop++) {
953 object_property_add_alias(source, prop->name,
954 OBJECT(target), prop->name);
955 }
956 class = object_class_get_parent(class);
957 } while (class != object_class_by_name(TYPE_DEVICE));
958}