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