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