]> git.proxmox.com Git - qemu.git/blame - hw/qdev-properties.c
net: reorganize headers
[qemu.git] / hw / qdev-properties.c
CommitLineData
1422e32d 1#include "net/net.h"
ee6847d1 2#include "qdev.h"
9f59b566 3#include "qerror.h"
2446333c 4#include "blockdev.h"
2b584959 5#include "hw/block-common.h"
606c10e2 6#include "net/hub.h"
074a86fc 7#include "qapi/qapi-visit-core.h"
077805fa 8#include "qemu-char.h"
ee6847d1
GH
9
10void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
11{
12 void *ptr = dev;
13 ptr += prop->offset;
14 return ptr;
15}
16
d4d34b0d
MA
17static void get_pointer(Object *obj, Visitor *v, Property *prop,
18 const char *(*print)(void *ptr),
19 const char *name, Error **errp)
20{
21 DeviceState *dev = DEVICE(obj);
22 void **ptr = qdev_get_prop_ptr(dev, prop);
23 char *p;
24
25 p = (char *) (*ptr ? print(*ptr) : "");
26 visit_type_str(v, &p, name, errp);
27}
28
29static void set_pointer(Object *obj, Visitor *v, Property *prop,
30 int (*parse)(DeviceState *dev, const char *str,
31 void **ptr),
32 const char *name, Error **errp)
33{
34 DeviceState *dev = DEVICE(obj);
35 Error *local_err = NULL;
36 void **ptr = qdev_get_prop_ptr(dev, prop);
37 char *str;
38 int ret;
39
40 if (dev->state != DEV_STATE_CREATED) {
41 error_set(errp, QERR_PERMISSION_DENIED);
42 return;
43 }
44
45 visit_type_str(v, &str, name, &local_err);
46 if (local_err) {
47 error_propagate(errp, local_err);
48 return;
49 }
50 if (!*str) {
51 g_free(str);
52 *ptr = NULL;
53 return;
54 }
55 ret = parse(dev, str, ptr);
56 error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
57 g_free(str);
58}
59
60static void get_enum(Object *obj, Visitor *v, void *opaque,
61 const char *name, Error **errp)
62{
63 DeviceState *dev = DEVICE(obj);
64 Property *prop = opaque;
65 int *ptr = qdev_get_prop_ptr(dev, prop);
66
67 visit_type_enum(v, ptr, prop->info->enum_table,
68 prop->info->name, prop->name, errp);
69}
70
71static void set_enum(Object *obj, Visitor *v, void *opaque,
72 const char *name, Error **errp)
73{
74 DeviceState *dev = DEVICE(obj);
75 Property *prop = opaque;
76 int *ptr = qdev_get_prop_ptr(dev, prop);
77
78 if (dev->state != DEV_STATE_CREATED) {
79 error_set(errp, QERR_PERMISSION_DENIED);
80 return;
81 }
82
83 visit_type_enum(v, ptr, prop->info->enum_table,
84 prop->info->name, prop->name, errp);
85}
86
87/* Bit */
88
d2364ee4
MT
89static uint32_t qdev_get_prop_mask(Property *prop)
90{
a3d4a1b0 91 assert(prop->info == &qdev_prop_bit);
d2364ee4
MT
92 return 0x1 << prop->bitnr;
93}
94
95static void bit_prop_set(DeviceState *dev, Property *props, bool val)
96{
97 uint32_t *p = qdev_get_prop_ptr(dev, props);
98 uint32_t mask = qdev_get_prop_mask(props);
99 if (val)
dbd48324 100 *p |= mask;
d2364ee4
MT
101 else
102 *p &= ~mask;
103}
104
d2364ee4
MT
105static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
106{
5a5e3d55 107 uint32_t *p = qdev_get_prop_ptr(dev, prop);
d2364ee4
MT
108 return snprintf(dest, len, (*p & qdev_get_prop_mask(prop)) ? "on" : "off");
109}
110
57c9fafe 111static void get_bit(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
112 const char *name, Error **errp)
113{
57c9fafe 114 DeviceState *dev = DEVICE(obj);
80e555c2
PB
115 Property *prop = opaque;
116 uint32_t *p = qdev_get_prop_ptr(dev, prop);
117 bool value = (*p & qdev_get_prop_mask(prop)) != 0;
118
119 visit_type_bool(v, &value, name, errp);
120}
121
57c9fafe 122static void set_bit(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
123 const char *name, Error **errp)
124{
57c9fafe 125 DeviceState *dev = DEVICE(obj);
80e555c2
PB
126 Property *prop = opaque;
127 Error *local_err = NULL;
128 bool value;
129
130 if (dev->state != DEV_STATE_CREATED) {
131 error_set(errp, QERR_PERMISSION_DENIED);
132 return;
133 }
134
135 visit_type_bool(v, &value, name, &local_err);
136 if (local_err) {
137 error_propagate(errp, local_err);
138 return;
139 }
140 bit_prop_set(dev, prop, value);
141}
142
d2364ee4 143PropertyInfo qdev_prop_bit = {
cafe5bdb
PB
144 .name = "boolean",
145 .legacy_name = "on/off",
d2364ee4 146 .print = print_bit,
80e555c2
PB
147 .get = get_bit,
148 .set = set_bit,
d2364ee4
MT
149};
150
c7cc172d
JQ
151/* --- 8bit integer --- */
152
c08fb2ac
MR
153static void get_uint8(Object *obj, Visitor *v, void *opaque,
154 const char *name, Error **errp)
80e555c2 155{
57c9fafe 156 DeviceState *dev = DEVICE(obj);
80e555c2 157 Property *prop = opaque;
c08fb2ac 158 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2 159
c08fb2ac 160 visit_type_uint8(v, ptr, name, errp);
80e555c2
PB
161}
162
c08fb2ac
MR
163static void set_uint8(Object *obj, Visitor *v, void *opaque,
164 const char *name, Error **errp)
80e555c2 165{
57c9fafe 166 DeviceState *dev = DEVICE(obj);
80e555c2 167 Property *prop = opaque;
27712df9 168 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
169
170 if (dev->state != DEV_STATE_CREATED) {
171 error_set(errp, QERR_PERMISSION_DENIED);
172 return;
173 }
174
27712df9 175 visit_type_uint8(v, ptr, name, errp);
80e555c2
PB
176}
177
c7cc172d
JQ
178PropertyInfo qdev_prop_uint8 = {
179 .name = "uint8",
c08fb2ac
MR
180 .get = get_uint8,
181 .set = set_uint8,
c7cc172d
JQ
182};
183
6835678c
JK
184/* --- 8bit hex value --- */
185
186static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
187{
188 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
189 char *end;
190
97aa6e9b
PB
191 if (str[0] != '0' || str[1] != 'x') {
192 return -EINVAL;
193 }
194
6835678c
JK
195 *ptr = strtoul(str, &end, 16);
196 if ((*end != '\0') || (end == str)) {
197 return -EINVAL;
198 }
199
200 return 0;
201}
202
203static int print_hex8(DeviceState *dev, Property *prop, char *dest, size_t len)
204{
205 uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
206 return snprintf(dest, len, "0x%" PRIx8, *ptr);
207}
208
209PropertyInfo qdev_prop_hex8 = {
cafe5bdb
PB
210 .name = "uint8",
211 .legacy_name = "hex8",
6835678c
JK
212 .parse = parse_hex8,
213 .print = print_hex8,
c08fb2ac
MR
214 .get = get_uint8,
215 .set = set_uint8,
6835678c
JK
216};
217
ee6847d1
GH
218/* --- 16bit integer --- */
219
c08fb2ac
MR
220static void get_uint16(Object *obj, Visitor *v, void *opaque,
221 const char *name, Error **errp)
80e555c2 222{
57c9fafe 223 DeviceState *dev = DEVICE(obj);
80e555c2 224 Property *prop = opaque;
c08fb2ac 225 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2 226
c08fb2ac 227 visit_type_uint16(v, ptr, name, errp);
80e555c2
PB
228}
229
c08fb2ac
MR
230static void set_uint16(Object *obj, Visitor *v, void *opaque,
231 const char *name, Error **errp)
80e555c2 232{
57c9fafe 233 DeviceState *dev = DEVICE(obj);
80e555c2 234 Property *prop = opaque;
27712df9 235 uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
236
237 if (dev->state != DEV_STATE_CREATED) {
238 error_set(errp, QERR_PERMISSION_DENIED);
239 return;
240 }
241
27712df9 242 visit_type_uint16(v, ptr, name, errp);
80e555c2
PB
243}
244
ee6847d1
GH
245PropertyInfo qdev_prop_uint16 = {
246 .name = "uint16",
c08fb2ac
MR
247 .get = get_uint16,
248 .set = set_uint16,
ee6847d1
GH
249};
250
251/* --- 32bit integer --- */
252
c08fb2ac
MR
253static void get_uint32(Object *obj, Visitor *v, void *opaque,
254 const char *name, Error **errp)
255{
256 DeviceState *dev = DEVICE(obj);
257 Property *prop = opaque;
27712df9 258 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
c08fb2ac 259
27712df9 260 visit_type_uint32(v, ptr, name, errp);
c08fb2ac
MR
261}
262
263static void set_uint32(Object *obj, Visitor *v, void *opaque,
264 const char *name, Error **errp)
265{
266 DeviceState *dev = DEVICE(obj);
267 Property *prop = opaque;
27712df9 268 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
c08fb2ac
MR
269
270 if (dev->state != DEV_STATE_CREATED) {
271 error_set(errp, QERR_PERMISSION_DENIED);
272 return;
273 }
274
27712df9 275 visit_type_uint32(v, ptr, name, errp);
c08fb2ac
MR
276}
277
57c9fafe 278static void get_int32(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
279 const char *name, Error **errp)
280{
57c9fafe 281 DeviceState *dev = DEVICE(obj);
80e555c2
PB
282 Property *prop = opaque;
283 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2 284
c08fb2ac 285 visit_type_int32(v, ptr, name, errp);
80e555c2
PB
286}
287
57c9fafe 288static void set_int32(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
289 const char *name, Error **errp)
290{
57c9fafe 291 DeviceState *dev = DEVICE(obj);
80e555c2 292 Property *prop = opaque;
27712df9 293 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
294
295 if (dev->state != DEV_STATE_CREATED) {
296 error_set(errp, QERR_PERMISSION_DENIED);
297 return;
298 }
299
27712df9 300 visit_type_int32(v, ptr, name, errp);
80e555c2
PB
301}
302
ee6847d1
GH
303PropertyInfo qdev_prop_uint32 = {
304 .name = "uint32",
c08fb2ac
MR
305 .get = get_uint32,
306 .set = set_uint32,
ee6847d1
GH
307};
308
316940b0
GH
309PropertyInfo qdev_prop_int32 = {
310 .name = "int32",
80e555c2
PB
311 .get = get_int32,
312 .set = set_int32,
316940b0
GH
313};
314
ee6847d1
GH
315/* --- 32bit hex value --- */
316
317static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
318{
319 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 320 char *end;
ee6847d1 321
97aa6e9b
PB
322 if (str[0] != '0' || str[1] != 'x') {
323 return -EINVAL;
324 }
325
449041d4
KW
326 *ptr = strtoul(str, &end, 16);
327 if ((*end != '\0') || (end == str)) {
6bf38816 328 return -EINVAL;
449041d4
KW
329 }
330
ee6847d1
GH
331 return 0;
332}
333
334static int print_hex32(DeviceState *dev, Property *prop, char *dest, size_t len)
335{
336 uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
337 return snprintf(dest, len, "0x%" PRIx32, *ptr);
338}
339
340PropertyInfo qdev_prop_hex32 = {
cafe5bdb
PB
341 .name = "uint32",
342 .legacy_name = "hex32",
ee6847d1
GH
343 .parse = parse_hex32,
344 .print = print_hex32,
c08fb2ac
MR
345 .get = get_uint32,
346 .set = set_uint32,
ee6847d1
GH
347};
348
5a053d1f
BS
349/* --- 64bit integer --- */
350
c08fb2ac
MR
351static void get_uint64(Object *obj, Visitor *v, void *opaque,
352 const char *name, Error **errp)
80e555c2 353{
57c9fafe 354 DeviceState *dev = DEVICE(obj);
80e555c2 355 Property *prop = opaque;
c08fb2ac 356 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2 357
c08fb2ac 358 visit_type_uint64(v, ptr, name, errp);
80e555c2
PB
359}
360
c08fb2ac
MR
361static void set_uint64(Object *obj, Visitor *v, void *opaque,
362 const char *name, Error **errp)
80e555c2 363{
57c9fafe 364 DeviceState *dev = DEVICE(obj);
80e555c2 365 Property *prop = opaque;
c08fb2ac 366 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
80e555c2
PB
367
368 if (dev->state != DEV_STATE_CREATED) {
369 error_set(errp, QERR_PERMISSION_DENIED);
370 return;
371 }
372
c08fb2ac 373 visit_type_uint64(v, ptr, name, errp);
80e555c2
PB
374}
375
5a053d1f
BS
376PropertyInfo qdev_prop_uint64 = {
377 .name = "uint64",
c08fb2ac
MR
378 .get = get_uint64,
379 .set = set_uint64,
5a053d1f
BS
380};
381
382/* --- 64bit hex value --- */
383
384static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
385{
386 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
449041d4 387 char *end;
5a053d1f 388
97aa6e9b
PB
389 if (str[0] != '0' || str[1] != 'x') {
390 return -EINVAL;
391 }
392
449041d4
KW
393 *ptr = strtoull(str, &end, 16);
394 if ((*end != '\0') || (end == str)) {
6bf38816 395 return -EINVAL;
449041d4
KW
396 }
397
5a053d1f
BS
398 return 0;
399}
400
401static int print_hex64(DeviceState *dev, Property *prop, char *dest, size_t len)
402{
403 uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
404 return snprintf(dest, len, "0x%" PRIx64, *ptr);
405}
406
407PropertyInfo qdev_prop_hex64 = {
cafe5bdb
PB
408 .name = "uint64",
409 .legacy_name = "hex64",
5a053d1f
BS
410 .parse = parse_hex64,
411 .print = print_hex64,
c08fb2ac
MR
412 .get = get_uint64,
413 .set = set_uint64,
5a053d1f
BS
414};
415
59419663
GH
416/* --- string --- */
417
dd0ba250 418static void release_string(Object *obj, const char *name, void *opaque)
d21357df 419{
dd0ba250
PB
420 Property *prop = opaque;
421 g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
d21357df
MA
422}
423
59419663
GH
424static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
425{
426 char **ptr = qdev_get_prop_ptr(dev, prop);
427 if (!*ptr)
428 return snprintf(dest, len, "<null>");
429 return snprintf(dest, len, "\"%s\"", *ptr);
430}
431
57c9fafe 432static void get_string(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
433 const char *name, Error **errp)
434{
57c9fafe 435 DeviceState *dev = DEVICE(obj);
80e555c2
PB
436 Property *prop = opaque;
437 char **ptr = qdev_get_prop_ptr(dev, prop);
438
439 if (!*ptr) {
440 char *str = (char *)"";
441 visit_type_str(v, &str, name, errp);
442 } else {
443 visit_type_str(v, ptr, name, errp);
444 }
445}
446
57c9fafe 447static void set_string(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
448 const char *name, Error **errp)
449{
57c9fafe 450 DeviceState *dev = DEVICE(obj);
80e555c2
PB
451 Property *prop = opaque;
452 char **ptr = qdev_get_prop_ptr(dev, prop);
453 Error *local_err = NULL;
454 char *str;
455
456 if (dev->state != DEV_STATE_CREATED) {
457 error_set(errp, QERR_PERMISSION_DENIED);
458 return;
459 }
460
461 visit_type_str(v, &str, name, &local_err);
462 if (local_err) {
463 error_propagate(errp, local_err);
464 return;
465 }
80e555c2
PB
466 if (*ptr) {
467 g_free(*ptr);
468 }
469 *ptr = str;
470}
471
59419663
GH
472PropertyInfo qdev_prop_string = {
473 .name = "string",
59419663 474 .print = print_string,
dd0ba250 475 .release = release_string,
80e555c2
PB
476 .get = get_string,
477 .set = set_string,
59419663
GH
478};
479
14b41872
GH
480/* --- drive --- */
481
7b009e5d 482static int parse_drive(DeviceState *dev, const char *str, void **ptr)
14b41872 483{
f8b6cc00 484 BlockDriverState *bs;
14b41872 485
f8b6cc00
MA
486 bs = bdrv_find(str);
487 if (bs == NULL)
6bf38816 488 return -ENOENT;
fa879d62 489 if (bdrv_attach_dev(bs, dev) < 0)
18846dee 490 return -EEXIST;
f8b6cc00 491 *ptr = bs;
14b41872
GH
492 return 0;
493}
494
dd0ba250 495static void release_drive(Object *obj, const char *name, void *opaque)
14bafc54 496{
dd0ba250
PB
497 DeviceState *dev = DEVICE(obj);
498 Property *prop = opaque;
f8b6cc00 499 BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
14bafc54
MA
500
501 if (*ptr) {
fa879d62 502 bdrv_detach_dev(*ptr, dev);
f8b6cc00 503 blockdev_auto_del(*ptr);
14bafc54
MA
504 }
505}
506
7b009e5d 507static const char *print_drive(void *ptr)
14b41872 508{
7b009e5d 509 return bdrv_get_device_name(ptr);
14b41872
GH
510}
511
7b009e5d
PB
512static void get_drive(Object *obj, Visitor *v, void *opaque,
513 const char *name, Error **errp)
514{
515 get_pointer(obj, v, opaque, print_drive, name, errp);
516}
517
518static void set_drive(Object *obj, Visitor *v, void *opaque,
519 const char *name, Error **errp)
520{
521 set_pointer(obj, v, opaque, parse_drive, name, errp);
522}
523
14b41872
GH
524PropertyInfo qdev_prop_drive = {
525 .name = "drive",
7b009e5d
PB
526 .get = get_drive,
527 .set = set_drive,
dd0ba250 528 .release = release_drive,
14b41872
GH
529};
530
313feaab
GH
531/* --- character device --- */
532
7b009e5d 533static int parse_chr(DeviceState *dev, const char *str, void **ptr)
06113719 534{
7b009e5d
PB
535 CharDriverState *chr = qemu_chr_find(str);
536 if (chr == NULL) {
6bf38816 537 return -ENOENT;
2d6c1ef4 538 }
7b009e5d 539 if (chr->avail_connections < 1) {
2d6c1ef4
AS
540 return -EEXIST;
541 }
7b009e5d
PB
542 *ptr = chr;
543 --chr->avail_connections;
06113719
GH
544 return 0;
545}
546
dd0ba250 547static void release_chr(Object *obj, const char *name, void *opaque)
a87f3e8b 548{
dd0ba250
PB
549 DeviceState *dev = DEVICE(obj);
550 Property *prop = opaque;
a87f3e8b
AS
551 CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
552
553 if (*ptr) {
554 qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
555 }
556}
557
558
7b009e5d 559static const char *print_chr(void *ptr)
313feaab 560{
7b009e5d 561 CharDriverState *chr = ptr;
bc19fcaa 562
7b009e5d
PB
563 return chr->label ? chr->label : "";
564}
565
566static void get_chr(Object *obj, Visitor *v, void *opaque,
567 const char *name, Error **errp)
568{
569 get_pointer(obj, v, opaque, print_chr, name, errp);
570}
571
572static void set_chr(Object *obj, Visitor *v, void *opaque,
573 const char *name, Error **errp)
574{
575 set_pointer(obj, v, opaque, parse_chr, name, errp);
313feaab
GH
576}
577
578PropertyInfo qdev_prop_chr = {
579 .name = "chr",
7b009e5d
PB
580 .get = get_chr,
581 .set = set_chr,
dd0ba250 582 .release = release_chr,
313feaab
GH
583};
584
2ef924b4
GH
585/* --- netdev device --- */
586
7b009e5d 587static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
2ef924b4 588{
4e68f7a0 589 NetClientState *netdev = qemu_find_netdev(str);
2ef924b4 590
7b009e5d 591 if (netdev == NULL) {
6bf38816 592 return -ENOENT;
7b009e5d
PB
593 }
594 if (netdev->peer) {
27f3f8a3
MA
595 return -EEXIST;
596 }
7b009e5d 597 *ptr = netdev;
2ef924b4
GH
598 return 0;
599}
600
7b009e5d 601static const char *print_netdev(void *ptr)
2ef924b4 602{
4e68f7a0 603 NetClientState *netdev = ptr;
2ef924b4 604
7b009e5d
PB
605 return netdev->name ? netdev->name : "";
606}
607
608static void get_netdev(Object *obj, Visitor *v, void *opaque,
609 const char *name, Error **errp)
610{
611 get_pointer(obj, v, opaque, print_netdev, name, errp);
612}
613
614static void set_netdev(Object *obj, Visitor *v, void *opaque,
615 const char *name, Error **errp)
616{
617 set_pointer(obj, v, opaque, parse_netdev, name, errp);
2ef924b4
GH
618}
619
620PropertyInfo qdev_prop_netdev = {
621 .name = "netdev",
7b009e5d
PB
622 .get = get_netdev,
623 .set = set_netdev,
2ef924b4
GH
624};
625
851bec09
GH
626/* --- vlan --- */
627
851bec09
GH
628static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
629{
4e68f7a0 630 NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
851bec09
GH
631
632 if (*ptr) {
606c10e2
ZYW
633 int id;
634 if (!net_hub_id_for_client(*ptr, &id)) {
635 return snprintf(dest, len, "%d", id);
636 }
851bec09 637 }
606c10e2
ZYW
638
639 return snprintf(dest, len, "<null>");
851bec09
GH
640}
641
57c9fafe 642static void get_vlan(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
643 const char *name, Error **errp)
644{
57c9fafe 645 DeviceState *dev = DEVICE(obj);
80e555c2 646 Property *prop = opaque;
4e68f7a0 647 NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
606c10e2 648 int32_t id = -1;
80e555c2 649
606c10e2
ZYW
650 if (*ptr) {
651 int hub_id;
652 if (!net_hub_id_for_client(*ptr, &hub_id)) {
653 id = hub_id;
654 }
655 }
656
657 visit_type_int32(v, &id, name, errp);
80e555c2
PB
658}
659
57c9fafe 660static void set_vlan(Object *obj, Visitor *v, void *opaque,
80e555c2
PB
661 const char *name, Error **errp)
662{
57c9fafe 663 DeviceState *dev = DEVICE(obj);
80e555c2 664 Property *prop = opaque;
4e68f7a0 665 NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
80e555c2 666 Error *local_err = NULL;
606c10e2 667 int32_t id;
4e68f7a0 668 NetClientState *hubport;
80e555c2
PB
669
670 if (dev->state != DEV_STATE_CREATED) {
671 error_set(errp, QERR_PERMISSION_DENIED);
672 return;
673 }
674
606c10e2 675 visit_type_int32(v, &id, name, &local_err);
80e555c2
PB
676 if (local_err) {
677 error_propagate(errp, local_err);
678 return;
679 }
680 if (id == -1) {
681 *ptr = NULL;
682 return;
683 }
606c10e2
ZYW
684
685 hubport = net_hub_port_find(id);
686 if (!hubport) {
80e555c2
PB
687 error_set(errp, QERR_INVALID_PARAMETER_VALUE,
688 name, prop->info->name);
689 return;
690 }
606c10e2 691 *ptr = hubport;
80e555c2
PB
692}
693
851bec09
GH
694PropertyInfo qdev_prop_vlan = {
695 .name = "vlan",
851bec09 696 .print = print_vlan,
80e555c2
PB
697 .get = get_vlan,
698 .set = set_vlan,
851bec09
GH
699};
700
ee6847d1
GH
701/* --- pointer --- */
702
036f7166 703/* Not a proper property, just for dirty hacks. TODO Remove it! */
ee6847d1
GH
704PropertyInfo qdev_prop_ptr = {
705 .name = "ptr",
ee6847d1
GH
706};
707
708/* --- mac address --- */
709
710/*
711 * accepted syntax versions:
712 * 01:02:03:04:05:06
713 * 01-02-03-04-05-06
714 */
e39e5d60
PB
715static void get_mac(Object *obj, Visitor *v, void *opaque,
716 const char *name, Error **errp)
ee6847d1 717{
e39e5d60
PB
718 DeviceState *dev = DEVICE(obj);
719 Property *prop = opaque;
1503fff3 720 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
e39e5d60
PB
721 char buffer[2 * 6 + 5 + 1];
722 char *p = buffer;
723
724 snprintf(buffer, sizeof(buffer), "%02x:%02x:%02x:%02x:%02x:%02x",
725 mac->a[0], mac->a[1], mac->a[2],
726 mac->a[3], mac->a[4], mac->a[5]);
727
728 visit_type_str(v, &p, name, errp);
729}
730
731static void set_mac(Object *obj, Visitor *v, void *opaque,
732 const char *name, Error **errp)
733{
734 DeviceState *dev = DEVICE(obj);
735 Property *prop = opaque;
736 MACAddr *mac = qdev_get_prop_ptr(dev, prop);
737 Error *local_err = NULL;
ee6847d1 738 int i, pos;
e39e5d60
PB
739 char *str, *p;
740
741 if (dev->state != DEV_STATE_CREATED) {
742 error_set(errp, QERR_PERMISSION_DENIED);
743 return;
744 }
745
746 visit_type_str(v, &str, name, &local_err);
747 if (local_err) {
748 error_propagate(errp, local_err);
749 return;
750 }
ee6847d1
GH
751
752 for (i = 0, pos = 0; i < 6; i++, pos += 3) {
88e150a5 753 if (!qemu_isxdigit(str[pos]))
e39e5d60 754 goto inval;
88e150a5 755 if (!qemu_isxdigit(str[pos+1]))
e39e5d60 756 goto inval;
1503fff3
GH
757 if (i == 5) {
758 if (str[pos+2] != '\0')
e39e5d60 759 goto inval;
1503fff3
GH
760 } else {
761 if (str[pos+2] != ':' && str[pos+2] != '-')
e39e5d60 762 goto inval;
1503fff3
GH
763 }
764 mac->a[i] = strtol(str+pos, &p, 16);
ee6847d1 765 }
a3400466 766 g_free(str);
e39e5d60 767 return;
1503fff3 768
e39e5d60
PB
769inval:
770 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
a3400466 771 g_free(str);
ee6847d1
GH
772}
773
774PropertyInfo qdev_prop_macaddr = {
1503fff3 775 .name = "macaddr",
e39e5d60
PB
776 .get = get_mac,
777 .set = set_mac,
ee6847d1
GH
778};
779
4e4fa398
JK
780/* --- lost tick policy --- */
781
1ce05125
PB
782static const char *lost_tick_policy_table[LOST_TICK_MAX+1] = {
783 [LOST_TICK_DISCARD] = "discard",
784 [LOST_TICK_DELAY] = "delay",
785 [LOST_TICK_MERGE] = "merge",
786 [LOST_TICK_SLEW] = "slew",
787 [LOST_TICK_MAX] = NULL,
4e4fa398
JK
788};
789
1ce05125
PB
790QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
791
4e4fa398 792PropertyInfo qdev_prop_losttickpolicy = {
1ce05125 793 .name = "LostTickPolicy",
1ce05125
PB
794 .enum_table = lost_tick_policy_table,
795 .get = get_enum,
796 .set = set_enum,
4e4fa398
JK
797};
798
8cd41745
MA
799/* --- BIOS CHS translation */
800
801static const char *bios_chs_trans_table[] = {
802 [BIOS_ATA_TRANSLATION_AUTO] = "auto",
803 [BIOS_ATA_TRANSLATION_NONE] = "none",
804 [BIOS_ATA_TRANSLATION_LBA] = "lba",
805};
806
807PropertyInfo qdev_prop_bios_chs_trans = {
808 .name = "bios-chs-trans",
809 .enum_table = bios_chs_trans_table,
810 .get = get_enum,
811 .set = set_enum,
812};
813
05cb5fe4
GH
814/* --- pci address --- */
815
816/*
817 * bus-local address, i.e. "$slot" or "$slot.$fn"
818 */
768a9ebe
PB
819static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
820 const char *name, Error **errp)
05cb5fe4 821{
768a9ebe
PB
822 DeviceState *dev = DEVICE(obj);
823 Property *prop = opaque;
27712df9 824 int32_t value, *ptr = qdev_get_prop_ptr(dev, prop);
05cb5fe4 825 unsigned int slot, fn, n;
768a9ebe 826 Error *local_err = NULL;
a3400466 827 char *str;
768a9ebe
PB
828
829 if (dev->state != DEV_STATE_CREATED) {
830 error_set(errp, QERR_PERMISSION_DENIED);
831 return;
832 }
833
834 visit_type_str(v, &str, name, &local_err);
835 if (local_err) {
5c878008 836 error_free(local_err);
27712df9
PB
837 local_err = NULL;
838 visit_type_int32(v, &value, name, &local_err);
839 if (local_err) {
840 error_propagate(errp, local_err);
841 } else if (value < -1 || value > 255) {
842 error_set(errp, QERR_INVALID_PARAMETER_VALUE, name ? name : "null",
843 "pci_devfn");
844 } else {
845 *ptr = value;
846 }
847 return;
768a9ebe 848 }
05cb5fe4
GH
849
850 if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
851 fn = 0;
852 if (sscanf(str, "%x%n", &slot, &n) != 1) {
768a9ebe 853 goto invalid;
05cb5fe4
GH
854 }
855 }
768a9ebe
PB
856 if (str[n] != '\0' || fn > 7 || slot > 31) {
857 goto invalid;
858 }
05cb5fe4 859 *ptr = slot << 3 | fn;
a3400466 860 g_free(str);
768a9ebe
PB
861 return;
862
863invalid:
864 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
a3400466 865 g_free(str);
05cb5fe4
GH
866}
867
868static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
869{
09f1bbcd 870 int32_t *ptr = qdev_get_prop_ptr(dev, prop);
05cb5fe4 871
73538c31 872 if (*ptr == -1) {
05cb5fe4
GH
873 return snprintf(dest, len, "<unset>");
874 } else {
875 return snprintf(dest, len, "%02x.%x", *ptr >> 3, *ptr & 7);
876 }
877}
878
879PropertyInfo qdev_prop_pci_devfn = {
b403298a
PB
880 .name = "int32",
881 .legacy_name = "pci-devfn",
05cb5fe4 882 .print = print_pci_devfn,
b403298a 883 .get = get_int32,
768a9ebe 884 .set = set_pci_devfn,
05cb5fe4
GH
885};
886
02fda01c
SH
887/* --- blocksize --- */
888
889static void set_blocksize(Object *obj, Visitor *v, void *opaque,
890 const char *name, Error **errp)
891{
892 DeviceState *dev = DEVICE(obj);
893 Property *prop = opaque;
c08fb2ac 894 uint16_t value, *ptr = qdev_get_prop_ptr(dev, prop);
02fda01c 895 Error *local_err = NULL;
27712df9
PB
896 const int64_t min = 512;
897 const int64_t max = 32768;
02fda01c
SH
898
899 if (dev->state != DEV_STATE_CREATED) {
900 error_set(errp, QERR_PERMISSION_DENIED);
901 return;
902 }
903
c08fb2ac 904 visit_type_uint16(v, &value, name, &local_err);
02fda01c
SH
905 if (local_err) {
906 error_propagate(errp, local_err);
907 return;
908 }
27712df9 909 if (value < min || value > max) {
02fda01c 910 error_set(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
27712df9 911 dev->id?:"", name, (int64_t)value, min, max);
02fda01c
SH
912 return;
913 }
914
915 /* We rely on power-of-2 blocksizes for bitmasks */
916 if ((value & (value - 1)) != 0) {
917 error_set(errp, QERR_PROPERTY_VALUE_NOT_POWER_OF_2,
c08fb2ac 918 dev->id?:"", name, (int64_t)value);
02fda01c
SH
919 return;
920 }
921
922 *ptr = value;
923}
924
925PropertyInfo qdev_prop_blocksize = {
926 .name = "blocksize",
c08fb2ac 927 .get = get_uint16,
02fda01c 928 .set = set_blocksize,
02fda01c
SH
929};
930
679042f0
AP
931/* --- pci host address --- */
932
933static void get_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
934 const char *name, Error **errp)
935{
936 DeviceState *dev = DEVICE(obj);
937 Property *prop = opaque;
938 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
939 char buffer[] = "xxxx:xx:xx.x";
940 char *p = buffer;
941 int rc = 0;
942
943 rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d",
944 addr->domain, addr->bus, addr->slot, addr->function);
945 assert(rc == sizeof(buffer) - 1);
946
947 visit_type_str(v, &p, name, errp);
948}
949
950/*
951 * Parse [<domain>:]<bus>:<slot>.<func>
952 * if <domain> is not supplied, it's assumed to be 0.
953 */
954static void set_pci_host_devaddr(Object *obj, Visitor *v, void *opaque,
955 const char *name, Error **errp)
956{
957 DeviceState *dev = DEVICE(obj);
958 Property *prop = opaque;
959 PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop);
960 Error *local_err = NULL;
961 char *str, *p;
962 char *e;
963 unsigned long val;
964 unsigned long dom = 0, bus = 0;
965 unsigned int slot = 0, func = 0;
966
967 if (dev->state != DEV_STATE_CREATED) {
968 error_set(errp, QERR_PERMISSION_DENIED);
969 return;
970 }
971
972 visit_type_str(v, &str, name, &local_err);
973 if (local_err) {
974 error_propagate(errp, local_err);
975 return;
976 }
977
978 p = str;
979 val = strtoul(p, &e, 16);
980 if (e == p || *e != ':') {
981 goto inval;
982 }
983 bus = val;
984
985 p = e + 1;
986 val = strtoul(p, &e, 16);
987 if (e == p) {
988 goto inval;
989 }
990 if (*e == ':') {
991 dom = bus;
992 bus = val;
993 p = e + 1;
994 val = strtoul(p, &e, 16);
995 if (e == p) {
996 goto inval;
997 }
998 }
999 slot = val;
1000
1001 if (*e != '.') {
1002 goto inval;
1003 }
1004 p = e + 1;
1005 val = strtoul(p, &e, 10);
1006 if (e == p) {
1007 goto inval;
1008 }
1009 func = val;
1010
1011 if (dom > 0xffff || bus > 0xff || slot > 0x1f || func > 7) {
1012 goto inval;
1013 }
1014
1015 if (*e) {
1016 goto inval;
1017 }
1018
1019 addr->domain = dom;
1020 addr->bus = bus;
1021 addr->slot = slot;
1022 addr->function = func;
1023
1024 g_free(str);
1025 return;
1026
1027inval:
1028 error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
1029 g_free(str);
1030}
1031
1032PropertyInfo qdev_prop_pci_host_devaddr = {
1033 .name = "pci-host-devaddr",
1034 .get = get_pci_host_devaddr,
1035 .set = set_pci_host_devaddr,
1036};
1037
ee6847d1
GH
1038/* --- public helpers --- */
1039
1040static Property *qdev_prop_walk(Property *props, const char *name)
1041{
1042 if (!props)
1043 return NULL;
1044 while (props->name) {
1045 if (strcmp(props->name, name) == 0)
1046 return props;
1047 props++;
1048 }
1049 return NULL;
1050}
1051
1052static Property *qdev_prop_find(DeviceState *dev, const char *name)
1053{
bce54474 1054 ObjectClass *class;
ee6847d1
GH
1055 Property *prop;
1056
1057 /* device properties */
bce54474
PB
1058 class = object_get_class(OBJECT(dev));
1059 do {
1060 prop = qdev_prop_walk(DEVICE_CLASS(class)->props, name);
1061 if (prop) {
1062 return prop;
1063 }
1064 class = object_class_get_parent(class);
1065 } while (class != object_class_by_name(TYPE_DEVICE));
ee6847d1
GH
1066
1067 return NULL;
1068}
1069
7db4c4e8
PB
1070void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
1071 Property *prop, const char *value)
1072{
1073 switch (ret) {
1074 case -EEXIST:
1075 error_set(errp, QERR_PROPERTY_VALUE_IN_USE,
f79f2bfc 1076 object_get_typename(OBJECT(dev)), prop->name, value);
7db4c4e8
PB
1077 break;
1078 default:
1079 case -EINVAL:
1080 error_set(errp, QERR_PROPERTY_VALUE_BAD,
f79f2bfc 1081 object_get_typename(OBJECT(dev)), prop->name, value);
7db4c4e8
PB
1082 break;
1083 case -ENOENT:
1084 error_set(errp, QERR_PROPERTY_VALUE_NOT_FOUND,
f79f2bfc 1085 object_get_typename(OBJECT(dev)), prop->name, value);
7db4c4e8
PB
1086 break;
1087 case 0:
1088 break;
1089 }
1090}
1091
ee6847d1
GH
1092int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
1093{
d822979b
PB
1094 char *legacy_name;
1095 Error *err = NULL;
ee6847d1 1096
d822979b
PB
1097 legacy_name = g_strdup_printf("legacy-%s", name);
1098 if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
0c96e285 1099 object_property_parse(OBJECT(dev), value, legacy_name, &err);
d822979b 1100 } else {
0c96e285 1101 object_property_parse(OBJECT(dev), value, name, &err);
ee6847d1 1102 }
d822979b
PB
1103 g_free(legacy_name);
1104
1105 if (err) {
7db4c4e8
PB
1106 qerror_report_err(err);
1107 error_free(err);
9ef5c4bf
GH
1108 return -1;
1109 }
1110 return 0;
ee6847d1
GH
1111}
1112
f4594a3b
IY
1113void qdev_prop_set_bit(DeviceState *dev, const char *name, bool value)
1114{
9b170e60
PB
1115 Error *errp = NULL;
1116 object_property_set_bool(OBJECT(dev), value, name, &errp);
59f971d4 1117 assert_no_error(errp);
f4594a3b
IY
1118}
1119
c7cc172d
JQ
1120void qdev_prop_set_uint8(DeviceState *dev, const char *name, uint8_t value)
1121{
9b170e60
PB
1122 Error *errp = NULL;
1123 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1124 assert_no_error(errp);
c7cc172d
JQ
1125}
1126
ee6847d1
GH
1127void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value)
1128{
9b170e60
PB
1129 Error *errp = NULL;
1130 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1131 assert_no_error(errp);
ee6847d1
GH
1132}
1133
1134void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value)
1135{
9b170e60
PB
1136 Error *errp = NULL;
1137 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1138 assert_no_error(errp);
ee6847d1
GH
1139}
1140
316940b0
GH
1141void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value)
1142{
9b170e60
PB
1143 Error *errp = NULL;
1144 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1145 assert_no_error(errp);
316940b0
GH
1146}
1147
5a053d1f
BS
1148void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
1149{
9b170e60
PB
1150 Error *errp = NULL;
1151 object_property_set_int(OBJECT(dev), value, name, &errp);
59f971d4 1152 assert_no_error(errp);
5a053d1f
BS
1153}
1154
3b25597b 1155void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
cc984673 1156{
9b170e60
PB
1157 Error *errp = NULL;
1158 object_property_set_str(OBJECT(dev), value, name, &errp);
59f971d4 1159 assert_no_error(errp);
cc984673
MA
1160}
1161
18846dee 1162int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
14b41872 1163{
9b170e60 1164 Error *errp = NULL;
0a54a0ce
PB
1165 const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
1166 object_property_set_str(OBJECT(dev), bdrv_name,
9b170e60
PB
1167 name, &errp);
1168 if (errp) {
1169 qerror_report_err(errp);
1170 error_free(errp);
18846dee
MA
1171 return -1;
1172 }
18846dee 1173 return 0;
14b41872
GH
1174}
1175
18846dee
MA
1176void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
1177{
1178 if (qdev_prop_set_drive(dev, name, value) < 0) {
1179 exit(1);
1180 }
1181}
313feaab
GH
1182void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
1183{
9b170e60 1184 Error *errp = NULL;
0a54a0ce
PB
1185 assert(!value || value->label);
1186 object_property_set_str(OBJECT(dev),
1187 value ? value->label : "", name, &errp);
59f971d4 1188 assert_no_error(errp);
313feaab
GH
1189}
1190
4e68f7a0 1191void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value)
2ef924b4 1192{
9b170e60 1193 Error *errp = NULL;
0a54a0ce
PB
1194 assert(!value || value->name);
1195 object_property_set_str(OBJECT(dev),
1196 value ? value->name : "", name, &errp);
59f971d4 1197 assert_no_error(errp);
2ef924b4
GH
1198}
1199
1503fff3
GH
1200void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
1201{
9b170e60
PB
1202 Error *errp = NULL;
1203 char str[2 * 6 + 5 + 1];
1204 snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x",
1205 value[0], value[1], value[2], value[3], value[4], value[5]);
1206
1207 object_property_set_str(OBJECT(dev), str, name, &errp);
59f971d4 1208 assert_no_error(errp);
1503fff3
GH
1209}
1210
9b170e60 1211void qdev_prop_set_enum(DeviceState *dev, const char *name, int value)
4e4fa398 1212{
9b170e60
PB
1213 Property *prop;
1214 Error *errp = NULL;
1215
1216 prop = qdev_prop_find(dev, name);
1217 object_property_set_str(OBJECT(dev), prop->info->enum_table[value],
1218 name, &errp);
59f971d4 1219 assert_no_error(errp);
4e4fa398
JK
1220}
1221
ee6847d1
GH
1222void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
1223{
7a7aae21
PB
1224 Property *prop;
1225 void **ptr;
1226
1227 prop = qdev_prop_find(dev, name);
1228 assert(prop && prop->info == &qdev_prop_ptr);
1229 ptr = qdev_get_prop_ptr(dev, prop);
1230 *ptr = value;
ee6847d1
GH
1231}
1232
458fb679 1233static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
b6b61144 1234
25920d6a 1235static void qdev_prop_register_global(GlobalProperty *prop)
b6b61144 1236{
458fb679 1237 QTAILQ_INSERT_TAIL(&global_props, prop, next);
b6b61144
GH
1238}
1239
458fb679 1240void qdev_prop_register_global_list(GlobalProperty *props)
b6b61144 1241{
458fb679 1242 int i;
b6b61144 1243
458fb679
GH
1244 for (i = 0; props[i].driver != NULL; i++) {
1245 qdev_prop_register_global(props+i);
b6b61144 1246 }
458fb679
GH
1247}
1248
1249void qdev_prop_set_globals(DeviceState *dev)
1250{
bce54474
PB
1251 ObjectClass *class = object_get_class(OBJECT(dev));
1252
1253 do {
1254 GlobalProperty *prop;
1255 QTAILQ_FOREACH(prop, &global_props, next) {
1256 if (strcmp(object_class_get_name(class), prop->driver) != 0) {
1257 continue;
1258 }
1259 if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
1260 exit(1);
1261 }
b6b61144 1262 }
bce54474
PB
1263 class = object_class_get_parent(class);
1264 } while (class);
b6b61144 1265}
25920d6a
KW
1266
1267static int qdev_add_one_global(QemuOpts *opts, void *opaque)
1268{
1269 GlobalProperty *g;
1270
7267c094 1271 g = g_malloc0(sizeof(*g));
25920d6a
KW
1272 g->driver = qemu_opt_get(opts, "driver");
1273 g->property = qemu_opt_get(opts, "property");
1274 g->value = qemu_opt_get(opts, "value");
1275 qdev_prop_register_global(g);
1276 return 0;
1277}
1278
1279void qemu_add_globals(void)
1280{
3329f07b 1281 qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
25920d6a 1282}